1/* 2 * Copyright (c) 2000-2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * Modified for MP, 1996 by Tuyen Nguyen 30 * Added AURP support, April 8, 1996 by Tuyen Nguyen 31 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX. 32 */ 33 34#define RESOLVE_DBG /* define debug globals in debug.h */ 35 36#include <sys/errno.h> 37#include <sys/types.h> 38#include <sys/param.h> 39#include <machine/spl.h> 40#include <sys/systm.h> 41#include <sys/kernel.h> 42#include <sys/proc.h> 43#include <sys/filedesc.h> 44#include <sys/fcntl.h> 45#include <sys/mbuf.h> 46#include <sys/ioctl.h> 47#include <sys/malloc.h> 48#include <sys/socket.h> 49#include <sys/socketvar.h> 50#include <sys/protosw.h> 51 52#include <net/if.h> 53#include <net/dlil.h> 54 55#include <netat/sysglue.h> 56#include <netat/appletalk.h> 57#include <netat/at_pcb.h> 58#include <netat/at_var.h> 59#include <netat/ddp.h> 60#include <netat/ep.h> 61#include <netat/nbp.h> 62#include <netat/rtmp.h> 63#include <netat/zip.h> 64#include <netat/routing_tables.h> 65#include <netat/at_snmp.h> 66#include <netat/aurp.h> 67#include <netat/debug.h> 68#include <netat/at_ddp_brt.h> 69#include <netat/at_aarp.h> 70#include <netat/adsp.h> 71#include <netat/adsp_internal.h> 72#include <netat/at_pat.h> 73#include <netat/atp.h> 74 75#include <net/kpi_protocol.h> 76 77/* globals */ 78 79/* Queue of LAP interfaces which have registered themselves with DDP */ 80struct at_ifQueueHd at_ifQueueHd; 81 82extern TAILQ_HEAD(name_registry, _nve_) name_registry; 83 84snmpStats_t snmpStats; /* snmp ddp & echo stats */ 85 86extern at_ddp_stats_t at_ddp_stats; /* DDP statistics */ 87extern struct atpcb ddp_head; 88extern at_ifaddr_t *ifID_home, *ifID_table[]; 89extern aarp_amt_array *aarp_table[]; 90extern at_ifaddr_t at_interfaces[]; 91 92/* routing mode special */ 93void (*ddp_AURPsendx)(void) = NULL; 94at_ifaddr_t *aurp_ifID = 0; 95 96int pktsIn = 0; 97int pktsOut = 0; 98int pktsDropped = 0; 99int pktsHome = 0; 100 101extern int *atp_pidM; 102extern int *adsp_pidM; 103extern struct atpcb *atp_inputQ[]; 104extern CCB *adsp_inputQ[]; 105 106static void fillin_pkt_chain(gbuf_t *); 107static int ot_ddp_check_socket(unsigned char ,int pid); 108 109 110struct { 111 ddp_handler_func func; 112} ddp_handler[256]; 113 114void init_ddp_handler(void) 115{ 116 bzero(ddp_handler, sizeof(ddp_handler)); 117} 118 119void add_ddp_handler(ddp_socket, input_func) 120 u_char ddp_socket; 121 ddp_handler_func input_func; 122{ 123 ddp_handler[ddp_socket].func = input_func; 124} 125 126void 127ddp_slowtimo() 128{ 129 ddp_brt_sweep(); 130} 131 132/* 133 * Raw DDP socket option processing. 134 */ 135int ddp_ctloutput(so, sopt) 136 struct socket *so; 137 struct sockopt *sopt; 138{ 139 struct atpcb *at_pcb = sotoatpcb(so); 140 int optval, error = 0; 141 142 if (sopt->sopt_level != ATPROTO_NONE) 143 return (EINVAL); 144 145 switch (sopt->sopt_dir) { 146 147 case SOPT_GET: 148 switch (sopt->sopt_name) { 149 case DDP_HDRINCL: 150 optval = at_pcb->ddp_flags & DDPFLG_HDRINCL; 151 error = sooptcopyout(sopt, &optval, sizeof optval); 152 break; 153 case DDP_CHKSUM_ON: 154 optval = at_pcb->ddp_flags & DDPFLG_CHKSUM; 155 error = sooptcopyout(sopt, &optval, sizeof optval); 156 break; 157 case DDP_STRIPHDR: 158 optval = at_pcb->ddp_flags & DDPFLG_STRIPHDR; 159 error = sooptcopyout(sopt, &optval, sizeof optval); 160 break; 161 case DDP_SLFSND_ON: 162 optval = at_pcb->ddp_flags & DDPFLG_SLFSND; 163 error = sooptcopyout(sopt, &optval, sizeof optval); 164 break; 165 case DDP_GETSOCKNAME: 166 { 167 ddp_addr_t addr; 168 addr.inet.net = at_pcb->laddr.s_net; 169 addr.inet.node = at_pcb->laddr.s_node; 170 addr.inet.socket = at_pcb->lport; 171 addr.ddptype = at_pcb->ddptype; 172 error = sooptcopyout(sopt, &addr, sizeof addr); 173 } 174 break; 175 default: 176 error = ENOPROTOOPT; 177 break; 178 } 179 break; 180 case SOPT_SET: 181 switch (sopt->sopt_name) { 182 case DDP_HDRINCL: 183 error = sooptcopyin(sopt, &optval, sizeof optval, 184 sizeof optval); 185 if (error) 186 break; 187 if (optval) 188 at_pcb->ddp_flags |= DDPFLG_HDRINCL; 189 else 190 at_pcb->ddp_flags &= ~DDPFLG_HDRINCL; 191 break; 192 case DDP_CHKSUM_ON: 193 error = sooptcopyin(sopt, &optval, sizeof optval, 194 sizeof optval); 195 if (error) 196 break; 197 if (optval) 198 at_pcb->ddp_flags |= DDPFLG_CHKSUM; 199 else 200 at_pcb->ddp_flags &= ~DDPFLG_CHKSUM; 201 break; 202 case DDP_STRIPHDR: 203 error = sooptcopyin(sopt, &optval, sizeof optval, 204 sizeof optval); 205 if (error) 206 break; 207 if (optval) 208 at_pcb->ddp_flags |= DDPFLG_STRIPHDR; 209 else 210 at_pcb->ddp_flags &= ~DDPFLG_STRIPHDR; 211 break; 212 case DDP_SLFSND_ON: 213 error = sooptcopyin(sopt, &optval, sizeof optval, 214 sizeof optval); 215 if (error) 216 break; 217 if (optval) 218 at_pcb->ddp_flags |= DDPFLG_SLFSND; 219 else 220 at_pcb->ddp_flags &= ~DDPFLG_SLFSND; 221 break; 222 default: 223 error = ENOPROTOOPT; 224 break; 225 } 226 break; 227 } 228 229 return(error); 230} /* ddp_cloutput */ 231 232/****************************************************************/ 233/* */ 234/* */ 235/* Support Routines */ 236/* */ 237/* */ 238/****************************************************************/ 239 240/* 241 * Name: 242 * ddp_checksum 243 * 244 * Description: 245 * This procedure determines the checksum of an extended DDP datagram. 246 * Add the unsigned bytes into an unsigned 16-bit accumulator. 247 * After each add, rotate the sign bit into the low order bit of 248 * the accumulator. When done, if the checksum is 0, changed into 0xFFFF. 249 * 250 * Calling sequence: 251 * checksum = ddp_checksum(mp, offset) 252 * 253 * Parameters: 254 * mp pointer to the datagram gbuf_t 255 * offset offset to start at in first gbuf_t block 256 * 257 * Return value: 258 * The DDP checksum. 259 * 260 */ 261 262u_short ddp_checksum(mp, offset) 263 register gbuf_t *mp; 264 register int offset; 265{ 266 register u_char *data; 267 register int length; 268 register u_short checksum; 269 270 checksum = 0; 271 272 do { 273 if (offset >= gbuf_len(mp)) 274 offset -= gbuf_len(mp); 275 else { 276 data = ((unsigned char *) gbuf_rptr(mp)) + offset; 277 length = gbuf_len(mp) - offset; 278 offset = 0; 279 /* Portable checksum from 3.0 */ 280 while (length--) { 281 checksum += *data++; 282 checksum = (checksum & 0x8000) ? 283 ((checksum << 1) | 1) : (checksum << 1); 284 } 285 } 286 } while ( (mp = gbuf_cont(mp)) ); 287 288 if (checksum == 0) 289 checksum = 0xffff; 290 291 return(checksum); 292} 293 294/* 295 * ddp_add_if() 296 * 297 * Description: 298 * This procedure is called by each LAP interface when it wants to place 299 * itself online. The LAP interfaces passes in a pointer to its at_if 300 * struct, which is added to DDP's list of active interfaces (at_ifQueueHd). 301 * When DDP wants to transmit a packet, it searches this list for the 302 * interface to use. 303 * 304 * If AT_IFF_DEFAULT is set, then this interface is to be brought online 305 * as the interface DDP socket addresses are tied to. Of course there can 306 * be only one default interface; we return an error if it's already set. 307 * 308 * Calling Sequence: 309 * ret_status = ddp_add_if(ifID) 310 * 311 * Formal Parameters: 312 * ifID pointer to LAP interface's at_if struct. 313 * 314 * Completion Status: 315 * 0 Procedure successfully completed. 316 * EALREADY This interface is already online, or there is 317 * already a default interface. 318 * ENOBUFS Cannot allocate input queue 319 * 320 */ 321int ddp_add_if(ifID) 322register at_ifaddr_t *ifID; 323{ 324 int port = -1; 325 326 dPrintf(D_M_DDP, D_L_STARTUP, 327 ("ddp_add_if: called, ifID:0x%x\n", (u_int) ifID)); 328 329 if (ifID->ifFlags & AT_IFF_DEFAULT) { 330 if (ifID_home) 331 return(EEXIST); /* home port already set */ 332 else { 333 port = IFID_HOME; 334 ifID_home = ifID; 335 } 336 } else { 337 for (port=IFID_HOME+1; port<IF_TOTAL_MAX; port++) 338 if (!ifID_table[port]) { 339 break; 340 } 341 if (port == IF_TOTAL_MAX) /* no space left */ 342 return(ENOMEM); 343 } 344 345 /* allocate an et_aarp_amt structure */ 346 if ((aarp_table[port] = 347 (aarp_amt_array *)_MALLOC(sizeof(aarp_amt_array), 348 M_RTABLE, M_WAITOK)) == NULL) 349 return(ENOMEM); 350 351 dPrintf(D_M_DDP, D_L_STARTUP, ("ddp:adding ifID_table[%d]\n", port)); 352 353 /* add i/f to port list */ 354 ifID_table[port] = ifID; 355 ifID->ifPort = port; /* set ddp port # in ifID */ 356 357 /* Add this interface to the list of online interfaces */ 358 TAILQ_INSERT_TAIL(&at_ifQueueHd, ifID, aa_link); 359 360 return (0); 361} /* ddp_add_if */ 362 363/* 364 * ddp_rem_if() 365 * 366 * Description: 367 * This procedure is called by each LAP interface when it wants to take 368 * itself offline. The LAP interfaces passes in a pointer to its at_if 369 * struct; DDP's list of active interfaces (at_ifQueueHd) is searched and 370 * this interface is removed from the list. DDP can still transmit 371 * packets as long as this interface is not the default interface; the 372 * sender will just get ENETUNREACH errors when it tries to send to an 373 * interface that went offline. However, if the default interface is 374 * taken offline, we no longer have a node ID to use as a source address 375 * and DDP must return ENETDOWN when a caller tries to send a packet. 376 * 377 * Formal Parameters: 378 * ifID pointer to LAP interface's at_if struct. 379 */ 380 381void ddp_rem_if(ifID) 382 register at_ifaddr_t *ifID; 383{ 384 struct ifaddr *ifa = &ifID->aa_ifa; 385 386 /* un-do processing done in SIOCSIFADDR */ 387 ifnet_lock_exclusive(ifID->aa_ifp); 388 IFA_LOCK(ifa); 389 if (ifa->ifa_debug & IFD_ATTACHED) { 390 if_detach_ifa(ifID->aa_ifp, ifa); 391 ifa->ifa_addr = NULL; 392 } 393 IFA_UNLOCK(ifa); 394 /* release reference held for at_interfaces[] */ 395 IFA_REMREF(ifa); 396 ifnet_lock_done(ifID->aa_ifp); 397 398 if (ifID->at_was_attached == 0 && ifID->aa_ifp != NULL) { 399 (void)proto_unplumb(PF_APPLETALK, ifID->aa_ifp); 400 } 401 402 /* un-do processing done in ddp_add_if() */ 403 if (ifID->ifPort) { 404 if (aarp_table[ifID->ifPort]) { 405 FREE(aarp_table[ifID->ifPort], M_RTABLE); 406 aarp_table[ifID->ifPort] = NULL; 407 } 408 409 at_state.flags |= AT_ST_IF_CHANGED; 410 ifID->aa_ifp = NULL; 411 412 trackrouter_rem_if(ifID); 413 TAILQ_REMOVE(&at_ifQueueHd, ifID, aa_link); 414 ifID_table[ifID->ifPort] = NULL; 415 ifID->ifName[0] = '\0'; 416 ifID->ifPort = 0; 417 } 418 419 /* *** deallocate ifID, eventually *** */ 420} /* ddp_rem_if */ 421 422/* 423 * The user may have registered an NVE with the NBP on a socket. When the 424 * socket is closed, the NVE should be deleted from NBP's name table. The 425 * user should delete the NVE before the socket is shut down, but there 426 * may be circumstances when they can't. So, whenever a DDP socket is closed, 427 * this routine is used to notify NBP of the socket closure. This would 428 * help NBP get rid of all NVE's registered on the socket. 429 */ 430 431/* *** Do we still need to do this? *** */ 432static int ot_ddp_check_socket(socket, pid) 433 unsigned char socket; 434 int pid; 435{ 436 int cnt = 0; 437 gref_t *gref; 438 439 dPrintf(D_M_DDP, D_L_INFO, ("ot_ddp_check_socket: %d\n", socket)); 440 for (gref = ddp_head.atpcb_next; gref != &ddp_head; gref = gref->atpcb_next) 441 if (gref->lport == socket && gref->pid == pid) 442 cnt++; 443 if ((atp_inputQ[socket] != NULL) && (atp_inputQ[socket] != (gref_t *)1) 444 && (atp_pidM[socket] == pid)) 445 cnt++; 446 if ((adsp_inputQ[socket] != NULL) && (adsp_pidM[socket] == pid)) 447 cnt++; 448 449 return(cnt); 450} 451 452void ddp_notify_nbp( 453 unsigned char socket, 454 int pid, 455 __unused unsigned char ddptype) 456{ 457 nve_entry_t *nve_entry, *nve_next; 458 459 if (at_state.flags & AT_ST_STARTED) { 460 /* *** NBP_CLOSE_NOTE processing (from ddp_nbp.c) *** */ 461 for ((nve_entry = TAILQ_FIRST(&name_registry)); nve_entry; nve_entry = nve_next) { 462 nve_next = TAILQ_NEXT(nve_entry, nve_link); 463 if ((at_socket)socket == nve_entry->address.socket && 464 /* *** check complete address and ddptype here *** */ 465 pid == nve_entry->pid && 466 ot_ddp_check_socket(nve_entry->address.socket, 467 nve_entry->pid) < 2) { 468 /* NB: nbp_delete_entry calls TAILQ_REMOVE */ 469 nbp_delete_entry(nve_entry); 470 } 471 } 472 } 473} /* ddp_notify_nbp */ 474 475static void fillin_pkt_chain(m) 476 gbuf_t *m; 477{ 478 gbuf_t *tmp_m = m; 479 register at_ddp_t 480 *ddp = (at_ddp_t *)gbuf_rptr(m), 481 *tmp_ddp; 482 u_short tmp; 483 484 if (UAS_VALUE(ddp->checksum)) { 485 tmp = ddp_checksum(m, 4); 486 UAS_ASSIGN_HTON(ddp->checksum, tmp); 487 } 488 489 for (tmp_m=gbuf_next(tmp_m); tmp_m; tmp_m=gbuf_next(tmp_m)) { 490 tmp_ddp = (at_ddp_t *)gbuf_rptr(tmp_m); 491 DDPLEN_ASSIGN(tmp_ddp, gbuf_msgsize(tmp_m)); 492 tmp_ddp->hopcount = 493 tmp_ddp->unused = 0; 494 NET_NET(tmp_ddp->src_net, ddp->src_net); 495 tmp_ddp->src_node = ddp->src_node; 496 tmp_ddp->src_socket = ddp->src_socket; 497 if (UAS_VALUE(tmp_ddp->checksum)) { 498 tmp = ddp_checksum(tmp_m, 4); 499 UAS_ASSIGN_HTON(ddp->checksum, tmp); 500 } 501 } 502} 503 504/* There are various ways a packet may go out.... it may be sent out 505 * directly to destination node, or sent to a random router or sent 506 * to a router whose entry exists in Best Router Cache. Following are 507 * constants used WITHIN this routine to keep track of choice of destination 508 */ 509#define DIRECT_ADDR 1 510#define BRT_ENTRY 2 511#define BRIDGE_ADDR 3 512 513/* 514 * ddp_output() 515 * 516 * Remarks : 517 * Called to queue a atp/ddp data packet on the network interface. 518 * It returns 0 normally, and an errno in case of error. 519 * The mbuf chain pointed to by *mp is consumed on success, and 520 * freed in case of error. 521 * 522 */ 523int ddp_output(mp, src_socket, src_addr_included) 524 register gbuf_t **mp; 525 at_socket src_socket; 526 int src_addr_included; 527{ 528 register at_ifaddr_t *ifID = ifID_home, *ifIDTmp = NULL; 529 register at_ddp_t *ddp; 530 register ddp_brt_t *brt = NULL; 531 register at_net_al dst_net; 532 register int len; 533 struct atalk_addr at_dest; 534 at_ifaddr_t *ARouterIf = NULL; 535 int loop = 0; 536 int error = 0; 537 int addr_type; 538 u_char addr_flag = 0; 539 char *addr = NULL; 540 register gbuf_t *m; 541 542 KERNEL_DEBUG(DBG_AT_DDP_OUTPUT | DBG_FUNC_START, 0, 543 0,0,0,0); 544 545 snmpStats.dd_outReq++; 546 547 m = *mp; 548 ddp = (at_ddp_t *)gbuf_rptr(m); 549 550 if (!ifID) { 551 /* Device/Interface not configured */ 552 dPrintf(D_M_DDP, D_L_ERROR, ("Device/Interface not configured")); 553 error = ENXIO; 554 gbuf_freel(*mp); 555 goto exit_ddp_output; 556 } 557 558 if ((ddp->dst_socket > (unsigned) (DDP_SOCKET_LAST + 1)) || 559 (ddp->dst_socket < DDP_SOCKET_1st_RESERVED)) { 560 dPrintf(D_M_DDP, D_L_ERROR, 561 ("Illegal destination socket on outgoing packet (0x%x)", 562 ddp->dst_socket)); 563 at_ddp_stats.xmit_bad_addr++; 564 error = ENOTSOCK; 565 gbuf_freel(*mp); 566 goto exit_ddp_output; 567 } 568 if ((len = gbuf_msgsize(*mp)) > DDP_DATAGRAM_SIZE) { 569 /* the packet is too large */ 570 dPrintf(D_M_DDP, D_L_ERROR, 571 ("Outgoing packet too long (len=%d bytes)", len)); 572 at_ddp_stats.xmit_bad_length++; 573 error = EMSGSIZE; 574 gbuf_freel(*mp); 575 goto exit_ddp_output; 576 } 577 at_ddp_stats.xmit_bytes += len; 578 at_ddp_stats.xmit_packets++; 579 580 DDPLEN_ASSIGN(ddp, len); 581 ddp->hopcount = 582 ddp->unused = 0; 583 584 /* If this packet is for the same node, loop it back 585 * up... Note that for LocalTalk, dst_net zero means "THIS_NET", so 586 * address 0.nn is eligible for loopback. For Extended EtherTalk, 587 * dst_net 0 can be used only for cable-wide or zone-wide 588 * broadcasts (0.ff) and as such, address of the form 0.nn is NOT 589 * eligible for loopback. 590 */ 591 dst_net = NET_VALUE(ddp->dst_net); 592 593 /* If our packet is destined for the 'virtual' bridge 594 * address of NODE==0xFE, replace that address with a 595 * real bridge address. 596 */ 597 if ((ddp->dst_node == 0xfe) && 598 ((dst_net == ATADDR_ANYNET) || 599 (dst_net >= ifID_home->ifThisCableStart && 600 dst_net <= ifID_home->ifThisCableEnd))) { 601 /* if there's a router that's not us, it's in ifID_home */ 602 NET_ASSIGN(ddp->dst_net, ifID_home->ifARouter.s_net); 603 dst_net = ifID_home->ifARouter.s_net; 604 ddp->dst_node = ifID_home->ifARouter.s_node; 605 } 606 607 if (MULTIHOME_MODE && (ifIDTmp = forUs(ddp))) { 608 ifID = ifIDTmp; 609 loop = TRUE; 610 dPrintf(D_M_DDP_LOW, D_L_USR1, 611 ("ddp_out: for us if:%s\n", ifIDTmp->ifName)); 612 } 613 614 if (!loop) 615 loop = ((ddp->dst_node == ifID->ifThisNode.s_node) && 616 (dst_net == ifID->ifThisNode.s_net) 617 ); 618 if (loop) { 619 gbuf_t *mdata, *mdata_next; 620 621 if (!MULTIHOME_MODE || !src_addr_included) { 622 NET_ASSIGN(ddp->src_net, ifID->ifThisNode.s_net); 623 ddp->src_node = ifID->ifThisNode.s_node; 624 } 625 ddp->src_socket = src_socket; 626 627 dPrintf(D_M_DDP_LOW, D_L_OUTPUT, 628 ("ddp_output: loop to %d:%d port=%d\n", 629 NET_VALUE(ddp->dst_net), 630 ddp->dst_node, 631 ifID->ifPort)); 632 633 fillin_pkt_chain(*mp); 634 635 dPrintf(D_M_DDP, D_L_VERBOSE, 636 ("Looping back packet from skt 0x%x to skt 0x%x\n", 637 ddp->src_socket, ddp->dst_socket)); 638 639 for (mdata = *mp; mdata; mdata = mdata_next) { 640 mdata_next = gbuf_next(mdata); 641 gbuf_next(mdata) = 0; 642 ddp_input(mdata, ifID); 643 } 644 goto exit_ddp_output; 645 } 646 if ((ddp->dst_socket == ZIP_SOCKET) && 647 (zip_type_packet(*mp) == ZIP_GETMYZONE)) { 648 ddp->src_socket = src_socket; 649 error = zip_handle_getmyzone(ifID, *mp); 650 gbuf_freel(*mp); 651 goto exit_ddp_output; 652 } 653 /* 654 * find out the interface on which the packet should go out 655 */ 656 TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) { 657 if ((ifID->ifThisNode.s_net == dst_net) || (dst_net == 0)) 658 /* the message is either going out (i) on the same 659 * NETWORK in case of LocalTalk, or (ii) on the same 660 * CABLE in case of Extended AppleTalk (EtherTalk). 661 */ 662 break; 663 664 if ((ifID->ifThisCableStart <= dst_net) && 665 (ifID->ifThisCableEnd >= dst_net) 666 ) 667 /* We're on EtherTalk and the message is going out to 668 * some other network on the same cable. 669 */ 670 break; 671 672 if (ARouterIf == NULL && ATALK_VALUE(ifID->ifARouter)) 673 ARouterIf = ifID; 674 } 675 dPrintf(D_M_DDP_LOW, D_L_USR1, 676 ("ddp_output: after search ifid:0x%x %s ifID_home:0x%x\n", 677 (u_int)ifID, ifID ? ifID->ifName : "", 678 (u_int)ifID_home)); 679 680 if (ifID) { 681 /* located the interface where the packet should 682 * go.... the "first-hop" destination address 683 * must be the same as real destination address. 684 */ 685 addr_type = DIRECT_ADDR; 686 } else { 687 /* no, the destination network number does 688 * not match known network numbers. If we have 689 * heard from this network recently, BRT table 690 * may have address of a router we could use! 691 */ 692 if (!MULTIPORT_MODE) { 693 BRT_LOOK (brt, dst_net); 694 if (brt) { 695 /* Bingo... BRT has an entry for this network. 696 * Use the link address as is. 697 */ 698 dPrintf(D_M_DDP, D_L_VERBOSE, 699 ("Found BRT entry to send to net 0x%x", dst_net)); 700 at_ddp_stats.xmit_BRT_used++; 701 addr_type = BRT_ENTRY; 702 ifID = brt->ifID; 703 } else { 704 /* No BRT entry available for dest network... do we 705 * know of any router at all?? 706 */ 707 if ((ifID = ARouterIf) != NULL) 708 addr_type = BRIDGE_ADDR; 709 else { 710 dPrintf(D_M_DDP, D_L_WARNING, 711 ("Found no interface to send pkt")); 712 at_ddp_stats.xmit_bad_addr++; 713 error = ENETUNREACH; 714 gbuf_freel(*mp); 715 goto exit_ddp_output; 716 } 717 } 718 } 719 else { /* We are in multiport mode, so we can bypass all the rest 720 * and directly ask for the routing of the packet 721 */ 722 at_ddp_stats.xmit_BRT_used++; 723 724 ifID = ifID_home; 725 if (!src_addr_included) { 726 ddp->src_node = ifID->ifThisNode.s_node; 727 NET_ASSIGN(ddp->src_net, ifID->ifThisNode.s_net); 728 } 729 ddp->src_socket = src_socket; 730 routing_needed(*mp, ifID, TRUE); 731 732 goto exit_ddp_output; 733 } 734 } 735 /* by the time we land here, we know the interface on 736 * which this packet is going out.... ifID. 737 */ 738 if (ifID->ifState == LAP_OFFLINE) { 739 gbuf_freel(*mp); 740 goto exit_ddp_output; 741 } 742 743 switch (addr_type) { 744 case DIRECT_ADDR : 745/* 746 at_dest.atalk_unused = 0; 747*/ 748 NET_ASSIGN(at_dest.atalk_net, dst_net); 749 at_dest.atalk_node = ddp->dst_node; 750 addr_flag = AT_ADDR; 751 addr = (char *)&at_dest; 752 break; 753 case BRT_ENTRY : 754 addr_flag = ET_ADDR; 755 addr = (char *)&brt->et_addr; 756 break; 757 case BRIDGE_ADDR : 758 NET_ASSIGN(at_dest.atalk_net, ifID->ifARouter.s_net); 759 at_dest.atalk_node = ifID->ifARouter.s_node; 760 addr_flag = AT_ADDR; 761 addr = (char *)&at_dest; 762 break; 763 764 } 765 /* Irrespective of the interface on which 766 * the packet is going out, we always put the 767 * same source address on the packet (unless multihoming mode). 768 */ 769 if (MULTIHOME_MODE) { 770 if (!src_addr_included) { 771 ddp->src_node = ifID->ifThisNode.s_node; 772 NET_ASSIGN(ddp->src_net, ifID->ifThisNode.s_net); 773 } 774 } 775 else { 776 ddp->src_node = ifID_home->ifThisNode.s_node; 777 NET_ASSIGN(ddp->src_net, ifID_home->ifThisNode.s_net); 778 } 779 ddp->src_socket = src_socket; 780 781 dPrintf(D_M_DDP_LOW, D_L_OUTPUT, 782 ("ddp_output: going out to %d:%d skt%d on %s\n", 783 dst_net, ddp->dst_node, ddp->dst_socket, ifID->ifName)); 784 785 fillin_pkt_chain(*mp); 786 787 { /* begin block */ 788 struct etalk_addr dest_addr; 789 struct atalk_addr dest_at_addr; 790 791 loop = TRUE; /* flag to aarp to loopback (default) */ 792 793 m = *mp; 794 795 /* the incoming frame is of the form {flag, address, ddp...} 796 * where "flag" indicates whether the address is an 802.3 797 * (link) address, or an appletalk address. If it's an 798 * 802.3 address, the packet can just go out to the network 799 * through PAT, if it's an appletalk address, AT->802.3 address 800 * resolution needs to be done. 801 * If 802.3 address is known, strip off the flag and 802.3 802 * address, and prepend 802.2 and 802.3 headers. 803 */ 804 805 if (addr == NULL) { 806 addr_flag = *(u_char *)gbuf_rptr(m); 807 gbuf_rinc(m,1); 808 } 809 810 switch (addr_flag) { 811 case AT_ADDR_NO_LOOP : 812 loop = FALSE; 813 /* pass thru */ 814 case AT_ADDR : 815 if (addr == NULL) { 816 dest_at_addr = *(struct atalk_addr *)gbuf_rptr(m); 817 gbuf_rinc(m,sizeof(struct atalk_addr)); 818 } else 819 dest_at_addr = *(struct atalk_addr *)addr; 820 break; 821 case ET_ADDR : 822 if (addr == NULL) { 823 dest_addr = *(struct etalk_addr *)gbuf_rptr(m); 824 gbuf_rinc(m,sizeof(struct etalk_addr)); 825 } else 826 dest_addr = *(struct etalk_addr *)addr; 827 break; 828 default : 829 dPrintf(D_M_DDP_LOW,D_L_ERROR, 830 ("ddp_output: Unknown addr_flag = 0x%x\n", addr_flag)); 831 gbuf_freel(m); /* unknown address type, chuck it */ 832 goto exit_ddp_output; 833 } 834 835 m = gbuf_strip(m); 836 837 /* At this point, rptr points to ddp header for sure */ 838 if (ifID->ifState == LAP_ONLINE_FOR_ZIP) { 839 /* see if this is a ZIP packet that we need 840 * to let through even though network is 841 * not yet alive!! 842 */ 843 if (zip_type_packet(m) == 0) { 844 gbuf_freel(m); 845 goto exit_ddp_output; 846 } 847 } 848 849 ifID->stats.xmit_packets++; 850 ifID->stats.xmit_bytes += gbuf_msgsize(m); 851 snmpStats.dd_outLong++; 852 853 switch (addr_flag) { 854 case AT_ADDR_NO_LOOP : 855 case AT_ADDR : 856 /* 857 * we don't want elap to be looking into ddp header, so 858 * it doesn't know net#, consequently can't do 859 * AMT_LOOKUP. That task left to aarp now. 860 */ 861 aarp_send_data(m,ifID, &dest_at_addr, loop); 862 break; 863 case ET_ADDR : 864 pat_output(ifID, m, (unsigned char *)&dest_addr, 0); 865 break; 866 } 867 } /* end block */ 868 exit_ddp_output: 869 KERNEL_DEBUG(DBG_AT_DDP_OUTPUT | DBG_FUNC_END, 0, 870 error, 0, 0, 0); 871 return(error); 872} /* ddp_output */ 873 874void ddp_input(mp, ifID) 875 register gbuf_t *mp; 876 register at_ifaddr_t *ifID; 877{ 878 register at_ddp_t *ddp; /* DDP header */ 879 register int msgsize; 880 register at_socket socket; 881 register int len; 882 register at_net_al dst_net; 883 884 KERNEL_DEBUG(DBG_AT_DDP_INPUT | DBG_FUNC_START, 0, 885 ifID, mp, gbuf_len(mp),0); 886 887 /* Makes sure we know the default interface before starting to 888 * accept incomming packets. If we don't we may end up with a 889 * null ifID_table[0] and have impredicable results (specially 890 * in router mode. This is a transitory state (because we can 891 * begin to receive packet while we're not completly set up yet. 892 */ 893 894 if (ifID_home == (at_ifaddr_t *)NULL) { 895 dPrintf(D_M_DDP, D_L_ERROR, 896 ("dropped incoming packet ifID_home not set yet\n")); 897 gbuf_freem(mp); 898 goto out; /* return */ 899 } 900 901 /* 902 * if a DDP packet has been broadcast, we're going to get a copy of 903 * it here; if it originated at user level via a write on a DDP 904 * socket; when it gets here, the first block in the chain will be 905 * empty since it only contained the lap level header which will be 906 * stripped in the lap level immediately below ddp 907 */ 908 909 if ((mp = (gbuf_t *)ddp_compress_msg(mp)) == NULL) { 910 dPrintf(D_M_DDP, D_L_ERROR, 911 ("dropped short incoming ET packet (len %d)", 0)); 912 snmpStats.dd_inTotal++; 913 at_ddp_stats.rcv_bad_length++; 914 goto out; /* return; */ 915 } 916 msgsize = gbuf_msgsize(mp); 917 918 at_ddp_stats.rcv_bytes += msgsize; 919 at_ddp_stats.rcv_packets++; 920 921 /* if the interface pointer is 0, the packet has been 922 * looped back by 'write' half of DDP. It is of the 923 * form {extended ddp,...}. The packet is meant to go 924 * up to some socket on the same node. 925 */ 926 if (!ifID) /* if loop back is specified */ 927 ifID = ifID_home; /* that means the home port */ 928 929 /* the incoming datagram has extended DDP header and is of 930 * the form {ddp,...}. 931 */ 932 if (msgsize < DDP_X_HDR_SIZE) { 933 dPrintf(D_M_DDP, D_L_ERROR, 934 ("dropped short incoming ET packet (len %d)", msgsize)); 935 at_ddp_stats.rcv_bad_length++; 936 gbuf_freem(mp); 937 goto out; /* return; */ 938 } 939 /* 940 * At this point, the message is always of the form 941 * {extended ddp, ... }. 942 */ 943 ddp = (at_ddp_t *)gbuf_rptr(mp); 944 len = DDPLEN_VALUE(ddp); 945 946 if (msgsize != len) { 947 if (msgsize > len) { 948 if (len < DDP_X_HDR_SIZE) { 949 dPrintf(D_M_DDP, D_L_ERROR, 950 ("Length problems, ddp length %d, buffer length %d", 951 len, msgsize)); 952 snmpStats.dd_tooLong++; 953 at_ddp_stats.rcv_bad_length++; 954 gbuf_freem(mp); 955 goto out; /* return; */ 956 } 957 /* 958 * shave off the extra bytes from the end of message 959 */ 960 mp = ddp_adjmsg(mp, -(msgsize - len)) ? mp : 0; 961 if (mp == 0) 962 goto out; /* return; */ 963 } else { 964 dPrintf(D_M_DDP, D_L_ERROR, 965 ("Length problems, ddp length %d, buffer length %d", 966 len, msgsize)); 967 snmpStats.dd_tooShort++; 968 at_ddp_stats.rcv_bad_length++; 969 gbuf_freem(mp); 970 goto out; /* return; */ 971 } 972 } 973 socket = ddp->dst_socket; 974 975 /* 976 * We want everything in router mode, specially socket 254 for nbp so we need 977 * to bypass this test when we are a router. 978 */ 979 980 if (!MULTIPORT_MODE && (socket > DDP_SOCKET_LAST || 981 socket < DDP_SOCKET_1st_RESERVED)) { 982 dPrintf(D_M_DDP, D_L_WARNING, 983 ("Bad dst socket on incoming packet (0x%x)", 984 ddp->dst_socket)); 985 at_ddp_stats.rcv_bad_socket++; 986 gbuf_freem(mp); 987 goto out; /* return; */ 988 } 989 /* 990 * if the checksum is true, then upstream wants us to calc 991 */ 992 if (UAS_VALUE(ddp->checksum) && 993 (UAS_VALUE_NTOH(ddp->checksum) != ddp_checksum(mp, 4))) { 994 dPrintf(D_M_DDP, D_L_WARNING, 995 ("Checksum error on incoming pkt, calc 0x%x, exp 0x%x", 996 ddp_checksum(mp, 4), UAS_VALUE_NTOH(ddp->checksum))); 997 snmpStats.dd_checkSum++; 998 at_ddp_stats.rcv_bad_checksum++; 999 gbuf_freem(mp); 1000 goto out; /* return; */ 1001 } 1002 1003/*############### routing input checking */ 1004 1005/* Router mode special: we send "up-stack" packets for this node or coming from any 1006 * other ports, but for the reserved atalk sockets (RTMP, ZIP, NBP [and EP]) 1007 * BTW, the way we know it's for the router and not the home port is that the 1008 * MAC (ethernet) address is always the one of the interface we're on, but 1009 * the AppleTalk address must be the one of the home port. If it's a multicast 1010 * or another AppleTalk address, this is the router job's to figure out where it's 1011 * going to go. 1012 */ 1013 /* *** a duplicate should be sent to any other client that is listening 1014 for packets of this type on a raw DDP socket *** */ 1015 if (ddp_handler[socket].func) { 1016 dPrintf(D_M_DDP,D_L_INPUT, 1017 ("ddp_input: skt %u hdnlr:0x%p\n", 1018 (u_int) socket, ddp_handler[socket].func)); 1019 pktsHome++; 1020 snmpStats.dd_inLocal++; 1021 1022 (*ddp_handler[socket].func)(mp, ifID); 1023 goto out; /* return; */ 1024 } 1025 dst_net = NET_VALUE(ddp->dst_net); 1026 if ( 1027 /* exact match */ 1028 forUs(ddp) || 1029 /* any node, wildcard or matching net */ 1030 ((ddp->dst_node == 255) && 1031 (((dst_net >= ifID_home->ifThisCableStart) && 1032 (dst_net <= ifID_home->ifThisCableEnd)) || 1033 dst_net == 0)) || 1034 /* this node is not online yet(?) */ 1035 (ifID->ifRoutingState < PORT_ONLINE) 1036 ) { 1037 gref_t *gref; 1038 pktsHome++; 1039 snmpStats.dd_inLocal++; 1040 1041 if (ddp->type == DDP_ATP) { 1042 if (atp_inputQ[socket] && (atp_inputQ[socket] != (gref_t *)1)) { 1043 /* if there's an ATP pcb */ 1044 atp_input(mp); 1045 goto out; /* return; */ 1046 } 1047 } else if (ddp->type == DDP_ADSP) { 1048 if (adsp_inputQ[socket]) { 1049 /* if there's an ADSP pcb */ 1050 adsp_input(mp); 1051 goto out; /* return; */ 1052 } 1053 } 1054 1055 /* otherwise look for a DDP pcb; 1056 ATP / raw-DDP and ADSP / raw-DDP are possible */ 1057 for (gref = ddp_head.atpcb_next; gref != &ddp_head; 1058 gref = gref->atpcb_next) 1059 if (gref->lport == socket && 1060 (gref->ddptype == 0 || gref->ddptype == ddp->type)) { 1061 dPrintf(D_M_DDP, D_L_INPUT, 1062 ("ddp_input: streamq, skt %d\n", socket)); 1063 if (gref->atpcb_socket) { 1064 struct sockaddr_at ddp_in; 1065 ddp_in.sat_len = sizeof(ddp_in); 1066 ddp_in.sat_family = AF_APPLETALK; 1067 ddp_in.sat_addr.s_net = NET_VALUE(ddp->src_net); 1068 ddp_in.sat_addr.s_node = ddp->src_node; 1069 ddp_in.sat_port = ddp->src_socket; 1070 1071 /* strip off DDP header if so indicated by 1072 sockopt */ 1073 if (gref->ddp_flags & DDPFLG_STRIPHDR) { 1074 mp = m_pullup((struct mbuf *)mp, 1075 DDP_X_HDR_SIZE); 1076 if (mp) { 1077 gbuf_rinc(mp, DDP_X_HDR_SIZE); 1078 } else { 1079 /* this should never happen because 1080 msgsize was checked earlier */ 1081 at_ddp_stats.rcv_bad_length++; 1082 goto out; /* return */ 1083 } 1084 } 1085 1086 if (sbappendaddr(&((gref->atpcb_socket)->so_rcv), 1087 (struct sockaddr *)&ddp_in, 1088 mp, 0, NULL) != 0) { 1089 sorwakeup(gref->atpcb_socket); 1090 } 1091 } else { 1092 atalk_putnext(gref, mp); 1093 } 1094 goto out; /* return */ 1095 } 1096 1097 at_ddp_stats.rcv_bad_socket++; 1098 gbuf_freem(mp); 1099 snmpStats.dd_noHandler++; 1100 dPrintf(D_M_DDP, D_L_WARNING, 1101 ("ddp_input: dropped pkt for socket %d\n", socket)); 1102 } else { 1103 dPrintf(D_M_DDP, D_L_ROUTING, 1104 ("ddp_input: routing_needed from port=%d sock=%d\n", 1105 ifID->ifPort, ddp->dst_socket)); 1106 1107 snmpStats.dd_fwdReq++; 1108 if (((pktsIn-pktsHome+200) >= RouterMix) && ((++pktsDropped % 5) == 0)) { 1109 at_ddp_stats.rcv_dropped_nobuf++; 1110 gbuf_freem(mp); 1111 } 1112 else { 1113 routing_needed(mp, ifID, FALSE); 1114 } 1115 } 1116out: 1117 KERNEL_DEBUG(DBG_AT_DDP_INPUT | DBG_FUNC_END, 0,0,0,0,0); 1118} /* ddp_input */ 1119 1120 1121/* 1122 * ddp_router_output() 1123 * 1124 * Remarks : 1125 * This is a modified version of ddp_output for router use. 1126 * The main difference is that the interface on which the packet needs 1127 * to be sent is specified and a *destination* AppleTalk address is passed 1128 * as an argument, this address may or may not be the same as the destination 1129 * address found in the ddp packet... This is the trick about routing, the 1130 * AppleTalk destination of the packet may not be the same as the Enet address 1131 * we send the packet too (ie, we may pass the baby to another router). 1132 * 1133 */ 1134int ddp_router_output(mp, ifID, addr_type, router_net, router_node, enet_addr) 1135 gbuf_t *mp; 1136 at_ifaddr_t *ifID; 1137 int addr_type; 1138 at_net_al router_net; 1139 at_node router_node; 1140 etalk_addr_t *enet_addr; 1141{ 1142 register at_ddp_t *ddp; 1143 struct atalk_addr at_dest; 1144 int addr_flag = 0; 1145 char *addr = NULL; 1146 register gbuf_t *m; 1147 1148 if (!ifID) { 1149 dPrintf(D_M_DDP, D_L_WARNING, ("BAD BAD ifID\n")); 1150 gbuf_freel(mp); 1151 return(EPROTOTYPE); 1152 } 1153 ddp = (at_ddp_t *)gbuf_rptr(mp); 1154 1155#ifdef AURP_SUPPORT 1156 if (ifID->ifFlags & AT_IFF_AURP) { /* AURP link? */ 1157 if (ddp_AURPsendx) { 1158 fillin_pkt_chain(mp); 1159 if (router_node == 255) 1160 router_node = 0; 1161 ddp_AURPsendx(AURPCODE_DATAPKT, mp, router_node); 1162 return 0; 1163 } else { 1164 gbuf_freel(mp); 1165 return EPROTOTYPE; 1166 } 1167 } 1168#endif 1169 1170 /* keep some of the tests for now ####### */ 1171 1172 if (gbuf_msgsize(mp) > DDP_DATAGRAM_SIZE) { 1173 /* the packet is too large */ 1174 dPrintf(D_M_DDP, D_L_WARNING, 1175 ("ddp_router_output: Packet too large size=%d\n", 1176 gbuf_msgsize(mp))); 1177 gbuf_freel(mp); 1178 return (EMSGSIZE); 1179 } 1180 1181 switch (addr_type) { 1182 1183 case AT_ADDR : 1184 1185 /* 1186 * Check for packet destined to the home stack 1187 */ 1188 1189 if ((ddp->dst_node == ifID->ifThisNode.s_node) && 1190 (NET_VALUE(ddp->dst_net) == ifID->ifThisNode.s_net)) { 1191 dPrintf(D_M_DDP_LOW, D_L_ROUTING, 1192 ("ddp_r_output: sending back home from port=%d socket=%d\n", 1193 ifID->ifPort, ddp->dst_socket)); 1194 1195 UAS_ASSIGN(ddp->checksum, 0); 1196 ddp_input(mp, ifID); 1197 return(0); 1198 } 1199 1200 NET_ASSIGN(at_dest.atalk_net, router_net); 1201 at_dest.atalk_node = router_node; 1202 1203 addr_flag = AT_ADDR_NO_LOOP; 1204 addr = (char *)&at_dest; 1205 dPrintf(D_M_DDP_LOW, D_L_ROUTING_AT, 1206 ("ddp_r_output: AT_ADDR out port=%d net %d:%d via rte %d:%d", 1207 ifID->ifPort, NET_VALUE(ddp->dst_net), ddp->dst_node, router_net, 1208 router_node)); 1209 break; 1210 1211 case ET_ADDR : 1212 addr_flag = ET_ADDR; 1213 addr = (char *)enet_addr; 1214 dPrintf(D_M_DDP_LOW, D_L_ROUTING, 1215 ("ddp_r_output: ET_ADDR out port=%d net %d:%d\n", 1216 ifID->ifPort, NET_VALUE(ddp->dst_net), ddp->dst_node)); 1217 break; 1218 } 1219 1220 if (ifID->ifState == LAP_OFFLINE) { 1221 gbuf_freel(mp); 1222 return 0; 1223 } 1224 1225 fillin_pkt_chain(mp); 1226 1227 { /* begin block */ 1228 struct etalk_addr dest_addr; 1229 struct atalk_addr dest_at_addr; 1230 int loop = TRUE; /* flag to aarp to loopback (default) */ 1231 1232 m = mp; 1233 1234 /* the incoming frame is of the form {flag, address, ddp...} 1235 * where "flag" indicates whether the address is an 802.3 1236 * (link) address, or an appletalk address. If it's an 1237 * 802.3 address, the packet can just go out to the network 1238 * through PAT, if it's an appletalk address, AT->802.3 address 1239 * resolution needs to be done. 1240 * If 802.3 address is known, strip off the flag and 802.3 1241 * address, and prepend 802.2 and 802.3 headers. 1242 */ 1243 1244 if (addr == NULL) { 1245 addr_flag = *(u_char *)gbuf_rptr(m); 1246 gbuf_rinc(m,1); 1247 } 1248 1249 switch (addr_flag) { 1250 case AT_ADDR_NO_LOOP : 1251 loop = FALSE; 1252 /* pass thru */ 1253 case AT_ADDR : 1254 if (addr == NULL) { 1255 dest_at_addr = *(struct atalk_addr *)gbuf_rptr(m); 1256 gbuf_rinc(m,sizeof(struct atalk_addr)); 1257 } else 1258 dest_at_addr = *(struct atalk_addr *)addr; 1259 break; 1260 case ET_ADDR : 1261 if (addr == NULL) { 1262 dest_addr = *(struct etalk_addr *)gbuf_rptr(m); 1263 gbuf_rinc(m,sizeof(struct etalk_addr)); 1264 } else 1265 dest_addr = *(struct etalk_addr *)addr; 1266 break; 1267 default : 1268 dPrintf(D_M_DDP_LOW,D_L_ERROR, 1269 ("ddp_router_output: Unknown addr_flag = 0x%x\n", addr_flag)); 1270 1271 gbuf_freel(m); /* unknown address type, chuck it */ 1272 return 0; 1273 } 1274 1275 m = gbuf_strip(m); 1276 1277 /* At this point, rptr points to ddp header for sure */ 1278 if (ifID->ifState == LAP_ONLINE_FOR_ZIP) { 1279 /* see if this is a ZIP packet that we need 1280 * to let through even though network is 1281 * not yet alive!! 1282 */ 1283 if (zip_type_packet(m) == 0) { 1284 gbuf_freel(m); 1285 return 0; 1286 } 1287 } 1288 1289 ifID->stats.xmit_packets++; 1290 ifID->stats.xmit_bytes += gbuf_msgsize(m); 1291 snmpStats.dd_outLong++; 1292 1293 switch (addr_flag) { 1294 case AT_ADDR_NO_LOOP : 1295 case AT_ADDR : 1296 /* 1297 * we don't want elap to be looking into ddp header, so 1298 * it doesn't know net#, consequently can't do 1299 * AMT_LOOKUP. That task left to aarp now. 1300 */ 1301 aarp_send_data(m,ifID,&dest_at_addr, loop); 1302 break; 1303 case ET_ADDR : 1304 pat_output(ifID, m, (unsigned char *)&dest_addr, 0); 1305 break; 1306 } 1307 } /* end block */ 1308 1309 return(0); 1310} /* ddp_router_output */ 1311 1312/*****************************************/ 1313 1314#ifdef AURP_SUPPORT 1315 1316void rt_delete(NetStop, NetStart) 1317 unsigned short NetStop; 1318 unsigned short NetStart; 1319{ 1320 RT_entry *found; 1321 1322 if ((found = rt_bdelete(NetStop, NetStart)) != 0) { 1323 bzero(found, sizeof(RT_entry)); 1324 found->right = RT_table_freelist; 1325 RT_table_freelist = found; 1326 } 1327} 1328 1329int ddp_AURPfuncx(code, param, node) 1330 int code; 1331 void *param; 1332 unsigned char node; 1333{ 1334 at_ifaddr_t *ifID; 1335 int k; 1336 1337 switch (code) { 1338 case AURPCODE_DATAPKT: /* data packet */ 1339 if (aurp_ifID) { 1340 dPrintf(D_M_DDP, D_L_TRACE, ("ddp_AURPfuncx: data, 0x%x, %d\n", 1341 (u_int) aurp_ifID, node)); 1342 1343 ddp_input((gbuf_t *)param, aurp_ifID); 1344 } else 1345 gbuf_freem((gbuf_t *)param); 1346 break; 1347 1348 case AURPCODE_REG: /* register/deregister */ 1349 if (!ROUTING_MODE) 1350 return -1; 1351 ddp_AURPsendx = (void(*)())param; 1352 1353 if (param) { 1354 /* register AURP callback function */ 1355 if (aurp_ifID) 1356 return 0; 1357 for (k=(IFID_HOME+1); k < IF_TOTAL_MAX; k++) { 1358 if (ifID_table[k] == 0) { 1359 aurp_ifID = &at_interfaces[k]; 1360 aurp_ifID->ifFlags = RTR_XNET_PORT; 1361 ddp_add_if(aurp_ifID); 1362 aurp_ifID->ifState = LAP_ONLINE; 1363 aurp_ifID->ifRoutingState = PORT_ONLINE; 1364 dPrintf(D_M_DDP, D_L_TRACE, 1365 ("ddp_AURPfuncx: on, 0x%x\n", 1366 (u_int) aurp_ifID)); 1367 1368 ddp_AURPsendx(AURPCODE_DEBUGINFO, 1369 &dbgBits, aurp_ifID->ifPort); 1370 return 0; 1371 } 1372 } 1373 return -1; 1374 1375 } else { 1376 /* deregister AURP callback function */ 1377 if (aurp_ifID) { 1378 rtmp_purge(aurp_ifID); 1379 ddp_rem_if(aurp_ifID); 1380 aurp_ifID->ifState = LAP_OFFLINE; 1381 aurp_ifID->ifRoutingState = PORT_OFFLINE; 1382 dPrintf(D_M_DDP, D_L_TRACE, 1383 ("ddp_AURPfuncx: off, 0x%x\n", (u_int) aurp_ifID)); 1384 aurp_ifID = 0; 1385 } 1386 } 1387 break; 1388 1389 case AURPCODE_AURPPROTO: /* proto type - AURP */ 1390 if (aurp_ifID) { 1391 aurp_ifID->ifFlags |= AT_IFF_AURP; 1392 } 1393 break; 1394 } 1395 1396 return 0; 1397} 1398#endif 1399 1400/* checks to see if address of packet is for one of our interfaces 1401 returns *ifID if it's for us, NULL if not 1402*/ 1403at_ifaddr_t *forUs(ddp) 1404 register at_ddp_t *ddp; 1405{ 1406 at_ifaddr_t *ifID; 1407 1408 TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) { 1409 if ((ddp->dst_node == ifID->ifThisNode.s_node) && 1410 (NET_VALUE(ddp->dst_net) == ifID->ifThisNode.s_net) 1411 ) { 1412 dPrintf(D_M_DDP_LOW, D_L_ROUTING, 1413 ("pkt was for port %d\n", ifID->ifPort)); 1414 1415 return(ifID); 1416 } 1417 } 1418 1419 return((at_ifaddr_t *)NULL); 1420} /* forUs */ 1421