-
- 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(__DECONST(char *, ifp->if_name), einit.name, IFNAMSIZ);
+ ifp->if_type = einit.type;
+ ifp->if_family = einit.family;
+ ifp->if_subfamily = einit.subfamily;
+ 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_output_lt.eff_lt = einit.output_lt;
+ ifp->if_output_lt.max_lt = einit.output_lt_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_input_lt.eff_lt = einit.input_lt;
+ ifp->if_input_lt.max_lt = einit.input_lt_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_legacy = einit.framer;
+ ifp->if_framer = einit.framer_extended;
+ 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;
+
+ /* Initialize external name (name + unit) */
+ snprintf(__DECONST(char *, ifp->if_xname), IFXNAMSIZ,
+ "%s%d", ifp->if_name, ifp->if_unit);
+
+ /*
+ * On embedded, framer() is already in the extended form;
+ * we simply use it as is, unless the caller specifies
+ * framer_extended() which will then override it.
+ *
+ * On non-embedded, framer() has long been exposed as part
+ * of the public KPI, and therefore its signature must
+ * remain the same (without the pre- and postpend length
+ * parameters.) We special case ether_frameout, such that
+ * it gets mapped to its extended variant. All other cases
+ * utilize the stub routine which will simply return zeroes
+ * for those new parameters.
+ *
+ * Internally, DLIL will only use the extended callback
+ * variant which is represented by if_framer.
+ */
+ if (ifp->if_framer == NULL && ifp->if_framer_legacy != NULL) {
+ if (ifp->if_framer_legacy == ether_frameout)
+ ifp->if_framer = ether_frameout_extended;
+ else
+ ifp->if_framer = ifnet_framer_stub;
+ }
+
+ 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;
+
+ /* 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_output_lt.eff_lt > ifp->if_output_lt.max_lt)
+ ifp->if_output_lt.max_lt = ifp->if_output_lt.eff_lt;
+ else if (ifp->if_output_lt.eff_lt == 0)
+ ifp->if_output_lt.eff_lt = ifp->if_output_lt.max_lt;
+
+ if (ifp->if_input_lt.eff_lt > ifp->if_input_lt.max_lt)
+ ifp->if_input_lt.max_lt = ifp->if_input_lt.eff_lt;
+ else if (ifp->if_input_lt.eff_lt == 0)
+ ifp->if_input_lt.eff_lt = ifp->if_input_lt.max_lt;
+
+ if (ifp->if_output_lt.max_lt == 0)
+ ifp->if_output_lt = ifp->if_input_lt;
+ else if (ifp->if_input_lt.max_lt == 0)
+ ifp->if_input_lt = ifp->if_output_lt;
+
+ if (ifp->if_ioctl == NULL)
+ ifp->if_ioctl = ifp_if_ioctl;
+
+ 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);