Annotation of sys/netatalk/ddp_output.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: ddp_output.c,v 1.6 2003/06/06 09:45:08 itojun Exp $ */
2:
3: /*
4: * Copyright (c) 1990,1991 Regents of The University of Michigan.
5: * All Rights Reserved.
6: *
7: * Permission to use, copy, modify, and distribute this software and
8: * its documentation for any purpose and without fee is hereby granted,
9: * provided that the above copyright notice appears in all copies and
10: * that both that copyright notice and this permission notice appear
11: * in supporting documentation, and that the name of The University
12: * of Michigan not be used in advertising or publicity pertaining to
13: * distribution of the software without specific, written prior
14: * permission. This software is supplied as is without expressed or
15: * implied warranties of any kind.
16: *
17: * Research Systems Unix Group
18: * The University of Michigan
19: * c/o Mike Clark
20: * 535 W. William Street
21: * Ann Arbor, Michigan
22: * +1-313-763-0525
23: * netatalk@itd.umich.edu
24: */
25:
26: /*
27: * The following is the contents of the COPYRIGHT file from the
28: * netatalk-1.4a2 distribution, from which this file is derived.
29: */
30: /*
31: * Copyright (c) 1990,1996 Regents of The University of Michigan.
32: *
33: * All Rights Reserved.
34: *
35: * Permission to use, copy, modify, and distribute this software and
36: * its documentation for any purpose and without fee is hereby granted,
37: * provided that the above copyright notice appears in all copies and
38: * that both that copyright notice and this permission notice appear
39: * in supporting documentation, and that the name of The University
40: * of Michigan not be used in advertising or publicity pertaining to
41: * distribution of the software without specific, written prior
42: * permission. This software is supplied as is without expressed or
43: * implied warranties of any kind.
44: *
45: * This product includes software developed by the University of
46: * California, Berkeley and its contributors.
47: *
48: * Solaris code is encumbered by the following:
49: *
50: * Copyright (C) 1996 by Sun Microsystems Computer Co.
51: *
52: * Permission to use, copy, modify, and distribute this software and
53: * its documentation for any purpose and without fee is hereby
54: * granted, provided that the above copyright notice appear in all
55: * copies and that both that copyright notice and this permission
56: * notice appear in supporting documentation. This software is
57: * provided "as is" without express or implied warranty.
58: *
59: * Research Systems Unix Group
60: * The University of Michigan
61: * c/o Wesley Craig
62: * 535 W. William Street
63: * Ann Arbor, Michigan
64: * +1-313-764-2278
65: * netatalk@umich.edu
66: */
67: /*
68: * None of the Solaris code mentioned is included in OpenBSD.
69: * This code also relies heavily on previous effort in FreeBSD and NetBSD.
70: */
71:
72: #include <sys/types.h>
73: #include <sys/param.h>
74: #include <sys/systm.h>
75: #include <sys/mbuf.h>
76: #include <sys/socket.h>
77: #include <sys/errno.h>
78: #include <sys/syslog.h>
79:
80: #include <net/if.h>
81: #include <net/route.h>
82:
83: #include <netinet/in.h>
84: #undef s_net
85: #include <netinet/if_ether.h>
86:
87: #include <machine/endian.h>
88:
89: #include <netatalk/at.h>
90: #include <netatalk/at_var.h>
91: #include <netatalk/ddp.h>
92: #include <netatalk/ddp_var.h>
93: #include <netatalk/at_extern.h>
94:
95: int ddp_output( struct mbuf *, ... );
96: u_int16_t at_cksum( struct mbuf *, int );
97: int ddp_route(struct mbuf *, struct route * );
98:
99: int ddp_cksum = 1;
100:
101: int
102: ddp_output(struct mbuf *m, ...)
103: {
104: struct ddpcb *ddp;
105: struct ddpehdr *deh;
106: va_list ap;
107:
108: va_start(ap, m);
109: ddp = va_arg(ap, struct ddpcb *);
110: va_end(ap);
111:
112: M_PREPEND( m, sizeof( struct ddpehdr ), M_DONTWAIT );
113: if (!m)
114: return (ENOBUFS);
115:
116: deh = mtod( m, struct ddpehdr *);
117: deh->deh_pad = 0;
118: deh->deh_hops = 0;
119:
120: deh->deh_len = m->m_pkthdr.len;
121:
122: deh->deh_dnet = ddp->ddp_fsat.sat_addr.s_net;
123: deh->deh_dnode = ddp->ddp_fsat.sat_addr.s_node;
124: deh->deh_dport = ddp->ddp_fsat.sat_port;
125: deh->deh_snet = ddp->ddp_lsat.sat_addr.s_net;
126: deh->deh_snode = ddp->ddp_lsat.sat_addr.s_node;
127: deh->deh_sport = ddp->ddp_lsat.sat_port;
128:
129: /*
130: * The checksum calculation is done after all of the other bytes have
131: * been filled in.
132: */
133: if ( ddp_cksum ) {
134: deh->deh_sum = at_cksum( m, sizeof( int ));
135: } else {
136: deh->deh_sum = 0;
137: }
138: deh->deh_bytes = htonl( deh->deh_bytes );
139:
140: return( ddp_route( m, &ddp->ddp_route ));
141: }
142:
143: u_int16_t
144: at_cksum( m, skip )
145: struct mbuf *m;
146: int skip;
147: {
148: u_int8_t *data, *end;
149: u_long cksum = 0;
150:
151: for (; m; m = m->m_next ) {
152: for ( data = mtod( m, u_int8_t * ), end = data + m->m_len; data < end;
153: data++ ) {
154: if ( skip ) {
155: skip--;
156: continue;
157: }
158: cksum = ( cksum + *data ) << 1;
159: if ( cksum & 0x00010000 ) {
160: cksum++;
161: }
162: cksum &= 0x0000ffff;
163: }
164: }
165:
166: if ( cksum == 0 ) {
167: cksum = 0x0000ffff;
168: }
169: return( (u_int16_t)cksum );
170: }
171:
172: int
173: ddp_route( m, ro )
174: struct mbuf *m;
175: struct route *ro;
176: {
177: struct sockaddr_at gate;
178: struct elaphdr *elh;
179: struct at_ifaddr *aa = NULL;
180: struct ifnet *ifp;
181: u_int16_t net;
182:
183: if ( ro->ro_rt && ( ifp = ro->ro_rt->rt_ifp )) {
184: net = satosat( ro->ro_rt->rt_gateway )->sat_addr.s_net;
185: for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
186: if ( aa->aa_ifp == ifp &&
187: ntohs( net ) >= ntohs( aa->aa_firstnet ) &&
188: ntohs( net ) <= ntohs( aa->aa_lastnet )) {
189: break;
190: }
191: }
192: }
193: if ( aa == NULL ) {
194: m_freem( m );
195: return( EINVAL );
196: }
197:
198: /*
199: * There are several places in the kernel where data is added to
200: * an mbuf without ensuring that the mbuf pointer is aligned.
201: * This is bad for transition routing, since phase 1 and phase 2
202: * packets end up poorly aligned due to the three byte elap header.
203: */
204: if ( aa->aa_flags & AFA_PHASE2 ) {
205: if (( m = m_pullup( m, MIN( MHLEN, m->m_pkthdr.len ))) == 0 ) {
206: return( ENOBUFS );
207: }
208: } else {
209: M_PREPEND(m, SZ_ELAPHDR, M_DONTWAIT);
210: if (!m)
211: return (ENOBUFS);
212:
213: elh = mtod( m, struct elaphdr *);
214: elh->el_snode = satosat( &aa->aa_addr )->sat_addr.s_node;
215: elh->el_type = ELAP_DDPEXTEND;
216: if ( ntohs( satosat( &ro->ro_dst )->sat_addr.s_net ) >=
217: ntohs( aa->aa_firstnet ) &&
218: ntohs( satosat( &ro->ro_dst )->sat_addr.s_net ) <=
219: ntohs( aa->aa_lastnet )) {
220: elh->el_dnode = satosat( &ro->ro_dst )->sat_addr.s_node;
221: } else {
222: elh->el_dnode = satosat( ro->ro_rt->rt_gateway )->sat_addr.s_node;
223: }
224: }
225:
226: if ( ntohs( satosat( &ro->ro_dst )->sat_addr.s_net ) >=
227: ntohs( aa->aa_firstnet ) &&
228: ntohs( satosat( &ro->ro_dst )->sat_addr.s_net ) <=
229: ntohs( aa->aa_lastnet )) {
230: gate = *satosat( &ro->ro_dst );
231: } else {
232: gate = *satosat( ro->ro_rt->rt_gateway );
233: }
234: ro->ro_rt->rt_use++;
235:
236: /* XXX The NULL should be a struct rtentry */
237: return((*ifp->if_output)( ifp, m, (struct sockaddr *) &gate, NULL ));
238: }
CVSweb