/*- * Called from the generic VFS startups. * This is the second stage of DEVFS initialisation. * The probed devices have already been loaded and the * basic structure of the DEVFS created. * We take the oportunity to mount the hidden DEVFS layer, so that * devices from devfs get sync'd. */ static int devfs_init(__unused struct vfsconf *vfsp) { if (devfs_sinit()) return (ENOTSUP); devfs_make_node(makedev(0, 0), DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0622, "console"); devfs_make_node(makedev(2, 0), DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0666, "tty"); if (setup_kmem) { devfs_setup_kmem(); } devfs_make_node(makedev(3, 2), DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0666, "null"); devfs_make_node(makedev(3, 3), DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0666, "zero"); devfs_make_node(makedev(6, 0), DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0600, "klog"); #if FDESC devfs_fdesc_init(); #endif return 0; }
__private_extern__ void devfs_setup_kmem(void) { devfs_make_node(makedev(3, 0), DEVFS_CHAR, UID_ROOT, GID_KMEM, 0640, "mem"); devfs_make_node(makedev(3, 1), DEVFS_CHAR, UID_ROOT, GID_KMEM, 0640, "kmem"); }
int ddi_create_minor_node(dev_info_t *dip, char *name, int spec_type, minor_t minor_num, char *node_type, int flag) { dev_t dev; int error=0; char *r, *dup; //printf("ddi_create_minor_node: name %s: %d,%d\n", name, flag, minor_num); dev = makedev(flag, minor_num); dip->dev = dev; /* * http://lists.apple.com/archives/darwin-kernel/2007/Nov/msg00038.html * * devfs_make_name() has an off-by-one error when using directories * and it appears Apple does not want to fix it. * * We then change "/" to "_" and create more Apple-like /dev names * */ MALLOC(dup, char *, strlen(name)+1, M_TEMP, M_WAITOK); if (dup == NULL) return ENOMEM; bcopy(name, dup, strlen(name)); dup[strlen(name)] = '\0'; for (r = dup; (r=strchr(r, '/')); *r = '_') /* empty */ ; dip->devc = NULL; dip->devb = NULL; if (spec_type == S_IFCHR) dip->devc = devfs_make_node(dev, DEVFS_CHAR, /* Make the node */ UID_ROOT, GID_OPERATOR, 0600, "rdisk_%s", dup); //0600, "rdisk3", dup); else dip->devb = devfs_make_node(dev, DEVFS_BLOCK, /* Make the node */ UID_ROOT, GID_OPERATOR, 0600, "disk_%s", dup); //0600, "disk3", dup); //printf("ddi_create_minor: devfs_make_name '%s'\n", dup ); FREE(dup, M_TEMP); return error; }
static void vndevice_do_init( void ) { int i; vndevice_bdev_major = bdevsw_add(BDEV_MAJOR, &vn_bdevsw); if (vndevice_bdev_major < 0) { printf("vndevice_init: bdevsw_add() returned %d\n", vndevice_bdev_major); return; } vndevice_cdev_major = cdevsw_add_with_bdev(CDEV_MAJOR, &vn_cdevsw, vndevice_bdev_major); if (vndevice_cdev_major < 0) { printf("vndevice_init: cdevsw_add() returned %d\n", vndevice_cdev_major); return; } for (i = 0; i < NVNDEVICE; i++) { dev_t dev = makedev(vndevice_bdev_major, i); vn_table[i].sc_bdev = devfs_make_node(dev, DEVFS_BLOCK, UID_ROOT, GID_OPERATOR, 0600, "vn%d", i); if (vn_table[i].sc_bdev == NULL) printf("vninit: devfs_make_node failed!\n"); } }
/** * Register VBoxGuest char device */ static int vgdrvDarwinCharDevInit(void) { int rc = RTSpinlockCreate(&g_Spinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxGuestDarwin"); if (RT_SUCCESS(rc)) { /* * Registering ourselves as a character device. */ g_iMajorDeviceNo = cdevsw_add(-1, &g_DevCW); if (g_iMajorDeviceNo >= 0) { g_hDevFsDeviceSys = devfs_make_node(makedev(g_iMajorDeviceNo, 0), DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0666, DEVICE_NAME_SYS); if (g_hDevFsDeviceSys != NULL) { /* * Register a sleep/wakeup notification callback. */ g_pSleepNotifier = registerPrioritySleepWakeInterest(&vgdrvDarwinSleepHandler, &g_DevExt, NULL); if (g_pSleepNotifier != NULL) { return KMOD_RETURN_SUCCESS; } } } vgdrvDarwinCharDevRemove(); } return KMOD_RETURN_FAILURE; }
// Driver entry point. Initializes globals and registers driver node in /dev. kern_return_t pmem_start(kmod_info_t * ki, void *d) { int error = 0; pmem_log("Loading /dev/%s driver", pmem_pmem_devname); // Memory allocations are tagged to prevent leaks pmem_tag = OSMalloc_Tagalloc(pmem_tagname, OSMT_DEFAULT); // Allocate one page for zero padding of illegal read requests pmem_zero_page = static_cast<uint8_t *>(OSMalloc(PAGE_SIZE, pmem_tag)); if (pmem_zero_page == NULL) { pmem_error("Failed to allocate memory for page buffer"); return pmem_cleanup(KERN_FAILURE); } bzero(pmem_zero_page, PAGE_SIZE); // Access the boot arguments through the platform export, // and parse the systems physical memory configuration. boot_args * ba = reinterpret_cast<boot_args *>(PE_state.bootArgs); pmem_physmem_size = ba->PhysicalMemorySize; pmem_mmap = reinterpret_cast<EfiMemoryRange *>(ba->MemoryMap + pmem_kernel_voffset); pmem_mmap_desc_size = ba->MemoryMapDescriptorSize; pmem_mmap_size = ba->MemoryMapSize; pmem_log("Size of physical memory:%lld", pmem_physmem_size); pmem_log("Size of physical pages:%d (PAGE_SHIFT=%d, PAGE_MASK=%#016x)", PAGE_SIZE, PAGE_SHIFT, PAGE_MASK); pmem_log("Phys. Memory map at:%#016llx (size:%lld desc_size:%d)", pmem_mmap, pmem_mmap_size, pmem_mmap_desc_size); pmem_log("Number of segments in memory map: %d", pmem_mmap_size / pmem_mmap_desc_size); // Install switch table pmem_devmajor = cdevsw_add(-1, &pmem_cdevsw); if (pmem_devmajor == -1) { pmem_error("Failed to create character device"); return pmem_cleanup(KERN_FAILURE); } // Create physical memory device file pmem_log("Adding node /dev/%s", pmem_pmem_devname); pmem_devpmemnode = devfs_make_node(makedev(pmem_devmajor, pmem_dev_pmem_minor), DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0660, pmem_pmem_devname); if (pmem_devpmemnode == NULL) { pmem_error("Failed to create /dev/%s node", pmem_pmem_devname); return pmem_cleanup(KERN_FAILURE); } pmem_log("obtaining kernel dtb pointer"); __asm__ __volatile__("movq %%cr3, %0" :"=r"(pmem_dtb)); // Only bits 51-12 (inclusive) in cr3 are part of the dtb pointer pmem_dtb &= ~PAGE_MASK; pmem_log("kernel dtb: %#016llx", pmem_dtb); pmem_log("initializing pte_mmap module"); pmem_log("pmem driver loaded, physical memory available in /dev/%s", pmem_pmem_devname); return error; }
int ddi_create_minor_node(dev_info_t *dip, const char *name, int spec_type, minor_t minor_num, const char *node_type, int flag) { #pragma unused(spec_type,node_type,flag) dev_t dev = makedev( (uint32_t)dip, minor_num ); if (NULL == devfs_make_node( dev, DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0666, name, 0 )) return DDI_FAILURE; else return DDI_SUCCESS; }
kern_return_t OsqueryStart(kmod_info_t *ki, void *d) { dbg_printf("Kernel module starting!\n"); // Restart the queue and setup queue locks. // This does not allocate, share, or set the queue buffer or buffer values. osquery_cqueue_setup(&osquery.cqueue); // Initialize the IOCTL (and more) device node. osquery.major_number = cdevsw_add(osquery.major_number, &osquery_cdevsw); if (osquery.major_number < 0) { dbg_printf("Could not get a major number!\n"); goto error_exit; } // Create the IOCTL (and more) device node. osquery.devfs = devfs_make_node(makedev(osquery.major_number, 0), DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0600, "osquery", 0); if (osquery.devfs == NULL) { dbg_printf("Could not get a devfs entry!\n"); goto error_exit; } // Set up the IOCTL and kernel API locks (not queue locks). setup_locks(); return KERN_SUCCESS; error_exit: // Upon error, remove the device node if it was allocated. if (osquery.devfs != NULL) { devfs_remove(osquery.devfs); osquery.devfs = NULL; } // Tear down device node data. if (!(osquery.major_number < 0)) { if (cdevsw_remove(osquery.major_number, &osquery_cdevsw) < 0) { panic("osquery kext: Cannot remove osquery from cdevsw"); } } // Reset the queue and remove the queue locks. osquery_cqueue_teardown(&osquery.cqueue); return KERN_FAILURE; }
/** * Start the kernel module. */ static kern_return_t VBoxNetAdpDarwinStart(struct kmod_info *pKModInfo, void *pvData) { int rc; /* * Initialize IPRT and find our module tag id. * (IPRT is shared with VBoxDrv, it creates the loggers.) */ rc = RTR0Init(0); if (RT_SUCCESS(rc)) { Log(("VBoxNetAdpDarwinStart\n")); rc = vboxNetAdpInit(); if (RT_SUCCESS(rc)) { g_nCtlDev = cdevsw_add(-1, &g_ChDev); if (g_nCtlDev < 0) { LogRel(("VBoxAdp: failed to register control device.")); rc = VERR_CANT_CREATE; } else { g_hCtlDev = devfs_make_node(makedev(g_nCtlDev, 0), DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0600, VBOXNETADP_CTL_DEV_NAME); if (!g_hCtlDev) { LogRel(("VBoxAdp: failed to create FS node for control device.")); rc = VERR_CANT_CREATE; } } } if (RT_SUCCESS(rc)) { LogRel(("VBoxAdpDrv: version " VBOX_VERSION_STRING " r%d\n", VBOX_SVN_REV)); return KMOD_RETURN_SUCCESS; } LogRel(("VBoxAdpDrv: failed to initialize device extension (rc=%d)\n", rc)); RTR0Term(); } else printf("VBoxAdpDrv: failed to initialize IPRT (rc=%d)\n", rc); return KMOD_RETURN_FAILURE; }
bool IOSCSITape::InitializeDeviceSupport(void) { if (FindDeviceMinorNumber()) { cdev_node = devfs_make_node( makedev(CdevMajorIniter.majorNumber, tapeNumber), DEVFS_CHAR, UID_ROOT, GID_OPERATOR, 0664, TAPE_FORMAT, tapeNumber); if (cdev_node) { flags = 0; return true; } } return false; }
kern_return_t OsqueryStart(kmod_info_t *ki, void *d) { dbg_printf("Kernel module starting!\n"); osquery_cqueue_setup(&osquery.cqueue); osquery.major_number = cdevsw_add(osquery.major_number, &osquery_cdevsw); if (osquery.major_number < 0) { dbg_printf("Could not get a major number!\n"); goto error_exit; } osquery.devfs = devfs_make_node(makedev(osquery.major_number, 0), DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0644, "osquery", 0); if (osquery.devfs == NULL) { dbg_printf("Could not get a devfs entry!\n"); goto error_exit; } setup_locks(); return KERN_SUCCESS; error_exit: if (osquery.devfs != NULL) { devfs_remove(osquery.devfs); osquery.devfs = NULL; } if (!(osquery.major_number < 0)) { if (cdevsw_remove(osquery.major_number, &osquery_cdevsw) < 0) { panic("osquery kext: Cannot remove osquery from cdevsw"); } } osquery_cqueue_teardown(&osquery.cqueue); return KERN_FAILURE; }
// Driver entry point. Initializes globals and registers driver node in /dev. kern_return_t chipsec_start(kmod_info_t * ki, void *d) { int error = 0; pmem_log("Loading /dev/%s driver", chipsec_devname); // Memory allocations are tagged to prevent leaks pmem_tag = OSMalloc_Tagalloc(pmem_tagname, OSMT_DEFAULT); // Allocate one page for zero padding of illegal read requests pmem_zero_page = static_cast<uint8_t *>(OSMalloc(PAGE_SIZE, pmem_tag)); if (pmem_zero_page == NULL) { pmem_error("Failed to allocate memory for page buffer"); return pmem_cleanup(KERN_FAILURE); } bzero(pmem_zero_page, PAGE_SIZE); // Install the character device chipsec_dev_major = cdevsw_add(-1, &pmem_cdevsw); if (chipsec_dev_major == -1) { pmem_error("Failed to create character device"); return pmem_cleanup(KERN_FAILURE); } // Create physical memory device file pmem_log("Adding node /dev/%s", chipsec_devname); pmem_devpmemnode = devfs_make_node(makedev(chipsec_dev_major, chipsec_dev_minor), DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0660, chipsec_devname); if (pmem_devpmemnode == NULL) { pmem_error("Failed to create /dev/%s node", chipsec_devname); return pmem_cleanup(KERN_FAILURE); } pmem_log("pmem driver loaded, physical memory available in /dev/%s", chipsec_devname); return error; }
static int nsmb_dev_open_nolock(dev_t dev, int oflags, int devtype, struct proc *p) { #pragma unused(oflags, devtype, p) struct smb_dev *sdp; kauth_cred_t cred = vfs_context_ucred(vfs_context_current()); sdp = SMB_GETDEV(dev); if (sdp && (sdp->sd_flags & NSMBFL_OPEN)) return (EBUSY); if (!sdp || minor(dev) == 0) { int avail_minor; for (avail_minor = 1; avail_minor < SMBMINORS; avail_minor++) if (!SMB_GETDEV(avail_minor)) break; if (avail_minor >= SMBMINORS) { SMBERROR("Too many minor devices, %d >= %d !", avail_minor, SMBMINORS); return (ENOMEM); } SMB_MALLOC(sdp, struct smb_dev *, sizeof(*sdp), M_NSMBDEV, M_WAITOK); bzero(sdp, sizeof(*sdp)); dev = makedev(smb_major, avail_minor); sdp->sd_devfs = devfs_make_node(dev, DEVFS_CHAR, kauth_cred_getuid(cred), kauth_cred_getgid(cred), 0700, "nsmb%x", avail_minor); if (!sdp->sd_devfs) { SMBERROR("devfs_make_node failed %d\n", avail_minor); SMB_FREE(sdp, M_NSMBDEV); return (ENOMEM); } if (avail_minor > smb_minor_hiwat) smb_minor_hiwat = avail_minor; SMB_GETDEV(dev) = sdp; return (EBUSY); }
static int vniocattach_file(struct vn_softc *vn, struct vn_ioctl_64 *vniop, dev_t dev, int in_kernel, proc_t p) { dev_t cdev; vfs_context_t ctx = vfs_context_current(); kauth_cred_t cred; struct nameidata nd; off_t file_size; int error, flags; flags = FREAD|FWRITE; if (in_kernel) { NDINIT(&nd, LOOKUP, OP_OPEN, FOLLOW, UIO_SYSSPACE, vniop->vn_file, ctx); } else { NDINIT(&nd, LOOKUP, OP_OPEN, FOLLOW, (IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : UIO_USERSPACE32), vniop->vn_file, ctx); } /* vn_open gives both long- and short-term references */ error = vn_open(&nd, flags, 0); if (error) { if (error != EACCES && error != EPERM && error != EROFS) { return (error); } flags &= ~FWRITE; if (in_kernel) { NDINIT(&nd, LOOKUP, OP_OPEN, FOLLOW, UIO_SYSSPACE, vniop->vn_file, ctx); } else { NDINIT(&nd, LOOKUP, OP_OPEN, FOLLOW, (IS_64BIT_PROCESS(p) ? UIO_USERSPACE64 : UIO_USERSPACE32), vniop->vn_file, ctx); } error = vn_open(&nd, flags, 0); if (error) { return (error); } } if (nd.ni_vp->v_type != VREG) { error = EINVAL; } else { error = vnode_size(nd.ni_vp, &file_size, ctx); } if (error != 0) { (void) vn_close(nd.ni_vp, flags, ctx); vnode_put(nd.ni_vp); return (error); } cred = kauth_cred_proc_ref(p); nd.ni_vp->v_flag |= VNOCACHE_DATA; error = setcred(nd.ni_vp, cred); if (error) { (void)vn_close(nd.ni_vp, flags, ctx); vnode_put(nd.ni_vp); kauth_cred_unref(&cred); return(error); } vn->sc_secsize = DEV_BSIZE; vn->sc_fsize = file_size; vn->sc_size = file_size / vn->sc_secsize; vn->sc_vp = nd.ni_vp; vn->sc_vid = vnode_vid(nd.ni_vp); vn->sc_open_flags = flags; vn->sc_cred = cred; cdev = makedev(vndevice_cdev_major, minor(dev)); vn->sc_cdev = devfs_make_node(cdev, DEVFS_CHAR, UID_ROOT, GID_OPERATOR, 0600, "rvn%d", minor(dev)); vn->sc_flags |= VNF_INITED; if (flags == FREAD) vn->sc_flags |= VNF_READONLY; /* lose the short-term reference */ vnode_put(nd.ni_vp); return(0); }
/** * Start the kernel module. */ static kern_return_t VBoxDrvDarwinStart(struct kmod_info *pKModInfo, void *pvData) { int rc; #ifdef DEBUG printf("VBoxDrvDarwinStart\n"); #endif /* * Initialize IPRT. */ rc = RTR0Init(0); if (RT_SUCCESS(rc)) { /* * Initialize the device extension. */ rc = supdrvInitDevExt(&g_DevExt, sizeof(SUPDRVSESSION)); if (RT_SUCCESS(rc)) { /* * Initialize the session hash table. */ memset(g_apSessionHashTab, 0, sizeof(g_apSessionHashTab)); /* paranoia */ rc = RTSpinlockCreate(&g_Spinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxDrvDarwin"); if (RT_SUCCESS(rc)) { /* * Registering ourselves as a character device. */ g_iMajorDeviceNo = cdevsw_add(-1, &g_DevCW); if (g_iMajorDeviceNo >= 0) { #ifdef VBOX_WITH_HARDENING g_hDevFsDeviceSys = devfs_make_node(makedev(g_iMajorDeviceNo, 0), DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0600, DEVICE_NAME_SYS); #else g_hDevFsDeviceSys = devfs_make_node(makedev(g_iMajorDeviceNo, 0), DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0666, DEVICE_NAME_SYS); #endif if (g_hDevFsDeviceSys) { g_hDevFsDeviceUsr = devfs_make_node(makedev(g_iMajorDeviceNo, 1), DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0666, DEVICE_NAME_USR); if (g_hDevFsDeviceUsr) { LogRel(("VBoxDrv: version " VBOX_VERSION_STRING " r%d; IOCtl version %#x; IDC version %#x; dev major=%d\n", VBOX_SVN_REV, SUPDRV_IOC_VERSION, SUPDRV_IDC_VERSION, g_iMajorDeviceNo)); /* Register a sleep/wakeup notification callback */ g_pSleepNotifier = registerPrioritySleepWakeInterest(&VBoxDrvDarwinSleepHandler, &g_DevExt, NULL); if (g_pSleepNotifier == NULL) LogRel(("VBoxDrv: register for sleep/wakeup events failed\n")); /* Find kernel symbols that are kind of optional. */ vboxdrvDarwinResolveSymbols(); return KMOD_RETURN_SUCCESS; } LogRel(("VBoxDrv: devfs_make_node(makedev(%d,1),,,,%s) failed\n", g_iMajorDeviceNo, DEVICE_NAME_USR)); devfs_remove(g_hDevFsDeviceSys); g_hDevFsDeviceSys = NULL; } else LogRel(("VBoxDrv: devfs_make_node(makedev(%d,0),,,,%s) failed\n", g_iMajorDeviceNo, DEVICE_NAME_SYS)); cdevsw_remove(g_iMajorDeviceNo, &g_DevCW); g_iMajorDeviceNo = -1; } else LogRel(("VBoxDrv: cdevsw_add failed (%d)\n", g_iMajorDeviceNo)); RTSpinlockDestroy(g_Spinlock); g_Spinlock = NIL_RTSPINLOCK; } else LogRel(("VBoxDrv: RTSpinlockCreate failed (rc=%d)\n", rc)); supdrvDeleteDevExt(&g_DevExt); } else printf("VBoxDrv: failed to initialize device extension (rc=%d)\n", rc); RTR0TermForced(); } else printf("VBoxDrv: failed to initialize IPRT (rc=%d)\n", rc); memset(&g_DevExt, 0, sizeof(g_DevExt)); return KMOD_RETURN_FAILURE; }
static int bpf_movein(struct uio *uio, int linktype, struct mbuf **mp, struct sockaddr *sockp, int *datlen) { struct mbuf *m; int error; int len; uint8_t sa_family; int hlen; switch (linktype) { #if SLIP case DLT_SLIP: sa_family = AF_INET; hlen = 0; break; #endif /* SLIP */ case DLT_EN10MB: sa_family = AF_UNSPEC; /* XXX Would MAXLINKHDR be better? */ hlen = sizeof(struct ether_header); break; #if FDDI case DLT_FDDI: #if defined(__FreeBSD__) || defined(__bsdi__) sa_family = AF_IMPLINK; hlen = 0; #else sa_family = AF_UNSPEC; /* XXX 4(FORMAC)+6(dst)+6(src)+3(LLC)+5(SNAP) */ hlen = 24; #endif break; #endif /* FDDI */ case DLT_RAW: case DLT_NULL: sa_family = AF_UNSPEC; hlen = 0; break; #ifdef __FreeBSD__ case DLT_ATM_RFC1483: /* * en atm driver requires 4-byte atm pseudo header. * though it isn't standard, vpi:vci needs to be * specified anyway. */ sa_family = AF_UNSPEC; hlen = 12; /* XXX 4(ATM_PH) + 3(LLC) + 5(SNAP) */ break; #endif case DLT_PPP: sa_family = AF_UNSPEC; hlen = 4; /* This should match PPP_HDRLEN */ break; case DLT_APPLE_IP_OVER_IEEE1394: sa_family = AF_UNSPEC; hlen = sizeof(struct firewire_header); break; case DLT_IEEE802_11: /* IEEE 802.11 wireless */ sa_family = AF_IEEE80211; hlen = 0; break; default: return (EIO); } // LP64todo - fix this! len = uio_resid(uio); *datlen = len - hlen; if ((unsigned)len > MCLBYTES) return (EIO); if (sockp) { /* * Build a sockaddr based on the data link layer type. * We do this at this level because the ethernet header * is copied directly into the data field of the sockaddr. * In the case of SLIP, there is no header and the packet * is forwarded as is. * Also, we are careful to leave room at the front of the mbuf * for the link level header. */ if ((hlen + SOCKADDR_HDR_LEN) > sockp->sa_len) { return (EIO); } sockp->sa_family = sa_family; } else { /* * We're directly sending the packet data supplied by * the user; we don't need to make room for the link * header, and don't need the header length value any * more, so set it to 0. */ hlen = 0; } MGETHDR(m, M_WAIT, MT_DATA); if (m == 0) return (ENOBUFS); if ((unsigned)len > MHLEN) { #if BSD >= 199103 MCLGET(m, M_WAIT); if ((m->m_flags & M_EXT) == 0) { #else MCLGET(m); if (m->m_len != MCLBYTES) { #endif error = ENOBUFS; goto bad; } } m->m_pkthdr.len = m->m_len = len; m->m_pkthdr.rcvif = NULL; *mp = m; /* * Make room for link header. */ if (hlen != 0) { m->m_pkthdr.len -= hlen; m->m_len -= hlen; #if BSD >= 199103 m->m_data += hlen; /* XXX */ #else m->m_off += hlen; #endif error = UIOMOVE((caddr_t)sockp->sa_data, hlen, UIO_WRITE, uio); if (error) goto bad; } error = UIOMOVE(mtod(m, caddr_t), len - hlen, UIO_WRITE, uio); if (!error) return (0); bad: m_freem(m); return (error); } #ifdef __APPLE__ /* * The dynamic addition of a new device node must block all processes that are opening * the last device so that no process will get an unexpected ENOENT */ static void bpf_make_dev_t(int maj) { static int bpf_growing = 0; unsigned int cur_size = nbpfilter, i; if (nbpfilter >= bpf_maxdevices) return; while (bpf_growing) { /* Wait until new device has been created */ (void)tsleep((caddr_t)&bpf_growing, PZERO, "bpf_growing", 0); } if (nbpfilter > cur_size) { /* other thread grew it already */ return; } bpf_growing = 1; /* need to grow bpf_dtab first */ if (nbpfilter == bpf_dtab_size) { int new_dtab_size; struct bpf_d **new_dtab = NULL; struct bpf_d **old_dtab = NULL; new_dtab_size = bpf_dtab_size + NBPFILTER; new_dtab = (struct bpf_d **)_MALLOC(sizeof(struct bpf_d *) * new_dtab_size, M_DEVBUF, M_WAIT); if (new_dtab == 0) { printf("bpf_make_dev_t: malloc bpf_dtab failed\n"); goto done; } if (bpf_dtab) { bcopy(bpf_dtab, new_dtab, sizeof(struct bpf_d *) * bpf_dtab_size); } bzero(new_dtab + bpf_dtab_size, sizeof(struct bpf_d *) * NBPFILTER); old_dtab = bpf_dtab; bpf_dtab = new_dtab; bpf_dtab_size = new_dtab_size; if (old_dtab != NULL) _FREE(old_dtab, M_DEVBUF); } i = nbpfilter++; (void) devfs_make_node(makedev(maj, i), DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0600, "bpf%d", i); done: bpf_growing = 0; wakeup((caddr_t)&bpf_growing); } #endif /* * Attach file to the bpf interface, i.e. make d listen on bp. */ static errno_t bpf_attachd(struct bpf_d *d, struct bpf_if *bp) { int first = bp->bif_dlist == NULL; int error = 0; /* * Point d at bp, and add d to the interface's list of listeners. * Finally, point the driver's bpf cookie at the interface so * it will divert packets to bpf. */ d->bd_bif = bp; d->bd_next = bp->bif_dlist; bp->bif_dlist = d; if (first) { /* Find the default bpf entry for this ifp */ if (bp->bif_ifp->if_bpf == NULL) { struct bpf_if *primary; for (primary = bpf_iflist; primary && primary->bif_ifp != bp->bif_ifp; primary = primary->bif_next) ; bp->bif_ifp->if_bpf = primary; } /* Only call dlil_set_bpf_tap for primary dlt */ if (bp->bif_ifp->if_bpf == bp) dlil_set_bpf_tap(bp->bif_ifp, BPF_TAP_INPUT_OUTPUT, bpf_tap_callback); if (bp->bif_tap) error = bp->bif_tap(bp->bif_ifp, bp->bif_dlt, BPF_TAP_INPUT_OUTPUT); } return error; }