errno_t ifnet_allocate( const struct ifnet_init_params *init, ifnet_t *interface) { int error; struct ifnet *ifp = NULL; if (init->family == 0) return EINVAL; if (init->name == NULL || init->output == NULL) return EINVAL; if (strlen(init->name) >= IFNAMSIZ) return EINVAL; if ((init->type & 0xFFFFFF00) != 0 || init->type == 0) return EINVAL; error = dlil_if_acquire(init->family, init->uniqueid, init->uniqueid_len, &ifp); if (error == 0) { /* * Cast ifp->if_name as non const. dlil_if_acquire sets it up * to point to storage of at least IFNAMSIZ bytes. It is safe * to write to this. */ strncpy(_cast_non_const(ifp->if_name), init->name, IFNAMSIZ); ifp->if_type = init->type; ifp->if_family = init->family; ifp->if_unit = init->unit; ifp->if_output = init->output; ifp->if_demux = init->demux; ifp->if_add_proto = init->add_proto; ifp->if_del_proto = init->del_proto; ifp->if_check_multi = init->check_multi; ifp->if_framer = init->framer; ifp->if_softc = init->softc; ifp->if_ioctl = init->ioctl; ifp->if_set_bpf_tap = init->set_bpf_tap; ifp->if_free = ifnet_kpi_free; ifp->if_event = init->event; ifp->if_kpi_storage = init->detach; ifp->if_eflags |= IFEF_USEKPI; if (init->broadcast_len && init->broadcast_addr) { if (init->broadcast_len > sizeof(ifp->if_broadcast.u.buffer)) { MALLOC(ifp->if_broadcast.u.ptr, u_char*, init->broadcast_len, M_IFADDR, M_NOWAIT); if (ifp->if_broadcast.u.ptr == NULL) { error = ENOMEM; } else { bcopy(init->broadcast_addr, ifp->if_broadcast.u.ptr, init->broadcast_len); } } else {
/* * Copy data from an mbuf chain into a buffer. This code is derived * from m_copydata in sys/uipc_mbuf.c. */ static void bpf_mcopy(const void *src_arg, void *dst_arg, size_t len) { struct mbuf *m = _cast_non_const(src_arg); u_int count; u_char *dst; dst = dst_arg; while (len > 0) { if (m == 0) panic("bpf_mcopy"); count = min(m->m_len, len); bcopy(mbuf_data(m), dst, count); m = m->m_next; dst += count; len -= count; } }
errno_t ifnet_allocate_extended(const struct ifnet_init_eparams *einit0, ifnet_t *interface) { struct ifnet_init_eparams einit; struct ifnet *ifp = NULL; int error; einit = *einit0; if (einit.ver != IFNET_INIT_CURRENT_VERSION || einit.len < sizeof (einit)) return (EINVAL); if (einit.family == 0 || einit.name == NULL || strlen(einit.name) >= IFNAMSIZ || (einit.type & 0xFFFFFF00) != 0 || einit.type == 0) return (EINVAL); if (einit.flags & IFNET_INIT_LEGACY) { if (einit.output == NULL || einit.flags != IFNET_INIT_LEGACY) return (EINVAL); einit.pre_enqueue = NULL; einit.start = NULL; einit.output_ctl = NULL; einit.output_sched_model = IFNET_SCHED_MODEL_NORMAL; einit.input_poll = NULL; einit.input_ctl = NULL; } else { if (einit.start == NULL) return (EINVAL); einit.output = NULL; if (einit.output_sched_model >= IFNET_SCHED_MODEL_MAX) return (EINVAL); if (einit.flags & IFNET_INIT_INPUT_POLL) { if (einit.input_poll == NULL || einit.input_ctl == NULL) return (EINVAL); } else { einit.input_poll = NULL; einit.input_ctl = NULL; } } error = dlil_if_acquire(einit.family, einit.uniqueid, einit.uniqueid_len, &ifp); if (error == 0) { u_int64_t br; /* * Cast ifp->if_name as non const. dlil_if_acquire sets it up * to point to storage of at least IFNAMSIZ bytes. It is safe * to write to this. */ strncpy(_cast_non_const(ifp->if_name), einit.name, IFNAMSIZ); ifp->if_type = einit.type; ifp->if_family = einit.family; ifp->if_unit = einit.unit; ifp->if_output = einit.output; ifp->if_pre_enqueue = einit.pre_enqueue; ifp->if_start = einit.start; ifp->if_output_ctl = einit.output_ctl; ifp->if_output_sched_model = einit.output_sched_model; ifp->if_output_bw.eff_bw = einit.output_bw; ifp->if_output_bw.max_bw = einit.output_bw_max; ifp->if_input_poll = einit.input_poll; ifp->if_input_ctl = einit.input_ctl; ifp->if_input_bw.eff_bw = einit.input_bw; ifp->if_input_bw.max_bw = einit.input_bw_max; ifp->if_demux = einit.demux; ifp->if_add_proto = einit.add_proto; ifp->if_del_proto = einit.del_proto; ifp->if_check_multi = einit.check_multi; ifp->if_framer = einit.framer; ifp->if_softc = einit.softc; ifp->if_ioctl = einit.ioctl; ifp->if_set_bpf_tap = einit.set_bpf_tap; ifp->if_free = ifnet_kpi_free; ifp->if_event = einit.event; ifp->if_kpi_storage = einit.detach; if (ifp->if_output_bw.eff_bw > ifp->if_output_bw.max_bw) ifp->if_output_bw.max_bw = ifp->if_output_bw.eff_bw; else if (ifp->if_output_bw.eff_bw == 0) ifp->if_output_bw.eff_bw = ifp->if_output_bw.max_bw; if (ifp->if_input_bw.eff_bw > ifp->if_input_bw.max_bw) ifp->if_input_bw.max_bw = ifp->if_input_bw.eff_bw; else if (ifp->if_input_bw.eff_bw == 0) ifp->if_input_bw.eff_bw = ifp->if_input_bw.max_bw; if (ifp->if_output_bw.max_bw == 0) ifp->if_output_bw = ifp->if_input_bw; else if (ifp->if_input_bw.max_bw == 0) ifp->if_input_bw = ifp->if_output_bw; if (ifp->if_ioctl == NULL) ifp->if_ioctl = ifp_if_ioctl; /* Pin if_baudrate to 32 bits */ br = MAX(ifp->if_output_bw.max_bw, ifp->if_input_bw.max_bw); if (br != 0) ifp->if_baudrate = (br > 0xFFFFFFFF) ? 0xFFFFFFFF : br; if (ifp->if_start != NULL) { ifp->if_eflags |= IFEF_TXSTART; if (ifp->if_pre_enqueue == NULL) ifp->if_pre_enqueue = ifnet_enqueue; ifp->if_output = ifp->if_pre_enqueue; } else { ifp->if_eflags &= ~IFEF_TXSTART; } if (ifp->if_input_poll != NULL) ifp->if_eflags |= IFEF_RXPOLL; else ifp->if_eflags &= ~IFEF_RXPOLL; VERIFY(!(einit.flags & IFNET_INIT_LEGACY) || (ifp->if_pre_enqueue == NULL && ifp->if_start == NULL && ifp->if_output_ctl == NULL && ifp->if_input_poll == NULL && ifp->if_input_ctl == NULL)); VERIFY(!(einit.flags & IFNET_INIT_INPUT_POLL) || (ifp->if_input_poll != NULL && ifp->if_input_ctl != NULL)); if (einit.broadcast_len && einit.broadcast_addr) { if (einit.broadcast_len > sizeof (ifp->if_broadcast.u.buffer)) { MALLOC(ifp->if_broadcast.u.ptr, u_char *, einit.broadcast_len, M_IFADDR, M_NOWAIT); if (ifp->if_broadcast.u.ptr == NULL) { error = ENOMEM; } else { bcopy(einit.broadcast_addr, ifp->if_broadcast.u.ptr, einit.broadcast_len); } } else {