Annotation of sys/netatalk/ddp_input.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: ddp_input.c,v 1.4 2006/03/04 22:40:16 brad Exp $ */
2:
3: /*
4: * Copyright (c) 1990,1994 Regents of The University of Michigan.
5: * All Rights Reserved. See COPYRIGHT.
6: */
7:
8: /*
9: * The following is the contents of the COPYRIGHT file from the
10: * netatalk-1.4a2 distribution, from which this file is derived.
11: */
12: /*
13: * Copyright (c) 1990,1996 Regents of The University of Michigan.
14: *
15: * All Rights Reserved.
16: *
17: * Permission to use, copy, modify, and distribute this software and
18: * its documentation for any purpose and without fee is hereby granted,
19: * provided that the above copyright notice appears in all copies and
20: * that both that copyright notice and this permission notice appear
21: * in supporting documentation, and that the name of The University
22: * of Michigan not be used in advertising or publicity pertaining to
23: * distribution of the software without specific, written prior
24: * permission. This software is supplied as is without expressed or
25: * implied warranties of any kind.
26: *
27: * This product includes software developed by the University of
28: * California, Berkeley and its contributors.
29: *
30: * Solaris code is encumbered by the following:
31: *
32: * Copyright (C) 1996 by Sun Microsystems Computer Co.
33: *
34: * Permission to use, copy, modify, and distribute this software and
35: * its documentation for any purpose and without fee is hereby
36: * granted, provided that the above copyright notice appear in all
37: * copies and that both that copyright notice and this permission
38: * notice appear in supporting documentation. This software is
39: * provided "as is" without express or implied warranty.
40: *
41: * Research Systems Unix Group
42: * The University of Michigan
43: * c/o Wesley Craig
44: * 535 W. William Street
45: * Ann Arbor, Michigan
46: * +1-313-764-2278
47: * netatalk@umich.edu
48: */
49: /*
50: * None of the Solaris code mentioned is included in OpenBSD.
51: * This code also relies heavily on previous effort in FreeBSD and NetBSD.
52: */
53:
54: #include <sys/param.h>
55: #include <sys/systm.h>
56: #include <sys/kernel.h>
57: #include <sys/malloc.h>
58: #include <sys/mbuf.h>
59: #include <sys/protosw.h>
60: #include <sys/socket.h>
61: #include <sys/ioctl.h>
62: #include <sys/errno.h>
63: #include <sys/syslog.h>
64: #include <sys/proc.h>
65: #include <sys/socketvar.h>
66:
67: #include <net/if.h>
68: #include <net/route.h>
69:
70: #include <machine/endian.h>
71:
72: #include <netatalk/at.h>
73: #include <netatalk/at_var.h>
74: #include <netatalk/ddp.h>
75: #include <netatalk/ddp_var.h>
76: #include <netatalk/at_extern.h>
77:
78: void atintr(void);
79: void ddp_input(struct mbuf *, struct ifnet *,
80: struct elaphdr *, int);
81: #if 0
82: static void m_printm(struct mbuf *);
83: static void bprint( char *, int );
84: #endif
85:
86: int ddp_forward = 1;
87: int ddp_firewall = 0;
88: extern int ddp_cksum;
89:
90: /*
91: * Could probably merge these two code segments a little better...
92: */
93: void
94: atintr()
95: {
96: struct elaphdr *elhp, elh;
97: struct ifnet *ifp;
98: struct mbuf *m;
99: struct at_ifaddr *aa;
100: int s;
101:
102: for (;;) {
103: s = splnet();
104:
105: IF_DEQUEUE( &atintrq2, m );
106:
107: splx( s );
108:
109: if ( m == 0 ) { /* no more queued packets */
110: break;
111: }
112:
113: ifp = m->m_pkthdr.rcvif;
114: for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
115: if ( aa->aa_ifp == ifp && ( aa->aa_flags & AFA_PHASE2 )) {
116: break;
117: }
118: }
119: if ( aa == NULL ) { /* ifp not an appletalk interface */
120: m_freem( m );
121: continue;
122: }
123:
124: ddp_input( m, ifp, (struct elaphdr *)NULL, 2 );
125: }
126:
127: for (;;) {
128: s = splnet();
129:
130: IF_DEQUEUE( &atintrq1, m );
131:
132: splx( s );
133:
134: if ( m == 0 ) { /* no more queued packets */
135: break;
136: }
137:
138: ifp = m->m_pkthdr.rcvif;
139: for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
140: if ( aa->aa_ifp == ifp && ( aa->aa_flags & AFA_PHASE2 ) == 0 ) {
141: break;
142: }
143: }
144: if ( aa == NULL ) { /* ifp not an appletalk interface */
145: m_freem( m );
146: continue;
147: }
148:
149: if ( m->m_len < SZ_ELAPHDR &&
150: (( m = m_pullup( m, SZ_ELAPHDR )) == 0 )) {
151: ddpstat.ddps_tooshort++;
152: continue;
153: }
154:
155: elhp = mtod( m, struct elaphdr *);
156: m_adj( m, SZ_ELAPHDR );
157:
158: if ( elhp->el_type == ELAP_DDPEXTEND ) {
159: ddp_input( m, ifp, (struct elaphdr *)NULL, 1 );
160: } else {
161: bcopy((caddr_t)elhp, (caddr_t)&elh, SZ_ELAPHDR );
162: ddp_input( m, ifp, &elh, 1 );
163: }
164: }
165: return;
166: }
167:
168: struct route forwro;
169:
170: void
171: ddp_input( m, ifp, elh, phase )
172: struct mbuf *m;
173: struct ifnet *ifp;
174: struct elaphdr *elh;
175: int phase;
176: {
177: struct sockaddr_at from, to;
178: struct ddpshdr *dsh, ddps;
179: struct at_ifaddr *aa;
180: struct ddpehdr *deh, ddpe;
181: struct ddpcb *ddp;
182: int dlen, mlen;
183: u_int16_t cksum;
184:
185: bzero( (caddr_t)&from, sizeof( struct sockaddr_at ));
186: if ( elh ) {
187: ddpstat.ddps_short++;
188:
189: if ( m->m_len < sizeof( struct ddpshdr ) &&
190: (( m = m_pullup( m, sizeof( struct ddpshdr ))) == 0 )) {
191: ddpstat.ddps_tooshort++;
192: return;
193: }
194:
195: dsh = mtod( m, struct ddpshdr *);
196: bcopy( (caddr_t)dsh, (caddr_t)&ddps, sizeof( struct ddpshdr ));
197: ddps.dsh_bytes = ntohl( ddps.dsh_bytes );
198: dlen = ddps.dsh_len;
199:
200: to.sat_addr.s_net = 0;
201: to.sat_addr.s_node = elh->el_dnode;
202: to.sat_port = ddps.dsh_dport;
203: from.sat_addr.s_net = 0;
204: from.sat_addr.s_node = elh->el_snode;
205: from.sat_port = ddps.dsh_sport;
206:
207: for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
208: if ( aa->aa_ifp == ifp && ( aa->aa_flags & AFA_PHASE2 ) == 0 &&
209: ( AA_SAT( aa )->sat_addr.s_node == to.sat_addr.s_node ||
210: to.sat_addr.s_node == ATADDR_BCAST )) {
211: break;
212: }
213: }
214: if ( aa == NULL ) {
215: m_freem( m );
216: return;
217: }
218: } else {
219: ddpstat.ddps_long++;
220:
221: if ( m->m_len < sizeof( struct ddpehdr ) &&
222: (( m = m_pullup( m, sizeof( struct ddpehdr ))) == 0 )) {
223: ddpstat.ddps_tooshort++;
224: return;
225: }
226:
227: deh = mtod( m, struct ddpehdr *);
228: bcopy( (caddr_t)deh, (caddr_t)&ddpe, sizeof( struct ddpehdr ));
229: ddpe.deh_bytes = ntohl( ddpe.deh_bytes );
230: dlen = ddpe.deh_len;
231:
232: if (( cksum = ddpe.deh_sum ) == 0 ) {
233: ddpstat.ddps_nosum++;
234: }
235:
236: from.sat_addr.s_net = ddpe.deh_snet;
237: from.sat_addr.s_node = ddpe.deh_snode;
238: from.sat_port = ddpe.deh_sport;
239: to.sat_addr.s_net = ddpe.deh_dnet;
240: to.sat_addr.s_node = ddpe.deh_dnode;
241: to.sat_port = ddpe.deh_dport;
242:
243: if ( to.sat_addr.s_net == 0 ) {
244: for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
245: if ( phase == 1 && ( aa->aa_flags & AFA_PHASE2 )) {
246: continue;
247: }
248: if ( phase == 2 && ( aa->aa_flags & AFA_PHASE2 ) == 0 ) {
249: continue;
250: }
251: if ( aa->aa_ifp == ifp &&
252: ( AA_SAT( aa )->sat_addr.s_node == to.sat_addr.s_node ||
253: to.sat_addr.s_node == ATADDR_BCAST ||
254: ( ifp->if_flags & IFF_LOOPBACK ))) {
255: break;
256: }
257: }
258: } else {
259: for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
260: if ( to.sat_addr.s_net == aa->aa_firstnet &&
261: to.sat_addr.s_node == 0 ) {
262: break;
263: }
264: if (( ntohs( to.sat_addr.s_net ) < ntohs( aa->aa_firstnet ) ||
265: ntohs( to.sat_addr.s_net ) > ntohs( aa->aa_lastnet )) &&
266: ( ntohs( to.sat_addr.s_net ) < 0xff00 ||
267: ntohs( to.sat_addr.s_net ) > 0xfffe)) {
268: continue;
269: }
270: if ( to.sat_addr.s_node != AA_SAT( aa )->sat_addr.s_node &&
271: to.sat_addr.s_node != ATADDR_BCAST ) {
272: continue;
273: }
274: break;
275: }
276: }
277: }
278:
279: /*
280: * Adjust the length, removing any padding that may have been added
281: * at a link layer. We do this before we attempt to forward a packet,
282: * possibly on a different media.
283: */
284: mlen = m->m_pkthdr.len;
285: if ( mlen < dlen ) {
286: ddpstat.ddps_toosmall++;
287: m_freem( m );
288: return;
289: }
290: if ( mlen > dlen ) {
291: m_adj( m, dlen - mlen );
292: }
293:
294: /*
295: * XXX Should we deliver broadcasts locally, also, or rely on the
296: * link layer to give us a copy? For the moment, the latter.
297: */
298: if ( aa == NULL || ( to.sat_addr.s_node == ATADDR_BCAST &&
299: aa->aa_ifp != ifp && ( ifp->if_flags & IFF_LOOPBACK ) == 0 )) {
300: if ( ddp_forward == 0 ) {
301: m_freem( m );
302: return;
303: }
304: if ( forwro.ro_rt && ( satosat( &forwro.ro_dst )->sat_addr.s_net !=
305: to.sat_addr.s_net ||
306: satosat( &forwro.ro_dst )->sat_addr.s_node !=
307: to.sat_addr.s_node )) {
308: RTFREE( forwro.ro_rt );
309: forwro.ro_rt = (struct rtentry *)0;
310: }
311: if ( forwro.ro_rt == (struct rtentry *)0 ||
312: forwro.ro_rt->rt_ifp == (struct ifnet *)0 ) {
313: forwro.ro_dst.sa_len = sizeof( struct sockaddr_at );
314: forwro.ro_dst.sa_family = AF_APPLETALK;
315: satosat( &forwro.ro_dst )->sat_addr.s_net = to.sat_addr.s_net;
316: satosat( &forwro.ro_dst )->sat_addr.s_node = to.sat_addr.s_node;
317: rtalloc( &forwro );
318: }
319:
320: if ( to.sat_addr.s_net != satosat( &forwro.ro_dst )->sat_addr.s_net &&
321: ddpe.deh_hops == DDP_MAXHOPS ) {
322: m_freem( m );
323: return;
324: }
325:
326: /* XXX FreeBSD doesn't have this */
327: if ( ddp_firewall &&
328: ( forwro.ro_rt == NULL || ( forwro.ro_rt->rt_ifp != ifp &&
329: forwro.ro_rt->rt_ifp != at_ifaddr->aa_ifp ))) {
330: m_freem( m );
331: return;
332: }
333:
334: ddpe.deh_hops++;
335: ddpe.deh_bytes = htonl( ddpe.deh_bytes );
336: bcopy( (caddr_t)&ddpe, (caddr_t)deh, sizeof( u_int16_t ));
337: if ( ddp_route( m, &forwro )) {
338: ddpstat.ddps_cantforward++;
339: } else {
340: ddpstat.ddps_forward++;
341: }
342: return;
343: }
344:
345: from.sat_len = sizeof( struct sockaddr_at );
346: from.sat_family = AF_APPLETALK;
347:
348: if ( elh ) {
349: m_adj( m, sizeof( struct ddpshdr ));
350: } else {
351: /*
352: * XXX I've always hated this about the TCP checksum, and here it
353: * is again. ddp_cksum determines whether we compute checksums on
354: * outgoing packets. Why is it used to disable checkumming on
355: * incoming packets as well? If the remote node went to the
356: * trouble of computing the checksum, shouldn't we check it?
357: */
358: if ( ddp_cksum && cksum && cksum != at_cksum( m, sizeof( int ))) {
359: ddpstat.ddps_badsum++;
360: m_freem( m );
361: return;
362: }
363: m_adj( m, sizeof( struct ddpehdr ));
364: }
365:
366: if (( ddp = ddp_search( &from, &to, aa )) == NULL ) {
367: m_freem( m );
368: return;
369: }
370:
371: if ( sbappendaddr( &ddp->ddp_socket->so_rcv, (struct sockaddr *)&from,
372: m, (struct mbuf *)0 ) == 0 ) {
373: ddpstat.ddps_nosockspace++;
374: m_freem( m );
375: return;
376: }
377: sorwakeup( ddp->ddp_socket );
378: }
379:
380: #if 0
381: static void
382: m_printm( m )
383: struct mbuf *m;
384: {
385: for (; m; m = m->m_next ) {
386: bprint( mtod( m, char * ), m->m_len );
387: }
388: }
389:
390: #define BPXLEN 48
391: #define BPALEN 16
392: char hexdig[] = "0123456789ABCDEF";
393:
394: static void
395: bprint( data, len )
396: char *data;
397: int len;
398: {
399: char xout[ BPXLEN ], aout[ BPALEN ];
400: int i = 0;
401:
402: bzero( xout, BPXLEN );
403: bzero( aout, BPALEN );
404:
405: for ( ;; ) {
406: if ( len < 1 ) {
407: if ( i != 0 ) {
408: printf( "%s\t%s\n", xout, aout );
409: }
410: printf( "%s\n", "(end)" );
411: break;
412: }
413:
414: xout[ (i*3) ] = hexdig[ ( *data & 0xf0 ) >> 4 ];
415: xout[ (i*3) + 1 ] = hexdig[ *data & 0x0f ];
416:
417: if ( (u_char)*data < 0x7f && (u_char)*data > 0x20 ) {
418: aout[ i ] = *data;
419: } else {
420: aout[ i ] = '.';
421: }
422:
423: xout[ (i*3) + 2 ] = ' ';
424:
425: i++;
426: len--;
427: data++;
428:
429: if ( i > BPALEN - 2 ) {
430: printf( "%s\t%s\n", xout, aout );
431: bzero( xout, BPXLEN );
432: bzero( aout, BPALEN );
433: i = 0;
434: continue;
435: }
436: }
437: }
438: #endif
CVSweb