ddp_input.c revision 18207
1/* 2 * Copyright (c) 1990,1994 Regents of The University of Michigan. 3 * All Rights Reserved. See COPYRIGHT. 4 */ 5 6#include <sys/types.h> 7#include <sys/param.h> 8#include <sys/systm.h> 9#include <sys/kernel.h> 10#include <net/netisr.h> 11#include <sys/mbuf.h> 12#include <sys/socket.h> 13#include <sys/socketvar.h> 14#include <sys/syslog.h> 15#include <net/if.h> 16#include <net/route.h> 17#include <netinet/in.h> 18#include <netinet/if_ether.h> 19 20#include <netatalk/at.h> 21#include <netatalk/at_var.h> 22#include <netatalk/endian.h> 23#include <netatalk/ddp.h> 24#include <netatalk/ddp_var.h> 25#include <netatalk/at_extern.h> 26 27int ddp_forward = 1; 28int ddp_firewall = 0; 29extern int ddp_cksum; 30void ddp_input( struct mbuf *, struct ifnet *, struct elaphdr *, int ); 31 32/* 33 * Could probably merge these two code segments a little better... 34 */ 35static void 36atintr( void ) 37{ 38 struct elaphdr *elhp, elh; 39 struct ifnet *ifp; 40 struct mbuf *m; 41 struct at_ifaddr *aa; 42 int s; 43 44 for (;;) { 45 s = splimp(); 46 47 IF_DEQUEUE( &atintrq2, m ); 48 49 splx( s ); 50 51 if ( m == 0 ) { /* no more queued packets */ 52 break; 53 } 54 55 ifp = m->m_pkthdr.rcvif; 56 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { 57 if ( aa->aa_ifp == ifp && ( aa->aa_flags & AFA_PHASE2 )) { 58 break; 59 } 60 } 61 if ( aa == NULL ) { /* ifp not an appletalk interface */ 62 m_freem( m ); 63 continue; 64 } 65 66 ddp_input( m, ifp, (struct elaphdr *)NULL, 2 ); 67 } 68 69 for (;;) { 70 s = splimp(); 71 72 IF_DEQUEUE( &atintrq1, m ); 73 74 splx( s ); 75 76 if ( m == 0 ) { /* no more queued packets */ 77 break; 78 } 79 80 ifp = m->m_pkthdr.rcvif; 81 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { 82 if ( aa->aa_ifp == ifp && ( aa->aa_flags & AFA_PHASE2 ) == 0 ) { 83 break; 84 } 85 } 86 if ( aa == NULL ) { /* ifp not an appletalk interface */ 87 m_freem( m ); 88 continue; 89 } 90 91 if ( m->m_len < SZ_ELAPHDR && 92 (( m = m_pullup( m, SZ_ELAPHDR )) == 0 )) { 93 ddpstat.ddps_tooshort++; 94 continue; 95 } 96 97 elhp = mtod( m, struct elaphdr *); 98 m_adj( m, SZ_ELAPHDR ); 99 100 if ( elhp->el_type == ELAP_DDPEXTEND ) { 101 ddp_input( m, ifp, (struct elaphdr *)NULL, 1 ); 102 } else { 103 bcopy((caddr_t)elhp, (caddr_t)&elh, SZ_ELAPHDR ); 104 ddp_input( m, ifp, &elh, 1 ); 105 } 106 } 107 return; 108} 109 110NETISR_SET(NETISR_ATALK, atintr); 111 112struct route forwro; 113 114void 115ddp_input( m, ifp, elh, phase ) 116 struct mbuf *m; 117 struct ifnet *ifp; 118 struct elaphdr *elh; 119 int phase; 120{ 121 struct sockaddr_at from, to; 122 struct ddpshdr *dsh, ddps; 123 struct at_ifaddr *aa; 124 struct ddpehdr *deh = NULL, ddpe; 125 struct ddpcb *ddp; 126 int dlen, mlen; 127 u_short cksum = 0; 128 129 bzero( (caddr_t)&from, sizeof( struct sockaddr_at )); 130 if ( elh ) { 131 ddpstat.ddps_short++; 132 133 if ( m->m_len < sizeof( struct ddpshdr ) && 134 (( m = m_pullup( m, sizeof( struct ddpshdr ))) == 0 )) { 135 ddpstat.ddps_tooshort++; 136 return; 137 } 138 139 dsh = mtod( m, struct ddpshdr *); 140 bcopy( (caddr_t)dsh, (caddr_t)&ddps, sizeof( struct ddpshdr )); 141 ddps.dsh_bytes = ntohl( ddps.dsh_bytes ); 142 dlen = ddps.dsh_len; 143 144 to.sat_addr.s_net = ATADDR_ANYNET; 145 to.sat_addr.s_node = elh->el_dnode; 146 to.sat_port = ddps.dsh_dport; 147 from.sat_addr.s_net = ATADDR_ANYNET; 148 from.sat_addr.s_node = elh->el_snode; 149 from.sat_port = ddps.dsh_sport; 150 151 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { 152 if ( aa->aa_ifp == ifp && ( aa->aa_flags & AFA_PHASE2 ) == 0 && 153 ( AA_SAT( aa )->sat_addr.s_node == to.sat_addr.s_node || 154 to.sat_addr.s_node == ATADDR_BCAST )) { 155 break; 156 } 157 } 158 if ( aa == NULL ) { 159 m_freem( m ); 160 return; 161 } 162 } else { 163 ddpstat.ddps_long++; 164 165 if ( m->m_len < sizeof( struct ddpehdr ) && 166 (( m = m_pullup( m, sizeof( struct ddpehdr ))) == 0 )) { 167 ddpstat.ddps_tooshort++; 168 return; 169 } 170 171 deh = mtod( m, struct ddpehdr *); 172 bcopy( (caddr_t)deh, (caddr_t)&ddpe, sizeof( struct ddpehdr )); 173 ddpe.deh_bytes = ntohl( ddpe.deh_bytes ); 174 dlen = ddpe.deh_len; 175 176 if (( cksum = ddpe.deh_sum ) == 0 ) { 177 ddpstat.ddps_nosum++; 178 } 179 180 from.sat_addr.s_net = ddpe.deh_snet; 181 from.sat_addr.s_node = ddpe.deh_snode; 182 from.sat_port = ddpe.deh_sport; 183 to.sat_addr.s_net = ddpe.deh_dnet; 184 to.sat_addr.s_node = ddpe.deh_dnode; 185 to.sat_port = ddpe.deh_dport; 186 187 if ( to.sat_addr.s_net == ATADDR_ANYNET ) { 188 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { 189 if ( phase == 1 && ( aa->aa_flags & AFA_PHASE2 )) { 190 continue; 191 } 192 if ( phase == 2 && ( aa->aa_flags & AFA_PHASE2 ) == 0 ) { 193 continue; 194 } 195 if ( aa->aa_ifp == ifp && 196 ( AA_SAT( aa )->sat_addr.s_node == to.sat_addr.s_node || 197 to.sat_addr.s_node == ATADDR_BCAST || 198 ( ifp->if_flags & IFF_LOOPBACK ))) { 199 break; 200 } 201 } 202 } else { 203 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { 204 if ( to.sat_addr.s_net == aa->aa_firstnet && 205 to.sat_addr.s_node == 0 ) { 206 break; 207 } 208 if (( ntohs( to.sat_addr.s_net ) < ntohs( aa->aa_firstnet ) || 209 ntohs( to.sat_addr.s_net ) > ntohs( aa->aa_lastnet )) && 210 ( ntohs( to.sat_addr.s_net ) < ntohs( 0xff00 ) || 211 ntohs( to.sat_addr.s_net ) > ntohs( 0xfffe ))) { 212 continue; 213 } 214 if ( to.sat_addr.s_node != AA_SAT( aa )->sat_addr.s_node && 215 to.sat_addr.s_node != ATADDR_BCAST ) { 216 continue; 217 } 218 break; 219 } 220 } 221 } 222 223 /* 224 * Adjust the length, removing any padding that may have been added 225 * at a link layer. We do this before we attempt to forward a packet, 226 * possibly on a different media. 227 */ 228 mlen = m->m_pkthdr.len; 229 if ( mlen < dlen ) { 230 ddpstat.ddps_toosmall++; 231 m_freem( m ); 232 return; 233 } 234 if ( mlen > dlen ) { 235 m_adj( m, dlen - mlen ); 236 } 237 238 /* 239 * XXX Should we deliver broadcasts locally, also, or rely on the 240 * link layer to give us a copy? For the moment, the latter. 241 */ 242 if ( aa == NULL || ( to.sat_addr.s_node == ATADDR_BCAST && 243 aa->aa_ifp != ifp && ( ifp->if_flags & IFF_LOOPBACK ) == 0 )) { 244 if ( ddp_forward == 0 ) { 245 m_freem( m ); 246 return; 247 } 248 if ( forwro.ro_rt && ( satosat( &forwro.ro_dst )->sat_addr.s_net != 249 to.sat_addr.s_net || 250 satosat( &forwro.ro_dst )->sat_addr.s_node != 251 to.sat_addr.s_node )) { 252 RTFREE( forwro.ro_rt ); 253 forwro.ro_rt = (struct rtentry *)0; 254 } 255 if ( forwro.ro_rt == (struct rtentry *)0 || 256 forwro.ro_rt->rt_ifp == (struct ifnet *)0 ) { 257 forwro.ro_dst.sa_len = sizeof( struct sockaddr_at ); 258 forwro.ro_dst.sa_family = AF_APPLETALK; 259 satosat( &forwro.ro_dst )->sat_addr.s_net = to.sat_addr.s_net; 260 satosat( &forwro.ro_dst )->sat_addr.s_node = to.sat_addr.s_node; 261 rtalloc( &forwro ); 262 } 263 264 if ( to.sat_addr.s_net != satosat( &forwro.ro_dst )->sat_addr.s_net && 265 ddpe.deh_hops == DDP_MAXHOPS ) { 266 m_freem( m ); 267 return; 268 } 269 270 if ( ddp_firewall && 271 ( forwro.ro_rt == NULL || forwro.ro_rt->rt_ifp != ifp )) { 272 m_freem( m ); 273 return; 274 } 275 276 ddpe.deh_hops++; 277 ddpe.deh_bytes = htonl( ddpe.deh_bytes ); 278 bcopy( (caddr_t)&ddpe, (caddr_t)deh, sizeof( u_short )); /* XXX deh? */ 279 if ( ddp_route( m, &forwro )) { 280 ddpstat.ddps_cantforward++; 281 } else { 282 ddpstat.ddps_forward++; 283 } 284 return; 285 } 286 287 from.sat_len = sizeof( struct sockaddr_at ); 288 from.sat_family = AF_APPLETALK; 289 290 if ( elh ) { 291 m_adj( m, sizeof( struct ddpshdr )); 292 } else { 293 if ( ddp_cksum && cksum && cksum != at_cksum( m, sizeof( int ))) { 294 ddpstat.ddps_badsum++; 295 m_freem( m ); 296 return; 297 } 298 m_adj( m, sizeof( struct ddpehdr )); 299 } 300 301 if (( ddp = ddp_search( &from, &to, aa )) == NULL ) { 302 m_freem( m ); 303 return; 304 } 305 306 if ( sbappendaddr( &ddp->ddp_socket->so_rcv, (struct sockaddr *)&from, 307 m, (struct mbuf *)0 ) == 0 ) { 308 ddpstat.ddps_nosockspace++; 309 m_freem( m ); 310 return; 311 } 312 sorwakeup( ddp->ddp_socket ); 313} 314 315#if 0 316 317#define BPXLEN 48 318#define BPALEN 16 319#include <ctype.h> 320char hexdig[] = "0123456789ABCDEF"; 321 322static void 323bprint( char *data, int len ) 324{ 325 char xout[ BPXLEN ], aout[ BPALEN ]; 326 int i = 0; 327 328 bzero( xout, BPXLEN ); 329 bzero( aout, BPALEN ); 330 331 for ( ;; ) { 332 if ( len < 1 ) { 333 if ( i != 0 ) { 334 printf( "%s\t%s\n", xout, aout ); 335 } 336 printf( "%s\n", "(end)" ); 337 break; 338 } 339 340 xout[ (i*3) ] = hexdig[ ( *data & 0xf0 ) >> 4 ]; 341 xout[ (i*3) + 1 ] = hexdig[ *data & 0x0f ]; 342 343 if ( (u_char)*data < 0x7f && (u_char)*data > 0x20 ) { 344 aout[ i ] = *data; 345 } else { 346 aout[ i ] = '.'; 347 } 348 349 xout[ (i*3) + 2 ] = ' '; 350 351 i++; 352 len--; 353 data++; 354 355 if ( i > BPALEN - 2 ) { 356 printf( "%s\t%s\n", xout, aout ); 357 bzero( xout, BPXLEN ); 358 bzero( aout, BPALEN ); 359 i = 0; 360 continue; 361 } 362 } 363} 364 365static void 366m_printm( struct mbuf *m ) 367{ 368 for (; m; m = m->m_next ) { 369 bprint( mtod( m, char * ), m->m_len ); 370 } 371} 372#endif 373