bootp_subr.c (b40ce4165d5eb3a5de1515245055350ae3dbab8e) | bootp_subr.c (7c208ed659437ef984f2bb98bdc20fa5cfdebefc) |
---|---|
1/* $FreeBSD$ */ 2 3/* | 1/*- |
4 * Copyright (c) 1995 Gordon Ross, Adam Glass 5 * Copyright (c) 1992 Regents of the University of California. 6 * All rights reserved. 7 * 8 * This software was developed by the Computer Systems Engineering group 9 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 10 * contributed to Berkeley. 11 * --- 25 unchanged lines hidden (view full) --- 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * based on: 41 * nfs/krpc_subr.c 42 * $NetBSD: krpc_subr.c,v 1.10 1995/08/08 20:43:43 gwr Exp $ 43 */ 44 | 2 * Copyright (c) 1995 Gordon Ross, Adam Glass 3 * Copyright (c) 1992 Regents of the University of California. 4 * All rights reserved. 5 * 6 * This software was developed by the Computer Systems Engineering group 7 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 8 * contributed to Berkeley. 9 * --- 25 unchanged lines hidden (view full) --- 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * based on: 39 * nfs/krpc_subr.c 40 * $NetBSD: krpc_subr.c,v 1.10 1995/08/08 20:43:43 gwr Exp $ 41 */ 42 |
43#include <sys/cdefs.h> 44__FBSDID("$FreeBSD$"); 45 |
|
45#include "opt_bootp.h" 46 47#include <sys/param.h> 48#include <sys/systm.h> | 46#include "opt_bootp.h" 47 48#include <sys/param.h> 49#include <sys/systm.h> |
50#include <sys/jail.h> |
|
49#include <sys/kernel.h> 50#include <sys/sockio.h> 51#include <sys/malloc.h> 52#include <sys/mount.h> 53#include <sys/mbuf.h> | 51#include <sys/kernel.h> 52#include <sys/sockio.h> 53#include <sys/malloc.h> 54#include <sys/mount.h> 55#include <sys/mbuf.h> |
56#include <sys/proc.h> |
|
54#include <sys/socket.h> 55#include <sys/socketvar.h> | 57#include <sys/socket.h> 58#include <sys/socketvar.h> |
59#include <sys/sysctl.h> |
|
56#include <sys/uio.h> 57 58#include <net/if.h> 59#include <net/route.h> 60 61#include <netinet/in.h> 62#include <net/if_types.h> 63#include <net/if_dl.h> | 60#include <sys/uio.h> 61 62#include <net/if.h> 63#include <net/route.h> 64 65#include <netinet/in.h> 66#include <net/if_types.h> 67#include <net/if_dl.h> |
68#include <net/vnet.h> |
|
64 | 69 |
65#include <nfs/rpcv2.h> | |
66#include <nfs/nfsproto.h> | 70#include <nfs/nfsproto.h> |
67#include <nfs/nfs.h> | 71#include <nfsclient/nfs.h> |
68#include <nfs/nfsdiskless.h> 69#include <nfs/krpc.h> 70#include <nfs/xdr_subs.h> 71 72 73#define BOOTP_MIN_LEN 300 /* Minimum size of bootp udp packet */ 74 75#ifndef BOOTP_SETTLE_DELAY --- 19 unchanged lines hidden (view full) --- 95 u_int16_t flags; 96 struct in_addr ciaddr; 97 struct in_addr yiaddr; 98 struct in_addr siaddr; 99 struct in_addr giaddr; 100 unsigned char chaddr[16]; 101 char sname[64]; 102 char file[128]; | 72#include <nfs/nfsdiskless.h> 73#include <nfs/krpc.h> 74#include <nfs/xdr_subs.h> 75 76 77#define BOOTP_MIN_LEN 300 /* Minimum size of bootp udp packet */ 78 79#ifndef BOOTP_SETTLE_DELAY --- 19 unchanged lines hidden (view full) --- 99 u_int16_t flags; 100 struct in_addr ciaddr; 101 struct in_addr yiaddr; 102 struct in_addr siaddr; 103 struct in_addr giaddr; 104 unsigned char chaddr[16]; 105 char sname[64]; 106 char file[128]; |
103 unsigned char vend[256]; | 107 unsigned char vend[1222]; |
104}; 105 106struct bootpc_ifcontext { 107 struct bootpc_ifcontext *next; 108 struct bootp_packet call; 109 struct bootp_packet reply; 110 int replylen; 111 int overload; --- 35 unchanged lines hidden (view full) --- 147 int taglen; 148}; 149 150struct bootpc_globalcontext { 151 struct bootpc_ifcontext *interfaces; 152 struct bootpc_ifcontext *lastinterface; 153 u_int32_t xid; 154 int gotrootpath; | 108}; 109 110struct bootpc_ifcontext { 111 struct bootpc_ifcontext *next; 112 struct bootp_packet call; 113 struct bootp_packet reply; 114 int replylen; 115 int overload; --- 35 unchanged lines hidden (view full) --- 151 int taglen; 152}; 153 154struct bootpc_globalcontext { 155 struct bootpc_ifcontext *interfaces; 156 struct bootpc_ifcontext *lastinterface; 157 u_int32_t xid; 158 int gotrootpath; |
155 int gotswappath; | |
156 int gotgw; 157 int ifnum; 158 int secs; 159 int starttime; 160 struct bootp_packet reply; 161 int replylen; | 159 int gotgw; 160 int ifnum; 161 int secs; 162 int starttime; 163 struct bootp_packet reply; 164 int replylen; |
162 struct bootpc_ifcontext *setswapfs; | |
163 struct bootpc_ifcontext *setrootfs; 164 struct bootpc_ifcontext *sethostname; | 165 struct bootpc_ifcontext *setrootfs; 166 struct bootpc_ifcontext *sethostname; |
165 char lookup_path[24]; | |
166 struct bootpc_tagcontext tmptag; 167 struct bootpc_tagcontext tag; 168}; 169 170#define IPPORT_BOOTPC 68 171#define IPPORT_BOOTPS 67 172 173#define BOOTP_REQUEST 1 --- 12 unchanged lines hidden (view full) --- 186 187#define TAG_END 255 /* End Option (i.e. no more options) */ 188 189/* Overload values */ 190#define OVERLOAD_FILE 1 191#define OVERLOAD_SNAME 2 192 193/* Site specific tags: */ | 167 struct bootpc_tagcontext tmptag; 168 struct bootpc_tagcontext tag; 169}; 170 171#define IPPORT_BOOTPC 68 172#define IPPORT_BOOTPS 67 173 174#define BOOTP_REQUEST 1 --- 12 unchanged lines hidden (view full) --- 187 188#define TAG_END 255 /* End Option (i.e. no more options) */ 189 190/* Overload values */ 191#define OVERLOAD_FILE 1 192#define OVERLOAD_SNAME 2 193 194/* Site specific tags: */ |
194#define TAG_SWAP 128 195#define TAG_SWAPSIZE 129 | |
196#define TAG_ROOTOPTS 130 | 195#define TAG_ROOTOPTS 130 |
197#define TAG_SWAPOPTS 131 | 196#define TAG_COOKIE 134 /* ascii info for userland, via sysctl */ |
198 199#define TAG_DHCP_MSGTYPE 53 200#define TAG_DHCP_REQ_ADDR 50 201#define TAG_DHCP_SERVERID 54 202#define TAG_DHCP_LEASETIME 51 203 | 197 198#define TAG_DHCP_MSGTYPE 53 199#define TAG_DHCP_REQ_ADDR 50 200#define TAG_DHCP_SERVERID 54 201#define TAG_DHCP_LEASETIME 51 202 |
203#define TAG_VENDOR_INDENTIFIER 60 204 |
|
204#define DHCP_NOMSG 0 205#define DHCP_DISCOVER 1 206#define DHCP_OFFER 2 207#define DHCP_REQUEST 3 208#define DHCP_ACK 5 209 | 205#define DHCP_NOMSG 0 206#define DHCP_DISCOVER 1 207#define DHCP_OFFER 2 208#define DHCP_REQUEST 3 209#define DHCP_ACK 5 210 |
210extern int nfs_diskless_valid; 211extern struct nfsv3_diskless nfsv3_diskless; | 211/* NFS read/write block size */ 212#ifndef BOOTP_BLOCKSIZE 213#define BOOTP_BLOCKSIZE 8192 214#endif |
212 | 215 |
216static char bootp_cookie[128]; 217SYSCTL_STRING(_kern, OID_AUTO, bootp_cookie, CTLFLAG_RD, 218 bootp_cookie, 0, "Cookie (T134) supplied by bootp server"); 219 |
|
213/* mountd RPC */ | 220/* mountd RPC */ |
214static int md_mount(struct sockaddr_in *mdsin, char *path, 215 u_char *fhp, int *fhsizep, 216 struct nfs_args *args,struct thread *td); 217static int md_lookup_swap(struct sockaddr_in *mdsin,char *path, 218 u_char *fhp, int *fhsizep, 219 struct nfs_args *args, 220 struct thread *td); 221static int setfs(struct sockaddr_in *addr, char *path, char *p); 222static int getdec(char **ptr); 223static char *substr(char *a,char *b); 224static void mountopts(struct nfs_args *args, char *p); 225static int xdr_opaque_decode(struct mbuf **ptr, u_char *buf, int len); 226static int xdr_int_decode(struct mbuf **ptr, int *iptr); 227static void print_in_addr(struct in_addr addr); 228static void print_sin_addr(struct sockaddr_in *addr); 229static void clear_sinaddr(struct sockaddr_in *sin); 230static 231struct bootpc_ifcontext *allocifctx(struct bootpc_globalcontext *gctx); 232static void bootpc_compose_query(struct bootpc_ifcontext *ifctx, 233 struct bootpc_globalcontext *gctx, 234 struct thread *td); | 221static int md_mount(struct sockaddr_in *mdsin, char *path, u_char *fhp, 222 int *fhsizep, struct nfs_args *args, struct thread *td); 223static int setfs(struct sockaddr_in *addr, char *path, char *p, 224 const struct in_addr *siaddr); 225static int getdec(char **ptr); 226static int getip(char **ptr, struct in_addr *ip); 227static void mountopts(struct nfs_args *args, char *p); 228static int xdr_opaque_decode(struct mbuf **ptr, u_char *buf, int len); 229static int xdr_int_decode(struct mbuf **ptr, int *iptr); 230static void print_in_addr(struct in_addr addr); 231static void print_sin_addr(struct sockaddr_in *addr); 232static void clear_sinaddr(struct sockaddr_in *sin); 233static void allocifctx(struct bootpc_globalcontext *gctx); 234static void bootpc_compose_query(struct bootpc_ifcontext *ifctx, 235 struct bootpc_globalcontext *gctx, struct thread *td); |
235static unsigned char *bootpc_tag(struct bootpc_tagcontext *tctx, | 236static unsigned char *bootpc_tag(struct bootpc_tagcontext *tctx, |
236 struct bootp_packet *bp, int len, int tag); | 237 struct bootp_packet *bp, int len, int tag); |
237static void bootpc_tag_helper(struct bootpc_tagcontext *tctx, | 238static void bootpc_tag_helper(struct bootpc_tagcontext *tctx, |
238 unsigned char *start, int len, int tag); | 239 unsigned char *start, int len, int tag); |
239 240#ifdef BOOTP_DEBUG | 240 241#ifdef BOOTP_DEBUG |
241void bootpboot_p_sa(struct sockaddr *sa,struct sockaddr *ma); 242void bootpboot_p_ma(struct sockaddr *ma); | 242void bootpboot_p_sa(struct sockaddr *sa, struct sockaddr *ma); |
243void bootpboot_p_rtentry(struct rtentry *rt); 244void bootpboot_p_tree(struct radix_node *rn); 245void bootpboot_p_rtlist(void); 246void bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa); 247void bootpboot_p_iflist(void); 248#endif 249 | 243void bootpboot_p_rtentry(struct rtentry *rt); 244void bootpboot_p_tree(struct radix_node *rn); 245void bootpboot_p_rtlist(void); 246void bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa); 247void bootpboot_p_iflist(void); 248#endif 249 |
250static int bootpc_call(struct bootpc_globalcontext *gctx, 251 struct thread *td); | 250static int bootpc_call(struct bootpc_globalcontext *gctx, 251 struct thread *td); |
252 | 252 |
253static int bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx, 254 struct bootpc_globalcontext *gctx, 255 struct thread *td); | 253static int bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx, 254 struct bootpc_globalcontext *gctx, struct thread *td); |
256 | 255 |
257static int bootpc_adjust_interface(struct bootpc_ifcontext *ifctx, 258 struct bootpc_globalcontext *gctx, 259 struct thread *td); | 256static int bootpc_adjust_interface(struct bootpc_ifcontext *ifctx, 257 struct bootpc_globalcontext *gctx, struct thread *td); |
260 | 258 |
261static void bootpc_decode_reply(struct nfsv3_diskless *nd, 262 struct bootpc_ifcontext *ifctx, 263 struct bootpc_globalcontext *gctx); | 259static void bootpc_decode_reply(struct nfsv3_diskless *nd, 260 struct bootpc_ifcontext *ifctx, 261 struct bootpc_globalcontext *gctx); |
264 | 262 |
265static int bootpc_received(struct bootpc_globalcontext *gctx, 266 struct bootpc_ifcontext *ifctx); | 263static int bootpc_received(struct bootpc_globalcontext *gctx, 264 struct bootpc_ifcontext *ifctx); |
267 268static __inline int bootpc_ifctx_isresolved(struct bootpc_ifcontext *ifctx); 269static __inline int bootpc_ifctx_isunresolved(struct bootpc_ifcontext *ifctx); 270static __inline int bootpc_ifctx_isfailed(struct bootpc_ifcontext *ifctx); 271 | 265 266static __inline int bootpc_ifctx_isresolved(struct bootpc_ifcontext *ifctx); 267static __inline int bootpc_ifctx_isunresolved(struct bootpc_ifcontext *ifctx); 268static __inline int bootpc_ifctx_isfailed(struct bootpc_ifcontext *ifctx); 269 |
272void bootpc_init(void); 273 | |
274/* 275 * In order to have multiple active interfaces with address 0.0.0.0 276 * and be able to send data to a selected interface, we perform 277 * some tricks: | 270/* 271 * In order to have multiple active interfaces with address 0.0.0.0 272 * and be able to send data to a selected interface, we perform 273 * some tricks: |
278 * | 274 * |
279 * - The 'broadcast' address is different for each interface. 280 * 281 * - We temporarily add routing pointing 255.255.255.255 to the 282 * selected interface broadcast address, thus the packet sent 283 * goes to that interface. 284 */ 285 286#ifdef BOOTP_DEBUG 287void | 275 * - The 'broadcast' address is different for each interface. 276 * 277 * - We temporarily add routing pointing 255.255.255.255 to the 278 * selected interface broadcast address, thus the packet sent 279 * goes to that interface. 280 */ 281 282#ifdef BOOTP_DEBUG 283void |
288bootpboot_p_sa(struct sockaddr *sa, 289 struct sockaddr *ma) | 284bootpboot_p_sa(struct sockaddr *sa, struct sockaddr *ma) |
290{ | 285{ |
286 |
|
291 if (sa == NULL) { 292 printf("(sockaddr *) <null>"); 293 return; 294 } 295 switch (sa->sa_family) { 296 case AF_INET: 297 { 298 struct sockaddr_in *sin; | 287 if (sa == NULL) { 288 printf("(sockaddr *) <null>"); 289 return; 290 } 291 switch (sa->sa_family) { 292 case AF_INET: 293 { 294 struct sockaddr_in *sin; |
299 | 295 |
300 sin = (struct sockaddr_in *) sa; 301 printf("inet "); 302 print_sin_addr(sin); 303 if (ma != NULL) { 304 sin = (struct sockaddr_in *) ma; 305 printf(" mask "); 306 print_sin_addr(sin); 307 } 308 } 309 break; 310 case AF_LINK: 311 { 312 struct sockaddr_dl *sli; 313 int i; | 296 sin = (struct sockaddr_in *) sa; 297 printf("inet "); 298 print_sin_addr(sin); 299 if (ma != NULL) { 300 sin = (struct sockaddr_in *) ma; 301 printf(" mask "); 302 print_sin_addr(sin); 303 } 304 } 305 break; 306 case AF_LINK: 307 { 308 struct sockaddr_dl *sli; 309 int i; |
314 | 310 |
315 sli = (struct sockaddr_dl *) sa; 316 printf("link %.*s ", sli->sdl_nlen, sli->sdl_data); 317 for (i = 0; i < sli->sdl_alen; i++) { 318 if (i > 0) 319 printf(":"); 320 printf("%x", ((unsigned char *) LLADDR(sli))[i]); 321 } 322 } 323 break; 324 default: 325 printf("af%d", sa->sa_family); 326 } 327} 328 | 311 sli = (struct sockaddr_dl *) sa; 312 printf("link %.*s ", sli->sdl_nlen, sli->sdl_data); 313 for (i = 0; i < sli->sdl_alen; i++) { 314 if (i > 0) 315 printf(":"); 316 printf("%x", ((unsigned char *) LLADDR(sli))[i]); 317 } 318 } 319 break; 320 default: 321 printf("af%d", sa->sa_family); 322 } 323} 324 |
329 | |
330void | 325void |
331bootpboot_p_ma(struct sockaddr *ma) 332{ 333 if (ma == NULL) { 334 printf("<null>"); 335 return; 336 } 337 printf("%x", *(int *)ma); 338} 339 340 341void | |
342bootpboot_p_rtentry(struct rtentry *rt) 343{ | 326bootpboot_p_rtentry(struct rtentry *rt) 327{ |
328 |
|
344 bootpboot_p_sa(rt_key(rt), rt_mask(rt)); 345 printf(" "); | 329 bootpboot_p_sa(rt_key(rt), rt_mask(rt)); 330 printf(" "); |
346 bootpboot_p_ma(rt->rt_genmask); 347 printf(" "); | |
348 bootpboot_p_sa(rt->rt_gateway, NULL); 349 printf(" "); 350 printf("flags %x", (unsigned short) rt->rt_flags); 351 printf(" %d", (int) rt->rt_rmx.rmx_expire); | 331 bootpboot_p_sa(rt->rt_gateway, NULL); 332 printf(" "); 333 printf("flags %x", (unsigned short) rt->rt_flags); 334 printf(" %d", (int) rt->rt_rmx.rmx_expire); |
352 printf(" %s%d\n", rt->rt_ifp->if_name, rt->rt_ifp->if_unit); | 335 printf(" %s\n", rt->rt_ifp->if_xname); |
353} 354 | 336} 337 |
355 | |
356void 357bootpboot_p_tree(struct radix_node *rn) 358{ | 338void 339bootpboot_p_tree(struct radix_node *rn) 340{ |
341 |
|
359 while (rn != NULL) { 360 if (rn->rn_bit < 0) { 361 if ((rn->rn_flags & RNF_ROOT) != 0) { 362 } else { 363 bootpboot_p_rtentry((struct rtentry *) rn); 364 } 365 rn = rn->rn_dupedkey; 366 } else { 367 bootpboot_p_tree(rn->rn_left); 368 bootpboot_p_tree(rn->rn_right); 369 return; 370 } 371 } 372} 373 | 342 while (rn != NULL) { 343 if (rn->rn_bit < 0) { 344 if ((rn->rn_flags & RNF_ROOT) != 0) { 345 } else { 346 bootpboot_p_rtentry((struct rtentry *) rn); 347 } 348 rn = rn->rn_dupedkey; 349 } else { 350 bootpboot_p_tree(rn->rn_left); 351 bootpboot_p_tree(rn->rn_right); 352 return; 353 } 354 } 355} 356 |
374 | |
375void 376bootpboot_p_rtlist(void) 377{ | 357void 358bootpboot_p_rtlist(void) 359{ |
360 struct radix_node_head *rnh; 361 |
|
378 printf("Routing table:\n"); | 362 printf("Routing table:\n"); |
379 bootpboot_p_tree(rt_tables[AF_INET]->rnh_treetop); | 363 rnh = rt_tables_get_rnh(0, AF_INET); 364 if (rnh == NULL) 365 return; 366 RADIX_NODE_HEAD_RLOCK(rnh); /* could sleep XXX */ 367 bootpboot_p_tree(rnh->rnh_treetop); 368 RADIX_NODE_HEAD_RUNLOCK(rnh); |
380} 381 | 369} 370 |
382 | |
383void 384bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa) 385{ | 371void 372bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa) 373{ |
386 printf("%s%d flags %x, addr ", 387 ifp->if_name, 388 ifp->if_unit, 389 (unsigned short) ifp->if_flags); | 374 375 printf("%s flags %x, addr ", 376 ifp->if_xname, ifp->if_flags); |
390 print_sin_addr((struct sockaddr_in *) ifa->ifa_addr); 391 printf(", broadcast "); 392 print_sin_addr((struct sockaddr_in *) ifa->ifa_dstaddr); 393 printf(", netmask "); 394 print_sin_addr((struct sockaddr_in *) ifa->ifa_netmask); 395 printf("\n"); 396} 397 | 377 print_sin_addr((struct sockaddr_in *) ifa->ifa_addr); 378 printf(", broadcast "); 379 print_sin_addr((struct sockaddr_in *) ifa->ifa_dstaddr); 380 printf(", netmask "); 381 print_sin_addr((struct sockaddr_in *) ifa->ifa_netmask); 382 printf("\n"); 383} 384 |
398 | |
399void 400bootpboot_p_iflist(void) 401{ 402 struct ifnet *ifp; 403 struct ifaddr *ifa; | 385void 386bootpboot_p_iflist(void) 387{ 388 struct ifnet *ifp; 389 struct ifaddr *ifa; |
404 | 390 |
405 printf("Interface list:\n"); | 391 printf("Interface list:\n"); |
406 for (ifp = TAILQ_FIRST(&ifnet); | 392 IFNET_RLOCK(); 393 for (ifp = TAILQ_FIRST(&V_ifnet); |
407 ifp != NULL; 408 ifp = TAILQ_NEXT(ifp, if_link)) { 409 for (ifa = TAILQ_FIRST(&ifp->if_addrhead); 410 ifa != NULL; 411 ifa = TAILQ_NEXT(ifa, ifa_link)) 412 if (ifa->ifa_addr->sa_family == AF_INET) 413 bootpboot_p_if(ifp, ifa); 414 } | 394 ifp != NULL; 395 ifp = TAILQ_NEXT(ifp, if_link)) { 396 for (ifa = TAILQ_FIRST(&ifp->if_addrhead); 397 ifa != NULL; 398 ifa = TAILQ_NEXT(ifa, ifa_link)) 399 if (ifa->ifa_addr->sa_family == AF_INET) 400 bootpboot_p_if(ifp, ifa); 401 } |
402 IFNET_RUNLOCK(); |
|
415} 416#endif /* defined(BOOTP_DEBUG) */ 417 | 403} 404#endif /* defined(BOOTP_DEBUG) */ 405 |
418 | |
419static void 420clear_sinaddr(struct sockaddr_in *sin) 421{ | 406static void 407clear_sinaddr(struct sockaddr_in *sin) 408{ |
409 |
|
422 bzero(sin, sizeof(*sin)); 423 sin->sin_len = sizeof(*sin); 424 sin->sin_family = AF_INET; 425 sin->sin_addr.s_addr = INADDR_ANY; /* XXX: htonl(INAADDR_ANY) ? */ 426 sin->sin_port = 0; 427} 428 | 410 bzero(sin, sizeof(*sin)); 411 sin->sin_len = sizeof(*sin); 412 sin->sin_family = AF_INET; 413 sin->sin_addr.s_addr = INADDR_ANY; /* XXX: htonl(INAADDR_ANY) ? */ 414 sin->sin_port = 0; 415} 416 |
429 430static struct bootpc_ifcontext * | 417static void |
431allocifctx(struct bootpc_globalcontext *gctx) 432{ 433 struct bootpc_ifcontext *ifctx; 434 ifctx = (struct bootpc_ifcontext *) malloc(sizeof(*ifctx), | 418allocifctx(struct bootpc_globalcontext *gctx) 419{ 420 struct bootpc_ifcontext *ifctx; 421 ifctx = (struct bootpc_ifcontext *) malloc(sizeof(*ifctx), |
435 M_TEMP, M_WAITOK); | 422 M_TEMP, M_WAITOK | M_ZERO); |
436 if (ifctx == NULL) 437 panic("Failed to allocate bootp interface context structure"); | 423 if (ifctx == NULL) 424 panic("Failed to allocate bootp interface context structure"); |
438 439 bzero(ifctx, sizeof(*ifctx)); | 425 |
440 ifctx->xid = gctx->xid; 441#ifdef BOOTP_NO_DHCP 442 ifctx->state = IF_BOOTP_UNRESOLVED; 443#else 444 ifctx->state = IF_DHCP_UNRESOLVED; 445#endif 446 gctx->xid += 0x100; | 426 ifctx->xid = gctx->xid; 427#ifdef BOOTP_NO_DHCP 428 ifctx->state = IF_BOOTP_UNRESOLVED; 429#else 430 ifctx->state = IF_DHCP_UNRESOLVED; 431#endif 432 gctx->xid += 0x100; |
447 return ifctx; | 433 if (gctx->interfaces != NULL) 434 gctx->lastinterface->next = ifctx; 435 else 436 gctx->interfaces = ifctx; 437 gctx->lastinterface = ifctx; |
448} 449 | 438} 439 |
450 | |
451static __inline int 452bootpc_ifctx_isresolved(struct bootpc_ifcontext *ifctx) 453{ | 440static __inline int 441bootpc_ifctx_isresolved(struct bootpc_ifcontext *ifctx) 442{ |
443 |
|
454 if (ifctx->state == IF_BOOTP_RESOLVED || 455 ifctx->state == IF_DHCP_RESOLVED) 456 return 1; 457 return 0; 458} 459 | 444 if (ifctx->state == IF_BOOTP_RESOLVED || 445 ifctx->state == IF_DHCP_RESOLVED) 446 return 1; 447 return 0; 448} 449 |
460 | |
461static __inline int 462bootpc_ifctx_isunresolved(struct bootpc_ifcontext *ifctx) 463{ | 450static __inline int 451bootpc_ifctx_isunresolved(struct bootpc_ifcontext *ifctx) 452{ |
453 |
|
464 if (ifctx->state == IF_BOOTP_UNRESOLVED || 465 ifctx->state == IF_DHCP_UNRESOLVED) 466 return 1; 467 return 0; 468} 469 | 454 if (ifctx->state == IF_BOOTP_UNRESOLVED || 455 ifctx->state == IF_DHCP_UNRESOLVED) 456 return 1; 457 return 0; 458} 459 |
470 | |
471static __inline int 472bootpc_ifctx_isfailed(struct bootpc_ifcontext *ifctx) 473{ | 460static __inline int 461bootpc_ifctx_isfailed(struct bootpc_ifcontext *ifctx) 462{ |
463 |
|
474 if (ifctx->state == IF_BOOTP_FAILED || 475 ifctx->state == IF_DHCP_FAILED) 476 return 1; 477 return 0; 478} 479 | 464 if (ifctx->state == IF_BOOTP_FAILED || 465 ifctx->state == IF_DHCP_FAILED) 466 return 1; 467 return 0; 468} 469 |
480 | |
481static int 482bootpc_received(struct bootpc_globalcontext *gctx, | 470static int 471bootpc_received(struct bootpc_globalcontext *gctx, |
483 struct bootpc_ifcontext *ifctx) | 472 struct bootpc_ifcontext *ifctx) |
484{ 485 unsigned char dhcpreplytype; 486 char *p; | 473{ 474 unsigned char dhcpreplytype; 475 char *p; |
476 |
|
487 /* 488 * Need timeout for fallback to less 489 * desirable alternative. 490 */ 491 | 477 /* 478 * Need timeout for fallback to less 479 * desirable alternative. 480 */ 481 |
492 | |
493 /* This call used for the side effect (badopt flag) */ 494 (void) bootpc_tag(&gctx->tmptag, &gctx->reply, 495 gctx->replylen, 496 TAG_END); 497 498 /* If packet is invalid, ignore it */ 499 if (gctx->tmptag.badopt != 0) 500 return 0; | 482 /* This call used for the side effect (badopt flag) */ 483 (void) bootpc_tag(&gctx->tmptag, &gctx->reply, 484 gctx->replylen, 485 TAG_END); 486 487 /* If packet is invalid, ignore it */ 488 if (gctx->tmptag.badopt != 0) 489 return 0; |
501 | 490 |
502 p = bootpc_tag(&gctx->tmptag, &gctx->reply, 503 gctx->replylen, TAG_DHCP_MSGTYPE); 504 if (p != NULL) 505 dhcpreplytype = *p; 506 else 507 dhcpreplytype = DHCP_NOMSG; | 491 p = bootpc_tag(&gctx->tmptag, &gctx->reply, 492 gctx->replylen, TAG_DHCP_MSGTYPE); 493 if (p != NULL) 494 dhcpreplytype = *p; 495 else 496 dhcpreplytype = DHCP_NOMSG; |
508 | 497 |
509 switch (ifctx->dhcpquerytype) { 510 case DHCP_DISCOVER: 511 if (dhcpreplytype != DHCP_OFFER /* Normal DHCP offer */ 512#ifndef BOOTP_FORCE_DHCP 513 && dhcpreplytype != DHCP_NOMSG /* Fallback to BOOTP */ 514#endif 515 ) 516 return 0; 517 break; 518 case DHCP_REQUEST: 519 if (dhcpreplytype != DHCP_ACK) 520 return 0; 521 case DHCP_NOMSG: | 498 switch (ifctx->dhcpquerytype) { 499 case DHCP_DISCOVER: 500 if (dhcpreplytype != DHCP_OFFER /* Normal DHCP offer */ 501#ifndef BOOTP_FORCE_DHCP 502 && dhcpreplytype != DHCP_NOMSG /* Fallback to BOOTP */ 503#endif 504 ) 505 return 0; 506 break; 507 case DHCP_REQUEST: 508 if (dhcpreplytype != DHCP_ACK) 509 return 0; 510 case DHCP_NOMSG: |
511 break; |
|
522 } | 512 } |
523 524 | 513 |
525 /* Ignore packet unless it gives us a root tag we didn't have */ | 514 /* Ignore packet unless it gives us a root tag we didn't have */ |
526 | 515 |
527 if ((ifctx->state == IF_BOOTP_RESOLVED || 528 (ifctx->dhcpquerytype == DHCP_DISCOVER && 529 (ifctx->state == IF_DHCP_OFFERED || 530 ifctx->state == IF_DHCP_RESOLVED))) && 531 (bootpc_tag(&gctx->tmptag, &ifctx->reply, 532 ifctx->replylen, 533 TAG_ROOT) != NULL || 534 bootpc_tag(&gctx->tmptag, &gctx->reply, 535 gctx->replylen, 536 TAG_ROOT) == NULL)) 537 return 0; | 516 if ((ifctx->state == IF_BOOTP_RESOLVED || 517 (ifctx->dhcpquerytype == DHCP_DISCOVER && 518 (ifctx->state == IF_DHCP_OFFERED || 519 ifctx->state == IF_DHCP_RESOLVED))) && 520 (bootpc_tag(&gctx->tmptag, &ifctx->reply, 521 ifctx->replylen, 522 TAG_ROOT) != NULL || 523 bootpc_tag(&gctx->tmptag, &gctx->reply, 524 gctx->replylen, 525 TAG_ROOT) == NULL)) 526 return 0; |
538 539 bcopy(&gctx->reply, 540 &ifctx->reply, 541 gctx->replylen); | 527 528 bcopy(&gctx->reply, &ifctx->reply, gctx->replylen); |
542 ifctx->replylen = gctx->replylen; | 529 ifctx->replylen = gctx->replylen; |
543 | 530 |
544 /* XXX: Only reset if 'perfect' response */ 545 if (ifctx->state == IF_BOOTP_UNRESOLVED) 546 ifctx->state = IF_BOOTP_RESOLVED; 547 else if (ifctx->state == IF_DHCP_UNRESOLVED && 548 ifctx->dhcpquerytype == DHCP_DISCOVER) { 549 if (dhcpreplytype == DHCP_OFFER) 550 ifctx->state = IF_DHCP_OFFERED; 551 else 552 ifctx->state = IF_BOOTP_RESOLVED; /* Fallback */ 553 } else if (ifctx->state == IF_DHCP_OFFERED && 554 ifctx->dhcpquerytype == DHCP_REQUEST) 555 ifctx->state = IF_DHCP_RESOLVED; | 531 /* XXX: Only reset if 'perfect' response */ 532 if (ifctx->state == IF_BOOTP_UNRESOLVED) 533 ifctx->state = IF_BOOTP_RESOLVED; 534 else if (ifctx->state == IF_DHCP_UNRESOLVED && 535 ifctx->dhcpquerytype == DHCP_DISCOVER) { 536 if (dhcpreplytype == DHCP_OFFER) 537 ifctx->state = IF_DHCP_OFFERED; 538 else 539 ifctx->state = IF_BOOTP_RESOLVED; /* Fallback */ 540 } else if (ifctx->state == IF_DHCP_OFFERED && 541 ifctx->dhcpquerytype == DHCP_REQUEST) 542 ifctx->state = IF_DHCP_RESOLVED; |
556 557 | 543 544 |
558 if (ifctx->dhcpquerytype == DHCP_DISCOVER && 559 ifctx->state != IF_BOOTP_RESOLVED) { 560 p = bootpc_tag(&gctx->tmptag, &ifctx->reply, 561 ifctx->replylen, TAG_DHCP_SERVERID); 562 if (p != NULL && gctx->tmptag.taglen == 4) { 563 memcpy(&ifctx->dhcpserver, p, 4); 564 ifctx->gotdhcpserver = 1; 565 } else 566 ifctx->gotdhcpserver = 0; 567 return 1; 568 } | 545 if (ifctx->dhcpquerytype == DHCP_DISCOVER && 546 ifctx->state != IF_BOOTP_RESOLVED) { 547 p = bootpc_tag(&gctx->tmptag, &ifctx->reply, 548 ifctx->replylen, TAG_DHCP_SERVERID); 549 if (p != NULL && gctx->tmptag.taglen == 4) { 550 memcpy(&ifctx->dhcpserver, p, 4); 551 ifctx->gotdhcpserver = 1; 552 } else 553 ifctx->gotdhcpserver = 0; 554 return 1; 555 } |
569 | 556 |
570 ifctx->gotrootpath = (bootpc_tag(&gctx->tmptag, &ifctx->reply, 571 ifctx->replylen, 572 TAG_ROOT) != NULL); 573 ifctx->gotgw = (bootpc_tag(&gctx->tmptag, &ifctx->reply, 574 ifctx->replylen, 575 TAG_ROUTERS) != NULL); 576 ifctx->gotnetmask = (bootpc_tag(&gctx->tmptag, &ifctx->reply, 577 ifctx->replylen, 578 TAG_SUBNETMASK) != NULL); 579 return 1; 580} 581 582static int | 557 ifctx->gotrootpath = (bootpc_tag(&gctx->tmptag, &ifctx->reply, 558 ifctx->replylen, 559 TAG_ROOT) != NULL); 560 ifctx->gotgw = (bootpc_tag(&gctx->tmptag, &ifctx->reply, 561 ifctx->replylen, 562 TAG_ROUTERS) != NULL); 563 ifctx->gotnetmask = (bootpc_tag(&gctx->tmptag, &ifctx->reply, 564 ifctx->replylen, 565 TAG_SUBNETMASK) != NULL); 566 return 1; 567} 568 569static int |
583bootpc_call(struct bootpc_globalcontext *gctx, 584 struct thread *td) | 570bootpc_call(struct bootpc_globalcontext *gctx, struct thread *td) |
585{ 586 struct socket *so; 587 struct sockaddr_in *sin, dst; 588 struct uio auio; 589 struct sockopt sopt; 590 struct iovec aio; 591 int error, on, rcvflg, timo, len; 592 time_t atimo; 593 time_t rtimo; 594 struct timeval tv; 595 struct bootpc_ifcontext *ifctx; 596 int outstanding; 597 int gotrootpath; 598 int retry; 599 const char *s; | 571{ 572 struct socket *so; 573 struct sockaddr_in *sin, dst; 574 struct uio auio; 575 struct sockopt sopt; 576 struct iovec aio; 577 int error, on, rcvflg, timo, len; 578 time_t atimo; 579 time_t rtimo; 580 struct timeval tv; 581 struct bootpc_ifcontext *ifctx; 582 int outstanding; 583 int gotrootpath; 584 int retry; 585 const char *s; |
600 | 586 |
601 /* 602 * Create socket and set its recieve timeout. 603 */ | 587 /* 588 * Create socket and set its recieve timeout. 589 */ |
604 error = socreate(AF_INET, &so, SOCK_DGRAM, 0, td); | 590 error = socreate(AF_INET, &so, SOCK_DGRAM, 0, td->td_ucred, td); |
605 if (error != 0) | 591 if (error != 0) |
606 goto out; 607 | 592 goto out0; 593 |
608 tv.tv_sec = 1; 609 tv.tv_usec = 0; 610 bzero(&sopt, sizeof(sopt)); | 594 tv.tv_sec = 1; 595 tv.tv_usec = 0; 596 bzero(&sopt, sizeof(sopt)); |
597 sopt.sopt_dir = SOPT_SET; |
|
611 sopt.sopt_level = SOL_SOCKET; 612 sopt.sopt_name = SO_RCVTIMEO; 613 sopt.sopt_val = &tv; 614 sopt.sopt_valsize = sizeof tv; | 598 sopt.sopt_level = SOL_SOCKET; 599 sopt.sopt_name = SO_RCVTIMEO; 600 sopt.sopt_val = &tv; 601 sopt.sopt_valsize = sizeof tv; |
615 | 602 |
616 error = sosetopt(so, &sopt); 617 if (error != 0) 618 goto out; | 603 error = sosetopt(so, &sopt); 604 if (error != 0) 605 goto out; |
619 | 606 |
620 /* 621 * Enable broadcast. 622 */ 623 on = 1; 624 sopt.sopt_name = SO_BROADCAST; 625 sopt.sopt_val = &on; 626 sopt.sopt_valsize = sizeof on; 627 --- 8 unchanged lines hidden (view full) --- 636 on = 1; 637 sopt.sopt_name = SO_DONTROUTE; 638 sopt.sopt_val = &on; 639 sopt.sopt_valsize = sizeof on; 640 641 error = sosetopt(so, &sopt); 642 if (error != 0) 643 goto out; | 607 /* 608 * Enable broadcast. 609 */ 610 on = 1; 611 sopt.sopt_name = SO_BROADCAST; 612 sopt.sopt_val = &on; 613 sopt.sopt_valsize = sizeof on; 614 --- 8 unchanged lines hidden (view full) --- 623 on = 1; 624 sopt.sopt_name = SO_DONTROUTE; 625 sopt.sopt_val = &on; 626 sopt.sopt_valsize = sizeof on; 627 628 error = sosetopt(so, &sopt); 629 if (error != 0) 630 goto out; |
644 | 631 |
645 /* 646 * Bind the local endpoint to a bootp client port. 647 */ 648 sin = &dst; 649 clear_sinaddr(sin); 650 sin->sin_port = htons(IPPORT_BOOTPC); 651 error = sobind(so, (struct sockaddr *)sin, td); 652 if (error != 0) { 653 printf("bind failed\n"); 654 goto out; 655 } | 632 /* 633 * Bind the local endpoint to a bootp client port. 634 */ 635 sin = &dst; 636 clear_sinaddr(sin); 637 sin->sin_port = htons(IPPORT_BOOTPC); 638 error = sobind(so, (struct sockaddr *)sin, td); 639 if (error != 0) { 640 printf("bind failed\n"); 641 goto out; 642 } |
656 | 643 |
657 /* 658 * Setup socket address for the server. 659 */ 660 sin = &dst; 661 clear_sinaddr(sin); 662 sin->sin_addr.s_addr = INADDR_BROADCAST; 663 sin->sin_port = htons(IPPORT_BOOTPS); | 644 /* 645 * Setup socket address for the server. 646 */ 647 sin = &dst; 648 clear_sinaddr(sin); 649 sin->sin_addr.s_addr = INADDR_BROADCAST; 650 sin->sin_port = htons(IPPORT_BOOTPS); |
664 | 651 |
665 /* 666 * Send it, repeatedly, until a reply is received, 667 * but delay each re-send by an increasing amount. 668 * If the delay hits the maximum, start complaining. 669 */ 670 timo = 0; 671 rtimo = 0; 672 for (;;) { | 652 /* 653 * Send it, repeatedly, until a reply is received, 654 * but delay each re-send by an increasing amount. 655 * If the delay hits the maximum, start complaining. 656 */ 657 timo = 0; 658 rtimo = 0; 659 for (;;) { |
673 | 660 |
674 outstanding = 0; 675 gotrootpath = 0; 676 677 for (ifctx = gctx->interfaces; 678 ifctx != NULL; 679 ifctx = ifctx->next) { 680 if (bootpc_ifctx_isresolved(ifctx) != 0 && 681 bootpc_tag(&gctx->tmptag, &ifctx->reply, 682 ifctx->replylen, 683 TAG_ROOT) != NULL) 684 gotrootpath = 1; 685 } | 661 outstanding = 0; 662 gotrootpath = 0; 663 664 for (ifctx = gctx->interfaces; 665 ifctx != NULL; 666 ifctx = ifctx->next) { 667 if (bootpc_ifctx_isresolved(ifctx) != 0 && 668 bootpc_tag(&gctx->tmptag, &ifctx->reply, 669 ifctx->replylen, 670 TAG_ROOT) != NULL) 671 gotrootpath = 1; 672 } |
686 | 673 |
687 for (ifctx = gctx->interfaces; 688 ifctx != NULL; 689 ifctx = ifctx->next) { 690 ifctx->outstanding = 0; 691 if (bootpc_ifctx_isresolved(ifctx) != 0 && 692 gotrootpath != 0) { 693 continue; 694 } --- 8 unchanged lines hidden (view full) --- 703 ifctx->dhcpquerytype != DHCP_REQUEST) || 704 (ifctx->state == IF_DHCP_UNRESOLVED && 705 ifctx->dhcpquerytype != DHCP_DISCOVER) || 706 (ifctx->state == IF_BOOTP_UNRESOLVED && 707 ifctx->dhcpquerytype != DHCP_NOMSG)) { 708 ifctx->sentmsg = 0; 709 bootpc_compose_query(ifctx, gctx, td); 710 } | 674 for (ifctx = gctx->interfaces; 675 ifctx != NULL; 676 ifctx = ifctx->next) { 677 ifctx->outstanding = 0; 678 if (bootpc_ifctx_isresolved(ifctx) != 0 && 679 gotrootpath != 0) { 680 continue; 681 } --- 8 unchanged lines hidden (view full) --- 690 ifctx->dhcpquerytype != DHCP_REQUEST) || 691 (ifctx->state == IF_DHCP_UNRESOLVED && 692 ifctx->dhcpquerytype != DHCP_DISCOVER) || 693 (ifctx->state == IF_BOOTP_UNRESOLVED && 694 ifctx->dhcpquerytype != DHCP_NOMSG)) { 695 ifctx->sentmsg = 0; 696 bootpc_compose_query(ifctx, gctx, td); 697 } |
711 | 698 |
712 /* Send BOOTP request (or re-send). */ | 699 /* Send BOOTP request (or re-send). */ |
713 | 700 |
714 if (ifctx->sentmsg == 0) { 715 switch(ifctx->dhcpquerytype) { 716 case DHCP_DISCOVER: 717 s = "DHCP Discover"; 718 break; 719 case DHCP_REQUEST: 720 s = "DHCP Request"; 721 break; --- 9 unchanged lines hidden (view full) --- 731 ifctx->sdl->sdl_alen, 732 (unsigned char *) LLADDR(ifctx->sdl), 733 ":"); 734 ifctx->sentmsg = 1; 735 } 736 737 aio.iov_base = (caddr_t) &ifctx->call; 738 aio.iov_len = sizeof(ifctx->call); | 701 if (ifctx->sentmsg == 0) { 702 switch(ifctx->dhcpquerytype) { 703 case DHCP_DISCOVER: 704 s = "DHCP Discover"; 705 break; 706 case DHCP_REQUEST: 707 s = "DHCP Request"; 708 break; --- 9 unchanged lines hidden (view full) --- 718 ifctx->sdl->sdl_alen, 719 (unsigned char *) LLADDR(ifctx->sdl), 720 ":"); 721 ifctx->sentmsg = 1; 722 } 723 724 aio.iov_base = (caddr_t) &ifctx->call; 725 aio.iov_len = sizeof(ifctx->call); |
739 | 726 |
740 auio.uio_iov = &aio; 741 auio.uio_iovcnt = 1; 742 auio.uio_segflg = UIO_SYSSPACE; 743 auio.uio_rw = UIO_WRITE; 744 auio.uio_offset = 0; 745 auio.uio_resid = sizeof(ifctx->call); 746 auio.uio_td = td; | 727 auio.uio_iov = &aio; 728 auio.uio_iovcnt = 1; 729 auio.uio_segflg = UIO_SYSSPACE; 730 auio.uio_rw = UIO_WRITE; 731 auio.uio_offset = 0; 732 auio.uio_resid = sizeof(ifctx->call); 733 auio.uio_td = td; |
747 | 734 |
748 /* Set netmask to 0.0.0.0 */ | 735 /* Set netmask to 0.0.0.0 */ |
749 | 736 |
750 sin = (struct sockaddr_in *) &ifctx->ireq.ifr_addr; 751 clear_sinaddr(sin); 752 error = ifioctl(ifctx->so, SIOCSIFNETMASK, 753 (caddr_t) &ifctx->ireq, td); 754 if (error != 0) 755 panic("bootpc_call:" 756 "set if netmask, error=%d", 757 error); | 737 sin = (struct sockaddr_in *) &ifctx->ireq.ifr_addr; 738 clear_sinaddr(sin); 739 error = ifioctl(ifctx->so, SIOCSIFNETMASK, 740 (caddr_t) &ifctx->ireq, td); 741 if (error != 0) 742 panic("bootpc_call:" 743 "set if netmask, error=%d", 744 error); |
758 | 745 |
759 error = sosend(so, (struct sockaddr *) &dst, 760 &auio, NULL, NULL, 0, td); 761 if (error != 0) { 762 printf("bootpc_call: sosend: %d state %08x\n", 763 error, (int) so->so_state); 764 } 765 766 /* XXX: Is this needed ? */ | 746 error = sosend(so, (struct sockaddr *) &dst, 747 &auio, NULL, NULL, 0, td); 748 if (error != 0) { 749 printf("bootpc_call: sosend: %d state %08x\n", 750 error, (int) so->so_state); 751 } 752 753 /* XXX: Is this needed ? */ |
767 tsleep(&error, PZERO + 8, "bootpw", 10); 768 | 754 pause("bootpw", hz/10); 755 |
769 /* Set netmask to 255.0.0.0 */ | 756 /* Set netmask to 255.0.0.0 */ |
770 | 757 |
771 sin = (struct sockaddr_in *) &ifctx->ireq.ifr_addr; 772 clear_sinaddr(sin); 773 sin->sin_addr.s_addr = htonl(0xff000000u); 774 error = ifioctl(ifctx->so, SIOCSIFNETMASK, 775 (caddr_t) &ifctx->ireq, td); 776 if (error != 0) 777 panic("bootpc_call:" 778 "set if netmask, error=%d", 779 error); | 758 sin = (struct sockaddr_in *) &ifctx->ireq.ifr_addr; 759 clear_sinaddr(sin); 760 sin->sin_addr.s_addr = htonl(0xff000000u); 761 error = ifioctl(ifctx->so, SIOCSIFNETMASK, 762 (caddr_t) &ifctx->ireq, td); 763 if (error != 0) 764 panic("bootpc_call:" 765 "set if netmask, error=%d", 766 error); |
780 | 767 |
781 } | 768 } |
782 | 769 |
783 if (outstanding == 0 && 784 (rtimo == 0 || time_second >= rtimo)) { 785 error = 0; 786 goto gotreply; 787 } | 770 if (outstanding == 0 && 771 (rtimo == 0 || time_second >= rtimo)) { 772 error = 0; 773 goto gotreply; 774 } |
788 | 775 |
789 /* Determine new timeout. */ 790 if (timo < MAX_RESEND_DELAY) 791 timo++; 792 else { 793 printf("DHCP/BOOTP timeout for server "); 794 print_sin_addr(&dst); 795 printf("\n"); 796 } | 776 /* Determine new timeout. */ 777 if (timo < MAX_RESEND_DELAY) 778 timo++; 779 else { 780 printf("DHCP/BOOTP timeout for server "); 781 print_sin_addr(&dst); 782 printf("\n"); 783 } |
797 | 784 |
798 /* 799 * Wait for up to timo seconds for a reply. 800 * The socket receive timeout was set to 1 second. 801 */ 802 atimo = timo + time_second; 803 while (time_second < atimo) { 804 aio.iov_base = (caddr_t) &gctx->reply; 805 aio.iov_len = sizeof(gctx->reply); | 785 /* 786 * Wait for up to timo seconds for a reply. 787 * The socket receive timeout was set to 1 second. 788 */ 789 atimo = timo + time_second; 790 while (time_second < atimo) { 791 aio.iov_base = (caddr_t) &gctx->reply; 792 aio.iov_len = sizeof(gctx->reply); |
806 | 793 |
807 auio.uio_iov = &aio; 808 auio.uio_iovcnt = 1; 809 auio.uio_segflg = UIO_SYSSPACE; 810 auio.uio_rw = UIO_READ; 811 auio.uio_offset = 0; 812 auio.uio_resid = sizeof(gctx->reply); 813 auio.uio_td = td; | 794 auio.uio_iov = &aio; 795 auio.uio_iovcnt = 1; 796 auio.uio_segflg = UIO_SYSSPACE; 797 auio.uio_rw = UIO_READ; 798 auio.uio_offset = 0; 799 auio.uio_resid = sizeof(gctx->reply); 800 auio.uio_td = td; |
814 | 801 |
815 rcvflg = 0; 816 error = soreceive(so, NULL, &auio, 817 NULL, NULL, &rcvflg); 818 gctx->secs = time_second - gctx->starttime; 819 for (ifctx = gctx->interfaces; 820 ifctx != NULL; 821 ifctx = ifctx->next) { 822 if (bootpc_ifctx_isresolved(ifctx) != 0 || 823 bootpc_ifctx_isfailed(ifctx) != 0) 824 continue; | 802 rcvflg = 0; 803 error = soreceive(so, NULL, &auio, 804 NULL, NULL, &rcvflg); 805 gctx->secs = time_second - gctx->starttime; 806 for (ifctx = gctx->interfaces; 807 ifctx != NULL; 808 ifctx = ifctx->next) { 809 if (bootpc_ifctx_isresolved(ifctx) != 0 || 810 bootpc_ifctx_isfailed(ifctx) != 0) 811 continue; |
825 | 812 |
826 ifctx->call.secs = htons(gctx->secs); 827 } 828 if (error == EWOULDBLOCK) 829 continue; 830 if (error != 0) 831 goto out; 832 len = sizeof(gctx->reply) - auio.uio_resid; | 813 ifctx->call.secs = htons(gctx->secs); 814 } 815 if (error == EWOULDBLOCK) 816 continue; 817 if (error != 0) 818 goto out; 819 len = sizeof(gctx->reply) - auio.uio_resid; |
833 | 820 |
834 /* Do we have the required number of bytes ? */ 835 if (len < BOOTP_MIN_LEN) 836 continue; 837 gctx->replylen = len; | 821 /* Do we have the required number of bytes ? */ 822 if (len < BOOTP_MIN_LEN) 823 continue; 824 gctx->replylen = len; |
838 | 825 |
839 /* Is it a reply? */ 840 if (gctx->reply.op != BOOTP_REPLY) 841 continue; | 826 /* Is it a reply? */ 827 if (gctx->reply.op != BOOTP_REPLY) 828 continue; |
842 | 829 |
843 /* Is this an answer to our query */ 844 for (ifctx = gctx->interfaces; 845 ifctx != NULL; 846 ifctx = ifctx->next) { 847 if (gctx->reply.xid != ifctx->call.xid) 848 continue; | 830 /* Is this an answer to our query */ 831 for (ifctx = gctx->interfaces; 832 ifctx != NULL; 833 ifctx = ifctx->next) { 834 if (gctx->reply.xid != ifctx->call.xid) 835 continue; |
849 | 836 |
850 /* Same HW address size ? */ 851 if (gctx->reply.hlen != ifctx->call.hlen) 852 continue; | 837 /* Same HW address size ? */ 838 if (gctx->reply.hlen != ifctx->call.hlen) 839 continue; |
853 | 840 |
854 /* Correct HW address ? */ 855 if (bcmp(gctx->reply.chaddr, 856 ifctx->call.chaddr, 857 ifctx->call.hlen) != 0) 858 continue; 859 860 break; 861 } --- 60 unchanged lines hidden (view full) --- 922 ifctx = ifctx->next) { 923 if (ifctx->state == IF_DHCP_OFFERED) { 924 if (ifctx->dhcpquerytype == DHCP_DISCOVER) 925 retry = 1; 926 else 927 ifctx->state = IF_DHCP_UNRESOLVED; 928 } 929 } | 841 /* Correct HW address ? */ 842 if (bcmp(gctx->reply.chaddr, 843 ifctx->call.chaddr, 844 ifctx->call.hlen) != 0) 845 continue; 846 847 break; 848 } --- 60 unchanged lines hidden (view full) --- 909 ifctx = ifctx->next) { 910 if (ifctx->state == IF_DHCP_OFFERED) { 911 if (ifctx->dhcpquerytype == DHCP_DISCOVER) 912 retry = 1; 913 else 914 ifctx->state = IF_DHCP_UNRESOLVED; 915 } 916 } |
930 | 917 |
931 if (retry != 0) 932 continue; | 918 if (retry != 0) 919 continue; |
933 | 920 |
934 if (gotrootpath != 0) { 935 gctx->gotrootpath = gotrootpath; 936 if (rtimo != 0 && time_second >= rtimo) 937 break; 938 } 939 } /* forever send/receive */ | 921 if (gotrootpath != 0) { 922 gctx->gotrootpath = gotrootpath; 923 if (rtimo != 0 && time_second >= rtimo) 924 break; 925 } 926 } /* forever send/receive */ |
940 941 /* | 927 928 /* |
942 * XXX: These are errors of varying seriousness being silently 943 * ignored 944 */ 945 946 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) { 947 if (bootpc_ifctx_isresolved(ifctx) == 0) { 948 printf("%s timeout for interface %s\n", 949 ifctx->dhcpquerytype != DHCP_NOMSG ? --- 13 unchanged lines hidden (view full) --- 963 if (bootpc_ifctx_isresolved(ifctx) != 0) { 964 error = 0; 965 goto out; 966 } 967 } 968#endif 969 error = ETIMEDOUT; 970 goto out; | 929 * XXX: These are errors of varying seriousness being silently 930 * ignored 931 */ 932 933 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) { 934 if (bootpc_ifctx_isresolved(ifctx) == 0) { 935 printf("%s timeout for interface %s\n", 936 ifctx->dhcpquerytype != DHCP_NOMSG ? --- 13 unchanged lines hidden (view full) --- 950 if (bootpc_ifctx_isresolved(ifctx) != 0) { 951 error = 0; 952 goto out; 953 } 954 } 955#endif 956 error = ETIMEDOUT; 957 goto out; |
971 | 958 |
972gotreply: 973out: 974 soclose(so); | 959gotreply: 960out: 961 soclose(so); |
962out0: |
|
975 return error; 976} 977 | 963 return error; 964} 965 |
978 | |
979static int 980bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx, | 966static int 967bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx, |
981 struct bootpc_globalcontext *gctx, 982 struct thread *td) | 968 struct bootpc_globalcontext *gctx, struct thread *td) |
983{ 984 struct sockaddr_in *sin; 985 int error; | 969{ 970 struct sockaddr_in *sin; 971 int error; |
986 | |
987 struct ifreq *ireq; 988 struct socket *so; 989 struct ifaddr *ifa; 990 struct sockaddr_dl *sdl; 991 | 972 struct ifreq *ireq; 973 struct socket *so; 974 struct ifaddr *ifa; 975 struct sockaddr_dl *sdl; 976 |
992 error = socreate(AF_INET, &ifctx->so, SOCK_DGRAM, 0, td); | 977 error = socreate(AF_INET, &ifctx->so, SOCK_DGRAM, 0, td->td_ucred, td); |
993 if (error != 0) 994 panic("nfs_boot: socreate, error=%d", error); | 978 if (error != 0) 979 panic("nfs_boot: socreate, error=%d", error); |
995 | 980 |
996 ireq = &ifctx->ireq; 997 so = ifctx->so; 998 999 /* 1000 * Bring up the interface. 1001 * 1002 * Get the old interface flags and or IFF_UP into them; if 1003 * IFF_UP set blindly, interface selection can be clobbered. 1004 */ 1005 error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, td); 1006 if (error != 0) 1007 panic("bootpc_fakeup_interface: GIFFLAGS, error=%d", error); 1008 ireq->ifr_flags |= IFF_UP; 1009 error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, td); 1010 if (error != 0) 1011 panic("bootpc_fakeup_interface: SIFFLAGS, error=%d", error); | 981 ireq = &ifctx->ireq; 982 so = ifctx->so; 983 984 /* 985 * Bring up the interface. 986 * 987 * Get the old interface flags and or IFF_UP into them; if 988 * IFF_UP set blindly, interface selection can be clobbered. 989 */ 990 error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, td); 991 if (error != 0) 992 panic("bootpc_fakeup_interface: GIFFLAGS, error=%d", error); 993 ireq->ifr_flags |= IFF_UP; 994 error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, td); 995 if (error != 0) 996 panic("bootpc_fakeup_interface: SIFFLAGS, error=%d", error); |
1012 | 997 |
1013 /* 1014 * Do enough of ifconfig(8) so that the chosen interface 1015 * can talk to the servers. (just set the address) 1016 */ | 998 /* 999 * Do enough of ifconfig(8) so that the chosen interface 1000 * can talk to the servers. (just set the address) 1001 */ |
1017 | 1002 |
1018 /* addr is 0.0.0.0 */ | 1003 /* addr is 0.0.0.0 */ |
1019 | 1004 |
1020 sin = (struct sockaddr_in *) &ireq->ifr_addr; 1021 clear_sinaddr(sin); 1022 error = ifioctl(so, SIOCSIFADDR, (caddr_t) ireq, td); 1023 if (error != 0 && (error != EEXIST || ifctx == gctx->interfaces)) 1024 panic("bootpc_fakeup_interface: " 1025 "set if addr, error=%d", error); | 1005 sin = (struct sockaddr_in *) &ireq->ifr_addr; 1006 clear_sinaddr(sin); 1007 error = ifioctl(so, SIOCSIFADDR, (caddr_t) ireq, td); 1008 if (error != 0 && (error != EEXIST || ifctx == gctx->interfaces)) 1009 panic("bootpc_fakeup_interface: " 1010 "set if addr, error=%d", error); |
1026 | 1011 |
1027 /* netmask is 255.0.0.0 */ | 1012 /* netmask is 255.0.0.0 */ |
1028 | 1013 |
1029 sin = (struct sockaddr_in *) &ireq->ifr_addr; 1030 clear_sinaddr(sin); 1031 sin->sin_addr.s_addr = htonl(0xff000000u); 1032 error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, td); 1033 if (error != 0) 1034 panic("bootpc_fakeup_interface: set if netmask, error=%d", 1035 error); | 1014 sin = (struct sockaddr_in *) &ireq->ifr_addr; 1015 clear_sinaddr(sin); 1016 sin->sin_addr.s_addr = htonl(0xff000000u); 1017 error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, td); 1018 if (error != 0) 1019 panic("bootpc_fakeup_interface: set if netmask, error=%d", 1020 error); |
1036 | 1021 |
1037 /* Broadcast is 255.255.255.255 */ | 1022 /* Broadcast is 255.255.255.255 */ |
1038 | 1023 |
1039 sin = (struct sockaddr_in *)&ireq->ifr_addr; 1040 clear_sinaddr(sin); 1041 clear_sinaddr(&ifctx->broadcast); 1042 sin->sin_addr.s_addr = htonl(INADDR_BROADCAST); 1043 ifctx->broadcast.sin_addr.s_addr = sin->sin_addr.s_addr; | 1024 sin = (struct sockaddr_in *)&ireq->ifr_addr; 1025 clear_sinaddr(sin); 1026 clear_sinaddr(&ifctx->broadcast); 1027 sin->sin_addr.s_addr = htonl(INADDR_BROADCAST); 1028 ifctx->broadcast.sin_addr.s_addr = sin->sin_addr.s_addr; |
1044 | 1029 |
1045 error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, td); 1046 if (error != 0) 1047 panic("bootpc_fakeup_interface: " 1048 "set if broadcast addr, error=%d", 1049 error); | 1030 error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, td); 1031 if (error != 0) 1032 panic("bootpc_fakeup_interface: " 1033 "set if broadcast addr, error=%d", 1034 error); |
1050 | 1035 |
1051 /* Get HW address */ | 1036 /* Get HW address */ |
1052 | 1037 |
1053 sdl = NULL; | 1038 sdl = NULL; |
1054 for (ifa = TAILQ_FIRST(&ifctx->ifp->if_addrhead); 1055 ifa != NULL; 1056 ifa = TAILQ_NEXT(ifa,ifa_link)) 1057 if (ifa->ifa_addr->sa_family == AF_LINK && 1058 (sdl = ((struct sockaddr_dl *) ifa->ifa_addr)) != NULL && 1059 sdl->sdl_type == IFT_ETHER) 1060 break; 1061 | 1039 TAILQ_FOREACH(ifa, &ifctx->ifp->if_addrhead, ifa_link) 1040 if (ifa->ifa_addr->sa_family == AF_LINK) { 1041 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 1042 if (sdl->sdl_type == IFT_ETHER) 1043 break; 1044 } 1045 |
1062 if (sdl == NULL) 1063 panic("bootpc: Unable to find HW address for %s", 1064 ifctx->ireq.ifr_name); 1065 ifctx->sdl = sdl; | 1046 if (sdl == NULL) 1047 panic("bootpc: Unable to find HW address for %s", 1048 ifctx->ireq.ifr_name); 1049 ifctx->sdl = sdl; |
1066 | 1050 |
1067 return error; 1068} 1069 1070 1071static int 1072bootpc_adjust_interface(struct bootpc_ifcontext *ifctx, | 1051 return error; 1052} 1053 1054 1055static int 1056bootpc_adjust_interface(struct bootpc_ifcontext *ifctx, |
1073 struct bootpc_globalcontext *gctx, 1074 struct thread *td) | 1057 struct bootpc_globalcontext *gctx, struct thread *td) |
1075{ 1076 int error; 1077 struct sockaddr_in defdst; 1078 struct sockaddr_in defmask; 1079 struct sockaddr_in *sin; | 1058{ 1059 int error; 1060 struct sockaddr_in defdst; 1061 struct sockaddr_in defmask; 1062 struct sockaddr_in *sin; |
1080 | |
1081 struct ifreq *ireq; 1082 struct socket *so; 1083 struct sockaddr_in *myaddr; 1084 struct sockaddr_in *netmask; 1085 struct sockaddr_in *gw; 1086 1087 ireq = &ifctx->ireq; 1088 so = ifctx->so; 1089 myaddr = &ifctx->myaddr; 1090 netmask = &ifctx->netmask; 1091 gw = &ifctx->gw; 1092 1093 if (bootpc_ifctx_isresolved(ifctx) == 0) { 1094 1095 /* Shutdown interfaces where BOOTP failed */ | 1063 struct ifreq *ireq; 1064 struct socket *so; 1065 struct sockaddr_in *myaddr; 1066 struct sockaddr_in *netmask; 1067 struct sockaddr_in *gw; 1068 1069 ireq = &ifctx->ireq; 1070 so = ifctx->so; 1071 myaddr = &ifctx->myaddr; 1072 netmask = &ifctx->netmask; 1073 gw = &ifctx->gw; 1074 1075 if (bootpc_ifctx_isresolved(ifctx) == 0) { 1076 1077 /* Shutdown interfaces where BOOTP failed */ |
1096 | 1078 |
1097 printf("Shutdown interface %s\n", ifctx->ireq.ifr_name); 1098 error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, td); 1099 if (error != 0) 1100 panic("bootpc_adjust_interface: " 1101 "SIOCGIFFLAGS, error=%d", error); 1102 ireq->ifr_flags &= ~IFF_UP; 1103 error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, td); 1104 if (error != 0) 1105 panic("bootpc_adjust_interface: " 1106 "SIOCSIFFLAGS, error=%d", error); | 1079 printf("Shutdown interface %s\n", ifctx->ireq.ifr_name); 1080 error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, td); 1081 if (error != 0) 1082 panic("bootpc_adjust_interface: " 1083 "SIOCGIFFLAGS, error=%d", error); 1084 ireq->ifr_flags &= ~IFF_UP; 1085 error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, td); 1086 if (error != 0) 1087 panic("bootpc_adjust_interface: " 1088 "SIOCSIFFLAGS, error=%d", error); |
1107 | 1089 |
1108 sin = (struct sockaddr_in *) &ireq->ifr_addr; 1109 clear_sinaddr(sin); 1110 error = ifioctl(so, SIOCDIFADDR, (caddr_t) ireq, td); 1111 if (error != 0 && (error != EEXIST || 1112 ifctx == gctx->interfaces)) 1113 panic("bootpc_adjust_interface: " 1114 "SIOCDIFADDR, error=%d", error); | 1090 sin = (struct sockaddr_in *) &ireq->ifr_addr; 1091 clear_sinaddr(sin); 1092 error = ifioctl(so, SIOCDIFADDR, (caddr_t) ireq, td); 1093 if (error != 0 && (error != EEXIST || 1094 ifctx == gctx->interfaces)) 1095 panic("bootpc_adjust_interface: " 1096 "SIOCDIFADDR, error=%d", error); |
1115 | 1097 |
1116 return 0; 1117 } 1118 1119 printf("Adjusted interface %s\n", ifctx->ireq.ifr_name); 1120 /* 1121 * Do enough of ifconfig(8) so that the chosen interface 1122 * can talk to the servers. (just set the address) 1123 */ 1124 bcopy(netmask, &ireq->ifr_addr, sizeof(*netmask)); 1125 error = ifioctl(so, SIOCSIFNETMASK, (caddr_t) ireq, td); 1126 if (error != 0) 1127 panic("bootpc_adjust_interface: " 1128 "set if netmask, error=%d", error); | 1098 return 0; 1099 } 1100 1101 printf("Adjusted interface %s\n", ifctx->ireq.ifr_name); 1102 /* 1103 * Do enough of ifconfig(8) so that the chosen interface 1104 * can talk to the servers. (just set the address) 1105 */ 1106 bcopy(netmask, &ireq->ifr_addr, sizeof(*netmask)); 1107 error = ifioctl(so, SIOCSIFNETMASK, (caddr_t) ireq, td); 1108 if (error != 0) 1109 panic("bootpc_adjust_interface: " 1110 "set if netmask, error=%d", error); |
1129 | 1111 |
1130 /* Broadcast is with host part of IP address all 1's */ | 1112 /* Broadcast is with host part of IP address all 1's */ |
1131 | 1113 |
1132 sin = (struct sockaddr_in *) &ireq->ifr_addr; 1133 clear_sinaddr(sin); 1134 sin->sin_addr.s_addr = myaddr->sin_addr.s_addr | 1135 ~ netmask->sin_addr.s_addr; 1136 error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t) ireq, td); 1137 if (error != 0) 1138 panic("bootpc_adjust_interface: " 1139 "set if broadcast addr, error=%d", error); | 1114 sin = (struct sockaddr_in *) &ireq->ifr_addr; 1115 clear_sinaddr(sin); 1116 sin->sin_addr.s_addr = myaddr->sin_addr.s_addr | 1117 ~ netmask->sin_addr.s_addr; 1118 error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t) ireq, td); 1119 if (error != 0) 1120 panic("bootpc_adjust_interface: " 1121 "set if broadcast addr, error=%d", error); |
1140 | 1122 |
1141 bcopy(myaddr, &ireq->ifr_addr, sizeof(*myaddr)); 1142 error = ifioctl(so, SIOCSIFADDR, (caddr_t) ireq, td); 1143 if (error != 0 && (error != EEXIST || ifctx == gctx->interfaces)) 1144 panic("bootpc_adjust_interface: " 1145 "set if addr, error=%d", error); | 1123 bcopy(myaddr, &ireq->ifr_addr, sizeof(*myaddr)); 1124 error = ifioctl(so, SIOCSIFADDR, (caddr_t) ireq, td); 1125 if (error != 0 && (error != EEXIST || ifctx == gctx->interfaces)) 1126 panic("bootpc_adjust_interface: " 1127 "set if addr, error=%d", error); |
1146 | 1128 |
1147 /* Add new default route */ 1148 1149 if (ifctx->gotgw != 0 || gctx->gotgw == 0) { 1150 clear_sinaddr(&defdst); 1151 clear_sinaddr(&defmask); | 1129 /* Add new default route */ 1130 1131 if (ifctx->gotgw != 0 || gctx->gotgw == 0) { 1132 clear_sinaddr(&defdst); 1133 clear_sinaddr(&defmask); |
1152 error = rtrequest(RTM_ADD, | 1134 /* XXX MRT just table 0 */ 1135 error = rtrequest_fib(RTM_ADD, |
1153 (struct sockaddr *) &defdst, 1154 (struct sockaddr *) gw, 1155 (struct sockaddr *) &defmask, | 1136 (struct sockaddr *) &defdst, 1137 (struct sockaddr *) gw, 1138 (struct sockaddr *) &defmask, |
1156 (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL); | 1139 (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL, 0); |
1157 if (error != 0) { 1158 printf("bootpc_adjust_interface: " 1159 "add net route, error=%d\n", error); 1160 return error; 1161 } 1162 } | 1140 if (error != 0) { 1141 printf("bootpc_adjust_interface: " 1142 "add net route, error=%d\n", error); 1143 return error; 1144 } 1145 } |
1163 | 1146 |
1164 return 0; 1165} 1166 | 1147 return 0; 1148} 1149 |
1150static int 1151setfs(struct sockaddr_in *addr, char *path, char *p, 1152 const struct in_addr *siaddr) 1153{ |
|
1167 | 1154 |
1155 if (getip(&p, &addr->sin_addr) == 0) { 1156 if (siaddr != NULL && *p == '/') 1157 bcopy(siaddr, &addr->sin_addr, sizeof(struct in_addr)); 1158 else 1159 return 0; 1160 } else { 1161 if (*p != ':') 1162 return 0; 1163 p++; 1164 } 1165 1166 addr->sin_len = sizeof(struct sockaddr_in); 1167 addr->sin_family = AF_INET; 1168 1169 strlcpy(path, p, MNAMELEN); 1170 return 1; 1171} 1172 |
|
1168static int | 1173static int |
1169setfs(struct sockaddr_in *addr, char *path, char *p) | 1174getip(char **ptr, struct in_addr *addr) |
1170{ | 1175{ |
1176 char *p; |
|
1171 unsigned int ip; 1172 int val; | 1177 unsigned int ip; 1178 int val; |
1173 | 1179 1180 p = *ptr; |
1174 ip = 0; 1175 if (((val = getdec(&p)) < 0) || (val > 255)) 1176 return 0; 1177 ip = val << 24; 1178 if (*p != '.') 1179 return 0; 1180 p++; 1181 if (((val = getdec(&p)) < 0) || (val > 255)) --- 6 unchanged lines hidden (view full) --- 1188 return 0; 1189 ip |= (val << 8); 1190 if (*p != '.') 1191 return 0; 1192 p++; 1193 if (((val = getdec(&p)) < 0) || (val > 255)) 1194 return 0; 1195 ip |= val; | 1181 ip = 0; 1182 if (((val = getdec(&p)) < 0) || (val > 255)) 1183 return 0; 1184 ip = val << 24; 1185 if (*p != '.') 1186 return 0; 1187 p++; 1188 if (((val = getdec(&p)) < 0) || (val > 255)) --- 6 unchanged lines hidden (view full) --- 1195 return 0; 1196 ip |= (val << 8); 1197 if (*p != '.') 1198 return 0; 1199 p++; 1200 if (((val = getdec(&p)) < 0) || (val > 255)) 1201 return 0; 1202 ip |= val; |
1196 if (*p != ':') 1197 return 0; 1198 p++; 1199 1200 addr->sin_addr.s_addr = htonl(ip); 1201 addr->sin_len = sizeof(struct sockaddr_in); 1202 addr->sin_family = AF_INET; 1203 1204 strncpy(path, p, MNAMELEN - 1); | 1203 1204 addr->s_addr = htonl(ip); 1205 *ptr = p; |
1205 return 1; 1206} 1207 | 1206 return 1; 1207} 1208 |
1208 | |
1209static int 1210getdec(char **ptr) 1211{ 1212 char *p; 1213 int ret; 1214 1215 p = *ptr; 1216 ret = 0; 1217 if ((*p < '0') || (*p > '9')) 1218 return -1; 1219 while ((*p >= '0') && (*p <= '9')) { 1220 ret = ret * 10 + (*p - '0'); 1221 p++; 1222 } 1223 *ptr = p; 1224 return ret; 1225} 1226 | 1209static int 1210getdec(char **ptr) 1211{ 1212 char *p; 1213 int ret; 1214 1215 p = *ptr; 1216 ret = 0; 1217 if ((*p < '0') || (*p > '9')) 1218 return -1; 1219 while ((*p >= '0') && (*p <= '9')) { 1220 ret = ret * 10 + (*p - '0'); 1221 p++; 1222 } 1223 *ptr = p; 1224 return ret; 1225} 1226 |
1227 1228static char * 1229substr(char *a, char *b) 1230{ 1231 char *loc1; 1232 char *loc2; 1233 1234 while (*a != '\0') { 1235 loc1 = a; 1236 loc2 = b; 1237 while (*loc1 == *loc2++) { 1238 if (*loc1 == '\0') 1239 return 0; 1240 loc1++; 1241 if (*loc2 == '\0') 1242 return loc1; 1243 } 1244 a++; 1245 } 1246 return 0; 1247} 1248 1249 | |
1250static void 1251mountopts(struct nfs_args *args, char *p) 1252{ | 1227static void 1228mountopts(struct nfs_args *args, char *p) 1229{ |
1253 char *tmp; 1254 | |
1255 args->version = NFS_ARGSVERSION; | 1230 args->version = NFS_ARGSVERSION; |
1256 args->rsize = 8192; 1257 args->wsize = 8192; | 1231 args->rsize = BOOTP_BLOCKSIZE; 1232 args->wsize = BOOTP_BLOCKSIZE; |
1258 args->flags = NFSMNT_RSIZE | NFSMNT_WSIZE | NFSMNT_RESVPORT; 1259 args->sotype = SOCK_DGRAM; | 1233 args->flags = NFSMNT_RSIZE | NFSMNT_WSIZE | NFSMNT_RESVPORT; 1234 args->sotype = SOCK_DGRAM; |
1260 if (p == NULL) 1261 return; 1262 if ((tmp = (char *)substr(p, "rsize="))) 1263 args->rsize = getdec(&tmp); 1264 if ((tmp = (char *)substr(p, "wsize="))) 1265 args->wsize = getdec(&tmp); 1266 if ((tmp = (char *)substr(p, "intr"))) 1267 args->flags |= NFSMNT_INT; 1268 if ((tmp = (char *)substr(p, "soft"))) 1269 args->flags |= NFSMNT_SOFT; 1270 if ((tmp = (char *)substr(p, "noconn"))) 1271 args->flags |= NFSMNT_NOCONN; 1272 if ((tmp = (char *)substr(p, "tcp"))) 1273 args->sotype = SOCK_STREAM; | 1235 if (p != NULL) 1236 nfs_parse_options(p, args); |
1274} 1275 | 1237} 1238 |
1276 | |
1277static int 1278xdr_opaque_decode(struct mbuf **mptr, u_char *buf, int len) 1279{ 1280 struct mbuf *m; 1281 int alignedlen; | 1239static int 1240xdr_opaque_decode(struct mbuf **mptr, u_char *buf, int len) 1241{ 1242 struct mbuf *m; 1243 int alignedlen; |
1282 | 1244 |
1283 m = *mptr; 1284 alignedlen = ( len + 3 ) & ~3; | 1245 m = *mptr; 1246 alignedlen = ( len + 3 ) & ~3; |
1285 | 1247 |
1286 if (m->m_len < alignedlen) { 1287 m = m_pullup(m, alignedlen); 1288 if (m == NULL) { 1289 *mptr = NULL; 1290 return EBADRPC; 1291 } 1292 } 1293 bcopy(mtod(m, u_char *), buf, len); 1294 m_adj(m, alignedlen); 1295 *mptr = m; 1296 return 0; 1297} 1298 | 1248 if (m->m_len < alignedlen) { 1249 m = m_pullup(m, alignedlen); 1250 if (m == NULL) { 1251 *mptr = NULL; 1252 return EBADRPC; 1253 } 1254 } 1255 bcopy(mtod(m, u_char *), buf, len); 1256 m_adj(m, alignedlen); 1257 *mptr = m; 1258 return 0; 1259} 1260 |
1299 | |
1300static int 1301xdr_int_decode(struct mbuf **mptr, int *iptr) 1302{ 1303 u_int32_t i; | 1261static int 1262xdr_int_decode(struct mbuf **mptr, int *iptr) 1263{ 1264 u_int32_t i; |
1265 |
|
1304 if (xdr_opaque_decode(mptr, (u_char *) &i, sizeof(u_int32_t)) != 0) 1305 return EBADRPC; 1306 *iptr = fxdr_unsigned(u_int32_t, i); 1307 return 0; 1308} 1309 | 1266 if (xdr_opaque_decode(mptr, (u_char *) &i, sizeof(u_int32_t)) != 0) 1267 return EBADRPC; 1268 *iptr = fxdr_unsigned(u_int32_t, i); 1269 return 0; 1270} 1271 |
1310 | |
1311static void 1312print_sin_addr(struct sockaddr_in *sin) 1313{ | 1272static void 1273print_sin_addr(struct sockaddr_in *sin) 1274{ |
1275 |
|
1314 print_in_addr(sin->sin_addr); 1315} 1316 | 1276 print_in_addr(sin->sin_addr); 1277} 1278 |
1317 | |
1318static void 1319print_in_addr(struct in_addr addr) 1320{ 1321 unsigned int ip; | 1279static void 1280print_in_addr(struct in_addr addr) 1281{ 1282 unsigned int ip; |
1322 | 1283 |
1323 ip = ntohl(addr.s_addr); 1324 printf("%d.%d.%d.%d", 1325 ip >> 24, (ip >> 16) & 255, (ip >> 8) & 255, ip & 255); 1326} 1327 1328static void | 1284 ip = ntohl(addr.s_addr); 1285 printf("%d.%d.%d.%d", 1286 ip >> 24, (ip >> 16) & 255, (ip >> 8) & 255, ip & 255); 1287} 1288 1289static void |
1329bootpc_compose_query(ifctx, gctx, td) 1330 struct bootpc_ifcontext *ifctx; 1331 struct bootpc_globalcontext *gctx; 1332 struct thread *td; | 1290bootpc_compose_query(struct bootpc_ifcontext *ifctx, 1291 struct bootpc_globalcontext *gctx, struct thread *td) |
1333{ 1334 unsigned char *vendp; | 1292{ 1293 unsigned char *vendp; |
1294 unsigned char vendor_client[64]; |
|
1335 uint32_t leasetime; | 1295 uint32_t leasetime; |
1296 uint8_t vendor_client_len; |
|
1336 1337 ifctx->gotrootpath = 0; 1338 1339 bzero((caddr_t) &ifctx->call, sizeof(ifctx->call)); | 1297 1298 ifctx->gotrootpath = 0; 1299 1300 bzero((caddr_t) &ifctx->call, sizeof(ifctx->call)); |
1340 | 1301 |
1341 /* bootpc part */ 1342 ifctx->call.op = BOOTP_REQUEST; /* BOOTREQUEST */ 1343 ifctx->call.htype = 1; /* 10mb ethernet */ 1344 ifctx->call.hlen = ifctx->sdl->sdl_alen;/* Hardware address length */ 1345 ifctx->call.hops = 0; 1346 if (bootpc_ifctx_isunresolved(ifctx) != 0) 1347 ifctx->xid++; 1348 ifctx->call.xid = txdr_unsigned(ifctx->xid); 1349 bcopy(LLADDR(ifctx->sdl), &ifctx->call.chaddr, ifctx->sdl->sdl_alen); | 1302 /* bootpc part */ 1303 ifctx->call.op = BOOTP_REQUEST; /* BOOTREQUEST */ 1304 ifctx->call.htype = 1; /* 10mb ethernet */ 1305 ifctx->call.hlen = ifctx->sdl->sdl_alen;/* Hardware address length */ 1306 ifctx->call.hops = 0; 1307 if (bootpc_ifctx_isunresolved(ifctx) != 0) 1308 ifctx->xid++; 1309 ifctx->call.xid = txdr_unsigned(ifctx->xid); 1310 bcopy(LLADDR(ifctx->sdl), &ifctx->call.chaddr, ifctx->sdl->sdl_alen); |
1350 | 1311 |
1351 vendp = ifctx->call.vend; 1352 *vendp++ = 99; /* RFC1048 cookie */ 1353 *vendp++ = 130; 1354 *vendp++ = 83; 1355 *vendp++ = 99; 1356 *vendp++ = TAG_MAXMSGSIZE; 1357 *vendp++ = 2; 1358 *vendp++ = (sizeof(struct bootp_packet) >> 8) & 255; 1359 *vendp++ = sizeof(struct bootp_packet) & 255; | 1312 vendp = ifctx->call.vend; 1313 *vendp++ = 99; /* RFC1048 cookie */ 1314 *vendp++ = 130; 1315 *vendp++ = 83; 1316 *vendp++ = 99; 1317 *vendp++ = TAG_MAXMSGSIZE; 1318 *vendp++ = 2; 1319 *vendp++ = (sizeof(struct bootp_packet) >> 8) & 255; 1320 *vendp++ = sizeof(struct bootp_packet) & 255; |
1321 1322 snprintf(vendor_client, sizeof(vendor_client), "%s:%s:%s", 1323 ostype, MACHINE, osrelease); 1324 vendor_client_len = strlen(vendor_client); 1325 *vendp++ = TAG_VENDOR_INDENTIFIER; 1326 *vendp++ = vendor_client_len; 1327 memcpy(vendp, vendor_client, vendor_client_len); 1328 vendp += vendor_client_len; |
|
1360 ifctx->dhcpquerytype = DHCP_NOMSG; 1361 switch (ifctx->state) { 1362 case IF_DHCP_UNRESOLVED: 1363 *vendp++ = TAG_DHCP_MSGTYPE; 1364 *vendp++ = 1; 1365 *vendp++ = DHCP_DISCOVER; 1366 ifctx->dhcpquerytype = DHCP_DISCOVER; 1367 ifctx->gotdhcpserver = 0; --- 13 unchanged lines hidden (view full) --- 1381 memcpy(vendp, &ifctx->dhcpserver, 4); 1382 vendp += 4; 1383 } 1384 *vendp++ = TAG_DHCP_LEASETIME; 1385 *vendp++ = 4; 1386 leasetime = htonl(300); 1387 memcpy(vendp, &leasetime, 4); 1388 vendp += 4; | 1329 ifctx->dhcpquerytype = DHCP_NOMSG; 1330 switch (ifctx->state) { 1331 case IF_DHCP_UNRESOLVED: 1332 *vendp++ = TAG_DHCP_MSGTYPE; 1333 *vendp++ = 1; 1334 *vendp++ = DHCP_DISCOVER; 1335 ifctx->dhcpquerytype = DHCP_DISCOVER; 1336 ifctx->gotdhcpserver = 0; --- 13 unchanged lines hidden (view full) --- 1350 memcpy(vendp, &ifctx->dhcpserver, 4); 1351 vendp += 4; 1352 } 1353 *vendp++ = TAG_DHCP_LEASETIME; 1354 *vendp++ = 4; 1355 leasetime = htonl(300); 1356 memcpy(vendp, &leasetime, 4); 1357 vendp += 4; |
1358 break; |
|
1389 default: | 1359 default: |
1390 ; | 1360 break; |
1391 } 1392 *vendp = TAG_END; | 1361 } 1362 *vendp = TAG_END; |
1393 | 1363 |
1394 ifctx->call.secs = 0; | 1364 ifctx->call.secs = 0; |
1395 ifctx->call.flags = htons(0x8000); /* We need an broadcast answer */ | 1365 ifctx->call.flags = htons(0x8000); /* We need a broadcast answer */ |
1396} 1397 | 1366} 1367 |
1398 | |
1399static int 1400bootpc_hascookie(struct bootp_packet *bp) 1401{ | 1368static int 1369bootpc_hascookie(struct bootp_packet *bp) 1370{ |
1371 |
|
1402 return (bp->vend[0] == 99 && bp->vend[1] == 130 && 1403 bp->vend[2] == 83 && bp->vend[3] == 99); 1404} 1405 | 1372 return (bp->vend[0] == 99 && bp->vend[1] == 130 && 1373 bp->vend[2] == 83 && bp->vend[3] == 99); 1374} 1375 |
1406 | |
1407static void 1408bootpc_tag_helper(struct bootpc_tagcontext *tctx, | 1376static void 1377bootpc_tag_helper(struct bootpc_tagcontext *tctx, |
1409 unsigned char *start, 1410 int len, 1411 int tag) | 1378 unsigned char *start, int len, int tag) |
1412{ 1413 unsigned char *j; 1414 unsigned char *ej; 1415 unsigned char code; 1416 1417 if (tctx->badtag != 0 || tctx->badopt != 0) 1418 return; | 1379{ 1380 unsigned char *j; 1381 unsigned char *ej; 1382 unsigned char code; 1383 1384 if (tctx->badtag != 0 || tctx->badopt != 0) 1385 return; |
1419 | 1386 |
1420 j = start; 1421 ej = j + len; | 1387 j = start; 1388 ej = j + len; |
1422 | 1389 |
1423 while (j < ej) { 1424 code = *j++; 1425 if (code == TAG_PAD) 1426 continue; 1427 if (code == TAG_END) 1428 return; 1429 if (j >= ej || j + *j + 1 > ej) { 1430 tctx->badopt = 1; --- 8 unchanged lines hidden (view full) --- 1439 tctx->foundopt = 1; 1440 if (len > 0) 1441 memcpy(tctx->buf + tctx->taglen, 1442 j, len); 1443 tctx->taglen += len; 1444 } 1445 if (code == TAG_OVERLOAD) 1446 tctx->overload = *j; | 1390 while (j < ej) { 1391 code = *j++; 1392 if (code == TAG_PAD) 1393 continue; 1394 if (code == TAG_END) 1395 return; 1396 if (j >= ej || j + *j + 1 > ej) { 1397 tctx->badopt = 1; --- 8 unchanged lines hidden (view full) --- 1406 tctx->foundopt = 1; 1407 if (len > 0) 1408 memcpy(tctx->buf + tctx->taglen, 1409 j, len); 1410 tctx->taglen += len; 1411 } 1412 if (code == TAG_OVERLOAD) 1413 tctx->overload = *j; |
1447 | 1414 |
1448 j += len; 1449 } 1450} 1451 | 1415 j += len; 1416 } 1417} 1418 |
1452 | |
1453static unsigned char * 1454bootpc_tag(struct bootpc_tagcontext *tctx, | 1419static unsigned char * 1420bootpc_tag(struct bootpc_tagcontext *tctx, |
1455 struct bootp_packet *bp, 1456 int len, 1457 int tag) | 1421 struct bootp_packet *bp, int len, int tag) |
1458{ | 1422{ |
1459 unsigned char *j; 1460 unsigned char *ej; 1461 | |
1462 tctx->overload = 0; 1463 tctx->badopt = 0; 1464 tctx->badtag = 0; 1465 tctx->foundopt = 0; 1466 tctx->taglen = 0; 1467 1468 if (bootpc_hascookie(bp) == 0) 1469 return NULL; | 1423 tctx->overload = 0; 1424 tctx->badopt = 0; 1425 tctx->badtag = 0; 1426 tctx->foundopt = 0; 1427 tctx->taglen = 0; 1428 1429 if (bootpc_hascookie(bp) == 0) 1430 return NULL; |
1470 1471 j = &bp->vend[4]; 1472 ej = (unsigned char *) bp + len; | |
1473 1474 bootpc_tag_helper(tctx, &bp->vend[4], 1475 (unsigned char *) bp + len - &bp->vend[4], tag); | 1431 1432 bootpc_tag_helper(tctx, &bp->vend[4], 1433 (unsigned char *) bp + len - &bp->vend[4], tag); |
1476 | 1434 |
1477 if ((tctx->overload & OVERLOAD_FILE) != 0) 1478 bootpc_tag_helper(tctx, 1479 (unsigned char *) bp->file, 1480 sizeof(bp->file), 1481 tag); 1482 if ((tctx->overload & OVERLOAD_SNAME) != 0) 1483 bootpc_tag_helper(tctx, 1484 (unsigned char *) bp->sname, 1485 sizeof(bp->sname), 1486 tag); | 1435 if ((tctx->overload & OVERLOAD_FILE) != 0) 1436 bootpc_tag_helper(tctx, 1437 (unsigned char *) bp->file, 1438 sizeof(bp->file), 1439 tag); 1440 if ((tctx->overload & OVERLOAD_SNAME) != 0) 1441 bootpc_tag_helper(tctx, 1442 (unsigned char *) bp->sname, 1443 sizeof(bp->sname), 1444 tag); |
1487 | 1445 |
1488 if (tctx->badopt != 0 || tctx->badtag != 0 || tctx->foundopt == 0) 1489 return NULL; 1490 tctx->buf[tctx->taglen] = '\0'; 1491 return tctx->buf; 1492} 1493 | 1446 if (tctx->badopt != 0 || tctx->badtag != 0 || tctx->foundopt == 0) 1447 return NULL; 1448 tctx->buf[tctx->taglen] = '\0'; 1449 return tctx->buf; 1450} 1451 |
1494 | |
1495static void | 1452static void |
1496bootpc_decode_reply(nd, ifctx, gctx) 1497 struct nfsv3_diskless *nd; 1498 struct bootpc_ifcontext *ifctx; 1499 struct bootpc_globalcontext *gctx; | 1453bootpc_decode_reply(struct nfsv3_diskless *nd, struct bootpc_ifcontext *ifctx, 1454 struct bootpc_globalcontext *gctx) |
1500{ 1501 char *p; 1502 unsigned int ip; 1503 1504 ifctx->gotgw = 0; 1505 ifctx->gotnetmask = 0; 1506 1507 clear_sinaddr(&ifctx->myaddr); 1508 clear_sinaddr(&ifctx->netmask); 1509 clear_sinaddr(&ifctx->gw); | 1455{ 1456 char *p; 1457 unsigned int ip; 1458 1459 ifctx->gotgw = 0; 1460 ifctx->gotnetmask = 0; 1461 1462 clear_sinaddr(&ifctx->myaddr); 1463 clear_sinaddr(&ifctx->netmask); 1464 clear_sinaddr(&ifctx->gw); |
1510 | 1465 |
1511 ifctx->myaddr.sin_addr = ifctx->reply.yiaddr; | 1466 ifctx->myaddr.sin_addr = ifctx->reply.yiaddr; |
1512 | 1467 |
1513 ip = ntohl(ifctx->myaddr.sin_addr.s_addr); | 1468 ip = ntohl(ifctx->myaddr.sin_addr.s_addr); |
1514 snprintf(gctx->lookup_path, sizeof(gctx->lookup_path), 1515 "swap.%d.%d.%d.%d", 1516 ip >> 24, (ip >> 16) & 255, (ip >> 8) & 255, ip & 255); 1517 | 1469 |
1518 printf("%s at ", ifctx->ireq.ifr_name); 1519 print_sin_addr(&ifctx->myaddr); 1520 printf(" server "); 1521 print_in_addr(ifctx->reply.siaddr); | 1470 printf("%s at ", ifctx->ireq.ifr_name); 1471 print_sin_addr(&ifctx->myaddr); 1472 printf(" server "); 1473 print_in_addr(ifctx->reply.siaddr); |
1522 | 1474 |
1523 ifctx->gw.sin_addr = ifctx->reply.giaddr; 1524 if (ifctx->reply.giaddr.s_addr != htonl(INADDR_ANY)) { 1525 printf(" via gateway "); 1526 print_in_addr(ifctx->reply.giaddr); 1527 } 1528 1529 /* This call used for the side effect (overload flag) */ 1530 (void) bootpc_tag(&gctx->tmptag, 1531 &ifctx->reply, ifctx->replylen, TAG_END); | 1475 ifctx->gw.sin_addr = ifctx->reply.giaddr; 1476 if (ifctx->reply.giaddr.s_addr != htonl(INADDR_ANY)) { 1477 printf(" via gateway "); 1478 print_in_addr(ifctx->reply.giaddr); 1479 } 1480 1481 /* This call used for the side effect (overload flag) */ 1482 (void) bootpc_tag(&gctx->tmptag, 1483 &ifctx->reply, ifctx->replylen, TAG_END); |
1532 | 1484 |
1533 if ((gctx->tmptag.overload & OVERLOAD_SNAME) == 0) 1534 if (ifctx->reply.sname[0] != '\0') 1535 printf(" server name %s", ifctx->reply.sname); 1536 if ((gctx->tmptag.overload & OVERLOAD_FILE) == 0) 1537 if (ifctx->reply.file[0] != '\0') 1538 printf(" boot file %s", ifctx->reply.file); | 1485 if ((gctx->tmptag.overload & OVERLOAD_SNAME) == 0) 1486 if (ifctx->reply.sname[0] != '\0') 1487 printf(" server name %s", ifctx->reply.sname); 1488 if ((gctx->tmptag.overload & OVERLOAD_FILE) == 0) 1489 if (ifctx->reply.file[0] != '\0') 1490 printf(" boot file %s", ifctx->reply.file); |
1539 | 1491 |
1540 printf("\n"); 1541 1542 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1543 TAG_SUBNETMASK); 1544 if (p != NULL) { 1545 if (gctx->tag.taglen != 4) 1546 panic("bootpc: subnet mask len is %d", 1547 gctx->tag.taglen); 1548 bcopy(p, &ifctx->netmask.sin_addr, 4); 1549 ifctx->gotnetmask = 1; 1550 printf("subnet mask "); 1551 print_sin_addr(&ifctx->netmask); 1552 printf(" "); 1553 } | 1492 printf("\n"); 1493 1494 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1495 TAG_SUBNETMASK); 1496 if (p != NULL) { 1497 if (gctx->tag.taglen != 4) 1498 panic("bootpc: subnet mask len is %d", 1499 gctx->tag.taglen); 1500 bcopy(p, &ifctx->netmask.sin_addr, 4); 1501 ifctx->gotnetmask = 1; 1502 printf("subnet mask "); 1503 print_sin_addr(&ifctx->netmask); 1504 printf(" "); 1505 } |
1554 | 1506 |
1555 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1556 TAG_ROUTERS); 1557 if (p != NULL) { 1558 /* Routers */ 1559 if (gctx->tag.taglen % 4) 1560 panic("bootpc: Router Len is %d", gctx->tag.taglen); 1561 if (gctx->tag.taglen > 0) { 1562 bcopy(p, &ifctx->gw.sin_addr, 4); 1563 printf("router "); 1564 print_sin_addr(&ifctx->gw); 1565 printf(" "); 1566 ifctx->gotgw = 1; 1567 gctx->gotgw = 1; 1568 } 1569 } | 1507 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1508 TAG_ROUTERS); 1509 if (p != NULL) { 1510 /* Routers */ 1511 if (gctx->tag.taglen % 4) 1512 panic("bootpc: Router Len is %d", gctx->tag.taglen); 1513 if (gctx->tag.taglen > 0) { 1514 bcopy(p, &ifctx->gw.sin_addr, 4); 1515 printf("router "); 1516 print_sin_addr(&ifctx->gw); 1517 printf(" "); 1518 ifctx->gotgw = 1; 1519 gctx->gotgw = 1; 1520 } 1521 } |
1570 | 1522 |
1571 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1572 TAG_ROOT); 1573 if (p != NULL) { 1574 if (gctx->setrootfs != NULL) { 1575 printf("rootfs %s (ignored) ", p); 1576 } else if (setfs(&nd->root_saddr, | 1523 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1524 TAG_ROOT); 1525 if (p != NULL) { 1526 if (gctx->setrootfs != NULL) { 1527 printf("rootfs %s (ignored) ", p); 1528 } else if (setfs(&nd->root_saddr, |
1577 nd->root_hostnam, p)) { 1578 printf("rootfs %s ",p); | 1529 nd->root_hostnam, p, &ifctx->reply.siaddr)) { 1530 if (*p == '/') { 1531 printf("root_server "); 1532 print_sin_addr(&nd->root_saddr); 1533 printf(" "); 1534 } 1535 printf("rootfs %s ", p); |
1579 gctx->gotrootpath = 1; 1580 ifctx->gotrootpath = 1; 1581 gctx->setrootfs = ifctx; | 1536 gctx->gotrootpath = 1; 1537 ifctx->gotrootpath = 1; 1538 gctx->setrootfs = ifctx; |
1582 | 1539 |
1583 p = bootpc_tag(&gctx->tag, &ifctx->reply, 1584 ifctx->replylen, 1585 TAG_ROOTOPTS); 1586 if (p != NULL) { 1587 mountopts(&nd->root_args, p); 1588 printf("rootopts %s ", p); 1589 } 1590 } else | 1540 p = bootpc_tag(&gctx->tag, &ifctx->reply, 1541 ifctx->replylen, 1542 TAG_ROOTOPTS); 1543 if (p != NULL) { 1544 mountopts(&nd->root_args, p); 1545 printf("rootopts %s ", p); 1546 } 1547 } else |
1591 panic("Failed to set rootfs to %s",p); | 1548 panic("Failed to set rootfs to %s", p); |
1592 } 1593 1594 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, | 1549 } 1550 1551 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, |
1595 TAG_SWAP); 1596 if (p != NULL) { 1597 if (gctx->setswapfs != NULL) { 1598 printf("swapfs %s (ignored) ", p); 1599 } else if (setfs(&nd->swap_saddr, 1600 nd->swap_hostnam, p)) { 1601 gctx->gotswappath = 1; 1602 gctx->setswapfs = ifctx; 1603 printf("swapfs %s ", p); 1604 1605 p = bootpc_tag(&gctx->tag, &ifctx->reply, 1606 ifctx->replylen, 1607 TAG_SWAPOPTS); 1608 if (p != NULL) { 1609 /* swap mount options */ 1610 mountopts(&nd->swap_args, p); 1611 printf("swapopts %s ", p); 1612 } 1613 1614 p = bootpc_tag(&gctx->tag, &ifctx->reply, 1615 ifctx->replylen, 1616 TAG_SWAPSIZE); 1617 if (p != NULL) { 1618 int swaplen; 1619 if (gctx->tag.taglen != 4) 1620 panic("bootpc: " 1621 "Expected 4 bytes for swaplen, " 1622 "not %d bytes", 1623 gctx->tag.taglen); 1624 bcopy(p, &swaplen, 4); 1625 nd->swap_nblks = ntohl(swaplen); 1626 printf("swapsize %d KB ", 1627 nd->swap_nblks); 1628 } 1629 } else 1630 panic("Failed to set swapfs to %s", p); 1631 } 1632 1633 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, | |
1634 TAG_HOSTNAME); 1635 if (p != NULL) { 1636 if (gctx->tag.taglen >= MAXHOSTNAMELEN) 1637 panic("bootpc: hostname >= %d bytes", 1638 MAXHOSTNAMELEN); 1639 if (gctx->sethostname != NULL) { 1640 printf("hostname %s (ignored) ", p); 1641 } else { 1642 strcpy(nd->my_hostnam, p); | 1552 TAG_HOSTNAME); 1553 if (p != NULL) { 1554 if (gctx->tag.taglen >= MAXHOSTNAMELEN) 1555 panic("bootpc: hostname >= %d bytes", 1556 MAXHOSTNAMELEN); 1557 if (gctx->sethostname != NULL) { 1558 printf("hostname %s (ignored) ", p); 1559 } else { 1560 strcpy(nd->my_hostnam, p); |
1643 strcpy(hostname, p); 1644 printf("hostname %s ",hostname); | 1561 mtx_lock(&prison0.pr_mtx); 1562 strcpy(prison0.pr_hostname, p); 1563 mtx_unlock(&prison0.pr_mtx); 1564 printf("hostname %s ", p); |
1645 gctx->sethostname = ifctx; 1646 } 1647 } | 1565 gctx->sethostname = ifctx; 1566 } 1567 } |
1568 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, 1569 TAG_COOKIE); 1570 if (p != NULL) { /* store in a sysctl variable */ 1571 int i, l = sizeof(bootp_cookie) - 1; 1572 for (i = 0; i < l && p[i] != '\0'; i++) 1573 bootp_cookie[i] = p[i]; 1574 p[i] = '\0'; 1575 } |
|
1648 | 1576 |
1577 |
|
1649 printf("\n"); | 1578 printf("\n"); |
1650 | 1579 |
1651 if (ifctx->gotnetmask == 0) { 1652 if (IN_CLASSA(ntohl(ifctx->myaddr.sin_addr.s_addr))) 1653 ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSA_NET); 1654 else if (IN_CLASSB(ntohl(ifctx->myaddr.sin_addr.s_addr))) 1655 ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSB_NET); 1656 else 1657 ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSC_NET); 1658 } --- 5 unchanged lines hidden (view full) --- 1664 1665void 1666bootpc_init(void) 1667{ 1668 struct bootpc_ifcontext *ifctx, *nctx; /* Interface BOOTP contexts */ 1669 struct bootpc_globalcontext *gctx; /* Global BOOTP context */ 1670 struct ifnet *ifp; 1671 int error; | 1580 if (ifctx->gotnetmask == 0) { 1581 if (IN_CLASSA(ntohl(ifctx->myaddr.sin_addr.s_addr))) 1582 ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSA_NET); 1583 else if (IN_CLASSB(ntohl(ifctx->myaddr.sin_addr.s_addr))) 1584 ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSB_NET); 1585 else 1586 ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSC_NET); 1587 } --- 5 unchanged lines hidden (view full) --- 1593 1594void 1595bootpc_init(void) 1596{ 1597 struct bootpc_ifcontext *ifctx, *nctx; /* Interface BOOTP contexts */ 1598 struct bootpc_globalcontext *gctx; /* Global BOOTP context */ 1599 struct ifnet *ifp; 1600 int error; |
1601#ifndef BOOTP_WIRED_TO 1602 int ifcnt; 1603#endif |
|
1672 struct nfsv3_diskless *nd; 1673 struct thread *td; 1674 1675 nd = &nfsv3_diskless; 1676 td = curthread; | 1604 struct nfsv3_diskless *nd; 1605 struct thread *td; 1606 1607 nd = &nfsv3_diskless; 1608 td = curthread; |
1677 | 1609 |
1678 /* 1679 * If already filled in, don't touch it here 1680 */ 1681 if (nfs_diskless_valid != 0) 1682 return; 1683 | 1610 /* 1611 * If already filled in, don't touch it here 1612 */ 1613 if (nfs_diskless_valid != 0) 1614 return; 1615 |
1684 /* 1685 * Wait until arp entries can be handled. 1686 */ 1687 while (time_second == 0) 1688 tsleep(&time_second, PZERO + 8, "arpkludge", 10); 1689 1690 gctx = malloc(sizeof(*gctx), M_TEMP, M_WAITOK); | 1616 gctx = malloc(sizeof(*gctx), M_TEMP, M_WAITOK | M_ZERO); |
1691 if (gctx == NULL) 1692 panic("Failed to allocate bootp global context structure"); | 1617 if (gctx == NULL) 1618 panic("Failed to allocate bootp global context structure"); |
1693 1694 bzero(gctx, sizeof(*gctx)); | 1619 |
1695 gctx->xid = ~0xFFFF; 1696 gctx->starttime = time_second; | 1620 gctx->xid = ~0xFFFF; 1621 gctx->starttime = time_second; |
1697 1698 ifctx = allocifctx(gctx); | |
1699 1700 /* 1701 * Find a network interface. 1702 */ | 1622 1623 /* 1624 * Find a network interface. 1625 */ |
1626 CURVNET_SET(TD_TO_VNET(td)); |
|
1703#ifdef BOOTP_WIRED_TO 1704 printf("bootpc_init: wired to interface '%s'\n", 1705 __XSTRING(BOOTP_WIRED_TO)); | 1627#ifdef BOOTP_WIRED_TO 1628 printf("bootpc_init: wired to interface '%s'\n", 1629 __XSTRING(BOOTP_WIRED_TO)); |
1706#endif 1707 bzero(&ifctx->ireq, sizeof(ifctx->ireq)); 1708 for (ifp = TAILQ_FIRST(&ifnet); | 1630 allocifctx(gctx); 1631#else 1632 /* 1633 * Preallocate interface context storage, if another interface 1634 * attaches and wins the race, it won't be eligible for bootp. 1635 */ 1636 IFNET_RLOCK(); 1637 for (ifp = TAILQ_FIRST(&V_ifnet), ifcnt = 0; |
1709 ifp != NULL; 1710 ifp = TAILQ_NEXT(ifp, if_link)) { | 1638 ifp != NULL; 1639 ifp = TAILQ_NEXT(ifp, if_link)) { |
1711 snprintf(ifctx->ireq.ifr_name, sizeof(ifctx->ireq.ifr_name), 1712 "%s%d", ifp->if_name, ifp->if_unit); | 1640 if ((ifp->if_flags & 1641 (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) != 1642 IFF_BROADCAST) 1643 continue; 1644 ifcnt++; 1645 } 1646 IFNET_RUNLOCK(); 1647 if (ifcnt == 0) 1648 panic("bootpc_init: no eligible interfaces"); 1649 for (; ifcnt > 0; ifcnt--) 1650 allocifctx(gctx); 1651#endif 1652 1653 IFNET_RLOCK(); 1654 for (ifp = TAILQ_FIRST(&V_ifnet), ifctx = gctx->interfaces; 1655 ifp != NULL && ifctx != NULL; 1656 ifp = TAILQ_NEXT(ifp, if_link)) { 1657 strlcpy(ifctx->ireq.ifr_name, ifp->if_xname, 1658 sizeof(ifctx->ireq.ifr_name)); |
1713#ifdef BOOTP_WIRED_TO 1714 if (strcmp(ifctx->ireq.ifr_name, 1715 __XSTRING(BOOTP_WIRED_TO)) != 0) 1716 continue; 1717#else 1718 if ((ifp->if_flags & 1719 (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) != 1720 IFF_BROADCAST) 1721 continue; 1722#endif | 1659#ifdef BOOTP_WIRED_TO 1660 if (strcmp(ifctx->ireq.ifr_name, 1661 __XSTRING(BOOTP_WIRED_TO)) != 0) 1662 continue; 1663#else 1664 if ((ifp->if_flags & 1665 (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) != 1666 IFF_BROADCAST) 1667 continue; 1668#endif |
1723 if (gctx->interfaces != NULL) 1724 gctx->lastinterface->next = ifctx; 1725 else 1726 gctx->interfaces = ifctx; | |
1727 ifctx->ifp = ifp; | 1669 ifctx->ifp = ifp; |
1728 gctx->lastinterface = ifctx; 1729 ifctx = allocifctx(gctx); | 1670 ifctx = ifctx->next; |
1730 } | 1671 } |
1731 free(ifctx, M_TEMP); 1732 1733 if (gctx->interfaces == NULL) { | 1672 IFNET_RUNLOCK(); 1673 CURVNET_RESTORE(); 1674 1675 if (gctx->interfaces == NULL || gctx->interfaces->ifp == NULL) { |
1734#ifdef BOOTP_WIRED_TO 1735 panic("bootpc_init: Could not find interface specified " 1736 "by BOOTP_WIRED_TO: " 1737 __XSTRING(BOOTP_WIRED_TO)); 1738#else 1739 panic("bootpc_init: no suitable interface"); 1740#endif 1741 } | 1676#ifdef BOOTP_WIRED_TO 1677 panic("bootpc_init: Could not find interface specified " 1678 "by BOOTP_WIRED_TO: " 1679 __XSTRING(BOOTP_WIRED_TO)); 1680#else 1681 panic("bootpc_init: no suitable interface"); 1682#endif 1683 } |
1742 1743 gctx->gotrootpath = 0; 1744 gctx->gotswappath = 0; 1745 gctx->gotgw = 0; 1746 | 1684 |
1747 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) 1748 bootpc_fakeup_interface(ifctx, gctx, td); | 1685 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) 1686 bootpc_fakeup_interface(ifctx, gctx, td); |
1749 | 1687 |
1750 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) 1751 bootpc_compose_query(ifctx, gctx, td); | 1688 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) 1689 bootpc_compose_query(ifctx, gctx, td); |
1752 1753 ifctx = gctx->interfaces; | 1690 |
1754 error = bootpc_call(gctx, td); | 1691 error = bootpc_call(gctx, td); |
1755 | 1692 |
1756 if (error != 0) { 1757#ifdef BOOTP_NFSROOT 1758 panic("BOOTP call failed"); 1759#else 1760 printf("BOOTP call failed\n"); 1761#endif 1762 } | 1693 if (error != 0) { 1694#ifdef BOOTP_NFSROOT 1695 panic("BOOTP call failed"); 1696#else 1697 printf("BOOTP call failed\n"); 1698#endif 1699 } |
1763 | 1700 1701 rootdevnames[0] = "nfs:"; |
1764 mountopts(&nd->root_args, NULL); | 1702 mountopts(&nd->root_args, NULL); |
1765 1766 mountopts(&nd->swap_args, NULL); | |
1767 1768 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) 1769 if (bootpc_ifctx_isresolved(ifctx) != 0) 1770 bootpc_decode_reply(nd, ifctx, gctx); | 1703 1704 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) 1705 if (bootpc_ifctx_isresolved(ifctx) != 0) 1706 bootpc_decode_reply(nd, ifctx, gctx); |
1771 1772 if (gctx->gotswappath == 0) 1773 nd->swap_nblks = 0; | 1707 |
1774#ifdef BOOTP_NFSROOT 1775 if (gctx->gotrootpath == 0) 1776 panic("bootpc: No root path offered"); 1777#endif | 1708#ifdef BOOTP_NFSROOT 1709 if (gctx->gotrootpath == 0) 1710 panic("bootpc: No root path offered"); 1711#endif |
1778 | 1712 |
1779 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) { 1780 bootpc_adjust_interface(ifctx, gctx, td); | 1713 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) { 1714 bootpc_adjust_interface(ifctx, gctx, td); |
1781 | 1715 |
1782 soclose(ifctx->so); 1783 } 1784 1785 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) 1786 if (ifctx->gotrootpath != 0) 1787 break; 1788 if (ifctx == NULL) { 1789 for (ifctx = gctx->interfaces; 1790 ifctx != NULL; 1791 ifctx = ifctx->next) 1792 if (bootpc_ifctx_isresolved(ifctx) != 0) 1793 break; 1794 } 1795 if (ifctx == NULL) 1796 goto out; | 1716 soclose(ifctx->so); 1717 } 1718 1719 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) 1720 if (ifctx->gotrootpath != 0) 1721 break; 1722 if (ifctx == NULL) { 1723 for (ifctx = gctx->interfaces; 1724 ifctx != NULL; 1725 ifctx = ifctx->next) 1726 if (bootpc_ifctx_isresolved(ifctx) != 0) 1727 break; 1728 } 1729 if (ifctx == NULL) 1730 goto out; |
1797 | 1731 |
1798 if (gctx->gotrootpath != 0) { | 1732 if (gctx->gotrootpath != 0) { |
1799 | 1733 1734 setenv("boot.netif.name", ifctx->ifp->if_xname); 1735 |
1800 error = md_mount(&nd->root_saddr, nd->root_hostnam, 1801 nd->root_fh, &nd->root_fhsize, 1802 &nd->root_args, td); 1803 if (error != 0) 1804 panic("nfs_boot: mountd root, error=%d", error); | 1736 error = md_mount(&nd->root_saddr, nd->root_hostnam, 1737 nd->root_fh, &nd->root_fhsize, 1738 &nd->root_args, td); 1739 if (error != 0) 1740 panic("nfs_boot: mountd root, error=%d", error); |
1805 1806 if (gctx->gotswappath != 0) { 1807 1808 error = md_mount(&nd->swap_saddr, 1809 nd->swap_hostnam, 1810 nd->swap_fh, &nd->swap_fhsize, 1811 &nd->swap_args, td); 1812 if (error != 0) 1813 panic("nfs_boot: mountd swap, error=%d", 1814 error); 1815 1816 error = md_lookup_swap(&nd->swap_saddr, 1817 gctx->lookup_path, 1818 nd->swap_fh, &nd->swap_fhsize, 1819 &nd->swap_args, td); 1820 if (error != 0) 1821 panic("nfs_boot: lookup swap, error=%d", 1822 error); 1823 } | 1741 |
1824 nfs_diskless_valid = 3; 1825 } | 1742 nfs_diskless_valid = 3; 1743 } |
1826 | 1744 |
1827 strcpy(nd->myif.ifra_name, ifctx->ireq.ifr_name); 1828 bcopy(&ifctx->myaddr, &nd->myif.ifra_addr, sizeof(ifctx->myaddr)); 1829 bcopy(&ifctx->myaddr, &nd->myif.ifra_broadaddr, sizeof(ifctx->myaddr)); 1830 ((struct sockaddr_in *) &nd->myif.ifra_broadaddr)->sin_addr.s_addr = 1831 ifctx->myaddr.sin_addr.s_addr | 1832 ~ ifctx->netmask.sin_addr.s_addr; 1833 bcopy(&ifctx->netmask, &nd->myif.ifra_mask, sizeof(ifctx->netmask)); | 1745 strcpy(nd->myif.ifra_name, ifctx->ireq.ifr_name); 1746 bcopy(&ifctx->myaddr, &nd->myif.ifra_addr, sizeof(ifctx->myaddr)); 1747 bcopy(&ifctx->myaddr, &nd->myif.ifra_broadaddr, sizeof(ifctx->myaddr)); 1748 ((struct sockaddr_in *) &nd->myif.ifra_broadaddr)->sin_addr.s_addr = 1749 ifctx->myaddr.sin_addr.s_addr | 1750 ~ ifctx->netmask.sin_addr.s_addr; 1751 bcopy(&ifctx->netmask, &nd->myif.ifra_mask, sizeof(ifctx->netmask)); |
1834 | 1752 |
1835out: 1836 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = nctx) { 1837 nctx = ifctx->next; 1838 free(ifctx, M_TEMP); 1839 } 1840 free(gctx, M_TEMP); 1841} 1842 | 1753out: 1754 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = nctx) { 1755 nctx = ifctx->next; 1756 free(ifctx, M_TEMP); 1757 } 1758 free(gctx, M_TEMP); 1759} 1760 |
1843 | |
1844/* 1845 * RPC: mountd/mount 1846 * Given a server pathname, get an NFS file handle. 1847 * Also, sets sin->sin_port to the NFS service port. 1848 */ 1849static int | 1761/* 1762 * RPC: mountd/mount 1763 * Given a server pathname, get an NFS file handle. 1764 * Also, sets sin->sin_port to the NFS service port. 1765 */ 1766static int |
1850md_mount(struct sockaddr_in *mdsin, /* mountd server address */ 1851 char *path, 1852 u_char *fhp, 1853 int *fhsizep, 1854 struct nfs_args *args, 1855 struct thread *td) | 1767md_mount(struct sockaddr_in *mdsin, char *path, u_char *fhp, int *fhsizep, 1768 struct nfs_args *args, struct thread *td) |
1856{ 1857 struct mbuf *m; 1858 int error; 1859 int authunixok; 1860 int authcount; 1861 int authver; | 1769{ 1770 struct mbuf *m; 1771 int error; 1772 int authunixok; 1773 int authcount; 1774 int authver; |
1862 | 1775 1776#define RPCPROG_MNT 100005 1777#define RPCMNT_VER1 1 1778#define RPCMNT_VER3 3 1779#define RPCMNT_MOUNT 1 1780#define AUTH_SYS 1 /* unix style (uid, gids) */ 1781#define AUTH_UNIX AUTH_SYS 1782 1783 /* XXX honor v2/v3 flags in args->flags? */ |
1863#ifdef BOOTP_NFSV3 1864 /* First try NFS v3 */ 1865 /* Get port number for MOUNTD. */ 1866 error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER3, 1867 &mdsin->sin_port, td); 1868 if (error == 0) { 1869 m = xdr_string_encode(path, strlen(path)); | 1784#ifdef BOOTP_NFSV3 1785 /* First try NFS v3 */ 1786 /* Get port number for MOUNTD. */ 1787 error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER3, 1788 &mdsin->sin_port, td); 1789 if (error == 0) { 1790 m = xdr_string_encode(path, strlen(path)); |
1870 | 1791 |
1871 /* Do RPC to mountd. */ 1872 error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER3, 1873 RPCMNT_MOUNT, &m, NULL, td); 1874 } 1875 if (error == 0) { 1876 args->flags |= NFSMNT_NFSV3; 1877 } else { 1878#endif 1879 /* Fallback to NFS v2 */ | 1792 /* Do RPC to mountd. */ 1793 error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER3, 1794 RPCMNT_MOUNT, &m, NULL, td); 1795 } 1796 if (error == 0) { 1797 args->flags |= NFSMNT_NFSV3; 1798 } else { 1799#endif 1800 /* Fallback to NFS v2 */ |
1880 | 1801 |
1881 /* Get port number for MOUNTD. */ 1882 error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1, 1883 &mdsin->sin_port, td); 1884 if (error != 0) 1885 return error; | 1802 /* Get port number for MOUNTD. */ 1803 error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1, 1804 &mdsin->sin_port, td); 1805 if (error != 0) 1806 return error; |
1886 | 1807 |
1887 m = xdr_string_encode(path, strlen(path)); | 1808 m = xdr_string_encode(path, strlen(path)); |
1888 | 1809 |
1889 /* Do RPC to mountd. */ 1890 error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1, 1891 RPCMNT_MOUNT, &m, NULL, td); 1892 if (error != 0) 1893 return error; /* message already freed */ | 1810 /* Do RPC to mountd. */ 1811 error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1, 1812 RPCMNT_MOUNT, &m, NULL, td); 1813 if (error != 0) 1814 return error; /* message already freed */ |
1894 | 1815 |
1895#ifdef BOOTP_NFSV3 1896 } 1897#endif 1898 1899 if (xdr_int_decode(&m, &error) != 0 || error != 0) 1900 goto bad; | 1816#ifdef BOOTP_NFSV3 1817 } 1818#endif 1819 1820 if (xdr_int_decode(&m, &error) != 0 || error != 0) 1821 goto bad; |
1901 | 1822 |
1902 if ((args->flags & NFSMNT_NFSV3) != 0) { 1903 if (xdr_int_decode(&m, fhsizep) != 0 || 1904 *fhsizep > NFSX_V3FHMAX || 1905 *fhsizep <= 0) 1906 goto bad; 1907 } else 1908 *fhsizep = NFSX_V2FH; 1909 --- 4 unchanged lines hidden (view full) --- 1914 if (xdr_int_decode(&m, &authcount) != 0) 1915 goto bad; 1916 authunixok = 0; 1917 if (authcount < 0 || authcount > 100) 1918 goto bad; 1919 while (authcount > 0) { 1920 if (xdr_int_decode(&m, &authver) != 0) 1921 goto bad; | 1823 if ((args->flags & NFSMNT_NFSV3) != 0) { 1824 if (xdr_int_decode(&m, fhsizep) != 0 || 1825 *fhsizep > NFSX_V3FHMAX || 1826 *fhsizep <= 0) 1827 goto bad; 1828 } else 1829 *fhsizep = NFSX_V2FH; 1830 --- 4 unchanged lines hidden (view full) --- 1835 if (xdr_int_decode(&m, &authcount) != 0) 1836 goto bad; 1837 authunixok = 0; 1838 if (authcount < 0 || authcount > 100) 1839 goto bad; 1840 while (authcount > 0) { 1841 if (xdr_int_decode(&m, &authver) != 0) 1842 goto bad; |
1922 if (authver == RPCAUTH_UNIX) | 1843 if (authver == AUTH_UNIX) |
1923 authunixok = 1; 1924 authcount--; 1925 } 1926 if (authunixok == 0) 1927 goto bad; 1928 } | 1844 authunixok = 1; 1845 authcount--; 1846 } 1847 if (authunixok == 0) 1848 goto bad; 1849 } |
1929 | 1850 |
1930 /* Set port number for NFS use. */ 1931 error = krpc_portmap(mdsin, NFS_PROG, 1932 (args->flags & 1933 NFSMNT_NFSV3) ? NFS_VER3 : NFS_VER2, 1934 &mdsin->sin_port, td); | 1851 /* Set port number for NFS use. */ 1852 error = krpc_portmap(mdsin, NFS_PROG, 1853 (args->flags & 1854 NFSMNT_NFSV3) ? NFS_VER3 : NFS_VER2, 1855 &mdsin->sin_port, td); |
1935 1936 goto out; 1937 1938bad: 1939 error = EBADRPC; 1940 1941out: 1942 m_freem(m); 1943 return error; 1944} | |
1945 | 1856 |
1946 1947static int 1948md_lookup_swap(struct sockaddr_in *mdsin, /* mountd server address */ 1949 char *path, 1950 u_char *fhp, 1951 int *fhsizep, 1952 struct nfs_args *args, 1953 struct thread *td) 1954{ 1955 struct mbuf *m; 1956 int error; 1957 int size = -1; 1958 int attribs_present; 1959 int status; 1960 union { 1961 u_int32_t v2[17]; 1962 u_int32_t v3[21]; 1963 } fattribs; 1964 1965 m = m_get(M_TRYWAIT,MT_DATA); 1966 if (m == NULL) 1967 return ENOBUFS; 1968 1969 if ((args->flags & NFSMNT_NFSV3) != 0) { 1970 *mtod(m, u_int32_t *) = txdr_unsigned(*fhsizep); 1971 bcopy(fhp, mtod(m, u_char *) + sizeof(u_int32_t), *fhsizep); 1972 m->m_len = *fhsizep + sizeof(u_int32_t); 1973 } else { 1974 bcopy(fhp, mtod(m, u_char *), NFSX_V2FH); 1975 m->m_len = NFSX_V2FH; 1976 } 1977 1978 m->m_next = xdr_string_encode(path, strlen(path)); 1979 if (m->m_next == NULL) { 1980 error = ENOBUFS; 1981 goto out; 1982 } 1983 1984 /* Do RPC to nfsd. */ 1985 if ((args->flags & NFSMNT_NFSV3) != 0) 1986 error = krpc_call(mdsin, NFS_PROG, NFS_VER3, 1987 NFSPROC_LOOKUP, &m, NULL, td); 1988 else 1989 error = krpc_call(mdsin, NFS_PROG, NFS_VER2, 1990 NFSV2PROC_LOOKUP, &m, NULL, td); 1991 if (error != 0) 1992 return error; /* message already freed */ 1993 1994 if (xdr_int_decode(&m, &status) != 0) 1995 goto bad; 1996 if (status != 0) { 1997 error = ENOENT; 1998 goto out; 1999 } 2000 2001 if ((args->flags & NFSMNT_NFSV3) != 0) { 2002 if (xdr_int_decode(&m, fhsizep) != 0 || 2003 *fhsizep > NFSX_V3FHMAX || 2004 *fhsizep <= 0) 2005 goto bad; 2006 } else 2007 *fhsizep = NFSX_V2FH; 2008 2009 if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0) 2010 goto bad; 2011 2012 if ((args->flags & NFSMNT_NFSV3) != 0) { 2013 if (xdr_int_decode(&m, &attribs_present) != 0) 2014 goto bad; 2015 if (attribs_present != 0) { 2016 if (xdr_opaque_decode(&m, (u_char *) &fattribs.v3, 2017 sizeof(u_int32_t) * 21) != 0) 2018 goto bad; 2019 size = fxdr_unsigned(u_int32_t, fattribs.v3[6]); 2020 } 2021 } else { 2022 if (xdr_opaque_decode(&m,(u_char *) &fattribs.v2, 2023 sizeof(u_int32_t) * 17) != 0) 2024 goto bad; 2025 size = fxdr_unsigned(u_int32_t, fattribs.v2[5]); 2026 } 2027 2028 if (nfsv3_diskless.swap_nblks == 0 && size != -1) { 2029 nfsv3_diskless.swap_nblks = size / 1024; 2030 printf("md_lookup_swap: Swap size is %d KB\n", 2031 nfsv3_diskless.swap_nblks); 2032 } 2033 | |
2034 goto out; | 1857 goto out; |
2035 | 1858 |
2036bad: 2037 error = EBADRPC; | 1859bad: 1860 error = EBADRPC; |
2038 | 1861 |
2039out: 2040 m_freem(m); 2041 return error; 2042} | 1862out: 1863 m_freem(m); 1864 return error; 1865} |
1866 1867SYSINIT(bootp_rootconf, SI_SUB_ROOT_CONF, SI_ORDER_FIRST, bootpc_init, NULL); |
|