kernel tree reorganization stage 1: Major cvs repository work (not logged as
[dragonfly.git] / sys / netproto / atalk / ddp_input.c
1 /*
2  * Copyright (c) 1990,1994 Regents of The University of Michigan.
3  * All Rights Reserved.  See COPYRIGHT.
4  *
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.3 2003/08/07 21:17:33 dillon Exp $
7  */
8
9 #include <sys/param.h>
10 #include <sys/systm.h>
11 #include <sys/kernel.h>
12 #include <net/netisr.h>
13 #include <sys/mbuf.h>
14 #include <sys/socket.h>
15 #include <sys/socketvar.h>
16 #include <net/if.h>
17 #include <net/route.h>
18 #include <net/intrq.h>
19
20 #include "at.h"
21 #include "at_var.h"
22 #include "ddp.h"
23 #include "ddp_var.h"
24 #include "at_extern.h"
25
26 static volatile int     ddp_forward = 1;
27 static volatile int     ddp_firewall = 0;
28 static struct ddpstat   ddpstat;
29 static struct route     forwro;
30
31 const int atintrq1_present = 1, atintrq2_present = 1;
32
33 static void     ddp_input(struct mbuf *, struct ifnet *, struct elaphdr *, int);
34
35 /*
36  * Could probably merge these two code segments a little better...
37  */
38 static void
39 atintr( void )
40 {
41     struct elaphdr      *elhp, elh;
42     struct ifnet        *ifp;
43     struct mbuf         *m;
44     int                 s;
45
46     /*
47      * First pull off all the phase 2 packets.
48      */
49     for (;;) {
50         s = splimp();
51
52         IF_DEQUEUE( &atintrq2, m );
53
54         splx( s );
55
56         if ( m == 0 ) {                 /* no more queued packets */
57             break;
58         }
59
60         ifp = m->m_pkthdr.rcvif;
61         ddp_input( m, ifp, (struct elaphdr *)NULL, 2 );
62     }
63
64     /*
65      * Then pull off all the phase 1 packets.
66      */
67     for (;;) {
68         s = splimp();
69
70         IF_DEQUEUE( &atintrq1, m );
71
72         splx( s );
73
74         if ( m == 0 ) {                 /* no more queued packets */
75             break;
76         }
77
78         ifp = m->m_pkthdr.rcvif;
79
80         if ( m->m_len < SZ_ELAPHDR &&
81                 (( m = m_pullup( m, SZ_ELAPHDR )) == 0 )) {
82             ddpstat.ddps_tooshort++;
83             continue;
84         }
85
86         /*
87          * this seems a little dubios, but I don't know phase 1 so leave it.
88          */
89         elhp = mtod( m, struct elaphdr *);
90         m_adj( m, SZ_ELAPHDR );
91
92         if ( elhp->el_type == ELAP_DDPEXTEND ) {
93             ddp_input( m, ifp, (struct elaphdr *)NULL, 1 );
94         } else {
95             bcopy((caddr_t)elhp, (caddr_t)&elh, SZ_ELAPHDR );
96             ddp_input( m, ifp, &elh, 1 );
97         }
98     }
99     return;
100 }
101
102 static void
103 netisr_atalk_setup(void *dummy __unused)
104 {
105         
106         register_netisr(NETISR_ATALK, atintr);
107 }
108 SYSINIT(atalk_setup, SI_SUB_CPU, SI_ORDER_ANY, netisr_atalk_setup, NULL);
109
110 static void
111 ddp_input( m, ifp, elh, phase )
112     struct mbuf         *m;
113     struct ifnet        *ifp;
114     struct elaphdr      *elh;
115     int                 phase;
116 {
117     struct sockaddr_at  from, to;
118     struct ddpshdr      *dsh, ddps;
119     struct at_ifaddr    *aa;
120     struct ddpehdr      *deh = NULL, ddpe;
121     struct ddpcb        *ddp;
122     int                 dlen, mlen;
123     u_short             cksum = 0;
124
125     bzero( (caddr_t)&from, sizeof( struct sockaddr_at ));
126     bzero( (caddr_t)&to, sizeof( struct sockaddr_at ));
127     if ( elh ) {
128         /*
129          * Extract the information in the short header.
130          * netowrk information is defaulted to ATADDR_ANYNET
131          * and node information comes from the elh info.
132          * We must be phase 1.
133          */
134         ddpstat.ddps_short++;
135
136         if ( m->m_len < sizeof( struct ddpshdr ) &&
137                 (( m = m_pullup( m, sizeof( struct ddpshdr ))) == 0 )) {
138             ddpstat.ddps_tooshort++;
139             return;
140         }
141
142         dsh = mtod( m, struct ddpshdr *);
143         bcopy( (caddr_t)dsh, (caddr_t)&ddps, sizeof( struct ddpshdr ));
144         ddps.dsh_bytes = ntohl( ddps.dsh_bytes );
145         dlen = ddps.dsh_len;
146
147         to.sat_addr.s_net = ATADDR_ANYNET;
148         to.sat_addr.s_node = elh->el_dnode;
149         to.sat_port = ddps.dsh_dport;
150         from.sat_addr.s_net = ATADDR_ANYNET;
151         from.sat_addr.s_node = elh->el_snode;
152         from.sat_port = ddps.dsh_sport;
153
154         /* 
155          * Make sure that we point to the phase1 ifaddr info 
156          * and that it's valid for this packet.
157          */
158         for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
159             if ( (aa->aa_ifp == ifp)
160             && ( (aa->aa_flags & AFA_PHASE2) == 0)
161             && ( (to.sat_addr.s_node == AA_SAT( aa )->sat_addr.s_node)
162               || (to.sat_addr.s_node == ATADDR_BCAST))) {
163                 break;
164             }
165         }
166         /* 
167          * maybe we got a broadcast not meant for us.. ditch it.
168          */
169         if ( aa == NULL ) {
170             m_freem( m );
171             return;
172         }
173     } else {
174         /*
175          * There was no 'elh' passed on. This could still be
176          * either phase1 or phase2.
177          * We have a long header, but we may be running on a phase 1 net.
178          * Extract out all the info regarding this packet's src & dst.
179          */
180         ddpstat.ddps_long++;
181
182         if ( m->m_len < sizeof( struct ddpehdr ) &&
183                 (( m = m_pullup( m, sizeof( struct ddpehdr ))) == 0 )) {
184             ddpstat.ddps_tooshort++;
185             return;
186         }
187
188         deh = mtod( m, struct ddpehdr *);
189         bcopy( (caddr_t)deh, (caddr_t)&ddpe, sizeof( struct ddpehdr ));
190         ddpe.deh_bytes = ntohl( ddpe.deh_bytes );
191         dlen = ddpe.deh_len;
192
193         if (( cksum = ddpe.deh_sum ) == 0 ) {
194             ddpstat.ddps_nosum++;
195         }
196
197         from.sat_addr.s_net = ddpe.deh_snet;
198         from.sat_addr.s_node = ddpe.deh_snode;
199         from.sat_port = ddpe.deh_sport;
200         to.sat_addr.s_net = ddpe.deh_dnet;
201         to.sat_addr.s_node = ddpe.deh_dnode;
202         to.sat_port = ddpe.deh_dport;
203
204         if ( to.sat_addr.s_net == ATADDR_ANYNET ) {
205             /*
206              * The TO address doesn't specify a net,
207              * So by definition it's for this net.
208              * Try find ifaddr info with the right phase, 
209              * the right interface, and either to our node, a broadcast,
210              * or looped back (though that SHOULD be covered in the other
211              * cases).
212              *
213              * XXX If we have multiple interfaces, then the first with
214              * this node number will match (which may NOT be what we want,
215              * but it's probably safe in 99.999% of cases.
216              */
217             for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
218                 if ( phase == 1 && ( aa->aa_flags & AFA_PHASE2 )) {
219                     continue;
220                 }
221                 if ( phase == 2 && ( aa->aa_flags & AFA_PHASE2 ) == 0 ) {
222                     continue;
223                 }
224                 if ( (aa->aa_ifp == ifp)
225                 && ( (to.sat_addr.s_node == AA_SAT( aa )->sat_addr.s_node)
226                   || (to.sat_addr.s_node == ATADDR_BCAST)
227                   || (ifp->if_flags & IFF_LOOPBACK))) {
228                     break;
229                 }
230             }
231         } else {
232             /* 
233              * A destination network was given. We just try to find 
234              * which ifaddr info matches it.
235              */
236             for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
237                 /*
238                  * This is a kludge. Accept packets that are
239                  * for any router on a local netrange.
240                  */
241                 if ( to.sat_addr.s_net == aa->aa_firstnet &&
242                         to.sat_addr.s_node == 0 ) {
243                     break;
244                 }
245                 /*
246                  * Don't use ifaddr info for which we are totally outside the
247                  * netrange, and it's not a startup packet.
248                  * Startup packets are always implicitly allowed on to
249                  * the next test.
250                  */
251                 if ((( ntohs( to.sat_addr.s_net ) < ntohs( aa->aa_firstnet ))
252                     || (ntohs( to.sat_addr.s_net ) > ntohs( aa->aa_lastnet )))
253                  && (( ntohs( to.sat_addr.s_net ) < 0xff00)
254                     || (ntohs( to.sat_addr.s_net ) > 0xfffe ))) {
255                     continue;
256                 }
257
258                 /*
259                  * Don't record a match either if we just don't have a match
260                  * in the node address. This can have if the interface
261                  * is in promiscuous mode for example.
262                  */
263                 if (( to.sat_addr.s_node != AA_SAT( aa )->sat_addr.s_node)
264                 && (to.sat_addr.s_node != ATADDR_BCAST) ) {
265                     continue;
266                 }
267                 break;
268             }
269         }
270     }
271
272     /*
273      * Adjust the length, removing any padding that may have been added
274      * at a link layer.  We do this before we attempt to forward a packet,
275      * possibly on a different media.
276      */
277     mlen = m->m_pkthdr.len;
278     if ( mlen < dlen ) {
279         ddpstat.ddps_toosmall++;
280         m_freem( m );
281         return;
282     }
283     if ( mlen > dlen ) {
284         m_adj( m, dlen - mlen );
285     }
286
287     /*
288      * If it aint for a net on any of our interfaces,
289      * or it IS for a net on a different interface than it came in on,
290      * (and it is not looped back) then consider if we should forward it.
291      * As we are not really a router this is a bit cheeky, but it may be
292      * useful some day.
293      */
294     if ( (aa == NULL)
295     || ( (to.sat_addr.s_node == ATADDR_BCAST)
296       && (aa->aa_ifp != ifp)
297       && (( ifp->if_flags & IFF_LOOPBACK ) == 0 ))) {
298         /* 
299          * If we've explicitly disabled it, don't route anything
300          */
301         if ( ddp_forward == 0 ) {
302             m_freem( m );
303             return;
304         }
305         /* 
306          * If the cached forwarding route is still valid, use it.
307          */
308         if ( forwro.ro_rt
309         && ( satosat(&forwro.ro_dst)->sat_addr.s_net != to.sat_addr.s_net
310           || satosat(&forwro.ro_dst)->sat_addr.s_node != to.sat_addr.s_node )) {
311             RTFREE( forwro.ro_rt );
312             forwro.ro_rt = (struct rtentry *)0;
313         }
314
315         /*
316          * If we don't have a cached one (any more) or it's useless,
317          * Then get a new route.
318          * XXX this could cause a 'route leak'. check this!
319          */
320         if ( forwro.ro_rt == (struct rtentry *)0
321         || forwro.ro_rt->rt_ifp == (struct ifnet *)0 ) {
322             forwro.ro_dst.sa_len = sizeof( struct sockaddr_at );
323             forwro.ro_dst.sa_family = AF_APPLETALK;
324             satosat(&forwro.ro_dst)->sat_addr.s_net = to.sat_addr.s_net;
325             satosat(&forwro.ro_dst)->sat_addr.s_node = to.sat_addr.s_node;
326             rtalloc(&forwro);
327         }
328
329         /* 
330          * If it's not going to get there on this hop, and it's
331          * already done too many hops, then throw it away.
332          */
333         if ( (to.sat_addr.s_net != satosat( &forwro.ro_dst )->sat_addr.s_net)
334         && (ddpe.deh_hops == DDP_MAXHOPS) ) {
335             m_freem( m );
336             return;
337         }
338
339         /*
340          * A ddp router might use the same interface
341          * to forward the packet, which this would not effect.
342          * Don't allow packets to cross from one interface to another however.
343          */
344         if ( ddp_firewall
345         && ( (forwro.ro_rt == NULL)
346           || (forwro.ro_rt->rt_ifp != ifp))) {
347             m_freem( m );
348             return;
349         }
350
351         /*
352          * Adjust the header.
353          * If it was a short header then it would have not gotten here,
354          * so we can assume there is room to drop the header in.
355          * XXX what about promiscuous mode, etc...
356          */
357         ddpe.deh_hops++;
358         ddpe.deh_bytes = htonl( ddpe.deh_bytes );
359         bcopy( (caddr_t)&ddpe, (caddr_t)deh, sizeof( u_short )); /* XXX deh? */
360         if ( ddp_route( m, &forwro )) {
361             ddpstat.ddps_cantforward++;
362         } else {
363             ddpstat.ddps_forward++;
364         }
365         return;
366     }
367
368     /*
369      * It was for us, and we have an ifaddr to use with it.
370      */
371     from.sat_len = sizeof( struct sockaddr_at );
372     from.sat_family = AF_APPLETALK;
373
374     /* 
375      * We are no longer interested in the link layer.
376      * so cut it off.
377      */
378     if ( elh ) {
379         m_adj( m, sizeof( struct ddpshdr ));
380     } else {
381         if ( ddp_cksum && cksum && cksum != at_cksum( m, sizeof( int ))) {
382             ddpstat.ddps_badsum++;
383             m_freem( m );
384             return;
385         }
386         m_adj( m, sizeof( struct ddpehdr ));
387     }
388
389     /* 
390      * Search for ddp protocol control blocks that match these
391      * addresses. 
392      */
393     if (( ddp = ddp_search( &from, &to, aa )) == NULL ) {
394         m_freem( m );
395         return;
396     }
397
398     /* 
399      * If we found one, deliver th epacket to the socket
400      */
401     if ( sbappendaddr( &ddp->ddp_socket->so_rcv, (struct sockaddr *)&from,
402             m, (struct mbuf *)0 ) == 0 ) {
403         /* 
404          * If the socket is full (or similar error) dump the packet.
405          */
406         ddpstat.ddps_nosockspace++;
407         m_freem( m );
408         return;
409     }
410     /*
411      * And wake up whatever might be waiting for it
412      */
413     sorwakeup( ddp->ddp_socket );
414 }
415
416 #if 0
417 /* As if we haven't got enough of this sort of think floating
418 around the kernel :) */
419
420 #define BPXLEN  48
421 #define BPALEN  16
422 #include <ctype.h>
423 char    hexdig[] = "0123456789ABCDEF";
424
425 static void
426 bprint( char *data, int len )
427 {
428     char        xout[ BPXLEN ], aout[ BPALEN ];
429     int         i = 0;
430
431     bzero( xout, BPXLEN );
432     bzero( aout, BPALEN );
433
434     for ( ;; ) {
435         if ( len < 1 ) {
436             if ( i != 0 ) {
437                 printf( "%s\t%s\n", xout, aout );
438             }
439             printf( "%s\n", "(end)" );
440             break;
441         }
442
443         xout[ (i*3) ] = hexdig[ ( *data & 0xf0 ) >> 4 ];
444         xout[ (i*3) + 1 ] = hexdig[ *data & 0x0f ];
445
446         if ( (u_char)*data < 0x7f && (u_char)*data > 0x20 ) {
447             aout[ i ] = *data;
448         } else {
449             aout[ i ] = '.';
450         }
451
452         xout[ (i*3) + 2 ] = ' ';
453
454         i++;
455         len--;
456         data++;
457
458         if ( i > BPALEN - 2 ) {
459             printf( "%s\t%s\n", xout, aout );
460             bzero( xout, BPXLEN );
461             bzero( aout, BPALEN );
462             i = 0;
463             continue;
464         }
465     }
466 }
467
468 static void
469 m_printm( struct mbuf *m )
470 {
471     for (; m; m = m->m_next ) {
472         bprint( mtod( m, char * ), m->m_len );
473     }
474 }
475 #endif