if_vlan.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  1. /* $OpenBSD: if_vlan.c,v 1.135 2015/07/20 22:16:41 rzalamena Exp $ */
  2. /*
  3. * Copyright 1998 Massachusetts Institute of Technology
  4. *
  5. * Permission to use, copy, modify, and distribute this software and
  6. * its documentation for any purpose and without fee is hereby
  7. * granted, provided that both the above copyright notice and this
  8. * permission notice appear in all copies, that both the above
  9. * copyright notice and this permission notice appear in all
  10. * supporting documentation, and that the name of M.I.T. not be used
  11. * in advertising or publicity pertaining to distribution of the
  12. * software without specific, written prior permission. M.I.T. makes
  13. * no representations about the suitability of this software for any
  14. * purpose. It is provided "as is" without express or implied
  15. * warranty.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
  18. * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
  19. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  20. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
  21. * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  22. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  23. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  24. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  26. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  27. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. *
  30. * $FreeBSD: src/sys/net/if_vlan.c,v 1.16 2000/03/26 15:21:40 charnier Exp $
  31. */
  32. /*
  33. * if_vlan.c - pseudo-device driver for IEEE 802.1Q virtual LANs.
  34. * This is sort of sneaky in the implementation, since
  35. * we need to pretend to be enough of an Ethernet implementation
  36. * to make arp work. The way we do this is by telling everyone
  37. * that we are an Ethernet, and then catch the packets that
  38. * ether_output() left on our output queue when it calls
  39. * if_start(), rewrite them for use by the real outgoing interface,
  40. * and ask it to send them.
  41. *
  42. * Some devices support 802.1Q tag insertion in firmware. The
  43. * vlan interface behavior changes when the IFCAP_VLAN_HWTAGGING
  44. * capability is set on the parent. In this case, vlan_start()
  45. * will not modify the ethernet header.
  46. */
  47. #include "mpw.h"
  48. #include <sys/param.h>
  49. #include <sys/kernel.h>
  50. #include <sys/malloc.h>
  51. #include <sys/mbuf.h>
  52. #include <sys/queue.h>
  53. #include <sys/socket.h>
  54. #include <sys/sockio.h>
  55. #include <sys/systm.h>
  56. #include <net/if.h>
  57. #include <net/if_dl.h>
  58. #include <net/if_types.h>
  59. #include <netinet/in.h>
  60. #include <netinet/if_ether.h>
  61. #include <net/if_vlan_var.h>
  62. #include "bpfilter.h"
  63. #if NBPFILTER > 0
  64. #include <net/bpf.h>
  65. #endif
  66. u_long vlan_tagmask, svlan_tagmask;
  67. #define TAG_HASH_SIZE 32
  68. #define TAG_HASH(tag) (tag & vlan_tagmask)
  69. LIST_HEAD(vlan_taghash, ifvlan) *vlan_tagh, *svlan_tagh;
  70. int vlan_input(struct ifnet *, struct mbuf *);
  71. void vlan_start(struct ifnet *ifp);
  72. int vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr);
  73. int vlan_unconfig(struct ifnet *ifp, struct ifnet *newp);
  74. int vlan_config(struct ifvlan *, struct ifnet *, u_int16_t);
  75. void vlan_vlandev_state(void *);
  76. void vlanattach(int count);
  77. int vlan_set_promisc(struct ifnet *ifp);
  78. int vlan_ether_addmulti(struct ifvlan *, struct ifreq *);
  79. int vlan_ether_delmulti(struct ifvlan *, struct ifreq *);
  80. void vlan_ether_purgemulti(struct ifvlan *);
  81. void vlan_ether_resetmulti(struct ifvlan *, struct ifnet *);
  82. int vlan_clone_create(struct if_clone *, int);
  83. int vlan_clone_destroy(struct ifnet *);
  84. void vlan_ifdetach(void *);
  85. struct if_clone vlan_cloner =
  86. IF_CLONE_INITIALIZER("vlan", vlan_clone_create, vlan_clone_destroy);
  87. struct if_clone svlan_cloner =
  88. IF_CLONE_INITIALIZER("svlan", vlan_clone_create, vlan_clone_destroy);
  89. /* ARGSUSED */
  90. void
  91. vlanattach(int count)
  92. {
  93. /* Normal VLAN */
  94. vlan_tagh = hashinit(TAG_HASH_SIZE, M_DEVBUF, M_NOWAIT,
  95. &vlan_tagmask);
  96. if (vlan_tagh == NULL)
  97. panic("vlanattach: hashinit");
  98. if_clone_attach(&vlan_cloner);
  99. /* Service-VLAN for QinQ/802.1ad provider bridges */
  100. svlan_tagh = hashinit(TAG_HASH_SIZE, M_DEVBUF, M_NOWAIT,
  101. &svlan_tagmask);
  102. if (svlan_tagh == NULL)
  103. panic("vlanattach: hashinit");
  104. if_clone_attach(&svlan_cloner);
  105. }
  106. int
  107. vlan_clone_create(struct if_clone *ifc, int unit)
  108. {
  109. struct ifvlan *ifv;
  110. struct ifnet *ifp;
  111. if ((ifv = malloc(sizeof(*ifv), M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL)
  112. return (ENOMEM);
  113. LIST_INIT(&ifv->vlan_mc_listhead);
  114. ifp = &ifv->ifv_if;
  115. ifp->if_softc = ifv;
  116. snprintf(ifp->if_xname, sizeof ifp->if_xname, "%s%d", ifc->ifc_name,
  117. unit);
  118. /* NB: flags are not set here */
  119. /* NB: mtu is not set here */
  120. /* Special handling for the IEEE 802.1ad QinQ variant */
  121. if (strcmp("svlan", ifc->ifc_name) == 0)
  122. ifv->ifv_type = ETHERTYPE_QINQ;
  123. else
  124. ifv->ifv_type = ETHERTYPE_VLAN;
  125. ifp->if_start = vlan_start;
  126. ifp->if_ioctl = vlan_ioctl;
  127. IFQ_SET_MAXLEN(&ifp->if_snd, 1);
  128. IFQ_SET_READY(&ifp->if_snd);
  129. if_attach(ifp);
  130. ether_ifattach(ifp);
  131. ifp->if_hdrlen = EVL_ENCAPLEN;
  132. return (0);
  133. }
  134. int
  135. vlan_clone_destroy(struct ifnet *ifp)
  136. {
  137. struct ifvlan *ifv = ifp->if_softc;
  138. vlan_unconfig(ifp, NULL);
  139. ether_ifdetach(ifp);
  140. if_detach(ifp);
  141. free(ifv, M_DEVBUF, sizeof(*ifv));
  142. return (0);
  143. }
  144. void
  145. vlan_ifdetach(void *ptr)
  146. {
  147. struct ifvlan *ifv = ptr;
  148. vlan_clone_destroy(&ifv->ifv_if);
  149. }
  150. void
  151. vlan_start(struct ifnet *ifp)
  152. {
  153. struct ifvlan *ifv;
  154. struct ifnet *p;
  155. struct mbuf *m;
  156. uint8_t prio;
  157. ifv = ifp->if_softc;
  158. p = ifv->ifv_p;
  159. for (;;) {
  160. IFQ_DEQUEUE(&ifp->if_snd, m);
  161. if (m == NULL)
  162. break;
  163. #if NBPFILTER > 0
  164. if (ifp->if_bpf)
  165. bpf_mtap_ether(ifp->if_bpf, m, BPF_DIRECTION_OUT);
  166. #endif /* NBPFILTER > 0 */
  167. if ((p->if_flags & (IFF_UP|IFF_RUNNING)) !=
  168. (IFF_UP|IFF_RUNNING)) {
  169. IF_DROP(&p->if_snd);
  170. ifp->if_oerrors++;
  171. m_freem(m);
  172. continue;
  173. }
  174. /* IEEE 802.1p has prio 0 and 1 swapped */
  175. prio = m->m_pkthdr.pf.prio;
  176. if (prio <= 1)
  177. prio = !prio;
  178. #if NMPW > 0
  179. struct ifnet *ifpn = if_get(m->m_pkthdr.ph_ifidx);
  180. /*
  181. * If this packet came from a pseudowire it means it already
  182. * has all tags it needs, so just output it.
  183. */
  184. if (ifpn && ifpn->if_type == IFT_MPLSTUNNEL) {
  185. /* NOTHING */
  186. } else
  187. #endif /* NMPW */
  188. /*
  189. * If the underlying interface cannot do VLAN tag insertion
  190. * itself, create an encapsulation header.
  191. */
  192. if ((p->if_capabilities & IFCAP_VLAN_HWTAGGING) &&
  193. (ifv->ifv_type == ETHERTYPE_VLAN)) {
  194. m->m_pkthdr.ether_vtag = ifv->ifv_tag +
  195. (prio << EVL_PRIO_BITS);
  196. m->m_flags |= M_VLANTAG;
  197. } else {
  198. struct ether_vlan_header evh;
  199. m_copydata(m, 0, ETHER_HDR_LEN, (caddr_t)&evh);
  200. evh.evl_proto = evh.evl_encap_proto;
  201. evh.evl_encap_proto = htons(ifv->ifv_type);
  202. evh.evl_tag = htons(ifv->ifv_tag +
  203. (prio << EVL_PRIO_BITS));
  204. m_adj(m, ETHER_HDR_LEN);
  205. M_PREPEND(m, sizeof(evh), M_DONTWAIT);
  206. if (m == NULL) {
  207. ifp->if_oerrors++;
  208. continue;
  209. }
  210. m_copyback(m, 0, sizeof(evh), &evh, M_NOWAIT);
  211. m->m_flags &= ~M_VLANTAG;
  212. }
  213. if (if_enqueue(p, m)) {
  214. ifp->if_oerrors++;
  215. continue;
  216. }
  217. ifp->if_opackets++;
  218. }
  219. }
  220. /*
  221. * vlan_input() returns 1 if it has consumed the packet, 0 otherwise.
  222. */
  223. int
  224. vlan_input(struct ifnet *ifp, struct mbuf *m)
  225. {
  226. struct ifvlan *ifv;
  227. struct ether_vlan_header *evl;
  228. struct ether_header *eh;
  229. struct vlan_taghash *tagh;
  230. u_int tag;
  231. struct mbuf_list ml = MBUF_LIST_INITIALIZER();
  232. u_int16_t etype;
  233. eh = mtod(m, struct ether_header *);
  234. etype = ntohs(eh->ether_type);
  235. if (m->m_flags & M_VLANTAG) {
  236. etype = ETHERTYPE_VLAN;
  237. tagh = vlan_tagh;
  238. } else if ((etype == ETHERTYPE_VLAN) || (etype == ETHERTYPE_QINQ)) {
  239. if (m->m_len < EVL_ENCAPLEN &&
  240. (m = m_pullup(m, EVL_ENCAPLEN)) == NULL) {
  241. ifp->if_ierrors++;
  242. return (1);
  243. }
  244. evl = mtod(m, struct ether_vlan_header *);
  245. m->m_pkthdr.ether_vtag = ntohs(evl->evl_tag);
  246. tagh = etype == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh;
  247. } else {
  248. /* Skip non-VLAN packets. */
  249. return (0);
  250. }
  251. /* From now on ether_vtag is fine */
  252. tag = EVL_VLANOFTAG(m->m_pkthdr.ether_vtag);
  253. m->m_pkthdr.pf.prio = EVL_PRIOFTAG(m->m_pkthdr.ether_vtag);
  254. /* IEEE 802.1p has prio 0 and 1 swapped */
  255. if (m->m_pkthdr.pf.prio <= 1)
  256. m->m_pkthdr.pf.prio = !m->m_pkthdr.pf.prio;
  257. LIST_FOREACH(ifv, &tagh[TAG_HASH(tag)], ifv_list) {
  258. if (ifp == ifv->ifv_p && tag == ifv->ifv_tag &&
  259. etype == ifv->ifv_type)
  260. break;
  261. }
  262. if (ifv == NULL) {
  263. ifp->if_noproto++;
  264. m_freem(m);
  265. return (1);
  266. }
  267. if ((ifv->ifv_if.if_flags & (IFF_UP|IFF_RUNNING)) !=
  268. (IFF_UP|IFF_RUNNING)) {
  269. m_freem(m);
  270. return (1);
  271. }
  272. /*
  273. * Drop promiscuously received packets if we are not in
  274. * promiscuous mode.
  275. */
  276. if (!ETHER_IS_MULTICAST(eh->ether_dhost) &&
  277. (ifp->if_flags & IFF_PROMISC) &&
  278. (ifv->ifv_if.if_flags & IFF_PROMISC) == 0) {
  279. if (bcmp(&ifv->ifv_ac.ac_enaddr, eh->ether_dhost,
  280. ETHER_ADDR_LEN)) {
  281. m_freem(m);
  282. return (1);
  283. }
  284. }
  285. /*
  286. * Having found a valid vlan interface corresponding to
  287. * the given source interface and vlan tag, remove the
  288. * encapsulation.
  289. */
  290. if (m->m_flags & M_VLANTAG) {
  291. m->m_flags &= ~M_VLANTAG;
  292. } else {
  293. eh->ether_type = evl->evl_proto;
  294. memmove((char *)eh + EVL_ENCAPLEN, eh, sizeof(*eh));
  295. m_adj(m, EVL_ENCAPLEN);
  296. }
  297. ml_enqueue(&ml, m);
  298. if_input(&ifv->ifv_if, &ml);
  299. return (1);
  300. }
  301. int
  302. vlan_config(struct ifvlan *ifv, struct ifnet *p, u_int16_t tag)
  303. {
  304. struct sockaddr_dl *sdl1, *sdl2;
  305. struct vlan_taghash *tagh;
  306. u_int flags;
  307. int s;
  308. if (p->if_type != IFT_ETHER)
  309. return EPROTONOSUPPORT;
  310. if (ifv->ifv_p == p && ifv->ifv_tag == tag) /* noop */
  311. return (0);
  312. /* Can we share an ifih between multiple vlan(4) instances? */
  313. ifv->ifv_ifih = SLIST_FIRST(&p->if_inputs);
  314. if (ifv->ifv_ifih->ifih_input != vlan_input) {
  315. ifv->ifv_ifih = malloc(sizeof(*ifv->ifv_ifih), M_DEVBUF,
  316. M_NOWAIT);
  317. if (ifv->ifv_ifih == NULL)
  318. return (ENOMEM);
  319. ifv->ifv_ifih->ifih_input = vlan_input;
  320. ifv->ifv_ifih->ifih_refcnt = 0;
  321. }
  322. /* Remember existing interface flags and reset the interface */
  323. flags = ifv->ifv_flags;
  324. vlan_unconfig(&ifv->ifv_if, p);
  325. ifv->ifv_p = p;
  326. ifv->ifv_if.if_baudrate = p->if_baudrate;
  327. if (p->if_capabilities & IFCAP_VLAN_MTU) {
  328. ifv->ifv_if.if_mtu = p->if_mtu;
  329. ifv->ifv_if.if_hardmtu = p->if_hardmtu;
  330. } else {
  331. ifv->ifv_if.if_mtu = p->if_mtu - EVL_ENCAPLEN;
  332. ifv->ifv_if.if_hardmtu = p->if_hardmtu - EVL_ENCAPLEN;
  333. }
  334. ifv->ifv_if.if_flags = p->if_flags &
  335. (IFF_UP | IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST);
  336. /* Reset promisc mode on the interface and its parent */
  337. if (flags & IFVF_PROMISC) {
  338. ifv->ifv_if.if_flags |= IFF_PROMISC;
  339. vlan_set_promisc(&ifv->ifv_if);
  340. }
  341. /*
  342. * If the parent interface can do hardware-assisted
  343. * VLAN encapsulation, then propagate its hardware-
  344. * assisted checksumming flags.
  345. *
  346. * If the card cannot handle hardware tagging, it cannot
  347. * possibly compute the correct checksums for tagged packets.
  348. */
  349. if (p->if_capabilities & IFCAP_VLAN_HWTAGGING)
  350. ifv->ifv_if.if_capabilities = p->if_capabilities &
  351. IFCAP_CSUM_MASK;
  352. /*
  353. * Hardware VLAN tagging only works with the default VLAN
  354. * ethernet type (0x8100).
  355. */
  356. if (ifv->ifv_type != ETHERTYPE_VLAN)
  357. ifv->ifv_if.if_capabilities &= ~IFCAP_VLAN_HWTAGGING;
  358. /*
  359. * Set up our ``Ethernet address'' to reflect the underlying
  360. * physical interface's.
  361. */
  362. sdl1 = ifv->ifv_if.if_sadl;
  363. sdl2 = p->if_sadl;
  364. sdl1->sdl_type = IFT_ETHER;
  365. sdl1->sdl_alen = ETHER_ADDR_LEN;
  366. bcopy(LLADDR(sdl2), LLADDR(sdl1), ETHER_ADDR_LEN);
  367. bcopy(LLADDR(sdl2), ifv->ifv_ac.ac_enaddr, ETHER_ADDR_LEN);
  368. ifv->ifv_tag = tag;
  369. /* Register callback for physical link state changes */
  370. ifv->lh_cookie = hook_establish(p->if_linkstatehooks, 1,
  371. vlan_vlandev_state, ifv);
  372. /* Register callback if parent wants to unregister */
  373. ifv->dh_cookie = hook_establish(p->if_detachhooks, 0,
  374. vlan_ifdetach, ifv);
  375. vlan_vlandev_state(ifv);
  376. tagh = ifv->ifv_type == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh;
  377. s = splnet();
  378. /* Change input handler of the physical interface. */
  379. if (++ifv->ifv_ifih->ifih_refcnt == 1)
  380. SLIST_INSERT_HEAD(&p->if_inputs, ifv->ifv_ifih, ifih_next);
  381. LIST_INSERT_HEAD(&tagh[TAG_HASH(tag)], ifv, ifv_list);
  382. splx(s);
  383. return (0);
  384. }
  385. int
  386. vlan_unconfig(struct ifnet *ifp, struct ifnet *newp)
  387. {
  388. struct sockaddr_dl *sdl;
  389. struct ifvlan *ifv;
  390. struct ifnet *p;
  391. int s;
  392. ifv = ifp->if_softc;
  393. if ((p = ifv->ifv_p) == NULL)
  394. return 0;
  395. /* Unset promisc mode on the interface and its parent */
  396. if (ifv->ifv_flags & IFVF_PROMISC) {
  397. ifp->if_flags &= ~IFF_PROMISC;
  398. vlan_set_promisc(ifp);
  399. }
  400. s = splnet();
  401. LIST_REMOVE(ifv, ifv_list);
  402. /* Restore previous input handler. */
  403. if (--ifv->ifv_ifih->ifih_refcnt == 0) {
  404. SLIST_REMOVE(&p->if_inputs, ifv->ifv_ifih, ifih, ifih_next);
  405. free(ifv->ifv_ifih, M_DEVBUF, sizeof(*ifv->ifv_ifih));
  406. }
  407. splx(s);
  408. hook_disestablish(p->if_linkstatehooks, ifv->lh_cookie);
  409. hook_disestablish(p->if_detachhooks, ifv->dh_cookie);
  410. /* Reset link state */
  411. if (newp != NULL) {
  412. ifp->if_link_state = LINK_STATE_INVALID;
  413. if_link_state_change(ifp);
  414. }
  415. /*
  416. * Since the interface is being unconfigured, we need to
  417. * empty the list of multicast groups that we may have joined
  418. * while we were alive and remove them from the parent's list
  419. * as well.
  420. */
  421. vlan_ether_resetmulti(ifv, newp);
  422. /* Disconnect from parent. */
  423. ifv->ifv_p = NULL;
  424. ifv->ifv_if.if_mtu = ETHERMTU;
  425. ifv->ifv_if.if_hardmtu = ETHERMTU;
  426. ifv->ifv_flags = 0;
  427. /* Clear our MAC address. */
  428. sdl = ifv->ifv_if.if_sadl;
  429. sdl->sdl_type = IFT_ETHER;
  430. sdl->sdl_alen = ETHER_ADDR_LEN;
  431. bzero(LLADDR(sdl), ETHER_ADDR_LEN);
  432. bzero(ifv->ifv_ac.ac_enaddr, ETHER_ADDR_LEN);
  433. return (0);
  434. }
  435. void
  436. vlan_vlandev_state(void *v)
  437. {
  438. struct ifvlan *ifv = v;
  439. if (ifv->ifv_if.if_link_state == ifv->ifv_p->if_link_state)
  440. return;
  441. ifv->ifv_if.if_link_state = ifv->ifv_p->if_link_state;
  442. ifv->ifv_if.if_baudrate = ifv->ifv_p->if_baudrate;
  443. if_link_state_change(&ifv->ifv_if);
  444. }
  445. int
  446. vlan_set_promisc(struct ifnet *ifp)
  447. {
  448. struct ifvlan *ifv = ifp->if_softc;
  449. int error = 0;
  450. if ((ifp->if_flags & IFF_PROMISC) != 0) {
  451. if ((ifv->ifv_flags & IFVF_PROMISC) == 0)
  452. if ((error = ifpromisc(ifv->ifv_p, 1)) == 0)
  453. ifv->ifv_flags |= IFVF_PROMISC;
  454. } else {
  455. if ((ifv->ifv_flags & IFVF_PROMISC) != 0)
  456. if ((error = ifpromisc(ifv->ifv_p, 0)) == 0)
  457. ifv->ifv_flags &= ~IFVF_PROMISC;
  458. }
  459. return (0);
  460. }
  461. int
  462. vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  463. {
  464. struct proc *p = curproc; /* XXX */
  465. struct ifaddr *ifa;
  466. struct ifnet *pr;
  467. struct ifreq *ifr;
  468. struct ifvlan *ifv;
  469. struct vlanreq vlr;
  470. int error = 0, s;
  471. ifr = (struct ifreq *)data;
  472. ifa = (struct ifaddr *)data;
  473. ifv = ifp->if_softc;
  474. switch (cmd) {
  475. case SIOCSIFADDR:
  476. if (ifv->ifv_p != NULL) {
  477. ifp->if_flags |= IFF_UP;
  478. if (ifa->ifa_addr->sa_family == AF_INET)
  479. arp_ifinit(&ifv->ifv_ac, ifa);
  480. } else
  481. error = EINVAL;
  482. break;
  483. case SIOCGIFADDR:
  484. {
  485. struct sockaddr *sa;
  486. sa = (struct sockaddr *)&ifr->ifr_data;
  487. bcopy(((struct arpcom *)ifp->if_softc)->ac_enaddr,
  488. (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
  489. }
  490. break;
  491. case SIOCSIFMTU:
  492. if (ifv->ifv_p != NULL) {
  493. if (ifr->ifr_mtu < ETHERMIN ||
  494. ifr->ifr_mtu > ifv->ifv_if.if_hardmtu)
  495. error = EINVAL;
  496. else
  497. ifp->if_mtu = ifr->ifr_mtu;
  498. } else
  499. error = EINVAL;
  500. break;
  501. case SIOCSETVLAN:
  502. if ((error = suser(p, 0)) != 0)
  503. break;
  504. if ((error = copyin(ifr->ifr_data, &vlr, sizeof vlr)))
  505. break;
  506. if (vlr.vlr_parent[0] == '\0') {
  507. s = splnet();
  508. vlan_unconfig(ifp, NULL);
  509. if (ifp->if_flags & IFF_UP)
  510. if_down(ifp);
  511. ifp->if_flags &= ~IFF_RUNNING;
  512. splx(s);
  513. break;
  514. }
  515. pr = ifunit(vlr.vlr_parent);
  516. if (pr == NULL) {
  517. error = ENOENT;
  518. break;
  519. }
  520. /*
  521. * Don't let the caller set up a VLAN tag with
  522. * anything except VLID bits.
  523. */
  524. if (vlr.vlr_tag & ~EVL_VLID_MASK) {
  525. error = EINVAL;
  526. break;
  527. }
  528. error = vlan_config(ifv, pr, vlr.vlr_tag);
  529. if (error)
  530. break;
  531. ifp->if_flags |= IFF_RUNNING;
  532. /* Update promiscuous mode, if necessary. */
  533. vlan_set_promisc(ifp);
  534. break;
  535. case SIOCGETVLAN:
  536. bzero(&vlr, sizeof vlr);
  537. if (ifv->ifv_p) {
  538. snprintf(vlr.vlr_parent, sizeof(vlr.vlr_parent),
  539. "%s", ifv->ifv_p->if_xname);
  540. vlr.vlr_tag = ifv->ifv_tag;
  541. }
  542. error = copyout(&vlr, ifr->ifr_data, sizeof vlr);
  543. break;
  544. case SIOCSIFFLAGS:
  545. /*
  546. * For promiscuous mode, we enable promiscuous mode on
  547. * the parent if we need promiscuous on the VLAN interface.
  548. */
  549. if (ifv->ifv_p != NULL)
  550. error = vlan_set_promisc(ifp);
  551. break;
  552. case SIOCADDMULTI:
  553. error = (ifv->ifv_p != NULL) ?
  554. vlan_ether_addmulti(ifv, ifr) : EINVAL;
  555. break;
  556. case SIOCDELMULTI:
  557. error = (ifv->ifv_p != NULL) ?
  558. vlan_ether_delmulti(ifv, ifr) : EINVAL;
  559. break;
  560. default:
  561. error = ENOTTY;
  562. }
  563. return error;
  564. }
  565. int
  566. vlan_ether_addmulti(struct ifvlan *ifv, struct ifreq *ifr)
  567. {
  568. struct ifnet *ifp = ifv->ifv_p;
  569. struct vlan_mc_entry *mc;
  570. u_int8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN];
  571. int error;
  572. error = ether_addmulti(ifr, (struct arpcom *)&ifv->ifv_ac);
  573. if (error != ENETRESET)
  574. return (error);
  575. /*
  576. * This is new multicast address. We have to tell parent
  577. * about it. Also, remember this multicast address so that
  578. * we can delete them on unconfigure.
  579. */
  580. if ((mc = malloc(sizeof(*mc), M_DEVBUF, M_NOWAIT)) == NULL) {
  581. error = ENOMEM;
  582. goto alloc_failed;
  583. }
  584. /*
  585. * As ether_addmulti() returns ENETRESET, following two
  586. * statement shouldn't fail.
  587. */
  588. (void)ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi);
  589. ETHER_LOOKUP_MULTI(addrlo, addrhi, &ifv->ifv_ac, mc->mc_enm);
  590. memcpy(&mc->mc_addr, &ifr->ifr_addr, ifr->ifr_addr.sa_len);
  591. LIST_INSERT_HEAD(&ifv->vlan_mc_listhead, mc, mc_entries);
  592. if ((error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)ifr)) != 0)
  593. goto ioctl_failed;
  594. return (error);
  595. ioctl_failed:
  596. LIST_REMOVE(mc, mc_entries);
  597. free(mc, M_DEVBUF, 0);
  598. alloc_failed:
  599. (void)ether_delmulti(ifr, (struct arpcom *)&ifv->ifv_ac);
  600. return (error);
  601. }
  602. int
  603. vlan_ether_delmulti(struct ifvlan *ifv, struct ifreq *ifr)
  604. {
  605. struct ifnet *ifp = ifv->ifv_p;
  606. struct ether_multi *enm;
  607. struct vlan_mc_entry *mc;
  608. u_int8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN];
  609. int error;
  610. /*
  611. * Find a key to lookup vlan_mc_entry. We have to do this
  612. * before calling ether_delmulti for obvious reason.
  613. */
  614. if ((error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi)) != 0)
  615. return (error);
  616. ETHER_LOOKUP_MULTI(addrlo, addrhi, &ifv->ifv_ac, enm);
  617. if (enm == NULL)
  618. return (EINVAL);
  619. LIST_FOREACH(mc, &ifv->vlan_mc_listhead, mc_entries)
  620. if (mc->mc_enm == enm)
  621. break;
  622. /* We won't delete entries we didn't add */
  623. if (mc == NULL)
  624. return (EINVAL);
  625. if ((error = ether_delmulti(ifr, (struct arpcom *)&ifv->ifv_ac)) != 0)
  626. return (error);
  627. /* We no longer use this multicast address. Tell parent so. */
  628. if ((error = (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)ifr)) != 0) {
  629. /* And forget about this address. */
  630. LIST_REMOVE(mc, mc_entries);
  631. free(mc, M_DEVBUF, 0);
  632. } else
  633. (void)ether_addmulti(ifr, (struct arpcom *)&ifv->ifv_ac);
  634. return (error);
  635. }
  636. /*
  637. * Delete any multicast address we have asked to add from parent
  638. * interface. Called when the vlan is being unconfigured.
  639. */
  640. void
  641. vlan_ether_purgemulti(struct ifvlan *ifv)
  642. {
  643. struct ifnet *ifp = ifv->ifv_p;
  644. struct vlan_mc_entry *mc;
  645. union {
  646. struct ifreq ifreq;
  647. struct {
  648. char ifr_name[IFNAMSIZ];
  649. struct sockaddr_storage ifr_ss;
  650. } ifreq_storage;
  651. } ifreq;
  652. struct ifreq *ifr = &ifreq.ifreq;
  653. memcpy(ifr->ifr_name, ifp->if_xname, IFNAMSIZ);
  654. while ((mc = LIST_FIRST(&ifv->vlan_mc_listhead)) != NULL) {
  655. memcpy(&ifr->ifr_addr, &mc->mc_addr, mc->mc_addr.ss_len);
  656. (void)(*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)ifr);
  657. LIST_REMOVE(mc, mc_entries);
  658. free(mc, M_DEVBUF, 0);
  659. }
  660. }
  661. void
  662. vlan_ether_resetmulti(struct ifvlan *ifv, struct ifnet *p)
  663. {
  664. struct ifnet *ifp = ifv->ifv_p;
  665. struct vlan_mc_entry *mc;
  666. union {
  667. struct ifreq ifreq;
  668. struct {
  669. char ifr_name[IFNAMSIZ];
  670. struct sockaddr_storage ifr_ss;
  671. } ifreq_storage;
  672. } ifreq;
  673. struct ifreq *ifr = &ifreq.ifreq;
  674. if (p == NULL) {
  675. vlan_ether_purgemulti(ifv);
  676. return;
  677. } else if (ifp == p)
  678. return;
  679. LIST_FOREACH(mc, &ifv->vlan_mc_listhead, mc_entries) {
  680. memcpy(&ifr->ifr_addr, &mc->mc_addr, mc->mc_addr.ss_len);
  681. /* Remove from the old parent */
  682. memcpy(ifr->ifr_name, ifp->if_xname, IFNAMSIZ);
  683. (void)(*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)ifr);
  684. /* Try to add to the new parent */
  685. memcpy(ifr->ifr_name, p->if_xname, IFNAMSIZ);
  686. (void)(*p->if_ioctl)(p, SIOCADDMULTI, (caddr_t)ifr);
  687. }
  688. }