2 * Copyright (c) 1980, 1986, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
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
29 * @(#)if.c 8.3 (Berkeley) 1/4/94
30 * $FreeBSD: src/sys/net/if.c,v 1.185 2004/03/13 02:35:03 brooks Exp $
33 #include <sys/param.h>
34 #include <sys/kernel.h>
35 #include <sys/malloc.h>
36 #include <sys/eventhandler.h>
37 #include <sys/limits.h>
40 #include <net/if_var.h>
41 #include <net/if_clone.h>
43 static LIST_HEAD(, if_clone
) if_cloners
= LIST_HEAD_INITIALIZER(if_cloners
);
44 static int if_cloners_count
;
46 MALLOC_DEFINE(M_CLONE
, "clone", "interface cloning framework");
48 static int if_name2unit(const char *, int *);
49 static bool if_clone_match(struct if_clone
*, const char *);
50 static struct if_clone
*if_clone_lookup(const char *);
51 static int if_clone_alloc_unit(struct if_clone
*, int *);
52 static void if_clone_free_unit(struct if_clone
*, int);
53 static int if_clone_createif(struct if_clone
*, int, caddr_t
);
56 * Lookup the cloner and create a clone network interface.
59 if_clone_create(char *name
, int len
, caddr_t params
)
62 char ifname
[IFNAMSIZ
];
67 if ((ifc
= if_clone_lookup(name
)) == NULL
)
69 if ((err
= if_name2unit(name
, &unit
)) != 0)
72 wildcard
= (unit
< 0);
74 if ((err
= if_clone_alloc_unit(ifc
, &unit
)) != 0)
77 ksnprintf(ifname
, IFNAMSIZ
, "%s%d", ifc
->ifc_name
, unit
);
80 * Update the name with the allocated unit for the caller,
81 * who must preserve enough space.
83 if (wildcard
&& strlcpy(name
, ifname
, len
) >= len
)
86 if ((err
= if_clone_createif(ifc
, unit
, params
)) != 0) {
87 if_clone_free_unit(ifc
, unit
);
95 * Lookup the cloner and destroy a clone network interface.
98 if_clone_destroy(const char *name
)
100 struct if_clone
*ifc
;
110 if ((ifc
= if_clone_lookup(ifp
->if_dname
)) == NULL
)
113 unit
= ifp
->if_dunit
;
114 if (unit
< ifc
->ifc_minifs
)
117 if (ifc
->ifc_destroy
== NULL
)
121 error
= ifc
->ifc_destroy(ifp
);
126 if_clone_free_unit(ifc
, unit
);
132 * Register a network interface cloner.
135 if_clone_attach(struct if_clone
*ifc
)
137 struct if_clone
*ifct
;
141 LIST_FOREACH(ifct
, &if_cloners
, ifc_list
) {
142 if (strcmp(ifct
->ifc_name
, ifc
->ifc_name
) == 0)
146 KASSERT(ifc
->ifc_minifs
- 1 <= ifc
->ifc_maxunit
,
147 ("%s: %s requested more units then allowed (%d > %d)",
148 __func__
, ifc
->ifc_name
, ifc
->ifc_minifs
,
149 ifc
->ifc_maxunit
+ 1));
151 * Compute bitmap size and allocate it.
153 maxclone
= ifc
->ifc_maxunit
+ 1;
155 if ((len
<< 3) < maxclone
)
157 ifc
->ifc_units
= kmalloc(len
, M_CLONE
, M_WAITOK
| M_ZERO
);
158 ifc
->ifc_bmlen
= len
;
160 LIST_INSERT_HEAD(&if_cloners
, ifc
, ifc_list
);
163 for (unit
= 0; unit
< ifc
->ifc_minifs
; unit
++) {
164 if_clone_alloc_unit(ifc
, &unit
);
165 if (if_clone_createif(ifc
, unit
, NULL
) != 0) {
166 panic("%s: failed to create required interface %s%d",
167 __func__
, ifc
->ifc_name
, unit
);
171 EVENTHANDLER_INVOKE(if_clone_event
, ifc
);
177 * Unregister a network interface cloner.
180 if_clone_detach(struct if_clone
*ifc
)
183 LIST_REMOVE(ifc
, ifc_list
);
184 kfree(ifc
->ifc_units
, M_CLONE
);
189 * Provide list of interface cloners to userspace.
192 if_clone_list(struct if_clonereq
*ifcr
)
194 char outbuf
[IFNAMSIZ
], *dst
;
195 struct if_clone
*ifc
;
196 int count
, error
= 0;
198 ifcr
->ifcr_total
= if_cloners_count
;
199 if ((dst
= ifcr
->ifcr_buffer
) == NULL
) {
200 /* Just asking how many there are. */
204 if (ifcr
->ifcr_count
< 0)
207 count
= (if_cloners_count
< ifcr
->ifcr_count
) ?
208 if_cloners_count
: ifcr
->ifcr_count
;
210 for (ifc
= LIST_FIRST(&if_cloners
);
211 ifc
!= NULL
&& count
!= 0;
212 ifc
= LIST_NEXT(ifc
, ifc_list
), count
--, dst
+= IFNAMSIZ
) {
213 strlcpy(outbuf
, ifc
->ifc_name
, IFNAMSIZ
);
214 error
= copyout(outbuf
, dst
, IFNAMSIZ
);
223 * Extract the unit number from interface name of the form "name###".
224 * A unit of -1 is stored if the given name doesn't have a unit.
226 * Returns 0 on success and an error on failure.
229 if_name2unit(const char *name
, int *unit
)
232 int cutoff
= INT_MAX
/ 10;
233 int cutlim
= INT_MAX
% 10;
235 for (cp
= name
; *cp
!= '\0' && (*cp
< '0' || *cp
> '9'); cp
++)
239 } else if (cp
[0] == '0' && cp
[1] != '\0') {
240 /* Disallow leading zeroes. */
243 for (*unit
= 0; *cp
!= '\0'; cp
++) {
244 if (*cp
< '0' || *cp
> '9') {
245 /* Bogus unit number. */
248 if (*unit
> cutoff
||
249 (*unit
== cutoff
&& *cp
- '0' > cutlim
))
251 *unit
= (*unit
* 10) + (*cp
- '0');
259 * Check whether the interface cloner matches the name.
262 if_clone_match(struct if_clone
*ifc
, const char *name
)
268 for (cp
= name
, i
= 0; i
< strlen(ifc
->ifc_name
); i
++, cp
++) {
269 if (ifc
->ifc_name
[i
] != *cp
)
273 /* Make sure there's a unit number or nothing after the name */
274 for ( ; *cp
!= '\0'; cp
++) {
275 if (*cp
< '0' || *cp
> '9')
283 * Look up a network interface cloner.
285 static struct if_clone
*
286 if_clone_lookup(const char *name
)
288 struct if_clone
*ifc
;
290 LIST_FOREACH(ifc
, &if_cloners
, ifc_list
) {
291 if (if_clone_match(ifc
, name
))
299 * Allocate a unit number.
301 * Returns 0 on success and an error on failure.
304 if_clone_alloc_unit(struct if_clone
*ifc
, int *unit
)
310 * Wildcard mode: find a free unit.
313 while (bytoff
< ifc
->ifc_bmlen
&&
314 ifc
->ifc_units
[bytoff
] == 0xff)
316 if (bytoff
>= ifc
->ifc_bmlen
)
318 while ((ifc
->ifc_units
[bytoff
] & (1 << bitoff
)) != 0)
320 *unit
= (bytoff
<< 3) + bitoff
;
323 bitoff
= *unit
- (bytoff
<< 3);
326 if (*unit
> ifc
->ifc_maxunit
)
330 * Allocate the unit in the bitmap.
332 KASSERT((ifc
->ifc_units
[bytoff
] & (1 << bitoff
)) == 0,
333 ("%s: bit is already set", __func__
));
334 ifc
->ifc_units
[bytoff
] |= (1 << bitoff
);
340 * Free an allocated unit number.
343 if_clone_free_unit(struct if_clone
*ifc
, int unit
)
348 bitoff
= unit
- (bytoff
<< 3);
349 KASSERT((ifc
->ifc_units
[bytoff
] & (1 << bitoff
)) != 0,
350 ("%s: bit is already cleared", __func__
));
351 ifc
->ifc_units
[bytoff
] &= ~(1 << bitoff
);
355 * Create a clone network interface.
358 if_clone_createif(struct if_clone
*ifc
, int unit
, caddr_t params
)
361 char ifname
[IFNAMSIZ
];
364 ksnprintf(ifname
, IFNAMSIZ
, "%s%d", ifc
->ifc_name
, unit
);
367 ifp
= ifunit(ifname
);
372 err
= (*ifc
->ifc_create
)(ifc
, unit
, params
);
377 ifp
= ifunit(ifname
);
382 err
= if_addgroup(ifp
, ifc
->ifc_name
);