Home | History | Annotate | Download | only in inet
      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 2008 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 
     27 #include <sys/types.h>
     28 #include <sys/stat.h>
     29 #include <sys/stream.h>
     30 #include <sys/ddi.h>
     31 #include <sys/sunddi.h>
     32 #include <sys/priv_names.h>
     33 
     34 /*
     35  * This file contains generic goo needed to hook the STREAMS modules and
     36  * drivers that live under uts/common/inet into the DDI.  In order to use it,
     37  * each module/driver should #define the symbols below (as appropriate) and
     38  * then #include this source file; see the other uts/common/inet/<star>ddi.c
     39  * files for examples of this in action.
     40  *
     41  * The symbols that all modules and drivers must define are:
     42  *
     43  *	INET_NAME	 The name of the module/driver.
     44  *
     45  * The symbols that all modules must define are:
     46  *
     47  *	INET_MODSTRTAB	 The name of the `streamtab' structure for this module.
     48  *	INET_MODDESC	 The one-line description for this module.
     49  *	INET_MODMTFLAGS  The mt-streams(9F) flags for the module.
     50  *
     51  * The symbols that all drivers must define are:
     52  *
     53  *	INET_DEVSTRTAB	 The name of the `streamtab' structure for this driver.
     54  *	INET_DEVDESC	 The one-line description for this driver.
     55  *	INET_DEVMTFLAGS  The mt-streams(9F) flags for the driver.
     56  *	INET_DEVMINOR	 The minor number of the driver (usually 0).
     57  *
     58  * Drivers that need to masquerade as IP should set INET_DEVMTFLAGS to
     59  * IP_DEVMTFLAGS and set INET_DEVSTRTAB to ipinfo.
     60  */
     61 
     62 #if	!defined(INET_NAME)
     63 #error inetddi.c: INET_NAME is not defined!
     64 #elif	!defined(INET_DEVDESC) && !defined(INET_MODDESC)
     65 #error inetddi.c: at least one of INET_DEVDESC or INET_MODDESC must be defined!
     66 #elif	defined(INET_DEVDESC) && !defined(INET_DEVSTRTAB)
     67 #error inetddi.c: INET_DEVDESC is defined but INET_DEVSTRTAB is not!
     68 #elif	defined(INET_DEVDESC) && !defined(INET_DEVMTFLAGS)
     69 #error inetddi.c: INET_DEVDESC is defined but INET_DEVMTFLAGS is not!
     70 #elif	defined(INET_DEVDESC) && !defined(INET_DEVMINOR)
     71 #error inetddi.c: INET_DEVDESC is defined but INET_DEVMINOR is not!
     72 #elif	defined(INET_MODDESC) && !defined(INET_MODSTRTAB)
     73 #error inetddi.c: INET_MODDESC is defined but INET_MODSTRTAB is not!
     74 #elif	defined(INET_MODDESC) && !defined(INET_MODMTFLAGS)
     75 #error inetddi.c: INET_MODDESC is defined but INET_MODMTFLAGS is not!
     76 #endif
     77 
     78 #ifdef	INET_DEVDESC
     79 
     80 extern struct streamtab INET_DEVSTRTAB;
     81 
     82 /*
     83  * Drivers that actually want to be IP would set INET_DEVSTRTAB to ipinfo.
     84  */
     85 
     86 static dev_info_t *inet_dev_info;
     87 
     88 #define	INET_DEFAULT_PRIV_MODE	0666
     89 
     90 static struct dev_priv {
     91 	char *driver;
     92 	int privonly;
     93 	const char *read_priv;
     94 	const char *write_priv;
     95 } netdev_privs[] = {
     96 	{"icmp", PRIVONLY_DEV,	PRIV_NET_ICMPACCESS,	PRIV_NET_ICMPACCESS},
     97 	{"icmp6", PRIVONLY_DEV,	PRIV_NET_ICMPACCESS,	PRIV_NET_ICMPACCESS},
     98 	{"ip", PRIVONLY_DEV,	PRIV_NET_RAWACCESS,	PRIV_NET_RAWACCESS},
     99 	{"ip6", PRIVONLY_DEV,	PRIV_NET_RAWACCESS,	PRIV_NET_RAWACCESS},
    100 	{"keysock", PRIVONLY_DEV, PRIV_SYS_IP_CONFIG,	PRIV_SYS_IP_CONFIG},
    101 	{"ipsecah", PRIVONLY_DEV, PRIV_SYS_IP_CONFIG,	PRIV_SYS_IP_CONFIG},
    102 	{"ipsecesp", PRIVONLY_DEV, PRIV_SYS_IP_CONFIG,	PRIV_SYS_IP_CONFIG},
    103 	{"spdsock", PRIVONLY_DEV, PRIV_SYS_IP_CONFIG,	PRIV_SYS_IP_CONFIG},
    104 	{NULL,	0,		NULL,			NULL}
    105 };
    106 
    107 static int
    108 inet_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
    109 {
    110 	int i, ndevs;
    111 
    112 	if (cmd != DDI_ATTACH)
    113 		return (DDI_FAILURE);
    114 
    115 	inet_dev_info = devi;
    116 
    117 	ndevs = sizeof (netdev_privs) / sizeof (struct dev_priv);
    118 	for (i = 0; i < ndevs; i++) {
    119 		char *drv = netdev_privs[i].driver;
    120 		if (drv == NULL || strcmp(drv, ddi_driver_name(devi)) == 0)
    121 			break;
    122 	}
    123 
    124 	return (ddi_create_priv_minor_node(devi, INET_NAME, S_IFCHR,
    125 	    INET_DEVMINOR, DDI_PSEUDO, netdev_privs[i].privonly,
    126 	    netdev_privs[i].read_priv, netdev_privs[i].write_priv,
    127 	    INET_DEFAULT_PRIV_MODE));
    128 }
    129 
    130 static int
    131 inet_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
    132 {
    133 	if (cmd != DDI_DETACH)
    134 		return (DDI_FAILURE);
    135 
    136 	ASSERT(devi == inet_dev_info);
    137 
    138 	ddi_remove_minor_node(devi, NULL);
    139 	return (DDI_SUCCESS);
    140 }
    141 
    142 
    143 /* ARGSUSED */
    144 static int
    145 inet_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
    146 {
    147 	int error = DDI_FAILURE;
    148 
    149 	switch (cmd) {
    150 	case DDI_INFO_DEVT2DEVINFO:
    151 		if (inet_dev_info != NULL) {
    152 			*result = (void *)inet_dev_info;
    153 			error = DDI_SUCCESS;
    154 		}
    155 		break;
    156 
    157 	case DDI_INFO_DEVT2INSTANCE:
    158 		*result = NULL;
    159 		error = DDI_SUCCESS;
    160 		break;
    161 
    162 	default:
    163 		break;
    164 	}
    165 
    166 	return (error);
    167 }
    168 
    169 DDI_DEFINE_STREAM_OPS(inet_devops, nulldev, nulldev, inet_attach, inet_detach,
    170     nulldev, inet_info, INET_DEVMTFLAGS, &INET_DEVSTRTAB,
    171     ddi_quiesce_not_supported);
    172 
    173 static struct modldrv modldrv = {
    174 	&mod_driverops,
    175 	INET_DEVDESC,
    176 	&inet_devops
    177 };
    178 
    179 #endif /* INET_DEVDESC */
    180 
    181 #ifdef	INET_MODDESC
    182 extern struct streamtab INET_MODSTRTAB;
    183 
    184 static struct fmodsw fsw = {
    185 	INET_NAME,
    186 	&INET_MODSTRTAB,
    187 	INET_MODMTFLAGS
    188 };
    189 
    190 static struct modlstrmod modlstrmod = {
    191 	&mod_strmodops,
    192 	INET_MODDESC,
    193 	&fsw
    194 };
    195 #endif /* INET_MODDESC */
    196 
    197 static struct modlinkage modlinkage = {
    198 	MODREV_1,
    199 #ifdef	INET_DEVDESC
    200 	&modldrv,
    201 #endif
    202 #ifdef	INET_MODDESC
    203 	&modlstrmod,
    204 #endif
    205 	NULL
    206 };
    207