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