4 * Copyright (c) 1995 Gordon Ross, Adam Glass
5 * Copyright (c) 1992 Regents of the University of California.
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.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the University of
23 * California, Lawrence Berkeley Laboratory and its contributors.
24 * 4. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 * $NetBSD: krpc_subr.c,v 1.10 1995/08/08 20:43:43 gwr Exp $
45 #include "opt_bootp.h"
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/kernel.h>
50 #include <sys/sockio.h>
52 #include <sys/mount.h>
54 #include <sys/socket.h>
55 #include <sys/socketvar.h>
59 #include <net/route.h>
61 #include <netinet/in.h>
62 #include <net/if_types.h>
63 #include <net/if_dl.h>
65 #include <nfs/rpcv2.h>
66 #include <nfs/nfsproto.h>
68 #include <nfs/nfsdiskless.h>
70 #include <nfs/xdr_subs.h>
73 #define BOOTP_MIN_LEN 300 /* Minimum size of bootp udp packet */
76 * What is the longest we will wait before re-sending a request?
77 * Note this is also the frequency of "RPC timeout" messages.
78 * The re-send loop count sup linearly to this maximum, so the
79 * first complaint will happen after (1+2+3+4+5)=15 seconds.
81 #define MAX_RESEND_DELAY 5 /* seconds */
83 /* Definitions from RFC951 */
92 struct in_addr ciaddr;
93 struct in_addr yiaddr;
94 struct in_addr siaddr;
95 struct in_addr giaddr;
96 unsigned char chaddr[16];
99 unsigned char vend[256];
102 #define IPPORT_BOOTPC 68
103 #define IPPORT_BOOTPS 67
105 extern int nfs_diskless_valid;
106 extern struct nfsv3_diskless nfsv3_diskless;
109 static int md_mount(struct sockaddr_in *mdsin, char *path,
110 u_char *fhp, int *fhsizep,
111 struct nfs_args *args,struct proc *procp);
112 static int md_lookup_swap(struct sockaddr_in *mdsin,char *path,
113 u_char *fhp, int *fhsizep,
114 struct nfs_args *args,
116 static int setfs(struct sockaddr_in *addr, char *path, char *p);
117 static int getdec(char **ptr);
118 static char *substr(char *a,char *b);
119 static void mountopts(struct nfs_args *args, char *p);
120 static int xdr_opaque_decode(struct mbuf **ptr, u_char *buf, int len);
121 static int xdr_int_decode(struct mbuf **ptr, int *iptr);
122 static void printip(char *prefix, struct in_addr addr);
125 void bootpboot_p_sa(struct sockaddr *sa,struct sockaddr *ma);
126 void bootpboot_p_ma(struct sockaddr *ma);
127 void bootpboot_p_rtentry(struct rtentry *rt);
128 void bootpboot_p_tree(struct radix_node *rn);
129 void bootpboot_p_rtlist(void);
130 void bootpboot_p_iflist(void);
133 static int bootpc_call(struct bootp_packet *call,
134 struct bootp_packet *reply,
137 static int bootpc_fakeup_interface(struct ifreq *ireq,
141 static int bootpc_adjust_interface(struct ifreq *ireq,
143 struct sockaddr_in *myaddr,
144 struct sockaddr_in *netmask,
145 struct sockaddr_in *gw,
148 void bootpc_init(void);
152 bootpboot_p_sa(struct sockaddr *sa,
156 printf("(sockaddr *) <null>");
159 switch (sa->sa_family) {
162 struct sockaddr_in *sin;
164 sin = (struct sockaddr_in *) sa;
165 printf("inet %x", ntohl(sin->sin_addr.s_addr));
167 sin = (struct sockaddr_in *) ma;
168 printf(" mask %x", ntohl(sin->sin_addr.s_addr));
174 struct sockaddr_dl *sli;
177 sli = (struct sockaddr_dl *) sa;
178 printf("link %.*s ", sli->sdl_nlen, sli->sdl_data);
179 for (i = 0; i < sli->sdl_alen; i++) {
182 printf("%x", ((unsigned char *) LLADDR(sli))[i]);
187 printf("af%d", sa->sa_family);
193 bootpboot_p_ma(struct sockaddr *ma)
199 printf("%x", *(int *)ma);
204 bootpboot_p_rtentry(struct rtentry *rt)
206 bootpboot_p_sa(rt_key(rt), rt_mask(rt));
208 bootpboot_p_ma(rt->rt_genmask);
210 bootpboot_p_sa(rt->rt_gateway, NULL);
212 printf("flags %x", (unsigned short) rt->rt_flags);
213 printf(" %d", (int) rt->rt_rmx.rmx_expire);
214 printf(" %s%d\n", rt->rt_ifp->if_name, rt->rt_ifp->if_unit);
219 bootpboot_p_tree(struct radix_node *rn)
222 if (rn->rn_bit < 0) {
223 if ((rn->rn_flags & RNF_ROOT) != 0) {
225 bootpboot_p_rtentry((struct rtentry *) rn);
227 rn = rn->rn_dupedkey;
229 bootpboot_p_tree(rn->rn_left);
230 bootpboot_p_tree(rn->rn_right);
238 bootpboot_p_rtlist(void)
240 printf("Routing table:\n");
241 bootpboot_p_tree(rt_tables[AF_INET]->rnh_treetop);
245 bootpboot_p_iflist(void)
250 printf("Interface list:\n");
251 for (ifp = TAILQ_FIRST(&ifnet);
253 ifp = TAILQ_NEXT(ifp,if_link)) {
254 for (ifa = TAILQ_FIRST(&ifp->if_addrhead);
256 ifa = TAILQ_NEXT(ifa,ifa_link))
257 if (ifa->ifa_addr->sa_family == AF_INET) {
258 printf("%s%d flags %x, addr %x, bcast %x, net %x\n",
259 ifp->if_name, ifp->if_unit,
260 (unsigned short) ifp->if_flags,
261 ntohl(((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr),
262 ntohl(((struct sockaddr_in *) ifa->ifa_dstaddr)->sin_addr.s_addr),
263 ntohl(((struct sockaddr_in *) ifa->ifa_netmask)->sin_addr.s_addr)
271 bootpc_call(struct bootp_packet *call,
272 struct bootp_packet *reply, /* output */
276 struct sockaddr_in *sin, sa;
281 int error, on, len, rcvflg, secs, timo;
284 * Create socket and set its recieve timeout.
286 if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0,procp)))
291 bzero(&sopt, sizeof sopt);
292 sopt.sopt_level = SOL_SOCKET;
293 sopt.sopt_name = SO_RCVTIMEO;
295 sopt.sopt_valsize = sizeof tv;
297 if ((error = sosetopt(so, &sopt)) != 0)
305 sopt.sopt_valsize = sizeof on;
306 sopt.sopt_name = SO_BROADCAST;
307 if ((error = sosetopt(so, &sopt)) != 0)
311 * Bind the local endpoint to a bootp client port.
314 bzero(sin, sizeof *sin);
315 sin->sin_len = sizeof(*sin);
316 sin->sin_family = AF_INET;
317 sin->sin_addr.s_addr = INADDR_ANY;
318 sin->sin_port = htons(IPPORT_BOOTPC);
319 error = sobind(so, (struct sockaddr *)sin, procp);
321 printf("bind failed\n");
326 * Setup socket address for the server.
329 bzero(sin, sizeof *sin);
330 sin->sin_len = sizeof(*sin);
331 sin->sin_family = AF_INET;
332 sin->sin_addr.s_addr = INADDR_BROADCAST;
333 sin->sin_port = htons(IPPORT_BOOTPS);
336 * Send it, repeatedly, until a reply is received,
337 * but delay each re-send by an increasing amount.
338 * If the delay hits the maximum, start complaining.
342 /* Send BOOTP request (or re-send). */
344 aio.iov_base = (caddr_t) call;
345 aio.iov_len = sizeof(*call);
349 auio.uio_segflg = UIO_SYSSPACE;
350 auio.uio_rw = UIO_WRITE;
352 auio.uio_resid = sizeof(*call);
353 auio.uio_procp = procp;
355 error = sosend(so, (struct sockaddr *)sin, &auio, NULL,
358 printf("bootpc_call: sosend: %d state %08x\n",
359 error, (int)so->so_state);
363 /* Determine new timeout. */
364 if (timo < MAX_RESEND_DELAY)
367 printf("BOOTP timeout for server 0x%lx\n",
368 (u_long)ntohl(sin->sin_addr.s_addr));
371 * Wait for up to timo seconds for a reply.
372 * The socket receive timeout was set to 1 second.
376 aio.iov_base = (caddr_t) reply;
377 aio.iov_len = sizeof(*reply);
381 auio.uio_segflg = UIO_SYSSPACE;
382 auio.uio_rw = UIO_READ;
384 auio.uio_resid = sizeof(*reply);
385 auio.uio_procp = procp;
388 error = soreceive(so, NULL, &auio,
389 NULL, NULL, &rcvflg);
390 if (error == EWOULDBLOCK) {
392 call->secs = htons(ntohs(call->secs) + 1);
397 len = sizeof(*reply) - auio.uio_resid;
399 /* Do we have the required number of bytes ? */
400 if (len < BOOTP_MIN_LEN)
403 /* Is it the right reply? */
407 if (reply->xid != call->xid)
410 if (reply->hlen != call->hlen)
413 if (bcmp(reply->chaddr,call->chaddr,call->hlen))
416 goto gotreply; /* break two levels */
419 } /* forever send/receive */
431 bootpc_fakeup_interface(struct ifreq *ireq,
435 struct sockaddr_in *sin;
437 struct sockaddr_in dst;
438 struct sockaddr_in gw;
439 struct sockaddr_in mask;
442 * Bring up the interface.
444 * Get the old interface flags and or IFF_UP into them; if
445 * IFF_UP set blindly, interface selection can be clobbered.
447 error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, procp);
449 panic("bootpc_fakeup_interface: GIFFLAGS, error=%d", error);
450 ireq->ifr_flags |= IFF_UP;
451 error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, procp);
453 panic("bootpc_fakeup_interface: SIFFLAGS, error=%d", error);
456 * Do enough of ifconfig(8) so that the chosen interface
457 * can talk to the servers. (just set the address)
460 /* addr is 0.0.0.0 */
462 sin = (struct sockaddr_in *)&ireq->ifr_addr;
463 bzero((caddr_t)sin, sizeof(*sin));
464 sin->sin_len = sizeof(*sin);
465 sin->sin_family = AF_INET;
466 sin->sin_addr.s_addr = INADDR_ANY;
467 error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp);
469 panic("bootpc_fakeup_interface: set if addr, error=%d", error);
471 /* netmask is 0.0.0.0 */
473 sin = (struct sockaddr_in *)&ireq->ifr_addr;
474 bzero((caddr_t)sin, sizeof(*sin));
475 sin->sin_len = sizeof(*sin);
476 sin->sin_family = AF_INET;
477 sin->sin_addr.s_addr = INADDR_ANY;
478 error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp);
480 panic("bootpc_fakeup_interface: set if net addr, error=%d", error);
482 /* Broadcast is 255.255.255.255 */
484 sin = (struct sockaddr_in *)&ireq->ifr_addr;
485 bzero((caddr_t)sin, sizeof(*sin));
486 sin->sin_len = sizeof(*sin);
487 sin->sin_family = AF_INET;
488 sin->sin_addr.s_addr = INADDR_BROADCAST;
489 error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp);
491 panic("bootpc_fakeup_interface: set if broadcast addr, error=%d", error);
493 /* Add default route to 0.0.0.0 so we can send data */
495 bzero((caddr_t) &dst, sizeof(dst));
496 dst.sin_len = sizeof(dst);
497 dst.sin_family = AF_INET;
498 dst.sin_addr.s_addr = htonl(0);
500 bzero((caddr_t) &gw, sizeof(gw));
501 gw.sin_len = sizeof(gw);
502 gw.sin_family = AF_INET;
503 gw.sin_addr.s_addr = htonl(0x0);
505 bzero((caddr_t) &mask, sizeof(mask));
506 mask.sin_len = sizeof(mask);
507 mask.sin_family = AF_INET;
508 mask.sin_addr.s_addr = htonl(0);
510 error = rtrequest(RTM_ADD,
511 (struct sockaddr *) &dst,
512 (struct sockaddr *) &gw,
513 (struct sockaddr *) &mask,
517 printf("bootpc_fakeup_interface: add default route, error=%d\n", error);
522 bootpc_adjust_interface(struct ifreq *ireq,struct socket *so,
523 struct sockaddr_in *myaddr,
524 struct sockaddr_in *netmask,
525 struct sockaddr_in *gw,
529 struct sockaddr_in oldgw;
530 struct sockaddr_in olddst;
531 struct sockaddr_in oldmask;
532 struct sockaddr_in *sin;
534 /* Remove old default route to 0.0.0.0 */
536 bzero((caddr_t) &olddst, sizeof(olddst));
537 olddst.sin_len = sizeof(olddst);
538 olddst.sin_family = AF_INET;
539 olddst.sin_addr.s_addr = INADDR_ANY;
541 bzero((caddr_t) &oldgw, sizeof(oldgw));
542 oldgw.sin_len = sizeof(oldgw);
543 oldgw.sin_family = AF_INET;
544 oldgw.sin_addr.s_addr = INADDR_ANY;
546 bzero((caddr_t) &oldmask, sizeof(oldmask));
547 oldmask.sin_len = sizeof(oldmask);
548 oldmask.sin_family = AF_INET;
549 oldmask.sin_addr.s_addr = INADDR_ANY;
551 error = rtrequest(RTM_DELETE,
552 (struct sockaddr *) &olddst,
553 (struct sockaddr *) &oldgw,
554 (struct sockaddr *) &oldmask,
555 (RTF_UP | RTF_STATIC), NULL);
557 printf("nfs_boot: del default route, error=%d\n", error);
562 * Do enough of ifconfig(8) so that the chosen interface
563 * can talk to the servers. (just set the address)
565 bcopy(netmask, &ireq->ifr_addr, sizeof(*netmask));
566 error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp);
568 panic("nfs_boot: set if netmask, error=%d", error);
570 /* Broadcast is with host part of IP address all 1's */
572 sin = (struct sockaddr_in *)&ireq->ifr_addr;
573 bzero((caddr_t)sin, sizeof(*sin));
574 sin->sin_len = sizeof(*sin);
575 sin->sin_family = AF_INET;
576 sin->sin_addr.s_addr = myaddr->sin_addr.s_addr |
577 ~ netmask->sin_addr.s_addr;
578 error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp);
580 panic("bootpc_call: set if broadcast addr, error=%d", error);
582 bcopy(myaddr, &ireq->ifr_addr, sizeof(*myaddr));
583 error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp);
585 panic("nfs_boot: set if addr, error=%d", error);
587 /* Add new default route */
589 error = rtrequest(RTM_ADD,
590 (struct sockaddr *) &olddst,
591 (struct sockaddr *) gw,
592 (struct sockaddr *) &oldmask,
593 (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL);
595 printf("nfs_boot: add net route, error=%d\n", error);
604 setfs(struct sockaddr_in *addr, char *path, char *p)
610 if (((val = getdec(&p)) < 0) || (val > 255))
616 if (((val = getdec(&p)) < 0) || (val > 255))
622 if (((val = getdec(&p)) < 0) || (val > 255))
628 if (((val = getdec(&p)) < 0) || (val > 255))
635 addr->sin_addr.s_addr = htonl(ip);
636 addr->sin_len = sizeof(struct sockaddr_in);
637 addr->sin_family = AF_INET;
639 strncpy(path, p, MNAMELEN - 1);
652 if ((*p < '0') || (*p > '9'))
654 while ((*p >= '0') && (*p <= '9')) {
655 ret = ret * 10 + (*p - '0');
664 substr(char *a, char *b)
672 while (*loc1 == *loc2++) {
686 mountopts(struct nfs_args *args, char *p)
690 args->flags = NFSMNT_RSIZE | NFSMNT_WSIZE | NFSMNT_RESVPORT;
691 args->sotype = SOCK_DGRAM;
692 if ((tmp = (char *)substr(p, "rsize=")))
693 args->rsize = getdec(&tmp);
694 if ((tmp = (char *)substr(p, "wsize=")))
695 args->wsize = getdec(&tmp);
696 if ((tmp = (char *)substr(p, "intr")))
697 args->flags |= NFSMNT_INT;
698 if ((tmp = (char *)substr(p, "soft")))
699 args->flags |= NFSMNT_SOFT;
700 if ((tmp = (char *)substr(p, "noconn")))
701 args->flags |= NFSMNT_NOCONN;
702 if ((tmp = (char *)substr(p, "tcp")))
703 args->sotype = SOCK_STREAM;
708 xdr_opaque_decode(struct mbuf **mptr, u_char *buf, int len)
714 alignedlen = ( len + 3 ) & ~3;
716 if (m->m_len < alignedlen) {
717 m = m_pullup(m, alignedlen);
723 bcopy(mtod(m, u_char *), buf, len);
724 m_adj(m, alignedlen);
731 xdr_int_decode(struct mbuf **mptr, int *iptr)
734 if (xdr_opaque_decode(mptr, (u_char *) &i, sizeof(u_int32_t)) != 0)
736 *iptr = fxdr_unsigned(u_int32_t, i);
742 printip(char *prefix, struct in_addr addr)
746 ip = ntohl(addr.s_addr);
748 printf("%s is %d.%d.%d.%d\n", prefix,
749 ip >> 24, (ip >> 16) & 255, (ip >> 8) & 255, ip & 255);
756 struct bootp_packet call;
757 struct bootp_packet reply;
758 static u_int32_t xid = ~0xFF;
769 struct sockaddr_in myaddr;
770 struct sockaddr_in netmask;
771 struct sockaddr_in gw;
776 char lookup_path[24];
780 struct sockaddr_dl *sdl;
783 struct nfsv3_diskless *nd;
791 nd = &nfsv3_diskless;
795 * If already filled in, don't touch it here
797 if (nfs_diskless_valid != 0)
801 * Wait until arp entries can be handled.
803 while (time_second == 0)
804 tsleep(&time_second, PZERO + 8, "arpkludge", 10);
807 * Find a network interface.
809 #ifdef BOOTP_WIRED_TO
810 printf("bootpc_init: wired to interface '%s'\n",
811 __XSTRING(BOOTP_WIRED_TO));
813 bzero(&ireq, sizeof(ireq));
814 for (ifp = TAILQ_FIRST(&ifnet);
816 ifp = TAILQ_NEXT(ifp,if_link))
818 snprintf(ireq.ifr_name, sizeof(ireq.ifr_name),
819 "%s%d", ifp->if_name, ifp->if_unit);
820 #ifdef BOOTP_WIRED_TO
821 if (strcmp(ireq.ifr_name, __XSTRING(BOOTP_WIRED_TO)) == 0)
825 (IFF_LOOPBACK | IFF_POINTOPOINT)) == 0)
830 panic("bootpc_init: no suitable interface");
831 strcpy(nd->myif.ifra_name, ireq.ifr_name);
832 printf("bootpc_init: using network interface '%s'\n",
835 if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0, procp)) != 0)
836 panic("nfs_boot: socreate, error=%d", error);
838 bootpc_fakeup_interface(&ireq, so, procp);
840 printf("Bootpc testing starting\n");
844 for (ifa = TAILQ_FIRST(&ifp->if_addrhead);
846 ifa = TAILQ_NEXT(ifa,ifa_link))
847 if (ifa->ifa_addr->sa_family == AF_LINK &&
848 (sdl = ((struct sockaddr_dl *) ifa->ifa_addr)) &&
849 sdl->sdl_type == IFT_ETHER)
853 panic("bootpc: Unable to find HW address");
854 if (sdl->sdl_alen != EALEN)
855 panic("bootpc: HW address len is %d, expected value is %d",
856 sdl->sdl_alen, EALEN);
858 printf("bootpc hw address is ");
860 for (j = 0; j < sdl->sdl_alen; j++) {
861 printf("%s%x",delim,((unsigned char *)LLADDR(sdl))[j]);
867 bootpboot_p_iflist();
868 bootpboot_p_rtlist();
871 bzero((caddr_t) &call, sizeof(call));
874 call.op = 1; /* BOOTREQUEST */
875 call.htype = 1; /* 10mb ethernet */
876 call.hlen = sdl->sdl_alen; /* Hardware address length */
879 call.xid = txdr_unsigned(xid);
880 bcopy(LLADDR(sdl), &call.chaddr, sdl->sdl_alen);
884 call.vend[j++] = 130;
889 * We send an RFC 1533 "Maximum DHCP Message Size" option, saying we
890 * can do 1200 bytes. If we don't ISC DHCPD will limit the answer to
891 * 64 bytes and root/swap and similar will be dropped.
895 call.vend[j++] = 1200 / 256;
896 call.vend[j++] = 1200 % 256;
898 call.vend[j++] = 255;
901 call.flags = htons(0x8000); /* We need an broadcast answer */
903 error = bootpc_call(&call, &reply, procp);
907 panic("BOOTP call failed");
912 bzero(&myaddr, sizeof(myaddr));
913 bzero(&netmask, sizeof(netmask));
914 bzero(&gw, sizeof(gw));
916 myaddr.sin_len = sizeof(myaddr);
917 myaddr.sin_family = AF_INET;
919 netmask.sin_len = sizeof(netmask);
920 netmask.sin_family = AF_INET;
922 gw.sin_len = sizeof(gw);
923 gw.sin_family = AF_INET;
925 nd->root_args.version = NFS_ARGSVERSION;
926 nd->root_args.rsize = 8192;
927 nd->root_args.wsize = 8192;
928 nd->root_args.sotype = SOCK_DGRAM;
929 nd->root_args.flags = (NFSMNT_WSIZE | NFSMNT_RSIZE | NFSMNT_RESVPORT);
931 nd->swap_saddr.sin_len = sizeof(gw);
932 nd->swap_saddr.sin_family = AF_INET;
934 nd->swap_args.version = NFS_ARGSVERSION;
935 nd->swap_args.rsize = 8192;
936 nd->swap_args.wsize = 8192;
937 nd->swap_args.sotype = SOCK_DGRAM;
938 nd->swap_args.flags = (NFSMNT_WSIZE | NFSMNT_RSIZE | NFSMNT_RESVPORT);
940 myaddr.sin_addr = reply.yiaddr;
942 ip = ntohl(myaddr.sin_addr.s_addr);
943 snprintf(lookup_path, sizeof(lookup_path), "swap.%d.%d.%d.%d",
944 ip >> 24, (ip >> 16) & 255 ,(ip >> 8) & 255 ,ip & 255);
946 printip("My ip address", myaddr.sin_addr);
948 printip("Server ip address", reply.siaddr);
950 gw.sin_addr = reply.giaddr;
951 printip("Gateway ip address", reply.giaddr);
953 if (reply.sname[0] != '\0')
954 printf("Server name is %s\n", reply.sname);
955 if (reply.file[0] != '\0')
956 printf("boot file is %s\n", reply.file);
957 if (reply.vend[0] == 99 && reply.vend[1] == 130 &&
958 reply.vend[2] == 83 && reply.vend[3] == 99) {
960 ncode = reply.vend[j];
961 while (j < sizeof(reply.vend)) {
962 code = reply.vend[j] = ncode;
969 len = reply.vend[j + 1];
971 if (len + j >= sizeof(reply.vend)) {
972 printf("Truncated field");
975 ncode = reply.vend[j + len];
976 reply.vend[j + len] = '\0';
981 panic("bootpc: subnet mask len is %d",
983 bcopy(&reply.vend[j], &netmask.sin_addr, 4);
985 printip("Subnet mask", netmask.sin_addr);
987 case 6: /* Domain Name servers. Unused */
988 case 16: /* Swap server IP address. unused */
995 panic("bootpc: Router Len is %d", len);
997 bcopy(&reply.vend[j], &gw.sin_addr, 4);
998 printip("Router", gw.sin_addr);
1003 if (setfs(&nd->root_saddr,
1004 nd->root_hostnam, p)) {
1005 printf("rootfs is %s\n", p);
1008 panic("Failed to set rootfs to %s", p);
1011 if (len >= MAXHOSTNAMELEN)
1012 panic("bootpc: hostname >=%d bytes",
1014 strncpy(nd->my_hostnam, &reply.vend[j], len);
1015 nd->my_hostnam[len] = 0;
1016 strncpy(hostname, &reply.vend[j], len);
1018 printf("Hostname is %s\n", hostname);
1021 if (setfs(&nd->swap_saddr,
1022 nd->swap_hostnam, p)) {
1024 printf("swapfs is %s\n", p);
1026 panic("Failed to set swapfs to %s", p);
1032 panic("bootpc: Expected 4 bytes for swaplen, not %d bytes",len);
1033 bcopy(&reply.vend[j], &swaplen, 4);
1034 nd->swap_nblks = ntohl(swaplen);
1035 printf("bootpc: Swap size is %d KB\n",
1039 case 130: /* root mount options */
1040 mountopts(&nd->root_args, p);
1042 case 131: /* swap mount options */
1043 mountopts(&nd->swap_args, p);
1046 printf("Ignoring field type %d\n",code);
1052 if (gotswappath == 0)
1054 #ifdef BOOTP_NFSROOT
1055 if (gotrootpath == 0)
1056 panic("bootpc: No root path offered");
1059 if (gotnetmask == 0) {
1060 if (IN_CLASSA(ntohl(myaddr.sin_addr.s_addr)))
1061 netmask.sin_addr.s_addr = htonl(IN_CLASSA_NET);
1062 else if (IN_CLASSB(ntohl(myaddr.sin_addr.s_addr)))
1063 netmask.sin_addr.s_addr = htonl(IN_CLASSB_NET);
1065 netmask.sin_addr.s_addr = htonl(IN_CLASSC_NET);
1069 gw.sin_addr.s_addr = myaddr.sin_addr.s_addr;
1073 bootpboot_p_iflist();
1074 bootpboot_p_rtlist();
1076 error = bootpc_adjust_interface(&ireq, so,
1077 &myaddr, &netmask, &gw, procp);
1082 bootpboot_p_iflist();
1083 bootpboot_p_rtlist();
1086 if (gotrootpath != 0) {
1088 error = md_mount(&nd->root_saddr, nd->root_hostnam,
1089 nd->root_fh, &nd->root_fhsize,
1090 &nd->root_args, procp);
1092 panic("nfs_boot: mountd root, error=%d", error);
1094 if (gotswappath != 0) {
1096 error = md_mount(&nd->swap_saddr,
1098 nd->swap_fh, &nd->swap_fhsize,
1099 &nd->swap_args, procp);
1101 panic("nfs_boot: mountd swap, error=%d",
1104 error = md_lookup_swap(&nd->swap_saddr,
1106 nd->swap_fh, &nd->swap_fhsize,
1107 &nd->swap_args, procp);
1109 panic("nfs_boot: lookup swap, error=%d",
1112 nfs_diskless_valid = 3;
1116 bcopy(&myaddr, &nd->myif.ifra_addr, sizeof(myaddr));
1117 bcopy(&myaddr, &nd->myif.ifra_broadaddr, sizeof(myaddr));
1118 ((struct sockaddr_in *) &nd->myif.ifra_broadaddr)->sin_addr.s_addr =
1119 myaddr.sin_addr.s_addr | ~ netmask.sin_addr.s_addr;
1120 bcopy(&netmask, &nd->myif.ifra_mask, sizeof(netmask));
1123 bootpboot_p_iflist();
1124 bootpboot_p_rtlist();
1132 * Given a server pathname, get an NFS file handle.
1133 * Also, sets sin->sin_port to the NFS service port.
1136 md_mount(struct sockaddr_in *mdsin, /* mountd server address */
1140 struct nfs_args *args,
1150 /* First try NFS v3 */
1151 /* Get port number for MOUNTD. */
1152 error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER3,
1153 &mdsin->sin_port, procp);
1155 m = xdr_string_encode(path, strlen(path));
1157 /* Do RPC to mountd. */
1158 error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER3,
1159 RPCMNT_MOUNT, &m, NULL, procp);
1162 args->flags |= NFSMNT_NFSV3;
1165 /* Fallback to NFS v2 */
1167 /* Get port number for MOUNTD. */
1168 error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1,
1169 &mdsin->sin_port, procp);
1173 m = xdr_string_encode(path, strlen(path));
1175 /* Do RPC to mountd. */
1176 error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1,
1177 RPCMNT_MOUNT, &m, NULL, procp);
1179 return error; /* message already freed */
1185 if (xdr_int_decode(&m, &error) != 0 || error != 0)
1188 if ((args->flags & NFSMNT_NFSV3) != 0) {
1189 if (xdr_int_decode(&m, fhsizep) != 0 ||
1190 *fhsizep > NFSX_V3FHMAX ||
1194 *fhsizep = NFSX_V2FH;
1196 if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0)
1199 if (args->flags & NFSMNT_NFSV3) {
1200 if (xdr_int_decode(&m, &authcount) != 0)
1203 if (authcount < 0 || authcount > 100)
1205 while (authcount > 0) {
1206 if (xdr_int_decode(&m, &authver) != 0)
1208 if (authver == RPCAUTH_UNIX)
1212 if (authunixok == 0)
1216 /* Set port number for NFS use. */
1217 error = krpc_portmap(mdsin, NFS_PROG,
1219 NFSMNT_NFSV3) ? NFS_VER3 : NFS_VER2,
1220 &mdsin->sin_port, procp);
1234 md_lookup_swap(struct sockaddr_in *mdsin, /* mountd server address */
1238 struct nfs_args *args,
1244 int attribs_present;
1251 m = m_get(M_WAIT,MT_DATA);
1255 if ((args->flags & NFSMNT_NFSV3) != 0) {
1256 *mtod(m, u_int32_t *) = txdr_unsigned(*fhsizep);
1257 bcopy(fhp, mtod(m, u_char *) + sizeof(u_int32_t), *fhsizep);
1258 m->m_len = *fhsizep + sizeof(u_int32_t);
1260 bcopy(fhp, mtod(m, u_char *), NFSX_V2FH);
1261 m->m_len = NFSX_V2FH;
1264 m->m_next = xdr_string_encode(path, strlen(path));
1265 if (m->m_next == NULL) {
1270 /* Do RPC to nfsd. */
1271 if ((args->flags & NFSMNT_NFSV3) != 0)
1272 error = krpc_call(mdsin, NFS_PROG, NFS_VER3,
1273 NFSPROC_LOOKUP, &m, NULL, procp);
1275 error = krpc_call(mdsin, NFS_PROG, NFS_VER2,
1276 NFSV2PROC_LOOKUP, &m, NULL, procp);
1278 return error; /* message already freed */
1280 if (xdr_int_decode(&m, &status) != 0)
1287 if ((args->flags & NFSMNT_NFSV3) != 0) {
1288 if (xdr_int_decode(&m, fhsizep) != 0 ||
1289 *fhsizep > NFSX_V3FHMAX ||
1293 *fhsizep = NFSX_V2FH;
1295 if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0)
1298 if ((args->flags & NFSMNT_NFSV3) != 0) {
1299 if (xdr_int_decode(&m, &attribs_present) != 0)
1301 if (attribs_present != 0) {
1302 if (xdr_opaque_decode(&m, (u_char *) &fattribs.v3,
1303 sizeof(u_int32_t) * 21) != 0)
1305 size = fxdr_unsigned(u_int32_t, fattribs.v3[6]);
1308 if (xdr_opaque_decode(&m,(u_char *) &fattribs.v2,
1309 sizeof(u_int32_t) * 17) != 0)
1311 size = fxdr_unsigned(u_int32_t, fattribs.v2[5]);
1314 if (nfsv3_diskless.swap_nblks == 0 && size != -1) {
1315 nfsv3_diskless.swap_nblks = size / 1024;
1316 printf("md_lookup_swap: Swap size is %d KB\n",
1317 nfsv3_diskless.swap_nblks);