Deleted Added
full compact
if_clone.c (239905) if_clone.c (241610)
1/*-
1/*-
2 * Copyright (c) 2012 Gleb Smirnoff <glebius@FreeBSD.org>
2 * Copyright (c) 1980, 1986, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.

--- 12 unchanged lines hidden (view full) ---

22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * @(#)if.c 8.5 (Berkeley) 1/9/95
3 * Copyright (c) 1980, 1986, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.

--- 12 unchanged lines hidden (view full) ---

23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * @(#)if.c 8.5 (Berkeley) 1/9/95
30 * $FreeBSD: head/sys/net/if_clone.c 239905 2012-08-30 12:18:45Z glebius $
31 * $FreeBSD: head/sys/net/if_clone.c 241610 2012-10-16 13:37:54Z glebius $
31 */
32
33#include <sys/param.h>
34#include <sys/malloc.h>
35#include <sys/limits.h>
36#include <sys/lock.h>
37#include <sys/mutex.h>
38#include <sys/kernel.h>
39#include <sys/systm.h>
40#include <sys/types.h>
41#include <sys/socket.h>
42
43#include <net/if.h>
44#include <net/if_clone.h>
32 */
33
34#include <sys/param.h>
35#include <sys/malloc.h>
36#include <sys/limits.h>
37#include <sys/lock.h>
38#include <sys/mutex.h>
39#include <sys/kernel.h>
40#include <sys/systm.h>
41#include <sys/types.h>
42#include <sys/socket.h>
43
44#include <net/if.h>
45#include <net/if_clone.h>
45#if 0
46#include <net/if_dl.h>
47#endif
48#include <net/if_types.h>
49#include <net/if_var.h>
50#include <net/radix.h>
51#include <net/route.h>
52#include <net/vnet.h>
53
46#include <net/if_var.h>
47#include <net/radix.h>
48#include <net/route.h>
49#include <net/vnet.h>
50
51/* Current IF_MAXUNIT expands maximum to 5 characters. */
52#define IFCLOSIZ (IFNAMSIZ - 5)
53
54/*
55 * Structure describing a `cloning' interface.
56 *
57 * List of locks
58 * (c) const until freeing
59 * (d) driver specific data, may need external protection.
60 * (e) locked by if_cloners_mtx
61 * (i) locked by ifc_mtx mtx
62 */
63struct if_clone {
64 char ifc_name[IFCLOSIZ]; /* (c) Name of device, e.g. `gif' */
65 struct unrhdr *ifc_unrhdr; /* (c) alloc_unr(9) header */
66 int ifc_maxunit; /* (c) maximum unit number */
67 long ifc_refcnt; /* (i) Reference count. */
68 LIST_HEAD(, ifnet) ifc_iflist; /* (i) List of cloned interfaces */
69 struct mtx ifc_mtx; /* Mutex to protect members. */
70
71 enum { SIMPLE, ADVANCED } ifc_type; /* (c) */
72
73 /* (c) Driver specific cloning functions. Called with no locks held. */
74 union {
75 struct { /* advanced cloner */
76 ifc_match_t *_ifc_match;
77 ifc_create_t *_ifc_create;
78 ifc_destroy_t *_ifc_destroy;
79 } A;
80 struct { /* simple cloner */
81 ifcs_create_t *_ifcs_create;
82 ifcs_destroy_t *_ifcs_destroy;
83 int _ifcs_minifs; /* minimum ifs */
84
85 } S;
86 } U;
87#define ifc_match U.A._ifc_match
88#define ifc_create U.A._ifc_create
89#define ifc_destroy U.A._ifc_destroy
90#define ifcs_create U.S._ifcs_create
91#define ifcs_destroy U.S._ifcs_destroy
92#define ifcs_minifs U.S._ifcs_minifs
93
94 LIST_ENTRY(if_clone) ifc_list; /* (e) On list of cloners */
95};
96
54static void if_clone_free(struct if_clone *ifc);
55static int if_clone_createif(struct if_clone *ifc, char *name, size_t len,
56 caddr_t params);
57
97static void if_clone_free(struct if_clone *ifc);
98static int if_clone_createif(struct if_clone *ifc, char *name, size_t len,
99 caddr_t params);
100
101static int ifc_simple_match(struct if_clone *, const char *);
102static int ifc_simple_create(struct if_clone *, char *, size_t, caddr_t);
103static int ifc_simple_destroy(struct if_clone *, struct ifnet *);
104
58static struct mtx if_cloners_mtx;
59static VNET_DEFINE(int, if_cloners_count);
60VNET_DEFINE(LIST_HEAD(, if_clone), if_cloners);
61
62#define V_if_cloners_count VNET(if_cloners_count)
63#define V_if_cloners VNET(if_cloners)
64
65#define IF_CLONERS_LOCK_INIT() \

--- 67 unchanged lines hidden (view full) ---

133 */
134int
135if_clone_create(char *name, size_t len, caddr_t params)
136{
137 struct if_clone *ifc;
138
139 /* Try to find an applicable cloner for this request */
140 IF_CLONERS_LOCK();
105static struct mtx if_cloners_mtx;
106static VNET_DEFINE(int, if_cloners_count);
107VNET_DEFINE(LIST_HEAD(, if_clone), if_cloners);
108
109#define V_if_cloners_count VNET(if_cloners_count)
110#define V_if_cloners VNET(if_cloners)
111
112#define IF_CLONERS_LOCK_INIT() \

--- 67 unchanged lines hidden (view full) ---

180 */
181int
182if_clone_create(char *name, size_t len, caddr_t params)
183{
184 struct if_clone *ifc;
185
186 /* Try to find an applicable cloner for this request */
187 IF_CLONERS_LOCK();
141 LIST_FOREACH(ifc, &V_if_cloners, ifc_list) {
142 if (ifc->ifc_match(ifc, name)) {
143 break;
188 LIST_FOREACH(ifc, &V_if_cloners, ifc_list)
189 if (ifc->ifc_type == SIMPLE) {
190 if (ifc_simple_match(ifc, name))
191 break;
192 } else {
193 if (ifc->ifc_match(ifc, name))
194 break;
144 }
195 }
145 }
146#ifdef VIMAGE
147 if (ifc == NULL && !IS_DEFAULT_VNET(curvnet)) {
148 CURVNET_SET_QUIET(vnet0);
196#ifdef VIMAGE
197 if (ifc == NULL && !IS_DEFAULT_VNET(curvnet)) {
198 CURVNET_SET_QUIET(vnet0);
149 LIST_FOREACH(ifc, &V_if_cloners, ifc_list) {
150 if (ifc->ifc_match(ifc, name))
151 break;
152 }
199 LIST_FOREACH(ifc, &V_if_cloners, ifc_list)
200 if (ifc->ifc_type == SIMPLE) {
201 if (ifc_simple_match(ifc, name))
202 break;
203 } else {
204 if (ifc->ifc_match(ifc, name))
205 break;
206 }
153 CURVNET_RESTORE();
154 }
155#endif
156 IF_CLONERS_UNLOCK();
157
158 if (ifc == NULL)
159 return (EINVAL);
160

--- 7 unchanged lines hidden (view full) ---

168if_clone_createif(struct if_clone *ifc, char *name, size_t len, caddr_t params)
169{
170 int err;
171 struct ifnet *ifp;
172
173 if (ifunit(name) != NULL)
174 return (EEXIST);
175
207 CURVNET_RESTORE();
208 }
209#endif
210 IF_CLONERS_UNLOCK();
211
212 if (ifc == NULL)
213 return (EINVAL);
214

--- 7 unchanged lines hidden (view full) ---

222if_clone_createif(struct if_clone *ifc, char *name, size_t len, caddr_t params)
223{
224 int err;
225 struct ifnet *ifp;
226
227 if (ifunit(name) != NULL)
228 return (EEXIST);
229
176 err = (*ifc->ifc_create)(ifc, name, len, params);
230 if (ifc->ifc_type == SIMPLE)
231 err = ifc_simple_create(ifc, name, len, params);
232 else
233 err = (*ifc->ifc_create)(ifc, name, len, params);
177
178 if (!err) {
179 ifp = ifunit(name);
180 if (ifp == NULL)
181 panic("%s: lookup failed for %s", __func__, name);
182
183 if_addgroup(ifp, ifc->ifc_name);
184

--- 24 unchanged lines hidden (view full) ---

209 LIST_FOREACH(ifc, &V_if_cloners, ifc_list) {
210 if (strcmp(ifc->ifc_name, ifp->if_dname) == 0) {
211 break;
212 }
213 }
214#ifdef VIMAGE
215 if (ifc == NULL && !IS_DEFAULT_VNET(curvnet)) {
216 CURVNET_SET_QUIET(vnet0);
234
235 if (!err) {
236 ifp = ifunit(name);
237 if (ifp == NULL)
238 panic("%s: lookup failed for %s", __func__, name);
239
240 if_addgroup(ifp, ifc->ifc_name);
241

--- 24 unchanged lines hidden (view full) ---

266 LIST_FOREACH(ifc, &V_if_cloners, ifc_list) {
267 if (strcmp(ifc->ifc_name, ifp->if_dname) == 0) {
268 break;
269 }
270 }
271#ifdef VIMAGE
272 if (ifc == NULL && !IS_DEFAULT_VNET(curvnet)) {
273 CURVNET_SET_QUIET(vnet0);
217 LIST_FOREACH(ifc, &V_if_cloners, ifc_list) {
218 if (ifc->ifc_match(ifc, name))
219 break;
220 }
274 LIST_FOREACH(ifc, &V_if_cloners, ifc_list)
275 if (ifc->type == SIMPLE) {
276 if (ifc_simple_match(ifc, name))
277 break;
278 } else {
279 if (ifc->ifc_match(ifc, name))
280 break;
281 }
221 CURVNET_RESTORE();
222 }
223#endif
224 IF_CLONERS_UNLOCK();
225 if (ifc == NULL) {
226 if_rele(ifp);
227 return (EINVAL);
228 }

--- 7 unchanged lines hidden (view full) ---

236 * Destroy a clone network interface.
237 */
238int
239if_clone_destroyif(struct if_clone *ifc, struct ifnet *ifp)
240{
241 int err;
242 struct ifnet *ifcifp;
243
282 CURVNET_RESTORE();
283 }
284#endif
285 IF_CLONERS_UNLOCK();
286 if (ifc == NULL) {
287 if_rele(ifp);
288 return (EINVAL);
289 }

--- 7 unchanged lines hidden (view full) ---

297 * Destroy a clone network interface.
298 */
299int
300if_clone_destroyif(struct if_clone *ifc, struct ifnet *ifp)
301{
302 int err;
303 struct ifnet *ifcifp;
304
244 if (ifc->ifc_destroy == NULL)
305 if (ifc->ifc_type == ADVANCED && ifc->ifc_destroy == NULL)
245 return(EOPNOTSUPP);
246
247 /*
248 * Given that the cloned ifnet might be attached to a different
249 * vnet from where its cloner was registered, we have to
250 * switch to the vnet context of the target vnet.
251 */
252 CURVNET_SET_QUIET(ifp->if_vnet);

--- 8 unchanged lines hidden (view full) ---

261 IF_CLONE_UNLOCK(ifc);
262 if (ifcifp == NULL) {
263 CURVNET_RESTORE();
264 return (ENXIO); /* ifp is not on the list. */
265 }
266
267 if_delgroup(ifp, ifc->ifc_name);
268
306 return(EOPNOTSUPP);
307
308 /*
309 * Given that the cloned ifnet might be attached to a different
310 * vnet from where its cloner was registered, we have to
311 * switch to the vnet context of the target vnet.
312 */
313 CURVNET_SET_QUIET(ifp->if_vnet);

--- 8 unchanged lines hidden (view full) ---

322 IF_CLONE_UNLOCK(ifc);
323 if (ifcifp == NULL) {
324 CURVNET_RESTORE();
325 return (ENXIO); /* ifp is not on the list. */
326 }
327
328 if_delgroup(ifp, ifc->ifc_name);
329
269 err = (*ifc->ifc_destroy)(ifc, ifp);
330 if (ifc->ifc_type == SIMPLE)
331 err = ifc_simple_destroy(ifc, ifp);
332 else
333 err = (*ifc->ifc_destroy)(ifc, ifp);
270
271 if (err != 0) {
272 if_addgroup(ifp, ifc->ifc_name);
273
274 IF_CLONE_LOCK(ifc);
275 IFC_IFLIST_INSERT(ifc, ifp);
276 IF_CLONE_UNLOCK(ifc);
277 }
278 CURVNET_RESTORE();
279 return (err);
280}
281
334
335 if (err != 0) {
336 if_addgroup(ifp, ifc->ifc_name);
337
338 IF_CLONE_LOCK(ifc);
339 IFC_IFLIST_INSERT(ifc, ifp);
340 IF_CLONE_UNLOCK(ifc);
341 }
342 CURVNET_RESTORE();
343 return (err);
344}
345
282/*
283 * Register a network interface cloner.
284 */
285int
286if_clone_attach(struct if_clone *ifc)
346static struct if_clone *
347if_clone_alloc(const char *name, int maxunit)
287{
348{
288 struct if_clone *ifc1;
349 struct if_clone *ifc;
289
350
290 KASSERT(ifc->ifc_name != NULL, ("%s: no name\n", __func__));
351 KASSERT(name != NULL, ("%s: no name\n", __func__));
291
352
353 ifc = malloc(sizeof(struct if_clone), M_CLONE, M_WAITOK | M_ZERO);
354 strncpy(ifc->ifc_name, name, IFCLOSIZ-1);
292 IF_CLONE_LOCK_INIT(ifc);
293 IF_CLONE_ADDREF(ifc);
355 IF_CLONE_LOCK_INIT(ifc);
356 IF_CLONE_ADDREF(ifc);
357 ifc->ifc_maxunit = maxunit ? maxunit : IF_MAXUNIT;
294 ifc->ifc_unrhdr = new_unrhdr(0, ifc->ifc_maxunit, &ifc->ifc_mtx);
295 LIST_INIT(&ifc->ifc_iflist);
296
358 ifc->ifc_unrhdr = new_unrhdr(0, ifc->ifc_maxunit, &ifc->ifc_mtx);
359 LIST_INIT(&ifc->ifc_iflist);
360
361 return (ifc);
362}
363
364static int
365if_clone_attach(struct if_clone *ifc)
366{
367 struct if_clone *ifc1;
368
297 IF_CLONERS_LOCK();
298 LIST_FOREACH(ifc1, &V_if_cloners, ifc_list)
299 if (strcmp(ifc->ifc_name, ifc1->ifc_name) == 0) {
300 IF_CLONERS_UNLOCK();
301 IF_CLONE_REMREF(ifc);
302 return (EEXIST);
303 }
304 LIST_INSERT_HEAD(&V_if_cloners, ifc, ifc_list);
305 V_if_cloners_count++;
306 IF_CLONERS_UNLOCK();
307
369 IF_CLONERS_LOCK();
370 LIST_FOREACH(ifc1, &V_if_cloners, ifc_list)
371 if (strcmp(ifc->ifc_name, ifc1->ifc_name) == 0) {
372 IF_CLONERS_UNLOCK();
373 IF_CLONE_REMREF(ifc);
374 return (EEXIST);
375 }
376 LIST_INSERT_HEAD(&V_if_cloners, ifc, ifc_list);
377 V_if_cloners_count++;
378 IF_CLONERS_UNLOCK();
379
308 if (ifc->ifc_attach != NULL)
309 (*ifc->ifc_attach)(ifc);
380 return (0);
381}
382
383struct if_clone *
384if_clone_advanced(const char *name, u_int maxunit, ifc_match_t match,
385 ifc_create_t create, ifc_destroy_t destroy)
386{
387 struct if_clone *ifc;
388
389 ifc = if_clone_alloc(name, maxunit);
390 ifc->ifc_type = ADVANCED;
391 ifc->ifc_match = match;
392 ifc->ifc_create = create;
393 ifc->ifc_destroy = destroy;
394
395 if (if_clone_attach(ifc) != 0) {
396 if_clone_free(ifc);
397 return (NULL);
398 }
399
310 EVENTHANDLER_INVOKE(if_clone_event, ifc);
311
400 EVENTHANDLER_INVOKE(if_clone_event, ifc);
401
312 return (0);
402 return (ifc);
313}
314
403}
404
405struct if_clone *
406if_clone_simple(const char *name, ifcs_create_t create, ifcs_destroy_t destroy,
407 u_int minifs)
408{
409 struct if_clone *ifc;
410 u_int unit;
411
412 ifc = if_clone_alloc(name, 0);
413 ifc->ifc_type = SIMPLE;
414 ifc->ifcs_create = create;
415 ifc->ifcs_destroy = destroy;
416 ifc->ifcs_minifs = minifs;
417
418 if (if_clone_attach(ifc) != 0) {
419 if_clone_free(ifc);
420 return (NULL);
421 }
422
423 for (unit = 0; unit < minifs; unit++) {
424 char name[IFNAMSIZ];
425 int error;
426
427 snprintf(name, IFNAMSIZ, "%s%d", ifc->ifc_name, unit);
428 error = if_clone_createif(ifc, name, IFNAMSIZ, NULL);
429 KASSERT(error == 0,
430 ("%s: failed to create required interface %s",
431 __func__, name));
432 }
433
434 EVENTHANDLER_INVOKE(if_clone_event, ifc);
435
436 return (ifc);
437}
438
315/*
316 * Unregister a network interface cloner.
317 */
318void
319if_clone_detach(struct if_clone *ifc)
320{
439/*
440 * Unregister a network interface cloner.
441 */
442void
443if_clone_detach(struct if_clone *ifc)
444{
321 struct ifc_simple_data *ifcs = ifc->ifc_data;
322
323 IF_CLONERS_LOCK();
324 LIST_REMOVE(ifc, ifc_list);
325 V_if_cloners_count--;
326 IF_CLONERS_UNLOCK();
327
328 /* Allow all simples to be destroyed */
445
446 IF_CLONERS_LOCK();
447 LIST_REMOVE(ifc, ifc_list);
448 V_if_cloners_count--;
449 IF_CLONERS_UNLOCK();
450
451 /* Allow all simples to be destroyed */
329 if (ifc->ifc_attach == ifc_simple_attach)
330 ifcs->ifcs_minifs = 0;
452 if (ifc->ifc_type == SIMPLE)
453 ifc->ifcs_minifs = 0;
331
332 /* destroy all interfaces for this cloner */
333 while (!LIST_EMPTY(&ifc->ifc_iflist))
334 if_clone_destroyif(ifc, LIST_FIRST(&ifc->ifc_iflist));
335
336 IF_CLONE_REMREF(ifc);
337}
338
339static void
340if_clone_free(struct if_clone *ifc)
341{
342
343 KASSERT(LIST_EMPTY(&ifc->ifc_iflist),
344 ("%s: ifc_iflist not empty", __func__));
345
346 IF_CLONE_LOCK_DESTROY(ifc);
347 delete_unrhdr(ifc->ifc_unrhdr);
454
455 /* destroy all interfaces for this cloner */
456 while (!LIST_EMPTY(&ifc->ifc_iflist))
457 if_clone_destroyif(ifc, LIST_FIRST(&ifc->ifc_iflist));
458
459 IF_CLONE_REMREF(ifc);
460}
461
462static void
463if_clone_free(struct if_clone *ifc)
464{
465
466 KASSERT(LIST_EMPTY(&ifc->ifc_iflist),
467 ("%s: ifc_iflist not empty", __func__));
468
469 IF_CLONE_LOCK_DESTROY(ifc);
470 delete_unrhdr(ifc->ifc_unrhdr);
471 free(ifc, M_CLONE);
348}
349
350/*
351 * Provide list of interface cloners to userspace.
352 */
353int
354if_clone_list(struct if_clonereq *ifcr)
355{

--- 122 unchanged lines hidden (view full) ---

478void
479ifc_free_unit(struct if_clone *ifc, int unit)
480{
481
482 free_unr(ifc->ifc_unrhdr, unit);
483 IF_CLONE_REMREF(ifc);
484}
485
472}
473
474/*
475 * Provide list of interface cloners to userspace.
476 */
477int
478if_clone_list(struct if_clonereq *ifcr)
479{

--- 122 unchanged lines hidden (view full) ---

602void
603ifc_free_unit(struct if_clone *ifc, int unit)
604{
605
606 free_unr(ifc->ifc_unrhdr, unit);
607 IF_CLONE_REMREF(ifc);
608}
609
486void
487ifc_simple_attach(struct if_clone *ifc)
488{
489 int err;
490 int unit;
491 char name[IFNAMSIZ];
492 struct ifc_simple_data *ifcs = ifc->ifc_data;
493
494 KASSERT(ifcs->ifcs_minifs - 1 <= ifc->ifc_maxunit,
495 ("%s: %s requested more units than allowed (%d > %d)",
496 __func__, ifc->ifc_name, ifcs->ifcs_minifs,
497 ifc->ifc_maxunit + 1));
498
499 for (unit = 0; unit < ifcs->ifcs_minifs; unit++) {
500 snprintf(name, IFNAMSIZ, "%s%d", ifc->ifc_name, unit);
501 err = if_clone_createif(ifc, name, IFNAMSIZ, NULL);
502 KASSERT(err == 0,
503 ("%s: failed to create required interface %s",
504 __func__, name));
505 }
506}
507
508int
610static int
509ifc_simple_match(struct if_clone *ifc, const char *name)
510{
511 const char *cp;
512 int i;
513
514 /* Match the name */
515 for (cp = name, i = 0; i < strlen(ifc->ifc_name); i++, cp++) {
516 if (ifc->ifc_name[i] != *cp)

--- 4 unchanged lines hidden (view full) ---

521 for (; *cp != '\0'; cp++) {
522 if (*cp < '0' || *cp > '9')
523 return (0);
524 }
525
526 return (1);
527}
528
611ifc_simple_match(struct if_clone *ifc, const char *name)
612{
613 const char *cp;
614 int i;
615
616 /* Match the name */
617 for (cp = name, i = 0; i < strlen(ifc->ifc_name); i++, cp++) {
618 if (ifc->ifc_name[i] != *cp)

--- 4 unchanged lines hidden (view full) ---

623 for (; *cp != '\0'; cp++) {
624 if (*cp < '0' || *cp > '9')
625 return (0);
626 }
627
628 return (1);
629}
630
529int
631static int
530ifc_simple_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
531{
532 char *dp;
533 int wildcard;
534 int unit;
535 int err;
632ifc_simple_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
633{
634 char *dp;
635 int wildcard;
636 int unit;
637 int err;
536 struct ifc_simple_data *ifcs = ifc->ifc_data;
537
538 err = ifc_name2unit(name, &unit);
539 if (err != 0)
540 return (err);
541
542 wildcard = (unit < 0);
543
544 err = ifc_alloc_unit(ifc, &unit);
545 if (err != 0)
546 return (err);
547
638
639 err = ifc_name2unit(name, &unit);
640 if (err != 0)
641 return (err);
642
643 wildcard = (unit < 0);
644
645 err = ifc_alloc_unit(ifc, &unit);
646 if (err != 0)
647 return (err);
648
548 err = ifcs->ifcs_create(ifc, unit, params);
649 err = ifc->ifcs_create(ifc, unit, params);
549 if (err != 0) {
550 ifc_free_unit(ifc, unit);
551 return (err);
552 }
553
554 /* In the wildcard case, we need to update the name. */
555 if (wildcard) {
556 for (dp = name; *dp != '\0'; dp++);

--- 7 unchanged lines hidden (view full) ---

564 panic("if_clone_create(): interface name too long");
565 }
566
567 }
568
569 return (0);
570}
571
650 if (err != 0) {
651 ifc_free_unit(ifc, unit);
652 return (err);
653 }
654
655 /* In the wildcard case, we need to update the name. */
656 if (wildcard) {
657 for (dp = name; *dp != '\0'; dp++);

--- 7 unchanged lines hidden (view full) ---

665 panic("if_clone_create(): interface name too long");
666 }
667
668 }
669
670 return (0);
671}
672
572int
673static int
573ifc_simple_destroy(struct if_clone *ifc, struct ifnet *ifp)
574{
575 int unit;
674ifc_simple_destroy(struct if_clone *ifc, struct ifnet *ifp)
675{
676 int unit;
576 struct ifc_simple_data *ifcs = ifc->ifc_data;
577
578 unit = ifp->if_dunit;
579
677
678 unit = ifp->if_dunit;
679
580 if (unit < ifcs->ifcs_minifs)
680 if (unit < ifc->ifcs_minifs)
581 return (EINVAL);
582
681 return (EINVAL);
682
583 ifcs->ifcs_destroy(ifp);
683 ifc->ifcs_destroy(ifp);
584
585 ifc_free_unit(ifc, unit);
586
587 return (0);
588}
684
685 ifc_free_unit(ifc, unit);
686
687 return (0);
688}