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 static LIST_HEAD(, bpf_provider_list) 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 ASSERT(bpf_provider_add(&bpf_mac) == 0); 172 dls_set_bpfattach(bpfattach, bpfdetach); 173 ipnet_set_bpfattach(bpfattach, bpfdetach, GLOBAL_ZONEID, 174 bpf_itap, bpf_provider_add); 175 176 /* 177 * Set up to be notified about zones coming and going 178 * so that proper interaction with ipnet is possible. 179 */ 180 bpf_inst = net_instance_alloc(NETINFO_VERSION); 181 if (bpf_inst == NULL) 182 goto attach_failed; 183 bpf_inst->nin_name = "bpf"; 184 bpf_inst->nin_create = bpf_create_inst; 185 bpf_inst->nin_destroy = bpf_destroy_inst; 186 bpf_inst->nin_shutdown = bpf_shutdown_inst; 187 if (net_instance_register(bpf_inst) != 0) { 188 net_instance_free(bpf_inst); 189 goto attach_failed; 190 } 191 192 return (DDI_SUCCESS); 193 /* NOTREACHED */ 194 case DDI_RESUME: 195 return (DDI_SUCCESS); 196 /* NOTREACHED */ 197 default: 198 break; 199 } 200 201 attach_failed: 202 203 /* 204 * Use our own detach routine to toss 205 * away any stuff we allocated above. 206 */ 207 (void) bpfilterdetach(); 208 (void) bpf_detach(dip, DDI_DETACH); 209 return (DDI_FAILURE); 210 } 211 212 static int 213 bpf_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 214 { 215 int error; 216 217 switch (cmd) { 218 case DDI_DETACH: 219 if (net_instance_unregister(bpf_inst) != 0) 220 return (DDI_FAILURE); 221 net_instance_free(bpf_inst); 222 223 ipnet_set_bpfattach(NULL, NULL, GLOBAL_ZONEID, NULL, 224 bpf_provider_remove); 225 /* 226 * Whilst we don't want to be notified about new devices that 227 * are being detached, to set the bpf detach function to NULL 228 * introduces a race condition between this kernel module 229 * unloading and a network interface driver also unloading. 230 */ 231 dls_set_bpfattach(NULL, bpfdetach); 232 error = bpfilterdetach(); 233 if (error != 0) 234 return (DDI_FAILURE); 235 /* 236 * Now everything is clean, set the detach to NULL too. 237 */ 238 dls_set_bpfattach(NULL, NULL); 239 ASSERT(bpf_provider_remove(&bpf_mac) == 0); 240 241 ASSERT(LIST_EMPTY(&bpf_providers)); 242 243 ddi_prop_remove_all(dip); 244 245 return (DDI_SUCCESS); 246 /* NOTREACHED */ 247 case DDI_SUSPEND: 248 case DDI_PM_SUSPEND: 249 return (DDI_SUCCESS); 250 /* NOTREACHED */ 251 default: 252 break; 253 } 254 return (DDI_FAILURE); 255 } 256 257 /*ARGSUSED*/ 258 static int 259 bpf_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 260 { 261 int error = DDI_FAILURE; 262 263 switch (infocmd) { 264 case DDI_INFO_DEVT2DEVINFO: 265 *result = bpf_dev_info; 266 error = DDI_SUCCESS; 267 break; 268 case DDI_INFO_DEVT2INSTANCE: 269 *result = (void *)0; 270 error = DDI_SUCCESS; 271 break; 272 default: 273 break; 274 } 275 return (error); 276 } 277 278 /* 279 * The two functions below work with and manage a list of providers that 280 * supply BPF with packets. Their addition and removal is only happens 281 * when the bpf module is attaching/detaching, thus there is no race 282 * condition to guard against with using locks as the kernel module system 283 * takes care of this for us. Similarly, bpf_provider_tickle() is called 284 * from bpf_setif, which implies an open file descriptor that would get 285 * in the way of detach being active. 286 */ 287 static int 288 bpf_provider_add(bpf_provider_t *provider) 289 { 290 bpf_provider_list_t *bp; 291 292 LIST_FOREACH(bp, &bpf_providers, bpl_next) { 293 if (bp->bpl_what == provider) 294 return (EEXIST); 295 } 296 297 298 bp = kmem_alloc(sizeof (*bp), KM_SLEEP); 299 bp->bpl_what = provider; 300 LIST_INSERT_HEAD(&bpf_providers, bp, bpl_next); 301 302 return (0); 303 } 304 305 static int 306 bpf_provider_remove(bpf_provider_t *provider) 307 { 308 bpf_provider_list_t *bp; 309 310 LIST_FOREACH(bp, &bpf_providers, bpl_next) { 311 if (bp->bpl_what == provider) 312 break; 313 } 314 315 if (bp == NULL) 316 return (ESRCH); 317 318 LIST_REMOVE(bp, bpl_next); 319 320 kmem_free(bp, sizeof (*bp)); 321 322 return (0); 323 } 324 325 /* 326 * return a pointer to the structure that holds all of the functions 327 * available to be used to support a particular packet provider. 328 */ 329 bpf_provider_t * 330 bpf_find_provider_by_id(int who) 331 { 332 bpf_provider_list_t *b; 333 334 LIST_FOREACH(b, &bpf_providers, bpl_next) { 335 if (b->bpl_what->bpr_unit == who) 336 return (b->bpl_what); 337 } 338 339 return (NULL); 340 } 341 342 /* 343 * This function is used by bpf_setif() to force an open() to be called on 344 * a given device name. If a device has been unloaded by the kernel, but it 345 * is still recognised, then calling this function will hopefully cause it 346 * to be loaded back into the kernel. When this function is called, it is 347 * not known which packet provider the name belongs to so all are tried. 348 */ 349 int 350 bpf_provider_tickle(char *name, zoneid_t zone) 351 { 352 bpf_provider_list_t *bp; 353 uintptr_t handle; 354 int tickled = 0; 355 356 LIST_FOREACH(bp, &bpf_providers, bpl_next) { 357 handle = 0; 358 if (bp->bpl_what->bpr_open(name, &handle, zone) == 0) { 359 bp->bpl_what->bpr_close(handle); 360 tickled++; 361 } else if (bp->bpl_what->bpr_unit == BPR_MAC) { 362 /* 363 * For mac devices, sometimes the open/close is not 364 * enough. In that case, further provocation is 365 * attempted by fetching the linkid and trying to 366 * use that as the key for open, rather than the 367 * name. 368 */ 369 datalink_id_t id; 370 371 if (bp->bpl_what->bpr_getlinkid(name, &id, 372 zone) == 0) { 373 if (bp->bpl_what->bpr_open(name, &handle, 374 zone) == 0) { 375 bp->bpl_what->bpr_close(handle); 376 tickled++; 377 } else { 378 mac_handle_t mh; 379 380 if (mac_open_by_linkid(id, &mh) == 0) { 381 mac_close(mh); 382 tickled++; 383 } 384 } 385 } 386 } 387 388 } 389 390 if (tickled != 0) 391 return (EWOULDBLOCK); 392 393 return (ENXIO); 394 } 395 396 /* 397 * The following three functions provide the necessary callbacks into 398 * the netinfo API. This API is primarily used to trigger awareness of 399 * when a zone is being torn down, allowing BPF to drive IPNET to 400 * tell it which interfaces need to go away. 401 */ 402 /*ARGSUSED*/ 403 static void * 404 bpf_create_inst(const netid_t netid) 405 { 406 /* 407 * BPF does not keep any per-instance state, its list of 408 * interfaces is global, as is its device hash table. 409 */ 410 return ((void *)bpf_itap); 411 } 412 413 /*ARGSUSED*/ 414 static void 415 bpf_shutdown_inst(const netid_t netid, void *arg) 416 { 417 zoneid_t zoneid; 418 419 zoneid = net_getzoneidbynetid(netid); 420 if (zoneid != GLOBAL_ZONEID) { 421 ipnet_set_bpfattach(NULL, NULL, zoneid, NULL, NULL); 422 } 423 } 424 425 /*ARGSUSED*/ 426 static void 427 bpf_destroy_inst(const netid_t netid, void *arg) 428 { 429 } 430 431 /* 432 * This function is required, and is called from bpfopen, rather than 433 * bpf_create_inst() for the simple reason that when bpf_create_inst() 434 * is called, the zone is not fully initialised yet. This leads fo 435 * functions that map the zoneid to pointers failing (when they should 436 * not be failing) and thus the system panic'ing. 437 */ 438 void 439 bpf_open_zone(const zoneid_t zoneid) 440 { 441 ipnet_set_bpfattach(bpfattach, bpfdetach, 442 zoneid, bpf_itap, bpf_provider_add); 443 } 444