]> arthur.barton.de Git - netatalk.git/blob - sys/netatalk/ddp_output.c
replaced all #include <sys/syslog.h> with #include <syslog.h>
[netatalk.git] / sys / netatalk / ddp_output.c
1 /*
2  * $Id: ddp_output.c,v 1.3 2002-01-03 17:49:39 sibaz Exp $
3  *
4  * Copyright (c) 1990,1991 Regents of The University of Michigan.
5  * All Rights Reserved. See COPYRIGHT.
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif /* HAVE_CONFIG_H */
11
12 #include <sys/types.h>
13 #include <sys/param.h>
14 #include <sys/mbuf.h>
15 #include <sys/socket.h>
16 #include <sys/errno.h>
17 #include <syslog.h>
18
19 #include <net/if.h>
20 #include <net/route.h>
21
22 #include <netinet/in.h>
23 #undef s_net
24 #include <netinet/if_ether.h>
25
26 #include "at.h"
27 #include "at_var.h"
28 #include "endian.h"
29 #include "ddp.h"
30 #include "ddp_var.h"
31
32 u_short at_cksum();
33 int     ddp_cksum = 1;
34
35 ddp_output( ddp, m )
36     struct ddpcb        *ddp;
37     struct mbuf         *m;
38 {
39 #ifndef BSD4_4
40     struct mbuf         *m0;
41     int                 len;
42 #endif /* ! BSD4_4 */
43     struct ifnet        *ifp;
44     struct at_ifaddr    *aa = NULL;
45     struct ddpehdr      *deh;
46     u_short             net;
47
48 #ifdef BSD4_4
49     M_PREPEND( m, sizeof( struct ddpehdr ), M_WAIT );
50 #else /* BSD4_4 */
51     for ( len = 0, m0 = m; m; m = m->m_next ) {
52         len += m->m_len;
53     }
54     MGET( m, M_WAIT, MT_HEADER );
55     if ( m == 0 ) {
56         m_freem( m0 );
57         return( ENOBUFS );
58     }
59     m->m_next = m0;
60 #endif /* BSD4_4 */
61
62 #ifndef BSD4_4
63 # define align(a)       (((a)+3)&0xfc)
64     m->m_off = MMINOFF + align( SZ_ELAPHDR );
65     m->m_len = sizeof( struct ddpehdr );
66 #endif /* ! BSD4_4 */
67
68     deh = mtod( m, struct ddpehdr *);
69     deh->deh_pad = 0;
70     deh->deh_hops = 0;
71
72 #ifdef BSD4_4
73     deh->deh_len = m->m_pkthdr.len;
74 #else /* BSD4_4 */
75     deh->deh_len = len + sizeof( struct ddpehdr );
76 #endif /* BSD4_4 */
77
78     deh->deh_dnet = ddp->ddp_fsat.sat_addr.s_net;
79     deh->deh_dnode = ddp->ddp_fsat.sat_addr.s_node;
80     deh->deh_dport = ddp->ddp_fsat.sat_port;
81     deh->deh_snet = ddp->ddp_lsat.sat_addr.s_net;
82     deh->deh_snode = ddp->ddp_lsat.sat_addr.s_node;
83     deh->deh_sport = ddp->ddp_lsat.sat_port;
84
85     /*
86      * The checksum calculation is done after all of the other bytes have
87      * been filled in.
88      */
89     if ( ddp_cksum ) {
90         deh->deh_sum = at_cksum( m, sizeof( int ));
91     } else {
92         deh->deh_sum = 0;
93     }
94     deh->deh_bytes = htonl( deh->deh_bytes );
95
96     return( ddp_route( m, &ddp->ddp_route ));
97 }
98
99     u_short
100 at_cksum( m, skip )
101     struct mbuf *m;
102     int         skip;
103 {
104     u_char      *data, *end;
105     u_int32_t   cksum = 0;
106
107     for (; m; m = m->m_next ) {
108         for ( data = mtod( m, u_char * ), end = data + m->m_len; data < end;
109                 data++ ) {
110             if ( skip ) {
111                 skip--;
112                 continue;
113             }
114             cksum = ( cksum + *data ) << 1;
115             if ( cksum & 0x00010000 ) {
116                 cksum++;
117             }
118             cksum &= 0x0000ffff;
119         }
120     }
121
122     if ( cksum == 0 ) {
123         cksum = 0x0000ffff;
124     }
125     return( (u_short)cksum );
126 }
127
128 ddp_route( m, ro )
129     struct mbuf         *m;
130     struct route        *ro;
131 {
132     struct sockaddr_at  gate;
133     struct elaphdr      *elh;
134     struct mbuf         *m0;
135     struct at_ifaddr    *aa = NULL;
136     struct ifnet        *ifp;
137     int                 mlen;
138     u_short             net;
139
140     if ( ro->ro_rt && ( ifp = ro->ro_rt->rt_ifp )) {
141 #ifdef BSD4_4
142         net = satosat( ro->ro_rt->rt_gateway )->sat_addr.s_net;
143 #else /* BSD4_4 */
144         net = satosat( &ro->ro_rt->rt_gateway )->sat_addr.s_net;
145 #endif /* BSD4_4 */
146         for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
147             if ( aa->aa_ifp == ifp &&
148                     ntohs( net ) >= ntohs( aa->aa_firstnet ) &&
149                     ntohs( net ) <= ntohs( aa->aa_lastnet )) {
150                 break;
151             }
152         }
153     }
154     if ( aa == NULL ) {
155         m_freem( m );
156         return( EINVAL );
157     }
158
159     /*
160      * There are several places in the kernel where data is added to
161      * an mbuf without ensuring that the mbuf pointer is aligned.
162      * This is bad for transition routing, since phase 1 and phase 2
163      * packets end up poorly aligned due to the three byte elap header.
164      */
165     if ( aa->aa_flags & AFA_PHASE2 ) {
166         for ( mlen = 0, m0 = m; m0; m0 = m0->m_next ) {
167             mlen += m0->m_len;
168         }
169         if (( m = m_pullup( m, MIN( MLEN, mlen ))) == 0 ) {
170             return( ENOBUFS );
171         }
172     } else {
173 # ifdef notdef
174 #ifdef BSD4_4
175         M_PREPEND( m, SZ_ELAPHDR, M_DONTWAIT );
176         if ( m == NULL ) {
177             return( ENOBUFS );
178         }
179 #else /* BSD4_4 */
180         m->m_off -= SZ_ELAPHDR;
181         m->m_len += SZ_ELAPHDR;
182 #endif /* BSD4_4 */
183 # endif /* notdef */
184
185         MGET( m0, M_WAIT, MT_HEADER );
186         if ( m0 == 0 ) {
187             m_freem( m );
188             return( ENOBUFS );
189         }
190         m0->m_next = m;
191         m0->m_off = MMINOFF + align( sizeof( struct ether_header ));
192         m0->m_len = SZ_ELAPHDR;
193         m = m0;
194
195         elh = mtod( m, struct elaphdr *);
196         elh->el_snode = satosat( &aa->aa_addr )->sat_addr.s_node;
197         elh->el_type = ELAP_DDPEXTEND;
198         if ( ntohs( satosat( &ro->ro_dst )->sat_addr.s_net ) >=
199                 ntohs( aa->aa_firstnet ) &&
200                 ntohs( satosat( &ro->ro_dst )->sat_addr.s_net ) <=
201                 ntohs( aa->aa_lastnet )) {
202             elh->el_dnode = satosat( &ro->ro_dst )->sat_addr.s_node;
203         } else {
204 #ifdef BSD4_4
205             elh->el_dnode = satosat( ro->ro_rt->rt_gateway )->sat_addr.s_node;
206 #else /* BSD4_4 */
207             elh->el_dnode = satosat( &ro->ro_rt->rt_gateway )->sat_addr.s_node;
208 #endif /* BSD4_4 */
209         }
210     }
211
212     if ( ntohs( satosat( &ro->ro_dst )->sat_addr.s_net ) >=
213             ntohs( aa->aa_firstnet ) &&
214             ntohs( satosat( &ro->ro_dst )->sat_addr.s_net ) <=
215             ntohs( aa->aa_lastnet )) {
216         gate = *satosat( &ro->ro_dst );
217     } else {
218 #ifdef BSD4_4
219         gate = *satosat( ro->ro_rt->rt_gateway );
220 #else /* BSD4_4 */
221         gate = *satosat( &ro->ro_rt->rt_gateway );
222 #endif /* BSD4_4 */
223     }
224     ro->ro_rt->rt_use++;
225
226 #ifdef ultrix
227     /*
228      * SAIEW: We can't make changes to net/if_loop.c, so we don't route
229      * further than this: if it's going to go through the lookback,
230      * short-circuit to ddp_input(). Who needs queuing?
231      *
232      * Note: Passing NULL for the elaphdr is cool, since we'll only ever
233      * try to send long form ddp throught the loopback.
234      */
235     if ( ifp->if_flags & IFF_LOOPBACK ) {
236 #ifdef notdef
237         m->m_off += SZ_ELAPHDR;
238         m->m_len -= SZ_ELAPHDR;
239 #endif /* notdef */
240         ddp_input( m, ifp, (struct elaphdr *)NULL, 2 );
241         return( 0 );
242     }
243 #endif /* ultrix */
244
245 #ifdef _IBMR2
246     /*
247      * We can't make changes to the interface routines on RS6ks, and
248      * they don't provide hooks for if_output, so we just resolve
249      * our address here, and pass the packet as a raw ethernet packet.
250      * This doesn't work particularly well, if we aren't *on* ethernet,
251      * but it's ok for the moment.
252      */
253     if ( ! ( ifp->if_flags & IFF_LOOPBACK )) {
254         struct ether_header     eh;
255
256         if ( !aarpresolve(( struct arpcom *)ifp, m,
257                 &gate, eh.ether_dhost )) {
258             return( 0 );
259         }
260         eh.ether_type = htons( ETHERTYPE_AT );
261         gate.sat_family = AF_UNSPEC;
262         bcopy( &eh, (*(struct sockaddr *)&gate).sa_data,
263                 sizeof( (*(struct sockaddr *)&gate).sa_data ));
264     }
265 #endif /* _IBMR2 */
266     return((*ifp->if_output)( ifp, m, &gate ));
267 }