Line data Source code
1 : /* $OpenBSD: if.c,v 1.564 2018/09/11 10:23:40 krw Exp $ */
2 : /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */
3 :
4 : /*
5 : * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 : * All rights reserved.
7 : *
8 : * Redistribution and use in source and binary forms, with or without
9 : * modification, are permitted provided that the following conditions
10 : * are met:
11 : * 1. Redistributions of source code must retain the above copyright
12 : * notice, this list of conditions and the following disclaimer.
13 : * 2. Redistributions in binary form must reproduce the above copyright
14 : * notice, this list of conditions and the following disclaimer in the
15 : * documentation and/or other materials provided with the distribution.
16 : * 3. Neither the name of the project nor the names of its contributors
17 : * may be used to endorse or promote products derived from this software
18 : * without specific prior written permission.
19 : *
20 : * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 : * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 : * SUCH DAMAGE.
31 : */
32 :
33 : /*
34 : * Copyright (c) 1980, 1986, 1993
35 : * The Regents of the University of California. All rights reserved.
36 : *
37 : * Redistribution and use in source and binary forms, with or without
38 : * modification, are permitted provided that the following conditions
39 : * are met:
40 : * 1. Redistributions of source code must retain the above copyright
41 : * notice, this list of conditions and the following disclaimer.
42 : * 2. Redistributions in binary form must reproduce the above copyright
43 : * notice, this list of conditions and the following disclaimer in the
44 : * documentation and/or other materials provided with the distribution.
45 : * 3. Neither the name of the University nor the names of its contributors
46 : * may be used to endorse or promote products derived from this software
47 : * without specific prior written permission.
48 : *
49 : * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 : * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 : * SUCH DAMAGE.
60 : *
61 : * @(#)if.c 8.3 (Berkeley) 1/4/94
62 : */
63 :
64 : #include "bpfilter.h"
65 : #include "bridge.h"
66 : #include "carp.h"
67 : #include "ether.h"
68 : #include "pf.h"
69 : #include "pfsync.h"
70 : #include "ppp.h"
71 : #include "pppoe.h"
72 : #include "switch.h"
73 : #include "trunk.h"
74 :
75 : #include <sys/param.h>
76 : #include <sys/systm.h>
77 : #include <sys/mbuf.h>
78 : #include <sys/socket.h>
79 : #include <sys/socketvar.h>
80 : #include <sys/timeout.h>
81 : #include <sys/protosw.h>
82 : #include <sys/kernel.h>
83 : #include <sys/ioctl.h>
84 : #include <sys/domain.h>
85 : #include <sys/task.h>
86 : #include <sys/atomic.h>
87 : #include <sys/proc.h>
88 :
89 : #include <dev/rndvar.h>
90 :
91 : #include <net/if.h>
92 : #include <net/if_dl.h>
93 : #include <net/if_types.h>
94 : #include <net/route.h>
95 : #include <net/netisr.h>
96 :
97 : #include <netinet/in.h>
98 : #include <netinet/if_ether.h>
99 : #include <netinet/igmp.h>
100 : #ifdef MROUTING
101 : #include <netinet/ip_mroute.h>
102 : #endif
103 :
104 : #ifdef INET6
105 : #include <netinet6/in6_var.h>
106 : #include <netinet6/in6_ifattach.h>
107 : #include <netinet6/nd6.h>
108 : #include <netinet/ip6.h>
109 : #include <netinet6/ip6_var.h>
110 : #endif
111 :
112 : #ifdef MPLS
113 : #include <netmpls/mpls.h>
114 : #endif
115 :
116 : #if NBPFILTER > 0
117 : #include <net/bpf.h>
118 : #endif
119 :
120 : #if NBRIDGE > 0
121 : #include <net/if_bridge.h>
122 : #endif
123 :
124 : #if NCARP > 0
125 : #include <netinet/ip_carp.h>
126 : #endif
127 :
128 : #if NPF > 0
129 : #include <net/pfvar.h>
130 : #endif
131 :
132 : #include <sys/device.h>
133 :
134 : void if_attachsetup(struct ifnet *);
135 : void if_attachdomain(struct ifnet *);
136 : void if_attach_common(struct ifnet *);
137 : int if_createrdomain(int, struct ifnet *);
138 : int if_setrdomain(struct ifnet *, int);
139 : void if_slowtimo(void *);
140 :
141 : void if_detached_qstart(struct ifqueue *);
142 : int if_detached_ioctl(struct ifnet *, u_long, caddr_t);
143 :
144 : int ifioctl_get(u_long, caddr_t);
145 : int ifconf(caddr_t);
146 :
147 : int if_getgroup(caddr_t, struct ifnet *);
148 : int if_getgroupmembers(caddr_t);
149 : int if_getgroupattribs(caddr_t);
150 : int if_setgroupattribs(caddr_t);
151 : int if_getgrouplist(caddr_t);
152 :
153 : void if_linkstate(struct ifnet *);
154 : void if_linkstate_task(void *);
155 :
156 : int if_clone_list(struct if_clonereq *);
157 : struct if_clone *if_clone_lookup(const char *, int *);
158 :
159 : int if_group_egress_build(void);
160 :
161 : void if_watchdog_task(void *);
162 :
163 : void if_netisr(void *);
164 :
165 : #ifdef DDB
166 : void ifa_print_all(void);
167 : #endif
168 :
169 : void if_qstart_compat(struct ifqueue *);
170 :
171 : /*
172 : * interface index map
173 : *
174 : * the kernel maintains a mapping of interface indexes to struct ifnet
175 : * pointers.
176 : *
177 : * the map is an array of struct ifnet pointers prefixed by an if_map
178 : * structure. the if_map structure stores the length of its array.
179 : *
180 : * as interfaces are attached to the system, the map is grown on demand
181 : * up to USHRT_MAX entries.
182 : *
183 : * interface index 0 is reserved and represents no interface. this
184 : * supports the use of the interface index as the scope for IPv6 link
185 : * local addresses, where scope 0 means no scope has been specified.
186 : * it also supports the use of interface index as the unique identifier
187 : * for network interfaces in SNMP applications as per RFC2863. therefore
188 : * if_get(0) returns NULL.
189 : */
190 :
191 : void if_ifp_dtor(void *, void *);
192 : void if_map_dtor(void *, void *);
193 : struct ifnet *if_ref(struct ifnet *);
194 :
195 : /*
196 : * struct if_map
197 : *
198 : * bounded array of ifnet srp pointers used to fetch references of live
199 : * interfaces with if_get().
200 : */
201 :
202 : struct if_map {
203 : unsigned long limit;
204 : /* followed by limit ifnet srp pointers */
205 : };
206 :
207 : /*
208 : * struct if_idxmap
209 : *
210 : * infrastructure to manage updates and accesses to the current if_map.
211 : */
212 :
213 : struct if_idxmap {
214 : unsigned int serial;
215 : unsigned int count;
216 : struct srp map;
217 : };
218 :
219 : void if_idxmap_init(unsigned int);
220 : void if_idxmap_insert(struct ifnet *);
221 : void if_idxmap_remove(struct ifnet *);
222 :
223 : TAILQ_HEAD(, ifg_group) ifg_head = TAILQ_HEAD_INITIALIZER(ifg_head);
224 :
225 : LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
226 : int if_cloners_count;
227 :
228 : struct timeout net_tick_to;
229 : void net_tick(void *);
230 : int net_livelocked(void);
231 : int ifq_congestion;
232 :
233 : int netisr;
234 :
235 : #define NET_TASKQ 1
236 : struct taskq *nettqmp[NET_TASKQ];
237 :
238 : struct task if_input_task_locked = TASK_INITIALIZER(if_netisr, NULL);
239 :
240 : /*
241 : * Serialize socket operations to ensure no new sleeping points
242 : * are introduced in IP output paths.
243 : */
244 : struct rwlock netlock = RWLOCK_INITIALIZER("netlock");
245 :
246 : /*
247 : * Network interface utility routines.
248 : */
249 : void
250 0 : ifinit(void)
251 : {
252 : unsigned int i;
253 :
254 : /*
255 : * most machines boot with 4 or 5 interfaces, so size the initial map
256 : * to accomodate this
257 : */
258 0 : if_idxmap_init(8);
259 :
260 0 : timeout_set(&net_tick_to, net_tick, &net_tick_to);
261 :
262 0 : for (i = 0; i < NET_TASKQ; i++) {
263 0 : nettqmp[i] = taskq_create("softnet", 1, IPL_NET, TASKQ_MPSAFE);
264 0 : if (nettqmp[i] == NULL)
265 0 : panic("unable to create network taskq %d", i);
266 : }
267 :
268 0 : net_tick(&net_tick_to);
269 0 : }
270 :
271 : static struct if_idxmap if_idxmap = {
272 : 0,
273 : 0,
274 : SRP_INITIALIZER()
275 : };
276 :
277 : struct srp_gc if_ifp_gc = SRP_GC_INITIALIZER(if_ifp_dtor, NULL);
278 : struct srp_gc if_map_gc = SRP_GC_INITIALIZER(if_map_dtor, NULL);
279 :
280 : struct ifnet_head ifnet = TAILQ_HEAD_INITIALIZER(ifnet);
281 :
282 : void
283 0 : if_idxmap_init(unsigned int limit)
284 : {
285 : struct if_map *if_map;
286 : struct srp *map;
287 : unsigned int i;
288 :
289 0 : if_idxmap.serial = 1; /* skip ifidx 0 so it can return NULL */
290 :
291 0 : if_map = malloc(sizeof(*if_map) + limit * sizeof(*map),
292 : M_IFADDR, M_WAITOK);
293 :
294 0 : if_map->limit = limit;
295 0 : map = (struct srp *)(if_map + 1);
296 0 : for (i = 0; i < limit; i++)
297 0 : srp_init(&map[i]);
298 :
299 : /* this is called early so there's nothing to race with */
300 0 : srp_update_locked(&if_map_gc, &if_idxmap.map, if_map);
301 0 : }
302 :
303 : void
304 0 : if_idxmap_insert(struct ifnet *ifp)
305 : {
306 : struct if_map *if_map;
307 : struct srp *map;
308 : unsigned int index, i;
309 :
310 0 : refcnt_init(&ifp->if_refcnt);
311 :
312 : /* the kernel lock guarantees serialised modifications to if_idxmap */
313 0 : KERNEL_ASSERT_LOCKED();
314 :
315 0 : if (++if_idxmap.count > USHRT_MAX)
316 0 : panic("too many interfaces");
317 :
318 0 : if_map = srp_get_locked(&if_idxmap.map);
319 0 : map = (struct srp *)(if_map + 1);
320 :
321 0 : index = if_idxmap.serial++ & USHRT_MAX;
322 :
323 0 : if (index >= if_map->limit) {
324 : struct if_map *nif_map;
325 : struct srp *nmap;
326 : unsigned int nlimit;
327 : struct ifnet *nifp;
328 :
329 0 : nlimit = if_map->limit * 2;
330 0 : nif_map = malloc(sizeof(*nif_map) + nlimit * sizeof(*nmap),
331 : M_IFADDR, M_WAITOK);
332 0 : nmap = (struct srp *)(nif_map + 1);
333 :
334 0 : nif_map->limit = nlimit;
335 0 : for (i = 0; i < if_map->limit; i++) {
336 0 : srp_init(&nmap[i]);
337 0 : nifp = srp_get_locked(&map[i]);
338 0 : if (nifp != NULL) {
339 0 : srp_update_locked(&if_ifp_gc, &nmap[i],
340 0 : if_ref(nifp));
341 0 : }
342 : }
343 :
344 0 : while (i < nlimit) {
345 0 : srp_init(&nmap[i]);
346 0 : i++;
347 : }
348 :
349 0 : srp_update_locked(&if_map_gc, &if_idxmap.map, nif_map);
350 : if_map = nif_map;
351 : map = nmap;
352 0 : }
353 :
354 : /* pick the next free index */
355 0 : for (i = 0; i < USHRT_MAX; i++) {
356 0 : if (index != 0 && srp_get_locked(&map[index]) == NULL)
357 : break;
358 :
359 0 : index = if_idxmap.serial++ & USHRT_MAX;
360 : }
361 :
362 : /* commit */
363 0 : ifp->if_index = index;
364 0 : srp_update_locked(&if_ifp_gc, &map[index], if_ref(ifp));
365 0 : }
366 :
367 : void
368 0 : if_idxmap_remove(struct ifnet *ifp)
369 : {
370 : struct if_map *if_map;
371 : struct srp *map;
372 : unsigned int index;
373 :
374 0 : index = ifp->if_index;
375 :
376 : /* the kernel lock guarantees serialised modifications to if_idxmap */
377 0 : KERNEL_ASSERT_LOCKED();
378 :
379 0 : if_map = srp_get_locked(&if_idxmap.map);
380 0 : KASSERT(index < if_map->limit);
381 :
382 0 : map = (struct srp *)(if_map + 1);
383 0 : KASSERT(ifp == (struct ifnet *)srp_get_locked(&map[index]));
384 :
385 0 : srp_update_locked(&if_ifp_gc, &map[index], NULL);
386 0 : if_idxmap.count--;
387 : /* end of if_idxmap modifications */
388 :
389 : /* sleep until the last reference is released */
390 0 : refcnt_finalize(&ifp->if_refcnt, "ifidxrm");
391 0 : }
392 :
393 : void
394 0 : if_ifp_dtor(void *null, void *ifp)
395 : {
396 0 : if_put(ifp);
397 0 : }
398 :
399 : void
400 0 : if_map_dtor(void *null, void *m)
401 : {
402 0 : struct if_map *if_map = m;
403 0 : struct srp *map = (struct srp *)(if_map + 1);
404 : unsigned int i;
405 :
406 : /*
407 : * dont need to serialize the use of update_locked since this is
408 : * the last reference to this map. there's nothing to race against.
409 : */
410 0 : for (i = 0; i < if_map->limit; i++)
411 0 : srp_update_locked(&if_ifp_gc, &map[i], NULL);
412 :
413 0 : free(if_map, M_IFADDR, sizeof(*if_map) + if_map->limit * sizeof(*map));
414 0 : }
415 :
416 : /*
417 : * Attach an interface to the
418 : * list of "active" interfaces.
419 : */
420 : void
421 0 : if_attachsetup(struct ifnet *ifp)
422 : {
423 : unsigned long ifidx;
424 :
425 0 : NET_ASSERT_LOCKED();
426 :
427 0 : TAILQ_INIT(&ifp->if_groups);
428 :
429 0 : if_addgroup(ifp, IFG_ALL);
430 :
431 0 : if_attachdomain(ifp);
432 : #if NPF > 0
433 0 : pfi_attach_ifnet(ifp);
434 : #endif
435 :
436 0 : timeout_set(&ifp->if_slowtimo, if_slowtimo, ifp);
437 0 : if_slowtimo(ifp);
438 :
439 0 : if_idxmap_insert(ifp);
440 0 : KASSERT(if_get(0) == NULL);
441 :
442 0 : ifidx = ifp->if_index;
443 :
444 0 : task_set(&ifp->if_watchdogtask, if_watchdog_task, (void *)ifidx);
445 0 : task_set(&ifp->if_linkstatetask, if_linkstate_task, (void *)ifidx);
446 :
447 : /* Announce the interface. */
448 0 : rtm_ifannounce(ifp, IFAN_ARRIVAL);
449 0 : }
450 :
451 : /*
452 : * Allocate the link level name for the specified interface. This
453 : * is an attachment helper. It must be called after ifp->if_addrlen
454 : * is initialized, which may not be the case when if_attach() is
455 : * called.
456 : */
457 : void
458 0 : if_alloc_sadl(struct ifnet *ifp)
459 : {
460 : unsigned int socksize;
461 : int namelen, masklen;
462 : struct sockaddr_dl *sdl;
463 :
464 : /*
465 : * If the interface already has a link name, release it
466 : * now. This is useful for interfaces that can change
467 : * link types, and thus switch link names often.
468 : */
469 0 : if (ifp->if_sadl != NULL)
470 0 : if_free_sadl(ifp);
471 :
472 0 : namelen = strlen(ifp->if_xname);
473 0 : masklen = offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;
474 0 : socksize = masklen + ifp->if_addrlen;
475 : #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
476 0 : if (socksize < sizeof(*sdl))
477 : socksize = sizeof(*sdl);
478 0 : socksize = ROUNDUP(socksize);
479 0 : sdl = malloc(socksize, M_IFADDR, M_WAITOK|M_ZERO);
480 0 : sdl->sdl_len = socksize;
481 0 : sdl->sdl_family = AF_LINK;
482 0 : bcopy(ifp->if_xname, sdl->sdl_data, namelen);
483 0 : sdl->sdl_nlen = namelen;
484 0 : sdl->sdl_alen = ifp->if_addrlen;
485 0 : sdl->sdl_index = ifp->if_index;
486 0 : sdl->sdl_type = ifp->if_type;
487 0 : ifp->if_sadl = sdl;
488 0 : }
489 :
490 : /*
491 : * Free the link level name for the specified interface. This is
492 : * a detach helper. This is called from if_detach() or from
493 : * link layer type specific detach functions.
494 : */
495 : void
496 0 : if_free_sadl(struct ifnet *ifp)
497 : {
498 0 : free(ifp->if_sadl, M_IFADDR, 0);
499 0 : ifp->if_sadl = NULL;
500 0 : }
501 :
502 : void
503 0 : if_attachdomain(struct ifnet *ifp)
504 : {
505 : struct domain *dp;
506 : int i, s;
507 :
508 0 : s = splnet();
509 :
510 : /* address family dependent data region */
511 0 : bzero(ifp->if_afdata, sizeof(ifp->if_afdata));
512 0 : for (i = 0; (dp = domains[i]) != NULL; i++) {
513 0 : if (dp->dom_ifattach)
514 0 : ifp->if_afdata[dp->dom_family] =
515 0 : (*dp->dom_ifattach)(ifp);
516 : }
517 :
518 0 : splx(s);
519 0 : }
520 :
521 : void
522 0 : if_attachhead(struct ifnet *ifp)
523 : {
524 0 : if_attach_common(ifp);
525 0 : NET_LOCK();
526 0 : TAILQ_INSERT_HEAD(&ifnet, ifp, if_list);
527 0 : if_attachsetup(ifp);
528 0 : NET_UNLOCK();
529 0 : }
530 :
531 : void
532 0 : if_attach(struct ifnet *ifp)
533 : {
534 0 : if_attach_common(ifp);
535 0 : NET_LOCK();
536 0 : TAILQ_INSERT_TAIL(&ifnet, ifp, if_list);
537 0 : if_attachsetup(ifp);
538 0 : NET_UNLOCK();
539 0 : }
540 :
541 : void
542 0 : if_attach_queues(struct ifnet *ifp, unsigned int nqs)
543 : {
544 : struct ifqueue **map;
545 : struct ifqueue *ifq;
546 : int i;
547 :
548 0 : KASSERT(ifp->if_ifqs == ifp->if_snd.ifq_ifqs);
549 0 : KASSERT(nqs != 0);
550 :
551 0 : map = mallocarray(sizeof(*map), nqs, M_DEVBUF, M_WAITOK);
552 :
553 0 : ifp->if_snd.ifq_softc = NULL;
554 0 : map[0] = &ifp->if_snd;
555 :
556 0 : for (i = 1; i < nqs; i++) {
557 0 : ifq = malloc(sizeof(*ifq), M_DEVBUF, M_WAITOK|M_ZERO);
558 0 : ifq_set_maxlen(ifq, ifp->if_snd.ifq_maxlen);
559 0 : ifq_init(ifq, ifp, i);
560 0 : map[i] = ifq;
561 : }
562 :
563 0 : ifp->if_ifqs = map;
564 0 : ifp->if_nifqs = nqs;
565 0 : }
566 :
567 : void
568 0 : if_attach_iqueues(struct ifnet *ifp, unsigned int niqs)
569 : {
570 : struct ifiqueue **map;
571 : struct ifiqueue *ifiq;
572 : unsigned int i;
573 :
574 0 : KASSERT(niqs != 0);
575 :
576 0 : map = mallocarray(niqs, sizeof(*map), M_DEVBUF, M_WAITOK);
577 :
578 0 : ifp->if_rcv.ifiq_softc = NULL;
579 0 : map[0] = &ifp->if_rcv;
580 :
581 0 : for (i = 1; i < niqs; i++) {
582 0 : ifiq = malloc(sizeof(*ifiq), M_DEVBUF, M_WAITOK|M_ZERO);
583 0 : ifiq_init(ifiq, ifp, i);
584 0 : map[i] = ifiq;
585 : }
586 :
587 0 : ifp->if_iqs = map;
588 0 : ifp->if_niqs = niqs;
589 0 : }
590 :
591 : void
592 0 : if_attach_common(struct ifnet *ifp)
593 : {
594 0 : KASSERT(ifp->if_ioctl != NULL);
595 :
596 0 : TAILQ_INIT(&ifp->if_addrlist);
597 0 : TAILQ_INIT(&ifp->if_maddrlist);
598 :
599 0 : if (!ISSET(ifp->if_xflags, IFXF_MPSAFE)) {
600 0 : KASSERTMSG(ifp->if_qstart == NULL,
601 : "%s: if_qstart set without MPSAFE set", ifp->if_xname);
602 0 : ifp->if_qstart = if_qstart_compat;
603 0 : } else {
604 0 : KASSERTMSG(ifp->if_start == NULL,
605 : "%s: if_start set with MPSAFE set", ifp->if_xname);
606 0 : KASSERTMSG(ifp->if_qstart != NULL,
607 : "%s: if_qstart not set with MPSAFE set", ifp->if_xname);
608 : }
609 :
610 0 : ifq_init(&ifp->if_snd, ifp, 0);
611 :
612 0 : ifp->if_snd.ifq_ifqs[0] = &ifp->if_snd;
613 0 : ifp->if_ifqs = ifp->if_snd.ifq_ifqs;
614 0 : ifp->if_nifqs = 1;
615 :
616 0 : ifiq_init(&ifp->if_rcv, ifp, 0);
617 :
618 0 : ifp->if_rcv.ifiq_ifiqs[0] = &ifp->if_rcv;
619 0 : ifp->if_iqs = ifp->if_rcv.ifiq_ifiqs;
620 0 : ifp->if_niqs = 1;
621 :
622 0 : ifp->if_addrhooks = malloc(sizeof(*ifp->if_addrhooks),
623 : M_TEMP, M_WAITOK);
624 0 : TAILQ_INIT(ifp->if_addrhooks);
625 0 : ifp->if_linkstatehooks = malloc(sizeof(*ifp->if_linkstatehooks),
626 : M_TEMP, M_WAITOK);
627 0 : TAILQ_INIT(ifp->if_linkstatehooks);
628 0 : ifp->if_detachhooks = malloc(sizeof(*ifp->if_detachhooks),
629 : M_TEMP, M_WAITOK);
630 0 : TAILQ_INIT(ifp->if_detachhooks);
631 :
632 0 : if (ifp->if_rtrequest == NULL)
633 0 : ifp->if_rtrequest = if_rtrequest_dummy;
634 0 : ifp->if_llprio = IFQ_DEFPRIO;
635 :
636 0 : SRPL_INIT(&ifp->if_inputs);
637 0 : }
638 :
639 : void
640 0 : if_attach_ifq(struct ifnet *ifp, const struct ifq_ops *newops, void *args)
641 : {
642 : /*
643 : * only switch the ifq_ops on the first ifq on an interface.
644 : *
645 : * the only ifq_ops we provide priq and hfsc, and hfsc only
646 : * works on a single ifq. because the code uses the ifq_ops
647 : * on the first ifq (if_snd) to select a queue for an mbuf,
648 : * by switching only the first one we change both the algorithm
649 : * and force the routing of all new packets to it.
650 : */
651 0 : ifq_attach(&ifp->if_snd, newops, args);
652 0 : }
653 :
654 : void
655 0 : if_start(struct ifnet *ifp)
656 : {
657 0 : KASSERT(ifp->if_qstart == if_qstart_compat);
658 0 : if_qstart_compat(&ifp->if_snd);
659 0 : }
660 : void
661 0 : if_qstart_compat(struct ifqueue *ifq)
662 : {
663 0 : struct ifnet *ifp = ifq->ifq_if;
664 : int s;
665 :
666 : /*
667 : * the stack assumes that an interface can have multiple
668 : * transmit rings, but a lot of drivers are still written
669 : * so that interfaces and send rings have a 1:1 mapping.
670 : * this provides compatability between the stack and the older
671 : * drivers by translating from the only queue they have
672 : * (ifp->if_snd) back to the interface and calling if_start.
673 : */
674 :
675 0 : KERNEL_LOCK();
676 0 : s = splnet();
677 0 : (*ifp->if_start)(ifp);
678 0 : splx(s);
679 0 : KERNEL_UNLOCK();
680 0 : }
681 :
682 : int
683 0 : if_enqueue(struct ifnet *ifp, struct mbuf *m)
684 : {
685 : unsigned int idx;
686 : struct ifqueue *ifq;
687 : int error;
688 :
689 : #if NPF > 0
690 0 : if (m->m_pkthdr.pf.delay > 0)
691 0 : return (pf_delay_pkt(m, ifp->if_index));
692 : #endif
693 :
694 : #if NBRIDGE > 0
695 0 : if (ifp->if_bridgeport && (m->m_flags & M_PROTO1) == 0) {
696 0 : KERNEL_LOCK();
697 0 : error = bridge_output(ifp, m, NULL, NULL);
698 0 : KERNEL_UNLOCK();
699 0 : return (error);
700 : }
701 : #endif
702 :
703 : #if NPF > 0
704 0 : pf_pkt_addr_changed(m);
705 : #endif /* NPF > 0 */
706 :
707 : /*
708 : * use the operations on the first ifq to pick which of the array
709 : * gets this mbuf.
710 : */
711 0 : idx = ifq_idx(&ifp->if_snd, ifp->if_nifqs, m);
712 0 : ifq = ifp->if_ifqs[idx];
713 :
714 0 : error = ifq_enqueue(ifq, m);
715 0 : if (error)
716 0 : return (error);
717 :
718 0 : ifq_start(ifq);
719 :
720 0 : return (0);
721 0 : }
722 :
723 : void
724 0 : if_input(struct ifnet *ifp, struct mbuf_list *ml)
725 : {
726 0 : ifiq_input(&ifp->if_rcv, ml, 2048);
727 0 : }
728 :
729 : int
730 0 : if_input_local(struct ifnet *ifp, struct mbuf *m, sa_family_t af)
731 : {
732 : #if NBPFILTER > 0
733 : /*
734 : * Only send packets to bpf if they are destinated to local
735 : * addresses.
736 : *
737 : * if_input_local() is also called for SIMPLEX interfaces to
738 : * duplicate packets for local use. But don't dup them to bpf.
739 : */
740 0 : if (ifp->if_flags & IFF_LOOPBACK) {
741 0 : caddr_t if_bpf = ifp->if_bpf;
742 :
743 0 : if (if_bpf)
744 0 : bpf_mtap_af(if_bpf, af, m, BPF_DIRECTION_OUT);
745 0 : }
746 : #endif
747 0 : m_resethdr(m);
748 0 : m->m_flags |= M_LOOP;
749 0 : m->m_pkthdr.ph_ifidx = ifp->if_index;
750 0 : m->m_pkthdr.ph_rtableid = ifp->if_rdomain;
751 :
752 0 : ifp->if_opackets++;
753 0 : ifp->if_obytes += m->m_pkthdr.len;
754 :
755 0 : ifp->if_ipackets++;
756 0 : ifp->if_ibytes += m->m_pkthdr.len;
757 :
758 0 : switch (af) {
759 : case AF_INET:
760 0 : ipv4_input(ifp, m);
761 0 : break;
762 : #ifdef INET6
763 : case AF_INET6:
764 0 : ipv6_input(ifp, m);
765 0 : break;
766 : #endif /* INET6 */
767 : #ifdef MPLS
768 : case AF_MPLS:
769 0 : mpls_input(ifp, m);
770 0 : break;
771 : #endif /* MPLS */
772 : default:
773 0 : printf("%s: can't handle af%d\n", ifp->if_xname, af);
774 0 : m_freem(m);
775 0 : return (EAFNOSUPPORT);
776 : }
777 :
778 0 : return (0);
779 0 : }
780 :
781 : int
782 0 : if_output_local(struct ifnet *ifp, struct mbuf *m, sa_family_t af)
783 : {
784 : struct ifiqueue *ifiq;
785 : unsigned int flow = 0;
786 :
787 0 : m->m_pkthdr.ph_family = af;
788 0 : m->m_pkthdr.ph_ifidx = ifp->if_index;
789 0 : m->m_pkthdr.ph_rtableid = ifp->if_rdomain;
790 :
791 0 : if (ISSET(m->m_pkthdr.ph_flowid, M_FLOWID_VALID))
792 0 : flow = m->m_pkthdr.ph_flowid & M_FLOWID_MASK;
793 :
794 0 : ifiq = ifp->if_iqs[flow % ifp->if_niqs];
795 :
796 0 : return (ifiq_enqueue(ifiq, m) == 0 ? 0 : ENOBUFS);
797 : }
798 :
799 : struct ifih {
800 : SRPL_ENTRY(ifih) ifih_next;
801 : int (*ifih_input)(struct ifnet *, struct mbuf *,
802 : void *);
803 : void *ifih_cookie;
804 : int ifih_refcnt;
805 : struct refcnt ifih_srpcnt;
806 : };
807 :
808 : void if_ih_ref(void *, void *);
809 : void if_ih_unref(void *, void *);
810 :
811 : struct srpl_rc ifih_rc = SRPL_RC_INITIALIZER(if_ih_ref, if_ih_unref, NULL);
812 :
813 : void
814 0 : if_ih_insert(struct ifnet *ifp, int (*input)(struct ifnet *, struct mbuf *,
815 : void *), void *cookie)
816 : {
817 : struct ifih *ifih;
818 :
819 : /* the kernel lock guarantees serialised modifications to if_inputs */
820 0 : KERNEL_ASSERT_LOCKED();
821 :
822 0 : SRPL_FOREACH_LOCKED(ifih, &ifp->if_inputs, ifih_next) {
823 0 : if (ifih->ifih_input == input && ifih->ifih_cookie == cookie) {
824 0 : ifih->ifih_refcnt++;
825 0 : break;
826 : }
827 : }
828 :
829 0 : if (ifih == NULL) {
830 0 : ifih = malloc(sizeof(*ifih), M_DEVBUF, M_WAITOK);
831 :
832 0 : ifih->ifih_input = input;
833 0 : ifih->ifih_cookie = cookie;
834 0 : ifih->ifih_refcnt = 1;
835 0 : refcnt_init(&ifih->ifih_srpcnt);
836 0 : SRPL_INSERT_HEAD_LOCKED(&ifih_rc, &ifp->if_inputs,
837 : ifih, ifih_next);
838 0 : }
839 0 : }
840 :
841 : void
842 0 : if_ih_ref(void *null, void *i)
843 : {
844 0 : struct ifih *ifih = i;
845 :
846 0 : refcnt_take(&ifih->ifih_srpcnt);
847 0 : }
848 :
849 : void
850 0 : if_ih_unref(void *null, void *i)
851 : {
852 0 : struct ifih *ifih = i;
853 :
854 0 : refcnt_rele_wake(&ifih->ifih_srpcnt);
855 0 : }
856 :
857 : void
858 0 : if_ih_remove(struct ifnet *ifp, int (*input)(struct ifnet *, struct mbuf *,
859 : void *), void *cookie)
860 : {
861 : struct ifih *ifih;
862 :
863 : /* the kernel lock guarantees serialised modifications to if_inputs */
864 0 : KERNEL_ASSERT_LOCKED();
865 :
866 0 : SRPL_FOREACH_LOCKED(ifih, &ifp->if_inputs, ifih_next) {
867 0 : if (ifih->ifih_input == input && ifih->ifih_cookie == cookie)
868 : break;
869 : }
870 :
871 0 : KASSERT(ifih != NULL);
872 :
873 0 : if (--ifih->ifih_refcnt == 0) {
874 0 : SRPL_REMOVE_LOCKED(&ifih_rc, &ifp->if_inputs, ifih,
875 : ifih, ifih_next);
876 :
877 0 : refcnt_finalize(&ifih->ifih_srpcnt, "ifihrm");
878 0 : free(ifih, M_DEVBUF, sizeof(*ifih));
879 0 : }
880 0 : }
881 :
882 : void
883 0 : if_input_process(struct ifnet *ifp, struct mbuf_list *ml)
884 : {
885 : struct mbuf *m;
886 : struct ifih *ifih;
887 0 : struct srp_ref sr;
888 : int s;
889 :
890 0 : if (ml_empty(ml))
891 0 : return;
892 :
893 0 : if (!ISSET(ifp->if_xflags, IFXF_CLONED))
894 0 : enqueue_randomness(ml_len(ml));
895 :
896 : /*
897 : * We grab the NET_LOCK() before processing any packet to
898 : * ensure there's no contention on the routing table lock.
899 : *
900 : * Without it we could race with a userland thread to insert
901 : * a L2 entry in ip{6,}_output(). Such race would result in
902 : * one of the threads sleeping *inside* the IP output path.
903 : *
904 : * Since we have a NET_LOCK() we also use it to serialize access
905 : * to PF globals, pipex globals, unicast and multicast addresses
906 : * lists.
907 : */
908 0 : NET_RLOCK();
909 0 : s = splnet();
910 0 : while ((m = ml_dequeue(ml)) != NULL) {
911 : /*
912 : * Pass this mbuf to all input handlers of its
913 : * interface until it is consumed.
914 : */
915 0 : SRPL_FOREACH(ifih, &sr, &ifp->if_inputs, ifih_next) {
916 0 : if ((*ifih->ifih_input)(ifp, m, ifih->ifih_cookie))
917 : break;
918 : }
919 0 : SRPL_LEAVE(&sr);
920 :
921 0 : if (ifih == NULL)
922 0 : m_freem(m);
923 : }
924 0 : splx(s);
925 0 : NET_RUNLOCK();
926 0 : }
927 :
928 : void
929 0 : if_netisr(void *unused)
930 : {
931 : int n, t = 0;
932 :
933 0 : NET_LOCK();
934 :
935 0 : while ((n = netisr) != 0) {
936 : /* Like sched_pause() but with a rwlock dance. */
937 0 : if (curcpu()->ci_schedstate.spc_schedflags & SPCF_SHOULDYIELD) {
938 0 : NET_UNLOCK();
939 0 : yield();
940 0 : NET_LOCK();
941 0 : }
942 :
943 0 : atomic_clearbits_int(&netisr, n);
944 :
945 : #if NETHER > 0
946 0 : if (n & (1 << NETISR_ARP)) {
947 0 : KERNEL_LOCK();
948 0 : arpintr();
949 0 : KERNEL_UNLOCK();
950 0 : }
951 : #endif
952 0 : if (n & (1 << NETISR_IP))
953 0 : ipintr();
954 : #ifdef INET6
955 0 : if (n & (1 << NETISR_IPV6))
956 0 : ip6intr();
957 : #endif
958 : #if NPPP > 0
959 0 : if (n & (1 << NETISR_PPP)) {
960 0 : KERNEL_LOCK();
961 0 : pppintr();
962 0 : KERNEL_UNLOCK();
963 0 : }
964 : #endif
965 : #if NBRIDGE > 0
966 0 : if (n & (1 << NETISR_BRIDGE)) {
967 0 : KERNEL_LOCK();
968 0 : bridgeintr();
969 0 : KERNEL_UNLOCK();
970 0 : }
971 : #endif
972 : #if NSWITCH > 0
973 0 : if (n & (1 << NETISR_SWITCH)) {
974 0 : KERNEL_LOCK();
975 0 : switchintr();
976 0 : KERNEL_UNLOCK();
977 0 : }
978 : #endif
979 : #if NPPPOE > 0
980 0 : if (n & (1 << NETISR_PPPOE)) {
981 0 : KERNEL_LOCK();
982 0 : pppoeintr();
983 0 : KERNEL_UNLOCK();
984 0 : }
985 : #endif
986 : #ifdef PIPEX
987 0 : if (n & (1 << NETISR_PIPEX)) {
988 0 : KERNEL_LOCK();
989 0 : pipexintr();
990 0 : KERNEL_UNLOCK();
991 0 : }
992 : #endif
993 0 : t |= n;
994 : }
995 :
996 : #if NPFSYNC > 0
997 0 : if (t & (1 << NETISR_PFSYNC)) {
998 0 : KERNEL_LOCK();
999 0 : pfsyncintr();
1000 0 : KERNEL_UNLOCK();
1001 0 : }
1002 : #endif
1003 :
1004 0 : NET_UNLOCK();
1005 0 : }
1006 :
1007 : void
1008 0 : if_deactivate(struct ifnet *ifp)
1009 : {
1010 0 : NET_LOCK();
1011 : /*
1012 : * Call detach hooks from head to tail. To make sure detach
1013 : * hooks are executed in the reverse order they were added, all
1014 : * the hooks have to be added to the head!
1015 : */
1016 0 : dohooks(ifp->if_detachhooks, HOOK_REMOVE | HOOK_FREE);
1017 :
1018 0 : NET_UNLOCK();
1019 0 : }
1020 :
1021 : /*
1022 : * Detach an interface from everything in the kernel. Also deallocate
1023 : * private resources.
1024 : */
1025 : void
1026 0 : if_detach(struct ifnet *ifp)
1027 : {
1028 : struct ifaddr *ifa;
1029 : struct ifg_list *ifg;
1030 : struct domain *dp;
1031 : int i, s;
1032 :
1033 : /* Undo pseudo-driver changes. */
1034 0 : if_deactivate(ifp);
1035 :
1036 0 : ifq_clr_oactive(&ifp->if_snd);
1037 :
1038 : /* Other CPUs must not have a reference before we start destroying. */
1039 0 : if_idxmap_remove(ifp);
1040 :
1041 : #if NBPFILTER > 0
1042 0 : bpfdetach(ifp);
1043 : #endif
1044 :
1045 0 : NET_LOCK();
1046 0 : s = splnet();
1047 0 : ifp->if_qstart = if_detached_qstart;
1048 0 : ifp->if_ioctl = if_detached_ioctl;
1049 0 : ifp->if_watchdog = NULL;
1050 :
1051 : /* Remove the watchdog timeout & task */
1052 0 : timeout_del(&ifp->if_slowtimo);
1053 0 : task_del(net_tq(ifp->if_index), &ifp->if_watchdogtask);
1054 :
1055 : /* Remove the link state task */
1056 0 : task_del(net_tq(ifp->if_index), &ifp->if_linkstatetask);
1057 :
1058 0 : rti_delete(ifp);
1059 : #if NETHER > 0 && defined(NFSCLIENT)
1060 0 : if (ifp->if_index == revarp_ifidx)
1061 0 : revarp_ifidx = 0;
1062 : #endif
1063 : #ifdef MROUTING
1064 0 : vif_delete(ifp);
1065 : #endif
1066 0 : in_ifdetach(ifp);
1067 : #ifdef INET6
1068 0 : in6_ifdetach(ifp);
1069 : #endif
1070 : #if NPF > 0
1071 0 : pfi_detach_ifnet(ifp);
1072 : #endif
1073 :
1074 : /* Remove the interface from the list of all interfaces. */
1075 0 : TAILQ_REMOVE(&ifnet, ifp, if_list);
1076 :
1077 0 : while ((ifg = TAILQ_FIRST(&ifp->if_groups)) != NULL)
1078 0 : if_delgroup(ifp, ifg->ifgl_group->ifg_group);
1079 :
1080 0 : if_free_sadl(ifp);
1081 :
1082 : /* We should not have any address left at this point. */
1083 0 : if (!TAILQ_EMPTY(&ifp->if_addrlist)) {
1084 : #ifdef DIAGNOSTIC
1085 0 : printf("%s: address list non empty\n", ifp->if_xname);
1086 : #endif
1087 0 : while ((ifa = TAILQ_FIRST(&ifp->if_addrlist)) != NULL) {
1088 0 : ifa_del(ifp, ifa);
1089 0 : ifa->ifa_ifp = NULL;
1090 0 : ifafree(ifa);
1091 : }
1092 : }
1093 :
1094 0 : free(ifp->if_addrhooks, M_TEMP, 0);
1095 0 : free(ifp->if_linkstatehooks, M_TEMP, 0);
1096 0 : free(ifp->if_detachhooks, M_TEMP, 0);
1097 :
1098 0 : for (i = 0; (dp = domains[i]) != NULL; i++) {
1099 0 : if (dp->dom_ifdetach && ifp->if_afdata[dp->dom_family])
1100 0 : (*dp->dom_ifdetach)(ifp,
1101 : ifp->if_afdata[dp->dom_family]);
1102 : }
1103 :
1104 : /* Announce that the interface is gone. */
1105 0 : rtm_ifannounce(ifp, IFAN_DEPARTURE);
1106 0 : splx(s);
1107 0 : NET_UNLOCK();
1108 :
1109 0 : for (i = 0; i < ifp->if_nifqs; i++)
1110 0 : ifq_destroy(ifp->if_ifqs[i]);
1111 0 : if (ifp->if_ifqs != ifp->if_snd.ifq_ifqs) {
1112 0 : for (i = 1; i < ifp->if_nifqs; i++) {
1113 0 : free(ifp->if_ifqs[i], M_DEVBUF,
1114 : sizeof(struct ifqueue));
1115 : }
1116 0 : free(ifp->if_ifqs, M_DEVBUF,
1117 0 : sizeof(struct ifqueue *) * ifp->if_nifqs);
1118 0 : }
1119 :
1120 0 : for (i = 0; i < ifp->if_niqs; i++)
1121 0 : ifiq_destroy(ifp->if_iqs[i]);
1122 0 : if (ifp->if_iqs != ifp->if_rcv.ifiq_ifiqs) {
1123 0 : for (i = 1; i < ifp->if_niqs; i++) {
1124 0 : free(ifp->if_iqs[i], M_DEVBUF,
1125 : sizeof(struct ifiqueue));
1126 : }
1127 0 : free(ifp->if_iqs, M_DEVBUF,
1128 0 : sizeof(struct ifiqueue *) * ifp->if_niqs);
1129 0 : }
1130 0 : }
1131 :
1132 : /*
1133 : * Returns true if ``ifp0'' is connected to the interface with index ``ifidx''.
1134 : */
1135 : int
1136 0 : if_isconnected(const struct ifnet *ifp0, unsigned int ifidx)
1137 : {
1138 : struct ifnet *ifp;
1139 : int connected = 0;
1140 :
1141 0 : ifp = if_get(ifidx);
1142 0 : if (ifp == NULL)
1143 0 : return (0);
1144 :
1145 0 : if (ifp0->if_index == ifp->if_index)
1146 0 : connected = 1;
1147 :
1148 : #if NBRIDGE > 0
1149 0 : if (SAME_BRIDGE(ifp0->if_bridgeport, ifp->if_bridgeport))
1150 0 : connected = 1;
1151 : #endif
1152 : #if NCARP > 0
1153 0 : if ((ifp0->if_type == IFT_CARP && ifp0->if_carpdev == ifp) ||
1154 0 : (ifp->if_type == IFT_CARP && ifp->if_carpdev == ifp0))
1155 0 : connected = 1;
1156 : #endif
1157 :
1158 0 : if_put(ifp);
1159 0 : return (connected);
1160 0 : }
1161 :
1162 : /*
1163 : * Create a clone network interface.
1164 : */
1165 : int
1166 0 : if_clone_create(const char *name, int rdomain)
1167 : {
1168 : struct if_clone *ifc;
1169 : struct ifnet *ifp;
1170 0 : int unit, ret;
1171 :
1172 0 : NET_ASSERT_LOCKED();
1173 :
1174 0 : ifc = if_clone_lookup(name, &unit);
1175 0 : if (ifc == NULL)
1176 0 : return (EINVAL);
1177 :
1178 0 : if (ifunit(name) != NULL)
1179 0 : return (EEXIST);
1180 :
1181 : /* XXXSMP breaks atomicity */
1182 0 : NET_UNLOCK();
1183 0 : ret = (*ifc->ifc_create)(ifc, unit);
1184 0 : NET_LOCK();
1185 :
1186 0 : if (ret != 0 || (ifp = ifunit(name)) == NULL)
1187 0 : return (ret);
1188 :
1189 0 : if_addgroup(ifp, ifc->ifc_name);
1190 0 : if (rdomain != 0)
1191 0 : if_setrdomain(ifp, rdomain);
1192 :
1193 0 : return (ret);
1194 0 : }
1195 :
1196 : /*
1197 : * Destroy a clone network interface.
1198 : */
1199 : int
1200 0 : if_clone_destroy(const char *name)
1201 : {
1202 : struct if_clone *ifc;
1203 : struct ifnet *ifp;
1204 : int ret;
1205 :
1206 0 : NET_ASSERT_LOCKED();
1207 :
1208 0 : ifc = if_clone_lookup(name, NULL);
1209 0 : if (ifc == NULL)
1210 0 : return (EINVAL);
1211 :
1212 0 : ifp = ifunit(name);
1213 0 : if (ifp == NULL)
1214 0 : return (ENXIO);
1215 :
1216 0 : if (ifc->ifc_destroy == NULL)
1217 0 : return (EOPNOTSUPP);
1218 :
1219 0 : if (ifp->if_flags & IFF_UP) {
1220 : int s;
1221 0 : s = splnet();
1222 0 : if_down(ifp);
1223 0 : splx(s);
1224 0 : }
1225 :
1226 : /* XXXSMP breaks atomicity */
1227 0 : NET_UNLOCK();
1228 0 : ret = (*ifc->ifc_destroy)(ifp);
1229 0 : NET_LOCK();
1230 :
1231 0 : return (ret);
1232 0 : }
1233 :
1234 : /*
1235 : * Look up a network interface cloner.
1236 : */
1237 : struct if_clone *
1238 0 : if_clone_lookup(const char *name, int *unitp)
1239 : {
1240 : struct if_clone *ifc;
1241 : const char *cp;
1242 : int unit;
1243 :
1244 : /* separate interface name from unit */
1245 0 : for (cp = name;
1246 0 : cp - name < IFNAMSIZ && *cp && (*cp < '0' || *cp > '9');
1247 0 : cp++)
1248 : continue;
1249 :
1250 0 : if (cp == name || cp - name == IFNAMSIZ || !*cp)
1251 0 : return (NULL); /* No name or unit number */
1252 :
1253 0 : if (cp - name < IFNAMSIZ-1 && *cp == '0' && cp[1] != '\0')
1254 0 : return (NULL); /* unit number 0 padded */
1255 :
1256 0 : LIST_FOREACH(ifc, &if_cloners, ifc_list) {
1257 0 : if (strlen(ifc->ifc_name) == cp - name &&
1258 0 : !strncmp(name, ifc->ifc_name, cp - name))
1259 : break;
1260 : }
1261 :
1262 0 : if (ifc == NULL)
1263 0 : return (NULL);
1264 :
1265 : unit = 0;
1266 0 : while (cp - name < IFNAMSIZ && *cp) {
1267 0 : if (*cp < '0' || *cp > '9' ||
1268 0 : unit > (INT_MAX - (*cp - '0')) / 10) {
1269 : /* Bogus unit number. */
1270 0 : return (NULL);
1271 : }
1272 0 : unit = (unit * 10) + (*cp++ - '0');
1273 : }
1274 :
1275 0 : if (unitp != NULL)
1276 0 : *unitp = unit;
1277 0 : return (ifc);
1278 0 : }
1279 :
1280 : /*
1281 : * Register a network interface cloner.
1282 : */
1283 : void
1284 0 : if_clone_attach(struct if_clone *ifc)
1285 : {
1286 : /*
1287 : * we are called at kernel boot by main(), when pseudo devices are
1288 : * being attached. The main() is the only guy which may alter the
1289 : * if_cloners. While system is running and main() is done with
1290 : * initialization, the if_cloners becomes immutable.
1291 : */
1292 0 : KASSERT(pdevinit_done == 0);
1293 0 : LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
1294 0 : if_cloners_count++;
1295 0 : }
1296 :
1297 : /*
1298 : * Provide list of interface cloners to userspace.
1299 : */
1300 : int
1301 0 : if_clone_list(struct if_clonereq *ifcr)
1302 : {
1303 0 : char outbuf[IFNAMSIZ], *dst;
1304 : struct if_clone *ifc;
1305 : int count, error = 0;
1306 :
1307 0 : if ((dst = ifcr->ifcr_buffer) == NULL) {
1308 : /* Just asking how many there are. */
1309 0 : ifcr->ifcr_total = if_cloners_count;
1310 0 : return (0);
1311 : }
1312 :
1313 0 : if (ifcr->ifcr_count < 0)
1314 0 : return (EINVAL);
1315 :
1316 0 : ifcr->ifcr_total = if_cloners_count;
1317 0 : count = MIN(if_cloners_count, ifcr->ifcr_count);
1318 :
1319 0 : LIST_FOREACH(ifc, &if_cloners, ifc_list) {
1320 0 : if (count == 0)
1321 : break;
1322 0 : bzero(outbuf, sizeof outbuf);
1323 0 : strlcpy(outbuf, ifc->ifc_name, IFNAMSIZ);
1324 0 : error = copyout(outbuf, dst, IFNAMSIZ);
1325 0 : if (error)
1326 : break;
1327 0 : count--;
1328 0 : dst += IFNAMSIZ;
1329 : }
1330 :
1331 0 : return (error);
1332 0 : }
1333 :
1334 : /*
1335 : * set queue congestion marker
1336 : */
1337 : void
1338 0 : if_congestion(void)
1339 : {
1340 : extern int ticks;
1341 :
1342 0 : ifq_congestion = ticks;
1343 0 : }
1344 :
1345 : int
1346 0 : if_congested(void)
1347 : {
1348 : extern int ticks;
1349 : int diff;
1350 :
1351 0 : diff = ticks - ifq_congestion;
1352 0 : if (diff < 0) {
1353 0 : ifq_congestion = ticks - hz;
1354 0 : return (0);
1355 : }
1356 :
1357 0 : return (diff <= (hz / 100));
1358 0 : }
1359 :
1360 : #define equal(a1, a2) \
1361 : (bcmp((caddr_t)(a1), (caddr_t)(a2), \
1362 : (a1)->sa_len) == 0)
1363 :
1364 : /*
1365 : * Locate an interface based on a complete address.
1366 : */
1367 : struct ifaddr *
1368 0 : ifa_ifwithaddr(struct sockaddr *addr, u_int rtableid)
1369 : {
1370 : struct ifnet *ifp;
1371 : struct ifaddr *ifa;
1372 : u_int rdomain;
1373 :
1374 0 : rdomain = rtable_l2(rtableid);
1375 0 : KERNEL_LOCK();
1376 0 : TAILQ_FOREACH(ifp, &ifnet, if_list) {
1377 0 : if (ifp->if_rdomain != rdomain)
1378 : continue;
1379 :
1380 0 : TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1381 0 : if (ifa->ifa_addr->sa_family != addr->sa_family)
1382 : continue;
1383 :
1384 0 : if (equal(addr, ifa->ifa_addr)) {
1385 0 : KERNEL_UNLOCK();
1386 0 : return (ifa);
1387 : }
1388 : }
1389 : }
1390 0 : KERNEL_UNLOCK();
1391 0 : return (NULL);
1392 0 : }
1393 :
1394 : /*
1395 : * Locate the point to point interface with a given destination address.
1396 : */
1397 : struct ifaddr *
1398 0 : ifa_ifwithdstaddr(struct sockaddr *addr, u_int rdomain)
1399 : {
1400 : struct ifnet *ifp;
1401 : struct ifaddr *ifa;
1402 :
1403 0 : rdomain = rtable_l2(rdomain);
1404 0 : KERNEL_LOCK();
1405 0 : TAILQ_FOREACH(ifp, &ifnet, if_list) {
1406 0 : if (ifp->if_rdomain != rdomain)
1407 : continue;
1408 0 : if (ifp->if_flags & IFF_POINTOPOINT) {
1409 0 : TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1410 0 : if (ifa->ifa_addr->sa_family !=
1411 0 : addr->sa_family || ifa->ifa_dstaddr == NULL)
1412 : continue;
1413 0 : if (equal(addr, ifa->ifa_dstaddr)) {
1414 0 : KERNEL_UNLOCK();
1415 0 : return (ifa);
1416 : }
1417 : }
1418 : }
1419 : }
1420 0 : KERNEL_UNLOCK();
1421 0 : return (NULL);
1422 0 : }
1423 :
1424 : /*
1425 : * Find an interface address specific to an interface best matching
1426 : * a given address.
1427 : */
1428 : struct ifaddr *
1429 0 : ifaof_ifpforaddr(struct sockaddr *addr, struct ifnet *ifp)
1430 : {
1431 : struct ifaddr *ifa;
1432 : char *cp, *cp2, *cp3;
1433 : char *cplim;
1434 : struct ifaddr *ifa_maybe = NULL;
1435 0 : u_int af = addr->sa_family;
1436 :
1437 0 : if (af >= AF_MAX)
1438 0 : return (NULL);
1439 0 : TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1440 0 : if (ifa->ifa_addr->sa_family != af)
1441 : continue;
1442 0 : if (ifa_maybe == NULL)
1443 0 : ifa_maybe = ifa;
1444 0 : if (ifa->ifa_netmask == 0 || ifp->if_flags & IFF_POINTOPOINT) {
1445 0 : if (equal(addr, ifa->ifa_addr) ||
1446 0 : (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
1447 0 : return (ifa);
1448 : continue;
1449 : }
1450 0 : cp = addr->sa_data;
1451 0 : cp2 = ifa->ifa_addr->sa_data;
1452 0 : cp3 = ifa->ifa_netmask->sa_data;
1453 0 : cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
1454 0 : for (; cp3 < cplim; cp3++)
1455 0 : if ((*cp++ ^ *cp2++) & *cp3)
1456 : break;
1457 0 : if (cp3 == cplim)
1458 0 : return (ifa);
1459 : }
1460 0 : return (ifa_maybe);
1461 0 : }
1462 :
1463 : void
1464 0 : if_rtrequest_dummy(struct ifnet *ifp, int req, struct rtentry *rt)
1465 : {
1466 0 : }
1467 :
1468 : /*
1469 : * Default action when installing a local route on a point-to-point
1470 : * interface.
1471 : */
1472 : void
1473 0 : p2p_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt)
1474 : {
1475 : struct ifnet *lo0ifp;
1476 : struct ifaddr *ifa, *lo0ifa;
1477 :
1478 0 : switch (req) {
1479 : case RTM_ADD:
1480 0 : if (!ISSET(rt->rt_flags, RTF_LOCAL))
1481 : break;
1482 :
1483 0 : TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1484 0 : if (memcmp(rt_key(rt), ifa->ifa_addr,
1485 0 : rt_key(rt)->sa_len) == 0)
1486 : break;
1487 : }
1488 :
1489 0 : if (ifa == NULL)
1490 : break;
1491 :
1492 0 : KASSERT(ifa == rt->rt_ifa);
1493 :
1494 0 : lo0ifp = if_get(rtable_loindex(ifp->if_rdomain));
1495 0 : KASSERT(lo0ifp != NULL);
1496 0 : TAILQ_FOREACH(lo0ifa, &lo0ifp->if_addrlist, ifa_list) {
1497 0 : if (lo0ifa->ifa_addr->sa_family ==
1498 0 : ifa->ifa_addr->sa_family)
1499 : break;
1500 : }
1501 0 : if_put(lo0ifp);
1502 :
1503 0 : if (lo0ifa == NULL)
1504 : break;
1505 :
1506 0 : rt->rt_flags &= ~RTF_LLINFO;
1507 0 : break;
1508 : case RTM_DELETE:
1509 : case RTM_RESOLVE:
1510 : default:
1511 : break;
1512 : }
1513 0 : }
1514 :
1515 :
1516 : /*
1517 : * Bring down all interfaces
1518 : */
1519 : void
1520 0 : if_downall(void)
1521 : {
1522 0 : struct ifreq ifrq; /* XXX only partly built */
1523 : struct ifnet *ifp;
1524 :
1525 0 : NET_LOCK();
1526 0 : TAILQ_FOREACH(ifp, &ifnet, if_list) {
1527 0 : if ((ifp->if_flags & IFF_UP) == 0)
1528 : continue;
1529 0 : if_down(ifp);
1530 0 : ifrq.ifr_flags = ifp->if_flags;
1531 0 : (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifrq);
1532 0 : }
1533 0 : NET_UNLOCK();
1534 0 : }
1535 :
1536 : /*
1537 : * Mark an interface down and notify protocols of
1538 : * the transition.
1539 : */
1540 : void
1541 0 : if_down(struct ifnet *ifp)
1542 : {
1543 0 : NET_ASSERT_LOCKED();
1544 :
1545 0 : ifp->if_flags &= ~IFF_UP;
1546 0 : getmicrotime(&ifp->if_lastchange);
1547 0 : IFQ_PURGE(&ifp->if_snd);
1548 :
1549 0 : if_linkstate(ifp);
1550 0 : }
1551 :
1552 : /*
1553 : * Mark an interface up and notify protocols of
1554 : * the transition.
1555 : */
1556 : void
1557 0 : if_up(struct ifnet *ifp)
1558 : {
1559 0 : NET_ASSERT_LOCKED();
1560 :
1561 0 : ifp->if_flags |= IFF_UP;
1562 0 : getmicrotime(&ifp->if_lastchange);
1563 :
1564 : #ifdef INET6
1565 : /* Userland expects the kernel to set ::1 on default lo(4). */
1566 0 : if (ifp->if_index == rtable_loindex(ifp->if_rdomain))
1567 0 : in6_ifattach(ifp);
1568 : #endif
1569 :
1570 0 : if_linkstate(ifp);
1571 0 : }
1572 :
1573 : /*
1574 : * Notify userland, the routing table and hooks owner of
1575 : * a link-state transition.
1576 : */
1577 : void
1578 0 : if_linkstate_task(void *xifidx)
1579 : {
1580 0 : unsigned int ifidx = (unsigned long)xifidx;
1581 : struct ifnet *ifp;
1582 :
1583 0 : KERNEL_LOCK();
1584 0 : NET_LOCK();
1585 :
1586 0 : ifp = if_get(ifidx);
1587 0 : if (ifp != NULL)
1588 0 : if_linkstate(ifp);
1589 0 : if_put(ifp);
1590 :
1591 0 : NET_UNLOCK();
1592 0 : KERNEL_UNLOCK();
1593 0 : }
1594 :
1595 : void
1596 0 : if_linkstate(struct ifnet *ifp)
1597 : {
1598 0 : NET_ASSERT_LOCKED();
1599 :
1600 0 : rtm_ifchg(ifp);
1601 0 : rt_if_track(ifp);
1602 0 : dohooks(ifp->if_linkstatehooks, 0);
1603 0 : }
1604 :
1605 : /*
1606 : * Schedule a link state change task.
1607 : */
1608 : void
1609 0 : if_link_state_change(struct ifnet *ifp)
1610 : {
1611 0 : task_add(net_tq(ifp->if_index), &ifp->if_linkstatetask);
1612 0 : }
1613 :
1614 : /*
1615 : * Handle interface watchdog timer routine. Called
1616 : * from softclock, we decrement timer (if set) and
1617 : * call the appropriate interface routine on expiration.
1618 : */
1619 : void
1620 0 : if_slowtimo(void *arg)
1621 : {
1622 0 : struct ifnet *ifp = arg;
1623 0 : int s = splnet();
1624 :
1625 0 : if (ifp->if_watchdog) {
1626 0 : if (ifp->if_timer > 0 && --ifp->if_timer == 0)
1627 0 : task_add(net_tq(ifp->if_index), &ifp->if_watchdogtask);
1628 0 : timeout_add(&ifp->if_slowtimo, hz / IFNET_SLOWHZ);
1629 0 : }
1630 0 : splx(s);
1631 0 : }
1632 :
1633 : void
1634 0 : if_watchdog_task(void *xifidx)
1635 : {
1636 0 : unsigned int ifidx = (unsigned long)xifidx;
1637 : struct ifnet *ifp;
1638 : int s;
1639 :
1640 0 : ifp = if_get(ifidx);
1641 0 : if (ifp == NULL)
1642 0 : return;
1643 :
1644 0 : KERNEL_LOCK();
1645 0 : s = splnet();
1646 0 : if (ifp->if_watchdog)
1647 0 : (*ifp->if_watchdog)(ifp);
1648 0 : splx(s);
1649 0 : KERNEL_UNLOCK();
1650 :
1651 0 : if_put(ifp);
1652 0 : }
1653 :
1654 : /*
1655 : * Map interface name to interface structure pointer.
1656 : */
1657 : struct ifnet *
1658 0 : ifunit(const char *name)
1659 : {
1660 : struct ifnet *ifp;
1661 :
1662 0 : TAILQ_FOREACH(ifp, &ifnet, if_list) {
1663 0 : if (strcmp(ifp->if_xname, name) == 0)
1664 0 : return (ifp);
1665 : }
1666 0 : return (NULL);
1667 0 : }
1668 :
1669 : /*
1670 : * Map interface index to interface structure pointer.
1671 : */
1672 : struct ifnet *
1673 0 : if_get(unsigned int index)
1674 : {
1675 0 : struct srp_ref sr;
1676 : struct if_map *if_map;
1677 : struct srp *map;
1678 : struct ifnet *ifp = NULL;
1679 :
1680 0 : if_map = srp_enter(&sr, &if_idxmap.map);
1681 0 : if (index < if_map->limit) {
1682 0 : map = (struct srp *)(if_map + 1);
1683 :
1684 0 : ifp = srp_follow(&sr, &map[index]);
1685 0 : if (ifp != NULL) {
1686 0 : KASSERT(ifp->if_index == index);
1687 0 : if_ref(ifp);
1688 0 : }
1689 : }
1690 0 : srp_leave(&sr);
1691 :
1692 0 : return (ifp);
1693 0 : }
1694 :
1695 : struct ifnet *
1696 0 : if_ref(struct ifnet *ifp)
1697 : {
1698 0 : refcnt_take(&ifp->if_refcnt);
1699 :
1700 0 : return (ifp);
1701 : }
1702 :
1703 : void
1704 0 : if_put(struct ifnet *ifp)
1705 : {
1706 0 : if (ifp == NULL)
1707 : return;
1708 :
1709 0 : refcnt_rele_wake(&ifp->if_refcnt);
1710 0 : }
1711 :
1712 : int
1713 0 : if_setlladdr(struct ifnet *ifp, const uint8_t *lladdr)
1714 : {
1715 0 : if (ifp->if_sadl == NULL)
1716 0 : return (EINVAL);
1717 :
1718 0 : memcpy(((struct arpcom *)ifp)->ac_enaddr, lladdr, ETHER_ADDR_LEN);
1719 0 : memcpy(LLADDR(ifp->if_sadl), lladdr, ETHER_ADDR_LEN);
1720 :
1721 0 : return (0);
1722 0 : }
1723 :
1724 : int
1725 0 : if_createrdomain(int rdomain, struct ifnet *ifp)
1726 : {
1727 : int error;
1728 : struct ifnet *loifp;
1729 0 : char loifname[IFNAMSIZ];
1730 : unsigned int unit = rdomain;
1731 :
1732 0 : if (!rtable_exists(rdomain) && (error = rtable_add(rdomain)) != 0)
1733 0 : return (error);
1734 0 : if (!rtable_empty(rdomain))
1735 0 : return (EEXIST);
1736 :
1737 : /* Create rdomain including its loopback if with unit == rdomain */
1738 0 : snprintf(loifname, sizeof(loifname), "lo%u", unit);
1739 0 : error = if_clone_create(loifname, 0);
1740 0 : if ((loifp = ifunit(loifname)) == NULL)
1741 0 : return (ENXIO);
1742 0 : if (error && (ifp != loifp || error != EEXIST))
1743 0 : return (error);
1744 :
1745 0 : rtable_l2set(rdomain, rdomain, loifp->if_index);
1746 0 : loifp->if_rdomain = rdomain;
1747 :
1748 0 : return (0);
1749 0 : }
1750 :
1751 : int
1752 0 : if_setrdomain(struct ifnet *ifp, int rdomain)
1753 : {
1754 0 : struct ifreq ifr;
1755 : int error, up = 0, s;
1756 :
1757 0 : if (rdomain < 0 || rdomain > RT_TABLEID_MAX)
1758 0 : return (EINVAL);
1759 :
1760 0 : if (rdomain != ifp->if_rdomain &&
1761 0 : (ifp->if_flags & IFF_LOOPBACK) &&
1762 0 : (ifp->if_index == rtable_loindex(ifp->if_rdomain)))
1763 0 : return (EPERM);
1764 :
1765 0 : if (!rtable_exists(rdomain))
1766 0 : return (ESRCH);
1767 :
1768 : /* make sure that the routing table is a real rdomain */
1769 0 : if (rdomain != rtable_l2(rdomain))
1770 0 : return (EINVAL);
1771 :
1772 0 : if (rdomain != ifp->if_rdomain) {
1773 0 : s = splnet();
1774 : /*
1775 : * We are tearing down the world.
1776 : * Take down the IF so:
1777 : * 1. everything that cares gets a message
1778 : * 2. the automagic IPv6 bits are recreated
1779 : */
1780 0 : if (ifp->if_flags & IFF_UP) {
1781 : up = 1;
1782 0 : if_down(ifp);
1783 0 : }
1784 0 : rti_delete(ifp);
1785 : #ifdef MROUTING
1786 0 : vif_delete(ifp);
1787 : #endif
1788 0 : in_ifdetach(ifp);
1789 : #ifdef INET6
1790 0 : in6_ifdetach(ifp);
1791 : #endif
1792 0 : splx(s);
1793 0 : }
1794 :
1795 : /* Let devices like enc(4) or mpe(4) know about the change */
1796 0 : ifr.ifr_rdomainid = rdomain;
1797 0 : if ((error = (*ifp->if_ioctl)(ifp, SIOCSIFRDOMAIN,
1798 0 : (caddr_t)&ifr)) != ENOTTY)
1799 0 : return (error);
1800 : error = 0;
1801 :
1802 : /* Add interface to the specified rdomain */
1803 0 : ifp->if_rdomain = rdomain;
1804 :
1805 : /* If we took down the IF, bring it back */
1806 0 : if (up) {
1807 0 : s = splnet();
1808 0 : if_up(ifp);
1809 0 : splx(s);
1810 0 : }
1811 :
1812 0 : return (0);
1813 0 : }
1814 :
1815 : /*
1816 : * Interface ioctls.
1817 : */
1818 : int
1819 0 : ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
1820 : {
1821 : struct ifnet *ifp;
1822 0 : struct ifreq *ifr = (struct ifreq *)data;
1823 0 : struct ifgroupreq *ifgr = (struct ifgroupreq *)data;
1824 0 : struct if_afreq *ifar = (struct if_afreq *)data;
1825 0 : char ifdescrbuf[IFDESCRSIZE];
1826 0 : char ifrtlabelbuf[RTLABEL_LEN];
1827 : int s, error = 0, oif_xflags;
1828 0 : size_t bytesdone;
1829 : unsigned short oif_flags;
1830 :
1831 0 : switch (cmd) {
1832 : case SIOCIFCREATE:
1833 0 : if ((error = suser(p)) != 0)
1834 0 : return (error);
1835 0 : NET_LOCK();
1836 0 : error = if_clone_create(ifr->ifr_name, 0);
1837 0 : NET_UNLOCK();
1838 0 : return (error);
1839 : case SIOCIFDESTROY:
1840 0 : if ((error = suser(p)) != 0)
1841 0 : return (error);
1842 0 : NET_LOCK();
1843 0 : error = if_clone_destroy(ifr->ifr_name);
1844 0 : NET_UNLOCK();
1845 0 : return (error);
1846 : case SIOCSIFGATTR:
1847 0 : if ((error = suser(p)) != 0)
1848 0 : return (error);
1849 0 : NET_LOCK();
1850 0 : error = if_setgroupattribs(data);
1851 0 : NET_UNLOCK();
1852 0 : return (error);
1853 : case SIOCGIFCONF:
1854 : case SIOCIFGCLONERS:
1855 : case SIOCGIFGMEMB:
1856 : case SIOCGIFGATTR:
1857 : case SIOCGIFGLIST:
1858 : case SIOCGIFFLAGS:
1859 : case SIOCGIFXFLAGS:
1860 : case SIOCGIFMETRIC:
1861 : case SIOCGIFMTU:
1862 : case SIOCGIFHARDMTU:
1863 : case SIOCGIFDATA:
1864 : case SIOCGIFDESCR:
1865 : case SIOCGIFRTLABEL:
1866 : case SIOCGIFPRIORITY:
1867 : case SIOCGIFRDOMAIN:
1868 : case SIOCGIFGROUP:
1869 : case SIOCGIFLLPRIO:
1870 0 : return (ifioctl_get(cmd, data));
1871 : }
1872 :
1873 0 : ifp = ifunit(ifr->ifr_name);
1874 0 : if (ifp == NULL)
1875 0 : return (ENXIO);
1876 0 : oif_flags = ifp->if_flags;
1877 0 : oif_xflags = ifp->if_xflags;
1878 :
1879 0 : switch (cmd) {
1880 : case SIOCIFAFATTACH:
1881 : case SIOCIFAFDETACH:
1882 0 : if ((error = suser(p)) != 0)
1883 : break;
1884 0 : NET_LOCK();
1885 0 : switch (ifar->ifar_af) {
1886 : case AF_INET:
1887 : /* attach is a noop for AF_INET */
1888 0 : if (cmd == SIOCIFAFDETACH)
1889 0 : in_ifdetach(ifp);
1890 : break;
1891 : #ifdef INET6
1892 : case AF_INET6:
1893 0 : if (cmd == SIOCIFAFATTACH)
1894 0 : error = in6_ifattach(ifp);
1895 : else
1896 0 : in6_ifdetach(ifp);
1897 : break;
1898 : #endif /* INET6 */
1899 : default:
1900 : error = EAFNOSUPPORT;
1901 0 : }
1902 0 : NET_UNLOCK();
1903 0 : break;
1904 :
1905 : case SIOCSIFFLAGS:
1906 0 : if ((error = suser(p)) != 0)
1907 : break;
1908 :
1909 0 : NET_LOCK();
1910 0 : ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
1911 0 : (ifr->ifr_flags & ~IFF_CANTCHANGE);
1912 :
1913 0 : error = (*ifp->if_ioctl)(ifp, cmd, data);
1914 0 : if (error != 0) {
1915 0 : ifp->if_flags = oif_flags;
1916 0 : } else if (ISSET(oif_flags ^ ifp->if_flags, IFF_UP)) {
1917 0 : s = splnet();
1918 0 : if (ISSET(ifp->if_flags, IFF_UP))
1919 0 : if_up(ifp);
1920 : else
1921 0 : if_down(ifp);
1922 0 : splx(s);
1923 0 : }
1924 0 : NET_UNLOCK();
1925 0 : break;
1926 :
1927 : case SIOCSIFXFLAGS:
1928 0 : if ((error = suser(p)) != 0)
1929 : break;
1930 :
1931 0 : NET_LOCK();
1932 : #ifdef INET6
1933 0 : if (ISSET(ifr->ifr_flags, IFXF_AUTOCONF6)) {
1934 0 : error = in6_ifattach(ifp);
1935 0 : if (error != 0) {
1936 0 : NET_UNLOCK();
1937 0 : break;
1938 : }
1939 : }
1940 :
1941 0 : if (ISSET(ifr->ifr_flags, IFXF_INET6_NOSOII) &&
1942 0 : !ISSET(ifp->if_xflags, IFXF_INET6_NOSOII)) {
1943 0 : ifp->if_xflags |= IFXF_INET6_NOSOII;
1944 0 : in6_soiiupdate(ifp);
1945 0 : }
1946 :
1947 0 : if (!ISSET(ifr->ifr_flags, IFXF_INET6_NOSOII) &&
1948 0 : ISSET(ifp->if_xflags, IFXF_INET6_NOSOII)) {
1949 0 : ifp->if_xflags &= ~IFXF_INET6_NOSOII;
1950 0 : in6_soiiupdate(ifp);
1951 0 : }
1952 :
1953 : #endif /* INET6 */
1954 :
1955 : #ifdef MPLS
1956 0 : if (ISSET(ifr->ifr_flags, IFXF_MPLS) &&
1957 0 : !ISSET(ifp->if_xflags, IFXF_MPLS)) {
1958 0 : s = splnet();
1959 0 : ifp->if_xflags |= IFXF_MPLS;
1960 0 : ifp->if_ll_output = ifp->if_output;
1961 0 : ifp->if_output = mpls_output;
1962 0 : splx(s);
1963 0 : }
1964 0 : if (ISSET(ifp->if_xflags, IFXF_MPLS) &&
1965 0 : !ISSET(ifr->ifr_flags, IFXF_MPLS)) {
1966 0 : s = splnet();
1967 0 : ifp->if_xflags &= ~IFXF_MPLS;
1968 0 : ifp->if_output = ifp->if_ll_output;
1969 0 : ifp->if_ll_output = NULL;
1970 0 : splx(s);
1971 0 : }
1972 : #endif /* MPLS */
1973 :
1974 : #ifndef SMALL_KERNEL
1975 0 : if (ifp->if_capabilities & IFCAP_WOL) {
1976 0 : if (ISSET(ifr->ifr_flags, IFXF_WOL) &&
1977 0 : !ISSET(ifp->if_xflags, IFXF_WOL)) {
1978 0 : s = splnet();
1979 0 : ifp->if_xflags |= IFXF_WOL;
1980 0 : error = ifp->if_wol(ifp, 1);
1981 0 : splx(s);
1982 0 : }
1983 0 : if (ISSET(ifp->if_xflags, IFXF_WOL) &&
1984 0 : !ISSET(ifr->ifr_flags, IFXF_WOL)) {
1985 0 : s = splnet();
1986 0 : ifp->if_xflags &= ~IFXF_WOL;
1987 0 : error = ifp->if_wol(ifp, 0);
1988 0 : splx(s);
1989 0 : }
1990 0 : } else if (ISSET(ifr->ifr_flags, IFXF_WOL)) {
1991 0 : ifr->ifr_flags &= ~IFXF_WOL;
1992 : error = ENOTSUP;
1993 0 : }
1994 : #endif
1995 :
1996 0 : if (error == 0)
1997 0 : ifp->if_xflags = (ifp->if_xflags & IFXF_CANTCHANGE) |
1998 0 : (ifr->ifr_flags & ~IFXF_CANTCHANGE);
1999 0 : NET_UNLOCK();
2000 0 : break;
2001 :
2002 : case SIOCSIFMETRIC:
2003 0 : if ((error = suser(p)) != 0)
2004 : break;
2005 0 : NET_LOCK();
2006 0 : ifp->if_metric = ifr->ifr_metric;
2007 0 : NET_UNLOCK();
2008 0 : break;
2009 :
2010 : case SIOCSIFMTU:
2011 0 : if ((error = suser(p)) != 0)
2012 : break;
2013 0 : NET_LOCK();
2014 0 : error = (*ifp->if_ioctl)(ifp, cmd, data);
2015 0 : NET_UNLOCK();
2016 0 : if (!error)
2017 0 : rtm_ifchg(ifp);
2018 : break;
2019 :
2020 : case SIOCSIFDESCR:
2021 0 : if ((error = suser(p)) != 0)
2022 : break;
2023 0 : error = copyinstr(ifr->ifr_data, ifdescrbuf,
2024 : IFDESCRSIZE, &bytesdone);
2025 0 : if (error == 0) {
2026 0 : (void)memset(ifp->if_description, 0, IFDESCRSIZE);
2027 0 : strlcpy(ifp->if_description, ifdescrbuf, IFDESCRSIZE);
2028 0 : }
2029 : break;
2030 :
2031 : case SIOCSIFRTLABEL:
2032 0 : if ((error = suser(p)) != 0)
2033 : break;
2034 0 : error = copyinstr(ifr->ifr_data, ifrtlabelbuf,
2035 : RTLABEL_LEN, &bytesdone);
2036 0 : if (error == 0) {
2037 0 : rtlabel_unref(ifp->if_rtlabelid);
2038 0 : ifp->if_rtlabelid = rtlabel_name2id(ifrtlabelbuf);
2039 0 : }
2040 : break;
2041 :
2042 : case SIOCSIFPRIORITY:
2043 0 : if ((error = suser(p)) != 0)
2044 : break;
2045 0 : if (ifr->ifr_metric < 0 || ifr->ifr_metric > 15) {
2046 : error = EINVAL;
2047 0 : break;
2048 : }
2049 0 : ifp->if_priority = ifr->ifr_metric;
2050 0 : break;
2051 :
2052 : case SIOCSIFRDOMAIN:
2053 0 : if ((error = suser(p)) != 0)
2054 : break;
2055 0 : NET_LOCK();
2056 0 : error = if_createrdomain(ifr->ifr_rdomainid, ifp);
2057 0 : if (!error || error == EEXIST)
2058 0 : error = if_setrdomain(ifp, ifr->ifr_rdomainid);
2059 0 : NET_UNLOCK();
2060 0 : break;
2061 :
2062 : case SIOCAIFGROUP:
2063 0 : if ((error = suser(p)))
2064 : break;
2065 0 : NET_LOCK();
2066 0 : error = if_addgroup(ifp, ifgr->ifgr_group);
2067 0 : if (error == 0) {
2068 0 : error = (*ifp->if_ioctl)(ifp, cmd, data);
2069 0 : if (error == ENOTTY)
2070 : error = 0;
2071 0 : }
2072 0 : NET_UNLOCK();
2073 0 : break;
2074 :
2075 : case SIOCDIFGROUP:
2076 0 : if ((error = suser(p)))
2077 : break;
2078 0 : NET_LOCK();
2079 0 : error = (*ifp->if_ioctl)(ifp, cmd, data);
2080 0 : if (error == ENOTTY)
2081 : error = 0;
2082 0 : if (error == 0)
2083 0 : error = if_delgroup(ifp, ifgr->ifgr_group);
2084 0 : NET_UNLOCK();
2085 0 : break;
2086 :
2087 : case SIOCSIFLLADDR:
2088 0 : if ((error = suser(p)))
2089 : break;
2090 0 : if ((ifp->if_sadl == NULL) ||
2091 0 : (ifr->ifr_addr.sa_len != ETHER_ADDR_LEN) ||
2092 0 : (ETHER_IS_MULTICAST(ifr->ifr_addr.sa_data))) {
2093 : error = EINVAL;
2094 0 : break;
2095 : }
2096 0 : NET_LOCK();
2097 0 : switch (ifp->if_type) {
2098 : case IFT_ETHER:
2099 : case IFT_CARP:
2100 : case IFT_XETHER:
2101 : case IFT_ISO88025:
2102 0 : error = (*ifp->if_ioctl)(ifp, cmd, data);
2103 0 : if (error == ENOTTY)
2104 : error = 0;
2105 0 : if (error == 0)
2106 0 : error = if_setlladdr(ifp,
2107 : ifr->ifr_addr.sa_data);
2108 : break;
2109 : default:
2110 : error = ENODEV;
2111 0 : }
2112 :
2113 0 : if (error == 0)
2114 0 : ifnewlladdr(ifp);
2115 0 : NET_UNLOCK();
2116 0 : break;
2117 :
2118 : case SIOCSIFLLPRIO:
2119 0 : if ((error = suser(p)))
2120 : break;
2121 0 : if (ifr->ifr_llprio < IFQ_MINPRIO ||
2122 0 : ifr->ifr_llprio > IFQ_MAXPRIO) {
2123 : error = EINVAL;
2124 0 : break;
2125 : }
2126 0 : NET_LOCK();
2127 0 : ifp->if_llprio = ifr->ifr_llprio;
2128 0 : NET_UNLOCK();
2129 0 : break;
2130 :
2131 : case SIOCSETKALIVE:
2132 : case SIOCDIFPHYADDR:
2133 : case SIOCSLIFPHYADDR:
2134 : case SIOCSLIFPHYRTABLE:
2135 : case SIOCSLIFPHYTTL:
2136 : case SIOCSLIFPHYDF:
2137 : case SIOCADDMULTI:
2138 : case SIOCDELMULTI:
2139 : case SIOCSIFMEDIA:
2140 : case SIOCSVNETID:
2141 : case SIOCSVNETFLOWID:
2142 : case SIOCSIFPAIR:
2143 : case SIOCSIFPARENT:
2144 : case SIOCDIFPARENT:
2145 0 : if ((error = suser(p)) != 0)
2146 : break;
2147 : /* FALLTHROUGH */
2148 : default:
2149 0 : error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
2150 0 : (struct mbuf *) cmd, (struct mbuf *) data,
2151 0 : (struct mbuf *) ifp, p));
2152 0 : if (error == EOPNOTSUPP) {
2153 0 : NET_LOCK();
2154 0 : error = ((*ifp->if_ioctl)(ifp, cmd, data));
2155 0 : NET_UNLOCK();
2156 0 : }
2157 : break;
2158 : }
2159 :
2160 0 : if (oif_flags != ifp->if_flags || oif_xflags != ifp->if_xflags)
2161 0 : rtm_ifchg(ifp);
2162 :
2163 0 : if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0)
2164 0 : getmicrotime(&ifp->if_lastchange);
2165 :
2166 0 : return (error);
2167 0 : }
2168 :
2169 : int
2170 0 : ifioctl_get(u_long cmd, caddr_t data)
2171 : {
2172 : struct ifnet *ifp;
2173 0 : struct ifreq *ifr = (struct ifreq *)data;
2174 0 : char ifdescrbuf[IFDESCRSIZE];
2175 0 : char ifrtlabelbuf[RTLABEL_LEN];
2176 : int error = 0;
2177 0 : size_t bytesdone;
2178 : const char *label;
2179 :
2180 0 : switch(cmd) {
2181 : case SIOCGIFCONF:
2182 0 : NET_RLOCK();
2183 0 : error = ifconf(data);
2184 0 : NET_RUNLOCK();
2185 0 : return (error);
2186 : case SIOCIFGCLONERS:
2187 0 : error = if_clone_list((struct if_clonereq *)data);
2188 0 : return (error);
2189 : case SIOCGIFGMEMB:
2190 0 : NET_RLOCK();
2191 0 : error = if_getgroupmembers(data);
2192 0 : NET_RUNLOCK();
2193 0 : return (error);
2194 : case SIOCGIFGATTR:
2195 0 : NET_RLOCK();
2196 0 : error = if_getgroupattribs(data);
2197 0 : NET_RUNLOCK();
2198 0 : return (error);
2199 : case SIOCGIFGLIST:
2200 0 : NET_RLOCK();
2201 0 : error = if_getgrouplist(data);
2202 0 : NET_RUNLOCK();
2203 0 : return (error);
2204 : }
2205 :
2206 0 : ifp = ifunit(ifr->ifr_name);
2207 0 : if (ifp == NULL)
2208 0 : return (ENXIO);
2209 :
2210 0 : NET_RLOCK();
2211 :
2212 0 : switch(cmd) {
2213 : case SIOCGIFFLAGS:
2214 0 : ifr->ifr_flags = ifp->if_flags;
2215 0 : if (ifq_is_oactive(&ifp->if_snd))
2216 0 : ifr->ifr_flags |= IFF_OACTIVE;
2217 : break;
2218 :
2219 : case SIOCGIFXFLAGS:
2220 0 : ifr->ifr_flags = ifp->if_xflags & ~(IFXF_MPSAFE|IFXF_CLONED);
2221 0 : break;
2222 :
2223 : case SIOCGIFMETRIC:
2224 0 : ifr->ifr_metric = ifp->if_metric;
2225 0 : break;
2226 :
2227 : case SIOCGIFMTU:
2228 0 : ifr->ifr_mtu = ifp->if_mtu;
2229 0 : break;
2230 :
2231 : case SIOCGIFHARDMTU:
2232 0 : ifr->ifr_hardmtu = ifp->if_hardmtu;
2233 0 : break;
2234 :
2235 : case SIOCGIFDATA: {
2236 0 : struct if_data ifdata;
2237 0 : if_getdata(ifp, &ifdata);
2238 0 : error = copyout(&ifdata, ifr->ifr_data, sizeof(ifdata));
2239 : break;
2240 0 : }
2241 :
2242 : case SIOCGIFDESCR:
2243 0 : strlcpy(ifdescrbuf, ifp->if_description, IFDESCRSIZE);
2244 0 : error = copyoutstr(ifdescrbuf, ifr->ifr_data, IFDESCRSIZE,
2245 : &bytesdone);
2246 0 : break;
2247 :
2248 : case SIOCGIFRTLABEL:
2249 0 : if (ifp->if_rtlabelid &&
2250 0 : (label = rtlabel_id2name(ifp->if_rtlabelid)) != NULL) {
2251 0 : strlcpy(ifrtlabelbuf, label, RTLABEL_LEN);
2252 0 : error = copyoutstr(ifrtlabelbuf, ifr->ifr_data,
2253 : RTLABEL_LEN, &bytesdone);
2254 0 : } else
2255 : error = ENOENT;
2256 : break;
2257 :
2258 : case SIOCGIFPRIORITY:
2259 0 : ifr->ifr_metric = ifp->if_priority;
2260 0 : break;
2261 :
2262 : case SIOCGIFRDOMAIN:
2263 0 : ifr->ifr_rdomainid = ifp->if_rdomain;
2264 0 : break;
2265 :
2266 : case SIOCGIFGROUP:
2267 0 : error = if_getgroup(data, ifp);
2268 0 : break;
2269 :
2270 : case SIOCGIFLLPRIO:
2271 0 : ifr->ifr_llprio = ifp->if_llprio;
2272 0 : break;
2273 :
2274 : default:
2275 0 : panic("invalid ioctl %lu", cmd);
2276 : }
2277 :
2278 0 : NET_RUNLOCK();
2279 :
2280 0 : return (error);
2281 0 : }
2282 :
2283 : /*
2284 : * Return interface configuration
2285 : * of system. List may be used
2286 : * in later ioctl's (above) to get
2287 : * other information.
2288 : */
2289 : int
2290 0 : ifconf(caddr_t data)
2291 : {
2292 0 : struct ifconf *ifc = (struct ifconf *)data;
2293 : struct ifnet *ifp;
2294 : struct ifaddr *ifa;
2295 0 : struct ifreq ifr, *ifrp;
2296 0 : int space = ifc->ifc_len, error = 0;
2297 :
2298 : /* If ifc->ifc_len is 0, fill it in with the needed size and return. */
2299 0 : if (space == 0) {
2300 0 : TAILQ_FOREACH(ifp, &ifnet, if_list) {
2301 : struct sockaddr *sa;
2302 :
2303 0 : if (TAILQ_EMPTY(&ifp->if_addrlist))
2304 0 : space += sizeof (ifr);
2305 : else
2306 0 : TAILQ_FOREACH(ifa,
2307 : &ifp->if_addrlist, ifa_list) {
2308 0 : sa = ifa->ifa_addr;
2309 0 : if (sa->sa_len > sizeof(*sa))
2310 0 : space += sa->sa_len -
2311 : sizeof(*sa);
2312 0 : space += sizeof(ifr);
2313 : }
2314 : }
2315 0 : ifc->ifc_len = space;
2316 0 : return (0);
2317 : }
2318 :
2319 0 : ifrp = ifc->ifc_req;
2320 0 : TAILQ_FOREACH(ifp, &ifnet, if_list) {
2321 0 : if (space < sizeof(ifr))
2322 : break;
2323 0 : bcopy(ifp->if_xname, ifr.ifr_name, IFNAMSIZ);
2324 0 : if (TAILQ_EMPTY(&ifp->if_addrlist)) {
2325 0 : bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
2326 0 : error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
2327 : sizeof(ifr));
2328 0 : if (error)
2329 : break;
2330 0 : space -= sizeof (ifr), ifrp++;
2331 0 : } else
2332 0 : TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
2333 0 : struct sockaddr *sa = ifa->ifa_addr;
2334 :
2335 0 : if (space < sizeof(ifr))
2336 0 : break;
2337 0 : if (sa->sa_len <= sizeof(*sa)) {
2338 0 : ifr.ifr_addr = *sa;
2339 0 : error = copyout((caddr_t)&ifr,
2340 0 : (caddr_t)ifrp, sizeof (ifr));
2341 0 : ifrp++;
2342 0 : } else {
2343 0 : space -= sa->sa_len - sizeof(*sa);
2344 0 : if (space < sizeof (ifr))
2345 0 : break;
2346 0 : error = copyout((caddr_t)&ifr,
2347 0 : (caddr_t)ifrp,
2348 : sizeof(ifr.ifr_name));
2349 0 : if (error == 0)
2350 0 : error = copyout((caddr_t)sa,
2351 0 : (caddr_t)&ifrp->ifr_addr,
2352 0 : sa->sa_len);
2353 0 : ifrp = (struct ifreq *)(sa->sa_len +
2354 0 : (caddr_t)&ifrp->ifr_addr);
2355 : }
2356 0 : if (error)
2357 0 : break;
2358 0 : space -= sizeof (ifr);
2359 0 : }
2360 : }
2361 0 : ifc->ifc_len -= space;
2362 0 : return (error);
2363 0 : }
2364 :
2365 : void
2366 0 : if_getdata(struct ifnet *ifp, struct if_data *data)
2367 : {
2368 : unsigned int i;
2369 :
2370 0 : *data = ifp->if_data;
2371 :
2372 0 : for (i = 0; i < ifp->if_nifqs; i++) {
2373 0 : struct ifqueue *ifq = ifp->if_ifqs[i];
2374 :
2375 0 : ifq_add_data(ifq, data);
2376 : }
2377 :
2378 0 : for (i = 0; i < ifp->if_niqs; i++) {
2379 0 : struct ifiqueue *ifiq = ifp->if_iqs[i];
2380 :
2381 0 : ifiq_add_data(ifiq, data);
2382 : }
2383 0 : }
2384 :
2385 : /*
2386 : * Dummy functions replaced in ifnet during detach (if protocols decide to
2387 : * fiddle with the if during detach.
2388 : */
2389 : void
2390 0 : if_detached_qstart(struct ifqueue *ifq)
2391 : {
2392 0 : ifq_purge(ifq);
2393 0 : }
2394 :
2395 : int
2396 0 : if_detached_ioctl(struct ifnet *ifp, u_long a, caddr_t b)
2397 : {
2398 0 : return ENODEV;
2399 : }
2400 :
2401 : /*
2402 : * Create interface group without members
2403 : */
2404 : struct ifg_group *
2405 0 : if_creategroup(const char *groupname)
2406 : {
2407 : struct ifg_group *ifg;
2408 :
2409 0 : if ((ifg = malloc(sizeof(*ifg), M_TEMP, M_NOWAIT)) == NULL)
2410 0 : return (NULL);
2411 :
2412 0 : strlcpy(ifg->ifg_group, groupname, sizeof(ifg->ifg_group));
2413 0 : ifg->ifg_refcnt = 0;
2414 0 : ifg->ifg_carp_demoted = 0;
2415 0 : TAILQ_INIT(&ifg->ifg_members);
2416 : #if NPF > 0
2417 0 : pfi_attach_ifgroup(ifg);
2418 : #endif
2419 0 : TAILQ_INSERT_TAIL(&ifg_head, ifg, ifg_next);
2420 :
2421 0 : return (ifg);
2422 0 : }
2423 :
2424 : /*
2425 : * Add a group to an interface
2426 : */
2427 : int
2428 0 : if_addgroup(struct ifnet *ifp, const char *groupname)
2429 : {
2430 : struct ifg_list *ifgl;
2431 : struct ifg_group *ifg = NULL;
2432 : struct ifg_member *ifgm;
2433 :
2434 0 : if (groupname[0] && groupname[strlen(groupname) - 1] >= '0' &&
2435 0 : groupname[strlen(groupname) - 1] <= '9')
2436 0 : return (EINVAL);
2437 :
2438 0 : TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
2439 0 : if (!strcmp(ifgl->ifgl_group->ifg_group, groupname))
2440 0 : return (EEXIST);
2441 :
2442 0 : if ((ifgl = malloc(sizeof(*ifgl), M_TEMP, M_NOWAIT)) == NULL)
2443 0 : return (ENOMEM);
2444 :
2445 0 : if ((ifgm = malloc(sizeof(*ifgm), M_TEMP, M_NOWAIT)) == NULL) {
2446 0 : free(ifgl, M_TEMP, sizeof(*ifgl));
2447 0 : return (ENOMEM);
2448 : }
2449 :
2450 0 : TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
2451 0 : if (!strcmp(ifg->ifg_group, groupname))
2452 : break;
2453 :
2454 0 : if (ifg == NULL && (ifg = if_creategroup(groupname)) == NULL) {
2455 0 : free(ifgl, M_TEMP, sizeof(*ifgl));
2456 0 : free(ifgm, M_TEMP, sizeof(*ifgm));
2457 0 : return (ENOMEM);
2458 : }
2459 :
2460 0 : ifg->ifg_refcnt++;
2461 0 : ifgl->ifgl_group = ifg;
2462 0 : ifgm->ifgm_ifp = ifp;
2463 :
2464 0 : TAILQ_INSERT_TAIL(&ifg->ifg_members, ifgm, ifgm_next);
2465 0 : TAILQ_INSERT_TAIL(&ifp->if_groups, ifgl, ifgl_next);
2466 :
2467 : #if NPF > 0
2468 0 : pfi_group_addmember(groupname, ifp);
2469 : #endif
2470 :
2471 0 : return (0);
2472 0 : }
2473 :
2474 : /*
2475 : * Remove a group from an interface
2476 : */
2477 : int
2478 0 : if_delgroup(struct ifnet *ifp, const char *groupname)
2479 : {
2480 : struct ifg_list *ifgl;
2481 : struct ifg_member *ifgm;
2482 :
2483 0 : TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
2484 0 : if (!strcmp(ifgl->ifgl_group->ifg_group, groupname))
2485 : break;
2486 0 : if (ifgl == NULL)
2487 0 : return (ENOENT);
2488 :
2489 0 : TAILQ_REMOVE(&ifp->if_groups, ifgl, ifgl_next);
2490 :
2491 0 : TAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next)
2492 0 : if (ifgm->ifgm_ifp == ifp)
2493 : break;
2494 :
2495 0 : if (ifgm != NULL) {
2496 0 : TAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm, ifgm_next);
2497 0 : free(ifgm, M_TEMP, sizeof(*ifgm));
2498 0 : }
2499 :
2500 0 : if (--ifgl->ifgl_group->ifg_refcnt == 0) {
2501 0 : TAILQ_REMOVE(&ifg_head, ifgl->ifgl_group, ifg_next);
2502 : #if NPF > 0
2503 0 : pfi_detach_ifgroup(ifgl->ifgl_group);
2504 : #endif
2505 0 : free(ifgl->ifgl_group, M_TEMP, 0);
2506 0 : }
2507 :
2508 0 : free(ifgl, M_TEMP, sizeof(*ifgl));
2509 :
2510 : #if NPF > 0
2511 0 : pfi_group_change(groupname);
2512 : #endif
2513 :
2514 0 : return (0);
2515 0 : }
2516 :
2517 : /*
2518 : * Stores all groups from an interface in memory pointed
2519 : * to by data
2520 : */
2521 : int
2522 0 : if_getgroup(caddr_t data, struct ifnet *ifp)
2523 : {
2524 : int len, error;
2525 : struct ifg_list *ifgl;
2526 0 : struct ifg_req ifgrq, *ifgp;
2527 0 : struct ifgroupreq *ifgr = (struct ifgroupreq *)data;
2528 :
2529 0 : if (ifgr->ifgr_len == 0) {
2530 0 : TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next)
2531 0 : ifgr->ifgr_len += sizeof(struct ifg_req);
2532 0 : return (0);
2533 : }
2534 :
2535 : len = ifgr->ifgr_len;
2536 0 : ifgp = ifgr->ifgr_groups;
2537 0 : TAILQ_FOREACH(ifgl, &ifp->if_groups, ifgl_next) {
2538 0 : if (len < sizeof(ifgrq))
2539 0 : return (EINVAL);
2540 0 : bzero(&ifgrq, sizeof ifgrq);
2541 0 : strlcpy(ifgrq.ifgrq_group, ifgl->ifgl_group->ifg_group,
2542 : sizeof(ifgrq.ifgrq_group));
2543 0 : if ((error = copyout((caddr_t)&ifgrq, (caddr_t)ifgp,
2544 : sizeof(struct ifg_req))))
2545 0 : return (error);
2546 0 : len -= sizeof(ifgrq);
2547 0 : ifgp++;
2548 : }
2549 :
2550 0 : return (0);
2551 0 : }
2552 :
2553 : /*
2554 : * Stores all members of a group in memory pointed to by data
2555 : */
2556 : int
2557 0 : if_getgroupmembers(caddr_t data)
2558 : {
2559 0 : struct ifgroupreq *ifgr = (struct ifgroupreq *)data;
2560 : struct ifg_group *ifg;
2561 : struct ifg_member *ifgm;
2562 0 : struct ifg_req ifgrq, *ifgp;
2563 : int len, error;
2564 :
2565 0 : TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
2566 0 : if (!strcmp(ifg->ifg_group, ifgr->ifgr_name))
2567 : break;
2568 0 : if (ifg == NULL)
2569 0 : return (ENOENT);
2570 :
2571 0 : if (ifgr->ifgr_len == 0) {
2572 0 : TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next)
2573 0 : ifgr->ifgr_len += sizeof(ifgrq);
2574 0 : return (0);
2575 : }
2576 :
2577 : len = ifgr->ifgr_len;
2578 0 : ifgp = ifgr->ifgr_groups;
2579 0 : TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next) {
2580 0 : if (len < sizeof(ifgrq))
2581 0 : return (EINVAL);
2582 0 : bzero(&ifgrq, sizeof ifgrq);
2583 0 : strlcpy(ifgrq.ifgrq_member, ifgm->ifgm_ifp->if_xname,
2584 : sizeof(ifgrq.ifgrq_member));
2585 0 : if ((error = copyout((caddr_t)&ifgrq, (caddr_t)ifgp,
2586 : sizeof(struct ifg_req))))
2587 0 : return (error);
2588 0 : len -= sizeof(ifgrq);
2589 0 : ifgp++;
2590 : }
2591 :
2592 0 : return (0);
2593 0 : }
2594 :
2595 : int
2596 0 : if_getgroupattribs(caddr_t data)
2597 : {
2598 0 : struct ifgroupreq *ifgr = (struct ifgroupreq *)data;
2599 : struct ifg_group *ifg;
2600 :
2601 0 : TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
2602 0 : if (!strcmp(ifg->ifg_group, ifgr->ifgr_name))
2603 : break;
2604 0 : if (ifg == NULL)
2605 0 : return (ENOENT);
2606 :
2607 0 : ifgr->ifgr_attrib.ifg_carp_demoted = ifg->ifg_carp_demoted;
2608 :
2609 0 : return (0);
2610 0 : }
2611 :
2612 : int
2613 0 : if_setgroupattribs(caddr_t data)
2614 : {
2615 0 : struct ifgroupreq *ifgr = (struct ifgroupreq *)data;
2616 : struct ifg_group *ifg;
2617 : struct ifg_member *ifgm;
2618 : int demote;
2619 :
2620 0 : TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
2621 0 : if (!strcmp(ifg->ifg_group, ifgr->ifgr_name))
2622 : break;
2623 0 : if (ifg == NULL)
2624 0 : return (ENOENT);
2625 :
2626 0 : demote = ifgr->ifgr_attrib.ifg_carp_demoted;
2627 0 : if (demote + ifg->ifg_carp_demoted > 0xff ||
2628 0 : demote + ifg->ifg_carp_demoted < 0)
2629 0 : return (EINVAL);
2630 :
2631 0 : ifg->ifg_carp_demoted += demote;
2632 :
2633 0 : TAILQ_FOREACH(ifgm, &ifg->ifg_members, ifgm_next)
2634 0 : ifgm->ifgm_ifp->if_ioctl(ifgm->ifgm_ifp, SIOCSIFGATTR, data);
2635 :
2636 0 : return (0);
2637 0 : }
2638 :
2639 : /*
2640 : * Stores all groups in memory pointed to by data
2641 : */
2642 : int
2643 0 : if_getgrouplist(caddr_t data)
2644 : {
2645 0 : struct ifgroupreq *ifgr = (struct ifgroupreq *)data;
2646 : struct ifg_group *ifg;
2647 0 : struct ifg_req ifgrq, *ifgp;
2648 : int len, error;
2649 :
2650 0 : if (ifgr->ifgr_len == 0) {
2651 0 : TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
2652 0 : ifgr->ifgr_len += sizeof(ifgrq);
2653 0 : return (0);
2654 : }
2655 :
2656 : len = ifgr->ifgr_len;
2657 0 : ifgp = ifgr->ifgr_groups;
2658 0 : TAILQ_FOREACH(ifg, &ifg_head, ifg_next) {
2659 0 : if (len < sizeof(ifgrq))
2660 0 : return (EINVAL);
2661 0 : bzero(&ifgrq, sizeof ifgrq);
2662 0 : strlcpy(ifgrq.ifgrq_group, ifg->ifg_group,
2663 : sizeof(ifgrq.ifgrq_group));
2664 0 : if ((error = copyout((caddr_t)&ifgrq, (caddr_t)ifgp,
2665 : sizeof(struct ifg_req))))
2666 0 : return (error);
2667 0 : len -= sizeof(ifgrq);
2668 0 : ifgp++;
2669 : }
2670 :
2671 0 : return (0);
2672 0 : }
2673 :
2674 : void
2675 0 : if_group_routechange(struct sockaddr *dst, struct sockaddr *mask)
2676 : {
2677 0 : switch (dst->sa_family) {
2678 : case AF_INET:
2679 0 : if (satosin(dst)->sin_addr.s_addr == INADDR_ANY &&
2680 0 : mask && (mask->sa_len == 0 ||
2681 0 : satosin(mask)->sin_addr.s_addr == INADDR_ANY))
2682 0 : if_group_egress_build();
2683 : break;
2684 : #ifdef INET6
2685 : case AF_INET6:
2686 0 : if (IN6_ARE_ADDR_EQUAL(&(satosin6(dst))->sin6_addr,
2687 0 : &in6addr_any) && mask && (mask->sa_len == 0 ||
2688 0 : IN6_ARE_ADDR_EQUAL(&(satosin6(mask))->sin6_addr,
2689 : &in6addr_any)))
2690 0 : if_group_egress_build();
2691 : break;
2692 : #endif
2693 : }
2694 0 : }
2695 :
2696 : int
2697 0 : if_group_egress_build(void)
2698 : {
2699 : struct ifnet *ifp;
2700 : struct ifg_group *ifg;
2701 : struct ifg_member *ifgm, *next;
2702 0 : struct sockaddr_in sa_in;
2703 : #ifdef INET6
2704 0 : struct sockaddr_in6 sa_in6;
2705 : #endif
2706 : struct rtentry *rt;
2707 :
2708 0 : TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
2709 0 : if (!strcmp(ifg->ifg_group, IFG_EGRESS))
2710 : break;
2711 :
2712 0 : if (ifg != NULL)
2713 0 : TAILQ_FOREACH_SAFE(ifgm, &ifg->ifg_members, ifgm_next, next)
2714 0 : if_delgroup(ifgm->ifgm_ifp, IFG_EGRESS);
2715 :
2716 0 : bzero(&sa_in, sizeof(sa_in));
2717 0 : sa_in.sin_len = sizeof(sa_in);
2718 0 : sa_in.sin_family = AF_INET;
2719 0 : rt = rtable_lookup(0, sintosa(&sa_in), sintosa(&sa_in), NULL, RTP_ANY);
2720 0 : while (rt != NULL) {
2721 0 : ifp = if_get(rt->rt_ifidx);
2722 0 : if (ifp != NULL) {
2723 0 : if_addgroup(ifp, IFG_EGRESS);
2724 0 : if_put(ifp);
2725 0 : }
2726 0 : rt = rtable_iterate(rt);
2727 : }
2728 :
2729 : #ifdef INET6
2730 0 : bcopy(&sa6_any, &sa_in6, sizeof(sa_in6));
2731 0 : rt = rtable_lookup(0, sin6tosa(&sa_in6), sin6tosa(&sa_in6), NULL,
2732 : RTP_ANY);
2733 0 : while (rt != NULL) {
2734 0 : ifp = if_get(rt->rt_ifidx);
2735 0 : if (ifp != NULL) {
2736 0 : if_addgroup(ifp, IFG_EGRESS);
2737 0 : if_put(ifp);
2738 0 : }
2739 0 : rt = rtable_iterate(rt);
2740 : }
2741 : #endif /* INET6 */
2742 :
2743 0 : return (0);
2744 0 : }
2745 :
2746 : /*
2747 : * Set/clear promiscuous mode on interface ifp based on the truth value
2748 : * of pswitch. The calls are reference counted so that only the first
2749 : * "on" request actually has an effect, as does the final "off" request.
2750 : * Results are undefined if the "off" and "on" requests are not matched.
2751 : */
2752 : int
2753 0 : ifpromisc(struct ifnet *ifp, int pswitch)
2754 : {
2755 0 : struct ifreq ifr;
2756 : unsigned short oif_flags;
2757 : int oif_pcount, error;
2758 :
2759 0 : oif_flags = ifp->if_flags;
2760 0 : oif_pcount = ifp->if_pcount;
2761 0 : if (pswitch) {
2762 0 : if (ifp->if_pcount++ != 0)
2763 0 : return (0);
2764 0 : ifp->if_flags |= IFF_PROMISC;
2765 0 : } else {
2766 0 : if (--ifp->if_pcount > 0)
2767 0 : return (0);
2768 0 : ifp->if_flags &= ~IFF_PROMISC;
2769 : }
2770 :
2771 0 : if ((ifp->if_flags & IFF_UP) == 0)
2772 0 : return (0);
2773 :
2774 0 : memset(&ifr, 0, sizeof(ifr));
2775 0 : ifr.ifr_flags = ifp->if_flags;
2776 0 : error = ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
2777 0 : if (error) {
2778 0 : ifp->if_flags = oif_flags;
2779 0 : ifp->if_pcount = oif_pcount;
2780 0 : }
2781 :
2782 0 : return (error);
2783 0 : }
2784 :
2785 : void
2786 0 : ifa_add(struct ifnet *ifp, struct ifaddr *ifa)
2787 : {
2788 0 : TAILQ_INSERT_TAIL(&ifp->if_addrlist, ifa, ifa_list);
2789 0 : }
2790 :
2791 : void
2792 0 : ifa_del(struct ifnet *ifp, struct ifaddr *ifa)
2793 : {
2794 0 : TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);
2795 0 : }
2796 :
2797 : void
2798 0 : ifa_update_broadaddr(struct ifnet *ifp, struct ifaddr *ifa, struct sockaddr *sa)
2799 : {
2800 0 : if (ifa->ifa_broadaddr->sa_len != sa->sa_len)
2801 0 : panic("ifa_update_broadaddr does not support dynamic length");
2802 0 : bcopy(sa, ifa->ifa_broadaddr, sa->sa_len);
2803 0 : }
2804 :
2805 : #ifdef DDB
2806 : /* debug function, can be called from ddb> */
2807 : void
2808 0 : ifa_print_all(void)
2809 : {
2810 : struct ifnet *ifp;
2811 : struct ifaddr *ifa;
2812 :
2813 0 : TAILQ_FOREACH(ifp, &ifnet, if_list) {
2814 0 : TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
2815 0 : char addr[INET6_ADDRSTRLEN];
2816 :
2817 0 : switch (ifa->ifa_addr->sa_family) {
2818 : case AF_INET:
2819 0 : printf("%s", inet_ntop(AF_INET,
2820 0 : &satosin(ifa->ifa_addr)->sin_addr,
2821 0 : addr, sizeof(addr)));
2822 0 : break;
2823 : #ifdef INET6
2824 : case AF_INET6:
2825 0 : printf("%s", inet_ntop(AF_INET6,
2826 0 : &(satosin6(ifa->ifa_addr))->sin6_addr,
2827 0 : addr, sizeof(addr)));
2828 0 : break;
2829 : #endif
2830 : }
2831 0 : printf(" on %s\n", ifp->if_xname);
2832 0 : }
2833 : }
2834 0 : }
2835 : #endif /* DDB */
2836 :
2837 : void
2838 0 : ifnewlladdr(struct ifnet *ifp)
2839 : {
2840 : #ifdef INET6
2841 : struct ifaddr *ifa;
2842 : #endif
2843 0 : struct ifreq ifrq;
2844 : short up;
2845 : int s;
2846 :
2847 0 : s = splnet();
2848 0 : up = ifp->if_flags & IFF_UP;
2849 :
2850 0 : if (up) {
2851 : /* go down for a moment... */
2852 0 : ifp->if_flags &= ~IFF_UP;
2853 0 : ifrq.ifr_flags = ifp->if_flags;
2854 0 : (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifrq);
2855 0 : }
2856 :
2857 0 : ifp->if_flags |= IFF_UP;
2858 0 : ifrq.ifr_flags = ifp->if_flags;
2859 0 : (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifrq);
2860 :
2861 : #ifdef INET6
2862 : /*
2863 : * Update the link-local address. Don't do it if we're
2864 : * a router to avoid confusing hosts on the network.
2865 : */
2866 0 : if (!ip6_forwarding) {
2867 0 : ifa = &in6ifa_ifpforlinklocal(ifp, 0)->ia_ifa;
2868 0 : if (ifa) {
2869 0 : in6_purgeaddr(ifa);
2870 0 : dohooks(ifp->if_addrhooks, 0);
2871 0 : in6_ifattach(ifp);
2872 0 : }
2873 : }
2874 : #endif
2875 0 : if (!up) {
2876 : /* go back down */
2877 0 : ifp->if_flags &= ~IFF_UP;
2878 0 : ifrq.ifr_flags = ifp->if_flags;
2879 0 : (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifrq);
2880 0 : }
2881 0 : splx(s);
2882 0 : }
2883 :
2884 : int net_ticks;
2885 : u_int net_livelocks;
2886 :
2887 : void
2888 0 : net_tick(void *null)
2889 : {
2890 : extern int ticks;
2891 :
2892 0 : if (ticks - net_ticks > 1)
2893 0 : net_livelocks++;
2894 :
2895 0 : net_ticks = ticks;
2896 :
2897 0 : timeout_add(&net_tick_to, 1);
2898 0 : }
2899 :
2900 : int
2901 0 : net_livelocked(void)
2902 : {
2903 : extern int ticks;
2904 :
2905 0 : return (ticks - net_ticks > 1);
2906 : }
2907 :
2908 : void
2909 0 : if_rxr_init(struct if_rxring *rxr, u_int lwm, u_int hwm)
2910 : {
2911 : extern int ticks;
2912 :
2913 0 : memset(rxr, 0, sizeof(*rxr));
2914 :
2915 0 : rxr->rxr_adjusted = ticks;
2916 0 : rxr->rxr_cwm = rxr->rxr_lwm = lwm;
2917 0 : rxr->rxr_hwm = hwm;
2918 0 : }
2919 :
2920 : static inline void
2921 0 : if_rxr_adjust_cwm(struct if_rxring *rxr)
2922 : {
2923 : extern int ticks;
2924 :
2925 0 : if (net_livelocked()) {
2926 0 : if (rxr->rxr_cwm > rxr->rxr_lwm)
2927 0 : rxr->rxr_cwm--;
2928 : else
2929 : return;
2930 0 : } else if (rxr->rxr_alive >= rxr->rxr_lwm)
2931 : return;
2932 0 : else if (rxr->rxr_cwm < rxr->rxr_hwm)
2933 0 : rxr->rxr_cwm++;
2934 :
2935 0 : rxr->rxr_adjusted = ticks;
2936 0 : }
2937 :
2938 : void
2939 0 : if_rxr_livelocked(struct if_rxring *rxr)
2940 : {
2941 : extern int ticks;
2942 :
2943 0 : if (ticks - rxr->rxr_adjusted >= 1) {
2944 0 : if (rxr->rxr_cwm > rxr->rxr_lwm)
2945 0 : rxr->rxr_cwm--;
2946 :
2947 0 : rxr->rxr_adjusted = ticks;
2948 0 : }
2949 0 : }
2950 :
2951 : u_int
2952 0 : if_rxr_get(struct if_rxring *rxr, u_int max)
2953 : {
2954 : extern int ticks;
2955 : u_int diff;
2956 :
2957 0 : if (ticks - rxr->rxr_adjusted >= 1) {
2958 : /* we're free to try for an adjustment */
2959 0 : if_rxr_adjust_cwm(rxr);
2960 0 : }
2961 :
2962 0 : if (rxr->rxr_alive >= rxr->rxr_cwm)
2963 0 : return (0);
2964 :
2965 0 : diff = min(rxr->rxr_cwm - rxr->rxr_alive, max);
2966 0 : rxr->rxr_alive += diff;
2967 :
2968 0 : return (diff);
2969 0 : }
2970 :
2971 : int
2972 0 : if_rxr_info_ioctl(struct if_rxrinfo *uifri, u_int t, struct if_rxring_info *e)
2973 : {
2974 0 : struct if_rxrinfo kifri;
2975 : int error;
2976 : u_int n;
2977 :
2978 0 : error = copyin(uifri, &kifri, sizeof(kifri));
2979 0 : if (error)
2980 0 : return (error);
2981 :
2982 0 : n = min(t, kifri.ifri_total);
2983 0 : kifri.ifri_total = t;
2984 :
2985 0 : if (n > 0) {
2986 0 : error = copyout(e, kifri.ifri_entries, sizeof(*e) * n);
2987 0 : if (error)
2988 0 : return (error);
2989 : }
2990 :
2991 0 : return (copyout(&kifri, uifri, sizeof(kifri)));
2992 0 : }
2993 :
2994 : int
2995 0 : if_rxr_ioctl(struct if_rxrinfo *ifri, const char *name, u_int size,
2996 : struct if_rxring *rxr)
2997 : {
2998 0 : struct if_rxring_info ifr;
2999 :
3000 0 : memset(&ifr, 0, sizeof(ifr));
3001 :
3002 0 : if (name != NULL)
3003 0 : strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
3004 :
3005 0 : ifr.ifr_size = size;
3006 0 : ifr.ifr_info = *rxr;
3007 :
3008 0 : return (if_rxr_info_ioctl(ifri, 1, &ifr));
3009 0 : }
3010 :
3011 : /*
3012 : * Network stack input queues.
3013 : */
3014 :
3015 : void
3016 0 : niq_init(struct niqueue *niq, u_int maxlen, u_int isr)
3017 : {
3018 0 : mq_init(&niq->ni_q, maxlen, IPL_NET);
3019 0 : niq->ni_isr = isr;
3020 0 : }
3021 :
3022 : int
3023 0 : niq_enqueue(struct niqueue *niq, struct mbuf *m)
3024 : {
3025 : int rv;
3026 :
3027 0 : rv = mq_enqueue(&niq->ni_q, m);
3028 0 : if (rv == 0)
3029 0 : schednetisr(niq->ni_isr);
3030 : else
3031 0 : if_congestion();
3032 :
3033 0 : return (rv);
3034 : }
3035 :
3036 : int
3037 0 : niq_enlist(struct niqueue *niq, struct mbuf_list *ml)
3038 : {
3039 : int rv;
3040 :
3041 0 : rv = mq_enlist(&niq->ni_q, ml);
3042 0 : if (rv == 0)
3043 0 : schednetisr(niq->ni_isr);
3044 : else
3045 0 : if_congestion();
3046 :
3047 0 : return (rv);
3048 : }
3049 :
3050 : __dead void
3051 0 : unhandled_af(int af)
3052 : {
3053 0 : panic("unhandled af %d", af);
3054 : }
3055 :
3056 : /*
3057 : * XXXSMP This tunable is here to work around the fact that IPsec
3058 : * globals aren't ready to be accessed by multiple threads in
3059 : * parallel.
3060 : */
3061 : int nettaskqs = NET_TASKQ;
3062 :
3063 : struct taskq *
3064 0 : net_tq(unsigned int ifindex)
3065 : {
3066 : struct taskq *t = NULL;
3067 :
3068 0 : t = nettqmp[ifindex % nettaskqs];
3069 :
3070 0 : return (t);
3071 : }
|