]> arthur.barton.de Git - netatalk.git/blob - sys/netatalk/ddp_input.c
8cb4dd56286f840ec2b37b4f442fb909b826c111
[netatalk.git] / sys / netatalk / ddp_input.c
1 /*
2  * Copyright (c) 1990,1994 Regents of The University of Michigan.
3  * All Rights Reserved.  See COPYRIGHT.
4  */
5
6 #include <sys/types.h>
7 #include <sys/param.h>
8 #include <sys/mbuf.h>
9 #include <sys/socket.h>
10 #include <sys/socketvar.h>
11 #include <sys/syslog.h>
12 #include <net/if.h>
13 #include <net/route.h>
14 #ifdef _IBMR2
15 #include <net/spl.h>
16 #endif _IBMR2
17
18 #include "at.h"
19 #include "at_var.h"
20 #include "endian.h"
21 #include "ddp.h"
22 #include "ddp_var.h"
23
24 int             ddp_forward = 1;
25 int             ddp_firewall = 0;
26 extern int      ddp_cksum;
27 extern u_short  at_cksum();
28
29 /*
30  * Could probably merge these two code segments a little better...
31  */
32 atintr()
33 {
34     struct elaphdr      *elhp, elh;
35     struct ifnet        *ifp;
36     struct mbuf         *m;
37     struct at_ifaddr    *aa;
38     int                 s;
39
40     for (;;) {
41 #ifndef _IBMR2
42         s = splimp();
43 #endif _IBMR2
44
45 #ifdef BSD4_4
46         IF_DEQUEUE( &atintrq2, m );
47 #else BSD4_4
48         IF_DEQUEUEIF( &atintrq2, m, ifp );
49 #endif BSD4_4
50
51 #ifndef _IBMR2
52         splx( s );
53 #endif _IBMR2
54
55         if ( m == 0 ) {                 /* no more queued packets */
56             break;
57         }
58
59 #ifdef BSD4_4
60         ifp = m->m_pkthdr.rcvif;
61 #endif BSD4_4
62         for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
63             if ( aa->aa_ifp == ifp && ( aa->aa_flags & AFA_PHASE2 )) {
64                 break;
65             }
66         }
67         if ( aa == NULL ) {             /* ifp not an appletalk interface */
68             m_freem( m );
69             continue;
70         }
71
72         ddp_input( m, ifp, (struct elaphdr *)NULL, 2 );
73     }
74
75     for (;;) {
76 #ifndef _IBMR2
77         s = splimp();
78 #endif _IBMR2
79
80 #ifdef BSD4_4
81         IF_DEQUEUE( &atintrq1, m );
82 #else BSD4_4
83         IF_DEQUEUEIF( &atintrq1, m, ifp );
84 #endif BSD4_4
85
86 #ifndef _IBMR2
87         splx( s );
88 #endif _IBMR2
89
90         if ( m == 0 ) {                 /* no more queued packets */
91             break;
92         }
93
94 #ifdef BSD4_4
95         ifp = m->m_pkthdr.rcvif;
96 #endif BSD4_4
97         for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
98             if ( aa->aa_ifp == ifp && ( aa->aa_flags & AFA_PHASE2 ) == 0 ) {
99                 break;
100             }
101         }
102         if ( aa == NULL ) {             /* ifp not an appletalk interface */
103             m_freem( m );
104             continue;
105         }
106
107         if ( m->m_len < SZ_ELAPHDR &&
108                 (( m = m_pullup( m, SZ_ELAPHDR )) == 0 )) {
109             ddpstat.ddps_tooshort++;
110             continue;
111         }
112
113         elhp = mtod( m, struct elaphdr *);
114         m_adj( m, SZ_ELAPHDR );
115
116         if ( elhp->el_type == ELAP_DDPEXTEND ) {
117             ddp_input( m, ifp, (struct elaphdr *)NULL, 1 );
118         } else {
119             bcopy((caddr_t)elhp, (caddr_t)&elh, SZ_ELAPHDR );
120             ddp_input( m, ifp, &elh, 1 );
121         }
122     }
123     return;
124 }
125
126 struct route    forwro;
127
128 ddp_input( m, ifp, elh, phase )
129     struct mbuf         *m;
130     struct ifnet        *ifp;
131     struct elaphdr      *elh;
132     int                 phase;
133 {
134     struct sockaddr_at  from, to;
135     struct ddpshdr      *dsh, ddps;
136     struct at_ifaddr    *aa;
137     struct ddpehdr      *deh, ddpe;
138 #ifndef BSD4_4
139     struct mbuf         *mp;
140 #endif BSD4_4
141     struct ddpcb        *ddp;
142     int                 dlen, mlen;
143     u_short             cksum;
144
145     bzero( (caddr_t)&from, sizeof( struct sockaddr_at ));
146     if ( elh ) {
147         ddpstat.ddps_short++;
148
149         if ( m->m_len < sizeof( struct ddpshdr ) &&
150                 (( m = m_pullup( m, sizeof( struct ddpshdr ))) == 0 )) {
151             ddpstat.ddps_tooshort++;
152             return;
153         }
154
155         dsh = mtod( m, struct ddpshdr *);
156         bcopy( (caddr_t)dsh, (caddr_t)&ddps, sizeof( struct ddpshdr ));
157         ddps.dsh_bytes = ntohl( ddps.dsh_bytes );
158         dlen = ddps.dsh_len;
159
160         to.sat_addr.s_net = 0;
161         to.sat_addr.s_node = elh->el_dnode;
162         to.sat_port = ddps.dsh_dport;
163         from.sat_addr.s_net = 0;
164         from.sat_addr.s_node = elh->el_snode;
165         from.sat_port = ddps.dsh_sport;
166
167         for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
168             if ( aa->aa_ifp == ifp && ( aa->aa_flags & AFA_PHASE2 ) == 0 &&
169                     ( AA_SAT( aa )->sat_addr.s_node == to.sat_addr.s_node ||
170                     to.sat_addr.s_node == ATADDR_BCAST )) {
171                 break;
172             }
173         }
174         if ( aa == NULL ) {
175             m_freem( m );
176             return;
177         }
178     } else {
179         ddpstat.ddps_long++;
180
181         if ( m->m_len < sizeof( struct ddpehdr ) &&
182                 (( m = m_pullup( m, sizeof( struct ddpehdr ))) == 0 )) {
183             ddpstat.ddps_tooshort++;
184             return;
185         }
186
187         deh = mtod( m, struct ddpehdr *);
188         bcopy( (caddr_t)deh, (caddr_t)&ddpe, sizeof( struct ddpehdr ));
189         ddpe.deh_bytes = ntohl( ddpe.deh_bytes );
190         dlen = ddpe.deh_len;
191
192         if (( cksum = ddpe.deh_sum ) == 0 ) {
193             ddpstat.ddps_nosum++;
194         }
195
196         from.sat_addr.s_net = ddpe.deh_snet;
197         from.sat_addr.s_node = ddpe.deh_snode;
198         from.sat_port = ddpe.deh_sport;
199         to.sat_addr.s_net = ddpe.deh_dnet;
200         to.sat_addr.s_node = ddpe.deh_dnode;
201         to.sat_port = ddpe.deh_dport;
202
203         if ( to.sat_addr.s_net == 0 ) {
204             for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
205                 if ( phase == 1 && ( aa->aa_flags & AFA_PHASE2 )) {
206                     continue;
207                 }
208                 if ( phase == 2 && ( aa->aa_flags & AFA_PHASE2 ) == 0 ) {
209                     continue;
210                 }
211                 if ( aa->aa_ifp == ifp &&
212                         ( AA_SAT( aa )->sat_addr.s_node == to.sat_addr.s_node ||
213                         to.sat_addr.s_node == ATADDR_BCAST ||
214                         ( ifp->if_flags & IFF_LOOPBACK ))) {
215                     break;
216                 }
217             }
218         } else {
219             for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
220                 if ( to.sat_addr.s_net == aa->aa_firstnet &&
221                         to.sat_addr.s_node == 0 ) {
222                     break;
223                 }
224                 if (( ntohs( to.sat_addr.s_net ) < ntohs( aa->aa_firstnet ) ||
225                         ntohs( to.sat_addr.s_net ) > ntohs( aa->aa_lastnet )) &&
226                         ( ntohs( to.sat_addr.s_net ) < 0xff00 ||
227                         ntohs( to.sat_addr.s_net ) > 0xfffe)) {
228                     continue;
229                 }
230                 if ( to.sat_addr.s_node != AA_SAT( aa )->sat_addr.s_node &&
231                         to.sat_addr.s_node != ATADDR_BCAST ) {
232                     continue;
233                 }
234                 break;
235             }
236         }
237     }
238
239     /*
240      * Adjust the length, removing any padding that may have been added
241      * at a link layer.  We do this before we attempt to forward a packet,
242      * possibly on a different media.
243      */
244 #ifdef BSD4_4
245     mlen = m->m_pkthdr.len;
246 #else BSD4_4
247     for ( mlen = 0, mp = m; mp; mp = mp->m_next ) {
248         mlen += mp->m_len;
249     }
250 #endif BSD4_4
251     if ( mlen < dlen ) {
252         ddpstat.ddps_toosmall++;
253         m_freem( m );
254         return;
255     }
256     if ( mlen > dlen ) {
257         m_adj( m, dlen - mlen );
258     }
259
260     /*
261      * XXX Should we deliver broadcasts locally, also, or rely on the
262      * link layer to give us a copy?  For the moment, the latter.
263      */
264     if ( aa == NULL || ( to.sat_addr.s_node == ATADDR_BCAST &&
265             aa->aa_ifp != ifp && ( ifp->if_flags & IFF_LOOPBACK ) == 0 )) {
266         if ( ddp_forward == 0 ) {
267             m_freem( m );
268             return;
269         }
270         if ( forwro.ro_rt && ( satosat( &forwro.ro_dst )->sat_addr.s_net !=
271                 to.sat_addr.s_net ||
272                 satosat( &forwro.ro_dst )->sat_addr.s_node !=
273                 to.sat_addr.s_node )) {
274 #ifdef ultrix
275             rtfree( forwro.ro_rt );
276 #else ultrix
277             RTFREE( forwro.ro_rt );
278 #endif ultrix
279             forwro.ro_rt = (struct rtentry *)0;
280         }
281         if ( forwro.ro_rt == (struct rtentry *)0 ||
282              forwro.ro_rt->rt_ifp == (struct ifnet *)0 ) {
283 #ifdef BSD4_4
284             forwro.ro_dst.sa_len = sizeof( struct sockaddr_at );
285 #endif BSD4_4
286             forwro.ro_dst.sa_family = AF_APPLETALK;
287             satosat( &forwro.ro_dst )->sat_addr.s_net = to.sat_addr.s_net;
288             satosat( &forwro.ro_dst )->sat_addr.s_node = to.sat_addr.s_node;
289             rtalloc( &forwro );
290         }
291
292         if ( to.sat_addr.s_net != satosat( &forwro.ro_dst )->sat_addr.s_net &&
293                 ddpe.deh_hops == DDP_MAXHOPS ) {
294             m_freem( m );
295             return;
296         }
297
298         if ( ddp_firewall &&
299                 ( forwro.ro_rt == NULL || ( forwro.ro_rt->rt_ifp != ifp &&
300                 forwro.ro_rt->rt_ifp != at_ifaddr->aa_ifp ))) {
301             m_freem( m );
302             return;
303         }
304
305         ddpe.deh_hops++;
306         ddpe.deh_bytes = htonl( ddpe.deh_bytes );
307         bcopy( (caddr_t)&ddpe, (caddr_t)deh, sizeof( u_short ));
308         if ( ddp_route( m, &forwro )) {
309             ddpstat.ddps_cantforward++;
310         } else {
311             ddpstat.ddps_forward++;
312         }
313         return;
314     }
315
316 #ifdef BSD4_4
317     from.sat_len = sizeof( struct sockaddr_at );
318 #endif BSD4_4
319     from.sat_family = AF_APPLETALK;
320
321     if ( elh ) {
322         m_adj( m, sizeof( struct ddpshdr ));
323     } else {
324         if ( ddp_cksum && cksum && cksum != at_cksum( m, sizeof( int ))) {
325             ddpstat.ddps_badsum++;
326             m_freem( m );
327             return;
328         }
329         m_adj( m, sizeof( struct ddpehdr ));
330     }
331
332     if (( ddp = ddp_search( &from, &to, aa )) == NULL ) {
333         m_freem( m );
334         return;
335     }
336
337     if ( sbappendaddr( &ddp->ddp_socket->so_rcv, (struct sockaddr *)&from,
338             m, (struct mbuf *)0 ) == 0 ) {
339         ddpstat.ddps_nosockspace++;
340         m_freem( m );
341         return;
342     }
343     sorwakeup( ddp->ddp_socket );
344 }
345
346 m_printm( m )
347     struct mbuf *m;
348 {
349     for (; m; m = m->m_next ) {
350         bprint( mtod( m, char * ), m->m_len );
351     }
352 }
353
354 #define BPXLEN  48
355 #define BPALEN  16
356 #include <ctype.h>
357 char    hexdig[] = "0123456789ABCDEF";
358
359 bprint( data, len )
360     char        *data;
361     int         len;
362 {
363     char        xout[ BPXLEN ], aout[ BPALEN ];
364     int         i = 0;
365
366     bzero( xout, BPXLEN );
367     bzero( aout, BPALEN );
368
369     for ( ;; ) {
370         if ( len < 1 ) {
371             if ( i != 0 ) {
372                 printf( "%s\t%s\n", xout, aout );
373             }
374             printf( "%s\n", "(end)" );
375             break;
376         }
377
378         xout[ (i*3) ] = hexdig[ ( *data & 0xf0 ) >> 4 ];
379         xout[ (i*3) + 1 ] = hexdig[ *data & 0x0f ];
380
381         if ( (u_char)*data < 0x7f && (u_char)*data > 0x20 ) {
382             aout[ i ] = *data;
383         } else {
384             aout[ i ] = '.';
385         }
386
387         xout[ (i*3) + 2 ] = ' ';
388
389         i++;
390         len--;
391         data++;
392
393         if ( i > BPALEN - 2 ) {
394             printf( "%s\t%s\n", xout, aout );
395             bzero( xout, BPXLEN );
396             bzero( aout, BPALEN );
397             i = 0;
398             continue;
399         }
400     }
401 }