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/common/syscall/systeminfo.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 /*
    2  * CDDL HEADER START
    3  *
    4  * The contents of this file are subject to the terms of the
    5  * Common Development and Distribution License (the "License").
    6  * You may not use this file except in compliance with the License.
    7  *
    8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
    9  * or http://www.opensolaris.org/os/licensing.
   10  * See the License for the specific language governing permissions
   11  * and limitations under the License.
   12  *
   13  * When distributing Covered Code, include this CDDL HEADER in each
   14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
   15  * If applicable, add the following below this CDDL HEADER, with the
   16  * fields enclosed by brackets "[]" replaced with your own identifying
   17  * information: Portions Copyright [yyyy] [name of copyright owner]
   18  *
   19  * CDDL HEADER END
   20  */
   21 /*
   22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
   23  * Use is subject to license terms.
   24  */
   25 
   26 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
   27 /*        All rights reserved.  */
   28 
   29 #include <sys/param.h>
   30 #include <sys/types.h>
   31 #include <sys/sysmacros.h>
   32 #include <sys/systm.h>
   33 #include <sys/tuneable.h>
   34 #include <sys/errno.h>
   35 #include <sys/cred.h>
   36 #include <sys/utsname.h>
   37 #include <sys/systeminfo.h>
   38 #include <sys/unistd.h>
   39 #include <sys/debug.h>
   40 #include <sys/bootconf.h>
   41 #include <sys/socket.h>
   42 #include <sys/policy.h>
   43 #include <net/if.h>
   44 #include <sys/sunddi.h>
   45 #include <sys/promif.h>
   46 #include <sys/zone.h>
   47 #include <sys/model.h>
   48 #include <netinet/inetutil.h>
   49 
   50 static void get_netif_name(char *, char *);
   51 
   52 long
   53 systeminfo(int command, char *buf, long count)
   54 {
   55         int error = 0;
   56         long strcnt, getcnt;
   57         char *kstr;
   58         char hostidp[HW_HOSTID_LEN];
   59 
   60         if (count < 0 && command != SI_SET_HOSTNAME &&
   61             command != SI_SET_SRPC_DOMAIN)
   62                 return (set_errno(EINVAL));
   63 
   64         /*
   65          * Deal with the common "get a string" case first.
   66          */
   67         switch (command) {
   68         case SI_SYSNAME:
   69                 kstr = utsname.sysname;
   70                 break;
   71         case SI_HOSTNAME:
   72                 kstr = uts_nodename();
   73                 break;
   74         case SI_RELEASE:
   75                 kstr = utsname.release;
   76                 break;
   77         case SI_VERSION:
   78                 kstr = utsname.version;
   79                 break;
   80         case SI_MACHINE:
   81                 kstr = utsname.machine;
   82                 break;
   83 #ifdef _LP64
   84         case SI_ARCHITECTURE_64:
   85         case SI_ARCHITECTURE_K:
   86                 kstr = architecture;
   87                 break;
   88         case SI_ARCHITECTURE_32:
   89         case SI_ARCHITECTURE:
   90                 kstr = architecture_32;
   91                 break;
   92         case SI_ARCHITECTURE_NATIVE:
   93                 kstr = get_udatamodel() == DATAMODEL_NATIVE ?
   94                     architecture : architecture_32;
   95                 break;
   96 #else
   97         case SI_ARCHITECTURE_K:
   98         case SI_ARCHITECTURE_32:
   99         case SI_ARCHITECTURE:
  100         case SI_ARCHITECTURE_NATIVE:
  101                 kstr = architecture;
  102                 break;
  103 #endif
  104         case SI_HW_SERIAL:
  105                 (void) snprintf(hostidp, sizeof (hostidp), "%u",
  106                     zone_get_hostid(curzone));
  107                 kstr = hostidp;
  108                 break;
  109         case SI_HW_PROVIDER:
  110                 kstr = hw_provider;
  111                 break;
  112         case SI_SRPC_DOMAIN:
  113                 kstr = curproc->p_zone->zone_domain;
  114                 break;
  115         case SI_PLATFORM:
  116                 kstr = platform;
  117                 break;
  118         case SI_ISALIST:
  119                 kstr = isa_list;
  120                 break;
  121         default:
  122                 kstr = NULL;
  123                 break;
  124         }
  125 
  126         if (kstr != NULL) {
  127                 strcnt = strlen(kstr);
  128                 if (count > 0) {
  129                         if (count <= strcnt) {
  130                                 getcnt = count - 1;
  131                                 if (subyte(buf + getcnt, 0) < 0)
  132                                         return (set_errno(EFAULT));
  133                         } else {
  134                                 getcnt = strcnt + 1;
  135                         }
  136                         if (copyout(kstr, buf, getcnt))
  137                                 return (set_errno(EFAULT));
  138                 }
  139                 return (strcnt + 1);
  140         }
  141 
  142         switch (command) {
  143         case SI_DHCP_CACHE:
  144         {
  145                 char    *tmp;
  146                 unsigned int tlen, octlen;
  147 
  148                 if (dhcack == NULL) {
  149                         tmp = "";
  150                         strcnt = 0;
  151                 } else {
  152                         /*
  153                          * If the interface didn't have a name (bindable
  154                          * driver) to begin with, it might have one now.
  155                          * So, re-run strplumb_get_netdev_path() to see
  156                          * if one can be established at this time.
  157                          */
  158                         if (netdev_path == NULL || netdev_path[0] == '\0') {
  159                                 netdev_path = strplumb_get_netdev_path();
  160                         }
  161                         /*
  162                          * If the interface name has not yet been resolved
  163                          * and a validnetdev_path[] was stashed by
  164                          * loadrootmodules in swapgeneric.c, or established
  165                          * above, resolve the interface name now.
  166                          */
  167                         if (dhcifname[0] == '\0' &&
  168                             netdev_path != NULL && netdev_path[0] != '\0') {
  169                                 get_netif_name(netdev_path, dhcifname);
  170                         }
  171 
  172                         /*
  173                          * Form reply:
  174                          *  IFNAMESIZ array of dhcp i/f
  175                          *  hexascii representation of dhcp reply
  176                          */
  177                         octlen = dhcacklen * 2 + 1;
  178                         tlen = octlen + IFNAMSIZ;
  179                         tmp = kmem_alloc(tlen, KM_SLEEP);
  180                         (void) strncpy(tmp, dhcifname, IFNAMSIZ);
  181                         if (octet_to_hexascii(dhcack, dhcacklen,
  182                             &tmp[IFNAMSIZ], &octlen) != 0) {
  183                                 kmem_free(tmp, tlen);
  184                                 error = EINVAL;
  185                                 break;
  186                         } else {
  187                                 strcnt = IFNAMSIZ + octlen;
  188                         }
  189                 }
  190 
  191                 if (count > 0) {
  192                         if (count <= strcnt) {
  193                                 getcnt = count - 1;
  194                                 if (subyte((buf + getcnt), 0) < 0)
  195                                         goto fail;
  196                         } else {
  197                                 getcnt = strcnt + 1;
  198                         }
  199                         if (copyout(tmp, buf, getcnt))
  200                                 goto fail;
  201                 }
  202                 if (strcnt != 0)
  203                         kmem_free(tmp, tlen);
  204                 return (strcnt + 1);
  205 fail:
  206                 if (strcnt != 0)
  207                         kmem_free(tmp, tlen);
  208                 error = EFAULT;
  209                 break;
  210         }
  211 
  212         case SI_SET_HOSTNAME:
  213         {
  214                 size_t          len;
  215                 char            name[SYS_NMLN];
  216                 char            *name_to_use;
  217 
  218                 if ((error = secpolicy_systeminfo(CRED())) != 0)
  219                         break;
  220 
  221                 name_to_use = uts_nodename();
  222                 if ((error = copyinstr(buf, name, SYS_NMLN, &len)) != 0)
  223                         break;
  224 
  225                 /*
  226                  * Must be non-NULL string and string
  227                  * must be less than SYS_NMLN chars.
  228                  */
  229                 if (len < 2 || (len == SYS_NMLN && name[SYS_NMLN-1] != '\0')) {
  230                         error = EINVAL;
  231                         break;
  232                 }
  233 
  234                 /*
  235                  * Copy the name into the relevant zone's nodename.
  236                  */
  237                 (void) strcpy(name_to_use, name);
  238 
  239                 /*
  240                  * Notify other interested parties that the nodename was set
  241                  */
  242                 if (name_to_use == utsname.nodename) /* global zone nodename */
  243                         nodename_set();
  244 
  245                 return (len);
  246         }
  247 
  248         case SI_SET_SRPC_DOMAIN:
  249         {
  250                 char name[SYS_NMLN];
  251                 size_t len;
  252 
  253                 if ((error = secpolicy_systeminfo(CRED())) != 0)
  254                         break;
  255                 if ((error = copyinstr(buf, name, SYS_NMLN, &len)) != 0)
  256                         break;
  257                 /*
  258                  * If string passed in is longer than length
  259                  * allowed for domain name, fail.
  260                  */
  261                 if (len == SYS_NMLN && name[SYS_NMLN-1] != '\0') {
  262                         error = EINVAL;
  263                         break;
  264                 }
  265 
  266                 (void) strcpy(curproc->p_zone->zone_domain, name);
  267                 return (len);
  268         }
  269 
  270         default:
  271                 error = EINVAL;
  272                 break;
  273         }
  274 
  275         return (set_errno(error));
  276 }
  277 
  278 /*
  279  * i_path_find_node: Internal routine used by path_to_devinfo
  280  * to locate a given nodeid in the device tree.
  281  */
  282 struct i_path_findnode {
  283         pnode_t nodeid;
  284         dev_info_t *dip;
  285 };
  286 
  287 static int
  288 i_path_find_node(dev_info_t *dev, void *arg)
  289 {
  290         struct i_path_findnode *f = (struct i_path_findnode *)arg;
  291 
  292 
  293         if (ddi_get_nodeid(dev) == (int)f->nodeid) {
  294                 f->dip = dev;
  295                 return (DDI_WALK_TERMINATE);
  296         }
  297         return (DDI_WALK_CONTINUE);
  298 }
  299 
  300 /*
  301  * Return the devinfo node to a boot device
  302  */
  303 static dev_info_t *
  304 path_to_devinfo(char *path)
  305 {
  306         struct i_path_findnode fn;
  307         extern dev_info_t *top_devinfo;
  308 
  309         /*
  310          * Get the nodeid of the given pathname, if such a mapping exists.
  311          */
  312         fn.dip = NULL;
  313         fn.nodeid = prom_finddevice(path);
  314         if (fn.nodeid != OBP_BADNODE) {
  315                 /*
  316                  * Find the nodeid in our copy of the device tree and return
  317                  * whatever name we used to bind this node to a driver.
  318                  */
  319                 ddi_walk_devs(top_devinfo, i_path_find_node, (void *)(&fn));
  320         }
  321 
  322         return (fn.dip);
  323 }
  324 
  325 /*
  326  * Determine the network interface name from the device path argument.
  327  */
  328 static void
  329 get_netif_name(char *devname, char *ifname)
  330 {
  331         dev_info_t      *dip;
  332         major_t         ndev;
  333         char            *name;
  334         int             unit;
  335 
  336         dip = path_to_devinfo(devname);
  337         if (dip == NULL) {
  338                 cmn_err(CE_WARN, "get_netif_name: "
  339                     "can't bind driver for '%s'\n", devname);
  340                 return;
  341         }
  342 
  343         ndev = ddi_driver_major(dip);
  344         if (ndev == -1) {
  345                 cmn_err(CE_WARN, "get_netif_name: "
  346                     "no driver bound to '%s'\n", devname);
  347                 return;
  348         }
  349 
  350         name = ddi_major_to_name(ndev);
  351         if (name == NULL) {
  352                 cmn_err(CE_WARN, "get_netif_name: "
  353                     "no name for major number %d\n", ndev);
  354                 return;
  355         }
  356 
  357         unit = i_ddi_devi_get_ppa(dip);
  358         if (unit < 0) {
  359                 cmn_err(CE_WARN, "get_netif_name: "
  360                     "illegal unit number %d\n", unit);
  361                 return;
  362         }
  363 
  364         (void) snprintf(ifname, IFNAMSIZ, "%s%d", name, unit);
  365 }

Cache object: 4a2800b63c683a4eb1430f9c545e5a19


[ 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.