-ndrv_getspec(struct ndrv_cb *np,
- struct sockopt *sopt,
- struct ndrv_descr *nd)
-{ struct dlil_demux_desc *mp, *mp1;
- int i, k, error = 0;
-
- /* Compute # structs to copy */
- i = k = min(np->nd_descrcnt,
- (nd->nd_len / sizeof (struct dlil_demux_desc)));
- mp = (struct dlil_demux_desc *)nd->nd_buf;
- TAILQ_FOREACH(mp1, &np->nd_dlist, next)
- { if (k-- == 0)
- break;
- error = copyout(mp1, mp++, sizeof (struct dlil_demux_desc));
- if (error)
- break;
- }
- if (error == 0)
- { nd->nd_len = i * (sizeof (struct dlil_demux_desc));
- error = sooptcopyout(sopt, nd, sizeof (*nd));
- }
- return(error);
+ndrv_setspec(struct ndrv_cb *np, struct sockopt *sopt)
+{
+ struct dlil_proto_reg_str dlilSpec;
+ struct ndrv_protocol_desc ndrvSpec;
+ struct dlil_demux_desc* dlilDemux = NULL;
+ struct ndrv_demux_desc* ndrvDemux = NULL;
+ int error = 0;
+
+ /* Sanity checking */
+ if (np->nd_tag)
+ return EBUSY;
+ if (np->nd_if == NULL)
+ return EINVAL;
+ if (sopt->sopt_valsize != sizeof(struct ndrv_protocol_desc))
+ return EINVAL;
+
+ /* Copy the ndrvSpec */
+ error = sooptcopyin(sopt, &ndrvSpec, sizeof(struct ndrv_protocol_desc),
+ sizeof(struct ndrv_protocol_desc));
+ if (error != 0)
+ return error;
+
+ /* Verify the parameter */
+ if (ndrvSpec.version > NDRV_PROTOCOL_DESC_VERS)
+ return ENOTSUP; // version is too new!
+ else if (ndrvSpec.version < 1)
+ return EINVAL; // version is not valid
+
+ /* Allocate storage for demux array */
+ MALLOC(ndrvDemux, struct ndrv_demux_desc*,
+ ndrvSpec.demux_count * sizeof(struct ndrv_demux_desc), M_TEMP, M_WAITOK);
+ if (ndrvDemux == NULL)
+ return ENOMEM;
+
+ /* Allocate enough dlil_demux_descs */
+ MALLOC(dlilDemux, struct dlil_demux_desc*,
+ sizeof(*dlilDemux) * ndrvSpec.demux_count, M_TEMP, M_WAITOK);
+ if (dlilDemux == NULL)
+ error = ENOMEM;
+
+ if (error == 0)
+ {
+ /* Copy the ndrv demux array from userland */
+ error = copyin(ndrvSpec.demux_list, ndrvDemux,
+ ndrvSpec.demux_count * sizeof(struct ndrv_demux_desc));
+ ndrvSpec.demux_list = ndrvDemux;
+ }
+
+ if (error == 0)
+ {
+ /* At this point, we've at least got enough bytes to start looking around */
+ u_long demuxOn = 0;
+
+ bzero(&dlilSpec, sizeof(dlilSpec));
+ TAILQ_INIT(&dlilSpec.demux_desc_head);
+ dlilSpec.interface_family = np->nd_family;
+ dlilSpec.unit_number = np->nd_unit;
+ dlilSpec.input = ndrv_input;
+ dlilSpec.protocol_family = ndrvSpec.protocol_family;
+
+ for (demuxOn = 0; demuxOn < ndrvSpec.demux_count; demuxOn++)
+ {
+ /* Convert an ndrv_demux_desc to a dlil_demux_desc */
+ error = ndrv_to_dlil_demux(&ndrvSpec.demux_list[demuxOn], &dlilDemux[demuxOn]);
+ if (error)
+ break;
+
+ /* Add the dlil_demux_desc to the list */
+ TAILQ_INSERT_TAIL(&dlilSpec.demux_desc_head, &dlilDemux[demuxOn], next);
+ }
+ }
+
+ if (error == 0)
+ {
+ /* We've got all our ducks lined up...lets attach! */
+ error = dlil_attach_protocol(&dlilSpec, &np->nd_tag);
+ }
+
+ /* Free any memory we've allocated */
+ if (dlilDemux)
+ FREE(dlilDemux, M_TEMP);
+ if (ndrvDemux)
+ FREE(ndrvDemux, M_TEMP);
+
+ return error;