From owner-freebsd-bugs@FreeBSD.ORG Fri Jul 11 08:30:13 2003 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 93D1C37B401 for ; Fri, 11 Jul 2003 08:30:13 -0700 (PDT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 2FCEC43F75 for ; Fri, 11 Jul 2003 08:30:11 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.9/8.12.9) with ESMTP id h6BFUAUp031418 for ; Fri, 11 Jul 2003 08:30:10 -0700 (PDT) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.9/8.12.9/Submit) id h6BFUAaL031417; Fri, 11 Jul 2003 08:30:10 -0700 (PDT) Resent-Date: Fri, 11 Jul 2003 08:30:10 -0700 (PDT) Resent-Message-Id: <200307111530.h6BFUAaL031417@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, msl@procergs.rs.gov.br Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 8E76C37B401 for ; Fri, 11 Jul 2003 08:22:56 -0700 (PDT) Received: from aveiro.procergs.com.br (aveiro.procergs.com.br [200.198.128.211]) by mx1.FreeBSD.org (Postfix) with ESMTP id C1F6A43F93 for ; Fri, 11 Jul 2003 08:22:53 -0700 (PDT) (envelope-from marcelo-leal@zeta1.procergs.com.br) Received: from colombo.procergs.com.br (zeta1.procergs.com.br [200.198.128.57]) by aveiro.procergs.com.br (Postfix) with ESMTP id 90806116431 for ; Fri, 11 Jul 2003 12:22:46 -0300 (BRT) Received: by colombo.procergs.com.br (Postfix, from userid 52647) id 3D85F23C06E; Fri, 11 Jul 2003 12:22:46 -0300 (BRT) Message-Id: <20030711152246.3D85F23C06E@colombo.procergs.com.br> Date: Fri, 11 Jul 2003 12:22:46 -0300 (BRT) From: Marcelo Leal To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Subject: kern/54383: NFS root configurations without dynamic protocols: dhcp, bootp, etc... X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: msl@procergs.rs.gov.br List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 11 Jul 2003 15:30:13 -0000 >Number: 54383 >Category: kern >Synopsis: NFS root configurations without dynamic protocols: dhcp, bootp, etc... >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Fri Jul 11 08:30:10 PDT 2003 >Closed-Date: >Last-Modified: >Originator: Marcelo Leal >Release: FreeBSD 5.1-RELEASE i386 >Organization: Cia de Processamento de Dados do Rio Grande do Sul >Environment: System: FreeBSD malgas.procergs.com.br 5.1-RELEASE FreeBSD 5.1-RELEASE #0: Mon Jun 23 04:28:13 BRT 2003 procergs@freebsd-5.1-release:/usr/src/sys/i386/compile/ROOT_NFS-CAM256-FHP i386 >Description: bootp_subr.c patch Today, hard drives is not so expansives, and "diskless" machines normaly have hard drives ( to hold swap device, /tmp, /dev/ and /spool directories). So, in my environment, my diskless machines have hard drives to do that job, and my important data are in a confiable storage equipament, and i have decided loads the diskless kernel from HD too. Then, i do not need bootp/dhcpd and tftp servers anymore... And i want configure my diskless kernel with variables, set in loader.conf. But i can't, because FreeBSD do IP, NETWORK, NFS SERVER and so configurations with bootp or dhcp protocol... So i did some adapadaptations and patches in the bootp_subr.c code for fix that... I kown about the dynamic protocols (dhcp, bootp, etc...), but believe in me, i want to boot the kernel from my hard drive. Look it by the best side: It's one more feature to the FreeBSD project. The variables in loader.conf: boot.netif.hostname= boot.netif.hwaddr= # if this variable is not set, the code will find one interface (the first ethernet)... boot.netif.ip= boot.netif.netmask= boot.nfsroot.server= boot.nfsroot.path= vfs.root.mountfrom= In my home page have instructions and my bootp_subr.c code: http://omestre.freeshell.org/FreeBSD/bootp_subr.c >How-To-Repeat: This report is not for bug, is a patch report. >Fix: --- bootp_subr.c Wed Feb 19 02:47:38 2003 +++ bootp_subr-5.0.c Fri Jul 11 11:16:28 2003 @@ -1,3 +1,5 @@ +/* $FreeBSD: src/sys/nfs/bootp_subr.c,v 1.20.2.8 2002/03/16 15:56:06 luigi Exp $ */ + /* * Copyright (c) 1995 Gordon Ross, Adam Glass * Copyright (c) 1992 Regents of the University of California. @@ -17,8 +19,8 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Lawrence Berkeley Laboratory and its contributors. + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -37,34 +39,28 @@ * * based on: * nfs/krpc_subr.c - * $NetBSD: krpc_subr.c,v 1.10 1995/08/08 20:43:43 gwr Exp $ + * $NetBSD: krpc_subr.c,v 1.10 1995/08/08 20:43:43 gwr Exp $ */ -#include -__FBSDID("$FreeBSD: src/sys/nfsclient/bootp_subr.c,v 1.47 2003/02/19 05:47:38 imp Exp $"); - #include "opt_bootp.h" #include #include #include #include +#include #include #include #include -#include #include #include #include #include - #include #include - #include #include #include - #include #include #include @@ -72,1951 +68,436 @@ #include #include - -#define BOOTP_MIN_LEN 300 /* Minimum size of bootp udp packet */ - -#ifndef BOOTP_SETTLE_DELAY -#define BOOTP_SETTLE_DELAY 3 -#endif - -/* - * What is the longest we will wait before re-sending a request? - * Note this is also the frequency of "RPC timeout" messages. - * The re-send loop count sup linearly to this maximum, so the - * first complaint will happen after (1+2+3+4+5)=15 seconds. - */ -#define MAX_RESEND_DELAY 5 /* seconds */ - -/* Definitions from RFC951 */ -struct bootp_packet { - u_int8_t op; - u_int8_t htype; - u_int8_t hlen; - u_int8_t hops; - u_int32_t xid; - u_int16_t secs; - u_int16_t flags; - struct in_addr ciaddr; - struct in_addr yiaddr; - struct in_addr siaddr; - struct in_addr giaddr; - unsigned char chaddr[16]; - char sname[64]; - char file[128]; - unsigned char vend[1222]; -}; - -struct bootpc_ifcontext { - struct bootpc_ifcontext *next; - struct bootp_packet call; - struct bootp_packet reply; - int replylen; - int overload; - struct socket *so; - struct ifreq ireq; - struct ifnet *ifp; - struct sockaddr_dl *sdl; - struct sockaddr_in myaddr; - struct sockaddr_in netmask; - struct sockaddr_in gw; - struct sockaddr_in broadcast; /* Different for each interface */ - int gotgw; - int gotnetmask; - int gotrootpath; - int outstanding; - int sentmsg; - u_int32_t xid; - enum { - IF_BOOTP_UNRESOLVED, - IF_BOOTP_RESOLVED, - IF_BOOTP_FAILED, - IF_DHCP_UNRESOLVED, - IF_DHCP_OFFERED, - IF_DHCP_RESOLVED, - IF_DHCP_FAILED, - } state; - int dhcpquerytype; /* dhcp type sent */ - struct in_addr dhcpserver; - int gotdhcpserver; -}; - -#define TAG_MAXLEN 1024 -struct bootpc_tagcontext { - char buf[TAG_MAXLEN + 1]; - int overload; - int badopt; - int badtag; - int foundopt; - int taglen; -}; - -struct bootpc_globalcontext { - struct bootpc_ifcontext *interfaces; - struct bootpc_ifcontext *lastinterface; - u_int32_t xid; - int gotrootpath; - int gotswappath; - int gotgw; - int ifnum; - int secs; - int starttime; - struct bootp_packet reply; - int replylen; - struct bootpc_ifcontext *setswapfs; - struct bootpc_ifcontext *setrootfs; - struct bootpc_ifcontext *sethostname; - char lookup_path[24]; - struct bootpc_tagcontext tmptag; - struct bootpc_tagcontext tag; -}; - -#define IPPORT_BOOTPC 68 -#define IPPORT_BOOTPS 67 - -#define BOOTP_REQUEST 1 -#define BOOTP_REPLY 2 - -/* Common tags */ -#define TAG_PAD 0 /* Pad option, implicit length 1 */ -#define TAG_SUBNETMASK 1 /* RFC 950 subnet mask */ -#define TAG_ROUTERS 3 /* Routers (in order of preference) */ -#define TAG_HOSTNAME 12 /* Client host name */ -#define TAG_ROOT 17 /* Root path */ - -/* DHCP specific tags */ -#define TAG_OVERLOAD 52 /* Option Overload */ -#define TAG_MAXMSGSIZE 57 /* Maximum DHCP Message Size */ - -#define TAG_END 255 /* End Option (i.e. no more options) */ - -/* Overload values */ -#define OVERLOAD_FILE 1 -#define OVERLOAD_SNAME 2 - -/* Site specific tags: */ -#define TAG_SWAP 128 -#define TAG_SWAPSIZE 129 -#define TAG_ROOTOPTS 130 -#define TAG_SWAPOPTS 131 -#define TAG_COOKIE 134 /* ascii info for userland, via sysctl */ - -#define TAG_DHCP_MSGTYPE 53 -#define TAG_DHCP_REQ_ADDR 50 -#define TAG_DHCP_SERVERID 54 -#define TAG_DHCP_LEASETIME 51 - -#define TAG_VENDOR_INDENTIFIER 60 - -#define DHCP_NOMSG 0 -#define DHCP_DISCOVER 1 -#define DHCP_OFFER 2 -#define DHCP_REQUEST 3 -#define DHCP_ACK 5 - -static char bootp_cookie[128]; -SYSCTL_STRING(_kern, OID_AUTO, bootp_cookie, CTLFLAG_RD, - bootp_cookie, 0, "Cookie (T134) supplied by bootp server"); - -/* mountd RPC */ -static int md_mount(struct sockaddr_in *mdsin, char *path, u_char *fhp, - int *fhsizep, struct nfs_args *args, struct thread *td); -static int md_lookup_swap(struct sockaddr_in *mdsin, char *path, - u_char *fhp, int *fhsizep, struct nfs_args *args, - struct thread *td); -static int setfs(struct sockaddr_in *addr, char *path, char *p); -static int getdec(char **ptr); -static char *substr(char *a, char *b); -static void mountopts(struct nfs_args *args, char *p); -static int xdr_opaque_decode(struct mbuf **ptr, u_char *buf, int len); -static int xdr_int_decode(struct mbuf **ptr, int *iptr); -static void print_in_addr(struct in_addr addr); -static void print_sin_addr(struct sockaddr_in *addr); -static void clear_sinaddr(struct sockaddr_in *sin); -static struct bootpc_ifcontext *allocifctx(struct bootpc_globalcontext *gctx); -static void bootpc_compose_query(struct bootpc_ifcontext *ifctx, - struct bootpc_globalcontext *gctx, struct thread *td); -static unsigned char *bootpc_tag(struct bootpc_tagcontext *tctx, - struct bootp_packet *bp, int len, int tag); -static void bootpc_tag_helper(struct bootpc_tagcontext *tctx, - unsigned char *start, int len, int tag); - -#ifdef BOOTP_DEBUG -void bootpboot_p_sa(struct sockaddr *sa, struct sockaddr *ma); -void bootpboot_p_ma(struct sockaddr *ma); -void bootpboot_p_rtentry(struct rtentry *rt); -void bootpboot_p_tree(struct radix_node *rn); -void bootpboot_p_rtlist(void); -void bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa); -void bootpboot_p_iflist(void); -#endif - -static int bootpc_call(struct bootpc_globalcontext *gctx, - struct thread *td); - -static int bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx, - struct bootpc_globalcontext *gctx, struct thread *td); - -static int bootpc_adjust_interface(struct bootpc_ifcontext *ifctx, - struct bootpc_globalcontext *gctx, struct thread *td); - -static void bootpc_decode_reply(struct nfsv3_diskless *nd, - struct bootpc_ifcontext *ifctx, - struct bootpc_globalcontext *gctx); - -static int bootpc_received(struct bootpc_globalcontext *gctx, - struct bootpc_ifcontext *ifctx); - -static __inline int bootpc_ifctx_isresolved(struct bootpc_ifcontext *ifctx); -static __inline int bootpc_ifctx_isunresolved(struct bootpc_ifcontext *ifctx); -static __inline int bootpc_ifctx_isfailed(struct bootpc_ifcontext *ifctx); - +#define ETHER_ADDR_LEN 6 /* - * In order to have multiple active interfaces with address 0.0.0.0 - * and be able to send data to a selected interface, we perform - * some tricks: - * - * - The 'broadcast' address is different for each interface. - * - * - We temporarily add routing pointing 255.255.255.255 to the - * selected interface broadcast address, thus the packet sent - * goes to that interface. - */ - -#ifdef BOOTP_DEBUG -void -bootpboot_p_sa(struct sockaddr *sa, struct sockaddr *ma) -{ - - if (sa == NULL) { - printf("(sockaddr *) "); - return; - } - switch (sa->sa_family) { - case AF_INET: - { - struct sockaddr_in *sin; - - sin = (struct sockaddr_in *) sa; - printf("inet "); - print_sin_addr(sin); - if (ma != NULL) { - sin = (struct sockaddr_in *) ma; - printf(" mask "); - print_sin_addr(sin); - } - } - break; - case AF_LINK: - { - struct sockaddr_dl *sli; - int i; - - sli = (struct sockaddr_dl *) sa; - printf("link %.*s ", sli->sdl_nlen, sli->sdl_data); - for (i = 0; i < sli->sdl_alen; i++) { - if (i > 0) - printf(":"); - printf("%x", ((unsigned char *) LLADDR(sli))[i]); - } - } - break; - default: - printf("af%d", sa->sa_family); - } -} - -void -bootpboot_p_ma(struct sockaddr *ma) -{ - - if (ma == NULL) { - printf(""); - return; - } - printf("%x", *(int *)ma); -} - -void -bootpboot_p_rtentry(struct rtentry *rt) -{ - - bootpboot_p_sa(rt_key(rt), rt_mask(rt)); - printf(" "); - bootpboot_p_ma(rt->rt_genmask); - printf(" "); - bootpboot_p_sa(rt->rt_gateway, NULL); - printf(" "); - printf("flags %x", (unsigned short) rt->rt_flags); - printf(" %d", (int) rt->rt_rmx.rmx_expire); - printf(" %s%d\n", rt->rt_ifp->if_name, rt->rt_ifp->if_unit); -} - -void -bootpboot_p_tree(struct radix_node *rn) -{ - - while (rn != NULL) { - if (rn->rn_bit < 0) { - if ((rn->rn_flags & RNF_ROOT) != 0) { - } else { - bootpboot_p_rtentry((struct rtentry *) rn); - } - rn = rn->rn_dupedkey; - } else { - bootpboot_p_tree(rn->rn_left); - bootpboot_p_tree(rn->rn_right); - return; - } - } -} - -void -bootpboot_p_rtlist(void) -{ - - printf("Routing table:\n"); - RADIX_NODE_LOCK(rt_tables[AF_INET]); /* could sleep XXX */ - bootpboot_p_tree(rt_tables[AF_INET]->rnh_treetop); - RADIX_NODE_UNLOCK(rt_tables[AF_INET]); -} - -void -bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa) -{ - - printf("%s%d flags %x, addr ", - ifp->if_name, - ifp->if_unit, - ifp->if_flags); - print_sin_addr((struct sockaddr_in *) ifa->ifa_addr); - printf(", broadcast "); - print_sin_addr((struct sockaddr_in *) ifa->ifa_dstaddr); - printf(", netmask "); - print_sin_addr((struct sockaddr_in *) ifa->ifa_netmask); - printf("\n"); -} - -void -bootpboot_p_iflist(void) -{ - struct ifnet *ifp; - struct ifaddr *ifa; - - printf("Interface list:\n"); - IFNET_RLOCK(); /* could sleep, but okay for debugging XXX */ - for (ifp = TAILQ_FIRST(&ifnet); - ifp != NULL; - ifp = TAILQ_NEXT(ifp, if_link)) { - for (ifa = TAILQ_FIRST(&ifp->if_addrhead); - ifa != NULL; - ifa = TAILQ_NEXT(ifa, ifa_link)) - if (ifa->ifa_addr->sa_family == AF_INET) - bootpboot_p_if(ifp, ifa); - } - IFNET_RUNLOCK(); -} -#endif /* defined(BOOTP_DEBUG) */ - +* extern int nfs_diskless_valid; +* extern struct nfsv3_diskless nfsv3_diskless; +* extern struct nfs_diskless nfs_diskless; +*/ +struct nfsv3_diskless *nd3; +struct nfs_diskless *nd = &nfs_diskless; + +static int get_file_handle(struct sockaddr_in *mdsin, char *path, u_char *fhp, int *fhsizep, struct nfs_args *args, struct thread *td); +static int xdr_opaque_decode(struct mbuf **ptr, u_char *buf, int len); +static int xdr_int_decode(struct mbuf **ptr, int *iptr); +static void print_in_addr(struct in_addr addr); +static void print_sin_addr(struct sockaddr_in *addr); +static void nfs_convert_diskless __P((void)); +static void nfs_convert_oargs __P((struct nfs_args *args, + struct onfs_args *oargs)); +static void clear_sinaddr(struct sockaddr_in *sin); +static void setup_nfsdiskless(void); + static void clear_sinaddr(struct sockaddr_in *sin) { - - bzero(sin, sizeof(*sin)); - sin->sin_len = sizeof(*sin); - sin->sin_family = AF_INET; - sin->sin_addr.s_addr = INADDR_ANY; /* XXX: htonl(INAADDR_ANY) ? */ - sin->sin_port = 0; -} - -static struct bootpc_ifcontext * -allocifctx(struct bootpc_globalcontext *gctx) -{ - struct bootpc_ifcontext *ifctx; - ifctx = (struct bootpc_ifcontext *) malloc(sizeof(*ifctx), - M_TEMP, M_WAITOK); - if (ifctx == NULL) - panic("Failed to allocate bootp interface context structure"); - - bzero(ifctx, sizeof(*ifctx)); - ifctx->xid = gctx->xid; -#ifdef BOOTP_NO_DHCP - ifctx->state = IF_BOOTP_UNRESOLVED; -#else - ifctx->state = IF_DHCP_UNRESOLVED; -#endif - gctx->xid += 0x100; - return ifctx; -} - -static __inline int -bootpc_ifctx_isresolved(struct bootpc_ifcontext *ifctx) -{ - - if (ifctx->state == IF_BOOTP_RESOLVED || - ifctx->state == IF_DHCP_RESOLVED) - return 1; - return 0; -} - -static __inline int -bootpc_ifctx_isunresolved(struct bootpc_ifcontext *ifctx) -{ - - if (ifctx->state == IF_BOOTP_UNRESOLVED || - ifctx->state == IF_DHCP_UNRESOLVED) - return 1; - return 0; -} - -static __inline int -bootpc_ifctx_isfailed(struct bootpc_ifcontext *ifctx) -{ - - if (ifctx->state == IF_BOOTP_FAILED || - ifctx->state == IF_DHCP_FAILED) - return 1; - return 0; -} - -static int -bootpc_received(struct bootpc_globalcontext *gctx, - struct bootpc_ifcontext *ifctx) -{ - unsigned char dhcpreplytype; - char *p; - - /* - * Need timeout for fallback to less - * desirable alternative. - */ - - /* This call used for the side effect (badopt flag) */ - (void) bootpc_tag(&gctx->tmptag, &gctx->reply, - gctx->replylen, - TAG_END); - - /* If packet is invalid, ignore it */ - if (gctx->tmptag.badopt != 0) - return 0; - - p = bootpc_tag(&gctx->tmptag, &gctx->reply, - gctx->replylen, TAG_DHCP_MSGTYPE); - if (p != NULL) - dhcpreplytype = *p; - else - dhcpreplytype = DHCP_NOMSG; - - switch (ifctx->dhcpquerytype) { - case DHCP_DISCOVER: - if (dhcpreplytype != DHCP_OFFER /* Normal DHCP offer */ -#ifndef BOOTP_FORCE_DHCP - && dhcpreplytype != DHCP_NOMSG /* Fallback to BOOTP */ -#endif - ) - return 0; - break; - case DHCP_REQUEST: - if (dhcpreplytype != DHCP_ACK) - return 0; - case DHCP_NOMSG: - break; - } - - /* Ignore packet unless it gives us a root tag we didn't have */ - - if ((ifctx->state == IF_BOOTP_RESOLVED || - (ifctx->dhcpquerytype == DHCP_DISCOVER && - (ifctx->state == IF_DHCP_OFFERED || - ifctx->state == IF_DHCP_RESOLVED))) && - (bootpc_tag(&gctx->tmptag, &ifctx->reply, - ifctx->replylen, - TAG_ROOT) != NULL || - bootpc_tag(&gctx->tmptag, &gctx->reply, - gctx->replylen, - TAG_ROOT) == NULL)) - return 0; - - bcopy(&gctx->reply, &ifctx->reply, gctx->replylen); - ifctx->replylen = gctx->replylen; - - /* XXX: Only reset if 'perfect' response */ - if (ifctx->state == IF_BOOTP_UNRESOLVED) - ifctx->state = IF_BOOTP_RESOLVED; - else if (ifctx->state == IF_DHCP_UNRESOLVED && - ifctx->dhcpquerytype == DHCP_DISCOVER) { - if (dhcpreplytype == DHCP_OFFER) - ifctx->state = IF_DHCP_OFFERED; - else - ifctx->state = IF_BOOTP_RESOLVED; /* Fallback */ - } else if (ifctx->state == IF_DHCP_OFFERED && - ifctx->dhcpquerytype == DHCP_REQUEST) - ifctx->state = IF_DHCP_RESOLVED; - - - if (ifctx->dhcpquerytype == DHCP_DISCOVER && - ifctx->state != IF_BOOTP_RESOLVED) { - p = bootpc_tag(&gctx->tmptag, &ifctx->reply, - ifctx->replylen, TAG_DHCP_SERVERID); - if (p != NULL && gctx->tmptag.taglen == 4) { - memcpy(&ifctx->dhcpserver, p, 4); - ifctx->gotdhcpserver = 1; - } else - ifctx->gotdhcpserver = 0; - return 1; - } - - ifctx->gotrootpath = (bootpc_tag(&gctx->tmptag, &ifctx->reply, - ifctx->replylen, - TAG_ROOT) != NULL); - ifctx->gotgw = (bootpc_tag(&gctx->tmptag, &ifctx->reply, - ifctx->replylen, - TAG_ROUTERS) != NULL); - ifctx->gotnetmask = (bootpc_tag(&gctx->tmptag, &ifctx->reply, - ifctx->replylen, - TAG_SUBNETMASK) != NULL); - return 1; -} - -static int -bootpc_call(struct bootpc_globalcontext *gctx, struct thread *td) -{ - struct socket *so; - struct sockaddr_in *sin, dst; - struct uio auio; - struct sockopt sopt; - struct iovec aio; - int error, on, rcvflg, timo, len; - time_t atimo; - time_t rtimo; - struct timeval tv; - struct bootpc_ifcontext *ifctx; - int outstanding; - int gotrootpath; - int retry; - const char *s; - - /* - * Create socket and set its recieve timeout. - */ - error = socreate(AF_INET, &so, SOCK_DGRAM, 0, td->td_ucred, td); - if (error != 0) - goto out; - - tv.tv_sec = 1; - tv.tv_usec = 0; - bzero(&sopt, sizeof(sopt)); - sopt.sopt_level = SOL_SOCKET; - sopt.sopt_name = SO_RCVTIMEO; - sopt.sopt_val = &tv; - sopt.sopt_valsize = sizeof tv; - - error = sosetopt(so, &sopt); - if (error != 0) - goto out; - - /* - * Enable broadcast. - */ - on = 1; - sopt.sopt_name = SO_BROADCAST; - sopt.sopt_val = &on; - sopt.sopt_valsize = sizeof on; - - error = sosetopt(so, &sopt); - if (error != 0) - goto out; - - /* - * Disable routing. - */ - - on = 1; - sopt.sopt_name = SO_DONTROUTE; - sopt.sopt_val = &on; - sopt.sopt_valsize = sizeof on; - - error = sosetopt(so, &sopt); - if (error != 0) - goto out; - - /* - * Bind the local endpoint to a bootp client port. - */ - sin = &dst; - clear_sinaddr(sin); - sin->sin_port = htons(IPPORT_BOOTPC); - error = sobind(so, (struct sockaddr *)sin, td); - if (error != 0) { - printf("bind failed\n"); - goto out; - } - - /* - * Setup socket address for the server. - */ - sin = &dst; - clear_sinaddr(sin); - sin->sin_addr.s_addr = INADDR_BROADCAST; - sin->sin_port = htons(IPPORT_BOOTPS); - - /* - * Send it, repeatedly, until a reply is received, - * but delay each re-send by an increasing amount. - * If the delay hits the maximum, start complaining. - */ - timo = 0; - rtimo = 0; - for (;;) { - - outstanding = 0; - gotrootpath = 0; - - for (ifctx = gctx->interfaces; - ifctx != NULL; - ifctx = ifctx->next) { - if (bootpc_ifctx_isresolved(ifctx) != 0 && - bootpc_tag(&gctx->tmptag, &ifctx->reply, - ifctx->replylen, - TAG_ROOT) != NULL) - gotrootpath = 1; - } - - for (ifctx = gctx->interfaces; - ifctx != NULL; - ifctx = ifctx->next) { - ifctx->outstanding = 0; - if (bootpc_ifctx_isresolved(ifctx) != 0 && - gotrootpath != 0) { - continue; - } - if (bootpc_ifctx_isfailed(ifctx) != 0) - continue; - - outstanding++; - ifctx->outstanding = 1; - - /* Proceed to next step in DHCP negotiation */ - if ((ifctx->state == IF_DHCP_OFFERED && - ifctx->dhcpquerytype != DHCP_REQUEST) || - (ifctx->state == IF_DHCP_UNRESOLVED && - ifctx->dhcpquerytype != DHCP_DISCOVER) || - (ifctx->state == IF_BOOTP_UNRESOLVED && - ifctx->dhcpquerytype != DHCP_NOMSG)) { - ifctx->sentmsg = 0; - bootpc_compose_query(ifctx, gctx, td); - } - - /* Send BOOTP request (or re-send). */ - - if (ifctx->sentmsg == 0) { - switch(ifctx->dhcpquerytype) { - case DHCP_DISCOVER: - s = "DHCP Discover"; - break; - case DHCP_REQUEST: - s = "DHCP Request"; - break; - case DHCP_NOMSG: - default: - s = "BOOTP Query"; - break; - } - printf("Sending %s packet from " - "interface %s (%*D)\n", - s, - ifctx->ireq.ifr_name, - ifctx->sdl->sdl_alen, - (unsigned char *) LLADDR(ifctx->sdl), - ":"); - ifctx->sentmsg = 1; - } - - aio.iov_base = (caddr_t) &ifctx->call; - aio.iov_len = sizeof(ifctx->call); - - auio.uio_iov = &aio; - auio.uio_iovcnt = 1; - auio.uio_segflg = UIO_SYSSPACE; - auio.uio_rw = UIO_WRITE; - auio.uio_offset = 0; - auio.uio_resid = sizeof(ifctx->call); - auio.uio_td = td; - - /* Set netmask to 0.0.0.0 */ - - sin = (struct sockaddr_in *) &ifctx->ireq.ifr_addr; - clear_sinaddr(sin); - error = ifioctl(ifctx->so, SIOCSIFNETMASK, - (caddr_t) &ifctx->ireq, td); - if (error != 0) - panic("bootpc_call:" - "set if netmask, error=%d", - error); - - error = sosend(so, (struct sockaddr *) &dst, - &auio, NULL, NULL, 0, td); - if (error != 0) { - printf("bootpc_call: sosend: %d state %08x\n", - error, (int) so->so_state); - } - - /* XXX: Is this needed ? */ - tsleep(&error, PZERO + 8, "bootpw", 10); - - /* Set netmask to 255.0.0.0 */ - - sin = (struct sockaddr_in *) &ifctx->ireq.ifr_addr; - clear_sinaddr(sin); - sin->sin_addr.s_addr = htonl(0xff000000u); - error = ifioctl(ifctx->so, SIOCSIFNETMASK, - (caddr_t) &ifctx->ireq, td); - if (error != 0) - panic("bootpc_call:" - "set if netmask, error=%d", - error); - - } - - if (outstanding == 0 && - (rtimo == 0 || time_second >= rtimo)) { - error = 0; - goto gotreply; - } - - /* Determine new timeout. */ - if (timo < MAX_RESEND_DELAY) - timo++; - else { - printf("DHCP/BOOTP timeout for server "); - print_sin_addr(&dst); - printf("\n"); - } - - /* - * Wait for up to timo seconds for a reply. - * The socket receive timeout was set to 1 second. - */ - atimo = timo + time_second; - while (time_second < atimo) { - aio.iov_base = (caddr_t) &gctx->reply; - aio.iov_len = sizeof(gctx->reply); - - auio.uio_iov = &aio; - auio.uio_iovcnt = 1; - auio.uio_segflg = UIO_SYSSPACE; - auio.uio_rw = UIO_READ; - auio.uio_offset = 0; - auio.uio_resid = sizeof(gctx->reply); - auio.uio_td = td; - - rcvflg = 0; - error = soreceive(so, NULL, &auio, - NULL, NULL, &rcvflg); - gctx->secs = time_second - gctx->starttime; - for (ifctx = gctx->interfaces; - ifctx != NULL; - ifctx = ifctx->next) { - if (bootpc_ifctx_isresolved(ifctx) != 0 || - bootpc_ifctx_isfailed(ifctx) != 0) - continue; - - ifctx->call.secs = htons(gctx->secs); - } - if (error == EWOULDBLOCK) - continue; - if (error != 0) - goto out; - len = sizeof(gctx->reply) - auio.uio_resid; - - /* Do we have the required number of bytes ? */ - if (len < BOOTP_MIN_LEN) - continue; - gctx->replylen = len; - - /* Is it a reply? */ - if (gctx->reply.op != BOOTP_REPLY) - continue; - - /* Is this an answer to our query */ - for (ifctx = gctx->interfaces; - ifctx != NULL; - ifctx = ifctx->next) { - if (gctx->reply.xid != ifctx->call.xid) - continue; - - /* Same HW address size ? */ - if (gctx->reply.hlen != ifctx->call.hlen) - continue; - - /* Correct HW address ? */ - if (bcmp(gctx->reply.chaddr, - ifctx->call.chaddr, - ifctx->call.hlen) != 0) - continue; - - break; - } - - if (ifctx != NULL) { - s = bootpc_tag(&gctx->tmptag, - &gctx->reply, - gctx->replylen, - TAG_DHCP_MSGTYPE); - if (s != NULL) { - switch (*s) { - case DHCP_OFFER: - s = "DHCP Offer"; - break; - case DHCP_ACK: - s = "DHCP Ack"; - break; - default: - s = "DHCP (unexpected)"; - break; - } - } else - s = "BOOTP Reply"; - - printf("Received %s packet" - " on %s from ", - s, - ifctx->ireq.ifr_name); - print_in_addr(gctx->reply.siaddr); - if (gctx->reply.giaddr.s_addr != - htonl(INADDR_ANY)) { - printf(" via "); - print_in_addr(gctx->reply.giaddr); - } - if (bootpc_received(gctx, ifctx) != 0) { - printf(" (accepted)"); - if (ifctx->outstanding) { - ifctx->outstanding = 0; - outstanding--; - } - /* Network settle delay */ - if (outstanding == 0) - atimo = time_second + - BOOTP_SETTLE_DELAY; - } else - printf(" (ignored)"); - if (ifctx->gotrootpath) { - gotrootpath = 1; - rtimo = time_second + - BOOTP_SETTLE_DELAY; - printf(" (got root path)"); - } else - printf(" (no root path)"); - printf("\n"); - } - } /* while secs */ -#ifdef BOOTP_TIMEOUT - if (gctx->secs > BOOTP_TIMEOUT && BOOTP_TIMEOUT > 0) - break; -#endif - /* Force a retry if halfway in DHCP negotiation */ - retry = 0; - for (ifctx = gctx->interfaces; ifctx != NULL; - ifctx = ifctx->next) { - if (ifctx->state == IF_DHCP_OFFERED) { - if (ifctx->dhcpquerytype == DHCP_DISCOVER) - retry = 1; - else - ifctx->state = IF_DHCP_UNRESOLVED; - } - } - - if (retry != 0) - continue; - - if (gotrootpath != 0) { - gctx->gotrootpath = gotrootpath; - if (rtimo != 0 && time_second >= rtimo) - break; - } - } /* forever send/receive */ - - /* - * XXX: These are errors of varying seriousness being silently - * ignored - */ - - for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) { - if (bootpc_ifctx_isresolved(ifctx) == 0) { - printf("%s timeout for interface %s\n", - ifctx->dhcpquerytype != DHCP_NOMSG ? - "DHCP" : "BOOTP", - ifctx->ireq.ifr_name); - } - } - if (gctx->gotrootpath != 0) { -#if 0 - printf("Got a root path, ignoring remaining timeout\n"); -#endif - error = 0; - goto out; - } -#ifndef BOOTP_NFSROOT - for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) { - if (bootpc_ifctx_isresolved(ifctx) != 0) { - error = 0; - goto out; - } - } -#endif - error = ETIMEDOUT; - goto out; - -gotreply: -out: - soclose(so); - return error; -} - -static int -bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx, - struct bootpc_globalcontext *gctx, struct thread *td) -{ - struct sockaddr_in *sin; - int error; - struct ifreq *ireq; - struct socket *so; - struct ifaddr *ifa; - struct sockaddr_dl *sdl; - - error = socreate(AF_INET, &ifctx->so, SOCK_DGRAM, 0, td->td_ucred, td); - if (error != 0) - panic("nfs_boot: socreate, error=%d", error); - - ireq = &ifctx->ireq; - so = ifctx->so; - - /* - * Bring up the interface. - * - * Get the old interface flags and or IFF_UP into them; if - * IFF_UP set blindly, interface selection can be clobbered. - */ - error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, td); - if (error != 0) - panic("bootpc_fakeup_interface: GIFFLAGS, error=%d", error); - ireq->ifr_flags |= IFF_UP; - error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, td); - if (error != 0) - panic("bootpc_fakeup_interface: SIFFLAGS, error=%d", error); - - /* - * Do enough of ifconfig(8) so that the chosen interface - * can talk to the servers. (just set the address) - */ - - /* addr is 0.0.0.0 */ - - sin = (struct sockaddr_in *) &ireq->ifr_addr; - clear_sinaddr(sin); - error = ifioctl(so, SIOCSIFADDR, (caddr_t) ireq, td); - if (error != 0 && (error != EEXIST || ifctx == gctx->interfaces)) - panic("bootpc_fakeup_interface: " - "set if addr, error=%d", error); - - /* netmask is 255.0.0.0 */ - - sin = (struct sockaddr_in *) &ireq->ifr_addr; - clear_sinaddr(sin); - sin->sin_addr.s_addr = htonl(0xff000000u); - error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, td); - if (error != 0) - panic("bootpc_fakeup_interface: set if netmask, error=%d", - error); - - /* Broadcast is 255.255.255.255 */ - - sin = (struct sockaddr_in *)&ireq->ifr_addr; - clear_sinaddr(sin); - clear_sinaddr(&ifctx->broadcast); - sin->sin_addr.s_addr = htonl(INADDR_BROADCAST); - ifctx->broadcast.sin_addr.s_addr = sin->sin_addr.s_addr; - - error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, td); - if (error != 0) - panic("bootpc_fakeup_interface: " - "set if broadcast addr, error=%d", - error); - - /* Get HW address */ - - sdl = NULL; - for (ifa = TAILQ_FIRST(&ifctx->ifp->if_addrhead); - ifa != NULL; - ifa = TAILQ_NEXT(ifa, ifa_link)) - if (ifa->ifa_addr->sa_family == AF_LINK && - (sdl = ((struct sockaddr_dl *) ifa->ifa_addr)) != NULL && - sdl->sdl_type == IFT_ETHER) - break; - - if (sdl == NULL) - panic("bootpc: Unable to find HW address for %s", - ifctx->ireq.ifr_name); - ifctx->sdl = sdl; - - return error; -} - - -static int -bootpc_adjust_interface(struct bootpc_ifcontext *ifctx, - struct bootpc_globalcontext *gctx, struct thread *td) -{ - int error; - struct sockaddr_in defdst; - struct sockaddr_in defmask; - struct sockaddr_in *sin; - struct ifreq *ireq; - struct socket *so; - struct sockaddr_in *myaddr; - struct sockaddr_in *netmask; - struct sockaddr_in *gw; - - ireq = &ifctx->ireq; - so = ifctx->so; - myaddr = &ifctx->myaddr; - netmask = &ifctx->netmask; - gw = &ifctx->gw; - - if (bootpc_ifctx_isresolved(ifctx) == 0) { - - /* Shutdown interfaces where BOOTP failed */ - - printf("Shutdown interface %s\n", ifctx->ireq.ifr_name); - error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, td); - if (error != 0) - panic("bootpc_adjust_interface: " - "SIOCGIFFLAGS, error=%d", error); - ireq->ifr_flags &= ~IFF_UP; - error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, td); - if (error != 0) - panic("bootpc_adjust_interface: " - "SIOCSIFFLAGS, error=%d", error); - - sin = (struct sockaddr_in *) &ireq->ifr_addr; - clear_sinaddr(sin); - error = ifioctl(so, SIOCDIFADDR, (caddr_t) ireq, td); - if (error != 0 && (error != EEXIST || - ifctx == gctx->interfaces)) - panic("bootpc_adjust_interface: " - "SIOCDIFADDR, error=%d", error); - - return 0; - } - - printf("Adjusted interface %s\n", ifctx->ireq.ifr_name); - /* - * Do enough of ifconfig(8) so that the chosen interface - * can talk to the servers. (just set the address) - */ - bcopy(netmask, &ireq->ifr_addr, sizeof(*netmask)); - error = ifioctl(so, SIOCSIFNETMASK, (caddr_t) ireq, td); - if (error != 0) - panic("bootpc_adjust_interface: " - "set if netmask, error=%d", error); - - /* Broadcast is with host part of IP address all 1's */ - - sin = (struct sockaddr_in *) &ireq->ifr_addr; - clear_sinaddr(sin); - sin->sin_addr.s_addr = myaddr->sin_addr.s_addr | - ~ netmask->sin_addr.s_addr; - error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t) ireq, td); - if (error != 0) - panic("bootpc_adjust_interface: " - "set if broadcast addr, error=%d", error); - - bcopy(myaddr, &ireq->ifr_addr, sizeof(*myaddr)); - error = ifioctl(so, SIOCSIFADDR, (caddr_t) ireq, td); - if (error != 0 && (error != EEXIST || ifctx == gctx->interfaces)) - panic("bootpc_adjust_interface: " - "set if addr, error=%d", error); - - /* Add new default route */ - - if (ifctx->gotgw != 0 || gctx->gotgw == 0) { - clear_sinaddr(&defdst); - clear_sinaddr(&defmask); - error = rtrequest(RTM_ADD, - (struct sockaddr *) &defdst, - (struct sockaddr *) gw, - (struct sockaddr *) &defmask, - (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL); - if (error != 0) { - printf("bootpc_adjust_interface: " - "add net route, error=%d\n", error); - return error; - } - } - - return 0; -} - -static int -setfs(struct sockaddr_in *addr, char *path, char *p) -{ - unsigned int ip; - int val; - - ip = 0; - if (((val = getdec(&p)) < 0) || (val > 255)) - return 0; - ip = val << 24; - if (*p != '.') - return 0; - p++; - if (((val = getdec(&p)) < 0) || (val > 255)) - return 0; - ip |= (val << 16); - if (*p != '.') - return 0; - p++; - if (((val = getdec(&p)) < 0) || (val > 255)) - return 0; - ip |= (val << 8); - if (*p != '.') - return 0; - p++; - if (((val = getdec(&p)) < 0) || (val > 255)) - return 0; - ip |= val; - if (*p != ':') - return 0; - p++; - - addr->sin_addr.s_addr = htonl(ip); - addr->sin_len = sizeof(struct sockaddr_in); - addr->sin_family = AF_INET; - - strncpy(path, p, MNAMELEN - 1); - return 1; -} - -static int -getdec(char **ptr) -{ - char *p; - int ret; - - p = *ptr; - ret = 0; - if ((*p < '0') || (*p > '9')) - return -1; - while ((*p >= '0') && (*p <= '9')) { - ret = ret * 10 + (*p - '0'); - p++; - } - *ptr = p; - return ret; -} - -static char * -substr(char *a, char *b) -{ - char *loc1; - char *loc2; - - while (*a != '\0') { - loc1 = a; - loc2 = b; - while (*loc1 == *loc2++) { - if (*loc1 == '\0') - return 0; - loc1++; - if (*loc2 == '\0') - return loc1; - } - a++; - } - return 0; + bzero(sin, sizeof(*sin)); + sin->sin_len = sizeof(*sin); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = INADDR_ANY; /* XXX: htonl(INAADDR_ANY) ? */ + sin->sin_port = 0; } static void -mountopts(struct nfs_args *args, char *p) -{ - char *tmp; - - args->version = NFS_ARGSVERSION; - args->rsize = 8192; - args->wsize = 8192; - args->flags = NFSMNT_RSIZE | NFSMNT_WSIZE | NFSMNT_RESVPORT; - args->sotype = SOCK_DGRAM; - if (p == NULL) - return; - if ((tmp = (char *)substr(p, "rsize="))) - args->rsize = getdec(&tmp); - if ((tmp = (char *)substr(p, "wsize="))) - args->wsize = getdec(&tmp); - if ((tmp = (char *)substr(p, "intr"))) - args->flags |= NFSMNT_INT; - if ((tmp = (char *)substr(p, "soft"))) - args->flags |= NFSMNT_SOFT; - if ((tmp = (char *)substr(p, "noconn"))) - args->flags |= NFSMNT_NOCONN; - if ((tmp = (char *)substr(p, "tcp"))) - args->sotype = SOCK_STREAM; -} - -static int -xdr_opaque_decode(struct mbuf **mptr, u_char *buf, int len) -{ - struct mbuf *m; - int alignedlen; - - m = *mptr; - alignedlen = ( len + 3 ) & ~3; - - if (m->m_len < alignedlen) { - m = m_pullup(m, alignedlen); - if (m == NULL) { - *mptr = NULL; - return EBADRPC; - } - } - bcopy(mtod(m, u_char *), buf, len); - m_adj(m, alignedlen); - *mptr = m; - return 0; +nfs_convert_oargs(args, oargs) + struct nfs_args *args; + struct onfs_args *oargs; +{ + args->version = NFS_ARGSVERSION; + args->addr = oargs->addr; + args->addrlen = oargs->addrlen; + args->sotype = oargs->sotype; + args->proto = oargs->proto; + args->fh = oargs->fh; + args->fhsize = oargs->fhsize; + args->flags = oargs->flags; + args->wsize = oargs->wsize; + args->rsize = oargs->rsize; + args->readdirsize = oargs->readdirsize; + args->timeo = oargs->timeo; + args->retrans = oargs->retrans; + args->maxgrouplist = oargs->maxgrouplist; + args->readahead = oargs->readahead; + /* args->leaseterm = oargs->leaseterm; */ + args->deadthresh = oargs->deadthresh; + args->hostname = oargs->hostname; } -static int -xdr_int_decode(struct mbuf **mptr, int *iptr) -{ - u_int32_t i; - - if (xdr_opaque_decode(mptr, (u_char *) &i, sizeof(u_int32_t)) != 0) - return EBADRPC; - *iptr = fxdr_unsigned(u_int32_t, i); - return 0; +static void +nfs_convert_diskless() +{ + bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif, + sizeof(struct ifaliasreq)); + bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway, + sizeof(struct sockaddr_in)); + nfs_convert_oargs(&nfsv3_diskless.swap_args,&nfs_diskless.swap_args); + nfsv3_diskless.swap_fhsize = NFSX_V2FH; + bcopy(nfs_diskless.swap_fh,nfsv3_diskless.swap_fh,NFSX_V2FH); + bcopy(&nfs_diskless.swap_saddr,&nfsv3_diskless.swap_saddr, + sizeof(struct sockaddr_in)); + bcopy(nfs_diskless.swap_hostnam,nfsv3_diskless.swap_hostnam, MNAMELEN); + nfsv3_diskless.swap_nblks = nfs_diskless.swap_nblks; + bcopy(&nfs_diskless.swap_ucred, &nfsv3_diskless.swap_ucred, + sizeof(struct ucred)); + nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args); + nfsv3_diskless.root_fhsize = NFSX_V2FH; + bcopy(nfs_diskless.root_fh,nfsv3_diskless.root_fh,NFSX_V2FH); + bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr, + sizeof(struct sockaddr_in)); + bcopy(nfs_diskless.root_hostnam,nfsv3_diskless.root_hostnam, MNAMELEN); + nfsv3_diskless.root_time = nfs_diskless.root_time; + bcopy(nfs_diskless.my_hostnam,nfsv3_diskless.my_hostnam, + MAXHOSTNAMELEN); + nfs_diskless_valid = 3; } static void print_sin_addr(struct sockaddr_in *sin) -{ - - print_in_addr(sin->sin_addr); -} - +{ + print_in_addr(sin->sin_addr); +} + + static void print_in_addr(struct in_addr addr) -{ - unsigned int ip; - - ip = ntohl(addr.s_addr); - printf("%d.%d.%d.%d", - ip >> 24, (ip >> 16) & 255, (ip >> 8) & 255, ip & 255); -} - -static void -bootpc_compose_query(struct bootpc_ifcontext *ifctx, - struct bootpc_globalcontext *gctx, struct thread *td) -{ - unsigned char *vendp; - unsigned char vendor_client[64]; - uint32_t leasetime; - uint8_t vendor_client_len; - - ifctx->gotrootpath = 0; - - bzero((caddr_t) &ifctx->call, sizeof(ifctx->call)); - - /* bootpc part */ - ifctx->call.op = BOOTP_REQUEST; /* BOOTREQUEST */ - ifctx->call.htype = 1; /* 10mb ethernet */ - ifctx->call.hlen = ifctx->sdl->sdl_alen;/* Hardware address length */ - ifctx->call.hops = 0; - if (bootpc_ifctx_isunresolved(ifctx) != 0) - ifctx->xid++; - ifctx->call.xid = txdr_unsigned(ifctx->xid); - bcopy(LLADDR(ifctx->sdl), &ifctx->call.chaddr, ifctx->sdl->sdl_alen); - - vendp = ifctx->call.vend; - *vendp++ = 99; /* RFC1048 cookie */ - *vendp++ = 130; - *vendp++ = 83; - *vendp++ = 99; - *vendp++ = TAG_MAXMSGSIZE; - *vendp++ = 2; - *vendp++ = (sizeof(struct bootp_packet) >> 8) & 255; - *vendp++ = sizeof(struct bootp_packet) & 255; - - snprintf(vendor_client, sizeof(vendor_client), "%s:%s:%s", - ostype, MACHINE, osrelease); - vendor_client_len = strlen(vendor_client); - *vendp++ = TAG_VENDOR_INDENTIFIER; - *vendp++ = vendor_client_len; - memcpy(vendp, vendor_client, vendor_client_len); - vendp += vendor_client_len;; - ifctx->dhcpquerytype = DHCP_NOMSG; - switch (ifctx->state) { - case IF_DHCP_UNRESOLVED: - *vendp++ = TAG_DHCP_MSGTYPE; - *vendp++ = 1; - *vendp++ = DHCP_DISCOVER; - ifctx->dhcpquerytype = DHCP_DISCOVER; - ifctx->gotdhcpserver = 0; - break; - case IF_DHCP_OFFERED: - *vendp++ = TAG_DHCP_MSGTYPE; - *vendp++ = 1; - *vendp++ = DHCP_REQUEST; - ifctx->dhcpquerytype = DHCP_REQUEST; - *vendp++ = TAG_DHCP_REQ_ADDR; - *vendp++ = 4; - memcpy(vendp, &ifctx->reply.yiaddr, 4); - vendp += 4; - if (ifctx->gotdhcpserver != 0) { - *vendp++ = TAG_DHCP_SERVERID; - *vendp++ = 4; - memcpy(vendp, &ifctx->dhcpserver, 4); - vendp += 4; - } - *vendp++ = TAG_DHCP_LEASETIME; - *vendp++ = 4; - leasetime = htonl(300); - memcpy(vendp, &leasetime, 4); - vendp += 4; - default: - ; - } - *vendp = TAG_END; - - ifctx->call.secs = 0; - ifctx->call.flags = htons(0x8000); /* We need a broadcast answer */ +{ + unsigned int ip; + + ip = ntohl(addr.s_addr); + printf("%d.%d.%d.%d\n", + ip >> 24, (ip >> 16) & 255, (ip >> 8) & 255, ip & 255); +} + +static int +hwaddr_to_sockaddr(char *ev, struct sockaddr_dl *sa) +{ + char *cp; + u_int32_t a[6]; + + bzero(sa, sizeof(*sa)); + sa->sdl_len = sizeof(*sa); + sa->sdl_family = AF_LINK; + sa->sdl_type = IFT_ETHER; + sa->sdl_alen = ETHER_ADDR_LEN; + if ((cp = getenv(ev)) == NULL) + return(1); + if (sscanf(cp, "%x:%x:%x:%x:%x:%x", &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]) != 6) + return(1); + sa->sdl_data[0] = a[0]; + sa->sdl_data[1] = a[1]; + sa->sdl_data[2] = a[2]; + sa->sdl_data[3] = a[3]; + sa->sdl_data[4] = a[4]; + sa->sdl_data[5] = a[5]; + return(0); } static int -bootpc_hascookie(struct bootp_packet *bp) -{ - - return (bp->vend[0] == 99 && bp->vend[1] == 130 && - bp->vend[2] == 83 && bp->vend[3] == 99); +inaddr_to_sockaddr(char *ev, struct sockaddr_in *sa) +{ + u_int32_t a[4]; + char *cp; + struct sockaddr_in *sin; + + bzero(sa, sizeof(*sa)); + sa->sin_len = sizeof(*sa); + sa->sin_family = AF_INET; + + if ((cp = getenv(ev)) == NULL) + return(1); + if (sscanf(cp, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]) != 4) + return(1); + /* XXX is this ordering correct? */ + sa->sin_addr.s_addr = (a[3] << 24) + (a[2] << 16) + (a[1] << 8) + a[0]; + sin = (struct sockaddr_in *) sa; + print_sin_addr(sin); + return(0); } static void -bootpc_tag_helper(struct bootpc_tagcontext *tctx, - unsigned char *start, int len, int tag) -{ - unsigned char *j; - unsigned char *ej; - unsigned char code; - - if (tctx->badtag != 0 || tctx->badopt != 0) - return; - - j = start; - ej = j + len; - - while (j < ej) { - code = *j++; - if (code == TAG_PAD) - continue; - if (code == TAG_END) - return; - if (j >= ej || j + *j + 1 > ej) { - tctx->badopt = 1; - return; - } - len = *j++; - if (code == tag) { - if (tctx->taglen + len > TAG_MAXLEN) { - tctx->badtag = 1; - return; - } - tctx->foundopt = 1; - if (len > 0) - memcpy(tctx->buf + tctx->taglen, - j, len); - tctx->taglen += len; - } - if (code == TAG_OVERLOAD) - tctx->overload = *j; - - j += len; - } -} - -static unsigned char * -bootpc_tag(struct bootpc_tagcontext *tctx, - struct bootp_packet *bp, int len, int tag) -{ - unsigned char *j; - unsigned char *ej; - - tctx->overload = 0; - tctx->badopt = 0; - tctx->badtag = 0; - tctx->foundopt = 0; - tctx->taglen = 0; - - if (bootpc_hascookie(bp) == 0) - return NULL; - - j = &bp->vend[4]; - ej = (unsigned char *) bp + len; - - bootpc_tag_helper(tctx, &bp->vend[4], - (unsigned char *) bp + len - &bp->vend[4], tag); - - if ((tctx->overload & OVERLOAD_FILE) != 0) - bootpc_tag_helper(tctx, - (unsigned char *) bp->file, - sizeof(bp->file), - tag); - if ((tctx->overload & OVERLOAD_SNAME) != 0) - bootpc_tag_helper(tctx, - (unsigned char *) bp->sname, - sizeof(bp->sname), - tag); - - if (tctx->badopt != 0 || tctx->badtag != 0 || tctx->foundopt == 0) - return NULL; - tctx->buf[tctx->taglen] = '\0'; - return tctx->buf; -} - -static void -bootpc_decode_reply(struct nfsv3_diskless *nd, struct bootpc_ifcontext *ifctx, - struct bootpc_globalcontext *gctx) -{ - char *p; - unsigned int ip; - - ifctx->gotgw = 0; - ifctx->gotnetmask = 0; - - clear_sinaddr(&ifctx->myaddr); - clear_sinaddr(&ifctx->netmask); - clear_sinaddr(&ifctx->gw); - - ifctx->myaddr.sin_addr = ifctx->reply.yiaddr; - - ip = ntohl(ifctx->myaddr.sin_addr.s_addr); - snprintf(gctx->lookup_path, sizeof(gctx->lookup_path), - "swap.%d.%d.%d.%d", - ip >> 24, (ip >> 16) & 255, (ip >> 8) & 255, ip & 255); - - printf("%s at ", ifctx->ireq.ifr_name); - print_sin_addr(&ifctx->myaddr); - printf(" server "); - print_in_addr(ifctx->reply.siaddr); - - ifctx->gw.sin_addr = ifctx->reply.giaddr; - if (ifctx->reply.giaddr.s_addr != htonl(INADDR_ANY)) { - printf(" via gateway "); - print_in_addr(ifctx->reply.giaddr); - } - - /* This call used for the side effect (overload flag) */ - (void) bootpc_tag(&gctx->tmptag, - &ifctx->reply, ifctx->replylen, TAG_END); - - if ((gctx->tmptag.overload & OVERLOAD_SNAME) == 0) - if (ifctx->reply.sname[0] != '\0') - printf(" server name %s", ifctx->reply.sname); - if ((gctx->tmptag.overload & OVERLOAD_FILE) == 0) - if (ifctx->reply.file[0] != '\0') - printf(" boot file %s", ifctx->reply.file); - - printf("\n"); - - p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, - TAG_SUBNETMASK); - if (p != NULL) { - if (gctx->tag.taglen != 4) - panic("bootpc: subnet mask len is %d", - gctx->tag.taglen); - bcopy(p, &ifctx->netmask.sin_addr, 4); - ifctx->gotnetmask = 1; - printf("subnet mask "); - print_sin_addr(&ifctx->netmask); - printf(" "); +setup_nfsdiskless(void) +{ + struct nfs_diskless *nd = &nfs_diskless; + struct ifnet *ifp; + struct ifaddr *ifa; + struct sockaddr_dl *sdl, ourdl; + struct socket *so; + char *cp; + int error; + struct thread *td; + struct sockaddr_in mygw, myaddr, netmask; + struct nfsv3_diskless *nd3 = &nfsv3_diskless; + char *cp3; + + td = curthread; + + /* set up interface */ + printf("me........:"); + if (inaddr_to_sockaddr("boot.netif.ip", &myaddr)) { + printf("FHP: no ip\n"); + return; + } + printf("mask......:"); + if (inaddr_to_sockaddr("boot.netif.netmask", &netmask)) { + printf("FHP: no netmask\n"); + return; + } + bcopy(&myaddr, &nd->myif.ifra_addr, sizeof(myaddr)); + bcopy(&myaddr, &nd->myif.ifra_broadaddr, sizeof(myaddr)); + ((struct sockaddr_in *) &nd->myif.ifra_broadaddr)->sin_addr.s_addr = + myaddr.sin_addr.s_addr | ~ netmask.sin_addr.s_addr; + bcopy(&netmask, &nd->myif.ifra_mask, sizeof(netmask)); + + if (hwaddr_to_sockaddr("boot.netif.hwaddr", &ourdl)) { + printf("FHP: guessing hardware address...\n"); + ifa = NULL; + ifp = TAILQ_FIRST(&ifnet); + TAILQ_FOREACH(ifp, &ifnet, if_link) { + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + if ((ifa->ifa_addr->sa_family == AF_LINK) && + (sdl = ((struct sockaddr_dl *)ifa->ifa_addr))) { + if ((sdl->sdl_type == ourdl.sdl_type) && + (sdl->sdl_alen == ourdl.sdl_alen)) + goto guess_done; + } + } + } + guess_done: + sprintf(nd->myif.ifra_name, "%s%d", ifp->if_name, ifp->if_unit); + } else { + ifa = NULL; + ifp = TAILQ_FIRST(&ifnet); + TAILQ_FOREACH(ifp, &ifnet, if_link) { + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + if ((ifa->ifa_addr->sa_family == AF_LINK) && + (sdl = ((struct sockaddr_dl *)ifa->ifa_addr))) { + if ((sdl->sdl_type == ourdl.sdl_type) && + (sdl->sdl_alen == ourdl.sdl_alen) && + !bcmp(sdl->sdl_data + sdl->sdl_nlen, + ourdl.sdl_data + ourdl.sdl_nlen, + sdl->sdl_alen)) + goto match_done; + } + } + } + printf("FHP: no matching interface\n"); + return; + match_done: + sprintf(nd->myif.ifra_name, "%s%d", ifp->if_name, ifp->if_unit); } - p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, - TAG_ROUTERS); - if (p != NULL) { - /* Routers */ - if (gctx->tag.taglen % 4) - panic("bootpc: Router Len is %d", gctx->tag.taglen); - if (gctx->tag.taglen > 0) { - bcopy(p, &ifctx->gw.sin_addr, 4); - printf("router "); - print_sin_addr(&ifctx->gw); - printf(" "); - ifctx->gotgw = 1; - gctx->gotgw = 1; - } - } - p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, - TAG_ROOT); - if (p != NULL) { - if (gctx->setrootfs != NULL) { - printf("rootfs %s (ignored) ", p); - } else if (setfs(&nd->root_saddr, - nd->root_hostnam, p)) { - printf("rootfs %s ", p); - gctx->gotrootpath = 1; - ifctx->gotrootpath = 1; - gctx->setrootfs = ifctx; - - p = bootpc_tag(&gctx->tag, &ifctx->reply, - ifctx->replylen, - TAG_ROOTOPTS); - if (p != NULL) { - mountopts(&nd->root_args, p); - printf("rootopts %s ", p); - } - } else - panic("Failed to set rootfs to %s", p); - } + /* set up root mount */ + nd->root_args.rsize = 8192; /* XXX tunable? */ + nd->root_args.wsize = 8192; + nd->root_args.sotype = SOCK_DGRAM; + nd->root_args.flags = (NFSMNT_WSIZE | NFSMNT_RSIZE | NFSMNT_RESVPORT); + printf("NFS svr...:"); + if (inaddr_to_sockaddr("boot.nfsroot.server", &nd->root_saddr)) { + printf("FHP: no NFS server\n"); + return; + } + nd->root_saddr.sin_port = htons(NFS_PORT); - p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, - TAG_SWAP); - if (p != NULL) { - if (gctx->setswapfs != NULL) { - printf("swapfs %s (ignored) ", p); - } else if (setfs(&nd->swap_saddr, - nd->swap_hostnam, p)) { - gctx->gotswappath = 1; - gctx->setswapfs = ifctx; - printf("swapfs %s ", p); - - p = bootpc_tag(&gctx->tag, &ifctx->reply, - ifctx->replylen, - TAG_SWAPOPTS); - if (p != NULL) { - /* swap mount options */ - mountopts(&nd->swap_args, p); - printf("swapopts %s ", p); - } - - p = bootpc_tag(&gctx->tag, &ifctx->reply, - ifctx->replylen, - TAG_SWAPSIZE); - if (p != NULL) { - int swaplen; - if (gctx->tag.taglen != 4) - panic("bootpc: " - "Expected 4 bytes for swaplen, " - "not %d bytes", - gctx->tag.taglen); - bcopy(p, &swaplen, 4); - nd->swap_nblks = ntohl(swaplen); - printf("swapsize %d KB ", - nd->swap_nblks); - } - } else - panic("Failed to set swapfs to %s", p); - } + if ((cp = getenv("boot.netif.hostname")) != NULL) { + strncpy(nd->my_hostnam, cp, MAXHOSTNAMELEN - 1); + printf("hostname..:%s\n", nd->my_hostnam); + } - p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, - TAG_HOSTNAME); - if (p != NULL) { - if (gctx->tag.taglen >= MAXHOSTNAMELEN) - panic("bootpc: hostname >= %d bytes", - MAXHOSTNAMELEN); - if (gctx->sethostname != NULL) { - printf("hostname %s (ignored) ", p); - } else { - strcpy(nd->my_hostnam, p); - strcpy(hostname, p); - printf("hostname %s ", hostname); - gctx->sethostname = ifctx; - } - } - p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen, - TAG_COOKIE); - if (p != NULL) { /* store in a sysctl variable */ - int i, l = sizeof(bootp_cookie) - 1; - for (i = 0; i < l && p[i] != '\0'; i++) - bootp_cookie[i] = p[i]; - p[i] = '\0'; - } + if ((cp = getenv("boot.nfsroot.path")) != NULL) + strncpy(nd->root_hostnam, cp, MNAMELEN - 1); + + /* + * by Leal + * 2003-17-03 + * gateway... + */ + if ((cp = getenv("boot.netif.gateway")) != NULL) { + /* set up gw */ + printf("gw........:"); + if (inaddr_to_sockaddr("boot.netif.gateway", &mygw)) { + printf("FHP: no gateway\n"); + return; + } + } + nfs_convert_diskless(); + /* + * Do enough of ifconfig(8) so that the chosen interface + * can talk to the servers. (just set the address) + */ + error = socreate(nd3->myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0, td->td_ucred, td); + if (error) + panic("FHP: socreate(%04x): %d", nd3->myif.ifra_addr.sa_family, error); + + error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd3->myif, td); + if (error) + panic("FHP: ifioctl error"); + + /* + * 2003-17-03 + * gateway... + */ + if (&mygw.sin_len != 0) { + struct sockaddr_in dst, mask; + clear_sinaddr(&dst); + clear_sinaddr(&mask); + error = rtrequest(RTM_ADD, + (struct sockaddr *) &dst, + (struct sockaddr *) &mygw, + (struct sockaddr *) &mask, + (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL); + if (error != 0) + panic("FHP gateway: RTM_ADD: %d", error); + } - printf("\n"); - if (ifctx->gotnetmask == 0) { - if (IN_CLASSA(ntohl(ifctx->myaddr.sin_addr.s_addr))) - ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSA_NET); - else if (IN_CLASSB(ntohl(ifctx->myaddr.sin_addr.s_addr))) - ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSB_NET); - else - ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSC_NET); - } - if (ifctx->gotgw == 0) { - /* Use proxyarp */ - ifctx->gw.sin_addr.s_addr = ifctx->myaddr.sin_addr.s_addr; - } -} + if ((cp3 = getenv("boot.nfsroot.path")) != NULL) { + strncpy(nd3->root_hostnam, cp3, MNAMELEN - 1); + } + error = get_file_handle(&nd3->root_saddr, nd3->root_hostnam, nd3->root_fh, &nd3->root_fhsize, &nd3->root_args, td); + if (error != 0 ) + panic ("FHP: get_file_handle error"); +} -void -bootpc_init(void) +static int +xdr_int_decode(struct mbuf **mptr, int *iptr) { - struct bootpc_ifcontext *ifctx, *nctx; /* Interface BOOTP contexts */ - struct bootpc_globalcontext *gctx; /* Global BOOTP context */ - struct ifnet *ifp; - int error; - struct nfsv3_diskless *nd; - struct thread *td; - - nd = &nfsv3_diskless; - td = curthread; - - /* - * If already filled in, don't touch it here - */ - if (nfs_diskless_valid != 0) - return; - - gctx = malloc(sizeof(*gctx), M_TEMP, M_WAITOK); - if (gctx == NULL) - panic("Failed to allocate bootp global context structure"); - - bzero(gctx, sizeof(*gctx)); - gctx->xid = ~0xFFFF; - gctx->starttime = time_second; - - ifctx = allocifctx(gctx); - - /* - * Find a network interface. - */ -#ifdef BOOTP_WIRED_TO - printf("bootpc_init: wired to interface '%s'\n", - __XSTRING(BOOTP_WIRED_TO)); -#endif - bzero(&ifctx->ireq, sizeof(ifctx->ireq)); - IFNET_RLOCK(); - for (ifp = TAILQ_FIRST(&ifnet); - ifp != NULL; - ifp = TAILQ_NEXT(ifp, if_link)) { - snprintf(ifctx->ireq.ifr_name, sizeof(ifctx->ireq.ifr_name), - "%s%d", ifp->if_name, ifp->if_unit); -#ifdef BOOTP_WIRED_TO - if (strcmp(ifctx->ireq.ifr_name, - __XSTRING(BOOTP_WIRED_TO)) != 0) - continue; -#else - if ((ifp->if_flags & - (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) != - IFF_BROADCAST) - continue; -#endif - if (gctx->interfaces != NULL) - gctx->lastinterface->next = ifctx; - else - gctx->interfaces = ifctx; - ifctx->ifp = ifp; - gctx->lastinterface = ifctx; - ifctx = allocifctx(gctx); - } - IFNET_RUNLOCK(); - free(ifctx, M_TEMP); - - if (gctx->interfaces == NULL) { -#ifdef BOOTP_WIRED_TO - panic("bootpc_init: Could not find interface specified " - "by BOOTP_WIRED_TO: " - __XSTRING(BOOTP_WIRED_TO)); -#else - panic("bootpc_init: no suitable interface"); -#endif - } - - gctx->gotrootpath = 0; - gctx->gotswappath = 0; - gctx->gotgw = 0; - - for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) - bootpc_fakeup_interface(ifctx, gctx, td); - - for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) - bootpc_compose_query(ifctx, gctx, td); - - ifctx = gctx->interfaces; - error = bootpc_call(gctx, td); - - if (error != 0) { -#ifdef BOOTP_NFSROOT - panic("BOOTP call failed"); -#else - printf("BOOTP call failed\n"); -#endif - } - - mountopts(&nd->root_args, NULL); - - mountopts(&nd->swap_args, NULL); - - for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) - if (bootpc_ifctx_isresolved(ifctx) != 0) - bootpc_decode_reply(nd, ifctx, gctx); - - if (gctx->gotswappath == 0) - nd->swap_nblks = 0; -#ifdef BOOTP_NFSROOT - if (gctx->gotrootpath == 0) - panic("bootpc: No root path offered"); -#endif - - for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) { - bootpc_adjust_interface(ifctx, gctx, td); - - soclose(ifctx->so); - } - - for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) - if (ifctx->gotrootpath != 0) - break; - if (ifctx == NULL) { - for (ifctx = gctx->interfaces; - ifctx != NULL; - ifctx = ifctx->next) - if (bootpc_ifctx_isresolved(ifctx) != 0) - break; - } - if (ifctx == NULL) - goto out; - - if (gctx->gotrootpath != 0) { - - error = md_mount(&nd->root_saddr, nd->root_hostnam, - nd->root_fh, &nd->root_fhsize, - &nd->root_args, td); - if (error != 0) - panic("nfs_boot: mountd root, error=%d", error); - - if (gctx->gotswappath != 0) { - - error = md_mount(&nd->swap_saddr, - nd->swap_hostnam, - nd->swap_fh, &nd->swap_fhsize, - &nd->swap_args, td); - if (error != 0) - panic("nfs_boot: mountd swap, error=%d", - error); - - error = md_lookup_swap(&nd->swap_saddr, - gctx->lookup_path, - nd->swap_fh, &nd->swap_fhsize, - &nd->swap_args, td); - if (error != 0) - panic("nfs_boot: lookup swap, error=%d", - error); - } - nfs_diskless_valid = 3; - } - - strcpy(nd->myif.ifra_name, ifctx->ireq.ifr_name); - bcopy(&ifctx->myaddr, &nd->myif.ifra_addr, sizeof(ifctx->myaddr)); - bcopy(&ifctx->myaddr, &nd->myif.ifra_broadaddr, sizeof(ifctx->myaddr)); - ((struct sockaddr_in *) &nd->myif.ifra_broadaddr)->sin_addr.s_addr = - ifctx->myaddr.sin_addr.s_addr | - ~ ifctx->netmask.sin_addr.s_addr; - bcopy(&ifctx->netmask, &nd->myif.ifra_mask, sizeof(ifctx->netmask)); + u_int32_t i; + if (xdr_opaque_decode(mptr, (u_char *) &i, sizeof(u_int32_t)) != 0) + return EBADRPC; + *iptr = fxdr_unsigned(u_int32_t, i); + return 0; +} + +static int +xdr_opaque_decode(struct mbuf **mptr, u_char *buf, int len) +{ + struct mbuf *m; + int alignedlen; -out: - for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = nctx) { - nctx = ifctx->next; - free(ifctx, M_TEMP); - } - free(gctx, M_TEMP); + m = *mptr; + alignedlen = ( len + 3 ) & ~3; + + if (m->m_len < alignedlen) { + m = m_pullup(m, alignedlen); + if (m == NULL) { + *mptr = NULL; + return EBADRPC; + } + } + bcopy(mtod(m, u_char *), buf, len); + m_adj(m, alignedlen); + *mptr = m; + return 0; } -/* - * RPC: mountd/mount - * Given a server pathname, get an NFS file handle. - * Also, sets sin->sin_port to the NFS service port. - */ +/* obtain the "magic" file number... */ static int -md_mount(struct sockaddr_in *mdsin, char *path, u_char *fhp, int *fhsizep, - struct nfs_args *args, struct thread *td) -{ - struct mbuf *m; - int error; - int authunixok; - int authcount; - int authver; +get_file_handle(struct sockaddr_in *mdsin, /* mountd server address */ + char *path, + u_char *fhp, + int *fhsizep, + struct nfs_args *args, + struct thread *td) +{ + struct mbuf *m; + int error; + int authunixok; + int authcount; + int authver; #ifdef BOOTP_NFSV3 - /* First try NFS v3 */ - /* Get port number for MOUNTD. */ - error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER3, - &mdsin->sin_port, td); - if (error == 0) { - m = xdr_string_encode(path, strlen(path)); - - /* Do RPC to mountd. */ - error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER3, - RPCMNT_MOUNT, &m, NULL, td); - } - if (error == 0) { - args->flags |= NFSMNT_NFSV3; - } else { -#endif - /* Fallback to NFS v2 */ - - /* Get port number for MOUNTD. */ - error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1, - &mdsin->sin_port, td); - if (error != 0) - return error; - - m = xdr_string_encode(path, strlen(path)); - - /* Do RPC to mountd. */ - error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1, - RPCMNT_MOUNT, &m, NULL, td); - if (error != 0) - return error; /* message already freed */ + /* First try NFS v3 */ + /* Get port number for MOUNTD. */ + error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER3, + &mdsin->sin_port, td); + if (error == 0) { + m = xdr_string_encode(path, strlen(path)); + + /* Do RPC to mountd. */ + error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER3, + RPCMNT_MOUNT, &m, NULL, td); + } + if (error == 0) { + args->flags |= NFSMNT_NFSV3; + } else { +#endif + /* Fallback to NFS v2 */ + + /* Get port number for MOUNTD. */ + error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1, + &mdsin->sin_port, td); + if (error != 0) + return error; + + m = xdr_string_encode(path, strlen(path)); + + /* Do RPC to mountd. */ + error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1, + RPCMNT_MOUNT, &m, NULL, td); + if (error != 0) + return error; /* message already freed */ #ifdef BOOTP_NFSV3 - } + } #endif - if (xdr_int_decode(&m, &error) != 0 || error != 0) - goto bad; - - if ((args->flags & NFSMNT_NFSV3) != 0) { - if (xdr_int_decode(&m, fhsizep) != 0 || - *fhsizep > NFSX_V3FHMAX || - *fhsizep <= 0) - goto bad; - } else - *fhsizep = NFSX_V2FH; - - if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0) - goto bad; - - if (args->flags & NFSMNT_NFSV3) { - if (xdr_int_decode(&m, &authcount) != 0) - goto bad; - authunixok = 0; - if (authcount < 0 || authcount > 100) - goto bad; - while (authcount > 0) { - if (xdr_int_decode(&m, &authver) != 0) - goto bad; - if (authver == RPCAUTH_UNIX) - authunixok = 1; - authcount--; - } - if (authunixok == 0) - goto bad; - } - - /* Set port number for NFS use. */ - error = krpc_portmap(mdsin, NFS_PROG, - (args->flags & - NFSMNT_NFSV3) ? NFS_VER3 : NFS_VER2, - &mdsin->sin_port, td); - - goto out; - + if (xdr_int_decode(&m, &error) != 0 || error != 0) + goto bad; + + if ((args->flags & NFSMNT_NFSV3) != 0) { + if (xdr_int_decode(&m, fhsizep) != 0 || + *fhsizep > NFSX_V3FHMAX || + *fhsizep <= 0) + goto bad; + } else + *fhsizep = NFSX_V2FH; + + if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0) + goto bad; + + if (args->flags & NFSMNT_NFSV3) { + if (xdr_int_decode(&m, &authcount) != 0) + goto bad; + authunixok = 0; + if (authcount < 0 || authcount > 100) + goto bad; + while (authcount > 0) { + if (xdr_int_decode(&m, &authver) != 0) + goto bad; + if (authver == RPCAUTH_UNIX) + authunixok = 1; + authcount--; + } + if (authunixok == 0) + goto bad; + } + /* Set port number for NFS use. */ + error = krpc_portmap(mdsin, NFS_PROG, + (args->flags & + NFSMNT_NFSV3) ? NFS_VER3 : NFS_VER2, + &mdsin->sin_port, td); + + goto out; + bad: - error = EBADRPC; - + error = EBADRPC; + out: - m_freem(m); - return error; + m_freem(m); + return error; } -static int -md_lookup_swap(struct sockaddr_in *mdsin, char *path, u_char *fhp, int *fhsizep, - struct nfs_args *args, struct thread *td) +void +bootpc_init(void) { - struct mbuf *m; - int error; - int size = -1; - int attribs_present; - int status; - union { - u_int32_t v2[17]; - u_int32_t v3[21]; - } fattribs; - - m = m_get(M_TRYWAIT, MT_DATA); - if (m == NULL) - return ENOBUFS; - - if ((args->flags & NFSMNT_NFSV3) != 0) { - *mtod(m, u_int32_t *) = txdr_unsigned(*fhsizep); - bcopy(fhp, mtod(m, u_char *) + sizeof(u_int32_t), *fhsizep); - m->m_len = *fhsizep + sizeof(u_int32_t); - } else { - bcopy(fhp, mtod(m, u_char *), NFSX_V2FH); - m->m_len = NFSX_V2FH; - } - - m->m_next = xdr_string_encode(path, strlen(path)); - if (m->m_next == NULL) { - error = ENOBUFS; - goto out; - } - - /* Do RPC to nfsd. */ - if ((args->flags & NFSMNT_NFSV3) != 0) - error = krpc_call(mdsin, NFS_PROG, NFS_VER3, - NFSPROC_LOOKUP, &m, NULL, td); - else - error = krpc_call(mdsin, NFS_PROG, NFS_VER2, - NFSV2PROC_LOOKUP, &m, NULL, td); - if (error != 0) - return error; /* message already freed */ - - if (xdr_int_decode(&m, &status) != 0) - goto bad; - if (status != 0) { - error = ENOENT; - goto out; - } - - if ((args->flags & NFSMNT_NFSV3) != 0) { - if (xdr_int_decode(&m, fhsizep) != 0 || - *fhsizep > NFSX_V3FHMAX || - *fhsizep <= 0) - goto bad; - } else - *fhsizep = NFSX_V2FH; - - if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0) - goto bad; - - if ((args->flags & NFSMNT_NFSV3) != 0) { - if (xdr_int_decode(&m, &attribs_present) != 0) - goto bad; - if (attribs_present != 0) { - if (xdr_opaque_decode(&m, (u_char *) &fattribs.v3, - sizeof(u_int32_t) * 21) != 0) - goto bad; - size = fxdr_unsigned(u_int32_t, fattribs.v3[6]); - } - } else { - if (xdr_opaque_decode(&m,(u_char *) &fattribs.v2, - sizeof(u_int32_t) * 17) != 0) - goto bad; - size = fxdr_unsigned(u_int32_t, fattribs.v2[5]); - } - - if (nfsv3_diskless.swap_nblks == 0 && size != -1) { - nfsv3_diskless.swap_nblks = size / 1024; - printf("md_lookup_swap: Swap size is %d KB\n", - nfsv3_diskless.swap_nblks); - } - - goto out; - -bad: - error = EBADRPC; - -out: - m_freem(m); - return error; + /* If already filled in, don't touch it here */ + if (nfs_diskless_valid != 0) + return; + /* The start... */ + printf("---------------------------------FILE HANDLE PATCH\n"); + printf("--------------------------------------------------\n"); + setup_nfsdiskless(); + printf("--------------------------------------------------\n"); } >Release-Note: >Audit-Trail: >Unformatted: