1 /* $NetBSD: if_tokensubr.c,v 1.57 2009/04/18 14:58:05 tsutsui Exp $ */
4 * Copyright (c) 1982, 1989, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
31 * from: NetBSD: if_fddisubr.c,v 1.2 1995/08/19 04:35:29 cgd Exp
35 * Copyright (c) 1997-1999 The NetBSD Foundation, Inc.
36 * All rights reserved.
38 * This code is derived from software contributed to The NetBSD Foundation
39 * by Onno van der Linden.
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
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.
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.
65 * Matt Thomas. All rights reserved.
67 * Redistribution and use in source and binary forms, with or without
68 * modification, are permitted provided that the following conditions
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
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
91 * from: NetBSD: if_fddisubr.c,v 1.2 1995/08/19 04:35:29 cgd Exp
94 #include <sys/cdefs.h>
95 __KERNEL_RCSID(0, "$NetBSD: if_tokensubr.c,v 1.57 2009/04/18 14:58:05 tsutsui Exp $");
98 #include "opt_atalk.h"
100 #include "opt_gateway.h"
102 #include "bpfilter.h"
104 #include <sys/param.h>
105 #include <sys/systm.h>
106 #include <sys/kernel.h>
107 #include <sys/malloc.h>
108 #include <sys/mbuf.h>
109 #include <sys/protosw.h>
110 #include <sys/socket.h>
111 #include <sys/ioctl.h>
112 #include <sys/errno.h>
113 #include <sys/syslog.h>
118 #include <net/netisr.h>
119 #include <net/route.h>
120 #include <net/if_llc.h>
121 #include <net/if_dl.h>
122 #include <net/if_types.h>
128 #include <net/if_ether.h>
129 #include <net/if_token.h>
133 #include <netinet/ip_carp.h>
137 #include <netinet/in.h>
138 #include <netinet/in_var.h>
139 #include <netinet/if_inarp.h>
144 #include <netdnet/dn.h>
148 #include <netiso/argo_debug.h>
149 #include <netiso/iso.h>
150 #include <netiso/iso_var.h>
151 #include <netiso/iso_snpac.h>
154 #include "bpfilter.h"
156 #define senderr(e) { error = (e); goto bad;}
158 #if defined(__bsdi__) || defined(__NetBSD__)
159 #define RTALLOC1(a, b) rtalloc1(a, b)
160 #define ARPRESOLVE(a, b, c, d, e, f) arpresolve(a, b, c, d, e)
161 #define TYPEHTONS(t) (t)
162 #elif defined(__FreeBSD__)
163 #define RTALLOC1(a, b) rtalloc1(a, b, 0UL)
164 #define ARPRESOLVE(a, b, c, d, e, f) arpresolve(a, b, c, d, e, f)
165 #define TYPEHTONS(t) (htons(t))
168 #define RCF_ALLROUTES (2 << 8) | TOKEN_RCF_FRAME2 | TOKEN_RCF_BROADCAST_ALL
169 #define RCF_SINGLEROUTE (2 << 8) | TOKEN_RCF_FRAME2 | TOKEN_RCF_BROADCAST_SINGLE
171 static int token_output(struct ifnet
*, struct mbuf
*,
172 const struct sockaddr
*, struct rtentry
*);
173 static void token_input(struct ifnet
*, struct mbuf
*);
176 * Token Ring output routine.
177 * Encapsulate a packet of type family for the local net.
178 * Assumes that ifp is actually pointer to arphdr structure.
179 * XXX route info has to go into the same mbuf as the header
182 token_output(struct ifnet
*ifp0
, struct mbuf
*m0
, const struct sockaddr
*dst
,
187 u_char edst
[ISO88025_ADDR_LEN
];
190 struct mbuf
*mcopy
= NULL
;
191 struct token_header
*trh
;
193 struct arphdr
*ah
= (struct arphdr
*)ifp0
;
195 struct token_rif
*rif
= NULL
;
196 struct token_rif bcastrif
;
197 struct ifnet
*ifp
= ifp0
;
199 ALTQ_DECL(struct altq_pktattr pktattr
;)
202 if (ifp
->if_type
== IFT_CARP
) {
205 /* loop back if this is going to the carp interface */
206 if (dst
!= NULL
&& ifp0
->if_link_state
== LINK_STATE_UP
&&
207 (ifa
= ifa_ifwithaddr(dst
)) != NULL
&&
208 ifa
->ifa_ifp
== ifp0
)
209 return (looutput(ifp0
, m
, dst
, rt0
));
211 ifp
= ifp
->if_carpdev
;
212 ah
= (struct arphdr
*)ifp
;
214 if ((ifp0
->if_flags
& (IFF_UP
|IFF_RUNNING
)) !=
215 (IFF_UP
|IFF_RUNNING
))
218 #endif /* NCARP > 0 */
220 if ((ifp
->if_flags
& (IFF_UP
|IFF_RUNNING
)) != (IFF_UP
|IFF_RUNNING
))
223 if ((rt
->rt_flags
& RTF_UP
) == 0) {
224 if ((rt0
= rt
= RTALLOC1(dst
, 1)))
227 senderr(EHOSTUNREACH
);
229 if (rt
->rt_flags
& RTF_GATEWAY
) {
230 if (rt
->rt_gwroute
== 0)
232 if (((rt
= rt
->rt_gwroute
)->rt_flags
& RTF_UP
) == 0) {
233 rtfree(rt
); rt
= rt0
;
234 lookup
: rt
->rt_gwroute
= RTALLOC1(rt
->rt_gateway
, 1);
235 if ((rt
= rt
->rt_gwroute
) == 0)
236 senderr(EHOSTUNREACH
);
239 if (rt
->rt_flags
& RTF_REJECT
)
240 if (rt
->rt_rmx
.rmx_expire
== 0 ||
241 time_second
< rt
->rt_rmx
.rmx_expire
)
242 senderr(rt
== rt0
? EHOSTDOWN
: EHOSTUNREACH
);
246 * If the queueing discipline needs packet classification,
247 * do it before prepending link headers.
249 IFQ_CLASSIFY(&ifp
->if_snd
, m
, dst
->sa_family
, &pktattr
);
251 switch (dst
->sa_family
) {
255 if (m
->m_flags
& M_BCAST
) {
256 if (ifp
->if_flags
& IFF_LINK0
) {
257 if (ifp
->if_flags
& IFF_LINK1
)
258 bcastrif
.tr_rcf
= htons(RCF_ALLROUTES
);
260 bcastrif
.tr_rcf
= htons(RCF_SINGLEROUTE
);
262 riflen
= sizeof(rif
->tr_rcf
);
264 memcpy(edst
, tokenbroadcastaddr
, sizeof(edst
));
267 * XXX m->m_flags & M_MCAST IEEE802_MAP_IP_MULTICAST ??
270 if (!ARPRESOLVE(ifp
, rt
, m
, dst
, edst
, rt0
))
271 return (0); /* if not yet resolved */
272 rif
= TOKEN_RIF((struct llinfo_arp
*) rt
->rt_llinfo
);
273 riflen
= (ntohs(rif
->tr_rcf
) & TOKEN_RCF_LEN_MASK
) >> 8;
275 /* If broadcasting on a simplex interface, loopback a copy. */
276 if ((m
->m_flags
& M_BCAST
) && (ifp
->if_flags
& IFF_SIMPLEX
))
277 mcopy
= m_copy(m
, 0, (int)M_COPYALL
);
278 etype
= htons(ETHERTYPE_IP
);
282 * XXX source routing, assume m->m_data contains the useful stuff
284 ah
= mtod(m
, struct arphdr
*);
285 ah
->ar_hrd
= htons(ARPHRD_IEEE802
);
287 switch (ntohs(ah
->ar_op
)) {
288 case ARPOP_REVREQUEST
:
290 etype
= htons(ETHERTYPE_REVARP
);
296 etype
= htons(ETHERTYPE_ARP
);
299 if (m
->m_flags
& M_BCAST
) {
300 if (ifp
->if_flags
& IFF_LINK0
) {
301 if (ifp
->if_flags
& IFF_LINK1
)
302 bcastrif
.tr_rcf
= htons(RCF_ALLROUTES
);
304 bcastrif
.tr_rcf
= htons(RCF_SINGLEROUTE
);
306 riflen
= sizeof(rif
->tr_rcf
);
308 memcpy(edst
, tokenbroadcastaddr
, sizeof(edst
));
311 void *tha
= ar_tha(ah
);
314 memcpy(edst
, tha
, sizeof(edst
));
315 trh
= (struct token_header
*)M_TRHSTART(m
);
316 trh
->token_ac
= TOKEN_AC
;
317 trh
->token_fc
= TOKEN_FC
;
318 if (trh
->token_shost
[0] & TOKEN_RI_PRESENT
) {
319 struct token_rif
*trrif
;
321 trrif
= TOKEN_RIF(trh
);
322 riflen
= (ntohs(trrif
->tr_rcf
) & TOKEN_RCF_LEN_MASK
) >> 8;
324 memcpy((void *)trh
->token_dhost
, (void *)edst
,
326 memcpy((void *)trh
->token_shost
, CLLADDR(ifp
->if_sadl
),
327 sizeof(trh
->token_shost
));
329 trh
->token_shost
[0] |= TOKEN_RI_PRESENT
;
331 * compare (m->m_data - m->m_pktdat) with (sizeof(struct token_header) + riflen + ...
333 m
->m_len
+= (sizeof(*trh
) + riflen
+ LLC_SNAPFRAMELEN
);
334 m
->m_data
-= (sizeof(*trh
) + riflen
+ LLC_SNAPFRAMELEN
);
335 m
->m_pkthdr
.len
+= (sizeof(*trh
) + riflen
+ LLC_SNAPFRAMELEN
);
344 const struct sockaddr_dl
*sdl
;
346 if (rt
&& (sdl
= satocsdl(rt
->rt_gateway
)) &&
347 sdl
->sdl_family
== AF_LINK
&& sdl
->sdl_alen
> 0) {
348 memcpy(edst
, CLLADDR(sdl
), sizeof(edst
));
350 else if ((error
= iso_snparesolve(ifp
,
351 (const struct sockaddr_iso
*)dst
, (char *)edst
, &snpalen
)))
352 goto bad
; /* Not resolved */
353 /* If broadcasting on a simplex interface, loopback a copy. */
355 m
->m_flags
|= (M_BCAST
|M_MCAST
);
356 if ((m
->m_flags
& M_BCAST
) && (ifp
->if_flags
& IFF_SIMPLEX
) &&
357 (mcopy
= m_copy(m
, 0, (int)M_COPYALL
))) {
358 M_PREPEND(mcopy
, sizeof (*trh
), M_DONTWAIT
);
360 trh
= mtod(mcopy
, struct token_header
*);
362 (void *)trh
->token_dhost
, sizeof (edst
));
363 bcopy(CLLADDR(ifp
->if_sadl
),
364 (void *)trh
->token_shost
, sizeof (edst
));
367 M_PREPEND(m
, 3, M_DONTWAIT
);
371 l
= mtod(m
, struct llc
*);
372 l
->llc_dsap
= l
->llc_ssap
= LLC_ISO_LSAP
;
373 l
->llc_control
= LLC_UI
;
374 #if defined(__FreeBSD__)
377 printf("token_output: sending pkt to: ");
378 for (i
=0; i
< ISO88025_ADDR_LEN
; i
++)
379 printf("%x ", edst
[i
] & 0xff);
388 const struct ether_header
*eh
;
389 eh
= (const struct ether_header
*)dst
->sa_data
;
390 memcpy(edst
, eh
->ether_dhost
, sizeof(edst
));
392 m
->m_flags
|= (M_BCAST
|M_MCAST
);
393 etype
= TYPEHTONS(eh
->ether_type
);
394 if (m
->m_flags
& M_BCAST
) {
395 if (ifp
->if_flags
& IFF_LINK0
) {
396 if (ifp
->if_flags
& IFF_LINK1
)
397 bcastrif
.tr_rcf
= htons(RCF_ALLROUTES
);
399 bcastrif
.tr_rcf
= htons(RCF_SINGLEROUTE
);
401 riflen
= sizeof(bcastrif
.tr_rcf
);
408 printf("%s: can't handle af%d\n", ifp
->if_xname
,
410 senderr(EAFNOSUPPORT
);
415 (void) looutput(ifp
, mcopy
, dst
, rt
);
418 M_PREPEND(m
, LLC_SNAPFRAMELEN
, M_DONTWAIT
);
421 l
= mtod(m
, struct llc
*);
422 l
->llc_control
= LLC_UI
;
423 l
->llc_dsap
= l
->llc_ssap
= LLC_SNAP_LSAP
;
424 l
->llc_snap
.org_code
[0] = l
->llc_snap
.org_code
[1] =
425 l
->llc_snap
.org_code
[2] = 0;
426 memcpy((void *) &l
->llc_snap
.ether_type
, (void *) &etype
,
431 * Add local net header. If no space in first mbuf,
435 M_PREPEND(m
, (riflen
+ sizeof (*trh
)), M_DONTWAIT
);
438 trh
= mtod(m
, struct token_header
*);
439 trh
->token_ac
= TOKEN_AC
;
440 trh
->token_fc
= TOKEN_FC
;
441 memcpy((void *)trh
->token_dhost
, (void *)edst
, sizeof (edst
));
442 memcpy((void *)trh
->token_shost
, CLLADDR(ifp
->if_sadl
),
443 sizeof(trh
->token_shost
));
446 struct token_rif
*trrif
;
448 trh
->token_shost
[0] |= TOKEN_RI_PRESENT
;
449 trrif
= TOKEN_RIF(trh
);
450 memcpy(trrif
, rif
, riflen
);
457 if (ifp0
!= ifp
&& ifp0
->if_type
== IFT_CARP
) {
458 memcpy((void *)trh
->token_shost
, CLLADDR(ifp0
->if_sadl
),
459 sizeof(trh
->token_shost
));
461 #endif /* NCARP > 0 */
463 return ifq_enqueue(ifp
, m ALTQ_COMMA
ALTQ_DECL(&pktattr
));
471 * Process a received token ring packet;
472 * the packet is in the mbuf chain m with
473 * the token ring header.
476 token_input(struct ifnet
*ifp
, struct mbuf
*m
)
480 struct token_header
*trh
;
483 if ((ifp
->if_flags
& IFF_UP
) == 0) {
488 trh
= mtod(m
, struct token_header
*);
490 ifp
->if_ibytes
+= m
->m_pkthdr
.len
;
491 if (memcmp(tokenbroadcastaddr
, trh
->token_dhost
,
492 sizeof(tokenbroadcastaddr
)) == 0)
493 m
->m_flags
|= M_BCAST
;
494 else if (trh
->token_dhost
[0] & 1)
495 m
->m_flags
|= M_MCAST
;
496 if (m
->m_flags
& (M_BCAST
|M_MCAST
))
499 /* Skip past the Token Ring header and RIF. */
500 lan_hdr_len
= sizeof(struct token_header
);
501 if (trh
->token_shost
[0] & TOKEN_RI_PRESENT
) {
502 struct token_rif
*trrif
;
504 trrif
= TOKEN_RIF(trh
);
505 lan_hdr_len
+= (ntohs(trrif
->tr_rcf
) & TOKEN_RCF_LEN_MASK
) >> 8;
508 l
= (struct llc
*)(mtod(m
, uint8_t *) + lan_hdr_len
);
510 switch (l
->llc_dsap
) {
511 #if defined(INET) || defined(NS) || defined(DECNET)
515 if (l
->llc_control
!= LLC_UI
|| l
->llc_ssap
!= LLC_SNAP_LSAP
)
517 if (l
->llc_snap
.org_code
[0] != 0 ||
518 l
->llc_snap
.org_code
[1] != 0 ||
519 l
->llc_snap
.org_code
[2] != 0)
521 etype
= ntohs(l
->llc_snap
.ether_type
);
522 m_adj(m
, lan_hdr_len
+ LLC_SNAPFRAMELEN
);
524 if (ifp
->if_carp
&& ifp
->if_type
!= IFT_CARP
&&
525 (carp_input(m
, (uint8_t *)&trh
->token_shost
,
526 (uint8_t *)&trh
->token_dhost
, l
->llc_snap
.ether_type
) == 0))
528 #endif /* NCARP > 0 */
533 schednetisr(NETISR_IP
);
538 schednetisr(NETISR_ARP
);
543 case ETHERTYPE_DECNET
:
544 schednetisr(NETISR_DECNET
);
550 printf("token_input: unknown protocol 0x%x\n", etype);
557 #endif /* INET || NS || DECNET */
560 switch (l
->llc_control
) {
562 /* LLC_UI_P forbidden in class 1 service */
563 if ((l
->llc_dsap
== LLC_ISO_LSAP
) &&
564 (l
->llc_ssap
== LLC_ISO_LSAP
)) {
566 #if defined(__FreeBSD__)
568 printf("clnp packet");
571 schednetisr(NETISR_ISO
);
579 if(m
->m_len
< LLC_XID_BASIC_MINLEN
+ lan_hdr_len
)
582 l
->llc_fid
= LLC_XID_FORMAT_BASIC
;
583 l
->llc_class
= LLC_XID_CLASS_I
;
584 l
->llc_dsap
= l
->llc_ssap
= 0;
585 /* Fall through to */
590 struct ether_header
*eh
;
592 u_char c
= l
->llc_dsap
;
594 l
->llc_dsap
= l
->llc_ssap
;
596 if (m
->m_flags
& (M_BCAST
| M_MCAST
))
597 bcopy(CLLADDR(ifp
->if_sadl
),
598 (void *)trh
->token_dhost
,
600 sa
.sa_family
= AF_UNSPEC
;
601 sa
.sa_len
= sizeof(sa
);
602 eh
= (struct ether_header
*)sa
.sa_data
;
603 for (i
= 0; i
< ISO88025_ADDR_LEN
; i
++) {
604 eh
->ether_shost
[i
] = c
= trh
->token_dhost
[i
];
606 eh
->ether_dhost
[i
] = trh
->token_shost
[i
];
607 eh
->ether_shost
[i
] = c
;
610 m_adj(m
, lan_hdr_len
);
611 ifp
->if_output(ifp
, m
, &sa
, NULL
);
622 /* printf("token_input: unknown dsap 0x%x\n", l->llc_dsap); */
624 #if defined(INET) || defined(NS) || defined(DECNET) || defined(ISO)
642 * Perform common duties while attaching to interface list
645 token_ifattach(struct ifnet
*ifp
, void *lla
)
648 ifp
->if_type
= IFT_ISO88025
;
650 ifp
->if_dlt
= DLT_IEEE802
;
651 ifp
->if_mtu
= ISO88025_MTU
;
652 ifp
->if_output
= token_output
;
653 ifp
->if_input
= token_input
;
654 ifp
->if_broadcastaddr
= tokenbroadcastaddr
;
655 #ifdef IFF_NOTRAILERS
656 ifp
->if_flags
|= IFF_NOTRAILERS
;
659 if_set_sadl(ifp
, lla
, ISO88025_ADDR_LEN
, true);
662 bpfattach(ifp
, DLT_IEEE802
, sizeof(struct token_header
));
667 token_ifdetach(struct ifnet
*ifp
)
673 #if 0 /* done in if_detach() */