Author: glebius
Date: Tue Dec 13 07:02:48 2011
New Revision: 228455
URL: http://svn.freebsd.org/changeset/base/228455

Log:
  Some cleanup of BOOTP code. Initially I wanted to just change the ifioctl()
  usage, but end up with more changes.
  
  - Use SIOCAIFADDR instead of old rusty SIOCSIFADDR, SIOCSIFBRDADDR
    and SIOCSIFNETMASK.
  - Use queue(9) instead of hand made stailq.
  - Use one socket for all ifioctl() and send/receive operations.
  - Use __func__ instead of cut-n-paste in logging and panics.
  - Axe some dead or strange code.
  
  Tested by:    gonzo, Stefan Bethke <stb lassitu.de>

Modified:
  head/sys/nfs/bootp_subr.c

Modified: head/sys/nfs/bootp_subr.c
==============================================================================
--- head/sys/nfs/bootp_subr.c   Tue Dec 13 06:56:43 2011        (r228454)
+++ head/sys/nfs/bootp_subr.c   Tue Dec 13 07:02:48 2011        (r228455)
@@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$");
 #include <net/route.h>
 
 #include <netinet/in.h>
+#include <netinet/in_var.h>
 #include <net/if_types.h>
 #include <net/if_dl.h>
 #include <net/vnet.h>
@@ -109,19 +110,22 @@ struct bootp_packet {
 };
 
 struct bootpc_ifcontext {
-       struct bootpc_ifcontext *next;
+       STAILQ_ENTRY(bootpc_ifcontext) next;
        struct bootp_packet call;
        struct bootp_packet reply;
        int replylen;
        int overload;
-       struct socket *so;
-       struct ifreq ireq;
+       union {
+               struct ifreq _ifreq;
+               struct in_aliasreq _in_alias_req;
+       } _req;
+#define        ireq    _req._ifreq
+#define        iareq   _req._in_alias_req
        struct ifnet *ifp;
        struct sockaddr_dl *sdl;
        struct sockaddr_in myaddr;
        struct sockaddr_in netmask;
        struct sockaddr_in gw;
-       struct sockaddr_in broadcast;   /* Different for each interface */
        int gotgw;
        int gotnetmask;
        int gotrootpath;
@@ -153,8 +157,7 @@ struct bootpc_tagcontext {
 };
 
 struct bootpc_globalcontext {
-       struct bootpc_ifcontext *interfaces;
-       struct bootpc_ifcontext *lastinterface;
+       STAILQ_HEAD(, bootpc_ifcontext) interfaces;
        u_int32_t xid;
        int gotrootpath;
        int gotgw;
@@ -215,6 +218,7 @@ struct bootpc_globalcontext {
 #endif
 
 static char bootp_cookie[128];
+static struct socket *bootp_so;
 SYSCTL_STRING(_kern, OID_AUTO, bootp_cookie, CTLFLAG_RD,
        bootp_cookie, 0, "Cookie (T134) supplied by bootp server");
 
@@ -233,7 +237,7 @@ static void print_sin_addr(struct sockad
 static void    clear_sinaddr(struct sockaddr_in *sin);
 static void    allocifctx(struct bootpc_globalcontext *gctx);
 static void    bootpc_compose_query(struct bootpc_ifcontext *ifctx,
-                   struct bootpc_globalcontext *gctx, struct thread *td);
+                   struct thread *td);
 static unsigned char *bootpc_tag(struct bootpc_tagcontext *tctx,
                    struct bootp_packet *bp, int len, int tag);
 static void bootpc_tag_helper(struct bootpc_tagcontext *tctx,
@@ -251,8 +255,8 @@ void bootpboot_p_iflist(void);
 static int     bootpc_call(struct bootpc_globalcontext *gctx,
                    struct thread *td);
 
-static int     bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx,
-                   struct bootpc_globalcontext *gctx, struct thread *td);
+static void    bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx,
+                   struct thread *td);
 
 static int     bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
                    struct bootpc_globalcontext *gctx, struct thread *td);
@@ -270,14 +274,9 @@ static __inline int bootpc_ifctx_isfaile
 
 /*
  * In order to have multiple active interfaces with address 0.0.0.0
- * and be able to send data to a selected interface, we perform
- * some tricks:
- *
- *  - The 'broadcast' address is different for each interface.
- *
- *  - We temporarily add routing pointing 255.255.255.255 to the
- *    selected interface broadcast address, thus the packet sent
- *    goes to that interface.
+ * and be able to send data to a selected interface, we first set
+ * mask to /8 on all interfaces, and temporarily set it to /0 when
+ * doing sosend().
  */
 
 #ifdef BOOTP_DEBUG
@@ -419,11 +418,8 @@ static void
 allocifctx(struct bootpc_globalcontext *gctx)
 {
        struct bootpc_ifcontext *ifctx;
-       ifctx = (struct bootpc_ifcontext *) malloc(sizeof(*ifctx),
-                                                  M_TEMP, M_WAITOK | M_ZERO);
-       if (ifctx == NULL)
-               panic("Failed to allocate bootp interface context structure");
 
+       ifctx = malloc(sizeof(*ifctx), M_TEMP, M_WAITOK | M_ZERO);
        ifctx->xid = gctx->xid;
 #ifdef BOOTP_NO_DHCP
        ifctx->state = IF_BOOTP_UNRESOLVED;
@@ -431,11 +427,7 @@ allocifctx(struct bootpc_globalcontext *
        ifctx->state = IF_DHCP_UNRESOLVED;
 #endif
        gctx->xid += 0x100;
-       if (gctx->interfaces != NULL)
-               gctx->lastinterface->next = ifctx;
-       else
-               gctx->interfaces = ifctx;
-       gctx->lastinterface = ifctx;
+       STAILQ_INSERT_TAIL(&gctx->interfaces, ifctx, next);
 }
 
 static __inline int
@@ -570,7 +562,6 @@ bootpc_received(struct bootpc_globalcont
 static int
 bootpc_call(struct bootpc_globalcontext *gctx, struct thread *td)
 {
-       struct socket *so;
        struct sockaddr_in *sin, dst;
        struct uio auio;
        struct sockopt sopt;
@@ -585,13 +576,6 @@ bootpc_call(struct bootpc_globalcontext 
        int retry;
        const char *s;
 
-       /*
-        * Create socket and set its recieve timeout.
-        */
-       error = socreate(AF_INET, &so, SOCK_DGRAM, 0, td->td_ucred, td);
-       if (error != 0)
-               goto out0;
-
        tv.tv_sec = 1;
        tv.tv_usec = 0;
        bzero(&sopt, sizeof(sopt));
@@ -601,7 +585,7 @@ bootpc_call(struct bootpc_globalcontext 
        sopt.sopt_val = &tv;
        sopt.sopt_valsize = sizeof tv;
 
-       error = sosetopt(so, &sopt);
+       error = sosetopt(bootp_so, &sopt);
        if (error != 0)
                goto out;
 
@@ -613,7 +597,7 @@ bootpc_call(struct bootpc_globalcontext 
        sopt.sopt_val = &on;
        sopt.sopt_valsize = sizeof on;
 
-       error = sosetopt(so, &sopt);
+       error = sosetopt(bootp_so, &sopt);
        if (error != 0)
                goto out;
 
@@ -626,7 +610,7 @@ bootpc_call(struct bootpc_globalcontext 
        sopt.sopt_val = &on;
        sopt.sopt_valsize = sizeof on;
 
-       error = sosetopt(so, &sopt);
+       error = sosetopt(bootp_so, &sopt);
        if (error != 0)
                goto out;
 
@@ -636,7 +620,7 @@ bootpc_call(struct bootpc_globalcontext 
        sin = &dst;
        clear_sinaddr(sin);
        sin->sin_port = htons(IPPORT_BOOTPC);
-       error = sobind(so, (struct sockaddr *)sin, td);
+       error = sobind(bootp_so, (struct sockaddr *)sin, td);
        if (error != 0) {
                printf("bind failed\n");
                goto out;
@@ -662,9 +646,7 @@ bootpc_call(struct bootpc_globalcontext 
                outstanding = 0;
                gotrootpath = 0;
 
-               for (ifctx = gctx->interfaces;
-                    ifctx != NULL;
-                    ifctx = ifctx->next) {
+               STAILQ_FOREACH(ifctx, &gctx->interfaces, next) {
                        if (bootpc_ifctx_isresolved(ifctx) != 0 &&
                            bootpc_tag(&gctx->tmptag, &ifctx->reply,
                                       ifctx->replylen,
@@ -672,9 +654,10 @@ bootpc_call(struct bootpc_globalcontext 
                                gotrootpath = 1;
                }
 
-               for (ifctx = gctx->interfaces;
-                    ifctx != NULL;
-                    ifctx = ifctx->next) {
+               STAILQ_FOREACH(ifctx, &gctx->interfaces, next) {
+                       struct in_aliasreq *ifra = &ifctx->iareq;
+                       sin = (struct sockaddr_in *)&ifra->ifra_mask;
+
                        ifctx->outstanding = 0;
                        if (bootpc_ifctx_isresolved(ifctx)  != 0 &&
                            gotrootpath != 0) {
@@ -694,7 +677,7 @@ bootpc_call(struct bootpc_globalcontext 
                            (ifctx->state == IF_BOOTP_UNRESOLVED &&
                             ifctx->dhcpquerytype != DHCP_NOMSG)) {
                                ifctx->sentmsg = 0;
-                               bootpc_compose_query(ifctx, gctx, td);
+                               bootpc_compose_query(ifctx, td);
                        }
 
                        /* Send BOOTP request (or re-send). */
@@ -734,44 +717,32 @@ bootpc_call(struct bootpc_globalcontext 
                        auio.uio_td = td;
 
                        /* Set netmask to 0.0.0.0 */
-
-                       sin = (struct sockaddr_in *) &ifctx->ireq.ifr_addr;
                        clear_sinaddr(sin);
-                       error = ifioctl(ifctx->so, SIOCSIFNETMASK,
-                                       (caddr_t) &ifctx->ireq, td);
+                       error = ifioctl(bootp_so, SIOCAIFADDR, (caddr_t)ifra,
+                           td);
                        if (error != 0)
-                               panic("bootpc_call:"
-                                     "set if netmask, error=%d",
-                                     error);
+                               panic("%s: SIOCAIFADDR, error=%d", __func__,
+                                   error);
 
-                       error = sosend(so, (struct sockaddr *) &dst,
+                       error = sosend(bootp_so, (struct sockaddr *) &dst,
                                       &auio, NULL, NULL, 0, td);
-                       if (error != 0) {
-                               printf("bootpc_call: sosend: %d state %08x\n",
-                                      error, (int) so->so_state);
-                       }
-
-                       /* XXX: Is this needed ? */
-                       pause("bootpw", hz/10);
+                       if (error != 0)
+                               printf("%s: sosend: %d state %08x\n", __func__,
+                                   error, (int )bootp_so->so_state);
 
                        /* Set netmask to 255.0.0.0 */
-
-                       sin = (struct sockaddr_in *) &ifctx->ireq.ifr_addr;
-                       clear_sinaddr(sin);
-                       sin->sin_addr.s_addr = htonl(0xff000000u);
-                       error = ifioctl(ifctx->so, SIOCSIFNETMASK,
-                                       (caddr_t) &ifctx->ireq, td);
+                       sin->sin_addr.s_addr = htonl(IN_CLASSA_NET);
+                       error = ifioctl(bootp_so, SIOCAIFADDR, (caddr_t)ifra,
+                           td);
                        if (error != 0)
-                               panic("bootpc_call:"
-                                     "set if netmask, error=%d",
-                                     error);
-
+                               panic("%s: SIOCAIFADDR, error=%d", __func__,
+                                   error);
                }
 
                if (outstanding == 0 &&
                    (rtimo == 0 || time_second >= rtimo)) {
                        error = 0;
-                       goto gotreply;
+                       goto out;
                }
 
                /* Determine new timeout. */
@@ -801,12 +772,10 @@ bootpc_call(struct bootpc_globalcontext 
                        auio.uio_td = td;
 
                        rcvflg = 0;
-                       error = soreceive(so, NULL, &auio,
+                       error = soreceive(bootp_so, NULL, &auio,
                                          NULL, NULL, &rcvflg);
                        gctx->secs = time_second - gctx->starttime;
-                       for (ifctx = gctx->interfaces;
-                            ifctx != NULL;
-                            ifctx = ifctx->next) {
+                       STAILQ_FOREACH(ifctx, &gctx->interfaces, next) {
                                if (bootpc_ifctx_isresolved(ifctx) != 0 ||
                                    bootpc_ifctx_isfailed(ifctx) != 0)
                                        continue;
@@ -829,9 +798,7 @@ bootpc_call(struct bootpc_globalcontext 
                                continue;
 
                        /* Is this an answer to our query */
-                       for (ifctx = gctx->interfaces;
-                            ifctx != NULL;
-                            ifctx = ifctx->next) {
+                       STAILQ_FOREACH(ifctx, &gctx->interfaces, next) {
                                if (gctx->reply.xid != ifctx->call.xid)
                                        continue;
 
@@ -906,15 +873,13 @@ bootpc_call(struct bootpc_globalcontext 
 #endif
                /* Force a retry if halfway in DHCP negotiation */
                retry = 0;
-               for (ifctx = gctx->interfaces; ifctx != NULL;
-                    ifctx = ifctx->next) {
+               STAILQ_FOREACH(ifctx, &gctx->interfaces, next)
                        if (ifctx->state == IF_DHCP_OFFERED) {
                                if (ifctx->dhcpquerytype == DHCP_DISCOVER)
                                        retry = 1;
                                else
                                        ifctx->state = IF_DHCP_UNRESOLVED;
                        }
-               }
 
                if (retry != 0)
                        continue;
@@ -931,14 +896,14 @@ bootpc_call(struct bootpc_globalcontext 
         * ignored
         */
 
-       for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) {
+       STAILQ_FOREACH(ifctx, &gctx->interfaces, next)
                if (bootpc_ifctx_isresolved(ifctx) == 0) {
                        printf("%s timeout for interface %s\n",
                               ifctx->dhcpquerytype != DHCP_NOMSG ?
                               "DHCP" : "BOOTP",
                               ifctx->ireq.ifr_name);
                }
-       }
+
        if (gctx->gotrootpath != 0) {
 #if 0
                printf("Got a root path, ignoring remaining timeout\n");
@@ -947,40 +912,28 @@ bootpc_call(struct bootpc_globalcontext 
                goto out;
        }
 #ifndef BOOTP_NFSROOT
-       for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) {
+       STAILQ_FOREACH(ifctx, &gctx->interfaces, next)
                if (bootpc_ifctx_isresolved(ifctx) != 0) {
                        error = 0;
                        goto out;
                }
-       }
 #endif
        error = ETIMEDOUT;
-       goto out;
 
-gotreply:
 out:
-       soclose(so);
-out0:
-       return error;
+       return (error);
 }
 
-static int
-bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx,
-    struct bootpc_globalcontext *gctx, struct thread *td)
+static void
+bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx, struct thread *td)
 {
+       struct ifreq *ifr;
+       struct in_aliasreq *ifra;
        struct sockaddr_in *sin;
        int error;
-       struct ifreq *ireq;
-       struct socket *so;
-       struct ifaddr *ifa;
-       struct sockaddr_dl *sdl;
-
-       error = socreate(AF_INET, &ifctx->so, SOCK_DGRAM, 0, td->td_ucred, td);
-       if (error != 0)
-               panic("nfs_boot: socreate, error=%d", error);
 
-       ireq = &ifctx->ireq;
-       so = ifctx->so;
+       ifr = &ifctx->ireq;
+       ifra = &ifctx->iareq;
 
        /*
         * Bring up the interface.
@@ -988,71 +941,57 @@ bootpc_fakeup_interface(struct bootpc_if
         * Get the old interface flags and or IFF_UP into them; if
         * IFF_UP set blindly, interface selection can be clobbered.
         */
-       error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, td);
+       error = ifioctl(bootp_so, SIOCGIFFLAGS, (caddr_t)ifr, td);
        if (error != 0)
-               panic("bootpc_fakeup_interface: GIFFLAGS, error=%d", error);
-       ireq->ifr_flags |= IFF_UP;
-       error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, td);
+               panic("%s: SIOCGIFFLAGS, error=%d", __func__, error);
+       ifr->ifr_flags |= IFF_UP;
+       error = ifioctl(bootp_so, SIOCSIFFLAGS, (caddr_t)ifr, td);
        if (error != 0)
-               panic("bootpc_fakeup_interface: SIFFLAGS, error=%d", error);
+               panic("%s: SIOCSIFFLAGS, error=%d", __func__, error);
 
        /*
         * Do enough of ifconfig(8) so that the chosen interface
-        * can talk to the servers.  (just set the address)
+        * can talk to the servers. Set address to 0.0.0.0/8 and
+        * broadcast address to local broadcast.
         */
-
-       /* addr is 0.0.0.0 */
-
-       sin = (struct sockaddr_in *) &ireq->ifr_addr;
+       sin = (struct sockaddr_in *)&ifra->ifra_addr;
        clear_sinaddr(sin);
-       error = ifioctl(so, SIOCSIFADDR, (caddr_t) ireq, td);
-       if (error != 0 && (error != EEXIST || ifctx == gctx->interfaces))
-               panic("bootpc_fakeup_interface: "
-                     "set if addr, error=%d", error);
-
-       /* netmask is 255.0.0.0 */
-
-       sin = (struct sockaddr_in *) &ireq->ifr_addr;
+       sin = (struct sockaddr_in *)&ifra->ifra_mask;
+       clear_sinaddr(sin);
+       sin->sin_addr.s_addr = htonl(IN_CLASSA_NET);
+       sin = (struct sockaddr_in *)&ifra->ifra_broadaddr;
        clear_sinaddr(sin);
-       sin->sin_addr.s_addr = htonl(0xff000000u);
-       error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, td);
+       sin->sin_addr.s_addr = htonl(INADDR_BROADCAST);
+       error = ifioctl(bootp_so, SIOCAIFADDR, (caddr_t)ifra, td);
        if (error != 0)
-               panic("bootpc_fakeup_interface: set if netmask, error=%d",
-                     error);
+               panic("%s: SIOCAIFADDR, error=%d", __func__, error);
+}
 
-       /* Broadcast is 255.255.255.255 */
+static void
+bootpc_shutdown_interface(struct bootpc_ifcontext *ifctx, struct thread *td)
+{
+       struct ifreq *ifr;
+       struct sockaddr_in *sin;
+       int error;
 
-       sin = (struct sockaddr_in *)&ireq->ifr_addr;
-       clear_sinaddr(sin);
-       clear_sinaddr(&ifctx->broadcast);
-       sin->sin_addr.s_addr = htonl(INADDR_BROADCAST);
-       ifctx->broadcast.sin_addr.s_addr = sin->sin_addr.s_addr;
+       ifr = &ifctx->ireq;
 
-       error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, td);
+       printf("Shutdown interface %s\n", ifctx->ireq.ifr_name);
+       error = ifioctl(bootp_so, SIOCGIFFLAGS, (caddr_t)ifr, td);
        if (error != 0)
-               panic("bootpc_fakeup_interface: "
-                     "set if broadcast addr, error=%d",
-                     error);
-
-       /* Get HW address */
-
-       sdl = NULL;
-       TAILQ_FOREACH(ifa, &ifctx->ifp->if_addrhead, ifa_link)
-               if (ifa->ifa_addr->sa_family == AF_LINK) {
-                       sdl = (struct sockaddr_dl *)ifa->ifa_addr;
-                       if (sdl->sdl_type == IFT_ETHER)
-                               break;
-               }
-
-       if (sdl == NULL)
-               panic("bootpc: Unable to find HW address for %s",
-                     ifctx->ireq.ifr_name);
-       ifctx->sdl = sdl;
+               panic("%s: SIOCGIFFLAGS, error=%d", __func__, error);
+       ifr->ifr_flags &= ~IFF_UP;
+       error = ifioctl(bootp_so, SIOCSIFFLAGS, (caddr_t)ifr, td);
+       if (error != 0)
+               panic("%s: SIOCSIFFLAGS, error=%d", __func__, error);
 
-       return error;
+       sin = (struct sockaddr_in *) &ifr->ifr_addr;
+       clear_sinaddr(sin);
+       error = ifioctl(bootp_so, SIOCDIFADDR, (caddr_t) ifr, td);
+       if (error != 0)
+               panic("%s: SIOCDIFADDR, error=%d", __func__, error);
 }
 
-
 static int
 bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
     struct bootpc_globalcontext *gctx, struct thread *td)
@@ -1061,42 +1000,22 @@ bootpc_adjust_interface(struct bootpc_if
        struct sockaddr_in defdst;
        struct sockaddr_in defmask;
        struct sockaddr_in *sin;
-       struct ifreq *ireq;
-       struct socket *so;
+       struct ifreq *ifr;
+       struct in_aliasreq *ifra;
        struct sockaddr_in *myaddr;
        struct sockaddr_in *netmask;
        struct sockaddr_in *gw;
 
-       ireq = &ifctx->ireq;
-       so = ifctx->so;
+       ifr = &ifctx->ireq;
+       ifra = &ifctx->iareq;
        myaddr = &ifctx->myaddr;
        netmask = &ifctx->netmask;
        gw = &ifctx->gw;
 
        if (bootpc_ifctx_isresolved(ifctx) == 0) {
-
                /* Shutdown interfaces where BOOTP failed */
-
-               printf("Shutdown interface %s\n", ifctx->ireq.ifr_name);
-               error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, td);
-               if (error != 0)
-                       panic("bootpc_adjust_interface: "
-                             "SIOCGIFFLAGS, error=%d", error);
-               ireq->ifr_flags &= ~IFF_UP;
-               error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, td);
-               if (error != 0)
-                       panic("bootpc_adjust_interface: "
-                             "SIOCSIFFLAGS, error=%d", error);
-
-               sin = (struct sockaddr_in *) &ireq->ifr_addr;
-               clear_sinaddr(sin);
-               error = ifioctl(so, SIOCDIFADDR, (caddr_t) ireq, td);
-               if (error != 0 && (error != EEXIST ||
-                                  ifctx == gctx->interfaces))
-                       panic("bootpc_adjust_interface: "
-                             "SIOCDIFADDR, error=%d", error);
-
-               return 0;
+               bootpc_shutdown_interface(ifctx, td);
+               return (0);
        }
 
        printf("Adjusted interface %s\n", ifctx->ireq.ifr_name);
@@ -1104,28 +1023,21 @@ bootpc_adjust_interface(struct bootpc_if
         * Do enough of ifconfig(8) so that the chosen interface
         * can talk to the servers.  (just set the address)
         */
-       bcopy(netmask, &ireq->ifr_addr, sizeof(*netmask));
-       error = ifioctl(so, SIOCSIFNETMASK, (caddr_t) ireq, td);
+       sin = (struct sockaddr_in *) &ifr->ifr_addr;
+       clear_sinaddr(sin);
+       error = ifioctl(bootp_so, SIOCDIFADDR, (caddr_t) ifr, td);
        if (error != 0)
-               panic("bootpc_adjust_interface: "
-                     "set if netmask, error=%d", error);
+               panic("%s: SIOCDIFADDR, error=%d", __func__, error);
 
-       /* Broadcast is with host part of IP address all 1's */
+       bcopy(myaddr, &ifra->ifra_addr, sizeof(*myaddr));
+       bcopy(netmask, &ifra->ifra_mask, sizeof(*netmask));
+       clear_sinaddr(&ifra->ifra_broadaddr);
+       ifra->ifra_broadaddr.sin_addr.s_addr = myaddr->sin_addr.s_addr |
+           ~netmask->sin_addr.s_addr;
 
-       sin = (struct sockaddr_in *) &ireq->ifr_addr;
-       clear_sinaddr(sin);
-       sin->sin_addr.s_addr = myaddr->sin_addr.s_addr |
-               ~ netmask->sin_addr.s_addr;
-       error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t) ireq, td);
+       error = ifioctl(bootp_so, SIOCAIFADDR, (caddr_t)ifra, td);
        if (error != 0)
-               panic("bootpc_adjust_interface: "
-                     "set if broadcast addr, error=%d", error);
-
-       bcopy(myaddr, &ireq->ifr_addr, sizeof(*myaddr));
-       error = ifioctl(so, SIOCSIFADDR, (caddr_t) ireq, td);
-       if (error != 0 && (error != EEXIST || ifctx == gctx->interfaces))
-               panic("bootpc_adjust_interface: "
-                     "set if addr, error=%d", error);
+               panic("%s: SIOCAIFADDR, error=%d", __func__, error);
 
        /* Add new default route */
 
@@ -1139,13 +1051,12 @@ bootpc_adjust_interface(struct bootpc_if
                                  (struct sockaddr *) &defmask,
                                  (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL, 0);
                if (error != 0) {
-                       printf("bootpc_adjust_interface: "
-                              "add net route, error=%d\n", error);
-                       return error;
+                       printf("%s: RTM_ADD, error=%d\n", __func__, error);
+                       return (error);
                }
        }
 
-       return 0;
+       return (0);
 }
 
 static int
@@ -1288,8 +1199,7 @@ print_in_addr(struct in_addr addr)
 }
 
 static void
-bootpc_compose_query(struct bootpc_ifcontext *ifctx,
-    struct bootpc_globalcontext *gctx, struct thread *td)
+bootpc_compose_query(struct bootpc_ifcontext *ifctx, struct thread *td)
 {
        unsigned char *vendp;
        unsigned char vendor_client[64];
@@ -1595,9 +1505,11 @@ bootpc_decode_reply(struct nfsv3_diskles
 void
 bootpc_init(void)
 {
-       struct bootpc_ifcontext *ifctx, *nctx;  /* Interface BOOTP contexts */
+       struct bootpc_ifcontext *ifctx;         /* Interface BOOTP contexts */
        struct bootpc_globalcontext *gctx;      /* Global BOOTP context */
        struct ifnet *ifp;
+       struct sockaddr_dl *sdl;
+       struct ifaddr *ifa;
        int error;
 #ifndef BOOTP_WIRED_TO
        int ifcnt;
@@ -1615,9 +1527,7 @@ bootpc_init(void)
                return;
 
        gctx = malloc(sizeof(*gctx), M_TEMP, M_WAITOK | M_ZERO);
-       if (gctx == NULL)
-               panic("Failed to allocate bootp global context structure");
-
+       STAILQ_INIT(&gctx->interfaces);
        gctx->xid = ~0xFFFF;
        gctx->starttime = time_second;
 
@@ -1626,7 +1536,7 @@ bootpc_init(void)
         */
        CURVNET_SET(TD_TO_VNET(td));
 #ifdef BOOTP_WIRED_TO
-       printf("bootpc_init: wired to interface '%s'\n",
+       printf("%s: wired to interface '%s'\n", __func__, 
               __XSTRING(BOOTP_WIRED_TO));
        allocifctx(gctx);
 #else
@@ -1634,60 +1544,94 @@ bootpc_init(void)
         * Preallocate interface context storage, if another interface
         * attaches and wins the race, it won't be eligible for bootp.
         */
+       ifcnt = 0;
        IFNET_RLOCK();
-       for (ifp = TAILQ_FIRST(&V_ifnet), ifcnt = 0;
-            ifp != NULL;
-            ifp = TAILQ_NEXT(ifp, if_link)) {
+       TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
                if ((ifp->if_flags &
                     (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) !=
                    IFF_BROADCAST)
                        continue;
+               switch (ifp->if_alloctype) {
+                       case IFT_ETHER:
+                       case IFT_FDDI:
+                       case IFT_ISO88025:
+                               break;
+                       default:
+                               continue;
+               }
                ifcnt++;
        }
        IFNET_RUNLOCK();
        if (ifcnt == 0)
-               panic("bootpc_init: no eligible interfaces");
+               panic("%s: no eligible interfaces", __func__);
        for (; ifcnt > 0; ifcnt--)
                allocifctx(gctx);
 #endif
 
+       ifctx = STAILQ_FIRST(&gctx->interfaces);
        IFNET_RLOCK();
-       for (ifp = TAILQ_FIRST(&V_ifnet), ifctx = gctx->interfaces;
-            ifp != NULL && ifctx != NULL;
-            ifp = TAILQ_NEXT(ifp, if_link)) {
-               strlcpy(ifctx->ireq.ifr_name, ifp->if_xname,
-                   sizeof(ifctx->ireq.ifr_name));
+       TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
+               if (ifctx == NULL)
+                       break;
 #ifdef BOOTP_WIRED_TO
-               if (strcmp(ifctx->ireq.ifr_name,
-                          __XSTRING(BOOTP_WIRED_TO)) != 0)
+               if (strcmp(ifp->if_xname, __XSTRING(BOOTP_WIRED_TO)) != 0)
                        continue;
 #else
                if ((ifp->if_flags &
                     (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) !=
                    IFF_BROADCAST)
                        continue;
+               switch (ifp->if_alloctype) {
+                       case IFT_ETHER:
+                       case IFT_FDDI:
+                       case IFT_ISO88025:
+                               break;
+                       default:
+                               continue;
+               }
 #endif
+               strlcpy(ifctx->ireq.ifr_name, ifp->if_xname,
+                   sizeof(ifctx->ireq.ifr_name));
                ifctx->ifp = ifp;
-               ifctx = ifctx->next;
+
+               /* Get HW address */
+               sdl = NULL;
+               TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
+                       if (ifa->ifa_addr->sa_family == AF_LINK) {
+                               sdl = (struct sockaddr_dl *)ifa->ifa_addr;
+                               if (sdl->sdl_type == IFT_ETHER)
+                                       break;
+                       }
+               if (sdl == NULL)
+                       panic("bootpc: Unable to find HW address for %s",
+                           ifctx->ireq.ifr_name);
+               ifctx->sdl = sdl;
+
+               ifctx = STAILQ_NEXT(ifctx, next);
        }
        IFNET_RUNLOCK();
        CURVNET_RESTORE();
 
-       if (gctx->interfaces == NULL || gctx->interfaces->ifp == NULL) {
+       if (STAILQ_EMPTY(&gctx->interfaces) ||
+           STAILQ_FIRST(&gctx->interfaces)->ifp == NULL) {
 #ifdef BOOTP_WIRED_TO
-               panic("bootpc_init: Could not find interface specified "
+               panic("%s: Could not find interface specified "
                      "by BOOTP_WIRED_TO: "
-                     __XSTRING(BOOTP_WIRED_TO));
+                     __XSTRING(BOOTP_WIRED_TO), __func__);
 #else
-               panic("bootpc_init: no suitable interface");
+               panic("%s: no suitable interface", __func__);
 #endif
        }
 
-       for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next)
-               bootpc_fakeup_interface(ifctx, gctx, td);
+       error = socreate(AF_INET, &bootp_so, SOCK_DGRAM, 0, td->td_ucred, td);
+       if (error != 0)
+               panic("%s: socreate, error=%d", __func__, error);
 
-       for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next)
-               bootpc_compose_query(ifctx, gctx, td);
+       STAILQ_FOREACH(ifctx, &gctx->interfaces, next)
+               bootpc_fakeup_interface(ifctx, td);
+
+       STAILQ_FOREACH(ifctx, &gctx->interfaces, next)
+               bootpc_compose_query(ifctx, td);
 
        error = bootpc_call(gctx, td);
 
@@ -1705,7 +1649,7 @@ bootpc_init(void)
 #endif
        mountopts(&nd->root_args, NULL);
 
-       for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next)
+       STAILQ_FOREACH(ifctx, &gctx->interfaces, next)
                if (bootpc_ifctx_isresolved(ifctx) != 0)
                        bootpc_decode_reply(nd, ifctx, gctx);
 
@@ -1714,19 +1658,16 @@ bootpc_init(void)
                panic("bootpc: No root path offered");
 #endif
 
-       for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) {
+       STAILQ_FOREACH(ifctx, &gctx->interfaces, next)
                bootpc_adjust_interface(ifctx, gctx, td);
 
-               soclose(ifctx->so);
-       }
+       soclose(bootp_so);
 
-       for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next)
+       STAILQ_FOREACH(ifctx, &gctx->interfaces, next)
                if (ifctx->gotrootpath != 0)
                        break;
        if (ifctx == NULL) {
-               for (ifctx = gctx->interfaces;
-                    ifctx != NULL;
-                    ifctx = ifctx->next)
+               STAILQ_FOREACH(ifctx, &gctx->interfaces, next)
                        if (bootpc_ifctx_isresolved(ifctx) != 0)
                                break;
        }
@@ -1755,8 +1696,8 @@ bootpc_init(void)
        bcopy(&ifctx->netmask, &nd->myif.ifra_mask, sizeof(ifctx->netmask));
 
 out:
-       for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = nctx) {
-               nctx = ifctx->next;
+       while((ifctx = STAILQ_FIRST(&gctx->interfaces)) != NULL) {
+               STAILQ_REMOVE_HEAD(&gctx->interfaces, next);
                free(ifctx, M_TEMP);
        }
        free(gctx, M_TEMP);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to