2 * Copyright (c) 1990,1994 Regents of The University of Michigan.
3 * All Rights Reserved. See COPYRIGHT.
5 * $FreeBSD: src/sys/netatalk/ddp_input.c,v 1.12 2000/02/13 03:31:58 peter Exp $
6 * $DragonFly: src/sys/netproto/atalk/ddp_input.c,v 1.15 2007/11/16 05:07:36 sephe Exp $
10 #include <sys/systm.h>
11 #include <sys/kernel.h>
13 #include <sys/socket.h>
14 #include <sys/socketvar.h>
16 #include <sys/thread2.h>
17 #include <sys/msgport2.h>
20 #include <net/netisr.h>
21 #include <net/route.h>
27 #include "at_extern.h"
29 static volatile int ddp_forward
= 1;
30 static volatile int ddp_firewall
= 0;
31 static struct ddpstat ddpstat
;
32 static struct route forwro
;
34 const int atintrq1_present
= 1, atintrq2_present
= 1;
36 static void ddp_input(struct mbuf
*, struct ifnet
*, struct elaphdr
*, int);
39 * Could probably merge these two code segments a little better...
42 at2intr(struct netmsg
*msg
)
44 struct mbuf
*m
= ((struct netmsg_packet
*)msg
)->nm_packet
;
47 * Phase 2 packet handling
49 ddp_input(m
, m
->m_pkthdr
.rcvif
, NULL
, 2);
50 /* msg was embedded in the mbuf, do not reply! */
54 at1intr(struct netmsg
*msg
)
56 struct mbuf
*m
= ((struct netmsg_packet
*)msg
)->nm_packet
;
57 struct elaphdr
*elhp
, elh
;
60 * Phase 1 packet handling
62 if (m
->m_len
< SZ_ELAPHDR
&& ((m
= m_pullup(m
, SZ_ELAPHDR
)) == 0)) {
63 ddpstat
.ddps_tooshort
++;
68 * This seems a little dubious, but I don't know phase 1 so leave it.
70 elhp
= mtod(m
, struct elaphdr
*);
73 if (elhp
->el_type
== ELAP_DDPEXTEND
) {
74 ddp_input(m
, m
->m_pkthdr
.rcvif
, NULL
, 1);
76 bcopy((caddr_t
)elhp
, (caddr_t
)&elh
, SZ_ELAPHDR
);
77 ddp_input(m
, m
->m_pkthdr
.rcvif
, &elh
, 1);
81 /* msg was embedded in the mbuf, do not reply! */
85 ddp_input(struct mbuf
*m
, struct ifnet
*ifp
, struct elaphdr
*elh
, int phase
)
87 struct sockaddr_at from
, to
;
88 struct ddpshdr
*dsh
, ddps
;
90 struct ddpehdr
*deh
= NULL
, ddpe
;
95 bzero( (caddr_t
)&from
, sizeof( struct sockaddr_at
));
96 bzero( (caddr_t
)&to
, sizeof( struct sockaddr_at
));
99 * Extract the information in the short header.
100 * netowrk information is defaulted to ATADDR_ANYNET
101 * and node information comes from the elh info.
102 * We must be phase 1.
104 ddpstat
.ddps_short
++;
106 if ( m
->m_len
< sizeof( struct ddpshdr
) &&
107 (( m
= m_pullup( m
, sizeof( struct ddpshdr
))) == 0 )) {
108 ddpstat
.ddps_tooshort
++;
112 dsh
= mtod( m
, struct ddpshdr
*);
113 bcopy( (caddr_t
)dsh
, (caddr_t
)&ddps
, sizeof( struct ddpshdr
));
114 ddps
.dsh_bytes
= ntohl( ddps
.dsh_bytes
);
117 to
.sat_addr
.s_net
= ATADDR_ANYNET
;
118 to
.sat_addr
.s_node
= elh
->el_dnode
;
119 to
.sat_port
= ddps
.dsh_dport
;
120 from
.sat_addr
.s_net
= ATADDR_ANYNET
;
121 from
.sat_addr
.s_node
= elh
->el_snode
;
122 from
.sat_port
= ddps
.dsh_sport
;
125 * Make sure that we point to the phase1 ifaddr info
126 * and that it's valid for this packet.
128 for ( aa
= at_ifaddr
; aa
; aa
= aa
->aa_next
) {
129 if ( (aa
->aa_ifp
== ifp
)
130 && ( (aa
->aa_flags
& AFA_PHASE2
) == 0)
131 && ( (to
.sat_addr
.s_node
== AA_SAT( aa
)->sat_addr
.s_node
)
132 || (to
.sat_addr
.s_node
== ATADDR_BCAST
))) {
137 * maybe we got a broadcast not meant for us.. ditch it.
145 * There was no 'elh' passed on. This could still be
146 * either phase1 or phase2.
147 * We have a long header, but we may be running on a phase 1 net.
148 * Extract out all the info regarding this packet's src & dst.
152 if ( m
->m_len
< sizeof( struct ddpehdr
) &&
153 (( m
= m_pullup( m
, sizeof( struct ddpehdr
))) == 0 )) {
154 ddpstat
.ddps_tooshort
++;
158 deh
= mtod( m
, struct ddpehdr
*);
159 bcopy( (caddr_t
)deh
, (caddr_t
)&ddpe
, sizeof( struct ddpehdr
));
160 ddpe
.deh_bytes
= ntohl( ddpe
.deh_bytes
);
163 if (( cksum
= ddpe
.deh_sum
) == 0 ) {
164 ddpstat
.ddps_nosum
++;
167 from
.sat_addr
.s_net
= ddpe
.deh_snet
;
168 from
.sat_addr
.s_node
= ddpe
.deh_snode
;
169 from
.sat_port
= ddpe
.deh_sport
;
170 to
.sat_addr
.s_net
= ddpe
.deh_dnet
;
171 to
.sat_addr
.s_node
= ddpe
.deh_dnode
;
172 to
.sat_port
= ddpe
.deh_dport
;
174 if ( to
.sat_addr
.s_net
== ATADDR_ANYNET
) {
176 * The TO address doesn't specify a net,
177 * So by definition it's for this net.
178 * Try find ifaddr info with the right phase,
179 * the right interface, and either to our node, a broadcast,
180 * or looped back (though that SHOULD be covered in the other
183 * XXX If we have multiple interfaces, then the first with
184 * this node number will match (which may NOT be what we want,
185 * but it's probably safe in 99.999% of cases.
187 for ( aa
= at_ifaddr
; aa
; aa
= aa
->aa_next
) {
188 if ( phase
== 1 && ( aa
->aa_flags
& AFA_PHASE2
)) {
191 if ( phase
== 2 && ( aa
->aa_flags
& AFA_PHASE2
) == 0 ) {
194 if ( (aa
->aa_ifp
== ifp
)
195 && ( (to
.sat_addr
.s_node
== AA_SAT( aa
)->sat_addr
.s_node
)
196 || (to
.sat_addr
.s_node
== ATADDR_BCAST
)
197 || (ifp
->if_flags
& IFF_LOOPBACK
))) {
203 * A destination network was given. We just try to find
204 * which ifaddr info matches it.
206 for ( aa
= at_ifaddr
; aa
; aa
= aa
->aa_next
) {
208 * This is a kludge. Accept packets that are
209 * for any router on a local netrange.
211 if ( to
.sat_addr
.s_net
== aa
->aa_firstnet
&&
212 to
.sat_addr
.s_node
== 0 ) {
216 * Don't use ifaddr info for which we are totally outside the
217 * netrange, and it's not a startup packet.
218 * Startup packets are always implicitly allowed on to
221 if ((( ntohs( to
.sat_addr
.s_net
) < ntohs( aa
->aa_firstnet
))
222 || (ntohs( to
.sat_addr
.s_net
) > ntohs( aa
->aa_lastnet
)))
223 && (( ntohs( to
.sat_addr
.s_net
) < 0xff00)
224 || (ntohs( to
.sat_addr
.s_net
) > 0xfffe ))) {
229 * Don't record a match either if we just don't have a match
230 * in the node address. This can have if the interface
231 * is in promiscuous mode for example.
233 if (( to
.sat_addr
.s_node
!= AA_SAT( aa
)->sat_addr
.s_node
)
234 && (to
.sat_addr
.s_node
!= ATADDR_BCAST
) ) {
243 * Adjust the length, removing any padding that may have been added
244 * at a link layer. We do this before we attempt to forward a packet,
245 * possibly on a different media.
247 mlen
= m
->m_pkthdr
.len
;
249 ddpstat
.ddps_toosmall
++;
254 m_adj( m
, dlen
- mlen
);
258 * If it aint for a net on any of our interfaces,
259 * or it IS for a net on a different interface than it came in on,
260 * (and it is not looped back) then consider if we should forward it.
261 * As we are not really a router this is a bit cheeky, but it may be
265 || ( (to
.sat_addr
.s_node
== ATADDR_BCAST
)
266 && (aa
->aa_ifp
!= ifp
)
267 && (( ifp
->if_flags
& IFF_LOOPBACK
) == 0 ))) {
269 * If we've explicitly disabled it, don't route anything
271 if ( ddp_forward
== 0 ) {
276 * If the cached forwarding route is still valid, use it.
279 && ( satosat(&forwro
.ro_dst
)->sat_addr
.s_net
!= to
.sat_addr
.s_net
280 || satosat(&forwro
.ro_dst
)->sat_addr
.s_node
!= to
.sat_addr
.s_node
)) {
281 RTFREE( forwro
.ro_rt
);
286 * If we don't have a cached one (any more) or it's useless,
287 * Then get a new route.
288 * XXX this could cause a 'route leak'. check this!
290 if ( forwro
.ro_rt
== NULL
291 || forwro
.ro_rt
->rt_ifp
== NULL
) {
292 forwro
.ro_dst
.sa_len
= sizeof( struct sockaddr_at
);
293 forwro
.ro_dst
.sa_family
= AF_APPLETALK
;
294 satosat(&forwro
.ro_dst
)->sat_addr
.s_net
= to
.sat_addr
.s_net
;
295 satosat(&forwro
.ro_dst
)->sat_addr
.s_node
= to
.sat_addr
.s_node
;
300 * If it's not going to get there on this hop, and it's
301 * already done too many hops, then throw it away.
303 if ( (to
.sat_addr
.s_net
!= satosat( &forwro
.ro_dst
)->sat_addr
.s_net
)
304 && (ddpe
.deh_hops
== DDP_MAXHOPS
) ) {
310 * A ddp router might use the same interface
311 * to forward the packet, which this would not effect.
312 * Don't allow packets to cross from one interface to another however.
315 && ( (forwro
.ro_rt
== NULL
)
316 || (forwro
.ro_rt
->rt_ifp
!= ifp
))) {
323 * If it was a short header then it would have not gotten here,
324 * so we can assume there is room to drop the header in.
325 * XXX what about promiscuous mode, etc...
328 ddpe
.deh_bytes
= htonl( ddpe
.deh_bytes
);
329 bcopy( (caddr_t
)&ddpe
, (caddr_t
)deh
, sizeof( u_short
)); /* XXX deh? */
330 if ( ddp_route( m
, &forwro
)) {
331 ddpstat
.ddps_cantforward
++;
333 ddpstat
.ddps_forward
++;
339 * It was for us, and we have an ifaddr to use with it.
341 from
.sat_len
= sizeof( struct sockaddr_at
);
342 from
.sat_family
= AF_APPLETALK
;
345 * We are no longer interested in the link layer.
349 m_adj( m
, sizeof( struct ddpshdr
));
351 if ( ddp_cksum
&& cksum
&& cksum
!= at_cksum( m
, sizeof( int ))) {
352 ddpstat
.ddps_badsum
++;
356 m_adj( m
, sizeof( struct ddpehdr
));
360 * Search for ddp protocol control blocks that match these
363 if (( ddp
= ddp_search( &from
, &to
, aa
)) == NULL
) {
369 * If we found one, deliver th epacket to the socket
371 if (ssb_appendaddr( &ddp
->ddp_socket
->so_rcv
, (struct sockaddr
*)&from
,
374 * If the socket is full (or similar error) dump the packet.
376 ddpstat
.ddps_nosockspace
++;
381 * And wake up whatever might be waiting for it
383 sorwakeup( ddp
->ddp_socket
);
387 /* As if we haven't got enough of this sort of think floating
388 around the kernel :) */
393 char hexdig
[] = "0123456789ABCDEF";
396 bprint(char *data
, int len
)
398 char xout
[ BPXLEN
], aout
[ BPALEN
];
401 bzero( xout
, BPXLEN
);
402 bzero( aout
, BPALEN
);
407 kprintf( "%s\t%s\n", xout
, aout
);
409 kprintf( "%s\n", "(end)" );
413 xout
[ (i
*3) ] = hexdig
[ ( *data
& 0xf0 ) >> 4 ];
414 xout
[ (i
*3) + 1 ] = hexdig
[ *data
& 0x0f ];
416 if ( (u_char
)*data
< 0x7f && (u_char
)*data
> 0x20 ) {
422 xout
[ (i
*3) + 2 ] = ' ';
428 if ( i
> BPALEN
- 2 ) {
429 kprintf( "%s\t%s\n", xout
, aout
);
430 bzero( xout
, BPXLEN
);
431 bzero( aout
, BPALEN
);
439 m_printm(struct mbuf
*m
)
441 for (; m
; m
= m
->m_next
) {
442 bprint( mtod( m
, char * ), m
->m_len
);