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