Changeset View
Standalone View
sys/nfs/bootp_subr.c
Show First 20 Lines • Show All 131 Lines • ▼ Show 20 Lines | struct bootpc_ifcontext { | ||||
int replylen; | int replylen; | ||||
int overload; | int overload; | ||||
union { | union { | ||||
struct ifreq _ifreq; | struct ifreq _ifreq; | ||||
struct in_aliasreq _in_alias_req; | struct in_aliasreq _in_alias_req; | ||||
} _req; | } _req; | ||||
#define ireq _req._ifreq | #define ireq _req._ifreq | ||||
#define iareq _req._in_alias_req | #define iareq _req._in_alias_req | ||||
struct ifnet *ifp; | if_t ifp; | ||||
struct sockaddr_dl *sdl; | struct sockaddr_dl *sdl; | ||||
struct sockaddr_in myaddr; | struct sockaddr_in myaddr; | ||||
struct sockaddr_in netmask; | struct sockaddr_in netmask; | ||||
struct sockaddr_in gw; | struct sockaddr_in gw; | ||||
int gotgw; | int gotgw; | ||||
int gotnetmask; | int gotnetmask; | ||||
int gotrootpath; | int gotrootpath; | ||||
int outstanding; | int outstanding; | ||||
▲ Show 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | |||||
static void bootpc_compose_query(struct bootpc_ifcontext *ifctx, | static void bootpc_compose_query(struct bootpc_ifcontext *ifctx, | ||||
struct thread *td); | struct thread *td); | ||||
static unsigned char *bootpc_tag(struct bootpc_tagcontext *tctx, | static unsigned char *bootpc_tag(struct bootpc_tagcontext *tctx, | ||||
struct bootp_packet *bp, int len, int tag); | struct bootp_packet *bp, int len, int tag); | ||||
static void bootpc_tag_helper(struct bootpc_tagcontext *tctx, | static void bootpc_tag_helper(struct bootpc_tagcontext *tctx, | ||||
unsigned char *start, int len, int tag); | unsigned char *start, int len, int tag); | ||||
#ifdef BOOTP_DEBUG | #ifdef BOOTP_DEBUG | ||||
void bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa); | |||||
void bootpboot_p_iflist(void); | void bootpboot_p_iflist(void); | ||||
#endif | #endif | ||||
static int bootpc_call(struct bootpc_globalcontext *gctx, | static int bootpc_call(struct bootpc_globalcontext *gctx, | ||||
struct thread *td); | struct thread *td); | ||||
static void bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx, | static void bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx, | ||||
struct thread *td); | struct thread *td); | ||||
Show All 15 Lines | |||||
/* | /* | ||||
* In order to have multiple active interfaces with address 0.0.0.0 | * In order to have multiple active interfaces with address 0.0.0.0 | ||||
* and be able to send data to a selected interface, we first set | * 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 | * mask to /8 on all interfaces, and temporarily set it to /0 when | ||||
* doing sosend(). | * doing sosend(). | ||||
*/ | */ | ||||
#ifdef BOOTP_DEBUG | #ifdef BOOTP_DEBUG | ||||
void | static u_int | ||||
bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa) | bootpboot_p_ifa(void *ifp, struct ifaddr *ifa, u_int count __unused) | ||||
{ | { | ||||
printf("%s flags %x, addr ", | printf("%s flags %x, addr ", | ||||
ifp->if_xname, ifp->if_flags); | if_name(ifp), if_getflags(ifp)); | ||||
print_sin_addr((struct sockaddr_in *) ifa->ifa_addr); | print_sin_addr((struct sockaddr_in *) ifa->ifa_addr); | ||||
printf(", broadcast "); | printf(", broadcast "); | ||||
print_sin_addr((struct sockaddr_in *) ifa->ifa_dstaddr); | print_sin_addr((struct sockaddr_in *) ifa->ifa_dstaddr); | ||||
printf(", netmask "); | printf(", netmask "); | ||||
print_sin_addr((struct sockaddr_in *) ifa->ifa_netmask); | print_sin_addr((struct sockaddr_in *) ifa->ifa_netmask); | ||||
printf("\n"); | printf("\n"); | ||||
return (0); | |||||
} | } | ||||
void | void | ||||
bootpboot_p_iflist(void) | bootpboot_p_iflist(void) | ||||
{ | { | ||||
struct ifnet *ifp; | struct epoch_tracker et; | ||||
struct ifaddr *ifa; | struct if_iter iter; | ||||
if_t ifp; | |||||
printf("Interface list:\n"); | printf("Interface list:\n"); | ||||
IFNET_RLOCK(); | NET_EPOCH_ENTER(et); | ||||
for (ifp = CK_STAILQ_FIRST(&V_ifnet); | for (ifp = if_iter_start(&iter); ifp != NULL; ifp = if_iter_next(&iter)) | ||||
ifp != NULL; | if_foreach_addr_type(ifp, AF_INET, bootpboot_p_ifa, ifp); | ||||
ifp = CK_STAILQ_NEXT(ifp, if_link)) { | if_iter_finish(&iter); | ||||
for (ifa = CK_STAILQ_FIRST(&ifp->if_addrhead); | NET_EPOCH_EXIT(et); | ||||
ifa != NULL; | |||||
ifa = CK_STAILQ_NEXT(ifa, ifa_link)) | |||||
if (ifa->ifa_addr->sa_family == AF_INET) | |||||
bootpboot_p_if(ifp, ifa); | |||||
} | } | ||||
IFNET_RUNLOCK(); | |||||
} | |||||
#endif /* defined(BOOTP_DEBUG) */ | #endif /* defined(BOOTP_DEBUG) */ | ||||
static void | static void | ||||
clear_sinaddr(struct sockaddr_in *sin) | clear_sinaddr(struct sockaddr_in *sin) | ||||
{ | { | ||||
bzero(sin, sizeof(*sin)); | bzero(sin, sizeof(*sin)); | ||||
sin->sin_len = sizeof(*sin); | sin->sin_len = sizeof(*sin); | ||||
▲ Show 20 Lines • Show All 1,154 Lines • ▼ Show 20 Lines | if (IN_CLASSA(ntohl(ifctx->myaddr.sin_addr.s_addr))) | ||||
ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSA_NET); | ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSA_NET); | ||||
else if (IN_CLASSB(ntohl(ifctx->myaddr.sin_addr.s_addr))) | else if (IN_CLASSB(ntohl(ifctx->myaddr.sin_addr.s_addr))) | ||||
ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSB_NET); | ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSB_NET); | ||||
else | else | ||||
ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSC_NET); | ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSC_NET); | ||||
} | } | ||||
} | } | ||||
static u_int | |||||
bootpc_init_ifa_cb(void *arg, struct ifaddr *ifa, u_int count) | |||||
{ | |||||
struct sockaddr_dl *sdl = (struct sockaddr_dl *)ifa->ifa_addr; | |||||
if (count != 0) | |||||
return (0); | |||||
if (sdl->sdl_type != IFT_ETHER) | |||||
return (0); | |||||
*(struct sockaddr_dl **)arg = sdl; | |||||
return (1); | |||||
} | |||||
void | void | ||||
bootpc_init(void) | bootpc_init(void) | ||||
{ | { | ||||
struct epoch_tracker et; | |||||
struct bootpc_ifcontext *ifctx = NULL; /* Interface BOOTP contexts */ | struct bootpc_ifcontext *ifctx = NULL; /* Interface BOOTP contexts */ | ||||
struct bootpc_globalcontext *gctx; /* Global BOOTP context */ | struct bootpc_globalcontext *gctx; /* Global BOOTP context */ | ||||
struct ifnet *ifp; | |||||
struct sockaddr_dl *sdl; | struct sockaddr_dl *sdl; | ||||
struct ifaddr *ifa; | struct if_iter iter; | ||||
if_t ifp; | |||||
int error; | int error; | ||||
#ifndef BOOTP_WIRED_TO | #ifndef BOOTP_WIRED_TO | ||||
int ifcnt; | int ifcnt; | ||||
#endif | #endif | ||||
struct nfsv3_diskless *nd; | struct nfsv3_diskless *nd; | ||||
struct thread *td; | struct thread *td; | ||||
int timeout; | int timeout; | ||||
int delay; | int delay; | ||||
char *s; | char *s; | ||||
timeout = BOOTP_IFACE_WAIT_TIMEOUT * hz; | timeout = BOOTP_IFACE_WAIT_TIMEOUT * hz; | ||||
delay = hz / 10; | delay = hz / 10; | ||||
nd = &nfsv3_diskless; | nd = &nfsv3_diskless; | ||||
td = curthread; | td = curthread; | ||||
/* | /* | ||||
* If already filled in, don't touch it here | * If already filled in, don't touch it here | ||||
*/ | */ | ||||
if (nfs_diskless_valid != 0) | if (nfs_diskless_valid != 0) | ||||
melifaro: Isn't it just `if_getifaddr(ifp)` ? | |||||
Done Inline ActionsI'm not sure. It's looking specifically for an IFT_ETHER type, would the if_addr always be an IFT_ETHER? jhibbits: I'm not sure. It's looking specifically for an IFT_ETHER type, would the if_addr always be an… | |||||
Not Done Inline Actionsif_attach() creates a new sdl, which is then assigned to if_addr. The data inside this sdl is derived from the if_type at the moment of attach (e.g. for everrything calling ether_ifattach() it will be IFT_ETHER). Additionally, I'm not sure if having AF_LINK address in the chain of addresses is the right thing to have. melifaro: `if_attach()` creates a new sdl, which is then assigned to `if_addr`. The data inside this sdl… | |||||
return; | return; | ||||
/* | /* | ||||
* If "vfs.root.mountfrom" is set and the value is something other | * If "vfs.root.mountfrom" is set and the value is something other | ||||
* than "nfs:", it means the user doesn't want to mount root via nfs, | * than "nfs:", it means the user doesn't want to mount root via nfs, | ||||
* there's no reason to continue with bootpc | * there's no reason to continue with bootpc | ||||
*/ | */ | ||||
if ((s = kern_getenv("vfs.root.mountfrom")) != NULL) { | if ((s = kern_getenv("vfs.root.mountfrom")) != NULL) { | ||||
Show All 31 Lines | printf("%s: wired to interface '%s'\n", __func__, | ||||
__XSTRING(BOOTP_WIRED_TO)); | __XSTRING(BOOTP_WIRED_TO)); | ||||
allocifctx(gctx); | allocifctx(gctx); | ||||
#else | #else | ||||
/* | /* | ||||
* Preallocate interface context storage, if another interface | * Preallocate interface context storage, if another interface | ||||
* attaches and wins the race, it won't be eligible for bootp. | * attaches and wins the race, it won't be eligible for bootp. | ||||
*/ | */ | ||||
ifcnt = 0; | ifcnt = 0; | ||||
IFNET_RLOCK(); | NET_EPOCH_ENTER(et); | ||||
CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { | for (if_t ifp = if_iter_start(&iter); ifp != NULL; ifp = if_iter_next(&iter)) { | ||||
if ((ifp->if_flags & | if ((if_getflags(ifp) & | ||||
(IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) != | (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) == | ||||
IFF_BROADCAST) | IFF_BROADCAST) | ||||
continue; | |||||
switch (ifp->if_alloctype) { | |||||
case IFT_ETHER: | |||||
break; | |||||
default: | |||||
continue; | |||||
} | |||||
ifcnt++; | ifcnt++; | ||||
} | } | ||||
if_iter_finish(&iter); | |||||
IFNET_RUNLOCK(); | NET_EPOCH_EXIT(et); | ||||
if (ifcnt == 0) { | if (ifcnt == 0) { | ||||
printf("WARNING: BOOTP found no eligible network interfaces, skipping!\n"); | printf("WARNING: BOOTP found no eligible network interfaces, skipping!\n"); | ||||
goto out; | goto out; | ||||
} | } | ||||
for (; ifcnt > 0; ifcnt--) | for (; ifcnt > 0; ifcnt--) | ||||
allocifctx(gctx); | allocifctx(gctx); | ||||
#endif | #endif | ||||
retry: | retry: | ||||
ifctx = STAILQ_FIRST(&gctx->interfaces); | ifctx = STAILQ_FIRST(&gctx->interfaces); | ||||
IFNET_RLOCK(); | NET_EPOCH_ENTER(et); | ||||
CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { | for (ifp = if_iter_start(&iter); ifp != NULL; ifp = if_iter_next(&iter)) { | ||||
if (ifctx == NULL) | if (ifctx == NULL) | ||||
break; | break; | ||||
#ifdef BOOTP_WIRED_TO | #ifdef BOOTP_WIRED_TO | ||||
if (strcmp(ifp->if_xname, __XSTRING(BOOTP_WIRED_TO)) != 0) | if (strcmp(if_name(ifp), __XSTRING(BOOTP_WIRED_TO)) != 0) | ||||
continue; | continue; | ||||
#else | #else | ||||
if ((ifp->if_flags & | if ((if_getflags(ifp) & | ||||
(IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) != | (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) != | ||||
IFF_BROADCAST) | IFF_BROADCAST) | ||||
continue; | break; | ||||
switch (ifp->if_alloctype) { | switch (if_getalloctype(ifp)) { | ||||
case IFT_ETHER: | case IFT_ETHER: | ||||
break; | break; | ||||
default: | default: | ||||
continue; | continue; | ||||
} | } | ||||
#endif | #endif | ||||
strlcpy(ifctx->ireq.ifr_name, ifp->if_xname, | strlcpy(ifctx->ireq.ifr_name, if_name(ifp), | ||||
sizeof(ifctx->ireq.ifr_name)); | sizeof(ifctx->ireq.ifr_name)); | ||||
ifctx->ifp = ifp; | ifctx->ifp = ifp; | ||||
/* Get HW address */ | /* Get HW address */ | ||||
sdl = NULL; | sdl = NULL; | ||||
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) | if_foreach_addr_type(ifp, AF_LINK, bootpc_init_ifa_cb, &sdl); | ||||
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) | if (sdl == NULL) | ||||
panic("bootpc: Unable to find HW address for %s", | panic("bootpc: Unable to find HW address for %s", | ||||
ifctx->ireq.ifr_name); | ifctx->ireq.ifr_name); | ||||
ifctx->sdl = sdl; | ifctx->sdl = sdl; | ||||
ifctx = STAILQ_NEXT(ifctx, next); | ifctx = STAILQ_NEXT(ifctx, next); | ||||
} | } | ||||
IFNET_RUNLOCK(); | if_iter_finish(&iter); | ||||
NET_EPOCH_EXIT(et); | |||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
if (STAILQ_EMPTY(&gctx->interfaces) || | if (STAILQ_EMPTY(&gctx->interfaces) || | ||||
STAILQ_FIRST(&gctx->interfaces)->ifp == NULL) { | STAILQ_FIRST(&gctx->interfaces)->ifp == NULL) { | ||||
if (timeout > 0) { | if (timeout > 0) { | ||||
pause("bootpc", delay); | pause("bootpc", delay); | ||||
timeout -= delay; | timeout -= delay; | ||||
goto retry; | goto retry; | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | STAILQ_FOREACH(ifctx, &gctx->interfaces, next) | ||||
break; | break; | ||||
} | } | ||||
if (ifctx == NULL) | if (ifctx == NULL) | ||||
goto out; | goto out; | ||||
if (gctx->gotrootpath != 0) { | if (gctx->gotrootpath != 0) { | ||||
struct epoch_tracker et; | struct epoch_tracker et; | ||||
kern_setenv("boot.netif.name", ifctx->ifp->if_xname); | kern_setenv("boot.netif.name", if_name(ifctx->ifp)); | ||||
NET_EPOCH_ENTER(et); | NET_EPOCH_ENTER(et); | ||||
bootpc_add_default_route(ifctx); | bootpc_add_default_route(ifctx); | ||||
NET_EPOCH_EXIT(et); | NET_EPOCH_EXIT(et); | ||||
error = md_mount(&nd->root_saddr, nd->root_hostnam, | error = md_mount(&nd->root_saddr, nd->root_hostnam, | ||||
nd->root_fh, &nd->root_fhsize, | nd->root_fh, &nd->root_fhsize, | ||||
&nd->root_args, td); | &nd->root_args, td); | ||||
NET_EPOCH_ENTER(et); | NET_EPOCH_ENTER(et); | ||||
▲ Show 20 Lines • Show All 136 Lines • Show Last 20 Lines |
Isn't it just if_getifaddr(ifp) ?