The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/boot/common/dev_net.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: dev_net.c,v 1.23 2008/04/28 20:24:06 martin Exp $      */
    2 
    3 /*-
    4  * Copyright (c) 1997 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Gordon W. Ross.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD: releng/8.2/sys/boot/common/dev_net.c 202408 2010-01-15 19:06:33Z marius $");
   34 
   35 /*-
   36  * This module implements a "raw device" interface suitable for
   37  * use by the stand-alone I/O library NFS code.  This interface
   38  * does not support any "block" access, and exists only for the
   39  * purpose of initializing the network interface, getting boot
   40  * parameters, and performing the NFS mount.
   41  *
   42  * At open time, this does:
   43  *
   44  * find interface      - netif_open()
   45  * RARP for IP address - rarp_getipaddress()
   46  * RPC/bootparams      - callrpc(d, RPC_BOOTPARAMS, ...)
   47  * RPC/mountd          - nfs_mount(sock, ip, path)
   48  *
   49  * the root file handle from mountd is saved in a global
   50  * for use by the NFS open code (NFS/lookup).
   51  */
   52 
   53 #include <machine/stdarg.h>
   54 #include <sys/param.h>
   55 #include <sys/socket.h>
   56 #include <net/if.h>
   57 #include <netinet/in.h>
   58 #include <netinet/in_systm.h>
   59 
   60 #include <stand.h>
   61 #include <string.h>
   62 #include <net.h>
   63 #include <netif.h>
   64 #include <bootp.h>
   65 #include <bootparam.h>
   66 
   67 #include "dev_net.h"
   68 #include "bootstrap.h"
   69 
   70 #ifdef  NETIF_DEBUG
   71 int debug = 0;
   72 #endif
   73 
   74 static char *netdev_name;
   75 static int netdev_sock = -1;
   76 static int netdev_opens;
   77 
   78 static int      net_init(void);
   79 static int      net_open(struct open_file *, ...);
   80 static int      net_close(struct open_file *);
   81 static void     net_cleanup(void);
   82 static int      net_strategy();
   83 static void     net_print(int);
   84 
   85 static int net_getparams(int sock);
   86 
   87 struct devsw netdev = {
   88         "net",
   89         DEVT_NET,
   90         net_init,
   91         net_strategy,
   92         net_open,
   93         net_close,
   94         noioctl,
   95         net_print,
   96         net_cleanup
   97 };
   98 
   99 static int
  100 net_init(void)
  101 {
  102 
  103         return (0);
  104 }
  105 
  106 /*
  107  * Called by devopen after it sets f->f_dev to our devsw entry.
  108  * This opens the low-level device and sets f->f_devdata.
  109  * This is declared with variable arguments...
  110  */
  111 static int
  112 net_open(struct open_file *f, ...)
  113 {
  114         va_list args;
  115         char *devname;          /* Device part of file name (or NULL). */
  116         int error = 0;
  117 
  118         va_start(args, f);
  119         devname = va_arg(args, char*);
  120         va_end(args);
  121 
  122 #ifdef  NETIF_OPEN_CLOSE_ONCE
  123         /* Before opening another interface, close the previous one first. */
  124         if (netdev_sock >= 0 && strcmp(devname, netdev_name) != 0)
  125                 net_cleanup();
  126 #endif
  127 
  128         /* On first open, do netif open, mount, etc. */
  129         if (netdev_opens == 0) {
  130                 /* Find network interface. */
  131                 if (netdev_sock < 0) {
  132                         netdev_sock = netif_open(devname);
  133                         if (netdev_sock < 0) {
  134                                 printf("net_open: netif_open() failed\n");
  135                                 return (ENXIO);
  136                         }
  137                         netdev_name = strdup(devname);
  138 #ifdef  NETIF_DEBUG
  139                         if (debug)
  140                                 printf("net_open: netif_open() succeeded\n");
  141 #endif
  142                 }
  143                 if (rootip.s_addr == 0) {
  144                         /* Get root IP address, and path, etc. */
  145                         error = net_getparams(netdev_sock);
  146                         if (error) {
  147                                 /* getparams makes its own noise */
  148                                 free(netdev_name);
  149                                 netif_close(netdev_sock);
  150                                 netdev_sock = -1;
  151                                 return (error);
  152                         }
  153                 }
  154         }
  155         netdev_opens++;
  156         f->f_devdata = &netdev_sock;
  157         return (error);
  158 }
  159 
  160 static int
  161 net_close(struct open_file *f)
  162 {
  163 
  164 #ifdef  NETIF_DEBUG
  165         if (debug)
  166                 printf("net_close: opens=%d\n", netdev_opens);
  167 #endif
  168 
  169         f->f_devdata = NULL;
  170 
  171 #ifndef NETIF_OPEN_CLOSE_ONCE
  172         /* Extra close call? */
  173         if (netdev_opens <= 0)
  174                 return (0);
  175         netdev_opens--;
  176         /* Not last close? */
  177         if (netdev_opens > 0)
  178                 return (0);
  179         /* On last close, do netif close, etc. */
  180 #ifdef  NETIF_DEBUG
  181         if (debug)
  182                 printf("net_close: calling net_cleanup()\n");
  183 #endif
  184         net_cleanup();
  185 #endif
  186         return (0);
  187 }
  188 
  189 static void
  190 net_cleanup(void)
  191 {
  192 
  193         if (netdev_sock >= 0) {
  194 #ifdef  NETIF_DEBUG
  195                 if (debug)
  196                         printf("net_cleanup: calling netif_close()\n");
  197 #endif
  198                 rootip.s_addr = 0;
  199                 free(netdev_name);
  200                 netif_close(netdev_sock);
  201                 netdev_sock = -1;
  202         }
  203 }
  204 
  205 static int
  206 net_strategy()
  207 {
  208 
  209         return (EIO);
  210 }
  211 
  212 #define SUPPORT_BOOTP
  213 
  214 /*
  215  * Get info for NFS boot: our IP address, our hostname,
  216  * server IP address, and our root path on the server.
  217  * There are two ways to do this:  The old, Sun way,
  218  * and the more modern, BOOTP way. (RFC951, RFC1048)
  219  *
  220  * The default is to use the Sun bootparams RPC
  221  * (because that is what the kernel will do).
  222  * MD code can make try_bootp initialied data,
  223  * which will override this common definition.
  224  */
  225 #ifdef  SUPPORT_BOOTP
  226 int try_bootp = 1;
  227 #endif
  228 
  229 extern n_long ip_convertaddr(char *p);
  230 
  231 static int
  232 net_getparams(int sock)
  233 {
  234         char buf[MAXHOSTNAMELEN];
  235         char temp[FNAME_SIZE];
  236         struct iodesc *d;
  237         int i;
  238         n_long smask;
  239 
  240 #ifdef  SUPPORT_BOOTP
  241         /*
  242          * Try to get boot info using BOOTP.  If we succeed, then
  243          * the server IP address, gateway, and root path will all
  244          * be initialized.  If any remain uninitialized, we will
  245          * use RARP and RPC/bootparam (the Sun way) to get them.
  246          */
  247         if (try_bootp)
  248                 bootp(sock, BOOTP_NONE);
  249         if (myip.s_addr != 0)
  250                 goto exit;
  251 #ifdef  NETIF_DEBUG
  252         if (debug)
  253                 printf("net_open: BOOTP failed, trying RARP/RPC...\n");
  254 #endif
  255 #endif
  256 
  257         /*
  258          * Use RARP to get our IP address.  This also sets our
  259          * netmask to the "natural" default for our address.
  260          */
  261         if (rarp_getipaddress(sock)) {
  262                 printf("net_open: RARP failed\n");
  263                 return (EIO);
  264         }
  265         printf("net_open: client addr: %s\n", inet_ntoa(myip));
  266 
  267         /* Get our hostname, server IP address, gateway. */
  268         if (bp_whoami(sock)) {
  269                 printf("net_open: bootparam/whoami RPC failed\n");
  270                 return (EIO);
  271         }
  272 #ifdef  NETIF_DEBUG
  273         if (debug)
  274                 printf("net_open: client name: %s\n", hostname);
  275 #endif
  276 
  277         /*
  278          * Ignore the gateway from whoami (unreliable).
  279          * Use the "gateway" parameter instead.
  280          */
  281         smask = 0;
  282         gateip.s_addr = 0;
  283         if (bp_getfile(sock, "gateway", &gateip, buf) == 0) {
  284                 /* Got it!  Parse the netmask. */
  285                 smask = ip_convertaddr(buf);
  286         }
  287         if (smask) {
  288                 netmask = smask;
  289 #ifdef  NETIF_DEBUG
  290                 if (debug)
  291                         printf("net_open: subnet mask: %s\n", intoa(netmask));
  292 #endif
  293         }
  294 #ifdef  NETIF_DEBUG
  295         if (gateip.s_addr && debug)
  296                 printf("net_open: net gateway: %s\n", inet_ntoa(gateip));
  297 #endif
  298 
  299         /* Get the root server and pathname. */
  300         if (bp_getfile(sock, "root", &rootip, rootpath)) {
  301                 printf("net_open: bootparam/getfile RPC failed\n");
  302                 return (EIO);
  303         }
  304 exit:
  305         /*
  306          * If present, strip the server's address off of the rootpath
  307          * before passing it along.  This allows us to be compatible with
  308          * the kernel's diskless (BOOTP_NFSROOT) booting conventions
  309          */
  310         for (i = 0; rootpath[i] != '\0' && i < FNAME_SIZE; i++)
  311                 if (rootpath[i] == ':')
  312                         break;
  313         if (i && i != FNAME_SIZE && rootpath[i] == ':') {
  314                 rootpath[i++] = '\0';
  315                 if (inet_addr(&rootpath[0]) != INADDR_NONE)
  316                         rootip.s_addr = inet_addr(&rootpath[0]);
  317                 bcopy(&rootpath[i], &temp[0], strlen(&rootpath[i])+1);
  318                 bcopy(&temp[0], &rootpath[0], strlen(&rootpath[i])+1);
  319         }
  320 #ifdef  NETIF_DEBUG
  321         if (debug) {
  322                 printf("net_open: server addr: %s\n", inet_ntoa(rootip));
  323                 printf("net_open: server path: %s\n", rootpath);
  324         }
  325 #endif
  326 
  327         d = socktodesc(sock);
  328         sprintf(temp, "%6D", d->myea, ":");
  329         setenv("boot.netif.ip", inet_ntoa(myip), 1);
  330         setenv("boot.netif.netmask", intoa(netmask), 1);
  331         setenv("boot.netif.gateway", inet_ntoa(gateip), 1);
  332         setenv("boot.netif.hwaddr", temp, 1);
  333         setenv("boot.nfsroot.server", inet_ntoa(rootip), 1);
  334         setenv("boot.nfsroot.path", rootpath, 1);
  335 
  336         return (0);
  337 }
  338 
  339 static void
  340 net_print(int verbose)
  341 {
  342         struct netif_driver *drv;
  343         int i, d, cnt;
  344 
  345         cnt = 0;
  346         for (d = 0; netif_drivers[d]; d++) {
  347                 drv = netif_drivers[d];
  348                 for (i = 0; i < drv->netif_nifs; i++) {
  349                         printf("\t%s%d:", "net", cnt++);
  350                         if (verbose)
  351                                 printf(" (%s%d)", drv->netif_bname,
  352                                     drv->netif_ifs[i].dif_unit);
  353                 }
  354         }
  355         printf("\n");
  356 }

Cache object: 500794d37c07354561b4539b73b14a10


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.