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);