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