114ddp_input( m, ifp, elh, phase ) 115 struct mbuf *m; 116 struct ifnet *ifp; 117 struct elaphdr *elh; 118 int phase; 119{ 120 struct sockaddr_at from, to; 121 struct ddpshdr *dsh, ddps; 122 struct at_ifaddr *aa; 123 struct ddpehdr *deh = NULL, ddpe; 124 struct ddpcb *ddp; 125 int dlen, mlen; 126 u_short cksum = 0; 127 128 bzero( (caddr_t)&from, sizeof( struct sockaddr_at )); 129 bzero( (caddr_t)&to, sizeof( struct sockaddr_at )); 130 if ( elh ) { 131 /* 132 * Extract the information in the short header. 133 * netowrk information is defaulted to ATADDR_ANYNET 134 * and node information comes from the elh info. 135 * We must be phase 1. 136 */ 137 ddpstat.ddps_short++; 138 139 if ( m->m_len < sizeof( struct ddpshdr ) && 140 (( m = m_pullup( m, sizeof( struct ddpshdr ))) == 0 )) { 141 ddpstat.ddps_tooshort++; 142 return; 143 } 144 145 dsh = mtod( m, struct ddpshdr *); 146 bcopy( (caddr_t)dsh, (caddr_t)&ddps, sizeof( struct ddpshdr )); 147 ddps.dsh_bytes = ntohl( ddps.dsh_bytes ); 148 dlen = ddps.dsh_len; 149 150 to.sat_addr.s_net = ATADDR_ANYNET; 151 to.sat_addr.s_node = elh->el_dnode; 152 to.sat_port = ddps.dsh_dport; 153 from.sat_addr.s_net = ATADDR_ANYNET; 154 from.sat_addr.s_node = elh->el_snode; 155 from.sat_port = ddps.dsh_sport; 156 157 /* 158 * Make sure that we point to the phase1 ifaddr info 159 * and that it's valid for this packet. 160 */ 161 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { 162 if ( (aa->aa_ifp == ifp) 163 && ( (aa->aa_flags & AFA_PHASE2) == 0) 164 && ( (to.sat_addr.s_node == AA_SAT( aa )->sat_addr.s_node) 165 || (to.sat_addr.s_node == ATADDR_BCAST))) { 166 break; 167 } 168 } 169 /* 170 * maybe we got a broadcast not meant for us.. ditch it. 171 */ 172 if ( aa == NULL ) { 173 m_freem( m ); 174 return; 175 } 176 } else { 177 /* 178 * There was no 'elh' passed on. This could still be 179 * either phase1 or phase2. 180 * We have a long header, but we may be running on a phase 1 net. 181 * Extract out all the info regarding this packet's src & dst. 182 */ 183 ddpstat.ddps_long++; 184 185 if ( m->m_len < sizeof( struct ddpehdr ) && 186 (( m = m_pullup( m, sizeof( struct ddpehdr ))) == 0 )) { 187 ddpstat.ddps_tooshort++; 188 return; 189 } 190 191 deh = mtod( m, struct ddpehdr *); 192 bcopy( (caddr_t)deh, (caddr_t)&ddpe, sizeof( struct ddpehdr )); 193 ddpe.deh_bytes = ntohl( ddpe.deh_bytes ); 194 dlen = ddpe.deh_len; 195 196 if (( cksum = ddpe.deh_sum ) == 0 ) { 197 ddpstat.ddps_nosum++; 198 } 199 200 from.sat_addr.s_net = ddpe.deh_snet; 201 from.sat_addr.s_node = ddpe.deh_snode; 202 from.sat_port = ddpe.deh_sport; 203 to.sat_addr.s_net = ddpe.deh_dnet; 204 to.sat_addr.s_node = ddpe.deh_dnode; 205 to.sat_port = ddpe.deh_dport; 206 207 if ( to.sat_addr.s_net == ATADDR_ANYNET ) { 208 /* 209 * The TO address doesn't specify a net, 210 * So by definition it's for this net. 211 * Try find ifaddr info with the right phase, 212 * the right interface, and either to our node, a broadcast, 213 * or looped back (though that SHOULD be covered in the other 214 * cases). 215 * 216 * XXX If we have multiple interfaces, then the first with 217 * this node number will match (which may NOT be what we want, 218 * but it's probably safe in 99.999% of cases. 219 */ 220 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { 221 if ( phase == 1 && ( aa->aa_flags & AFA_PHASE2 )) { 222 continue; 223 } 224 if ( phase == 2 && ( aa->aa_flags & AFA_PHASE2 ) == 0 ) { 225 continue; 226 } 227 if ( (aa->aa_ifp == ifp) 228 && ( (to.sat_addr.s_node == AA_SAT( aa )->sat_addr.s_node) 229 || (to.sat_addr.s_node == ATADDR_BCAST) 230 || (ifp->if_flags & IFF_LOOPBACK))) { 231 break; 232 } 233 } 234 } else { 235 /* 236 * A destination network was given. We just try to find 237 * which ifaddr info matches it. 238 */ 239 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { 240 /* 241 * This is a kludge. Accept packets that are 242 * for any router on a local netrange. 243 */ 244 if ( to.sat_addr.s_net == aa->aa_firstnet && 245 to.sat_addr.s_node == 0 ) { 246 break; 247 } 248 /* 249 * Don't use ifaddr info for which we are totally outside the 250 * netrange, and it's not a startup packet. 251 * Startup packets are always implicitly allowed on to 252 * the next test. 253 */ 254 if ((( ntohs( to.sat_addr.s_net ) < ntohs( aa->aa_firstnet )) 255 || (ntohs( to.sat_addr.s_net ) > ntohs( aa->aa_lastnet ))) 256 && (( ntohs( to.sat_addr.s_net ) < 0xff00) 257 || (ntohs( to.sat_addr.s_net ) > 0xfffe ))) { 258 continue; 259 } 260 261 /* 262 * Don't record a match either if we just don't have a match 263 * in the node address. This can have if the interface 264 * is in promiscuous mode for example. 265 */ 266 if (( to.sat_addr.s_node != AA_SAT( aa )->sat_addr.s_node) 267 && (to.sat_addr.s_node != ATADDR_BCAST) ) { 268 continue; 269 } 270 break; 271 } 272 } 273 } 274 275 /* 276 * Adjust the length, removing any padding that may have been added 277 * at a link layer. We do this before we attempt to forward a packet, 278 * possibly on a different media. 279 */ 280 mlen = m->m_pkthdr.len; 281 if ( mlen < dlen ) { 282 ddpstat.ddps_toosmall++; 283 m_freem( m ); 284 return; 285 } 286 if ( mlen > dlen ) { 287 m_adj( m, dlen - mlen ); 288 } 289 290 /* 291 * If it aint for a net on any of our interfaces, 292 * or it IS for a net on a different interface than it came in on, 293 * (and it is not looped back) then consider if we should forward it. 294 * As we are not really a router this is a bit cheeky, but it may be 295 * useful some day. 296 */ 297 if ( (aa == NULL) 298 || ( (to.sat_addr.s_node == ATADDR_BCAST) 299 && (aa->aa_ifp != ifp) 300 && (( ifp->if_flags & IFF_LOOPBACK ) == 0 ))) { 301 /* 302 * If we've explicitly disabled it, don't route anything 303 */ 304 if ( ddp_forward == 0 ) { 305 m_freem( m ); 306 return; 307 } 308 /* 309 * If the cached forwarding route is still valid, use it. 310 */ 311 if ( forwro.ro_rt 312 && ( satosat(&forwro.ro_dst)->sat_addr.s_net != to.sat_addr.s_net 313 || satosat(&forwro.ro_dst)->sat_addr.s_node != to.sat_addr.s_node )) { 314 RTFREE( forwro.ro_rt ); 315 forwro.ro_rt = (struct rtentry *)0; 316 } 317 318 /* 319 * If we don't have a cached one (any more) or it's useless, 320 * Then get a new route. 321 * XXX this could cause a 'route leak'. check this! 322 */ 323 if ( forwro.ro_rt == (struct rtentry *)0 324 || forwro.ro_rt->rt_ifp == (struct ifnet *)0 ) { 325 forwro.ro_dst.sa_len = sizeof( struct sockaddr_at ); 326 forwro.ro_dst.sa_family = AF_APPLETALK; 327 satosat(&forwro.ro_dst)->sat_addr.s_net = to.sat_addr.s_net; 328 satosat(&forwro.ro_dst)->sat_addr.s_node = to.sat_addr.s_node; 329 rtalloc(&forwro); 330 } 331 332 /* 333 * If it's not going to get there on this hop, and it's 334 * already done too many hops, then throw it away. 335 */ 336 if ( (to.sat_addr.s_net != satosat( &forwro.ro_dst )->sat_addr.s_net) 337 && (ddpe.deh_hops == DDP_MAXHOPS) ) { 338 m_freem( m ); 339 return; 340 } 341 342 /* 343 * A ddp router might use the same interface 344 * to forward the packet, which this would not effect. 345 * Don't allow packets to cross from one interface to another however. 346 */ 347 if ( ddp_firewall 348 && ( (forwro.ro_rt == NULL) 349 || (forwro.ro_rt->rt_ifp != ifp))) { 350 m_freem( m ); 351 return; 352 } 353 354 /* 355 * Adjust the header. 356 * If it was a short header then it would have not gotten here, 357 * so we can assume there is room to drop the header in. 358 * XXX what about promiscuous mode, etc... 359 */ 360 ddpe.deh_hops++; 361 ddpe.deh_bytes = htonl( ddpe.deh_bytes ); 362 bcopy( (caddr_t)&ddpe, (caddr_t)deh, sizeof( u_short )); /* XXX deh? */ 363 if ( ddp_route( m, &forwro )) { 364 ddpstat.ddps_cantforward++; 365 } else { 366 ddpstat.ddps_forward++; 367 } 368 return; 369 } 370 371 /* 372 * It was for us, and we have an ifaddr to use with it. 373 */ 374 from.sat_len = sizeof( struct sockaddr_at ); 375 from.sat_family = AF_APPLETALK; 376 377 /* 378 * We are no longer interested in the link layer. 379 * so cut it off. 380 */ 381 if ( elh ) { 382 m_adj( m, sizeof( struct ddpshdr )); 383 } else { 384 if ( ddp_cksum && cksum && cksum != at_cksum( m, sizeof( int ))) { 385 ddpstat.ddps_badsum++; 386 m_freem( m ); 387 return; 388 } 389 m_adj( m, sizeof( struct ddpehdr )); 390 } 391 392 /* 393 * Search for ddp protocol control blocks that match these 394 * addresses. 395 */ 396 if (( ddp = ddp_search( &from, &to, aa )) == NULL ) { 397 m_freem( m ); 398 return; 399 } 400 401#ifdef MAC 402 if (mac_check_socket_deliver(ddp->ddp_socket, m) != 0) { 403 m_freem( m ); 404 return; 405 } 406#endif 407 408 /* 409 * If we found one, deliver th epacket to the socket 410 */ 411 if ( sbappendaddr( &ddp->ddp_socket->so_rcv, (struct sockaddr *)&from, 412 m, (struct mbuf *)0 ) == 0 ) { 413 /* 414 * If the socket is full (or similar error) dump the packet. 415 */ 416 ddpstat.ddps_nosockspace++; 417 m_freem( m ); 418 return; 419 } 420 /* 421 * And wake up whatever might be waiting for it 422 */ 423 sorwakeup( ddp->ddp_socket ); 424} 425 426#if 0 427/* As if we haven't got enough of this sort of think floating 428around the kernel :) */ 429 430#define BPXLEN 48 431#define BPALEN 16 432#include <ctype.h> 433char hexdig[] = "0123456789ABCDEF"; 434 435static void 436bprint( char *data, int len ) 437{ 438 char xout[ BPXLEN ], aout[ BPALEN ]; 439 int i = 0; 440 441 bzero( xout, BPXLEN ); 442 bzero( aout, BPALEN ); 443 444 for ( ;; ) { 445 if ( len < 1 ) { 446 if ( i != 0 ) { 447 printf( "%s\t%s\n", xout, aout ); 448 } 449 printf( "%s\n", "(end)" ); 450 break; 451 } 452 453 xout[ (i*3) ] = hexdig[ ( *data & 0xf0 ) >> 4 ]; 454 xout[ (i*3) + 1 ] = hexdig[ *data & 0x0f ]; 455 456 if ( (u_char)*data < 0x7f && (u_char)*data > 0x20 ) { 457 aout[ i ] = *data; 458 } else { 459 aout[ i ] = '.'; 460 } 461 462 xout[ (i*3) + 2 ] = ' '; 463 464 i++; 465 len--; 466 data++; 467 468 if ( i > BPALEN - 2 ) { 469 printf( "%s\t%s\n", xout, aout ); 470 bzero( xout, BPXLEN ); 471 bzero( aout, BPALEN ); 472 i = 0; 473 continue; 474 } 475 } 476} 477 478static void 479m_printm( struct mbuf *m ) 480{ 481 for (; m; m = m->m_next ) { 482 bprint( mtod( m, char * ), m->m_len ); 483 } 484} 485#endif
| 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
|