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