When using the PXE loader and a stock kernel you can specify the root path as with "option root-path" with a path like "/usr/diskless/5.2-CURRENT". The server is then derived from the value of next-server (the siaddr entry in the dhcp packet). If you add options BOOTP to your kernel this configuration causes a panic because the kernel wants a root path like "10.1.0.1:/usr/diskless/5.2-CURRENT". This has been annoying me for quite some time so today I took a look at the problem. The following patch fixes it. I'd like to commit it soon, any objections?
-- Brooks Index: bootp_subr.c =================================================================== RCS file: /usr/cvs/src/sys/nfsclient/bootp_subr.c,v retrieving revision 1.56 diff -u -p -r1.56 bootp_subr.c --- bootp_subr.c 14 Nov 2003 20:54:08 -0000 1.56 +++ bootp_subr.c 11 Feb 2004 00:48:45 -0000 @@ -216,7 +216,8 @@ SYSCTL_STRING(_kern, OID_AUTO, bootp_coo /* mountd RPC */ static int md_mount(struct sockaddr_in *mdsin, char *path, u_char *fhp, int *fhsizep, struct nfs_args *args, struct thread *td); -static int setfs(struct sockaddr_in *addr, char *path, char *p); +static int setfs(struct sockaddr_in *addr, char *path, char *p, + const struct in_addr *siaddr); static int getdec(char **ptr); static char *substr(char *a, char *b); static void mountopts(struct nfs_args *args, char *p); @@ -1157,42 +1158,49 @@ bootpc_adjust_interface(struct bootpc_if } static int -setfs(struct sockaddr_in *addr, char *path, char *p) +setfs(struct sockaddr_in *addr, char *path, char *p, + const struct in_addr *siaddr) { unsigned int ip; int val; - ip = 0; - if (((val = getdec(&p)) < 0) || (val > 255)) - return 0; - ip = val << 24; - if (*p != '.') - return 0; - p++; - if (((val = getdec(&p)) < 0) || (val > 255)) - return 0; - ip |= (val << 16); - if (*p != '.') - return 0; - p++; - if (((val = getdec(&p)) < 0) || (val > 255)) - return 0; - ip |= (val << 8); - if (*p != '.') - return 0; - p++; - if (((val = getdec(&p)) < 0) || (val > 255)) - return 0; - ip |= val; - if (*p != ':') + if (*p != '/') { + ip = 0; + if (((val = getdec(&p)) < 0) || (val > 255)) + return 0; + ip = val << 24; + if (*p != '.') + return 0; + p++; + if (((val = getdec(&p)) < 0) || (val > 255)) + return 0; + ip |= (val << 16); + if (*p != '.') + return 0; + p++; + if (((val = getdec(&p)) < 0) || (val > 255)) + return 0; + ip |= (val << 8); + if (*p != '.') + return 0; + p++; + if (((val = getdec(&p)) < 0) || (val > 255)) + return 0; + ip |= val; + if (*p != ':') + return 0; + p++; + + addr->sin_addr.s_addr = htonl(ip); + } else if (siaddr != NULL) + bcopy(siaddr, &addr->sin_addr.s_addr, sizeof(struct in_addr)); + else return 0; - p++; - addr->sin_addr.s_addr = htonl(ip); addr->sin_len = sizeof(struct sockaddr_in); addr->sin_family = AF_INET; - strncpy(path, p, MNAMELEN - 1); + strlcpy(path, p, MNAMELEN); return 1; } @@ -1551,7 +1559,12 @@ bootpc_decode_reply(struct nfsv3_diskles if (gctx->setrootfs != NULL) { printf("rootfs %s (ignored) ", p); } else if (setfs(&nd->root_saddr, - nd->root_hostnam, p)) { + nd->root_hostnam, p, &ifctx->reply.siaddr)) { + if (*p == '/') { + printf("root_server "); + print_sin_addr(&nd->root_saddr); + printf(" "); + } printf("rootfs %s ", p); gctx->gotrootpath = 1; ifctx->gotrootpath = 1; -- Any statement of the form "X is the one, true Y" is FALSE. PGP fingerprint 655D 519C 26A7 82E7 2529 9BF0 5D8E 8BE9 F238 1AD4
pgp00000.pgp
Description: PGP signature