This source file includes following definitions.
- vlanattach
- vlan_clone_create
- vlan_clone_destroy
- vlan_ifdetach
- vlan_start
- vlan_input
- vlan_config
- vlan_unconfig
- vlan_vlandev_state
- vlan_set_promisc
- vlan_ioctl
- vlan_ether_addmulti
- vlan_ether_delmulti
- vlan_ether_purgemulti
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 #include "vlan.h"
52
53 #include <sys/param.h>
54 #include <sys/kernel.h>
55 #include <sys/malloc.h>
56 #include <sys/mbuf.h>
57 #include <sys/queue.h>
58 #include <sys/socket.h>
59 #include <sys/sockio.h>
60 #include <sys/sysctl.h>
61 #include <sys/systm.h>
62 #include <sys/proc.h>
63
64 #include "bpfilter.h"
65 #if NBPFILTER > 0
66 #include <net/bpf.h>
67 #endif
68
69 #include <net/if.h>
70 #include <net/if_dl.h>
71 #include <net/if_types.h>
72
73 #ifdef INET
74 #include <netinet/in.h>
75 #include <netinet/if_ether.h>
76 #endif
77
78 #include <net/if_vlan_var.h>
79
80 extern struct ifaddr **ifnet_addrs;
81 u_long vlan_tagmask;
82
83 #define TAG_HASH_SIZE 32
84 #define TAG_HASH(tag) (tag & vlan_tagmask)
85 LIST_HEAD(, ifvlan) *vlan_tagh;
86
87 void vlan_start (struct ifnet *ifp);
88 int vlan_ioctl (struct ifnet *ifp, u_long cmd, caddr_t addr);
89 int vlan_unconfig (struct ifnet *ifp);
90 int vlan_config (struct ifvlan *, struct ifnet *, u_int16_t);
91 void vlan_vlandev_state(void *);
92 void vlanattach (int count);
93 int vlan_set_promisc (struct ifnet *ifp);
94 int vlan_ether_addmulti(struct ifvlan *, struct ifreq *);
95 int vlan_ether_delmulti(struct ifvlan *, struct ifreq *);
96 void vlan_ether_purgemulti(struct ifvlan *);
97 int vlan_clone_create(struct if_clone *, int);
98 int vlan_clone_destroy(struct ifnet *);
99 void vlan_ifdetach(void *);
100
101 struct if_clone vlan_cloner =
102 IF_CLONE_INITIALIZER("vlan", vlan_clone_create, vlan_clone_destroy);
103
104
105 void
106 vlanattach(int count)
107 {
108 vlan_tagh = hashinit(TAG_HASH_SIZE, M_DEVBUF, M_NOWAIT, &vlan_tagmask);
109 if (vlan_tagh == NULL)
110 panic("vlanattach: hashinit");
111
112 if_clone_attach(&vlan_cloner);
113 }
114
115 int
116 vlan_clone_create(struct if_clone *ifc, int unit)
117 {
118 struct ifvlan *ifv;
119 struct ifnet *ifp;
120
121 ifv = malloc(sizeof(*ifv), M_DEVBUF, M_NOWAIT);
122 if (!ifv)
123 return (ENOMEM);
124 bzero(ifv, sizeof(*ifv));
125
126 LIST_INIT(&ifv->vlan_mc_listhead);
127 ifp = &ifv->ifv_if;
128 ifp->if_softc = ifv;
129 snprintf(ifp->if_xname, sizeof ifp->if_xname, "%s%d", ifc->ifc_name,
130 unit);
131
132
133
134 ifp->if_start = vlan_start;
135 ifp->if_ioctl = vlan_ioctl;
136 ifp->if_output = ether_output;
137 IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
138 IFQ_SET_READY(&ifp->if_snd);
139 if_attach(ifp);
140 ether_ifattach(ifp);
141
142 ifp->if_type = IFT_L2VLAN;
143 ifp->if_hdrlen = EVL_ENCAPLEN;
144
145 return (0);
146 }
147
148 int
149 vlan_clone_destroy(struct ifnet *ifp)
150 {
151 struct ifvlan *ifv = ifp->if_softc;
152
153 vlan_unconfig(ifp);
154 ether_ifdetach(ifp);
155 if_detach(ifp);
156
157 free(ifv, M_DEVBUF);
158 return (0);
159 }
160
161 void
162 vlan_ifdetach(void *ptr)
163 {
164 struct ifvlan *ifv = (struct ifvlan *)ptr;
165
166
167
168
169
170
171 ifv->dh_cookie = NULL;
172 vlan_clone_destroy(&ifv->ifv_if);
173 }
174
175 void
176 vlan_start(struct ifnet *ifp)
177 {
178 struct ifvlan *ifv;
179 struct ifnet *p;
180 struct mbuf *m;
181 int error;
182
183 ifv = ifp->if_softc;
184 p = ifv->ifv_p;
185
186 ifp->if_flags |= IFF_OACTIVE;
187 for (;;) {
188 IFQ_DEQUEUE(&ifp->if_snd, m);
189 if (m == NULL)
190 break;
191
192 if ((p->if_flags & (IFF_UP|IFF_RUNNING)) !=
193 (IFF_UP|IFF_RUNNING)) {
194 IF_DROP(&p->if_snd);
195
196 ifp->if_oerrors++;
197 m_freem(m);
198 continue;
199 }
200
201 #if NBPFILTER > 0
202 if (ifp->if_bpf)
203 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
204 #endif
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224 if (p->if_capabilities & IFCAP_VLAN_HWTAGGING) {
225 m->m_pkthdr.rcvif = ifp;
226 m->m_flags |= M_PROTO1;
227 } else {
228 struct ether_vlan_header evh;
229
230 m_copydata(m, 0, ETHER_HDR_LEN, (caddr_t)&evh);
231 evh.evl_proto = evh.evl_encap_proto;
232 evh.evl_encap_proto = htons(ETHERTYPE_VLAN);
233 evh.evl_tag = htons(ifv->ifv_tag +
234 (ifv->ifv_prio << EVL_PRIO_BITS));
235
236 m_adj(m, ETHER_HDR_LEN);
237 M_PREPEND(m, sizeof(evh), M_DONTWAIT);
238 if (m == NULL) {
239 ifp->if_oerrors++;
240 continue;
241 }
242
243 m_copyback(m, 0, sizeof(evh), &evh);
244 }
245
246
247
248
249
250 p->if_obytes += m->m_pkthdr.len;
251 if (m->m_flags & M_MCAST)
252 p->if_omcasts++;
253 IFQ_ENQUEUE(&p->if_snd, m, NULL, error);
254 if (error) {
255
256 ifp->if_oerrors++;
257 continue;
258 }
259
260 ifp->if_opackets++;
261 if ((p->if_flags & (IFF_RUNNING|IFF_OACTIVE)) == IFF_RUNNING)
262 p->if_start(p);
263 }
264 ifp->if_flags &= ~IFF_OACTIVE;
265
266 return;
267 }
268
269
270
271
272 int
273 vlan_input(eh, m)
274 struct ether_header *eh;
275 struct mbuf *m;
276 {
277 struct ifvlan *ifv;
278 u_int tag;
279 struct ifnet *ifp = m->m_pkthdr.rcvif;
280
281 if (m->m_len < EVL_ENCAPLEN &&
282 (m = m_pullup(m, EVL_ENCAPLEN)) == NULL) {
283 ifp->if_ierrors++;
284 return (0);
285 }
286
287 tag = EVL_VLANOFTAG(ntohs(*mtod(m, u_int16_t *)));
288
289 LIST_FOREACH(ifv, &vlan_tagh[TAG_HASH(tag)], ifv_list) {
290 if (m->m_pkthdr.rcvif == ifv->ifv_p && tag == ifv->ifv_tag)
291 break;
292 }
293 if (ifv == NULL)
294 return (1);
295
296 if ((ifv->ifv_if.if_flags & (IFF_UP|IFF_RUNNING)) !=
297 (IFF_UP|IFF_RUNNING)) {
298 m_freem(m);
299 return (0);
300 }
301
302
303
304
305
306
307
308
309 m->m_pkthdr.rcvif = &ifv->ifv_if;
310 eh->ether_type = mtod(m, u_int16_t *)[1];
311 m->m_len -= EVL_ENCAPLEN;
312 m->m_data += EVL_ENCAPLEN;
313 m->m_pkthdr.len -= EVL_ENCAPLEN;
314
315 #if NBPFILTER > 0
316 if (ifv->ifv_if.if_bpf)
317 bpf_mtap_hdr(ifv->ifv_if.if_bpf, (char *)eh, ETHER_HDR_LEN,
318 m, BPF_DIRECTION_IN);
319 #endif
320 ifv->ifv_if.if_ipackets++;
321 ether_input(&ifv->ifv_if, eh, m);
322
323 return (0);
324 }
325
326 int
327 vlan_config(struct ifvlan *ifv, struct ifnet *p, u_int16_t tag)
328 {
329 struct ifaddr *ifa1, *ifa2;
330 struct sockaddr_dl *sdl1, *sdl2;
331 int s;
332
333 if (p->if_type != IFT_ETHER)
334 return EPROTONOSUPPORT;
335 if (ifv->ifv_p == p && ifv->ifv_tag == tag)
336 return (0);
337 if (ifv->ifv_p)
338 return EBUSY;
339
340 ifv->ifv_p = p;
341
342 if (p->if_capabilities & IFCAP_VLAN_MTU)
343 ifv->ifv_if.if_mtu = p->if_mtu;
344 else {
345
346
347
348
349 ifv->ifv_if.if_mtu = p->if_mtu - EVL_ENCAPLEN;
350 #ifdef DIAGNOSTIC
351 printf("%s: initialized with non-standard mtu %lu (parent %s)\n",
352 ifv->ifv_if.if_xname, ifv->ifv_if.if_mtu,
353 ifv->ifv_p->if_xname);
354 #endif
355 }
356
357 ifv->ifv_if.if_flags = p->if_flags &
358 (IFF_UP | IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST);
359
360
361
362
363
364 ifv->ifv_if.if_type = p->if_type;
365
366
367
368
369
370 ifv->ifv_if.if_baudrate = p->if_baudrate;
371
372
373
374
375
376
377
378
379
380
381
382
383 if (p->if_capabilities & IFCAP_VLAN_HWTAGGING)
384 ifv->ifv_if.if_capabilities = p->if_capabilities &
385 (IFCAP_CSUM_IPv4|IFCAP_CSUM_TCPv4|
386 IFCAP_CSUM_UDPv4);
387
388
389
390
391
392
393 ifa1 = ifnet_addrs[ifv->ifv_if.if_index];
394 ifa2 = ifnet_addrs[p->if_index];
395 sdl1 = (struct sockaddr_dl *)ifa1->ifa_addr;
396 sdl2 = (struct sockaddr_dl *)ifa2->ifa_addr;
397 sdl1->sdl_type = IFT_ETHER;
398 sdl1->sdl_alen = ETHER_ADDR_LEN;
399 bcopy(LLADDR(sdl2), LLADDR(sdl1), ETHER_ADDR_LEN);
400 bcopy(LLADDR(sdl2), ifv->ifv_ac.ac_enaddr, ETHER_ADDR_LEN);
401
402 ifv->ifv_tag = tag;
403 s = splnet();
404 LIST_INSERT_HEAD(&vlan_tagh[TAG_HASH(tag)], ifv, ifv_list);
405
406
407 ifv->lh_cookie = hook_establish(p->if_linkstatehooks, 1,
408 vlan_vlandev_state, ifv);
409
410
411 ifv->dh_cookie = hook_establish(p->if_detachhooks, 1,
412 vlan_ifdetach, ifv);
413
414 vlan_vlandev_state(ifv);
415 splx(s);
416
417 return 0;
418 }
419
420 int
421 vlan_unconfig(struct ifnet *ifp)
422 {
423 struct ifaddr *ifa;
424 struct sockaddr_dl *sdl;
425 struct ifvlan *ifv;
426 struct ifnet *p;
427 struct ifreq *ifr, *ifr_p;
428 int s;
429
430 ifv = ifp->if_softc;
431 p = ifv->ifv_p;
432 if (p == NULL)
433 return 0;
434
435 ifr = (struct ifreq *)&ifp->if_data;
436 ifr_p = (struct ifreq *)&ifv->ifv_p->if_data;
437
438 s = splnet();
439 LIST_REMOVE(ifv, ifv_list);
440 if (ifv->lh_cookie != NULL)
441 hook_disestablish(p->if_linkstatehooks, ifv->lh_cookie);
442
443 if (ifv->dh_cookie != NULL)
444 hook_disestablish(p->if_detachhooks, ifv->dh_cookie);
445 splx(s);
446
447
448
449
450
451
452
453 vlan_ether_purgemulti(ifv);
454
455
456 ifv->ifv_p = NULL;
457 ifv->ifv_if.if_mtu = ETHERMTU;
458
459
460 ifa = ifnet_addrs[ifv->ifv_if.if_index];
461 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
462 sdl->sdl_type = IFT_ETHER;
463 sdl->sdl_alen = ETHER_ADDR_LEN;
464 bzero(LLADDR(sdl), ETHER_ADDR_LEN);
465 bzero(ifv->ifv_ac.ac_enaddr, ETHER_ADDR_LEN);
466
467 return 0;
468 }
469
470 void
471 vlan_vlandev_state(void *v)
472 {
473 struct ifvlan *ifv = v;
474
475 if (ifv->ifv_if.if_link_state == ifv->ifv_p->if_link_state)
476 return;
477
478 ifv->ifv_if.if_link_state = ifv->ifv_p->if_link_state;
479 ifv->ifv_if.if_baudrate = ifv->ifv_p->if_baudrate;
480 if_link_state_change(&ifv->ifv_if);
481 }
482
483 int
484 vlan_set_promisc(struct ifnet *ifp)
485 {
486 struct ifvlan *ifv = ifp->if_softc;
487 int error = 0;
488
489 if ((ifp->if_flags & IFF_PROMISC) != 0) {
490 if ((ifv->ifv_flags & IFVF_PROMISC) == 0) {
491 error = ifpromisc(ifv->ifv_p, 1);
492 if (error == 0)
493 ifv->ifv_flags |= IFVF_PROMISC;
494 }
495 } else {
496 if ((ifv->ifv_flags & IFVF_PROMISC) != 0) {
497 error = ifpromisc(ifv->ifv_p, 0);
498 if (error == 0)
499 ifv->ifv_flags &= ~IFVF_PROMISC;
500 }
501 }
502
503 return (0);
504 }
505
506 int
507 vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
508 {
509 struct proc *p = curproc;
510 struct ifaddr *ifa;
511 struct ifnet *pr;
512 struct ifreq *ifr;
513 struct ifvlan *ifv;
514 struct vlanreq vlr;
515 int error = 0, p_mtu = 0, s;
516
517 ifr = (struct ifreq *)data;
518 ifa = (struct ifaddr *)data;
519 ifv = ifp->if_softc;
520
521 switch (cmd) {
522 case SIOCSIFADDR:
523 if (ifv->ifv_p != NULL) {
524 ifp->if_flags |= IFF_UP;
525
526 switch (ifa->ifa_addr->sa_family) {
527 #ifdef INET
528 case AF_INET:
529 arp_ifinit(&ifv->ifv_ac, ifa);
530 break;
531 #endif
532 default:
533 break;
534 }
535 } else {
536 error = EINVAL;
537 }
538 break;
539
540 case SIOCGIFADDR:
541 {
542 struct sockaddr *sa;
543
544 sa = (struct sockaddr *) &ifr->ifr_data;
545 bcopy(((struct arpcom *)ifp->if_softc)->ac_enaddr,
546 (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
547 }
548 break;
549
550 case SIOCSIFMTU:
551 if (ifv->ifv_p != NULL) {
552 if (ifv->ifv_p->if_capabilities & IFCAP_VLAN_MTU)
553 p_mtu = ifv->ifv_p->if_mtu;
554 else
555 p_mtu = ifv->ifv_p->if_mtu - EVL_ENCAPLEN;
556
557 if (ifr->ifr_mtu > p_mtu || ifr->ifr_mtu < ETHERMIN)
558 error = EINVAL;
559 else
560 ifp->if_mtu = ifr->ifr_mtu;
561 } else
562 error = EINVAL;
563
564 break;
565
566 case SIOCSETVLAN:
567 if ((error = suser(p, 0)) != 0)
568 break;
569 if ((error = copyin(ifr->ifr_data, &vlr, sizeof vlr)))
570 break;
571 if (vlr.vlr_parent[0] == '\0') {
572 s = splnet();
573 vlan_unconfig(ifp);
574 if (ifp->if_flags & IFF_UP)
575 if_down(ifp);
576 ifp->if_flags &= ~IFF_RUNNING;
577 splx(s);
578 break;
579 }
580 pr = ifunit(vlr.vlr_parent);
581 if (pr == NULL) {
582 error = ENOENT;
583 break;
584 }
585
586
587
588
589 if (vlr.vlr_tag & ~EVL_VLID_MASK) {
590 error = EINVAL;
591 break;
592 }
593 error = vlan_config(ifv, pr, vlr.vlr_tag);
594 if (error)
595 break;
596 ifp->if_flags |= IFF_RUNNING;
597
598
599 vlan_set_promisc(ifp);
600 break;
601
602 case SIOCGETVLAN:
603 bzero(&vlr, sizeof vlr);
604 if (ifv->ifv_p) {
605 snprintf(vlr.vlr_parent, sizeof(vlr.vlr_parent),
606 "%s", ifv->ifv_p->if_xname);
607 vlr.vlr_tag = ifv->ifv_tag;
608 }
609 error = copyout(&vlr, ifr->ifr_data, sizeof vlr);
610 break;
611 case SIOCSETVLANPRIO:
612 if ((error = suser(p, 0)) != 0)
613 break;
614 if ((error = copyin(ifr->ifr_data, &vlr, sizeof vlr)))
615 break;
616
617
618
619
620 if (vlr.vlr_tag > EVL_PRIO_MAX) {
621 error = EINVAL;
622 break;
623 }
624 ifv->ifv_prio = vlr.vlr_tag;
625 break;
626 case SIOCGETVLANPRIO:
627 bzero(&vlr, sizeof vlr);
628 if (ifv->ifv_p)
629 strlcpy(vlr.vlr_parent, ifv->ifv_p->if_xname,
630 sizeof(vlr.vlr_parent));
631 vlr.vlr_tag = ifv->ifv_prio;
632 error = copyout(&vlr, ifr->ifr_data, sizeof vlr);
633 break;
634 case SIOCSIFFLAGS:
635
636
637
638
639 if (ifv->ifv_p != NULL)
640 error = vlan_set_promisc(ifp);
641 break;
642
643 case SIOCADDMULTI:
644 error = (ifv->ifv_p != NULL) ?
645 vlan_ether_addmulti(ifv, ifr) : EINVAL;
646 break;
647
648 case SIOCDELMULTI:
649 error = (ifv->ifv_p != NULL) ?
650 vlan_ether_delmulti(ifv, ifr) : EINVAL;
651 break;
652 default:
653 error = EINVAL;
654 }
655 return error;
656 }
657
658
659 int
660 vlan_ether_addmulti(struct ifvlan *ifv, struct ifreq *ifr)
661 {
662 struct ifnet *ifp = ifv->ifv_p;
663 struct vlan_mc_entry *mc;
664 u_int8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN];
665 int error;
666
667
668
669
670
671
672 error = ether_addmulti(ifr, (struct arpcom *)&ifv->ifv_ac);
673 if (error != ENETRESET)
674 return (error);
675
676
677
678
679
680
681 MALLOC(mc, struct vlan_mc_entry *, sizeof(struct vlan_mc_entry),
682 M_DEVBUF, M_NOWAIT);
683 if (mc == NULL) {
684 error = ENOMEM;
685 goto alloc_failed;
686 }
687
688
689
690
691
692 (void)ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi);
693 ETHER_LOOKUP_MULTI(addrlo, addrhi, &ifv->ifv_ac, mc->mc_enm);
694 memcpy(&mc->mc_addr, &ifr->ifr_addr, ifr->ifr_addr.sa_len);
695 LIST_INSERT_HEAD(&ifv->vlan_mc_listhead, mc, mc_entries);
696
697 error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)ifr);
698 if (error != 0)
699 goto ioctl_failed;
700
701 return (error);
702
703 ioctl_failed:
704 LIST_REMOVE(mc, mc_entries);
705 FREE(mc, M_DEVBUF);
706 alloc_failed:
707 (void)ether_delmulti(ifr, (struct arpcom *)&ifv->ifv_ac);
708
709 return (error);
710 }
711
712 int
713 vlan_ether_delmulti(struct ifvlan *ifv, struct ifreq *ifr)
714 {
715 struct ifnet *ifp = ifv->ifv_p;
716 struct ether_multi *enm;
717 struct vlan_mc_entry *mc;
718 u_int8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN];
719 int error;
720
721
722
723
724
725 if ((error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi)) != 0)
726 return (error);
727 ETHER_LOOKUP_MULTI(addrlo, addrhi, &ifv->ifv_ac, enm);
728 if (enm == NULL)
729 return (EINVAL);
730
731 LIST_FOREACH(mc, &ifv->vlan_mc_listhead, mc_entries)
732 if (mc->mc_enm == enm)
733 break;
734
735
736 if (mc == NULL)
737 return (EINVAL);
738
739 error = ether_delmulti(ifr, (struct arpcom *)&ifv->ifv_ac);
740 if (error != ENETRESET)
741 return (error);
742
743
744 error = (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)ifr);
745 if (error == 0) {
746
747 LIST_REMOVE(mc, mc_entries);
748 FREE(mc, M_DEVBUF);
749 } else
750 (void)ether_addmulti(ifr, (struct arpcom *)&ifv->ifv_ac);
751 return (error);
752 }
753
754
755
756
757
758 void
759 vlan_ether_purgemulti(struct ifvlan *ifv)
760 {
761 struct ifnet *ifp = ifv->ifv_p;
762 struct vlan_mc_entry *mc;
763 union {
764 struct ifreq ifreq;
765 struct {
766 char ifr_name[IFNAMSIZ];
767 struct sockaddr_storage ifr_ss;
768 } ifreq_storage;
769 } ifreq;
770 struct ifreq *ifr = &ifreq.ifreq;
771
772 memcpy(ifr->ifr_name, ifp->if_xname, IFNAMSIZ);
773 while ((mc = LIST_FIRST(&ifv->vlan_mc_listhead)) != NULL) {
774 memcpy(&ifr->ifr_addr, &mc->mc_addr, mc->mc_addr.ss_len);
775 (void)(*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)ifr);
776 LIST_REMOVE(mc, mc_entries);
777 FREE(mc, M_DEVBUF);
778 }
779 }