Line data Source code
1 : /* $OpenBSD: if_vether.c,v 1.30 2018/01/09 15:24:24 bluhm Exp $ */
2 :
3 : /*
4 : * Copyright (c) 2009 Theo de Raadt
5 : *
6 : * Permission to use, copy, modify, and distribute this software for any
7 : * purpose with or without fee is hereby granted, provided that the above
8 : * copyright notice and this permission notice appear in all copies.
9 : *
10 : * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 : * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 : */
18 :
19 : #include <sys/param.h>
20 : #include <sys/systm.h>
21 : #include <sys/mbuf.h>
22 : #include <sys/socket.h>
23 : #include <sys/sockio.h>
24 : #include <sys/ioctl.h>
25 :
26 : #include <net/if.h>
27 : #include <net/if_media.h>
28 :
29 : #include <netinet/in.h>
30 : #include <netinet/if_ether.h>
31 :
32 : #include "bpfilter.h"
33 : #if NBPFILTER > 0
34 : #include <net/bpf.h>
35 : #endif
36 :
37 : void vetherattach(int);
38 : int vetherioctl(struct ifnet *, u_long, caddr_t);
39 : void vetherstart(struct ifnet *);
40 : int vether_clone_create(struct if_clone *, int);
41 : int vether_clone_destroy(struct ifnet *);
42 : int vether_media_change(struct ifnet *);
43 : void vether_media_status(struct ifnet *, struct ifmediareq *);
44 :
45 : struct vether_softc {
46 : struct arpcom sc_ac;
47 : struct ifmedia sc_media;
48 : };
49 :
50 : struct if_clone vether_cloner =
51 : IF_CLONE_INITIALIZER("vether", vether_clone_create, vether_clone_destroy);
52 :
53 : int
54 0 : vether_media_change(struct ifnet *ifp)
55 : {
56 0 : return (0);
57 : }
58 :
59 : void
60 0 : vether_media_status(struct ifnet *ifp, struct ifmediareq *imr)
61 : {
62 0 : imr->ifm_active = IFM_ETHER | IFM_AUTO;
63 0 : imr->ifm_status = IFM_AVALID | IFM_ACTIVE;
64 0 : }
65 :
66 : void
67 0 : vetherattach(int nvether)
68 : {
69 0 : if_clone_attach(&vether_cloner);
70 0 : }
71 :
72 : int
73 0 : vether_clone_create(struct if_clone *ifc, int unit)
74 : {
75 : struct ifnet *ifp;
76 : struct vether_softc *sc;
77 :
78 0 : sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
79 0 : ifp = &sc->sc_ac.ac_if;
80 0 : snprintf(ifp->if_xname, sizeof ifp->if_xname, "vether%d", unit);
81 0 : ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
82 0 : ether_fakeaddr(ifp);
83 :
84 0 : ifp->if_softc = sc;
85 0 : ifp->if_ioctl = vetherioctl;
86 0 : ifp->if_start = vetherstart;
87 0 : IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
88 :
89 0 : ifp->if_hardmtu = ETHER_MAX_HARDMTU_LEN;
90 0 : ifp->if_capabilities = IFCAP_VLAN_MTU;
91 :
92 0 : ifmedia_init(&sc->sc_media, 0, vether_media_change,
93 : vether_media_status);
94 0 : ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL);
95 0 : ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO);
96 :
97 0 : if_attach(ifp);
98 0 : ether_ifattach(ifp);
99 0 : return (0);
100 : }
101 :
102 : int
103 0 : vether_clone_destroy(struct ifnet *ifp)
104 : {
105 0 : struct vether_softc *sc = ifp->if_softc;
106 :
107 0 : ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
108 0 : ether_ifdetach(ifp);
109 0 : if_detach(ifp);
110 0 : free(sc, M_DEVBUF, sizeof(*sc));
111 0 : return (0);
112 : }
113 :
114 : /*
115 : * The bridge has magically already done all the work for us,
116 : * and we only need to discard the packets.
117 : */
118 : void
119 0 : vetherstart(struct ifnet *ifp)
120 : {
121 : struct mbuf *m;
122 :
123 0 : for (;;) {
124 0 : IFQ_DEQUEUE(&ifp->if_snd, m);
125 0 : if (m == NULL)
126 : return;
127 :
128 : #if NBPFILTER > 0
129 0 : if (ifp->if_bpf)
130 0 : bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
131 : #endif /* NBPFILTER > 0 */
132 :
133 0 : m_freem(m);
134 : }
135 0 : }
136 :
137 : int
138 0 : vetherioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
139 : {
140 0 : struct vether_softc *sc = (struct vether_softc *)ifp->if_softc;
141 0 : struct ifreq *ifr = (struct ifreq *)data;
142 : int error = 0, link_state;
143 :
144 0 : switch (cmd) {
145 : case SIOCSIFADDR:
146 0 : ifp->if_flags |= IFF_UP;
147 : /* FALLTHROUGH */
148 :
149 : case SIOCSIFFLAGS:
150 0 : if (ifp->if_flags & IFF_UP) {
151 0 : ifp->if_flags |= IFF_RUNNING;
152 : link_state = LINK_STATE_UP;
153 0 : } else {
154 0 : ifp->if_flags &= ~IFF_RUNNING;
155 : link_state = LINK_STATE_DOWN;
156 : }
157 0 : if (ifp->if_link_state != link_state) {
158 0 : ifp->if_link_state = link_state;
159 0 : if_link_state_change(ifp);
160 0 : }
161 : break;
162 :
163 : case SIOCADDMULTI:
164 : case SIOCDELMULTI:
165 : break;
166 :
167 : case SIOCGIFMEDIA:
168 : case SIOCSIFMEDIA:
169 0 : error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
170 0 : break;
171 :
172 : default:
173 0 : error = ether_ioctl(ifp, &sc->sc_ac, cmd, data);
174 0 : }
175 0 : return (error);
176 : }
|