2 * Copyright (c) 1990,1991 Regents of The University of Michigan.
3 * All Rights Reserved. See COPYRIGHT.
9 #include <sys/socket.h>
10 #include <sys/errno.h>
11 #include <sys/syslog.h>
14 #include <net/route.h>
16 #include <netinet/in.h>
18 #include <netinet/if_ether.h>
38 struct at_ifaddr *aa = NULL;
43 M_PREPEND( m, sizeof( struct ddpehdr ), M_WAIT );
45 for ( len = 0, m0 = m; m; m = m->m_next ) {
48 MGET( m, M_WAIT, MT_HEADER );
57 # define align(a) (((a)+3)&0xfc)
58 m->m_off = MMINOFF + align( SZ_ELAPHDR );
59 m->m_len = sizeof( struct ddpehdr );
62 deh = mtod( m, struct ddpehdr *);
67 deh->deh_len = m->m_pkthdr.len;
69 deh->deh_len = len + sizeof( struct ddpehdr );
72 deh->deh_dnet = ddp->ddp_fsat.sat_addr.s_net;
73 deh->deh_dnode = ddp->ddp_fsat.sat_addr.s_node;
74 deh->deh_dport = ddp->ddp_fsat.sat_port;
75 deh->deh_snet = ddp->ddp_lsat.sat_addr.s_net;
76 deh->deh_snode = ddp->ddp_lsat.sat_addr.s_node;
77 deh->deh_sport = ddp->ddp_lsat.sat_port;
80 * The checksum calculation is done after all of the other bytes have
84 deh->deh_sum = at_cksum( m, sizeof( int ));
88 deh->deh_bytes = htonl( deh->deh_bytes );
90 return( ddp_route( m, &ddp->ddp_route ));
101 for (; m; m = m->m_next ) {
102 for ( data = mtod( m, u_char * ), end = data + m->m_len; data < end;
108 cksum = ( cksum + *data ) << 1;
109 if ( cksum & 0x00010000 ) {
119 return( (u_short)cksum );
126 struct sockaddr_at gate;
129 struct at_ifaddr *aa = NULL;
134 if ( ro->ro_rt && ( ifp = ro->ro_rt->rt_ifp )) {
136 net = satosat( ro->ro_rt->rt_gateway )->sat_addr.s_net;
138 net = satosat( &ro->ro_rt->rt_gateway )->sat_addr.s_net;
140 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
141 if ( aa->aa_ifp == ifp &&
142 ntohs( net ) >= ntohs( aa->aa_firstnet ) &&
143 ntohs( net ) <= ntohs( aa->aa_lastnet )) {
154 * There are several places in the kernel where data is added to
155 * an mbuf without ensuring that the mbuf pointer is aligned.
156 * This is bad for transition routing, since phase 1 and phase 2
157 * packets end up poorly aligned due to the three byte elap header.
159 if ( aa->aa_flags & AFA_PHASE2 ) {
160 for ( mlen = 0, m0 = m; m0; m0 = m0->m_next ) {
163 if (( m = m_pullup( m, MIN( MLEN, mlen ))) == 0 ) {
169 M_PREPEND( m, SZ_ELAPHDR, M_DONTWAIT );
174 m->m_off -= SZ_ELAPHDR;
175 m->m_len += SZ_ELAPHDR;
179 MGET( m0, M_WAIT, MT_HEADER );
185 m0->m_off = MMINOFF + align( sizeof( struct ether_header ));
186 m0->m_len = SZ_ELAPHDR;
189 elh = mtod( m, struct elaphdr *);
190 elh->el_snode = satosat( &aa->aa_addr )->sat_addr.s_node;
191 elh->el_type = ELAP_DDPEXTEND;
192 if ( ntohs( satosat( &ro->ro_dst )->sat_addr.s_net ) >=
193 ntohs( aa->aa_firstnet ) &&
194 ntohs( satosat( &ro->ro_dst )->sat_addr.s_net ) <=
195 ntohs( aa->aa_lastnet )) {
196 elh->el_dnode = satosat( &ro->ro_dst )->sat_addr.s_node;
199 elh->el_dnode = satosat( ro->ro_rt->rt_gateway )->sat_addr.s_node;
201 elh->el_dnode = satosat( &ro->ro_rt->rt_gateway )->sat_addr.s_node;
206 if ( ntohs( satosat( &ro->ro_dst )->sat_addr.s_net ) >=
207 ntohs( aa->aa_firstnet ) &&
208 ntohs( satosat( &ro->ro_dst )->sat_addr.s_net ) <=
209 ntohs( aa->aa_lastnet )) {
210 gate = *satosat( &ro->ro_dst );
213 gate = *satosat( ro->ro_rt->rt_gateway );
215 gate = *satosat( &ro->ro_rt->rt_gateway );
222 * SAIEW: We can't make changes to net/if_loop.c, so we don't route
223 * further than this: if it's going to go through the lookback,
224 * short-circuit to ddp_input(). Who needs queuing?
226 * Note: Passing NULL for the elaphdr is cool, since we'll only ever
227 * try to send long form ddp throught the loopback.
229 if ( ifp->if_flags & IFF_LOOPBACK ) {
231 m->m_off += SZ_ELAPHDR;
232 m->m_len -= SZ_ELAPHDR;
234 ddp_input( m, ifp, (struct elaphdr *)NULL, 2 );
241 * We can't make changes to the interface routines on RS6ks, and
242 * they don't provide hooks for if_output, so we just resolve
243 * our address here, and pass the packet as a raw ethernet packet.
244 * This doesn't work particularly well, if we aren't *on* ethernet,
245 * but it's ok for the moment.
247 if ( ! ( ifp->if_flags & IFF_LOOPBACK )) {
248 struct ether_header eh;
250 if ( !aarpresolve(( struct arpcom *)ifp, m,
251 &gate, eh.ether_dhost )) {
254 eh.ether_type = htons( ETHERTYPE_AT );
255 gate.sat_family = AF_UNSPEC;
256 bcopy( &eh, (*(struct sockaddr *)&gate).sa_data,
257 sizeof( (*(struct sockaddr *)&gate).sa_data ));
260 return((*ifp->if_output)( ifp, m, &gate ));