2 * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 * Copyright (c) 1987, 1988, 1989 Apple Computer, Inc.
34 * Modified for MP, 1996 by Tuyen Nguyen
35 * Added AURP support, April 8, 1996 by Tuyen Nguyen
36 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
39 #define RESOLVE_DBG /* define debug globals in debug.h */
41 #include <sys/errno.h>
42 #include <sys/types.h>
43 #include <sys/param.h>
44 #include <machine/spl.h>
45 #include <sys/systm.h>
46 #include <sys/kernel.h>
48 #include <sys/filedesc.h>
49 #include <sys/fcntl.h>
51 #include <sys/ioctl.h>
52 #include <sys/malloc.h>
53 #include <sys/socket.h>
54 #include <sys/socketvar.h>
55 #include <sys/protosw.h>
60 #include <netat/sysglue.h>
61 #include <netat/appletalk.h>
62 #include <netat/at_var.h>
63 #include <netat/ddp.h>
65 #include <netat/nbp.h>
66 #include <netat/rtmp.h>
67 #include <netat/zip.h>
68 #include <netat/at_pcb.h>
69 #include <netat/routing_tables.h>
70 #include <netat/at_snmp.h>
71 #include <netat/aurp.h>
72 #include <netat/debug.h>
73 #include <netat/at_ddp_brt.h>
74 #include <netat/at_aarp.h>
75 #include <netat/adsp.h>
76 #include <netat/adsp_internal.h>
80 /* Queue of LAP interfaces which have registered themselves with DDP */
81 struct at_ifQueueHd at_ifQueueHd
;
83 extern at_state_t at_state
;
84 extern TAILQ_HEAD(name_registry
, _nve_
) name_registry
;
86 snmpStats_t snmpStats
; /* snmp ddp & echo stats */
88 extern at_ddp_stats_t at_ddp_stats
; /* DDP statistics */
89 extern struct atpcb ddp_head
;
90 extern at_ifaddr_t
*ifID_home
, *ifID_table
[];
91 extern aarp_amt_array
*aarp_table
[];
92 extern at_ifaddr_t at_interfaces
[];
94 /* routing mode special */
95 void (*ddp_AURPsendx
)();
96 at_ifaddr_t
*aurp_ifID
= 0;
97 extern pktsIn
,pktsOut
;
98 int pktsDropped
,pktsHome
;
100 atlock_t ddpinp_lock
;
102 extern int *atp_pidM
;
103 extern int *adsp_pidM
;
104 extern struct atpcb
*atp_inputQ
[];
105 extern CCB
*adsp_inputQ
[];
107 at_ifaddr_t
*forUs(at_ddp_t
*);
109 void ddp_input(), ddp_notify_nbp();
111 extern void routing_needed();
112 extern void ddp_brt_sweep();
118 void init_ddp_handler()
120 bzero(ddp_handler
, sizeof(ddp_handler
));
123 void add_ddp_handler(ddp_socket
, input_func
)
125 void (*input_func
)();
127 ddp_handler
[ddp_socket
].func
= input_func
;
137 * Raw DDP socket option processing.
139 int ddp_ctloutput(so
, sopt
)
141 struct sockopt
*sopt
;
143 struct atpcb
*at_pcb
= sotoatpcb(so
);
144 int optval
, error
= 0;
146 if (sopt
->sopt_level
!= ATPROTO_NONE
)
149 switch (sopt
->sopt_dir
) {
152 switch (sopt
->sopt_name
) {
154 optval
= at_pcb
->ddp_flags
& DDPFLG_HDRINCL
;
155 error
= sooptcopyout(sopt
, &optval
, sizeof optval
);
158 optval
= at_pcb
->ddp_flags
& DDPFLG_CHKSUM
;
159 error
= sooptcopyout(sopt
, &optval
, sizeof optval
);
162 optval
= at_pcb
->ddp_flags
& DDPFLG_STRIPHDR
;
163 error
= sooptcopyout(sopt
, &optval
, sizeof optval
);
166 optval
= at_pcb
->ddp_flags
& DDPFLG_SLFSND
;
167 error
= sooptcopyout(sopt
, &optval
, sizeof optval
);
169 case DDP_GETSOCKNAME
:
172 addr
.inet
.net
= at_pcb
->laddr
.s_net
;
173 addr
.inet
.node
= at_pcb
->laddr
.s_node
;
174 addr
.inet
.socket
= at_pcb
->lport
;
175 addr
.ddptype
= at_pcb
->ddptype
;
176 error
= sooptcopyout(sopt
, &addr
, sizeof addr
);
185 switch (sopt
->sopt_name
) {
187 error
= sooptcopyin(sopt
, &optval
, sizeof optval
,
192 at_pcb
->ddp_flags
|= DDPFLG_HDRINCL
;
194 at_pcb
->ddp_flags
&= ~DDPFLG_HDRINCL
;
197 error
= sooptcopyin(sopt
, &optval
, sizeof optval
,
202 at_pcb
->ddp_flags
|= DDPFLG_CHKSUM
;
204 at_pcb
->ddp_flags
&= ~DDPFLG_CHKSUM
;
207 error
= sooptcopyin(sopt
, &optval
, sizeof optval
,
212 at_pcb
->ddp_flags
|= DDPFLG_STRIPHDR
;
214 at_pcb
->ddp_flags
&= ~DDPFLG_STRIPHDR
;
217 error
= sooptcopyin(sopt
, &optval
, sizeof optval
,
222 at_pcb
->ddp_flags
|= DDPFLG_SLFSND
;
224 at_pcb
->ddp_flags
&= ~DDPFLG_SLFSND
;
236 /****************************************************************/
239 /* Support Routines */
242 /****************************************************************/
249 * This procedure determines the checksum of an extended DDP datagram.
250 * Add the unsigned bytes into an unsigned 16-bit accumulator.
251 * After each add, rotate the sign bit into the low order bit of
252 * the accumulator. When done, if the checksum is 0, changed into 0xFFFF.
255 * checksum = ddp_checksum(mp, offset)
258 * mp pointer to the datagram gbuf_t
259 * offset offset to start at in first gbuf_t block
266 u_short
ddp_checksum(mp
, offset
)
270 register u_char
*data
;
272 register u_short checksum
;
277 if (offset
>= gbuf_len(mp
))
278 offset
-= gbuf_len(mp
);
280 data
= ((unsigned char *) gbuf_rptr(mp
)) + offset
;
281 length
= gbuf_len(mp
) - offset
;
283 /* Portable checksum from 3.0 */
286 checksum
= (checksum
& 0x8000) ?
287 ((checksum
<< 1) | 1) : (checksum
<< 1);
290 } while ( (mp
= gbuf_cont(mp
)) );
302 * This procedure is called by each LAP interface when it wants to place
303 * itself online. The LAP interfaces passes in a pointer to its at_if
304 * struct, which is added to DDP's list of active interfaces (at_ifQueueHd).
305 * When DDP wants to transmit a packet, it searches this list for the
308 * If AT_IFF_DEFAULT is set, then this interface is to be brought online
309 * as the interface DDP socket addresses are tied to. Of course there can
310 * be only one default interface; we return an error if it's already set.
313 * ret_status = ddp_add_if(ifID)
316 * ifID pointer to LAP interface's at_if struct.
319 * 0 Procedure successfully completed.
320 * EALREADY This interface is already online, or there is
321 * already a default interface.
322 * ENOBUFS Cannot allocate input queue
326 register at_ifaddr_t
*ifID
;
330 dPrintf(D_M_DDP
, D_L_STARTUP
,
331 ("ddp_add_if: called, ifID:0x%x\n", (u_int
) ifID
));
333 if (ifID
->ifFlags
& AT_IFF_DEFAULT
) {
335 return(EEXIST
); /* home port already set */
341 for (port
=IFID_HOME
+1; port
<IF_TOTAL_MAX
; port
++)
342 if (!ifID_table
[port
]) {
345 if (port
== IF_TOTAL_MAX
) /* no space left */
349 /* allocate an et_aarp_amt structure */
350 if ((aarp_table
[port
] =
351 (aarp_amt_array
*)_MALLOC(sizeof(aarp_amt_array
),
352 M_RTABLE
, M_WAITOK
)) == NULL
)
355 dPrintf(D_M_DDP
, D_L_STARTUP
, ("ddp:adding ifID_table[%d]\n", port
));
357 /* add i/f to port list */
358 ifID_table
[port
] = ifID
;
359 ifID
->ifPort
= port
; /* set ddp port # in ifID */
361 /* Add this interface to the list of online interfaces */
362 TAILQ_INSERT_TAIL(&at_ifQueueHd
, ifID
, aa_link
);
371 * This procedure is called by each LAP interface when it wants to take
372 * itself offline. The LAP interfaces passes in a pointer to its at_if
373 * struct; DDP's list of active interfaces (at_ifQueueHd) is searched and
374 * this interface is removed from the list. DDP can still transmit
375 * packets as long as this interface is not the default interface; the
376 * sender will just get ENETUNREACH errors when it tries to send to an
377 * interface that went offline. However, if the default interface is
378 * taken offline, we no longer have a node ID to use as a source address
379 * and DDP must return ENETDOWN when a caller tries to send a packet.
382 * ifID pointer to LAP interface's at_if struct.
385 void ddp_rem_if(ifID
)
386 register at_ifaddr_t
*ifID
;
388 struct ifaddr
*ifa
= &ifID
->aa_ifa
;
390 /* un-do processing done in SIOCSIFADDR */
392 ifnet_lock_exclusive(ifID
->aa_ifp
);
393 if_detach_ifa(ifID
->aa_ifp
, ifa
);
394 ifa
->ifa_addr
= NULL
;
395 ifnet_lock_done(ifID
->aa_ifp
);
397 if (ifID
->at_dl_tag
) {
398 /* dlil_detach_protocol(ifID->at_dl_tag); */
399 ether_detach_at(ifID
->aa_ifp
);
403 /* un-do processing done in ddp_add_if() */
405 if (aarp_table
[ifID
->ifPort
]) {
406 FREE(aarp_table
[ifID
->ifPort
], M_RTABLE
);
407 aarp_table
[ifID
->ifPort
] = NULL
;
410 at_state
.flags
|= AT_ST_IF_CHANGED
;
413 trackrouter_rem_if(ifID
);
414 TAILQ_REMOVE(&at_ifQueueHd
, ifID
, aa_link
);
415 ifID_table
[ifID
->ifPort
] = NULL
;
416 ifID
->ifName
[0] = '\0';
420 /* *** deallocate ifID, eventually *** */
424 * The user may have registered an NVE with the NBP on a socket. When the
425 * socket is closed, the NVE should be deleted from NBP's name table. The
426 * user should delete the NVE before the socket is shut down, but there
427 * may be circumstances when he can't. So, whenever a DDP socket is closed,
428 * this routine is used to notify NBP of the socket closure. This would
429 * help NBP get rid of all NVE's registered on the socket.
432 /* *** Do we still need to do this? *** */
433 int ot_ddp_check_socket(socket
, pid
)
434 unsigned char socket
;
440 dPrintf(D_M_DDP
, D_L_INFO
, ("ot_ddp_check_socket: %d\n", socket
));
441 for (gref
= ddp_head
.atpcb_next
; gref
!= &ddp_head
; gref
= gref
->atpcb_next
)
442 if (gref
->lport
== socket
&& gref
->pid
== pid
)
444 if ((atp_inputQ
[socket
] != NULL
) && (atp_inputQ
[socket
] != (gref_t
*)1)
445 && (atp_pidM
[socket
] == pid
))
447 if ((adsp_inputQ
[socket
] != NULL
) && (adsp_pidM
[socket
] == pid
))
453 void ddp_notify_nbp(socket
, pid
, ddptype
)
454 unsigned char socket
;
456 unsigned char ddptype
; /* not used */
459 nve_entry_t
*nve_entry
, *nve_next
;
461 if (at_state
.flags
& AT_ST_STARTED
) {
462 /* *** NBP_CLOSE_NOTE processing (from ddp_nbp.c) *** */
463 ATDISABLE(nve_lock
, NVE_LOCK
);
464 for ((nve_entry
= TAILQ_FIRST(&name_registry
)); nve_entry
; nve_entry
= nve_next
) {
465 nve_next
= TAILQ_NEXT(nve_entry
, nve_link
);
466 if ((at_socket
)socket
== nve_entry
->address
.socket
&&
467 /* *** check complete address and ddptype here *** */
468 pid
== nve_entry
->pid
&&
469 ot_ddp_check_socket(nve_entry
->address
.socket
,
470 nve_entry
->pid
) < 2) {
471 /* NB: nbp_delete_entry calls TAILQ_REMOVE */
472 nbp_delete_entry(nve_entry
);
475 ATENABLE(nve_lock
, NVE_LOCK
);
477 } /* ddp_notify_nbp */
479 static void fillin_pkt_chain(m
)
484 *ddp
= (at_ddp_t
*)gbuf_rptr(m
),
488 if (UAS_VALUE(ddp
->checksum
)) {
489 tmp
= ddp_checksum(m
, 4);
490 UAS_ASSIGN(ddp
->checksum
, tmp
);
493 for (tmp_m
=gbuf_next(tmp_m
); tmp_m
; tmp_m
=gbuf_next(tmp_m
)) {
494 tmp_ddp
= (at_ddp_t
*)gbuf_rptr(tmp_m
);
495 tmp_ddp
->length
= gbuf_msgsize(tmp_m
);
498 NET_NET(tmp_ddp
->src_net
, ddp
->src_net
);
499 tmp_ddp
->src_node
= ddp
->src_node
;
500 tmp_ddp
->src_socket
= ddp
->src_socket
;
501 if (UAS_VALUE(tmp_ddp
->checksum
)) {
502 tmp
= ddp_checksum(tmp_m
, 4);
503 UAS_ASSIGN(tmp_ddp
->checksum
, tmp
);
508 /* There are various ways a packet may go out.... it may be sent out
509 * directly to destination node, or sent to a random router or sent
510 * to a router whose entry exists in Best Router Cache. Following are
511 * constants used WITHIN this routine to keep track of choice of destination
513 #define DIRECT_ADDR 1
515 #define BRIDGE_ADDR 3
521 * Called to queue a atp/ddp data packet on the network interface.
522 * It returns 0 normally, and an errno in case of error.
523 * The mbuf chain pointed to by *mp is consumed on success, and
524 * freed in case of error.
527 int ddp_output(mp
, src_socket
, src_addr_included
)
528 register gbuf_t
**mp
;
529 at_socket src_socket
;
530 int src_addr_included
;
532 register at_ifaddr_t
*ifID
= ifID_home
, *ifIDTmp
= NULL
;
533 register at_ddp_t
*ddp
;
534 register ddp_brt_t
*brt
;
535 register at_net_al dst_net
;
537 struct atalk_addr at_dest
;
538 at_ifaddr_t
*ARouterIf
= NULL
;
546 KERNEL_DEBUG(DBG_AT_DDP_OUTPUT
| DBG_FUNC_START
, 0,
549 snmpStats
.dd_outReq
++;
552 ddp
= (at_ddp_t
*)gbuf_rptr(m
);
555 /* Device/Interface not configured */
556 dPrintf(D_M_DDP
, D_L_ERROR
, ("Device/Interface not configured"));
559 goto exit_ddp_output
;
562 if ((ddp
->dst_socket
> (unsigned) (DDP_SOCKET_LAST
+ 1)) ||
563 (ddp
->dst_socket
< DDP_SOCKET_1st_RESERVED
)) {
564 dPrintf(D_M_DDP
, D_L_ERROR
,
565 ("Illegal destination socket on outgoing packet (0x%x)",
567 at_ddp_stats
.xmit_bad_addr
++;
570 goto exit_ddp_output
;
572 if ((len
= gbuf_msgsize(*mp
)) > DDP_DATAGRAM_SIZE
) {
573 /* the packet is too large */
574 dPrintf(D_M_DDP
, D_L_ERROR
,
575 ("Outgoing packet too long (len=%d bytes)", len
));
576 at_ddp_stats
.xmit_bad_length
++;
579 goto exit_ddp_output
;
581 at_ddp_stats
.xmit_bytes
+= len
;
582 at_ddp_stats
.xmit_packets
++;
588 /* If this packet is for the same node, loop it back
589 * up... Note that for LocalTalk, dst_net zero means "THIS_NET", so
590 * address 0.nn is eligible for loopback. For Extended EtherTalk,
591 * dst_net 0 can be used only for cable-wide or zone-wide
592 * broadcasts (0.ff) and as such, address of the form 0.nn is NOT
593 * eligible for loopback.
595 dst_net
= NET_VALUE(ddp
->dst_net
);
597 /* If our packet is destined for the 'virtual' bridge
598 * address of NODE==0xFE, replace that address with a
599 * real bridge address.
601 if ((ddp
->dst_node
== 0xfe) &&
602 ((dst_net
== ATADDR_ANYNET
) ||
603 (dst_net
>= ifID_home
->ifThisCableStart
&&
604 dst_net
<= ifID_home
->ifThisCableEnd
))) {
605 /* if there's a router that's not us, it's in ifID_home */
606 NET_ASSIGN(ddp
->dst_net
, ifID_home
->ifARouter
.s_net
);
607 dst_net
= ifID_home
->ifARouter
.s_net
;
608 ddp
->dst_node
= ifID_home
->ifARouter
.s_node
;
611 if (MULTIHOME_MODE
&& (ifIDTmp
= forUs(ddp
))) {
614 dPrintf(D_M_DDP_LOW
, D_L_USR1
,
615 ("ddp_out: for us if:%s\n", ifIDTmp
->ifName
));
619 loop
= ((ddp
->dst_node
== ifID
->ifThisNode
.s_node
) &&
620 (dst_net
== ifID
->ifThisNode
.s_net
)
623 gbuf_t
*mdata
, *mdata_next
;
625 if (!MULTIHOME_MODE
|| !src_addr_included
) {
626 NET_ASSIGN(ddp
->src_net
, ifID
->ifThisNode
.s_net
);
627 ddp
->src_node
= ifID
->ifThisNode
.s_node
;
629 ddp
->src_socket
= src_socket
;
631 dPrintf(D_M_DDP_LOW
, D_L_OUTPUT
,
632 ("ddp_output: loop to %d:%d port=%d\n",
633 NET_VALUE(ddp
->dst_net
),
637 fillin_pkt_chain(*mp
);
639 dPrintf(D_M_DDP
, D_L_VERBOSE
,
640 ("Looping back packet from skt 0x%x to skt 0x%x\n",
641 ddp
->src_socket
, ddp
->dst_socket
));
643 for (mdata
= *mp
; mdata
; mdata
= mdata_next
) {
644 mdata_next
= gbuf_next(mdata
);
645 gbuf_next(mdata
) = 0;
646 ddp_input(mdata
, ifID
);
648 goto exit_ddp_output
;
650 if ((ddp
->dst_socket
== ZIP_SOCKET
) &&
651 (zip_type_packet(*mp
) == ZIP_GETMYZONE
)) {
652 ddp
->src_socket
= src_socket
;
653 error
= zip_handle_getmyzone(ifID
, *mp
);
655 goto exit_ddp_output
;
658 * find out the interface on which the packet should go out
660 TAILQ_FOREACH(ifID
, &at_ifQueueHd
, aa_link
) {
661 if ((ifID
->ifThisNode
.s_net
== dst_net
) || (dst_net
== 0))
662 /* the message is either going out (i) on the same
663 * NETWORK in case of LocalTalk, or (ii) on the same
664 * CABLE in case of Extended AppleTalk (EtherTalk).
668 if ((ifID
->ifThisCableStart
<= dst_net
) &&
669 (ifID
->ifThisCableEnd
>= dst_net
)
671 /* We're on EtherTalk and the message is going out to
672 * some other network on the same cable.
676 if (ARouterIf
== NULL
&& ATALK_VALUE(ifID
->ifARouter
))
679 dPrintf(D_M_DDP_LOW
, D_L_USR1
,
680 ("ddp_output: after search ifid:0x%x %s ifID_home:0x%x\n",
681 (u_int
)ifID
, ifID
? ifID
->ifName
: "",
685 /* located the interface where the packet should
686 * go.... the "first-hop" destination address
687 * must be the same as real destination address.
689 addr_type
= DIRECT_ADDR
;
691 /* no, the destination network number does
692 * not match known network numbers. If we have
693 * heard from this network recently, BRT table
694 * may have address of a router we could use!
696 if (!MULTIPORT_MODE
) {
697 BRT_LOOK (brt
, dst_net
);
699 /* Bingo... BRT has an entry for this network.
700 * Use the link address as is.
702 dPrintf(D_M_DDP
, D_L_VERBOSE
,
703 ("Found BRT entry to send to net 0x%x", dst_net
));
704 at_ddp_stats
.xmit_BRT_used
++;
705 addr_type
= BRT_ENTRY
;
708 /* No BRT entry available for dest network... do we
709 * know of any router at all??
711 if ((ifID
= ARouterIf
) != NULL
)
712 addr_type
= BRIDGE_ADDR
;
714 dPrintf(D_M_DDP
, D_L_WARNING
,
715 ("Found no interface to send pkt"));
716 at_ddp_stats
.xmit_bad_addr
++;
719 goto exit_ddp_output
;
723 else { /* We are in multiport mode, so we can bypass all the rest
724 * and directly ask for the routing of the packet
726 at_ddp_stats
.xmit_BRT_used
++;
729 if (!src_addr_included
) {
730 ddp
->src_node
= ifID
->ifThisNode
.s_node
;
731 NET_ASSIGN(ddp
->src_net
, ifID
->ifThisNode
.s_net
);
733 ddp
->src_socket
= src_socket
;
734 routing_needed(*mp
, ifID
, TRUE
);
736 goto exit_ddp_output
;
739 /* by the time we land here, we know the interface on
740 * which this packet is going out.... ifID.
742 if (ifID
->ifState
== LAP_OFFLINE
) {
744 goto exit_ddp_output
;
750 at_dest.atalk_unused = 0;
752 NET_ASSIGN(at_dest
.atalk_net
, dst_net
);
753 at_dest
.atalk_node
= ddp
->dst_node
;
755 addr
= (char *)&at_dest
;
759 addr
= (char *)&brt
->et_addr
;
762 NET_ASSIGN(at_dest
.atalk_net
, ifID
->ifARouter
.s_net
);
763 at_dest
.atalk_node
= ifID
->ifARouter
.s_node
;
765 addr
= (char *)&at_dest
;
769 /* Irrespective of the interface on which
770 * the packet is going out, we always put the
771 * same source address on the packet (unless multihoming mode).
773 if (MULTIHOME_MODE
) {
774 if (!src_addr_included
) {
775 ddp
->src_node
= ifID
->ifThisNode
.s_node
;
776 NET_ASSIGN(ddp
->src_net
, ifID
->ifThisNode
.s_net
);
780 ddp
->src_node
= ifID_home
->ifThisNode
.s_node
;
781 NET_ASSIGN(ddp
->src_net
, ifID_home
->ifThisNode
.s_net
);
783 ddp
->src_socket
= src_socket
;
785 dPrintf(D_M_DDP_LOW
, D_L_OUTPUT
,
786 ("ddp_output: going out to %d:%d skt%d on %s\n",
787 dst_net
, ddp
->dst_node
, ddp
->dst_socket
, ifID
->ifName
));
789 fillin_pkt_chain(*mp
);
792 struct etalk_addr dest_addr
;
793 struct atalk_addr dest_at_addr
;
794 int loop
= TRUE
; /* flag to aarp to loopback (default) */
798 /* the incoming frame is of the form {flag, address, ddp...}
799 * where "flag" indicates whether the address is an 802.3
800 * (link) address, or an appletalk address. If it's an
801 * 802.3 address, the packet can just go out to the network
802 * through PAT, if it's an appletalk address, AT->802.3 address
803 * resolution needs to be done.
804 * If 802.3 address is known, strip off the flag and 802.3
805 * address, and prepend 802.2 and 802.3 headers.
809 addr_flag
= *(u_char
*)gbuf_rptr(m
);
814 case AT_ADDR_NO_LOOP
:
819 dest_at_addr
= *(struct atalk_addr
*)gbuf_rptr(m
);
820 gbuf_rinc(m
,sizeof(struct atalk_addr
));
822 dest_at_addr
= *(struct atalk_addr
*)addr
;
826 dest_addr
= *(struct etalk_addr
*)gbuf_rptr(m
);
827 gbuf_rinc(m
,sizeof(struct etalk_addr
));
829 dest_addr
= *(struct etalk_addr
*)addr
;
832 dPrintf(D_M_DDP_LOW
,D_L_ERROR
,
833 ("ddp_output: Unknown addr_flag = 0x%x\n", addr_flag
));
834 gbuf_freel(m
); /* unknown address type, chuck it */
835 goto exit_ddp_output
;
840 /* At this point, rptr points to ddp header for sure */
841 if (ifID
->ifState
== LAP_ONLINE_FOR_ZIP
) {
842 /* see if this is a ZIP packet that we need
843 * to let through even though network is
846 if (zip_type_packet(m
) == 0) {
848 goto exit_ddp_output
;
852 ifID
->stats
.xmit_packets
++;
853 ifID
->stats
.xmit_bytes
+= gbuf_msgsize(m
);
854 snmpStats
.dd_outLong
++;
857 case AT_ADDR_NO_LOOP
:
860 * we don't want elap to be looking into ddp header, so
861 * it doesn't know net#, consequently can't do
862 * AMT_LOOKUP. That task left to aarp now.
864 aarp_send_data(m
,ifID
,&dest_at_addr
, loop
);
867 pat_output(ifID
, m
, &dest_addr
, 0);
872 KERNEL_DEBUG(DBG_AT_DDP_OUTPUT
| DBG_FUNC_END
, 0,
877 void ddp_input(mp
, ifID
)
879 register at_ifaddr_t
*ifID
;
881 register at_ddp_t
*ddp
; /* DDP header */
882 register int msgsize
;
883 register at_socket socket
;
885 register at_net_al dst_net
;
887 KERNEL_DEBUG(DBG_AT_DDP_INPUT
| DBG_FUNC_START
, 0,
888 ifID
, mp
, gbuf_len(mp
),0);
890 /* Makes sure we know the default interface before starting to
891 * accept incomming packets. If we don't we may end up with a
892 * null ifID_table[0] and have impredicable results (specially
893 * in router mode. This is a transitory state (because we can
894 * begin to receive packet while we're not completly set up yet.
897 if (ifID_home
== (at_ifaddr_t
*)NULL
) {
898 dPrintf(D_M_DDP
, D_L_ERROR
,
899 ("dropped incoming packet ifID_home not set yet\n"));
901 goto out
; /* return */
905 * if a DDP packet has been broadcast, we're going to get a copy of
906 * it here; if it originated at user level via a write on a DDP
907 * socket; when it gets here, the first block in the chain will be
908 * empty since it only contained the lap level header which will be
909 * stripped in the lap level immediately below ddp
912 if ((mp
= (gbuf_t
*)ddp_compress_msg(mp
)) == NULL
) {
913 dPrintf(D_M_DDP
, D_L_ERROR
,
914 ("dropped short incoming ET packet (len %d)", 0));
915 snmpStats
.dd_inTotal
++;
916 at_ddp_stats
.rcv_bad_length
++;
917 goto out
; /* return; */
919 msgsize
= gbuf_msgsize(mp
);
921 at_ddp_stats
.rcv_bytes
+= msgsize
;
922 at_ddp_stats
.rcv_packets
++;
924 /* if the interface pointer is 0, the packet has been
925 * looped back by 'write' half of DDP. It is of the
926 * form {extended ddp,...}. The packet is meant to go
927 * up to some socket on the same node.
929 if (!ifID
) /* if loop back is specified */
930 ifID
= ifID_home
; /* that means the home port */
932 /* the incoming datagram has extended DDP header and is of
933 * the form {ddp,...}.
935 if (msgsize
< DDP_X_HDR_SIZE
) {
936 dPrintf(D_M_DDP
, D_L_ERROR
,
937 ("dropped short incoming ET packet (len %d)", msgsize
));
938 at_ddp_stats
.rcv_bad_length
++;
940 goto out
; /* return; */
943 * At this point, the message is always of the form
944 * {extended ddp, ... }.
946 ddp
= (at_ddp_t
*)gbuf_rptr(mp
);
949 if (msgsize
!= len
) {
950 if ((unsigned) msgsize
> len
) {
951 if (len
< DDP_X_HDR_SIZE
) {
952 dPrintf(D_M_DDP
, D_L_ERROR
,
953 ("Length problems, ddp length %d, buffer length %d",
955 snmpStats
.dd_tooLong
++;
956 at_ddp_stats
.rcv_bad_length
++;
958 goto out
; /* return; */
961 * shave off the extra bytes from the end of message
963 mp
= ddp_adjmsg(mp
, -(msgsize
- len
)) ? mp
: 0;
965 goto out
; /* return; */
967 dPrintf(D_M_DDP
, D_L_ERROR
,
968 ("Length problems, ddp length %d, buffer length %d",
970 snmpStats
.dd_tooShort
++;
971 at_ddp_stats
.rcv_bad_length
++;
973 goto out
; /* return; */
976 socket
= ddp
->dst_socket
;
979 * We want everything in router mode, specially socket 254 for nbp so we need
980 * to bypass this test when we are a router.
983 if (!MULTIPORT_MODE
&& (socket
> DDP_SOCKET_LAST
||
984 socket
< DDP_SOCKET_1st_RESERVED
)) {
985 dPrintf(D_M_DDP
, D_L_WARNING
,
986 ("Bad dst socket on incoming packet (0x%x)",
988 at_ddp_stats
.rcv_bad_socket
++;
990 goto out
; /* return; */
993 * if the checksum is true, then upstream wants us to calc
995 if (UAS_VALUE(ddp
->checksum
) &&
996 (UAS_VALUE(ddp
->checksum
) != ddp_checksum(mp
, 4))) {
997 dPrintf(D_M_DDP
, D_L_WARNING
,
998 ("Checksum error on incoming pkt, calc 0x%x, exp 0x%x",
999 ddp_checksum(mp
, 4), UAS_VALUE(ddp
->checksum
)));
1000 snmpStats
.dd_checkSum
++;
1001 at_ddp_stats
.rcv_bad_checksum
++;
1003 goto out
; /* return; */
1006 /*############### routing input checking */
1008 /* Router mode special: we send "up-stack" packets for this node or coming from any
1009 * other ports, but for the reserved atalk sockets (RTMP, ZIP, NBP [and EP])
1010 * BTW, the way we know it's for the router and not the home port is that the
1011 * MAC (ethernet) address is always the one of the interface we're on, but
1012 * the AppleTalk address must be the one of the home port. If it's a multicast
1013 * or another AppleTalk address, this is the router job's to figure out where it's
1016 /* *** a duplicate should be sent to any other client that is listening
1017 for packets of this type on a raw DDP socket *** */
1018 if (ddp_handler
[socket
].func
) {
1019 dPrintf(D_M_DDP
,D_L_INPUT
,
1020 ("ddp_input: skt %d hdnlr:0x%x\n",
1021 (u_int
) socket
, ddp_handler
[socket
].func
));
1023 snmpStats
.dd_inLocal
++;
1025 (*ddp_handler
[socket
].func
)(mp
, ifID
);
1026 goto out
; /* return; */
1028 dst_net
= NET_VALUE(ddp
->dst_net
);
1032 /* any node, wildcard or matching net */
1033 ((ddp
->dst_node
== 255) &&
1034 (((dst_net
>= ifID_home
->ifThisCableStart
) &&
1035 (dst_net
<= ifID_home
->ifThisCableEnd
)) ||
1037 /* this node is not online yet(?) */
1038 (ifID
->ifRoutingState
< PORT_ONLINE
)
1042 snmpStats
.dd_inLocal
++;
1044 if (ddp
->type
== DDP_ATP
) {
1045 if (atp_inputQ
[socket
] && (atp_inputQ
[socket
] != (gref_t
*)1)) {
1046 /* if there's an ATP pcb */
1048 goto out
; /* return; */
1050 } else if (ddp
->type
== DDP_ADSP
) {
1051 if (adsp_inputQ
[socket
]) {
1052 /* if there's an ADSP pcb */
1054 goto out
; /* return; */
1058 /* otherwise look for a DDP pcb;
1059 ATP / raw-DDP and ADSP / raw-DDP are possible */
1060 for (gref
= ddp_head
.atpcb_next
; gref
!= &ddp_head
;
1061 gref
= gref
->atpcb_next
)
1062 if (gref
->lport
== socket
&&
1063 (gref
->ddptype
== 0 || gref
->ddptype
== ddp
->type
)) {
1064 dPrintf(D_M_DDP
, D_L_INPUT
,
1065 ("ddp_input: streamq, skt %d\n", socket
));
1066 if (gref
->atpcb_socket
) {
1067 struct sockaddr_at ddp_in
;
1068 ddp_in
.sat_len
= sizeof(ddp_in
);
1069 ddp_in
.sat_family
= AF_APPLETALK
;
1070 ddp_in
.sat_addr
.s_net
= NET_VALUE(ddp
->src_net
);
1071 ddp_in
.sat_addr
.s_node
= ddp
->src_node
;
1072 ddp_in
.sat_port
= ddp
->src_socket
;
1074 /* strip off DDP header if so indicated by
1076 if (gref
->ddp_flags
& DDPFLG_STRIPHDR
) {
1077 mp
= m_pullup((struct mbuf
*)mp
,
1080 gbuf_rinc(mp
, DDP_X_HDR_SIZE
);
1082 /* this should never happen because
1083 msgsize was checked earlier */
1084 at_ddp_stats
.rcv_bad_length
++;
1085 goto out
; /* return */
1089 if (sbappendaddr(&((gref
->atpcb_socket
)->so_rcv
),
1090 (struct sockaddr
*)&ddp_in
,
1091 mp
, 0, NULL
) != 0) {
1092 sorwakeup(gref
->atpcb_socket
);
1095 atalk_putnext(gref
, mp
);
1097 goto out
; /* return */
1100 at_ddp_stats
.rcv_bad_socket
++;
1102 snmpStats
.dd_noHandler
++;
1103 dPrintf(D_M_DDP
, D_L_WARNING
,
1104 ("ddp_input: dropped pkt for socket %d\n", socket
));
1106 dPrintf(D_M_DDP
, D_L_ROUTING
,
1107 ("ddp_input: routing_needed from port=%d sock=%d\n",
1108 ifID
->ifPort
, ddp
->dst_socket
));
1110 snmpStats
.dd_fwdReq
++;
1111 if (((pktsIn
-pktsHome
+200) >= RouterMix
) && ((++pktsDropped
% 5) == 0)) {
1112 at_ddp_stats
.rcv_dropped_nobuf
++;
1116 routing_needed(mp
, ifID
, FALSE
);
1120 KERNEL_DEBUG(DBG_AT_DDP_INPUT
| DBG_FUNC_END
, 0,0,0,0,0);
1125 * ddp_router_output()
1128 * This is a modified version of ddp_output for router use.
1129 * The main difference is that the interface on which the packet needs
1130 * to be sent is specified and a *destination* AppleTalk address is passed
1131 * as an argument, this address may or may not be the same as the destination
1132 * address found in the ddp packet... This is the trick about routing, the
1133 * AppleTalk destination of the packet may not be the same as the Enet address
1134 * we send the packet too (ie, we may pass the baby to another router).
1137 int ddp_router_output(mp
, ifID
, addr_type
, router_net
, router_node
, enet_addr
)
1141 at_net_al router_net
;
1142 at_node router_node
;
1143 etalk_addr_t
*enet_addr
;
1145 register at_ddp_t
*ddp
;
1146 struct atalk_addr at_dest
;
1152 dPrintf(D_M_DDP
, D_L_WARNING
, ("BAD BAD ifID\n"));
1156 ddp
= (at_ddp_t
*)gbuf_rptr(mp
);
1158 if (ifID
->ifFlags
& AT_IFF_AURP
) { /* AURP link? */
1159 if (ddp_AURPsendx
) {
1160 fillin_pkt_chain(mp
);
1161 if (router_node
== 255)
1163 ddp_AURPsendx(AURPCODE_DATAPKT
, mp
, router_node
);
1171 /* keep some of the tests for now ####### */
1173 if (gbuf_msgsize(mp
) > DDP_DATAGRAM_SIZE
) {
1174 /* the packet is too large */
1175 dPrintf(D_M_DDP
, D_L_WARNING
,
1176 ("ddp_router_output: Packet too large size=%d\n",
1182 switch (addr_type
) {
1187 * Check for packet destined to the home stack
1190 if ((ddp
->dst_node
== ifID
->ifThisNode
.s_node
) &&
1191 (NET_VALUE(ddp
->dst_net
) == ifID
->ifThisNode
.s_net
)) {
1192 dPrintf(D_M_DDP_LOW
, D_L_ROUTING
,
1193 ("ddp_r_output: sending back home from port=%d socket=%d\n",
1194 ifID
->ifPort
, ddp
->dst_socket
));
1196 UAS_ASSIGN(ddp
->checksum
, 0);
1197 ddp_input(mp
, ifID
);
1201 NET_ASSIGN(at_dest
.atalk_net
, router_net
);
1202 at_dest
.atalk_node
= router_node
;
1204 addr_flag
= AT_ADDR_NO_LOOP
;
1205 addr
= (char *)&at_dest
;
1206 dPrintf(D_M_DDP_LOW
, D_L_ROUTING_AT
,
1207 ("ddp_r_output: AT_ADDR out port=%d net %d:%d via rte %d:%d",
1208 ifID
->ifPort
, NET_VALUE(ddp
->dst_net
), ddp
->dst_node
, router_net
,
1213 addr_flag
= ET_ADDR
;
1214 addr
= (char *)enet_addr
;
1215 dPrintf(D_M_DDP_LOW
, D_L_ROUTING
,
1216 ("ddp_r_output: ET_ADDR out port=%d net %d:%d\n",
1217 ifID
->ifPort
, NET_VALUE(ddp
->dst_net
), ddp
->dst_node
));
1221 if (ifID
->ifState
== LAP_OFFLINE
) {
1226 fillin_pkt_chain(mp
);
1229 struct etalk_addr dest_addr
;
1230 struct atalk_addr dest_at_addr
;
1231 int loop
= TRUE
; /* flag to aarp to loopback (default) */
1235 /* the incoming frame is of the form {flag, address, ddp...}
1236 * where "flag" indicates whether the address is an 802.3
1237 * (link) address, or an appletalk address. If it's an
1238 * 802.3 address, the packet can just go out to the network
1239 * through PAT, if it's an appletalk address, AT->802.3 address
1240 * resolution needs to be done.
1241 * If 802.3 address is known, strip off the flag and 802.3
1242 * address, and prepend 802.2 and 802.3 headers.
1246 addr_flag
= *(u_char
*)gbuf_rptr(m
);
1250 switch (addr_flag
) {
1251 case AT_ADDR_NO_LOOP
:
1256 dest_at_addr
= *(struct atalk_addr
*)gbuf_rptr(m
);
1257 gbuf_rinc(m
,sizeof(struct atalk_addr
));
1259 dest_at_addr
= *(struct atalk_addr
*)addr
;
1263 dest_addr
= *(struct etalk_addr
*)gbuf_rptr(m
);
1264 gbuf_rinc(m
,sizeof(struct etalk_addr
));
1266 dest_addr
= *(struct etalk_addr
*)addr
;
1269 dPrintf(D_M_DDP_LOW
,D_L_ERROR
,
1270 ("ddp_router_output: Unknown addr_flag = 0x%x\n", addr_flag
));
1272 gbuf_freel(m
); /* unknown address type, chuck it */
1278 /* At this point, rptr points to ddp header for sure */
1279 if (ifID
->ifState
== LAP_ONLINE_FOR_ZIP
) {
1280 /* see if this is a ZIP packet that we need
1281 * to let through even though network is
1284 if (zip_type_packet(m
) == 0) {
1290 ifID
->stats
.xmit_packets
++;
1291 ifID
->stats
.xmit_bytes
+= gbuf_msgsize(m
);
1292 snmpStats
.dd_outLong
++;
1294 switch (addr_flag
) {
1295 case AT_ADDR_NO_LOOP
:
1298 * we don't want elap to be looking into ddp header, so
1299 * it doesn't know net#, consequently can't do
1300 * AMT_LOOKUP. That task left to aarp now.
1302 aarp_send_data(m
,ifID
,&dest_at_addr
, loop
);
1305 pat_output(ifID
, m
, &dest_addr
, 0);
1311 } /* ddp_router_output */
1313 /*****************************************/
1315 void rt_delete(NetStop
, NetStart
)
1316 unsigned short NetStop
;
1317 unsigned short NetStart
;
1322 ATDISABLE(s
, ddpinp_lock
);
1323 if ((found
= rt_bdelete(NetStop
, NetStart
)) != 0) {
1324 bzero(found
, sizeof(RT_entry
));
1325 found
->right
= RT_table_freelist
;
1326 RT_table_freelist
= found
;
1328 ATENABLE(s
, ddpinp_lock
);
1331 int ddp_AURPfuncx(code
, param
, node
)
1336 extern void rtmp_timeout();
1337 extern void rtmp_send_port();
1342 case AURPCODE_DATAPKT
: /* data packet */
1344 dPrintf(D_M_DDP
, D_L_TRACE
, ("ddp_AURPfuncx: data, 0x%x, %d\n",
1345 (u_int
) aurp_ifID
, node
));
1347 ddp_input((gbuf_t
*)param
, aurp_ifID
);
1349 gbuf_freem((gbuf_t
*)param
);
1352 case AURPCODE_REG
: /* register/deregister */
1355 ddp_AURPsendx
= (void(*)())param
;
1358 /* register AURP callback function */
1361 for (k
=(IFID_HOME
+1); k
< IF_TOTAL_MAX
; k
++) {
1362 if (ifID_table
[k
] == 0) {
1363 aurp_ifID
= &at_interfaces
[k
];
1364 aurp_ifID
->ifFlags
= RTR_XNET_PORT
;
1365 ddp_add_if(aurp_ifID
);
1366 aurp_ifID
->ifState
= LAP_ONLINE
;
1367 aurp_ifID
->ifRoutingState
= PORT_ONLINE
;
1368 dPrintf(D_M_DDP
, D_L_TRACE
,
1369 ("ddp_AURPfuncx: on, 0x%x\n",
1370 (u_int
) aurp_ifID
));
1372 ddp_AURPsendx(AURPCODE_DEBUGINFO
,
1373 &dbgBits
, aurp_ifID
->ifPort
);
1380 /* deregister AURP callback function */
1382 rtmp_purge(aurp_ifID
);
1383 ddp_rem_if(aurp_ifID
);
1384 aurp_ifID
->ifState
= LAP_OFFLINE
;
1385 aurp_ifID
->ifRoutingState
= PORT_OFFLINE
;
1386 dPrintf(D_M_DDP
, D_L_TRACE
,
1387 ("ddp_AURPfuncx: off, 0x%x\n", (u_int
) aurp_ifID
));
1393 case AURPCODE_AURPPROTO
: /* proto type - AURP */
1395 aurp_ifID
->ifFlags
|= AT_IFF_AURP
;
1404 /* checks to see if address of packet is for one of our interfaces
1405 returns *ifID if it's for us, NULL if not
1407 at_ifaddr_t
*forUs(ddp
)
1408 register at_ddp_t
*ddp
;
1412 TAILQ_FOREACH(ifID
, &at_ifQueueHd
, aa_link
) {
1413 if ((ddp
->dst_node
== ifID
->ifThisNode
.s_node
) &&
1414 (NET_VALUE(ddp
->dst_net
) == ifID
->ifThisNode
.s_net
)
1416 dPrintf(D_M_DDP_LOW
, D_L_ROUTING
,
1417 ("pkt was for port %d\n", ifID
->ifPort
));
1423 return((at_ifaddr_t
*)NULL
);