|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Copyright (c) 1987, 1988, 1989 Apple Computer, Inc.
27: *
28: * The information contained herein is subject to change without
29: * notice and should not be construed as a commitment by Apple
30: * Computer, Inc. Apple Computer, Inc. assumes no responsibility
31: * for any errors that may appear.
32: *
33: * Confidential and Proprietary to Apple Computer, Inc.
34: *
35: *
36: *
37: */
38:
39:
40: #define RESOLVE_DBG /* define debug globals in debug.h */
41:
42: #include <sysglue.h>
43: #include <at/appletalk.h>
44: #include <lap.h>
45: #include <llap.h>
46: #include <at/elap.h>
47: #include <at/ddp.h>
48: #include <at/ep.h>
49: #include <nbp.h>
50: #include <rtmp.h>
51: #include <at/zip.h>
52: #include <at/at_lap.h>
53: #include <at_elap.h>
54: #include <at_ddp.h>
55: #include <adsp_local.h>
56: #include <at_ddp_brt.h>
57: #include <at_zip.h>
58: #include <routing_tables.h>
59: #include <atlog.h>
60: #include <at_snmp.h>
61: #include <at_aurp.h>
62:
63: #include "at_kdebug.h"
64:
65: /* globals */
66: /* Queue of LAP interfaces which have registered themselves with DDP */
67: static at_if_t at_ifQueueHd = { &at_ifQueueHd, &at_ifQueueHd };
68:
69: /* Pointer to LAP interface which DDP addresses are tied to */
70: /*at_if_t *at_ifDefault = 0; */
71:
72: /* DDP statistics */
73: static at_ddp_stats_t at_ddp_stats;
74: snmpStats_t snmpStats; /* snmp ddp & echo stats */
75:
76: /* DDP input queue */
77: static char *InputQueue = NULL;
78:
79: /* DDP Socket Table */
80: ddp_socket_t ddp_socket [DDP_SOCKET_LAST + 1];
81:
82: at_if_t *ifID_table[IF_TOTAL_MAX];
83: /* the table of ifID structures, one per
84: * interface (not just ethernet)
85: * NOTE: for MH, entry 0 in this table is
86: * now defined to be the default I/F
87: */
88:
89: /* Appletalk state */
90: extern at_state_t *at_statep;
91:
92: /* routing mode special */
93: void (*ddp_AURPsendx)();
94: at_if_t *aurp_ifID = 0;
95: extern routing_needed();
96: extern pktsIn,pktsOut;
97: /* extern char ddp_off_flag; */
98: int pktsDropped,pktsHome;
99: atlock_t ddpall_lock;
100: atlock_t ddpinp_lock;
101:
102: int ot_protoCnt = 0;
103: char ot_protoT[256];
104: char ot_atp_socketM[256];
105: char ot_adsp_socketM[256];
106:
107: extern int *atp_pidM;
108: extern int *adsp_pidM;
109: extern gref_t *atp_inputQ[];
110: extern CCB *adsp_inputQ[];
111:
112: at_if_t *forUs(at_ddp_t *);
113:
114: extern void
115: routershutdown(),
116: ddp_brt_shutdown();
117: void ddp_notify_nbp();
118:
119: #define MAX_NOTIFY_NBP 16
120: static struct {
121: unsigned char socket;
122: unsigned char ddptype;
123: unsigned short filler;
124: int pid;
125: } notify_nbp_tbl[MAX_NOTIFY_NBP];
126:
127: void
128: Xddp_notify_nbp(id)
129: int id;
130: {
131: unsigned char socket;
132:
133: if ((socket = notify_nbp_tbl[id].socket) != 0) {
134: notify_nbp_tbl[id].socket = 0;
135: ddp_notify_nbp(
136: socket,
137: notify_nbp_tbl[id].pid,
138: notify_nbp_tbl[id].ddptype);
139: }
140: }
141:
142: int
143: ot_ddp_check_socket(socket, pid)
144: unsigned char socket;
145: int pid;
146: {
147: extern ddp_dev_t ddp_devs[];
148: int cnt;
149:
150: dPrintf(D_M_DDP, D_L_INFO, ("ot_ddp_check_socket: %d\n", socket));
151: cnt = (DDP_SOCK_UPQ(socket) == NULL) ? 0 :
152: ( (ddp_devs[socket].pid == pid) ? 1 : 0 );
153: if (ot_protoT[3]) { /* ATP */
154: if ((atp_inputQ[socket] != NULL)
155: && (atp_inputQ[socket] != (gref_t *)1)
156: && (atp_pidM[socket] == pid))
157: cnt++;
158: }
159: if (ot_protoT[DDP_ADSP]) {
160: if ((adsp_inputQ[socket] != NULL) && (adsp_pidM[socket] == pid))
161: cnt++;
162: }
163:
164: return(cnt);
165: }
166:
167: /****************************************************************/
168: /* */
169: /* */
170: /* Support Routines */
171: /* */
172: /* */
173: /****************************************************************/
174:
175: /*
176: * Name:
177: * ddp_checksum
178: *
179: * Description:
180: * This procedure determines the checksum of an extended DDP datagram.
181: * Add the unsigned bytes into an unsigned 16-bit accumulator.
182: * After each add, rotate the sign bit into the low order bit of
183: * the accumulator. When done, if the checksum is 0, changed into 0xFFFF.
184: *
185: * Calling sequence:
186: * checksum = ddp_checksum(mp, offset)
187: *
188: * Parameters:
189: * mp pointer to the datagram gbuf_t
190: * offset offset to start at in first gbuf_t block
191: *
192: * Return value:
193: * The DDP checksum.
194: *
195: */
196:
197: static u_short
198: ddp_checksum(mp, offset)
199: register gbuf_t *mp;
200: register int offset;
201: {
202: register u_char *data;
203: register int length;
204: register u_short checksum;
205:
206: checksum = 0;
207:
208: do {
209: if (offset >= gbuf_len(mp))
210: offset -= gbuf_len(mp);
211: else {
212: data = ((unsigned char *) gbuf_rptr(mp)) + offset;
213: length = gbuf_len(mp) - offset;
214: offset = 0;
215: /* Portable checksum from 3.0 */
216: while (length--) {
217: checksum += *data++;
218: checksum = (checksum & 0x8000) ?
219: ((checksum << 1) | 1) : (checksum << 1);
220: }
221: }
222: } while ( (mp = gbuf_cont(mp)) );
223:
224: if (checksum == 0)
225: checksum = 0xffff;
226:
227: return(checksum);
228: }
229:
230:
231: void ddp_shutdown()
232: {
233: routershutdown();
234: ddp_brt_shutdown();
235: ddps_shutdown((gref_t *)InputQueue);
236: InputQueue = NULL;
237: dPrintf(D_M_DDP, D_L_VERBOSE, ("DDP shutdown completed"));
238: return;
239: }
240:
241:
242: /*
243: * Name:
244: * ddp_init
245: *
246: * Description:
247: * Initializes DDP. The streams version allocates a new queue pair to
248: * be used as the input queue for incoming lap datagrams. The write
249: * queue of this pair is not used.
250: *
251: * Return value:
252: *
253: * Priority Level:
254: * This function is called by the stream head open routines, or
255: * by the lap layer's ONLINE function via ddp_add_if().
256: */
257: static int
258: ddp_init()
259: {
260: char *q;
261: char *ddps_init();
262: void ddp_brt_init();
263: at_socket socket;
264:
265: typedef void (*proc_ptr)();
266: proc_ptr handler;
267: extern void sip_init();
268:
269: dPrintf(D_M_DDP, D_L_STARTUP, ("ddp_init starting\n"));
270: /* If using streams, we may get called more than once */
271: if (InputQueue == NULL) {
272: bzero((char *)notify_nbp_tbl, sizeof(notify_nbp_tbl));
273: if ((q = ddps_init()) == NULL)
274: return(ENOBUFS);
275: else {
276: InputQueue = q;
277: /* initialize the ddp_socket table */
278: bzero(ddp_socket,sizeof(ddp_socket));
279: for (socket = DDP_SOCKET_1st_RESERVED;
280: socket <= DDP_SOCKET_LAST; socket++)
281: ddp_socket[socket].number = socket;
282: bzero(&at_ddp_stats, sizeof(at_ddp_stats_t));
283: ddp_brt_init();
284:
285: /* Initialize all the protocols implemented in
286: * kernel
287: */
288: handler = (proc_ptr)ep_init();
289: ddp_socket[EP_SOCKET].number = EP_SOCKET;
290: ddp_socket[EP_SOCKET].flags |= DDP_CALL_HANDLER;
291: DDP_SOCK_HANDLER(EP_SOCKET) = handler;
292:
293: handler = (proc_ptr)rtmp_init();
294: ddp_socket[RTMP_SOCKET].number= RTMP_SOCKET;
295: ddp_socket[RTMP_SOCKET].flags|=DDP_CALL_HANDLER;
296: DDP_SOCK_HANDLER(RTMP_SOCKET) = handler;
297:
298: handler = (proc_ptr)zip_init();
299: ddp_socket[ZIP_SOCKET].flags|=DDP_CALL_HANDLER;
300: ddp_socket[ZIP_SOCKET].number = ZIP_SOCKET;
301: DDP_SOCK_HANDLER(ZIP_SOCKET) = handler;
302:
303: handler = (proc_ptr)nbp_init();
304: ddp_socket[NBP_SOCKET].number = NBP_SOCKET;
305: ddp_socket[NBP_SOCKET].flags |= DDP_CALL_HANDLER;
306: DDP_SOCK_HANDLER(NBP_SOCKET) = handler;
307:
308: bzero(ifID_table, sizeof(ifID_table));
309:
310: sip_init();
311: }
312: }
313: dPrintf(D_M_DDP, D_L_STARTUP, ("ddp_init OK\n"));
314:
315: return (0);
316: }
317:
318:
319: /*
320: * ddp_add_if()
321: *
322: * Description:
323: * This procedure is called by each LAP interface when it wants to place
324: * itself online. The LAP interfaces passes in a pointer to its at_if
325: * struct, which is added to DDP's list of active interfaces (at_ifQueueHd).
326: * When DDP wants to transmit a packet, it searches this list for the
327: * interface to use.
328: *
329: * If AT_IFF_DEFAULT is set, then this interface is to be brought online
330: * as the interface DDP socket addresses are tied to. Of course there can
331: * be only one default interface; we return an error if it's already set.
332: *
333: * Calling Sequence:
334: * ret_status = ddp_add_if(ifID)
335: *
336: * Formal Parameters:
337: * ifID pointer to LAP interface's at_if struct.
338: *
339: * Completion Status:
340: * 0 Procedure successfully completed.
341: * EALREADY This interface is already online, or there is
342: * already a default interface.
343: * ENOBUFS Cannot allocate input queue
344: *
345: * Side Effects:
346: * The global at_ifDefault may be set.
347: */
348: int ddp_add_if(ifID)
349: register at_if_t *ifID;
350: {
351: int status;
352: int port = -1;
353:
354: dPrintf(D_M_DDP, D_L_STARTUP, ("ddp_add_if: called, ifID:0x%x\n", (u_int) ifID));
355: /* Initialize some of the ddp data structures and protocol modules
356: * like NBP and RTMP.
357: */
358: if (!(at_statep->flags & AT_ST_DDP_INIT)) {
359:
360: if ((status = ddp_init()) != 0) {
361: ifID->ddpInputQueue = NULL;
362: return(status);
363: }
364: at_statep->flags |= AT_ST_DDP_INIT;
365: }
366: if (ifID->ifFlags & AT_IFF_DEFAULT) {
367: if (ifID_table[IFID_HOME]) {
368: return(EEXIST); /* home port already set */
369: }
370: else {
371: port = 0;
372: ifID_table[IFID_HOME] = ifID;
373: }
374: }
375: else
376: for (port=IFID_HOME+1; port<IF_TOTAL_MAX; port++) { /* add i/f to port list */
377: if (!ifID_table[port]) {
378: ifID_table[port] = ifID;
379: ifID->ifPort = port; /* set ddp port # in ifID */
380: break;
381: }
382: }
383:
384: if (port == IF_TOTAL_MAX) { /* no space left */
385: ifID->ddpInputQueue = NULL;
386: return(ENOMEM);
387: }
388: dPrintf(D_M_DDP, D_L_STARTUP, ("ddp:adding ifID_table[%d]\n", port));
389:
390: /* Add this interface to the list of online interfaces */
391: ddp_insque((LIB_QELEM_T *)ifID, (LIB_QELEM_T *)at_ifQueueHd.FwdLink);
392:
393: ifID->ddpInputQueue = InputQueue;
394: ATALK_ASSIGN(ifID->ifARouter, 0, 0, 0);
395: at_statep->ifs_online++;
396:
397: return (0);
398: }
399:
400:
401: /*
402: * ddp_rem_if()
403: *
404: * Description:
405: * This procedure is called by each LAP interface when it wants to take
406: * itself offline. The LAP interfaces passes in a pointer to its at_if
407: * struct; DDP's list of active interfaces (at_ifQueueHd) is searched and
408: * this interface is removed from the list. DDP can still transmit
409: * packets as long as this interface is not the default interface; the
410: * sender will just get ENETUNREACH errors when it tries to send to an
411: * interface that went offline. However, if the default interface is
412: * taken offline, we no longer have a node ID to use as a source address
413: * and DDP must return ENETDOWN when a caller tries to send a packet.
414: *
415: * Calling Sequence:
416: * ret_status = ddp_rem_if(ifID)
417: *
418: * Formal Parameters:
419: * ifID pointer to LAP interface's at_if struct.
420: *
421: * Completion Status:
422: * 0 Procedure successfully completed.
423: * EALREADY This interface is already offline.
424: *
425: * Side Effects:
426: * The global at_ifDefault may be reset.
427: */
428: int ddp_rem_if(ifID)
429: register at_if_t *ifID;
430: {
431: register at_if_t *ifQueuep;
432: int s;
433:
434: ATDISABLE(s, ddpall_lock);
435: ifQueuep = at_ifQueueHd.FwdLink;
436: while (ifQueuep != &at_ifQueueHd) {
437: if (ATALK_EQUAL(ifQueuep->ifThisNode, ifID->ifThisNode)){
438: trackrouter_rem_if(ifID);
439: ifID->ifARouterTimer = 0;
440: ddp_remque((LIB_QELEM_T *)ifQueuep);
441: if (at_statep->ifs_online == 1) { /* if last interface */
442: ddp_shutdown();
443: }
444: ifID_table[ifID->ifPort] = NULL;
445: at_statep->ifs_online--;
446: ATENABLE(s, ddpall_lock);
447: return (0);
448: }
449: ifQueuep = ifQueuep->FwdLink;
450: }
451: ATENABLE(s, ddpall_lock);
452: return (EALREADY);
453: }
454:
455: /*
456: * The user may have registered an NVE with the NBP on a socket. When the
457: * socket is closed, the NVE should be deleted from NBP's name table. The
458: * user should delete the NVE before the socket is shut down, but there
459: * may be circumstances when he can't. So, whenever a DDP socket is closed,
460: * this routine is used to notify NBP of the socket closure. This would
461: * help NBP get rid of all NVE's registered on the socket.
462: */
463: void ddp_notify_nbp(socket, pid, ddptype)
464: unsigned char socket;
465: int pid;
466: unsigned char ddptype;
467: {
468: register int size;
469: register gbuf_t *mp;
470: register at_ddp_t *ddp;
471: register at_nbp_t *nbp;
472: void ddp_input();
473: int id;
474:
475: /* *** do this only when the default interface is filled in? *** */
476: if (DDP_SOCK_UPQ(NBP_SOCKET) && ifID_table[IFID_HOME]) {
477: size = DDP_X_HDR_SIZE + 2; /* for NBP control fields */
478:
479: if (!(mp = gbuf_alloc(size+8, PRI_HI))) {
480: dPrintf(D_M_DDP, D_L_ERROR, ("DDP: TROUBLE out of gbuf"));
481: /* *** find an empty entry? *** */
482: for (id = 0; id < MAX_NOTIFY_NBP; id++) {
483: if (notify_nbp_tbl[id].socket == 0) {
484: notify_nbp_tbl[id].socket = socket;
485: notify_nbp_tbl[id].ddptype = ddptype;
486: notify_nbp_tbl[id].pid = pid;
487: atalk_timeout(Xddp_notify_nbp, id, SYS_HZ/10);
488: break;
489: }
490: }
491: return;
492: }
493:
494: gbuf_wset(mp, size);
495: ddp = (at_ddp_t *)gbuf_rptr(mp);
496: nbp = (at_nbp_t *)ddp->data;
497:
498: nbp->control = NBP_CLOSE_NOTE;
499: nbp->tuple_count = nbp->at_nbp_id = 0;
500: ((int *)gbuf_wptr(mp))[0] = (int)pid;
501: ((int *)gbuf_wptr(mp))[1] = (int)ddptype;
502:
503: ddp->type = NBP_DDP_TYPE;
504: ddp->unused = ddp->hopcount = 0;
505: DDPLEN_ASSIGN(ddp, size);
506: UAS_ASSIGN(ddp->checksum, 0);
507: NET_NET(ddp->src_net, ifID_table[IFID_HOME]->ifThisNode.atalk_net);
508: ddp->src_node = ifID_table[IFID_HOME]->ifThisNode.atalk_node;
509: ddp->src_socket = (at_socket)socket;
510: NET_NET(ddp->dst_net, ifID_table[IFID_HOME]->ifThisNode.atalk_net);
511: ddp->dst_node = ifID_table[IFID_HOME]->ifThisNode.atalk_node;
512: ddp->dst_socket = NBP_SOCKET;
513: ddp_input(mp, 0); /* ifID 0 implies loopback */
514: }
515: } /* ddp_notify_nbp */
516:
517:
518: /* This routine shrinks the ddp header from long to short,
519: * It also prepends ALAP header and fills up some of the
520: * fields as appropriate.
521: */
522: static at_ddp_short_t *ddp_shrink_hdr (mp)
523: register gbuf_t *mp;
524: {
525: register at_ddp_t *ddp;
526: register at_ddp_short_t *ddp_short;
527: register at_llap_hdr_t *llap;
528: gbuf_t *newmp;
529:
530: if ((newmp = (gbuf_t *)gbuf_copym((gbuf_t *) mp)) == (gbuf_t *)NULL)
531: return ((at_ddp_short_t *)NULL);
532: gbuf_freem(mp);
533: mp = newmp;
534:
535: ddp = (at_ddp_t *)gbuf_rptr(mp);
536: gbuf_rinc(mp,((DDP_X_HDR_SIZE - DDP_HDR_SIZE) - LLAP_HDR_SIZE));
537: llap = (at_llap_hdr_t *)gbuf_rptr(mp);
538: ddp_short = (at_ddp_short_t *)(gbuf_rptr(mp) + LLAP_HDR_SIZE);
539:
540: llap->destination = ddp->dst_node;
541: llap->type = LLAP_TYPE_DDP;
542: ddp_short->length = ddp->length - (DDP_X_HDR_SIZE - DDP_HDR_SIZE);
543: ddp_short->unused = 0;
544: return ((at_ddp_short_t *)mp);
545: }
546:
547:
548: /* mp points to message of the form {llap, short ddp, ...}.
549: * Get rid of llap, extend ddp header to make it of the form
550: * {extended ddp, ... }
551: */
552: static gbuf_t *ddp_extend_hdr (mp)
553: register gbuf_t *mp;
554: {
555: register at_llap_hdr_t *llap;
556: register at_ddp_short_t *ddp_short;
557: register at_ddp_t *ddp;
558: char buf[DDP_HDR_SIZE + LLAP_HDR_SIZE];
559: gbuf_t *m1, *m2;
560:
561: /* We need to remove the llap header from the packet and extend the
562: * short DDP header in to a long one. 5 bytes of additional space
563: * is required in effect, but we can not afford to put these 5 bytes
564: * in a separate buffer, since the ddp buffer would end up being
565: * fragmented into two pieces, which is a no-no. So, we first get
566: * rid of the llap and ddp short headers and then add the extended
567: * header.
568: */
569:
570: /* Assuming that the llap and ddp short headers are placed next
571: * to each other in the same buffer
572: */
573: bcopy(gbuf_rptr(mp), buf, LLAP_HDR_SIZE + DDP_HDR_SIZE);
574: m1 = ddp_adjmsg(mp, LLAP_HDR_SIZE+DDP_HDR_SIZE) ? mp : 0;
575:
576: /* If the message did not contain any ddp data bytes, then m would
577: * be NULL at this point... and we can't just grow a NULL message,
578: * we need to ALLOC a new one.
579: */
580: if (m1) {
581: if ((m2 = (gbuf_t *)ddp_growmsg(m1, -DDP_X_HDR_SIZE)) == NULL) {
582: dPrintf(D_M_DDP, D_L_WARNING,
583: ("Dropping packet - no bufs to extend hdr"));
584: at_ddp_stats.rcv_dropped_nobuf++;
585: gbuf_freem(m1);
586: return(NULL);
587: }
588: } else
589: /* Original message mp has already been freed by ddp_adjmsg if we
590: * managed to arrive here... this case occurs only when the
591: * message mp did not contain any ddp data bytes, only lap and
592: * ddp headers
593: */
594: if ((m2 = gbuf_alloc(AT_WR_OFFSET+DDP_X_HDR_SIZE, PRI_MED)) == NULL) {
595: dPrintf(D_M_DDP,D_L_WARNING,
596: ("Packet (no data) dropped - no bufs to extend hdr"));
597: at_ddp_stats.rcv_dropped_nobuf++;
598: return(NULL);
599: } else {
600: gbuf_rinc(m2,AT_WR_OFFSET);
601: gbuf_wset(m2,DDP_X_HDR_SIZE);
602: }
603:
604: /* By the time we arrive here, m2 points to message of the form
605: * {Extended DDP, ... }
606: * mp and m1 are either non-existent or irrelevant.
607: */
608: ddp = (at_ddp_t *)gbuf_rptr(m2);
609: llap = (at_llap_hdr_t *)buf;
610: ddp_short = (at_ddp_short_t *)(buf + LLAP_HDR_SIZE);
611:
612: ddp->unused = ddp->hopcount = 0;
613: ddp->length = ddp_short->length + DDP_X_HDR_SIZE - DDP_HDR_SIZE;
614: UAS_ASSIGN(ddp->checksum, 0);
615: NET_NET(ddp->dst_net, ifID_table[IFID_HOME]->ifThisNode.atalk_net);
616: NET_NET(ddp->src_net, ifID_table[IFID_HOME]->ifThisNode.atalk_net);
617: ddp->src_node = llap->source;
618: ddp->dst_node = llap->destination;
619: ddp->dst_socket = ddp_short->dst_socket;
620: ddp->src_socket = ddp_short->src_socket;
621: ddp->type = ddp_short->type;
622: return (m2);
623: }
624:
625:
626: int ddp_get_cfg(cfgp, src_socket)
627: register at_ddp_cfg_t *cfgp;
628: at_socket src_socket;
629: {
630: register at_if_t *ifID = ifID_table[IFID_HOME];
631:
632: dPrintf(D_M_DDP, D_L_VERBOSE, ("ddp_get_cfg() entry"));
633: cfgp->network_up = (ifID != NULL);
634:
635: cfgp->flags = ifID? ifID->ifFlags : 0;
636:
637: if (ifID) {
638: NET_NET(cfgp->node_addr.net, ifID->ifThisNode.atalk_net);
639: cfgp->node_addr.node = ifID->ifThisNode.atalk_node;
640: cfgp->node_addr.socket = src_socket;
641: if (!ROUTING_MODE && (ifID->ifRouterState == NO_ROUTER)) {
642: NET_ASSIGN(cfgp->router_addr.net, 0);
643: cfgp->router_addr.node = 0;
644: } else {
645: NET_NET(cfgp->router_addr.net, ifID->ifARouter.atalk_net);
646: cfgp->router_addr.node = ifID->ifARouter.atalk_node;
647: }
648: cfgp->netlo = ifID->ifThisCableStart;
649: cfgp->nethi = ifID->ifThisCableEnd;
650: }
651: else {
652: NET_ASSIGN(cfgp->node_addr.net, 64000);
653: cfgp->node_addr.node = 128;
654: NET_ASSIGN(cfgp->router_addr.net, 0);
655: cfgp->router_addr.node = 0;
656: cfgp->node_addr.socket = src_socket;
657: cfgp->netlo = 1;
658: cfgp->nethi = 64500;
659: }
660:
661: return(0);
662: }
663:
664:
665: int ddp_get_stats(statsp)
666: at_ddp_stats_t *statsp;
667: {
668: dPrintf(D_M_DDP, D_L_VERBOSE, ("ddp_get_cfg() entry"));
669: bcopy(&at_ddp_stats, statsp, sizeof(at_ddp_stats));
670: return(0);
671: }
672:
673:
674: /****************************************************************/
675: /* */
676: /* */
677: /* Module Code */
678: /* */
679: /* */
680: /****************************************************************/
681:
682: /*
683: * ddp_bind_socket()
684: *
685: * Description:
686: *
687: * Calling Sequence:
688: * ret_status = ddp_bind_socket(socketp)
689: *
690: * Formal Parameters:
691: * socketp pointer to a socket table entry
692: *
693: * Completion Status:
694: * 0 Procedure successfully completed.
695: * EINVAL Invalid well-known socket supplied.
696: * EACCES User is not super-user.
697: * ENETDOWN There are no interfaces online.
698: *
699: * Side Effects:
700: * NONE
701: */
702:
703: int
704: ddp_bind_socket(socketp)
705: register ddp_socket_t *socketp;
706: {
707: register at_socket socket;
708: u_char proto;
709: int s;
710:
711: ATDISABLE(s, ddpall_lock);
712: if (socketp->dev == NULL)
713: proto = 0;
714: else
715: proto = ((ddp_dev_t *)socketp->dev)->proto;
716:
717: /* Request for dynamic socket? */
718: if (socketp->number == 0) {
719: /* Search table for free one */
720: for (socket = DDP_SOCKET_LAST-proto;
721: socket >= DDP_SOCKET_1st_DYNAMIC; socket--)
722: if (DDP_SOCK_UPQ(socket) == 0) {
723: if ((proto == DDP_ATP) && atp_inputQ[socket])
724: continue;
725: else if ((proto == DDP_ADSP) && adsp_inputQ[socket])
726: continue;
727: break;
728: }
729: if (socket < DDP_SOCKET_1st_DYNAMIC)
730: {
731: ATENABLE(s, ddpall_lock);
732: return(EADDRNOTAVAIL); /* Error if no free sockets */
733: }
734: else
735: socketp->number = ddp_socket[socket].number;
736: } else {
737: /* Asking to open a socket by its number. Check if its legal &
738: * free.
739: */
740: socket = socketp->number;
741: if (socket > DDP_SOCKET_LAST)
742: {
743: ATENABLE(s, ddpall_lock);
744: return(EINVAL);
745: }
746: if (DDP_SOCK_UPQ(socket) || DDP_SOCK_HANDLER(socket))
747: {
748: ATENABLE(s, ddpall_lock);
749: return(EISCONN);
750: }
751: }
752: if (proto == DDP_ATP) {
753: if (atp_inputQ[socket])
754: {
755: ATENABLE(s, ddpall_lock);
756: return(EISCONN);
757: }
758: ot_atp_socketM[socket] = 1;
759: } else if (proto == DDP_ADSP) {
760: if (adsp_inputQ[socket])
761: {
762: ATENABLE(s, ddpall_lock);
763: return(EISCONN);
764: }
765: ot_adsp_socketM[socket] = 1;
766: }
767: ddp_socket[socket].flags = socketp->flags;
768: DDP_SOCK_UPQ(socket) = socketp->sock_u.gref;
769: ATENABLE(s, ddpall_lock);
770:
771: dPrintf(D_M_DDP, D_L_VERBOSE,
772: ("Socket 0x%x is opened", (u_char)socket));
773:
774: return(0);
775: }
776:
777:
778: /*
779: * ddp_close_socket()
780: *
781: * Description:
782: * This procedure closes a DDP socket.
783: * NBP is notified that the socket is being closed so that it can
784: * deregister any attached names.
785: *
786: * Calling Sequence:
787: * ret_status = ddp_close_socket(socketp)
788: *
789: * Formal Parameters:
790: * socketp pointer to a socket table entry
791: *
792: * Completion Status:
793: * 0 Procedure successfully completed.
794: * ENOTCONN Socket was not open.
795: *
796: * Side Effects:
797: * NONE
798: */
799: int ddp_close_socket(socketp)
800: register ddp_socket_t *socketp;
801: {
802: register at_socket socket = socketp->number;
803:
804: /* Make sure socket was open, if not return error */
805: if (!DDP_SOCK_UPQ(socket))
806: return (ENOTCONN);
807:
808: /* Notify NBP that we are closing this DDP socket */
809: ddp_notify_nbp(socket,
810: ((ddp_dev_t *)socketp->dev)->pid, 0);
811:
812: /* mark socket as closed */
813: if (socketp->flags & DDP_CALL_HANDLER)
814: socketp->sock_u.handler = NULL;
815: else
816: socketp->sock_u.gref = NULL;
817: socketp->flags = 0;
818:
819: if (((ddp_dev_t *)socketp->dev)->proto == DDP_ATP)
820: ot_atp_socketM[socket] = 0;
821: else if (((ddp_dev_t *)socketp->dev)->proto == DDP_ADSP)
822: ot_adsp_socketM[socket] = 0;
823:
824: dPrintf(D_M_DDP, D_L_VERBOSE,
825: ("Socket 0x%x is closed", (u_char)socket));
826:
827: return (0);
828: }
829:
830:
831: /* There are various ways a packet may go out.... it may be sent out
832: * directly to destination node, or sent to a random router or sent
833: * to a router whose entry exists in Best Router Cache. Following are
834: * constants used WITHIN this routine to keep track of choice of destination
835: */
836: #define DIRECT_ADDR 1
837: #define BRT_ENTRY 2
838: #define BRIDGE_ADDR 3
839:
840: /*
841: * ddp_output()
842: *
843: * Remarks :
844: * called to queue a atp/ddp data packet on the network interface.
845: * It returns 0 normally, and an errno in case of error.
846: *
847: */
848: int ddp_output(mp, src_socket, src_addr_included)
849: register gbuf_t **mp;
850: at_socket src_socket;
851: int src_addr_included;
852: {
853: register at_if_t *ifID, *ifIDTmp;
854: register at_ddp_t *ddp;
855: register ddp_brt_t *brt;
856: register at_net_al dst_net;
857: register int len;
858: struct atalk_addr at_dest;
859: at_if_t *ARouterIf = NULL;
860: at_ddp_short_t *ddp_short = NULL;
861: int loop = 0;
862: int error;
863: int addr_type;
864: void ddp_input();
865: u_char addr_flag, ddp_type;
866: char *addr = NULL;
867: register gbuf_t *m, *tmp_m;
868: at_ddp_t *tmp_ddp;
869:
870: snmpStats.dd_outReq++;
871: if ((ifID = ifID_table[IFID_HOME]) == NULL)
872: return (ENETDOWN);
873: m = *mp;
874: ddp = (at_ddp_t *)gbuf_rptr(m);
875: if (MULTIHOME_MODE && (ifIDTmp = forUs(ddp))) {
876: ifID = ifIDTmp;
877: loop = TRUE;
878: dPrintf(D_M_DDP_LOW, D_L_USR1,
879: ("ddp_out: for us if:%s\n", ifID->ifName));
880: }
881:
882: if ((ddp->dst_socket > (unsigned) (DDP_SOCKET_LAST + 1)) ||
883: (ddp->dst_socket < DDP_SOCKET_1st_RESERVED)) {
884: dPrintf(D_M_DDP, D_L_ERROR,
885: ("Illegal destination socket on outgoing packet (0x%x)",
886: ddp->dst_socket));
887: at_ddp_stats.xmit_bad_addr++;
888: return (ENOTSOCK);
889: }
890: if ((len = gbuf_msgsize(*mp)) > DDP_DATAGRAM_SIZE) {
891: /* the packet is too large */
892: dPrintf(D_M_DDP, D_L_ERROR,
893: ("Outgoing packet too long (len=%d bytes)", len));
894: at_ddp_stats.xmit_bad_length++;
895: return (EMSGSIZE);
896: }
897: at_ddp_stats.xmit_bytes += len;
898: at_ddp_stats.xmit_packets++;
899:
900: DDPLEN_ASSIGN(ddp, len);
901: ddp->hopcount = ddp->unused = 0;
902:
903: /* If this packet is for the same node, loop it back
904: * up... Note that for LocalTalk, dst_net zero means "THIS_NET", so
905: * address 0.nn is eligible for loopback. For Extended EtherTalk,
906: * dst_net 0 can be used only for cable-wide or zone-wide
907: * broadcasts (0.ff) and as such, address of the form 0.nn is NOT
908: * eligible for loopback.
909: */
910: dst_net = NET_VALUE(ddp->dst_net);
911:
912: /* If our packet is destined for the 'virtual' bridge
913: * address of NODE==0xFE, replace that address with a
914: * real bridge address.
915: */
916: if ((ddp->dst_node == 0xfe) &&
917: ((dst_net == 0) ||
918: (dst_net >= ifID->ifThisCableStart &&
919: dst_net <= ifID->ifThisCableEnd))) {
920: NET_NET(ddp->dst_net, ifID->ifARouter.atalk_net);
921: dst_net = NET_VALUE(ifID->ifARouter.atalk_net);
922: ddp->dst_node = ifID->ifARouter.atalk_node;
923: }
924: loop = ((ddp->dst_node == ifID->ifThisNode.atalk_node) &&
925: (dst_net == NET_VALUE(ifID->ifThisNode.atalk_net))
926: );
927:
928: if (loop) {
929: gbuf_t *mdata, *mdata_next;
930:
931: ddp_type = ddp->type;
932: ddp->src_node = ifID->ifThisNode.atalk_node;
933: ddp->src_socket = src_socket;
934: NET_NET(ddp->src_net, ifID->ifThisNode.atalk_net);
935:
936: dPrintf(D_M_DDP_LOW, D_L_OUTPUT,
937: ("ddp_output: loop to %d:%d port=%d\n",
938: NET_VALUE(ddp->src_net),
939: ddp->src_node,
940: ifID->ifPort));
941:
942: if (UAS_VALUE(ddp->checksum)) {
943: u_short tmp;
944: tmp = ddp_checksum(*mp, 4);
945: UAS_ASSIGN(ddp->checksum, tmp);
946: }
947: tmp_m = *mp;
948: for (tmp_m=gbuf_next(tmp_m); tmp_m; tmp_m=gbuf_next(tmp_m)) {
949: tmp_ddp = (at_ddp_t *)gbuf_rptr(tmp_m);
950: DDPLEN_ASSIGN(tmp_ddp, gbuf_msgsize(tmp_m));
951: tmp_ddp->hopcount = tmp_ddp->unused = 0;
952: tmp_ddp->src_node = ddp->src_node;
953: NET_NET(tmp_ddp->src_net, ddp->src_net);
954: if (UAS_VALUE(tmp_ddp->checksum)) {
955: u_short tmp;
956: tmp = ddp_checksum(tmp_m, 4);
957: UAS_ASSIGN(tmp_ddp->checksum, tmp);
958: }
959: }
960: dPrintf(D_M_DDP, D_L_VERBOSE,
961: ("Looping back a packet from socket 0x%x to socket 0x%x",
962: ddp->src_socket, ddp->dst_socket));
963:
964: for (mdata = *mp; mdata; mdata = mdata_next) {
965: mdata_next = gbuf_next(mdata);
966: gbuf_next(mdata) = 0;
967: ddp_input(mdata, ifID);
968: }
969: return (0);
970: }
971: if ((ddp->dst_socket == ZIP_SOCKET) &&
972: (zip_type_packet(*mp) == ZIP_GETMYZONE)) {
973: ddp->src_socket = src_socket;
974: if ((error = zip_handle_getmyzone(ifID, *mp)) != 0)
975: return(error);
976: gbuf_freem(*mp);
977: return (0);
978: }
979: /*
980: * find out the interface on which the packet should go out
981: */
982: for (ifID = at_ifQueueHd.FwdLink; ifID != &at_ifQueueHd; ifID = ifID->FwdLink) {
983:
984: if ((NET_VALUE(ifID->ifThisNode.atalk_net) == dst_net) || (dst_net == 0))
985: /* the message is either going out (i) on the same
986: * NETWORK in case of LocalTalk, or (ii) on the same
987: * CABLE in case of Extended AppleTalk (EtherTalk).
988: */
989: break;
990:
991: if ((ifID->ifThisCableStart <= dst_net) &&
992: (ifID->ifThisCableEnd >= dst_net)
993: )
994: /* We're on EtherTalk and the message is going out to
995: * some other network on the same cable.
996: */
997: break;
998:
999: if (ARouterIf == NULL && ATALK_VALUE(ifID->ifARouter))
1000: ARouterIf = ifID;
1001: }
1002: dPrintf(D_M_DDP_LOW, D_L_USR1,
1003: ("ddp_out: after search ifid:0x%x %s ifID0:0x%x\n",
1004: (u_int) ifID, ifID ? ifID->ifName : "",
1005: (u_int) ifID_table[0]));
1006:
1007: if (ifID != &at_ifQueueHd) {
1008: /* located the interface where the packet should
1009: * go.... the "first-hop" destination address
1010: * must be the same as real destination address.
1011: */
1012: addr_type = DIRECT_ADDR;
1013: } else {
1014: /* no, the destination network number does
1015: * not match known network numbers. If we have
1016: * heard from this network recently, BRT table
1017: * may have address of a router we could use!
1018: */
1019: if (!ROUTING_MODE && !MULTIHOME_MODE) {
1020:
1021: BRT_LOOK (brt, dst_net);
1022: if (brt) {
1023: /* Bingo... BRT has an entry for this network.
1024: * Use the link address as is.
1025: */
1026: dPrintf(D_M_DDP, D_L_VERBOSE,
1027: ("Found BRT entry to send to net 0x%x", dst_net));
1028: at_ddp_stats.xmit_BRT_used++;
1029: addr_type = BRT_ENTRY;
1030: ifID = brt->ifID;
1031: } else {
1032: /* No BRT entry available for dest network... do we
1033: * know of any router at all??
1034: */
1035: if ((ifID = ARouterIf) != NULL)
1036: addr_type = BRIDGE_ADDR;
1037: else {
1038: dPrintf(D_M_DDP, D_L_WARNING,
1039: ("Found no interface to send pkt"));
1040: at_ddp_stats.xmit_bad_addr++;
1041: return (ENETUNREACH);
1042: }
1043: }
1044: }
1045: else { /* We are in multiport mode, so we can bypass all the rest
1046: * and directly ask for the routing of the packet
1047: */
1048:
1049: ddp->src_socket = src_socket;
1050: at_ddp_stats.xmit_BRT_used++;
1051: if (!MULTIPORT_MODE || ifID == &at_ifQueueHd)
1052: ifID = ifID_table[IFID_HOME];
1053: if (!src_addr_included) {
1054: ddp->src_node = ifID->ifThisNode.atalk_node;
1055: NET_NET(ddp->src_net, ifID->ifThisNode.atalk_net);
1056: }
1057: routing_needed(*mp, ifID, TRUE);
1058: return (0);
1059: }
1060: }
1061: /* by the time we land here, we know the interface on
1062: * which this packet is going out.... ifID.
1063: */
1064:
1065: switch (addr_type) {
1066: case DIRECT_ADDR :
1067: at_dest.atalk_unused = 0;
1068: NET_ASSIGN(at_dest.atalk_net, dst_net);
1069: at_dest.atalk_node = ddp->dst_node;
1070: addr_flag = AT_ADDR;
1071: addr = (char *)&at_dest;
1072: break;
1073: case BRT_ENTRY :
1074: addr_flag = ET_ADDR;
1075: addr = (char *)&brt->et_addr;
1076: break;
1077: case BRIDGE_ADDR :
1078: at_dest = ifID->ifARouter;
1079: addr_flag = AT_ADDR;
1080: addr = (char *)&at_dest;
1081: break;
1082:
1083: }
1084: /* Irrespective of the interface on which
1085: * the packet is going out, we always put the
1086: * same source address on the packet (unless multihoming mode).
1087: */
1088: if (MULTIPORT_MODE) {
1089: if (!src_addr_included) {
1090: ddp->src_node = ifID->ifThisNode.atalk_node;
1091: NET_NET(ddp->src_net, ifID->ifThisNode.atalk_net);
1092: }
1093: }
1094: else {
1095: ddp->src_node = ifID_table[IFID_HOME]->ifThisNode.atalk_node;
1096: NET_NET(ddp->src_net, ifID_table[IFID_HOME]->ifThisNode.atalk_net);
1097: }
1098:
1099: ddp->src_socket = src_socket;
1100: if (UAS_VALUE(ddp->checksum)) {
1101: u_short tmp;
1102: tmp = ddp_checksum(*mp, 4);
1103: UAS_ASSIGN(ddp->checksum, tmp);
1104: }
1105:
1106: dPrintf(D_M_DDP, D_L_VERBOSE,
1107: ("Packet going out to : net 0x%x, node 0x%x, socket 0x%x on %s",
1108: (ddp_short ? 0 : dst_net),
1109: (ddp_short ? 0 : ddp->dst_node),
1110: (ddp_short ? ddp_short->dst_socket : ddp->dst_socket),ifID->ifName));
1111: dPrintf(D_M_DDP_LOW, D_L_OUTPUT,
1112: ("ddp_output: going out to %d:%d skt%d\n",
1113: dst_net, ddp->dst_node, ddp->dst_socket));
1114:
1115: if (ifID->ifState != LAP_OFFLINE) {
1116: tmp_m = *mp;
1117: for (tmp_m=gbuf_next(tmp_m); tmp_m; tmp_m=gbuf_next(tmp_m)) {
1118: tmp_ddp = (at_ddp_t *)gbuf_rptr(tmp_m);
1119: DDPLEN_ASSIGN(tmp_ddp, gbuf_msgsize(tmp_m));
1120: tmp_ddp->hopcount = tmp_ddp->unused = 0;
1121: tmp_ddp->src_node = ddp->src_node;
1122: NET_NET(tmp_ddp->src_net, ddp->src_net);
1123: tmp_ddp->dst_node = ddp->dst_node;
1124: NET_NET(tmp_ddp->dst_net, ddp->dst_net);
1125: if (UAS_VALUE(tmp_ddp->checksum)) {
1126: u_short tmp;
1127: tmp = ddp_checksum(tmp_m, 4);
1128: UAS_ASSIGN(tmp_ddp->checksum, tmp);
1129: }
1130: }
1131: {
1132: struct etalk_addr dest_addr;
1133: struct atalk_addr dest_at_addr;
1134: int loop = TRUE; /* flag to aarp to loopback (default) */
1135: elap_specifics_t *elapp = (elap_specifics_t *)ifID->ifLapp;
1136:
1137: m = *mp;
1138:
1139: /* the incoming frame is of the form {flag, address, ddp...}
1140: * where "flag" indicates whether the address is an 802.3
1141: * (link) address, or an appletalk address. If it's an
1142: * 802.3 address, the packet can just go out to the network
1143: * through PAT, if it's an appletalk address, AT->802.3 address
1144: * resolution needs to be done.
1145: * If 802.3 address is known, strip off the flag and 802.3
1146: * address, and prepend 802.2 and 802.3 headers.
1147: */
1148:
1149: if (addr == NULL) {
1150: addr_flag = *(u_char *)gbuf_rptr(m);
1151: gbuf_rinc(m,1);
1152: }
1153:
1154: switch (addr_flag) {
1155: case AT_ADDR_NO_LOOP :
1156: loop = FALSE;
1157: /* pass thru */
1158: case AT_ADDR :
1159: if (addr == NULL) {
1160: dest_at_addr = *(struct atalk_addr *)gbuf_rptr(m);
1161: gbuf_rinc(m,sizeof(struct atalk_addr));
1162: } else
1163: dest_at_addr = *(struct atalk_addr *)addr;
1164: break;
1165: case ET_ADDR :
1166: if (addr == NULL) {
1167: dest_addr = *(struct etalk_addr *)gbuf_rptr(m);
1168: gbuf_rinc(m,sizeof(struct etalk_addr));
1169: } else
1170: dest_addr = *(struct etalk_addr *)addr;
1171: break;
1172: default :
1173: dPrintf(D_M_DDP_LOW,D_L_ERROR,
1174: ("ddp_output: Unknown addr_flag = 0x%x\n", addr_flag));
1175: gbuf_freel(m); /* unknown address type, chuck it */
1176: return 0;
1177: }
1178:
1179: while (gbuf_len(m) == 0) {
1180: tmp_m = m;
1181: m = gbuf_cont(m);
1182: gbuf_freeb(tmp_m);
1183: }
1184:
1185: /* At this point, rptr points to ddp header for sure */
1186:
1187: if (elapp->elap_if.ifState == LAP_OFFLINE) {
1188: gbuf_freel(m);
1189: return 0;
1190: }
1191:
1192: if (elapp->elap_if.ifState == LAP_ONLINE_FOR_ZIP) {
1193: /* see if this is a ZIP packet that we need
1194: * to let through even though network is
1195: * not yet alive!!
1196: */
1197: if (zip_type_packet(m) == 0) {
1198: gbuf_freel(m);
1199: return 0;
1200: }
1201: }
1202:
1203: elapp->stats.xmit_packets++;
1204: elapp->stats.xmit_bytes += gbuf_msgsize(m);
1205: snmpStats.dd_outLong++;
1206:
1207: switch (addr_flag) {
1208: case AT_ADDR_NO_LOOP :
1209: case AT_ADDR :
1210: /*
1211: * we don't want elap to be looking into ddp header, so
1212: * it doesn't know net#, consequently can't do
1213: * AMT_LOOKUP. That task left to aarp now.
1214: */
1215: aarp_send_data(m,elapp,&dest_at_addr, loop);
1216: break;
1217: case ET_ADDR :
1218: pat_output(elapp->pat_id, m, &dest_addr, 0);
1219: break;
1220: }
1221: }
1222: return(0);
1223: }
1224: gbuf_freel(*mp);
1225: return (0);
1226: } /* ddp_output */
1227:
1228: void ddp_input(mp, ifID)
1229: register gbuf_t *mp;
1230: register at_if_t *ifID;
1231: {
1232: register at_ddp_t *ddp;
1233: register int msgsize;
1234: register at_socket socket;
1235: register int len;
1236: register at_net_al dst_net;
1237: extern volatile RoutingMix;
1238:
1239: KERNEL_DEBUG(DBG_AT_DDP_INPUT | DBG_FUNC_START, 0,0,0,0,0);
1240:
1241: /* Makes sure we know the default interface before starting to
1242: * accept incomming packets. If we don't we may end up with a
1243: * null ifID_table[0] and have impredicable results (specially
1244: * in router mode. This is a transitory state (because we can
1245: * begin to receive packet while we're not completly set up yet.
1246: */
1247:
1248: if (ifID_table[IFID_HOME] == (at_if_t *)NULL) {
1249: dPrintf(D_M_DDP, D_L_ERROR,
1250: ("dropped incoming packet ifID_home not set yet\n"));
1251: gbuf_freem(mp);
1252: goto out; /* return */
1253: }
1254:
1255: /*
1256: * if a DDP packet has been broadcast, we're going to get a copy of
1257: * it here; if it originated at user level via a write on a DDP
1258: * socket; when it gets here, the first block in the chain will be
1259: * empty since it only contained the lap level header which will be
1260: * stripped in the lap level immediately below ddp
1261: */
1262:
1263: if ((mp = (gbuf_t *)ddp_compress_msg(mp)) == NULL) {
1264: dPrintf(D_M_DDP, D_L_ERROR,
1265: ("dropped short incoming ET packet (len %d)", 0));
1266: snmpStats.dd_inTotal++;
1267: at_ddp_stats.rcv_bad_length++;
1268: goto out; /* return; */
1269: }
1270: msgsize = gbuf_msgsize(mp);
1271:
1272: at_ddp_stats.rcv_bytes += msgsize;
1273: at_ddp_stats.rcv_packets++;
1274:
1275: /* if the interface pointer is 0, the packet has been
1276: * looped back by 'write' half of DDP. It is of the
1277: * form {extended ddp,...}. The packet is meant to go
1278: * up to some socket on the same node.
1279: */
1280: if (ifID == (at_if_t *)NULL) /* if loop back is specified */
1281: ifID = ifID_table[IFID_HOME]; /* that means the home port */
1282:
1283: /* the incoming datagram has extended DDP header and is of
1284: * the form {ddp,...}.
1285: */
1286: if (msgsize < DDP_X_HDR_SIZE) {
1287: dPrintf(D_M_DDP, D_L_ERROR,
1288: ("dropped short incoming ET packet (len %d)",
1289: msgsize));
1290: at_ddp_stats.rcv_bad_length++;
1291: gbuf_freem(mp);
1292: goto out; /* return; */
1293: }
1294: /*
1295: * At this point, the message is always of the form
1296: * {extended ddp, ... }.
1297: */
1298: ddp = (at_ddp_t *)gbuf_rptr(mp);
1299: len = DDPLEN_VALUE(ddp);
1300:
1301: if (msgsize != len) {
1302: if ((unsigned) msgsize > len) {
1303: if (len < DDP_X_HDR_SIZE) {
1304: dPrintf(D_M_DDP, D_L_ERROR,
1305: ("Length problems, ddp length %d, buffer length %d",
1306: len, msgsize));
1307: snmpStats.dd_tooLong++;
1308: at_ddp_stats.rcv_bad_length++;
1309: gbuf_freem(mp);
1310: goto out; /* return; */
1311: }
1312: /*
1313: * shave off the extra bytes from the end of message
1314: */
1315: mp = ddp_adjmsg(mp, -(msgsize - len)) ? mp : 0;
1316: if (mp == 0)
1317: goto out; /* return; */
1318: } else {
1319: dPrintf(D_M_DDP, D_L_ERROR,
1320: ("Length problems, ddp length %d, buffer length %d",
1321: len, msgsize));
1322: snmpStats.dd_tooShort++;
1323: at_ddp_stats.rcv_bad_length++;
1324: gbuf_freem(mp);
1325: goto out; /* return; */
1326: }
1327: }
1328: socket = ddp->dst_socket;
1329:
1330: /*
1331: * We want everything in router mode, specially socket 254 for nbp so we need
1332: * to bypass this test when we are a router.
1333: */
1334:
1335: if (!ROUTING_MODE && (socket > DDP_SOCKET_LAST ||
1336: socket < DDP_SOCKET_1st_RESERVED)) {
1337: dPrintf(D_M_DDP, D_L_WARNING,
1338: ("Bad dst socket on incoming packet (0x%x)",
1339: ddp->dst_socket));
1340: at_ddp_stats.rcv_bad_socket++;
1341: gbuf_freem(mp);
1342: goto out; /* return; */
1343: }
1344: /*
1345: * if the checksum is true, then upstream wants us to calc
1346: */
1347: if (UAS_VALUE(ddp->checksum) &&
1348: (UAS_VALUE(ddp->checksum) != ddp_checksum(mp, 4))) {
1349: dPrintf(D_M_DDP, D_L_WARNING,
1350: ("Checksum error on incoming pkt, calc 0x%x, exp 0x%x",
1351: ddp_checksum(mp, 4), UAS_VALUE(ddp->checksum)));
1352: snmpStats.dd_checkSum++;
1353: at_ddp_stats.rcv_bad_checksum++;
1354: gbuf_freem(mp);
1355: goto out; /* return; */
1356: }
1357:
1358: /*############### routing input checking */
1359:
1360: /* Router mode special: we send "up-stack" packets for this node or coming from any
1361: * other ports, but for the reserved atalk sockets (RTMP, ZIP, NBP [and EP])
1362: * BTW, the way we know it's for the router and not the home port is that the
1363: * MAC (ethernet) address is always the one of the interface we're on, but
1364: * the AppleTalk address must be the one of the home port. If it's a multicast
1365: * or another AppleTalk address, this is the router job's to figure out where it's
1366: * going to go.
1367: */
1368: dst_net = NET_VALUE(ddp->dst_net);
1369: if (((ddp->dst_node == ifID_table[IFID_HOME]->ifThisNode.atalk_node) &&
1370: (dst_net == NET_VALUE(ifID_table[IFID_HOME]->ifThisNode.atalk_net))) ||
1371: ((ddp->dst_node == 255) &&
1372: (((dst_net >= ifID_table[IFID_HOME]->ifThisCableStart) &&
1373: (dst_net <= ifID_table[IFID_HOME]->ifThisCableEnd)) || dst_net == 0)) ||
1374: (socket == RTMP_SOCKET) || (socket == NBP_SOCKET) || (socket == EP_SOCKET) ||
1375: (socket == ZIP_SOCKET) || (ifID->ifRoutingState < PORT_ONLINE) ||
1376: ( MULTIPORT_MODE && forUs(ddp))
1377: )
1378: {
1379:
1380: gref_t *gref;
1381: extern ddp_dev_t ddp_devs[];
1382: pktsHome++;
1383: snmpStats.dd_inLocal++;
1384: if (ot_protoT[ddp->type]) {
1385: if (ddp->type == DDP_ATP) {
1386: if ((socket == ZIP_SOCKET) || (atp_inputQ[socket] == NULL)
1387: || (atp_inputQ[socket] == (gref_t *)1))
1388: goto l_continue;
1389: atp_input(mp);
1390: } else if (ddp->type == DDP_ADSP) {
1391: if (adsp_inputQ[socket] == NULL)
1392: goto l_continue;
1393: adsp_input(mp);
1394: }
1395: goto out; /* return; */
1396: }
1397: /*
1398: * Assure that this isn't for a shut-down socket
1399: */
1400: l_continue:
1401: if ((ddp_devs[socket].flags&DDPF_SHUTDOWN) == 0 &&
1402: (gref = DDP_SOCK_UPQ(socket)) != NULL) {
1403: /* there is an upstream! either a queue or a handler routine */
1404: if (ddp_socket[socket].flags & DDP_CALL_HANDLER) {
1405: dPrintf(D_M_DDP,D_L_INPUT,
1406: ("ddp_input: skt hndlr skt %d hdnlr:0x%x\n",
1407: (u_int) socket,
1408: DDP_SOCK_HANDLER(socket)));
1409: (*DDP_SOCK_HANDLER(socket))(mp, ifID);
1410: } else {
1411: dPrintf(D_M_DDP, D_L_INPUT,
1412: ("ddp_input: streamq, skt %d\n", socket));
1413:
1414: if (DDP_FLAGS(gref) & DDPF_SI) {
1415: if (si_ddp_input(gref, mp)) {
1416: at_ddp_stats.rcv_dropped_nobuf++;
1417: }
1418: } else
1419: atalk_putnext(gref, mp);
1420: }
1421: } else {
1422: dPrintf(D_M_DDP, D_L_VERBOSE,
1423: ("Dropping a packet -- dest socket closed"));
1424: at_ddp_stats.rcv_bad_socket++;
1425: gbuf_freem(mp);
1426: snmpStats.dd_noHandler++;
1427: dPrintf(D_M_DDP, D_L_WARNING,
1428: ("ddp_input: dropped, hndlr socket %d unknown\n", socket));
1429: }
1430: }
1431:
1432: else {
1433: dPrintf(D_M_DDP, D_L_ROUTING, ("ddp_input: routing_needed from port=%d sock=%d\n",
1434: ifID->ifPort, ddp->dst_socket));
1435:
1436: snmpStats.dd_fwdReq++;
1437: if (((pktsIn-pktsHome+200) >= RoutingMix) && ((++pktsDropped % 5) == 0)) {
1438: at_ddp_stats.rcv_dropped_nobuf++;
1439: gbuf_freem(mp);
1440: }
1441: else {
1442: routing_needed(mp, ifID, FALSE);
1443: }
1444: }
1445: out:
1446: KERNEL_DEBUG(DBG_AT_DDP_INPUT | DBG_FUNC_END, 0,0,0,0,0);
1447: }
1448:
1449:
1450: /*
1451: * ddp_router_output()
1452: *
1453: * Remarks :
1454: * This is a modified version of ddp_output for router use.
1455: * The main difference is that the interface on which the packet needs
1456: * to be sent is specified and a *destination* AppleTalk address is passed
1457: * as an argument, this address may or may not be the same as the destination
1458: * address found in the ddp packet... This is the trick about routing, the
1459: * AppleTalk destination of the packet may not be the same as the Enet address
1460: * we send the packet too (ie, we may pass the baby to another router).
1461: *
1462: */
1463: int ddp_router_output(mp, ifID, addr_type, router_net, router_node, enet_addr)
1464: gbuf_t *mp;
1465: at_if_t *ifID;
1466: int addr_type;
1467: at_net_al router_net;
1468: at_node router_node;
1469: etalk_addr_t *enet_addr;
1470: {
1471: register at_ddp_t *ddp;
1472: struct atalk_addr at_dest;
1473: void ddp_input();
1474: int addr_flag;
1475: char *addr = NULL;
1476: register gbuf_t *m, *tmp_m;
1477: at_ddp_t *tmp_ddp;
1478:
1479: if (!ifID || ! IFID_VALID(ifID)) {
1480:
1481: dPrintf(D_M_DDP, D_L_WARNING, ("BAD BAD ifID\n"));
1482: gbuf_freel(mp);
1483: return(EPROTOTYPE);
1484: }
1485: ddp = (at_ddp_t *)gbuf_rptr(mp);
1486:
1487: if (ifID->ifFlags & AT_IFF_AURP) { /* AURP link? */
1488: if (ddp_AURPsendx) {
1489: for (tmp_m=gbuf_next(mp); tmp_m; tmp_m=gbuf_next(tmp_m)) {
1490: tmp_ddp = (at_ddp_t *)gbuf_rptr(tmp_m);
1491: DDPLEN_ASSIGN(tmp_ddp, gbuf_msgsize(tmp_m));
1492: tmp_ddp->hopcount = tmp_ddp->unused = 0;
1493: tmp_ddp->src_node = ddp->src_node;
1494: NET_NET(tmp_ddp->src_net, ddp->src_net);
1495: tmp_ddp->dst_node = ddp->dst_node;
1496: NET_NET(tmp_ddp->dst_net, ddp->dst_net);
1497: if (UAS_VALUE(tmp_ddp->checksum)) {
1498: u_short tmp;
1499: tmp = ddp_checksum(tmp_m, 4);
1500: UAS_ASSIGN(tmp_ddp->checksum, tmp);
1501: }
1502: }
1503: if (router_node == 255)
1504: router_node = 0;
1505: ddp_AURPsendx(AURPCODE_DATAPKT, mp, router_node);
1506: return 0;
1507: } else {
1508: gbuf_freel(mp);
1509: return EPROTOTYPE;
1510: }
1511: }
1512:
1513: /* keep some of the tests for now ####### */
1514:
1515: if (gbuf_msgsize(mp) > DDP_DATAGRAM_SIZE) {
1516: /* the packet is too large */
1517: dPrintf(D_M_DDP, D_L_WARNING,
1518: ("ddp_router_output: Packet too large size=%d\n",
1519: gbuf_msgsize(mp)));
1520: gbuf_freel(mp);
1521: return (EMSGSIZE);
1522: }
1523:
1524: switch (addr_type) {
1525:
1526: case AT_ADDR :
1527:
1528: /*
1529: * Check for packet destined to the home stack
1530: */
1531:
1532: if ((ddp->dst_node == ifID->ifThisNode.atalk_node) &&
1533: (NET_VALUE(ddp->dst_net) == NET_VALUE(ifID->ifThisNode.atalk_net))) {
1534: dPrintf(D_M_DDP_LOW, D_L_ROUTING,
1535: ("ddp_r_output: sending back home from port=%d socket=%d\n",
1536: ifID->ifPort, ddp->dst_socket));
1537:
1538: UAS_ASSIGN(ddp->checksum, 0);
1539: ddp_input(mp, ifID);
1540: return(0);
1541: }
1542:
1543: NET_ASSIGN(at_dest.atalk_net, router_net);
1544: at_dest.atalk_node = router_node;
1545:
1546: addr_flag = AT_ADDR_NO_LOOP;
1547: addr = (char *)&at_dest;
1548: dPrintf(D_M_DDP_LOW, D_L_ROUTING_AT,
1549: ("ddp_r_output: AT_ADDR out port=%d net %d:%d via rte %d:%d",
1550: ifID->ifPort, NET_VALUE(ddp->dst_net), ddp->dst_node, router_net,
1551: router_node));
1552: break;
1553:
1554: case ET_ADDR :
1555: addr_flag = ET_ADDR;
1556: addr = (char *)enet_addr;
1557: dPrintf(D_M_DDP_LOW, D_L_ROUTING,
1558: ("ddp_r_output: ET_ADDR out port=%d net %d:%d\n",
1559: ifID->ifPort, NET_VALUE(ddp->dst_net), ddp->dst_node));
1560: break;
1561: }
1562:
1563: if (UAS_VALUE(ddp->checksum)) {
1564: u_short tmp;
1565: tmp = ddp_checksum(mp, 4);
1566: UAS_ASSIGN(ddp->checksum, tmp);
1567: }
1568:
1569:
1570: if (ifID->ifState != LAP_OFFLINE) {
1571: for (tmp_m=gbuf_next(mp); tmp_m; tmp_m=gbuf_next(tmp_m)) {
1572: tmp_ddp = (at_ddp_t *)gbuf_rptr(tmp_m);
1573: DDPLEN_ASSIGN(tmp_ddp, gbuf_msgsize(tmp_m));
1574: tmp_ddp->hopcount = tmp_ddp->unused = 0;
1575: tmp_ddp->src_node = ddp->src_node;
1576: NET_NET(tmp_ddp->src_net, ddp->src_net);
1577: tmp_ddp->dst_node = ddp->dst_node;
1578: NET_NET(tmp_ddp->dst_net, ddp->dst_net);
1579: if (UAS_VALUE(tmp_ddp->checksum)) {
1580: u_short tmp;
1581: tmp = ddp_checksum(tmp_m, 4);
1582: UAS_ASSIGN(tmp_ddp->checksum, tmp);
1583: }
1584: }
1585: {
1586: struct etalk_addr dest_addr;
1587: struct atalk_addr dest_at_addr;
1588: int loop = TRUE; /* flag to aarp to loopback (default) */
1589: elap_specifics_t *elapp = (elap_specifics_t *)ifID->ifLapp;
1590:
1591: m = mp;
1592:
1593: /* the incoming frame is of the form {flag, address, ddp...}
1594: * where "flag" indicates whether the address is an 802.3
1595: * (link) address, or an appletalk address. If it's an
1596: * 802.3 address, the packet can just go out to the network
1597: * through PAT, if it's an appletalk address, AT->802.3 address
1598: * resolution needs to be done.
1599: * If 802.3 address is known, strip off the flag and 802.3
1600: * address, and prepend 802.2 and 802.3 headers.
1601: */
1602:
1603: if (addr == NULL) {
1604: addr_flag = *(u_char *)gbuf_rptr(m);
1605: gbuf_rinc(m,1);
1606: }
1607:
1608: switch (addr_flag) {
1609: case AT_ADDR_NO_LOOP :
1610: loop = FALSE;
1611: /* pass thru */
1612: case AT_ADDR :
1613: if (addr == NULL) {
1614: dest_at_addr = *(struct atalk_addr *)gbuf_rptr(m);
1615: gbuf_rinc(m,sizeof(struct atalk_addr));
1616: } else
1617: dest_at_addr = *(struct atalk_addr *)addr;
1618: break;
1619: case ET_ADDR :
1620: if (addr == NULL) {
1621: dest_addr = *(struct etalk_addr *)gbuf_rptr(m);
1622: gbuf_rinc(m,sizeof(struct etalk_addr));
1623: } else
1624: dest_addr = *(struct etalk_addr *)addr;
1625: break;
1626: default :
1627: dPrintf(D_M_DDP_LOW,D_L_ERROR,
1628: ("ddp_output: Unknown addr_flag = 0x%x\n", addr_flag));
1629:
1630: gbuf_freel(m); /* unknown address type, chuck it */
1631: return 0;
1632: }
1633:
1634: while (gbuf_len(m) == 0) {
1635: tmp_m = m;
1636: m = gbuf_cont(m);
1637: gbuf_freeb(tmp_m);
1638: }
1639:
1640: /* At this point, rptr points to ddp header for sure */
1641:
1642: if (elapp->elap_if.ifState == LAP_OFFLINE) {
1643: gbuf_freel(m);
1644: return 0;
1645: }
1646:
1647: if (elapp->elap_if.ifState == LAP_ONLINE_FOR_ZIP) {
1648: /* see if this is a ZIP packet that we need
1649: * to let through even though network is
1650: * not yet alive!!
1651: */
1652: if (zip_type_packet(m) == 0) {
1653: gbuf_freel(m);
1654: return 0;
1655: }
1656: }
1657:
1658: elapp->stats.xmit_packets++;
1659: elapp->stats.xmit_bytes += gbuf_msgsize(m);
1660: snmpStats.dd_outLong++;
1661:
1662: switch (addr_flag) {
1663: case AT_ADDR_NO_LOOP :
1664: case AT_ADDR :
1665: /*
1666: * we don't want elap to be looking into ddp header, so
1667: * it doesn't know net#, consequently can't do
1668: * AMT_LOOKUP. That task left to aarp now.
1669: */
1670: aarp_send_data(m,elapp,&dest_at_addr, loop);
1671: break;
1672: case ET_ADDR :
1673: pat_output(elapp->pat_id, m, &dest_addr, 0);
1674: break;
1675: }
1676: }
1677: return(0);
1678: }
1679: gbuf_freel(mp);
1680: return (0);
1681: }
1682:
1683: int gbuf_freel(m)
1684: gbuf_t *m;
1685: {
1686: gbuf_t *tmp_m;
1687:
1688: while ((tmp_m = m) != 0) {
1689: m = gbuf_next(m);
1690: gbuf_next(tmp_m) = 0;
1691: gbuf_freem(tmp_m);
1692: }
1693: return (0);
1694: }
1695:
1696: /*****************************************/
1697:
1698: void rt_delete(NetStop, NetStart)
1699: unsigned short NetStop;
1700: unsigned short NetStart;
1701: {
1702: RT_entry *found;
1703: int s;
1704:
1705: ATDISABLE(s, ddpinp_lock);
1706: if ((found = rt_bdelete(NetStop, NetStart)) != 0) {
1707: bzero(found, sizeof(RT_entry));
1708: found->right = RT_table_freelist;
1709: RT_table_freelist = found;
1710: }
1711: ATENABLE(s, ddpinp_lock);
1712: }
1713:
1714: int ddp_AURPfuncx(code, param, node)
1715: int code;
1716: void *param;
1717: unsigned char node;
1718: {
1719: extern void zt_add_zonename();
1720: extern void zt_set_zmap();
1721: extern int zt_ent_zindex();
1722: extern void zt_remove_zones();
1723: extern void rtmp_timeout();
1724: extern void rtmp_send_port();
1725: extern elap_specifics_t elap_specifics[];
1726: aurp_rtinfo_t rtinfo;
1727: elap_specifics_t *elapp;
1728: int k;
1729:
1730: switch (code) {
1731: case AURPCODE_DATAPKT: /* data packet */
1732: if (aurp_ifID) {
1733: dPrintf(D_M_DDP, D_L_TRACE, ("ddp_AURPfuncx: data, 0x%x, %d\n",
1734: (u_int) aurp_ifID, node));
1735:
1736: ddp_input((gbuf_t *)param, aurp_ifID);
1737: } else
1738: gbuf_freem((gbuf_t *)param);
1739: break;
1740:
1741: case AURPCODE_REG: /* register/deregister */
1742: if (!ROUTING_MODE)
1743: return -1;
1744: ddp_AURPsendx = (void(*)())param;
1745:
1746: if (param) {
1747: /* register AURP callback function */
1748: if (aurp_ifID)
1749: return 0;
1750: elapp = (elap_specifics_t *)&elap_specifics[1];
1751: for (k=1; k < IF_TOTAL_MAX; k++, elapp++) {
1752: if (elapp->pat_id == 0) {
1753: /* assign a port */
1754: elapp->pat_id = k;
1755: aurp_ifID = (at_if_t *)&elapp->elap_if;
1756: aurp_ifID->ifFlags = (AT_IFF_ETHERTALK|RTR_XNET_PORT);
1757: ddp_add_if(aurp_ifID);
1758: aurp_ifID->ifLapp = (void *)elapp;
1759: aurp_ifID->ifState = LAP_ONLINE;
1760: aurp_ifID->ifRoutingState = PORT_ONLINE;
1761: dPrintf(D_M_DDP, D_L_TRACE,
1762: ("ddp_AURPfuncx: on, 0x%x\n",
1763: (u_int) aurp_ifID));
1764:
1765: ddp_AURPsendx(AURPCODE_DEBUGINFO,
1766: &dbgBits, aurp_ifID->ifPort);
1767: return 0;
1768: }
1769: }
1770: return -1;
1771:
1772: } else {
1773: /* deregister AURP callback function */
1774: if (aurp_ifID) {
1775: rtmp_purge(aurp_ifID);
1776: elapp = (elap_specifics_t *)aurp_ifID->ifLapp;
1777: ddp_rem_if(aurp_ifID);
1778: elapp->pat_id = 0;
1779: aurp_ifID->ifLapp = (void *)0;
1780: aurp_ifID->ifState = LAP_OFFLINE;
1781: aurp_ifID->ifRoutingState = PORT_OFFLINE;
1782: dPrintf(D_M_DDP, D_L_TRACE,
1783: ("ddp_AURPfuncx: off, 0x%x\n", (u_int) aurp_ifID));
1784: aurp_ifID = 0;
1785: }
1786: }
1787: break;
1788:
1789: case AURPCODE_AURPPROTO: /* proto type - AURP */
1790: if (aurp_ifID) {
1791: aurp_ifID->ifFlags |= AT_IFF_AURP;
1792: rtinfo.RT_table = (void *)RT_table;
1793: rtinfo.ZT_table = (void *)ZT_table;
1794: rtinfo.RT_maxentry = RT_MAXENTRY;
1795: rtinfo.ZT_maxentry = ZT_MAXENTRY;
1796: rtinfo.rt_lock = (void *)&ddpinp_lock;
1797: rtinfo.rt_insert = (void *)rt_insert;
1798: rtinfo.rt_delete = (void *)rt_delete;
1799: rtinfo.rt_lookup = (void *)rt_blookup;
1800: rtinfo.zt_add_zname = (void *)zt_add_zonename;
1801: rtinfo.zt_set_zmap = (void *)zt_set_zmap;
1802: rtinfo.zt_get_zindex = (void *)zt_ent_zindex;
1803: rtinfo.zt_remove_zones = (void *)zt_remove_zones;
1804: ddp_AURPsendx(AURPCODE_RTINFO, &rtinfo, 0);
1805: }
1806: break;
1807: }
1808:
1809: return 0;
1810: }
1811:
1812:
1813: at_if_t *forUs(ddp)
1814: register at_ddp_t *ddp;
1815:
1816: /* checks to see if address of packet is for one of our interfaces
1817: returns *ifID if it's for us, NULL if not
1818: */
1819: {
1820: register at_if_t **ifID = &ifID_table[0];
1821: int port;
1822:
1823: for (port=0; *ifID && port<IF_TOTAL_MAX; ifID++,port++) {
1824: if ((ddp->dst_node == (*ifID)->ifThisNode.atalk_node) &&
1825: (NET_EQUAL(ddp->dst_net, (*ifID)->ifThisNode.atalk_net))
1826: ) {
1827: dPrintf(D_M_DDP_LOW, D_L_ROUTING,
1828: ("pkt was for port %d\n", port));
1829:
1830: return(*ifID);
1831: }
1832: }
1833: return((at_if_t *)NULL);
1834: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.