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