1 /* $NetBSD: if_tokensubr.c,v 1.76 2016/04/28 00:16:56 ozaki-r Exp $ */
2
3 /*
4 * Copyright (c) 1982, 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * from: NetBSD: if_fddisubr.c,v 1.2 1995/08/19 04:35:29 cgd Exp
32 */
33
34 /*
35 * Copyright (c) 1997-1999 The NetBSD Foundation, Inc.
36 * All rights reserved.
37 *
38 * This code is derived from software contributed to The NetBSD Foundation
39 * by Onno van der Linden.
40 *
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
51 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
52 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
54 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
55 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
56 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
57 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
58 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
59 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
60 * POSSIBILITY OF SUCH DAMAGE.
61 */
62
63 /*
64 * Copyright (c) 1995
65 * Matt Thomas. All rights reserved.
66 *
67 * Redistribution and use in source and binary forms, with or without
68 * modification, are permitted provided that the following conditions
69 * are met:
70 * 1. Redistributions of source code must retain the above copyright
71 * notice, this list of conditions and the following disclaimer.
72 * 2. Redistributions in binary form must reproduce the above copyright
73 * notice, this list of conditions and the following disclaimer in the
74 * documentation and/or other materials provided with the distribution.
75 * 3. The names of its contributors may not be used to endorse or promote
76 * products derived from this software without specific prior written
77 * permission.
78 *
79 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
80 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
81 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
82 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
83 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
84 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
85 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
86 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
87 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
88 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
89 * SUCH DAMAGE.
90 *
91 * from: NetBSD: if_fddisubr.c,v 1.2 1995/08/19 04:35:29 cgd Exp
92 */
93
94 #include <sys/cdefs.h>
95 __KERNEL_RCSID(0, "$NetBSD: if_tokensubr.c,v 1.76 2016/04/28 00:16:56 ozaki-r Exp $");
96
97 #ifdef _KERNEL_OPT
98 #include "opt_inet.h"
99 #include "opt_atalk.h"
100 #include "opt_gateway.h"
101 #endif
102
103 #include <sys/param.h>
104 #include <sys/systm.h>
105 #include <sys/kernel.h>
106 #include <sys/malloc.h>
107 #include <sys/mbuf.h>
108 #include <sys/protosw.h>
109 #include <sys/socket.h>
110 #include <sys/ioctl.h>
111 #include <sys/errno.h>
112 #include <sys/syslog.h>
113
114 #include <sys/cpu.h>
115
116 #include <net/if.h>
117 #include <net/if_dl.h>
118 #include <net/if_llatbl.h>
119 #include <net/if_llc.h>
120 #include <net/if_types.h>
121 #include <net/netisr.h>
122 #include <net/route.h>
123
124 #include <net/bpf.h>
125
126 #include <net/if_ether.h>
127 #include <net/if_token.h>
128
129 #ifdef INET
130 #include <netinet/in.h>
131 #include <netinet/in_var.h>
132 #include <netinet/if_inarp.h>
133 #endif
134
135 #include "carp.h"
136 #if NCARP > 0
137 #include <netinet/ip_carp.h>
138 #endif
139
140 #define senderr(e) { error = (e); goto bad;}
141
142 #define RCF_ALLROUTES (2 << 8) | TOKEN_RCF_FRAME2 | TOKEN_RCF_BROADCAST_ALL
143 #define RCF_SINGLEROUTE (2 << 8) | TOKEN_RCF_FRAME2 | TOKEN_RCF_BROADCAST_SINGLE
144
145 static int token_output(struct ifnet *, struct mbuf *,
146 const struct sockaddr *, const struct rtentry *);
147 static void token_input(struct ifnet *, struct mbuf *);
148
149 /*
150 * Token Ring output routine.
151 * Encapsulate a packet of type family for the local net.
152 * Assumes that ifp is actually pointer to arphdr structure.
153 * XXX route info has to go into the same mbuf as the header
154 */
155 static int
token_output(struct ifnet * ifp0,struct mbuf * m0,const struct sockaddr * dst,const struct rtentry * rt)156 token_output(struct ifnet *ifp0, struct mbuf *m0, const struct sockaddr *dst,
157 const struct rtentry *rt)
158 {
159 uint16_t etype;
160 int error = 0;
161 u_char edst[ISO88025_ADDR_LEN];
162 struct mbuf *m = m0;
163 struct mbuf *mcopy = NULL;
164 struct token_header *trh;
165 #ifdef INET
166 struct arphdr *ah = (struct arphdr *)ifp0;
167 #endif /* INET */
168 struct token_rif *rif = NULL;
169 struct token_rif bcastrif;
170 struct ifnet *ifp = ifp0;
171 size_t riflen = 0;
172
173 #if NCARP > 0
174 if (ifp->if_type == IFT_CARP) {
175 struct ifaddr *ifa;
176
177 /* loop back if this is going to the carp interface */
178 if (dst != NULL && ifp0->if_link_state == LINK_STATE_UP &&
179 (ifa = ifa_ifwithaddr(dst)) != NULL &&
180 ifa->ifa_ifp == ifp0)
181 return (looutput(ifp0, m, dst, rt));
182
183 ifp = ifp->if_carpdev;
184 ah = (struct arphdr *)ifp;
185
186 if ((ifp0->if_flags & (IFF_UP|IFF_RUNNING)) !=
187 (IFF_UP|IFF_RUNNING))
188 senderr(ENETDOWN);
189 }
190 #endif /* NCARP > 0 */
191
192 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
193 senderr(ENETDOWN);
194
195 /*
196 * If the queueing discipline needs packet classification,
197 * do it before prepending link headers.
198 */
199 IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family);
200
201 switch (dst->sa_family) {
202
203 #ifdef INET
204 case AF_INET:
205 if (m->m_flags & M_BCAST) {
206 if (ifp->if_flags & IFF_LINK0) {
207 if (ifp->if_flags & IFF_LINK1)
208 bcastrif.tr_rcf = htons(RCF_ALLROUTES);
209 else
210 bcastrif.tr_rcf = htons(RCF_SINGLEROUTE);
211 rif = &bcastrif;
212 riflen = sizeof(rif->tr_rcf);
213 }
214 memcpy(edst, tokenbroadcastaddr, sizeof(edst));
215 }
216 /*
217 * XXX m->m_flags & M_MCAST IEEE802_MAP_IP_MULTICAST ??
218 */
219 else {
220 struct llentry *la;
221 if (!arpresolve(ifp, rt, m, dst, edst, sizeof(edst)))
222 return (0); /* if not yet resolved */
223 la = rt->rt_llinfo;
224 KASSERT(la != NULL);
225 TOKEN_RIF_LLE_ASSERT(la);
226 rif = TOKEN_RIF_LLE(la);
227 riflen = (ntohs(rif->tr_rcf) & TOKEN_RCF_LEN_MASK) >> 8;
228 }
229 /* If broadcasting on a simplex interface, loopback a copy. */
230 if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
231 mcopy = m_copy(m, 0, (int)M_COPYALL);
232 etype = htons(ETHERTYPE_IP);
233 break;
234 case AF_ARP:
235 /*
236 * XXX source routing, assume m->m_data contains the useful stuff
237 */
238 ah = mtod(m, struct arphdr *);
239 ah->ar_hrd = htons(ARPHRD_IEEE802);
240
241 switch (ntohs(ah->ar_op)) {
242 case ARPOP_REVREQUEST:
243 case ARPOP_REVREPLY:
244 etype = htons(ETHERTYPE_REVARP);
245 break;
246
247 case ARPOP_REQUEST:
248 case ARPOP_REPLY:
249 default:
250 etype = htons(ETHERTYPE_ARP);
251 }
252
253 if (m->m_flags & M_BCAST) {
254 if (ifp->if_flags & IFF_LINK0) {
255 if (ifp->if_flags & IFF_LINK1)
256 bcastrif.tr_rcf = htons(RCF_ALLROUTES);
257 else
258 bcastrif.tr_rcf = htons(RCF_SINGLEROUTE);
259 rif = &bcastrif;
260 riflen = sizeof(rif->tr_rcf);
261 }
262 memcpy(edst, tokenbroadcastaddr, sizeof(edst));
263 }
264 else {
265 void *tha = ar_tha(ah);
266 if (tha == NULL)
267 return 0;
268 memcpy(edst, tha, sizeof(edst));
269 trh = (struct token_header *)M_TRHSTART(m);
270 trh->token_ac = TOKEN_AC;
271 trh->token_fc = TOKEN_FC;
272 if (trh->token_shost[0] & TOKEN_RI_PRESENT) {
273 struct token_rif *trrif;
274
275 trrif = TOKEN_RIF(trh);
276 riflen = (ntohs(trrif->tr_rcf) & TOKEN_RCF_LEN_MASK) >> 8;
277 }
278 memcpy((void *)trh->token_dhost, (void *)edst,
279 sizeof (edst));
280 memcpy((void *)trh->token_shost, CLLADDR(ifp->if_sadl),
281 sizeof(trh->token_shost));
282 if (riflen != 0)
283 trh->token_shost[0] |= TOKEN_RI_PRESENT;
284 /*
285 * compare (m->m_data - m->m_pktdat) with (sizeof(struct token_header) + riflen + ...
286 */
287 m->m_len += (sizeof(*trh) + riflen + LLC_SNAPFRAMELEN);
288 m->m_data -= (sizeof(*trh) + riflen + LLC_SNAPFRAMELEN);
289 m->m_pkthdr.len += (sizeof(*trh) + riflen + LLC_SNAPFRAMELEN);
290 goto send;
291 }
292 break;
293 #endif
294
295 case AF_UNSPEC:
296 {
297 const struct ether_header *eh;
298 eh = (const struct ether_header *)dst->sa_data;
299 memcpy(edst, eh->ether_dhost, sizeof(edst));
300 if (*edst & 1)
301 m->m_flags |= (M_BCAST|M_MCAST);
302 etype = eh->ether_type;
303 if (m->m_flags & M_BCAST) {
304 if (ifp->if_flags & IFF_LINK0) {
305 if (ifp->if_flags & IFF_LINK1)
306 bcastrif.tr_rcf = htons(RCF_ALLROUTES);
307 else
308 bcastrif.tr_rcf = htons(RCF_SINGLEROUTE);
309 rif = &bcastrif;
310 riflen = sizeof(bcastrif.tr_rcf);
311 }
312 }
313 break;
314 }
315
316 default:
317 printf("%s: can't handle af%d\n", ifp->if_xname,
318 dst->sa_family);
319 senderr(EAFNOSUPPORT);
320 }
321
322
323 if (mcopy)
324 (void) looutput(ifp, mcopy, dst, rt);
325 if (etype != 0) {
326 struct llc *l;
327 M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT);
328 if (m == 0)
329 senderr(ENOBUFS);
330 l = mtod(m, struct llc *);
331 l->llc_control = LLC_UI;
332 l->llc_dsap = l->llc_ssap = LLC_SNAP_LSAP;
333 l->llc_snap.org_code[0] = l->llc_snap.org_code[1] =
334 l->llc_snap.org_code[2] = 0;
335 memcpy((void *) &l->llc_snap.ether_type, (void *) &etype,
336 sizeof(uint16_t));
337 }
338
339 /*
340 * Add local net header. If no space in first mbuf,
341 * allocate another.
342 */
343
344 M_PREPEND(m, (riflen + sizeof (*trh)), M_DONTWAIT);
345 if (m == 0)
346 senderr(ENOBUFS);
347 trh = mtod(m, struct token_header *);
348 trh->token_ac = TOKEN_AC;
349 trh->token_fc = TOKEN_FC;
350 memcpy((void *)trh->token_dhost, (void *)edst, sizeof (edst));
351 memcpy((void *)trh->token_shost, CLLADDR(ifp->if_sadl),
352 sizeof(trh->token_shost));
353
354 if (riflen != 0) {
355 struct token_rif *trrif;
356
357 trh->token_shost[0] |= TOKEN_RI_PRESENT;
358 trrif = TOKEN_RIF(trh);
359 memcpy(trrif, rif, riflen);
360 }
361 #ifdef INET
362 send:
363 #endif
364
365 #if NCARP > 0
366 if (ifp0 != ifp && ifp0->if_type == IFT_CARP) {
367 memcpy((void *)trh->token_shost, CLLADDR(ifp0->if_sadl),
368 sizeof(trh->token_shost));
369 }
370 #endif /* NCARP > 0 */
371
372 return ifq_enqueue(ifp, m);
373 bad:
374 if (m)
375 m_freem(m);
376 return (error);
377 }
378
379 /*
380 * Process a received token ring packet;
381 * the packet is in the mbuf chain m with
382 * the token ring header.
383 */
384 static void
token_input(struct ifnet * ifp,struct mbuf * m)385 token_input(struct ifnet *ifp, struct mbuf *m)
386 {
387 pktqueue_t *pktq = NULL;
388 struct ifqueue *inq = NULL;
389 struct llc *l;
390 struct token_header *trh;
391 int s, lan_hdr_len;
392 int isr = 0;
393
394 if ((ifp->if_flags & IFF_UP) == 0) {
395 m_freem(m);
396 return;
397 }
398
399 trh = mtod(m, struct token_header *);
400
401 ifp->if_ibytes += m->m_pkthdr.len;
402 if (memcmp(tokenbroadcastaddr, trh->token_dhost,
403 sizeof(tokenbroadcastaddr)) == 0)
404 m->m_flags |= M_BCAST;
405 else if (trh->token_dhost[0] & 1)
406 m->m_flags |= M_MCAST;
407 if (m->m_flags & (M_BCAST|M_MCAST))
408 ifp->if_imcasts++;
409
410 /* Skip past the Token Ring header and RIF. */
411 lan_hdr_len = sizeof(struct token_header);
412 if (trh->token_shost[0] & TOKEN_RI_PRESENT) {
413 struct token_rif *trrif;
414
415 trrif = TOKEN_RIF(trh);
416 lan_hdr_len += (ntohs(trrif->tr_rcf) & TOKEN_RCF_LEN_MASK) >> 8;
417 }
418
419 l = (struct llc *)(mtod(m, uint8_t *) + lan_hdr_len);
420
421 switch (l->llc_dsap) {
422 #if defined(INET)
423 case LLC_SNAP_LSAP:
424 {
425 uint16_t etype;
426 if (l->llc_control != LLC_UI || l->llc_ssap != LLC_SNAP_LSAP)
427 goto dropanyway;
428 if (l->llc_snap.org_code[0] != 0 ||
429 l->llc_snap.org_code[1] != 0 ||
430 l->llc_snap.org_code[2] != 0)
431 goto dropanyway;
432 etype = ntohs(l->llc_snap.ether_type);
433 m_adj(m, lan_hdr_len + LLC_SNAPFRAMELEN);
434 #if NCARP > 0
435 if (ifp->if_carp && ifp->if_type != IFT_CARP &&
436 (carp_input(m, (uint8_t *)&trh->token_shost,
437 (uint8_t *)&trh->token_dhost, l->llc_snap.ether_type) == 0))
438 return;
439 #endif /* NCARP > 0 */
440
441 switch (etype) {
442 #ifdef INET
443 case ETHERTYPE_IP:
444 pktq = ip_pktq;
445 break;
446
447 case ETHERTYPE_ARP:
448 isr = NETISR_ARP;
449 inq = &arpintrq;
450 break;
451 #endif
452 default:
453 /*
454 printf("token_input: unknown protocol 0x%x\n", etype);
455 */
456 ifp->if_noproto++;
457 goto dropanyway;
458 }
459 break;
460 }
461 #endif /* INET */
462
463 default:
464 /* printf("token_input: unknown dsap 0x%x\n", l->llc_dsap); */
465 ifp->if_noproto++;
466 #if defined(INET)
467 dropanyway:
468 #endif
469 m_freem(m);
470 return;
471 }
472
473 if (__predict_true(pktq)) {
474 if (__predict_false(!pktq_enqueue(pktq, m, 0))) {
475 m_freem(m);
476 }
477 return;
478 }
479
480 s = splnet();
481 if (IF_QFULL(inq)) {
482 IF_DROP(inq);
483 m_freem(m);
484 } else {
485 IF_ENQUEUE(inq, m);
486 schednetisr(isr);
487 }
488 splx(s);
489 }
490
491 /*
492 * Perform common duties while attaching to interface list
493 */
494 void
token_ifattach(struct ifnet * ifp,void * lla)495 token_ifattach(struct ifnet *ifp, void *lla)
496 {
497
498 ifp->if_type = IFT_ISO88025;
499 ifp->if_hdrlen = 14;
500 ifp->if_dlt = DLT_IEEE802;
501 ifp->if_mtu = ISO88025_MTU;
502 ifp->if_output = token_output;
503 ifp->_if_input = token_input;
504 ifp->if_broadcastaddr = tokenbroadcastaddr;
505 #ifdef IFF_NOTRAILERS
506 ifp->if_flags |= IFF_NOTRAILERS;
507 #endif
508
509 if_set_sadl(ifp, lla, ISO88025_ADDR_LEN, true);
510
511 bpf_attach(ifp, DLT_IEEE802, sizeof(struct token_header));
512 }
513
514 void
token_ifdetach(struct ifnet * ifp)515 token_ifdetach(struct ifnet *ifp)
516 {
517
518 bpf_detach(ifp);
519 }
520