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