bin/143533: Changes to support Sun jumpstart via bootparamd, enhance bootparamd for multiple networks

Brian McGovern mcgovern at beta.com
Wed Feb 3 18:50:05 UTC 2010


>Number:         143533
>Category:       bin
>Synopsis:       Changes to support Sun jumpstart via bootparamd, enhance bootparamd for multiple networks
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Wed Feb 03 18:50:04 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator:     Brian McGovern
>Release:        8.0-RELEASE
>Organization:
>Environment:
FreeBSD nmtg-bxb-lab-dev2.cisco.com 8.0-RELEASE FreeBSD 8.0-RELEASE #0: Sat Nov 21 15:02:08 UTC 2009     root at mason.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC  amd64
>Description:
This patch combines some work to provide bootparamd will the full set of parameters to support Solaris boot/solaris jumpstart using FreeBSD as the boot server (most bootparamd.c changes). 

This patch also adds code to allow bootparamd to serve multiple networks by allowing more than one router to be specified, either on the command line or via a configuration file (remaining changes).

The man page has also been updated to document the use of the new -R and -F flags.
>How-To-Repeat:
There is no problem to repeat. The patch should apply to the 8.0- source tree (current p-levels do not appear to have changed bootparamd, so the patch should continue to apply cleanly).
>Fix:


Patch attached with submission follows:

_diff -r Makefile.orig Makefile
8c8,9
< SRCS=	bootparamd.c main.c ${GENSRCS}
---
> 
> SRCS=	multinet.c bootparamd.c main.c ${GENSRCS}
11c12,13
< CFLAGS+= -DTFTP_DIR=\"/tftpboot\" -I.
---
> CFLAGS+= -DTFTP_DIR=\"/tftpboot\" -I. 
> 
Only in bootparamd.new: Makefile.inc
diff -r bootparamd.8.orig bootparamd.8
13a14,15
> .Op Fl R Ar router/netmask
> .Op Fl F Ar router file
47a50,53
> .It Fl R Ar router/netbits
> Specify an alternate router for a given subnet.
> .It Fl F Ar router_file
> Specify a file from which to load alternate router/netbit pairs.
65a72,98
> 
> If you expect to use bootparamd on multiple networks, you can specify multiple
> gateways using -R, followed by the router to use, slash, and the number of bits
> in the netmask. As an example:
> 
> bootparamd -r 1.2.3.4 -R 10.1.1.1/24
> 
> will cause bootparamd to use 1.2.3.4 as the default router for any unmatched 
> networks, but will use 10.1.1.1 when a client on the 10.1.1.0/24 network 
> requests parameters. Note that the client making the request must resolve to
> an IP address, either via gethostname(3) or inet_aton(3) for pattern matching.
> 
> You may specify -R as many times as needed.
> 
> Using -F, you may also specify a file from which to read routing information. 
> Similar to the -R option, each line of the file should specify a router and the
> number of bits in the netmask. For example:
> 
> 10.1.1.1/25
> 10.1.1.129/25
> 10.1.2.1/24
> 
> Comments in this file may be specified by using a semi-colon or hash character
> at the start of the comment.
> 
> Multiple -F values may be specified, if needed.
> 
diff -r bootparamd.c.orig bootparamd.c
42a43
> int get_router_for_client __P((char *, in_addr_t));
81a83
>     route_addr = get_router_for_client(res.client_name, route_addr);
117c119
<   char *where, *index();
---
>   char *where;
130c132,135
<   if (! he ) goto failed;
---
>   if (! he ) {
>     if (debug) warnx("bad hostname %s", getfile->client_name);
>     goto failed;
>   }
135a141,146
>     if (debug) warnx("matched: %s",buffer);
>     res.server_name = "";
>     res.server_path = "";
>     res.server_address.address_type = IP_ADDR_TYPE;
>     bzero(&res.server_address.bp_address_u.ip_addr,4);
> 
142,145d152
<       he = gethostbyname(hostname);
<       if ( !he ) goto failed;
<       bcopy( he->h_addr, &res.server_address.bp_address_u.ip_addr, 4);
<       res.server_name = hostname;
147,155c154,169
<       res.server_address.address_type = IP_ADDR_TYPE;
<     }
<     else { /* special for dump, answer with null strings */
<       if (!strcmp(getfile->file_id, "dump")) {
< 	res.server_name = "";
< 	res.server_path = "";
<         res.server_address.address_type = IP_ADDR_TYPE;
< 	bzero(&res.server_address.bp_address_u.ip_addr,4);
<       } else goto failed;
---
>       if (hostname[0]) {
>         he = gethostbyname(hostname);
>         if ( !he ) {
>           if (debug) warnx("invalid hostname %s", hostname);
>           goto failed;
>         }
>         bcopy( he->h_addr, &res.server_address.bp_address_u.ip_addr, 4);
>         res.server_name = hostname;
>       }
>     } else { 
>       /* XXX allow "dump" keyword with no value.  Why? no idea. 
>          Fail otherwise. */
>       if (strcmp(getfile->file_id, "dump")) {
>         if (debug) warnx("invalid value for keyword %s", getfile->file_id);
>         goto failed;
>       }
158c172
<       fprintf(stderr, "returning server:%s path:%s address: %d.%d.%d.%d\n",
---
>       fprintf(stderr, "returning server:\"%s\" path:\"%s\" address: %d.%d.%d.%d\n",
diff -r main.c.orig main.c
51,52c51
< 
< 	while ((c = getopt(argc, argv,"dsr:f:")) != -1)
---
> 	while ((c = getopt(argc, argv,"dsr:f:R:F:")) != -1)
56a56,67
> 	  case 'R':
> 	    {
> 	      if (!(add_router(optarg)))
>                 errx(1,"Unable to add router/netmask %s",optarg);
> 	      break;
> 	    }
> 	  case 'F':
> 	    {
> 	      if (!(add_routers_from_file(optarg)))
> 	        errx(1,"Unable to load routers/netmasks from file %s",optarg);
> 	      break;
> 	    }
diff -r multinet.c.orig multinet.c
0a1,145
> /*
> 
> This code is not copyright, and is placed in the public domain. Feel free to
> use and modify. Please send modifications and/or suggestions + bug fixes to
> 
>         Brian McGovern <mcgovern at beta.com>
> 
> */
> 
> #include <sys/types.h>
> #include <sys/socket.h>
> #include <netinet/in.h>
> #include <arpa/inet.h>
> #include <errno.h>
> #include <netdb.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> 
> extern	int	debug;
> extern	int	dolog;
> 
> 
> struct router_list
>   {
>     struct	in_addr		router,
> 				netmask;
>     struct	router_list	*next;
>   } *router_list			= NULL;;
> 
> struct in_addr		get_address_for_client(char *client)
>   {
>     struct	hostent		*host	= gethostbyname(client);
>     struct	in_addr		tmp	= {0};
>     if (host)
>       memcpy(&tmp.s_addr, host->h_addr, sizeof(tmp.s_addr));
>     else
>       {
>         if (!(inet_aton(client,&tmp)))
>           tmp.s_addr = 0;
>       }
>     return tmp;
>   }
> 
> struct	in_addr		get_netmask_from_bits(char *numbits)
>   {
>     struct	in_addr	tmp		= {0};
>     long		bits		= 0;
>     errno = 0;
>     bits = strtol(numbits, (char **)NULL, 10);
>     if ((!(errno)) && ((bits < 32) && (bits > 0)))
>       tmp.s_addr = htonl((~0) << (32 - bits));
>     return tmp;
>   }
> 
> in_addr_t		get_router_for_client(char *client, in_addr_t default_router)
>   {
>     struct router_list	*ptr		= router_list;
>     struct in_addr	address		= {0};
>     in_addr_t		return_address	= 0;
>     if (!router_list)
>       return default_router;
>     address = get_address_for_client(client);
>     while (ptr)
>       {
>         if ((address.s_addr & ptr->netmask.s_addr) == (ptr->router.s_addr & ptr->netmask.s_addr))
> 	  {
> 	    return_address = ptr->router.s_addr;
> 	    return return_address;
> 	  }
>         ptr = ptr->next;
>       }
>     return default_router;
>   }
> 
> int			add_router(char *routermask)
>   {
>     struct router_list	*ptr		= router_list;
>     struct in_addr	router_addr	= {0},
> 			netmask_addr	= {0};
>     char		*tmpstr		= NULL,
> 			*netbits	= NULL,
> 			*router		= NULL;
> 
> 
>     tmpstr = netbits = strdup(routermask);
> 
>     if (!tmpstr)
>       return 0;
> 
>     router = strsep(&netbits,"/\0");
>     router_addr = get_address_for_client(router);
>     netmask_addr = get_netmask_from_bits(netbits);
>     
>     free(tmpstr);
> 
>     if ((!router_addr.s_addr) || (!netmask_addr.s_addr))
>       return 0;
> 
>     if (!ptr)
>       ptr = router_list = (struct router_list *)calloc(1,sizeof(struct router_list));
>     else
>       {
>         while (ptr->next != NULL)
> 	  ptr = ptr->next;
> 	ptr->next = (struct router_list *)calloc(1,sizeof(struct router_list));
> 	ptr = ptr->next;
>       }
>     if (!ptr)
>       {
>         return 0;
>       }
>     ptr->router = router_addr;
>     ptr->netmask = netmask_addr;
>     return 1;
>   }
> 
> int			add_routers_from_file(char *filename)
>   {
> #define			BUFSIZE		  512
>     unsigned char	buffer[BUFSIZE]	= {0},
> 			*ptr		= NULL;
>     FILE		*fh		= fopen(filename,"r");
>     int			retval		= 1,
> 			fileline	= 0;
> 
>     if (!fh)
>       return 0;
>     while (fgets(buffer, BUFSIZE, fh))
>       {
>         fileline++;
>         if (ptr = strpbrk(buffer,"#;\n"))
> 	  *ptr = 0;
> 	if ((strlen(buffer) > 2) && (add_router(buffer) == 0))
> 	  {
>             if (debug)
> 	      fprintf(stderr,"Unable to add router/netmask %s from line %d of file %s\n",buffer,fileline,filename);
> 	    if (dolog)
> 	      syslog(LOG_NOTICE,"Unable to add router/netmask %s from line %d of file %s\n",buffer,fileline,filename);
> 	    retval = 0;
> 	  }
>       }
>     fclose(fh);
>     return retval;
>   }


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list