-
- 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)
- {
- strncpy(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_u.kpi = 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);
+ 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);