diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/nfs/bootp_subr.c | 413 |
1 files changed, 177 insertions, 236 deletions
diff --git a/sys/nfs/bootp_subr.c b/sys/nfs/bootp_subr.c index bd4a826..1e5e066 100644 --- a/sys/nfs/bootp_subr.c +++ b/sys/nfs/bootp_subr.c @@ -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 sockaddr_in *addr); 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_isfailed(struct bootpc_ifcontext *ifctx); /* * 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 *gctx) 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_globalcontext *gctx, 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 *gctx, struct thread *td) 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 *gctx, struct thread *td) 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 *gctx, struct thread *td) 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 *gctx, struct thread *td) 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 *gctx, struct thread *td) 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 *gctx, struct thread *td) 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 *gctx, struct thread *td) 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 *gctx, struct thread *td) (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 *gctx, struct thread *td) 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 *gctx, struct thread *td) 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 *gctx, struct thread *td) 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 *gctx, struct thread *td) #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 *gctx, struct thread *td) * 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 *gctx, struct thread *td) 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_ifcontext *ifctx, * 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(0xff000000u); - error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, td); - if (error != 0) - panic("bootpc_fakeup_interface: set if netmask, error=%d", - error); - - /* Broadcast is 255.255.255.255 */ - - sin = (struct sockaddr_in *)&ireq->ifr_addr; + sin->sin_addr.s_addr = htonl(IN_CLASSA_NET); + sin = (struct sockaddr_in *)&ifra->ifra_broadaddr; 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; - - error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, td); + error = ifioctl(bootp_so, SIOCAIFADDR, (caddr_t)ifra, td); if (error != 0) - panic("bootpc_fakeup_interface: " - "set if broadcast addr, error=%d", - error); + panic("%s: SIOCAIFADDR, error=%d", __func__, error); +} - /* Get HW address */ +static void +bootpc_shutdown_interface(struct bootpc_ifcontext *ifctx, struct thread *td) +{ + struct ifreq *ifr; + struct sockaddr_in *sin; + int error; - 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; - } + ifr = &ifctx->ireq; - if (sdl == NULL) - panic("bootpc: Unable to find HW address for %s", - ifctx->ireq.ifr_name); - ifctx->sdl = sdl; + printf("Shutdown interface %s\n", ifctx->ireq.ifr_name); + error = ifioctl(bootp_so, SIOCGIFFLAGS, (caddr_t)ifr, td); + if (error != 0) + 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_ifcontext *ifctx, 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_ifcontext *ifctx, * 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_ifcontext *ifctx, (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_diskless *nd, struct bootpc_ifcontext *ifctx, 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); |