Date: Tue, 10 Dec 2002 18:48:19 -0200 (BRST) From: Marcelo Leal <msl@procergs.rs.gov.br> To: FreeBSD-gnats-submit@FreeBSD.org Subject: kern/46174: bootp_subr.c patch Message-ID: <20021210204819.64EF3E97D457@lagos.procergs.com.br>
next in thread | raw e-mail | index | archive | help
>Number: 46174 >Category: kern >Synopsis: bootp_subr.c patch >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Tue Dec 10 12:50:11 PST 2002 >Closed-Date: >Last-Modified: >Originator: Marcelo leal >Release: FreeBSD 4.7-RELEASE i386 >Organization: PROCERGS >Environment: System: FreeBSD lagos.procergs.com.br 4.7-RELEASE FreeBSD 4.7-RELEASE #18: Tue Dec 10 12:51:17 BRST 2002 procergs@lagos.procergs.com.br:/usr/src/sys/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. Because the machines have hard drives, 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, root server and so configurations with bootp or pxe protocol... So i did some adaptations and patches in the bootp_subr.c code for fix this. Now i have a bootp_subr.c code that works fine! With the BOOTP and BOOTP_NFSROOT options in kernel config file, and replacing the default bootp_subr.c code for mine, The FreeBSD kernel can configure itself for nfs root filesystem (get a file handle too), without dynamic protocols. This is one more feature for FreeBSD project. I would be honor if the FreeBSD project lets me put my contribution in kernel source code... The variables in loader.conf: boot.netif.hostname= boot.netif.hwaddr= 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://oslo.procergs.com.br/tor/leal/FreeBSD/bootp_subr.c >How-To-Repeat: This report is not for bug, is a patch report. >Fix: /* $FreeBSD: src/sys/nfs/bootp_subr.c,v 1.20.2.8 2002/03/16 15:56:06 luigi Exp $ */ /* * Copyright (c) 2002 Marcelo Leal * Copyright (c) 1995 Gordon Ross, Adam Glass * Copyright (c) 1992 Regents of the University of California. * All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * 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. * 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. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * based on: * nfs/krpc_subr.c * $NetBSD: krpc_subr.c,v 1.10 1995/08/08 20:43:43 gwr Exp $ */ #include "opt_bootp.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/sockio.h> #include <sys/proc.h> #include <sys/malloc.h> #include <sys/mount.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/sysctl.h> #include <sys/uio.h> #include <net/if.h> #include <net/route.h> #include <netinet/in.h> #include <net/if_types.h> #include <net/if_dl.h> #include <nfs/rpcv2.h> #include <nfs/nfsproto.h> #include <nfs/nfs.h> #include <nfs/nfsdiskless.h> #include <nfs/krpc.h> #include <nfs/xdr_subs.h> #define ETHER_ADDR_LEN 6 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 proc *procp); 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 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 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); } static void print_in_addr(struct in_addr addr) { 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 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 setup_nfsdiskless() { 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 proc *procp; struct sockaddr_in myaddr, netmask; struct nfsv3_diskless *nd3 = &nfsv3_diskless; struct onfs_args oargs; char *cp3; procp = curproc; /* set up interface */ printf("me........:", "%s"); if (inaddr_to_sockaddr("boot.netif.ip", &myaddr)) { printf("FHP: no ip\n"); return; } printf("mask......:", "%s"); 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: no hardware address\n"); return; } 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 interface\n"); return; /* no matching interface */ match_done: sprintf(nd->myif.ifra_name, "%s%d", ifp->if_name, ifp->if_unit); /* 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...:", "%s"); 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); if ((cp = getenv("boot.netif.hostname")) != NULL) { strncpy(nd->my_hostnam, cp, MAXHOSTNAMELEN - 1); printf("hostname..:%s\n", nd->my_hostnam); } if ((cp = getenv("boot.nfsroot.path")) != NULL) strncpy(nd->root_hostnam, cp, MNAMELEN - 1); 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, procp); if (error) panic("FHP: socreate(%04x): %d", nd3->myif.ifra_addr.sa_family, error); error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd3->myif, procp); if (error) panic("FHP: ifioctl error", "%s"); 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, procp); if (error != 0 ) panic ("FHP: get_file_handle error", "%s"); } 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 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; } /* obtain the "magic" file number... */ static int get_file_handle(struct sockaddr_in *mdsin, /* mountd server address */ char *path, u_char *fhp, int *fhsizep, struct nfs_args *args, struct proc *procp) { 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, procp); 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, procp); } 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, procp); 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, procp); 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, procp); goto out; bad: error = EBADRPC; out: m_freem(m); return error; } void bootpc_init(void) { /* If already filled in, don't touch it here */ if (nfs_diskless_valid != 0) return; /* The start... */ printf("---------------------------------FILE HANDLE PATCH\n", "%s"); printf("\033\[01\;34mCia de Processamento de Dados do Rio Grande do Sul\033\[0m\n", "%s"); printf("--------------------------------------------------\n", "%s"); setup_nfsdiskless(); printf("--------------------------------------------------\n", "%s"); } >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20021210204819.64EF3E97D457>