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 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/param.h> 29 #include <sys/stat.h> 30 #include <sys/errno.h> 31 #include <sys/uio.h> 32 #include <sys/buf.h> 33 #include <sys/modctl.h> 34 #include <sys/open.h> 35 #include <sys/kmem.h> 36 #include <sys/conf.h> 37 #include <sys/cmn_err.h> 38 #include <sys/cred.h> 39 #include <sys/sunddi.h> 40 #include <sys/mac_provider.h> 41 #include <sys/dls_impl.h> 42 #include <inet/ipnet.h> 43 44 extern int bpfopen(dev_t *devp, int flag, int otyp, cred_t *cred); 45 extern int bpfclose(dev_t dev, int flag, int otyp, cred_t *cred); 46 extern int bpfread(dev_t dev, struct uio *uio_p, cred_t *cred_p); 47 extern int bpfwrite(dev_t dev, struct uio *uio, cred_t *cred); 48 extern int bpfchpoll(dev_t, short, int, short *, struct pollhead **); 49 extern int bpfioctl(dev_t, int, intptr_t, int, cred_t *, int *); 50 extern int bpfilterattach(void); 51 extern int bpfilterdetach(void); 52 53 extern bpf_provider_t bpf_mac; 54 extern bpf_provider_t bpf_ipnet; 55 56 static int bpf_attach(dev_info_t *, ddi_attach_cmd_t); 57 static void *bpf_create_inst(const netid_t); 58 static void bpf_destroy_inst(const netid_t, void *); 59 static int bpf_detach(dev_info_t *, ddi_detach_cmd_t); 60 static int bpf_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 61 static int bpf_provider_add(bpf_provider_t *); 62 static int bpf_provider_remove(bpf_provider_t *); 63 static void bpf_shutdown_inst(const netid_t, void *); 64 65 extern void bpfdetach(uintptr_t); 66 extern int bpf_bufsize; 67 extern int bpf_maxbufsize; 68 69 bpf_provider_head_t bpf_providers; 70 71 static struct cb_ops bpf_cb_ops = { 72 bpfopen, 73 bpfclose, 74 nodev, /* strategy */ 75 nodev, /* print */ 76 nodev, /* dump */ 77 bpfread, 78 bpfwrite, /* write */ 79 bpfioctl, /* ioctl */ 80 nodev, /* devmap */ 81 nodev, /* mmap */ 82 nodev, /* segmap */ 83 bpfchpoll, /* poll */ 84 ddi_prop_op, 85 NULL, 86 D_MTSAFE, 87 CB_REV, 88 nodev, /* aread */ 89 nodev, /* awrite */ 90 }; 91 92 static struct dev_ops bpf_ops = { 93 DEVO_REV, 94 0, 95 bpf_getinfo, 96 nulldev, 97 nulldev, 98 bpf_attach, 99 bpf_detach, 100 nodev, /* reset */ 101 &bpf_cb_ops, 102 (struct bus_ops *)0 103 }; 104 105 extern struct mod_ops mod_driverops; 106 static struct modldrv bpfmod = { 107 &mod_driverops, "Berkely Packet Filter", &bpf_ops 108 }; 109 static struct modlinkage modlink1 = { MODREV_1, &bpfmod, NULL }; 110 111 static dev_info_t *bpf_dev_info = NULL; 112 static net_instance_t *bpf_inst = NULL; 113 114 int 115 _init() 116 { 117 int bpfinst; 118 119 bpfinst = mod_install(&modlink1); 120 return (bpfinst); 121 } 122 123 int 124 _fini(void) 125 { 126 int bpfinst; 127 128 bpfinst = mod_remove(&modlink1); 129 return (bpfinst); 130 } 131 132 int 133 _info(struct modinfo *modinfop) 134 { 135 int bpfinst; 136 137 bpfinst = mod_info(&modlink1, modinfop); 138 return (bpfinst); 139 } 140 141 static int 142 bpf_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 143 { 144 145 switch (cmd) { 146 case DDI_ATTACH: 147 /* 148 * Default buffer size from bpf's driver.conf file 149 */ 150 bpf_bufsize = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 151 "buf_size", 32 * 1024); 152 /* 153 * Maximum buffer size from bpf's driver.conf file 154 */ 155 bpf_maxbufsize = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 156 "max_buf_size", 16 * 1024 * 1024); 157 158 if (ddi_create_minor_node(dip, "bpf", S_IFCHR, 0, 159 DDI_PSEUDO, 0) == DDI_FAILURE) { 160 ddi_remove_minor_node(dip, NULL); 161 goto attach_failed; 162 } 163 bpf_dev_info = dip; 164 ddi_report_dev(dip); 165 166 LIST_INIT(&bpf_providers); 167 168 if (bpfilterattach() != 0) 169 goto attach_failed; 170 171 ipnet_set_itap(bpf_itap); 172 VERIFY(bpf_provider_add(&bpf_ipnet) == 0); 173 VERIFY(bpf_provider_add(&bpf_mac) == 0); 174 175 /* 176 * Set up to be notified about zones coming and going 177 * so that proper interaction with ipnet is possible. 178 */ 179 bpf_inst = net_instance_alloc(NETINFO_VERSION); 180 if (bpf_inst == NULL) 181 goto attach_failed; 182 bpf_inst->nin_name = "bpf"; 183 bpf_inst->nin_create = bpf_create_inst; 184 bpf_inst->nin_destroy = bpf_destroy_inst; 185 bpf_inst->nin_shutdown = bpf_shutdown_inst; 186 if (net_instance_register(bpf_inst) != 0) { 187 net_instance_free(bpf_inst); 188 goto attach_failed; 189 } 190 191 return (DDI_SUCCESS); 192 /* NOTREACHED */ 193 case DDI_RESUME: 194 return (DDI_SUCCESS); 195 /* NOTREACHED */ 196 default: 197 break; 198 } 199 200 attach_failed: 201 202 /* 203 * Use our own detach routine to toss 204 * away any stuff we allocated above. 205 */ 206 (void) bpfilterdetach(); 207 (void) bpf_detach(dip, DDI_DETACH); 208 return (DDI_FAILURE); 209 } 210 211 static int 212 bpf_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 213 { 214 int error; 215 216 switch (cmd) { 217 case DDI_DETACH: 218 if (net_instance_unregister(bpf_inst) != 0) 219 return (DDI_FAILURE); 220 net_instance_free(bpf_inst); 221 222 ipnet_set_itap(NULL); 223 error = bpfilterdetach(); 224 if (error != 0) 225 return (DDI_FAILURE); 226 VERIFY(bpf_provider_remove(&bpf_ipnet) == 0); 227 VERIFY(bpf_provider_remove(&bpf_mac) == 0); 228 229 ASSERT(LIST_EMPTY(&bpf_providers)); 230 231 ddi_prop_remove_all(dip); 232 233 return (DDI_SUCCESS); 234 /* NOTREACHED */ 235 case DDI_SUSPEND: 236 case DDI_PM_SUSPEND: 237 return (DDI_SUCCESS); 238 /* NOTREACHED */ 239 default: 240 break; 241 } 242 return (DDI_FAILURE); 243 } 244 245 /*ARGSUSED*/ 246 static int 247 bpf_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 248 { 249 int error = DDI_FAILURE; 250 251 switch (infocmd) { 252 case DDI_INFO_DEVT2DEVINFO: 253 *result = bpf_dev_info; 254 error = DDI_SUCCESS; 255 break; 256 case DDI_INFO_DEVT2INSTANCE: 257 *result = (void *)0; 258 error = DDI_SUCCESS; 259 break; 260 default: 261 break; 262 } 263 return (error); 264 } 265 266 /* 267 * The two functions below work with and manage a list of providers that 268 * supply BPF with packets. Their addition and removal is only happens 269 * when the bpf module is attaching/detaching, thus there is no race 270 * condition to guard against with using locks as the kernel module system 271 * takes care of this for us. Similarly, bpf_provider_tickle() is called 272 * from bpf_setif, which implies an open file descriptor that would get 273 * in the way of detach being active. 274 */ 275 static int 276 bpf_provider_add(bpf_provider_t *provider) 277 { 278 bpf_provider_list_t *bp; 279 280 LIST_FOREACH(bp, &bpf_providers, bpl_next) { 281 if (bp->bpl_what == provider) 282 return (EEXIST); 283 } 284 285 286 bp = kmem_alloc(sizeof (*bp), KM_SLEEP); 287 bp->bpl_what = provider; 288 LIST_INSERT_HEAD(&bpf_providers, bp, bpl_next); 289 290 return (0); 291 } 292 293 static int 294 bpf_provider_remove(bpf_provider_t *provider) 295 { 296 bpf_provider_list_t *bp; 297 298 LIST_FOREACH(bp, &bpf_providers, bpl_next) { 299 if (bp->bpl_what == provider) 300 break; 301 } 302 303 if (bp == NULL) 304 return (ESRCH); 305 306 LIST_REMOVE(bp, bpl_next); 307 308 kmem_free(bp, sizeof (*bp)); 309 310 return (0); 311 } 312 313 /* 314 * return a pointer to the structure that holds all of the functions 315 * available to be used to support a particular packet provider. 316 */ 317 bpf_provider_t * 318 bpf_find_provider_by_id(int who) 319 { 320 bpf_provider_list_t *b; 321 322 LIST_FOREACH(b, &bpf_providers, bpl_next) { 323 if (b->bpl_what->bpr_unit == who) 324 return (b->bpl_what); 325 } 326 327 return (NULL); 328 } 329 330 /* 331 * This function is used by bpf_setif() to force an open() to be called on 332 * a given device name. If a device has been unloaded by the kernel, but it 333 * is still recognised, then calling this function will hopefully cause it 334 * to be loaded back into the kernel. When this function is called, it is 335 * not known which packet provider the name belongs to so all are tried. 336 */ 337 int 338 bpf_provider_tickle(char *name, zoneid_t zone) 339 { 340 bpf_provider_list_t *bp; 341 uintptr_t handle; 342 int tickled = 0; 343 344 LIST_FOREACH(bp, &bpf_providers, bpl_next) { 345 handle = 0; 346 if (bp->bpl_what->bpr_open(name, &handle, zone) == 0) { 347 bp->bpl_what->bpr_close(handle); 348 tickled++; 349 } else if (bp->bpl_what->bpr_unit == BPR_MAC) { 350 /* 351 * For mac devices, sometimes the open/close is not 352 * enough. In that case, further provocation is 353 * attempted by fetching the linkid and trying to 354 * use that as the key for open, rather than the 355 * name. 356 */ 357 datalink_id_t id; 358 359 if (bp->bpl_what->bpr_getlinkid(name, &id, 360 zone) == 0) { 361 if (bp->bpl_what->bpr_open(name, &handle, 362 zone) == 0) { 363 bp->bpl_what->bpr_close(handle); 364 tickled++; 365 } else { 366 mac_handle_t mh; 367 368 if (mac_open_by_linkid(id, &mh) == 0) { 369 mac_close(mh); 370 tickled++; 371 } 372 } 373 } 374 } 375 376 } 377 378 if (tickled != 0) 379 return (EWOULDBLOCK); 380 381 return (ENXIO); 382 } 383 384 /* 385 * The following three functions provide the necessary callbacks into 386 * the netinfo API. This API is primarily used to trigger awareness of 387 * when a zone is being torn down, allowing BPF to drive IPNET to 388 * tell it which interfaces need to go away. 389 */ 390 /*ARGSUSED*/ 391 static void * 392 bpf_create_inst(const netid_t netid) 393 { 394 /* 395 * BPF does not keep any per-instance state, its list of 396 * interfaces is global, as is its device hash table. 397 */ 398 return ((void *)bpf_itap); 399 } 400 401 /*ARGSUSED*/ 402 static void 403 bpf_shutdown_inst(const netid_t netid, void *arg) 404 { 405 } 406 407 /*ARGSUSED*/ 408 static void 409 bpf_destroy_inst(const netid_t netid, void *arg) 410 { 411 }