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

Attachment: pgp00000.pgp
Description: PGP signature

Reply via email to