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