This source file includes following definitions.
- etherip_input
- etherip_output
- etherip_sysctl
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 #include "bridge.h"
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/mbuf.h>
34 #include <sys/socket.h>
35 #include <sys/sysctl.h>
36
37 #include <net/if.h>
38 #include <net/route.h>
39 #include <net/bpf.h>
40
41 #ifdef INET
42 #include <netinet/in.h>
43 #include <netinet/in_systm.h>
44 #include <netinet/ip.h>
45 #include <netinet/in_pcb.h>
46 #include <netinet/ip_var.h>
47 #endif
48
49 #include <netinet/ip_ether.h>
50 #include <netinet/if_ether.h>
51 #include <net/if_bridge.h>
52 #include <net/if_gif.h>
53
54 #include "gif.h"
55 #include "bpfilter.h"
56
57 #ifdef ENCDEBUG
58 #define DPRINTF(x) if (encdebug) printf x
59 #else
60 #define DPRINTF(x)
61 #endif
62
63
64
65
66
67 int etherip_allow = 0;
68
69 struct etheripstat etheripstat;
70
71
72
73
74
75
76
77
78 void
79 etherip_input(struct mbuf *m, ...)
80 {
81 union sockaddr_union ssrc, sdst;
82 struct ether_header eh;
83 int iphlen;
84 struct etherip_header eip;
85 u_int8_t v;
86 va_list ap;
87
88 #if NGIF > 0
89 struct gif_softc *sc;
90 #if NBRIDGE > 0
91 int s;
92 #endif
93 #endif
94
95 va_start(ap, m);
96 iphlen = va_arg(ap, int);
97 va_end(ap);
98
99 etheripstat.etherip_ipackets++;
100
101
102 if (!etherip_allow && (m->m_flags & (M_AUTH|M_CONF)) == 0) {
103 DPRINTF(("etherip_input(): dropped due to policy\n"));
104 etheripstat.etherip_pdrops++;
105 m_freem(m);
106 return;
107 }
108
109
110
111
112
113 if (m->m_pkthdr.len < iphlen + sizeof(struct ether_header) +
114 sizeof(struct etherip_header)) {
115 DPRINTF(("etherip_input(): encapsulated packet too short\n"));
116 etheripstat.etherip_hdrops++;
117 m_freem(m);
118 return;
119 }
120
121
122 m_copydata(m, iphlen, sizeof(struct etherip_header), (caddr_t)&eip);
123 if ((eip.eip_ver & ETHERIP_VER_VERS_MASK) != ETHERIP_VERSION) {
124 DPRINTF(("etherip_input(): received EtherIP version number "
125 "%d not suppoorted\n", (v >> 4) & 0xff));
126 etheripstat.etherip_adrops++;
127 m_freem(m);
128 return;
129 }
130
131
132
133
134
135
136 if (eip.eip_ver & ETHERIP_VER_RSVD_MASK) {
137 DPRINTF(("etherip_input(): received EtherIP invalid EtherIP "
138 "header (reserved field non-zero\n"));
139 etheripstat.etherip_adrops++;
140 m_freem(m);
141 return;
142 }
143
144
145 if (eip.eip_pad) {
146 DPRINTF(("etherip_input(): received EtherIP invalid "
147 "pad value\n"));
148 etheripstat.etherip_adrops++;
149 m_freem(m);
150 return;
151 }
152
153
154 if (m->m_len < iphlen + sizeof(struct ether_header) +
155 sizeof(struct etherip_header)) {
156 if ((m = m_pullup(m, iphlen + sizeof(struct ether_header) +
157 sizeof(struct etherip_header))) == NULL) {
158 DPRINTF(("etherip_input(): m_pullup() failed\n"));
159 etheripstat.etherip_adrops++;
160 return;
161 }
162 }
163
164
165 bzero(&ssrc, sizeof(ssrc));
166 bzero(&sdst, sizeof(sdst));
167
168 v = *mtod(m, u_int8_t *);
169 switch (v >> 4) {
170 #ifdef INET
171 case 4:
172 ssrc.sa.sa_len = sdst.sa.sa_len = sizeof(struct sockaddr_in);
173 ssrc.sa.sa_family = sdst.sa.sa_family = AF_INET;
174 m_copydata(m, offsetof(struct ip, ip_src),
175 sizeof(struct in_addr),
176 (caddr_t) &ssrc.sin.sin_addr);
177 m_copydata(m, offsetof(struct ip, ip_dst),
178 sizeof(struct in_addr),
179 (caddr_t) &sdst.sin.sin_addr);
180 break;
181 #endif
182 #ifdef INET6
183 case 6:
184 ssrc.sa.sa_len = sdst.sa.sa_len = sizeof(struct sockaddr_in6);
185 ssrc.sa.sa_family = sdst.sa.sa_family = AF_INET6;
186 m_copydata(m, offsetof(struct ip6_hdr, ip6_src),
187 sizeof(struct in6_addr),
188 (caddr_t) &ssrc.sin6.sin6_addr);
189 m_copydata(m, offsetof(struct ip6_hdr, ip6_dst),
190 sizeof(struct in6_addr),
191 (caddr_t) &sdst.sin6.sin6_addr);
192 break;
193 #endif
194 default:
195 DPRINTF(("etherip_input(): invalid protocol %d\n", v));
196 m_freem(m);
197 etheripstat.etherip_hdrops++;
198 return ;
199 }
200
201
202 m_adj(m, iphlen + sizeof(struct etherip_header));
203
204
205 etheripstat.etherip_ibytes += m->m_pkthdr.len;
206
207
208 m_copydata(m, 0, sizeof(eh), (void *) &eh);
209
210
211 m->m_flags &= ~(M_BCAST|M_MCAST|M_AUTH|M_CONF|M_AUTH_AH);
212 if (eh.ether_dhost[0] & 1) {
213 if (bcmp((caddr_t) etherbroadcastaddr,
214 (caddr_t)eh.ether_dhost, sizeof(etherbroadcastaddr)) == 0)
215 m->m_flags |= M_BCAST;
216 else
217 m->m_flags |= M_MCAST;
218 }
219
220 #if NGIF > 0
221
222 LIST_FOREACH(sc, &gif_softc_list, gif_list) {
223 if ((sc->gif_psrc == NULL) ||
224 (sc->gif_pdst == NULL) ||
225 !(sc->gif_if.if_flags & (IFF_UP|IFF_RUNNING)))
226 continue;
227
228 if (!bcmp(sc->gif_psrc, &sdst, sc->gif_psrc->sa_len) &&
229 !bcmp(sc->gif_pdst, &ssrc, sc->gif_pdst->sa_len) &&
230 sc->gif_if.if_bridge != NULL)
231 break;
232 }
233
234
235 if (sc == NULL) {
236 DPRINTF(("etherip_input(): no interface found\n"));
237 etheripstat.etherip_noifdrops++;
238 m_freem(m);
239 return;
240 }
241 #if NBPFILTER > 0
242 if (sc->gif_if.if_bpf)
243 bpf_mtap_af(sc->gif_if.if_bpf, AF_LINK, m, BPF_DIRECTION_IN);
244 #endif
245
246
247 m_adj(m, sizeof(struct ether_header));
248
249 #if NBRIDGE > 0
250
251
252
253
254
255 m->m_pkthdr.rcvif = &sc->gif_if;
256 if (m->m_flags & (M_BCAST|M_MCAST))
257 sc->gif_if.if_imcasts++;
258
259 s = splnet();
260 m = bridge_input(&sc->gif_if, &eh, m);
261 splx(s);
262 if (m == NULL)
263 return;
264 #endif
265 #endif
266
267 etheripstat.etherip_noifdrops++;
268 m_freem(m);
269 return;
270 }
271
272 int
273 etherip_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
274 int protoff)
275 {
276 #ifdef INET
277 struct ip *ipo;
278 #endif
279
280 #ifdef INET6
281 struct ip6_hdr *ip6;
282 #endif
283
284 struct etherip_header eip;
285 struct mbuf *m0;
286 ushort hlen;
287
288
289 if ((tdb->tdb_src.sa.sa_family != 0) &&
290 (tdb->tdb_src.sa.sa_family != AF_INET) &&
291 (tdb->tdb_src.sa.sa_family != AF_INET6)) {
292 DPRINTF(("etherip_output(): IP in protocol-family <%d> "
293 "attempted, aborting", tdb->tdb_src.sa.sa_family));
294 etheripstat.etherip_adrops++;
295 m_freem(m);
296 return EINVAL;
297 }
298
299 if ((tdb->tdb_dst.sa.sa_family != AF_INET) &&
300 (tdb->tdb_dst.sa.sa_family != AF_INET6)) {
301 DPRINTF(("etherip_output(): IP in protocol-family <%d> "
302 "attempted, aborting", tdb->tdb_dst.sa.sa_family));
303 etheripstat.etherip_adrops++;
304 m_freem(m);
305 return EINVAL;
306 }
307
308 if (tdb->tdb_dst.sa.sa_family != tdb->tdb_src.sa.sa_family) {
309 DPRINTF(("etherip_output(): mismatch in tunnel source and "
310 "destination address protocol families (%d/%d), aborting",
311 tdb->tdb_src.sa.sa_family, tdb->tdb_dst.sa.sa_family));
312 etheripstat.etherip_adrops++;
313 m_freem(m);
314 return EINVAL;
315 }
316
317 switch (tdb->tdb_dst.sa.sa_family) {
318 #ifdef INET
319 case AF_INET:
320 hlen = sizeof(struct ip);
321 break;
322 #endif
323 #ifdef INET6
324 case AF_INET6:
325 hlen = sizeof(struct ip6_hdr);
326 break;
327 #endif
328 default:
329 DPRINTF(("etherip_output(): unsupported tunnel protocol "
330 "family <%d>, aborting", tdb->tdb_dst.sa.sa_family));
331 etheripstat.etherip_adrops++;
332 m_freem(m);
333 return EINVAL;
334 }
335
336
337 hlen += sizeof(struct etherip_header);
338
339 if (!(m->m_flags & M_PKTHDR)) {
340 DPRINTF(("etherip_output(): mbuf is not a header\n"));
341 m_freem(m);
342 return (ENOBUFS);
343 }
344
345 MGETHDR(m0, M_DONTWAIT, MT_DATA);
346 if (m0 == NULL) {
347 DPRINTF(("etherip_output(): M_GETHDR failed\n"));
348 etheripstat.etherip_adrops++;
349 m_freem(m);
350 return ENOBUFS;
351 }
352 M_MOVE_PKTHDR(m0, m);
353 m0->m_next = m;
354 m0->m_len = hlen;
355 m0->m_pkthdr.len += hlen;
356 m = m0;
357
358
359 etheripstat.etherip_opackets++;
360 etheripstat.etherip_obytes += m->m_pkthdr.len - hlen;
361
362 switch (tdb->tdb_dst.sa.sa_family) {
363 #ifdef INET
364 case AF_INET:
365 ipo = mtod(m, struct ip *);
366
367 ipo->ip_v = IPVERSION;
368 ipo->ip_hl = 5;
369 ipo->ip_len = htons(m->m_pkthdr.len);
370 ipo->ip_ttl = ip_defttl;
371 ipo->ip_p = IPPROTO_ETHERIP;
372 ipo->ip_tos = 0;
373 ipo->ip_off = 0;
374 ipo->ip_sum = 0;
375 ipo->ip_id = htons(ip_randomid());
376
377
378
379
380
381
382 ipo->ip_src = tdb->tdb_src.sin.sin_addr;
383 ipo->ip_dst = tdb->tdb_dst.sin.sin_addr;
384 break;
385 #endif
386 #ifdef INET6
387 case AF_INET6:
388 ip6 = mtod(m, struct ip6_hdr *);
389
390 ip6->ip6_flow = 0;
391 ip6->ip6_nxt = IPPROTO_ETHERIP;
392 ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
393 ip6->ip6_vfc |= IPV6_VERSION;
394 ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6));
395 ip6->ip6_hlim = ip_defttl;
396 ip6->ip6_dst = tdb->tdb_dst.sin6.sin6_addr;
397 ip6->ip6_src = tdb->tdb_src.sin6.sin6_addr;
398 break;
399 #endif
400 }
401
402
403 eip.eip_ver = ETHERIP_VERSION & ETHERIP_VER_VERS_MASK;
404 eip.eip_pad = 0;
405 m_copyback(m, hlen - sizeof(struct etherip_header),
406 sizeof(struct etherip_header), &eip);
407
408 *mp = m;
409
410 return 0;
411 }
412
413 int
414 etherip_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
415 int *name;
416 u_int namelen;
417 void *oldp, *newp;
418 size_t *oldlenp, newlen;
419 {
420
421 if (namelen != 1)
422 return (ENOTDIR);
423
424 switch (name[0]) {
425 case ETHERIPCTL_ALLOW:
426 return (sysctl_int(oldp, oldlenp, newp, newlen,
427 ðerip_allow));
428 default:
429 return (ENOPROTOOPT);
430 }
431
432 }