ddp_input.c revision 111888
1/* 2 * Copyright (c) 1990,1994 Regents of The University of Michigan. 3 * All Rights Reserved. See COPYRIGHT. 4 * 5 * $FreeBSD: head/sys/netatalk/ddp_input.c 111888 2003-03-04 23:19:55Z jlemon $ 6 */ 7 8#include "opt_mac.h" 9 10#include <sys/param.h> 11#include <sys/kernel.h> 12#include <sys/lock.h> 13#include <sys/mac.h> 14#include <sys/mbuf.h> 15#include <sys/signalvar.h> 16#include <sys/socket.h> 17#include <sys/socketvar.h> 18#include <sys/sx.h> 19#include <sys/systm.h> 20#include <net/if.h> 21#include <net/route.h> 22 23#include <netatalk/at.h> 24#include <netatalk/at_var.h> 25#include <netatalk/ddp.h> 26#include <netatalk/ddp_var.h> 27#include <netatalk/at_extern.h> 28 29static volatile int ddp_forward = 1; 30static volatile int ddp_firewall = 0; 31static struct ddpstat ddpstat; 32static struct route forwro; 33 34static void ddp_input(struct mbuf *, struct ifnet *, struct elaphdr *, int); 35 36/* 37 * Could probably merge these two code segments a little better... 38 */ 39void 40at2intr(struct mbuf *m) 41{ 42 43 /* 44 * Phase 2 packet handling 45 */ 46 ddp_input(m, m->m_pkthdr.rcvif, NULL, 2); 47 return; 48} 49 50void 51at1intr(struct mbuf *m) 52{ 53 struct elaphdr *elhp, elh; 54 55 /* 56 * Phase 1 packet handling 57 */ 58 if (m->m_len < SZ_ELAPHDR && ((m = m_pullup(m, SZ_ELAPHDR)) == 0)) { 59 ddpstat.ddps_tooshort++; 60 return; 61 } 62 63 /* 64 * This seems a little dubious, but I don't know phase 1 so leave it. 65 */ 66 elhp = mtod(m, struct elaphdr *); 67 m_adj(m, SZ_ELAPHDR); 68 69 if (elhp->el_type == ELAP_DDPEXTEND) { 70 ddp_input(m, m->m_pkthdr.rcvif, NULL, 1); 71 } else { 72 bcopy((caddr_t)elhp, (caddr_t)&elh, SZ_ELAPHDR); 73 ddp_input(m, m->m_pkthdr.rcvif, &elh, 1); 74 } 75 return; 76} 77 78static void 79ddp_input( m, ifp, elh, phase ) 80 struct mbuf *m; 81 struct ifnet *ifp; 82 struct elaphdr *elh; 83 int phase; 84{ 85 struct sockaddr_at from, to; 86 struct ddpshdr *dsh, ddps; 87 struct at_ifaddr *aa; 88 struct ddpehdr *deh = NULL, ddpe; 89 struct ddpcb *ddp; 90 int dlen, mlen; 91 u_short cksum = 0; 92 93 bzero( (caddr_t)&from, sizeof( struct sockaddr_at )); 94 bzero( (caddr_t)&to, sizeof( struct sockaddr_at )); 95 if ( elh ) { 96 /* 97 * Extract the information in the short header. 98 * netowrk information is defaulted to ATADDR_ANYNET 99 * and node information comes from the elh info. 100 * We must be phase 1. 101 */ 102 ddpstat.ddps_short++; 103 104 if ( m->m_len < sizeof( struct ddpshdr ) && 105 (( m = m_pullup( m, sizeof( struct ddpshdr ))) == 0 )) { 106 ddpstat.ddps_tooshort++; 107 return; 108 } 109 110 dsh = mtod( m, struct ddpshdr *); 111 bcopy( (caddr_t)dsh, (caddr_t)&ddps, sizeof( struct ddpshdr )); 112 ddps.dsh_bytes = ntohl( ddps.dsh_bytes ); 113 dlen = ddps.dsh_len; 114 115 to.sat_addr.s_net = ATADDR_ANYNET; 116 to.sat_addr.s_node = elh->el_dnode; 117 to.sat_port = ddps.dsh_dport; 118 from.sat_addr.s_net = ATADDR_ANYNET; 119 from.sat_addr.s_node = elh->el_snode; 120 from.sat_port = ddps.dsh_sport; 121 122 /* 123 * Make sure that we point to the phase1 ifaddr info 124 * and that it's valid for this packet. 125 */ 126 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { 127 if ( (aa->aa_ifp == ifp) 128 && ( (aa->aa_flags & AFA_PHASE2) == 0) 129 && ( (to.sat_addr.s_node == AA_SAT( aa )->sat_addr.s_node) 130 || (to.sat_addr.s_node == ATADDR_BCAST))) { 131 break; 132 } 133 } 134 /* 135 * maybe we got a broadcast not meant for us.. ditch it. 136 */ 137 if ( aa == NULL ) { 138 m_freem( m ); 139 return; 140 } 141 } else { 142 /* 143 * There was no 'elh' passed on. This could still be 144 * either phase1 or phase2. 145 * We have a long header, but we may be running on a phase 1 net. 146 * Extract out all the info regarding this packet's src & dst. 147 */ 148 ddpstat.ddps_long++; 149 150 if ( m->m_len < sizeof( struct ddpehdr ) && 151 (( m = m_pullup( m, sizeof( struct ddpehdr ))) == 0 )) { 152 ddpstat.ddps_tooshort++; 153 return; 154 } 155 156 deh = mtod( m, struct ddpehdr *); 157 bcopy( (caddr_t)deh, (caddr_t)&ddpe, sizeof( struct ddpehdr )); 158 ddpe.deh_bytes = ntohl( ddpe.deh_bytes ); 159 dlen = ddpe.deh_len; 160 161 if (( cksum = ddpe.deh_sum ) == 0 ) { 162 ddpstat.ddps_nosum++; 163 } 164 165 from.sat_addr.s_net = ddpe.deh_snet; 166 from.sat_addr.s_node = ddpe.deh_snode; 167 from.sat_port = ddpe.deh_sport; 168 to.sat_addr.s_net = ddpe.deh_dnet; 169 to.sat_addr.s_node = ddpe.deh_dnode; 170 to.sat_port = ddpe.deh_dport; 171 172 if ( to.sat_addr.s_net == ATADDR_ANYNET ) { 173 /* 174 * The TO address doesn't specify a net, 175 * So by definition it's for this net. 176 * Try find ifaddr info with the right phase, 177 * the right interface, and either to our node, a broadcast, 178 * or looped back (though that SHOULD be covered in the other 179 * cases). 180 * 181 * XXX If we have multiple interfaces, then the first with 182 * this node number will match (which may NOT be what we want, 183 * but it's probably safe in 99.999% of cases. 184 */ 185 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { 186 if ( phase == 1 && ( aa->aa_flags & AFA_PHASE2 )) { 187 continue; 188 } 189 if ( phase == 2 && ( aa->aa_flags & AFA_PHASE2 ) == 0 ) { 190 continue; 191 } 192 if ( (aa->aa_ifp == ifp) 193 && ( (to.sat_addr.s_node == AA_SAT( aa )->sat_addr.s_node) 194 || (to.sat_addr.s_node == ATADDR_BCAST) 195 || (ifp->if_flags & IFF_LOOPBACK))) { 196 break; 197 } 198 } 199 } else { 200 /* 201 * A destination network was given. We just try to find 202 * which ifaddr info matches it. 203 */ 204 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { 205 /* 206 * This is a kludge. Accept packets that are 207 * for any router on a local netrange. 208 */ 209 if ( to.sat_addr.s_net == aa->aa_firstnet && 210 to.sat_addr.s_node == 0 ) { 211 break; 212 } 213 /* 214 * Don't use ifaddr info for which we are totally outside the 215 * netrange, and it's not a startup packet. 216 * Startup packets are always implicitly allowed on to 217 * the next test. 218 */ 219 if ((( ntohs( to.sat_addr.s_net ) < ntohs( aa->aa_firstnet )) 220 || (ntohs( to.sat_addr.s_net ) > ntohs( aa->aa_lastnet ))) 221 && (( ntohs( to.sat_addr.s_net ) < 0xff00) 222 || (ntohs( to.sat_addr.s_net ) > 0xfffe ))) { 223 continue; 224 } 225 226 /* 227 * Don't record a match either if we just don't have a match 228 * in the node address. This can have if the interface 229 * is in promiscuous mode for example. 230 */ 231 if (( to.sat_addr.s_node != AA_SAT( aa )->sat_addr.s_node) 232 && (to.sat_addr.s_node != ATADDR_BCAST) ) { 233 continue; 234 } 235 break; 236 } 237 } 238 } 239 240 /* 241 * Adjust the length, removing any padding that may have been added 242 * at a link layer. We do this before we attempt to forward a packet, 243 * possibly on a different media. 244 */ 245 mlen = m->m_pkthdr.len; 246 if ( mlen < dlen ) { 247 ddpstat.ddps_toosmall++; 248 m_freem( m ); 249 return; 250 } 251 if ( mlen > dlen ) { 252 m_adj( m, dlen - mlen ); 253 } 254 255 /* 256 * If it aint for a net on any of our interfaces, 257 * or it IS for a net on a different interface than it came in on, 258 * (and it is not looped back) then consider if we should forward it. 259 * As we are not really a router this is a bit cheeky, but it may be 260 * useful some day. 261 */ 262 if ( (aa == NULL) 263 || ( (to.sat_addr.s_node == ATADDR_BCAST) 264 && (aa->aa_ifp != ifp) 265 && (( ifp->if_flags & IFF_LOOPBACK ) == 0 ))) { 266 /* 267 * If we've explicitly disabled it, don't route anything 268 */ 269 if ( ddp_forward == 0 ) { 270 m_freem( m ); 271 return; 272 } 273 /* 274 * If the cached forwarding route is still valid, use it. 275 */ 276 if ( forwro.ro_rt 277 && ( satosat(&forwro.ro_dst)->sat_addr.s_net != to.sat_addr.s_net 278 || satosat(&forwro.ro_dst)->sat_addr.s_node != to.sat_addr.s_node )) { 279 RTFREE( forwro.ro_rt ); 280 forwro.ro_rt = (struct rtentry *)0; 281 } 282 283 /* 284 * If we don't have a cached one (any more) or it's useless, 285 * Then get a new route. 286 * XXX this could cause a 'route leak'. check this! 287 */ 288 if ( forwro.ro_rt == (struct rtentry *)0 289 || forwro.ro_rt->rt_ifp == (struct ifnet *)0 ) { 290 forwro.ro_dst.sa_len = sizeof( struct sockaddr_at ); 291 forwro.ro_dst.sa_family = AF_APPLETALK; 292 satosat(&forwro.ro_dst)->sat_addr.s_net = to.sat_addr.s_net; 293 satosat(&forwro.ro_dst)->sat_addr.s_node = to.sat_addr.s_node; 294 rtalloc(&forwro); 295 } 296 297 /* 298 * If it's not going to get there on this hop, and it's 299 * already done too many hops, then throw it away. 300 */ 301 if ( (to.sat_addr.s_net != satosat( &forwro.ro_dst )->sat_addr.s_net) 302 && (ddpe.deh_hops == DDP_MAXHOPS) ) { 303 m_freem( m ); 304 return; 305 } 306 307 /* 308 * A ddp router might use the same interface 309 * to forward the packet, which this would not effect. 310 * Don't allow packets to cross from one interface to another however. 311 */ 312 if ( ddp_firewall 313 && ( (forwro.ro_rt == NULL) 314 || (forwro.ro_rt->rt_ifp != ifp))) { 315 m_freem( m ); 316 return; 317 } 318 319 /* 320 * Adjust the header. 321 * If it was a short header then it would have not gotten here, 322 * so we can assume there is room to drop the header in. 323 * XXX what about promiscuous mode, etc... 324 */ 325 ddpe.deh_hops++; 326 ddpe.deh_bytes = htonl( ddpe.deh_bytes ); 327 bcopy( (caddr_t)&ddpe, (caddr_t)deh, sizeof( u_short )); /* XXX deh? */ 328 if ( ddp_route( m, &forwro )) { 329 ddpstat.ddps_cantforward++; 330 } else { 331 ddpstat.ddps_forward++; 332 } 333 return; 334 } 335 336 /* 337 * It was for us, and we have an ifaddr to use with it. 338 */ 339 from.sat_len = sizeof( struct sockaddr_at ); 340 from.sat_family = AF_APPLETALK; 341 342 /* 343 * We are no longer interested in the link layer. 344 * so cut it off. 345 */ 346 if ( elh ) { 347 m_adj( m, sizeof( struct ddpshdr )); 348 } else { 349 if ( ddp_cksum && cksum && cksum != at_cksum( m, sizeof( int ))) { 350 ddpstat.ddps_badsum++; 351 m_freem( m ); 352 return; 353 } 354 m_adj( m, sizeof( struct ddpehdr )); 355 } 356 357 /* 358 * Search for ddp protocol control blocks that match these 359 * addresses. 360 */ 361 if (( ddp = ddp_search( &from, &to, aa )) == NULL ) { 362 m_freem( m ); 363 return; 364 } 365 366#ifdef MAC 367 if (mac_check_socket_deliver(ddp->ddp_socket, m) != 0) { 368 m_freem( m ); 369 return; 370 } 371#endif 372 373 /* 374 * If we found one, deliver th epacket to the socket 375 */ 376 if ( sbappendaddr( &ddp->ddp_socket->so_rcv, (struct sockaddr *)&from, 377 m, (struct mbuf *)0 ) == 0 ) { 378 /* 379 * If the socket is full (or similar error) dump the packet. 380 */ 381 ddpstat.ddps_nosockspace++; 382 m_freem( m ); 383 return; 384 } 385 /* 386 * And wake up whatever might be waiting for it 387 */ 388 sorwakeup( ddp->ddp_socket ); 389} 390 391#if 0 392/* As if we haven't got enough of this sort of think floating 393around the kernel :) */ 394 395#define BPXLEN 48 396#define BPALEN 16 397#include <ctype.h> 398char hexdig[] = "0123456789ABCDEF"; 399 400static void 401bprint( char *data, int len ) 402{ 403 char xout[ BPXLEN ], aout[ BPALEN ]; 404 int i = 0; 405 406 bzero( xout, BPXLEN ); 407 bzero( aout, BPALEN ); 408 409 for ( ;; ) { 410 if ( len < 1 ) { 411 if ( i != 0 ) { 412 printf( "%s\t%s\n", xout, aout ); 413 } 414 printf( "%s\n", "(end)" ); 415 break; 416 } 417 418 xout[ (i*3) ] = hexdig[ ( *data & 0xf0 ) >> 4 ]; 419 xout[ (i*3) + 1 ] = hexdig[ *data & 0x0f ]; 420 421 if ( (u_char)*data < 0x7f && (u_char)*data > 0x20 ) { 422 aout[ i ] = *data; 423 } else { 424 aout[ i ] = '.'; 425 } 426 427 xout[ (i*3) + 2 ] = ' '; 428 429 i++; 430 len--; 431 data++; 432 433 if ( i > BPALEN - 2 ) { 434 printf( "%s\t%s\n", xout, aout ); 435 bzero( xout, BPXLEN ); 436 bzero( aout, BPALEN ); 437 i = 0; 438 continue; 439 } 440 } 441} 442 443static void 444m_printm( struct mbuf *m ) 445{ 446 for (; m; m = m->m_next ) { 447 bprint( mtod( m, char * ), m->m_len ); 448 } 449} 450#endif 451