|
|
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) 1988, 1989, 1997, 1998 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: #include <sysglue.h>
38:
39: /* reaching for DDP and NBP headers in the datagram */
40: #define DATA_DDP(mp) ((at_ddp_t *)(gbuf_rptr(mp)))
41: #define DATA_NBP(mp) ((at_nbp_t *)((DATA_DDP(mp))->data))
42:
43: /* Get to the nve_entry_t part ofthe buffer */
44: #define NVE_ENTRY(mp) (nve_entry_t *)(gbuf_rptr(mp))
45:
46: #include <string.h>
47: #include <at/appletalk.h>
48: #include <at/ddp.h>
49: #include <at/nbp.h>
50: #include <at/zip.h>
51: #include <rtmp.h>
52: #include <lap.h>
53: #include <at/elap.h> /* router */
54: #include <at/at_lap.h>
55: #include <routing_tables.h> /* router */
56: #include <at_elap.h> /* router */
57: #include <at_ddp.h> /* for FROM_US */
58: #include <at_snmp.h>
59:
60: #ifndef MIN
61: #define MIN(a,b) ((a)>(b)?(b):(a))
62: #endif
63:
64: #include "nbp.h"
65:
66: #define errno nbperrno
67: #define NBP_DEBUG 0
68:
69: /* externs */
70: extern at_state_t at_state, *at_statep;
71: extern at_if_t *ifID_table[];
72:
73:
74: /* statics */
75: static nve_entry_t name_registry = {&name_registry, &name_registry};
76: static at_nvestr_t this_zone;
77: static int Extended_net;
78: static int errno;
79: static gbuf_t *lzones=0; /* head of local zones list */
80: static int lzonecnt=0; /* # zones stored in lzones */
81: static u_int hzonehash=0; /* hash val of home zone */
82: atlock_t nve_lock;
83: static int nve_lock_pri;
84:
85: static int nbp_lkup_reply(nbp_req_t *, nve_entry_t *);
86: static int nbp_strcmp(at_nvestr_t *, at_nvestr_t *, u_char);
87: static int nbp_setup_resp(nbp_req_t *, int);
88: static int nbp_send_resp(nbp_req_t *);
89: static int nbp_insert_entry(nve_entry_t *);
90: static int nbp_enum_gen(nve_entry_t *);
91:
92: /* macros */
93: #define NBP2ENTITY(nbp) &nbp->tuple[0].en_u.en_se.entity
94: #define NVE_LOCK nve_lock
95:
96: /* prototypes */
97: at_nvestr_t *getRTRLocalZone(if_zone_t *);
98: at_nvestr_t *getSPLocalZone(int);
99: at_nvestr_t *getLocalZone(int);
100: int nbp_add_multicast( at_nvestr_t *, at_if_t *);
101: int isZoneLocal(at_nvestr_t *);
102: u_int nbp_strhash (at_nvestr_t *);
103:
104: int sethzonehash(elapp)
105: elap_specifics_t *elapp;
106: {
107: if (elapp->cfg.zonename.len) {
108: hzonehash = nbp_strhash(&elapp->cfg.zonename);
109: }
110: }
111:
112:
113: int nbp_init ()
114: {
115: void nbp_input();
116: at_ddp_cfg_t ddp_cfg;
117:
118: /* Initialize Extended_net */
119: ddp_get_cfg (&ddp_cfg, 0);
120: if (ddp_cfg.flags & AT_IFF_LOCALTALK)
121: Extended_net = 0;
122: else
123: Extended_net = 1;
124:
125: ATLOCKINIT(nve_lock);
126: return ((int)nbp_input);
127: }
128:
129: void nbp_shutdown()
130: {
131: /* delete all NVE's and release buffers */
132: register nve_entry_t *nve_entry, *next_nve;
133: extern void nbp_delete_entry();
134:
135: ATDISABLE(nve_lock_pri,NVE_LOCK);
136: for (nve_entry = name_registry.fwd, next_nve = nve_entry->fwd;
137: nve_entry != &name_registry;
138: nve_entry = next_nve, next_nve = nve_entry->fwd) {
139: nbp_delete_entry(nve_entry);
140: }
141: ATENABLE(nve_lock_pri,NVE_LOCK);
142:
143: if (lzones) {
144: gbuf_freem(lzones);
145: lzones = NULL;
146: }
147: } /* nbp_shutdown */
148:
149: void nbp_input (m, ifID)
150: register gbuf_t *m;
151: register at_if_t *ifID;
152: {
153: void zip_handler(), nbp_handler(), rtmp_handler();
154:
155: switch (gbuf_type(m)) {
156:
157: /* *** fix this later: this code may no longer be needed *** */
158: case MSG_ERROR :
159: if (*gbuf_rptr(m) == ESHUTDOWN) {
160: /* DDP shutting down, clean up the name registry */
161: nbp_shutdown();
162: }
163: break;
164: /* *** end code that may no longer be needed *** */
165:
166: case MSG_DATA :
167: switch (((at_ddp_t *)(DATA_DDP(m)))->type) {
168: case NBP_DDP_TYPE :
169: nbp_handler (m, ifID);
170: return;
171: case ZIP_DDP_TYPE :
172: dPrintf(D_M_NBP_LOW, D_L_WARNING,
173: ("nbp_input: calling zip_handler\n"));
174: zip_handler (m);
175: break;
176: case RTMP_DDP_TYPE : /* applicable only in case of LocalTalk */
177: dPrintf(D_M_NBP_LOW,D_L_WARNING,
178: ("nbp_input: calling rtmp_handler\n"));
179: rtmp_handler (m);
180: break;
181: }
182: break;
183: default :
184: dPrintf(D_M_NBP, D_L_WARNING,
185: ("nbp_input: default_handler type=%d\n", gbuf_type(m)));
186: break;
187: }
188: gbuf_freem(m);
189: }
190:
191: static
192: u_char *nbp2zone(nbp, maxp)
193: at_nbp_t *nbp;
194: u_char *maxp;
195: {
196:
197: u_char *p;
198:
199: p = (u_char*)NBP2ENTITY(nbp); /* p -> object */
200: if (p >= maxp) return NULL;
201: p += (*p +1); /* p -> type */
202: if (p >= maxp) return NULL;
203: p += (*p +1); /* p -> zone */
204: if (p >= maxp) return NULL;
205: if ((p + *p) >= maxp) return NULL;
206: return(p);
207: }
208:
209: static void nbp_handler (m, ifID)
210: register gbuf_t *m;
211: register at_if_t *ifID;
212:
213: {
214: register at_nbp_t *nbp = DATA_NBP(m);
215: register nve_entry_t *nve_entry, *next_nve;
216: register RT_entry *rt;
217: register int ddpSent = FALSE; /* true if we re-sent this pkt (don't free) */
218: struct etalk_addr mcastAddr;
219: nbp_req_t nbp_req;
220: nve_entry_t *nbp_search_nve();
221: void nbp_delete_entry();
222: at_ddp_t *ddp;
223: u_char *p;
224:
225: /* Some initializations */
226: nbp_req.response = NULL;
227: nbp_req.request = m;
228: nbp_req.space_unused = nbp_req.flags = 0;
229:
230:
231: dPrintf(D_M_NBP_LOW, D_L_USR1,
232: ("nbp_handler control:%d tuplecount:%d id:%d\n",
233: nbp->control, nbp->tuple_count, nbp->at_nbp_id));
234: switch (nbp->control) {
235: case NBP_LKUP :
236: {
237: at_net_al dst_net;
238: ddp = DATA_DDP(m);
239: dst_net = NET_VALUE(ddp->dst_net);
240: dPrintf(D_M_NBP_LOW, D_L_USR2, (" LKUP %s\n",
241: ifID != ifID_table[0] ? "non-home" : "home"));
242: if ( ROUTING_MODE && (NET_VALUE(ddp->dst_net) != 0)
243: && ((dst_net < ifID->ifThisCableStart)
244: || (dst_net > ifID->ifThisCableEnd)) ) {
245: routing_needed(m, ifID, TRUE);
246: ddpSent = TRUE;
247: break;
248: }
249: }
250:
251: if (nbp_validate_n_hash (&nbp_req, TRUE, FALSE) == 0) {
252: nbp_req.func = nbp_lkup_reply;
253: (void) nbp_search_nve(&nbp_req, ifID);
254: if (nbp_req.response) {
255: nbp_send_resp(&nbp_req);
256: }
257: }
258: #ifdef NBP_DEBUG
259: {
260: char zone[35],object[35],type[35];
261: strncpy(zone,nbp_req.nve.zone.str, nbp_req.nve.zone.len);
262: strncpy(object,nbp_req.nve.object.str, nbp_req.nve.object.len);
263: strncpy(type,nbp_req.nve.type.str, nbp_req.nve.type.len);
264: object[nbp_req.nve.object.len] = '\0';
265: zone[nbp_req.nve.zone.len] = '\0';
266: type[nbp_req.nve.type.len] = '\0';
267: if (ifID != ifID_table[0])
268: dPrintf(D_M_NBP_LOW,D_L_USR2,
269: ("nbp_LKUP for:%s:%s@%s", object, type, zone));
270: }
271: #endif /* NBP_DEBUG */
272:
273: break;
274: case NBP_REGISTER :
275: /* Whatever the outcome of this operation, we need to return
276: * a response to the requester; so set up the response buffers
277: */
278: #ifdef NBP_DEBUG
279: {
280: at_net_al dst_net,src_net;
281: int src_node, dst_node, src_skt, dst_skt;
282: ddp = DATA_DDP(m);
283: dst_net = NET_VALUE(ddp->dst_net);
284: src_net = NET_VALUE(ddp->src_net);
285: src_node = ddp->src_node;
286: dst_node = ddp->dst_node;
287: src_skt = ddp->src_socket;
288: dst_skt = ddp->dst_socket;
289: dPrintf(D_M_NBP_LOW,D_L_USR2,
290: ("nbp reg ddp src:%d.%d.%d ",src_net,src_node,src_skt));
291: dPrintf(D_M_NBP_LOW,D_L_USR2,
292: ("dst: %d.%d.%d\n",dst_net,dst_node,dst_skt));
293: }
294: #endif /* NBP_DEBUG */
295: (void) nbp_setup_resp(&nbp_req, 0);
296: if (nbp_validate_n_hash (&nbp_req, FALSE, TRUE) != 0) {
297: /* bad tuple... send an error message */
298: goto bad;
299: }
300:
301:
302:
303: nbp_req.func = NULL;
304: if ((nve_entry = nbp_search_nve(&nbp_req, NULL)) != NULL) {
305: /* We have an entry for the same name in the registry.
306: * This is either a duplicate request (client
307: * retransmission) or another request. If this is a
308: * retransmitted request (ie it's for the same socket),
309: * then return ok; else return error.
310: */
311: if (*(int *)&nve_entry->address ==
312: *(int *)&nbp_req.nve.address) {
313: /* Send ok response */
314: DATA_NBP(nbp_req.response)->tuple_count = 0;
315: nbp_send_resp(&nbp_req);
316: break;
317: } else {
318: errno = EADDRNOTAVAIL;
319: goto bad;
320: }
321: } else {
322: /* Normal case; no tuple found for this name, so insert
323: * this tuple in the registry and return ok response.
324: */
325: #ifdef NBP_DEBUG
326: {
327: char str[35];
328: char object[35];
329: strncpy(str,nbp_req.nve.zone.str,nbp_req.nve.zone.len);
330: str[nbp_req.nve.zone.len] = '\0';
331: strncpy(object,nbp_req.nve.object.str,nbp_req.nve.object.len);
332: object[nbp_req.nve.object.len] = '\0';
333: dPrintf(D_M_NBP_LOW, D_L_USR4,
334: ("nbp_register for zone %s (len:%d) obj:%s (len:%d)\n",
335: str, nbp_req.nve.zone.len, object,
336: nbp_req.nve.object.len));
337: }
338: #endif /* NBP_DEBUG */
339:
340: if ((nbp_enum_gen(&nbp_req.nve) != 0) ||
341: nbp_insert_entry(&nbp_req.nve) != 0)
342: goto bad;
343: else {
344: /* Send okay response */
345: DATA_NBP(nbp_req.response)->tuple_count = 0;
346: nbp_send_resp(&nbp_req);
347: break;
348: }
349: }
350: bad:
351: DATA_NBP(nbp_req.response)->tuple_count = errno;
352: nbp_send_resp(&nbp_req);
353: break;
354: case NBP_DELETE :
355: /* Whatever the outcome of this operation, we need to return
356: * a response to the requester; so set up the response buffers
357: */
358: (void) nbp_setup_resp(&nbp_req, 0);
359: if (nbp_validate_n_hash (&nbp_req, FALSE, TRUE) != 0) {
360: /* bad tuple... send an error message */
361: DATA_NBP(nbp_req.response)->tuple_count = errno;
362: nbp_send_resp(&nbp_req);
363: break;
364: }
365:
366: nbp_req.func = NULL;
367: if (MULTIHOME_MODE &&
368: nbp_req.nve.zone.len == 1 &&
369: nbp_req.nve.zone.str[0] == '*'
370: ) { /* if mhome & *, remove nve from all default zones */
371:
372: int found = FALSE; /* if any found & deleted */
373: at_if_t **ifID;
374:
375: for (ifID=ifID_table; *ifID; ifID++) {
376: nbp_req.nve.zone = (*ifID)->ifZoneName;
377: if ((nve_entry = nbp_search_nve(&nbp_req, NULL)) == NULL)
378: continue;
379: ATDISABLE(nve_lock_pri,NVE_LOCK);
380: nbp_delete_entry(nve_entry);
381: ATENABLE(nve_lock_pri,NVE_LOCK);
382: found = TRUE;
383: }
384: nbp_req.nve.zone.len = 1;
385: nbp_req.nve.zone.str[0] = '*';
386: if (found)
387: DATA_NBP(nbp_req.response)->tuple_count = 0;
388: else
389: DATA_NBP(nbp_req.response)->tuple_count = EADDRNOTAVAIL;
390: nbp_send_resp(&nbp_req);
391: break;
392: } else {
393: if ((nve_entry = nbp_search_nve(&nbp_req, NULL)) == NULL) {
394: /* Can't find the tuple we're looking for, send error*/
395: DATA_NBP(nbp_req.response)->tuple_count = EADDRNOTAVAIL;
396: nbp_send_resp(&nbp_req);
397: } else {
398: /* Normal case; tuple found for this name, so delete
399: * the entry from the registry and return ok response.
400: */
401: ATDISABLE(nve_lock_pri,NVE_LOCK);
402: nbp_delete_entry(nve_entry);
403: ATENABLE(nve_lock_pri,NVE_LOCK);
404: DATA_NBP(nbp_req.response)->tuple_count = 0;
405: nbp_send_resp(&nbp_req);
406: }
407: }
408: break;
409: case NBP_CLOSE_NOTE :
410: ATDISABLE(nve_lock_pri,NVE_LOCK);
411: for (nve_entry = name_registry.fwd, next_nve = nve_entry->fwd;
412: nve_entry != &name_registry;
413: nve_entry = next_nve, next_nve = nve_entry->fwd) {
414: if ( DATA_DDP(m)->src_socket == nve_entry->address.socket &&
415: (*(int *)gbuf_wptr(m) == nve_entry->pid) &&
416: ot_ddp_check_socket(nve_entry->address.socket,
417: nve_entry->pid) < 2) {
418: nbp_delete_entry(nve_entry);
419: }
420: }
421: ATENABLE(nve_lock_pri,NVE_LOCK);
422: break;
423: case NBP_FWDRQ:
424: {
425: register int zhome=0; /* true if home zone == destination zone */
426: register int zno, i;
427: register gbuf_t *m2;
428: register error_found =0;
429: register at_if_t *ifIDorig;
430:
431: if (MULTIHOME_MODE || !ROUTING_MODE) /* for routers only! */
432: break;
433:
434: ddp = DATA_DDP(m);
435:
436: ifIDorig = ifID;
437: ifID= NULL;
438: for (i = 0 ; i < RT_MAXENTRY; i++) {
439: rt = &RT_table[i];
440: if ((rt->EntryState & RTE_STATE_PERMANENT) &&
441: NET_VALUE(ddp->dst_net) >= rt->NetStart &&
442: NET_VALUE(ddp->dst_net) <= rt->NetStop
443: ) {
444: /* sanity check */
445: if (rt->NetPort >= IF_TOTAL_MAX) {
446: dPrintf(D_M_NBP,D_L_ERROR,
447: ("nbp_handler:FWDREQ: bad port# from RT_table\n"));
448: error_found = TRUE;
449: break;
450: }
451: ifID = ifID_table[rt->NetPort];
452: if (!ifID || !IFID_VALID(ifID)) {
453: dPrintf(D_M_NBP,D_L_ERROR,
454: ("nbp_handler:FWDREQ: ifID %s\n",
455: !ifID ? "not found" : "invalid"));
456: error_found = TRUE;
457: break;
458: }
459: if (ifID->ifState == LAP_OFFLINE) {
460: dPrintf(D_M_NBP,D_L_ERROR,
461: ("nbp_handler:FWDREQ: ifID offline (port %d)\n",
462: rt->NetPort));
463: error_found = TRUE;
464: break;
465: }
466: break;
467: }
468: }
469: if (error_found) /* the port is not correct */
470: break;
471:
472: if (!ifID) { /* this packet is not for us, let the routing engine handle it */
473: routing_needed(m, ifIDorig, TRUE);
474: ddpSent= TRUE;
475: break;
476: }
477:
478: /*
479: * At this point, we have a valid Forward request for one of our
480: * direclty connected port. Convert it to a NBP Lookup
481: */
482:
483: nbp->control = NBP_LKUP;
484: NET_ASSIGN(ddp->dst_net, 0);
485: ddp->dst_node = 255;
486:
487:
488: /*### LD 01/18/94 Check if the dest is also the home zone. */
489:
490: p = nbp2zone(nbp, gbuf_wptr(m));
491: if ((p == NULL) || !(zno = zt_find_zname(p))) {
492: dPrintf(D_M_NBP,D_L_WARNING,
493: ("nbp_handler: FWDRQ:zone not found\n"));
494: break;
495: }
496: if (isZoneLocal((at_nvestr_t*)p))
497: zhome = TRUE; /* one of our ports is in destination zone */
498: if (!zt_get_zmcast(ifID, p, &mcastAddr)) {
499: dPrintf(D_M_NBP,D_L_ERROR,
500: ("nbp_handler: FDWREQ:zt_get_zmcast error\n"));
501: break;
502: }
503:
504:
505: if (zhome) { /*### LD 01/18/95 In case our home is here, call back nbp */
506:
507: if (!(m2 = (gbuf_t *)gbuf_copym((gbuf_t *)m))) {
508: dPrintf(D_M_NBP,D_L_ERROR,
509: ("nbp_handler: FWDRQ:gbuf_copym failed\n"));
510: break;
511: }
512:
513: ddp = DATA_DDP(m2);
514: nbp = DATA_NBP(m2);
515: nbp->control = NBP_LKUP;
516: NET_ASSIGN(ddp->dst_net, 0);
517: ddp->dst_node = 255;
518: dPrintf(D_M_NBP,D_L_INFO,
519: ("nbp_handler: FWDRQ:loop back for us\n"));
520: nbp_handler(m2, ifID_table[IFID_HOME]);
521: }
522:
523: if ((ifID->ifType == IFTYPE_FDDITALK)
524: || (ifID->ifType == IFTYPE_TOKENTALK))
525: ddp_bit_reverse(&mcastAddr);
526: ddp_router_output(m, ifID, ET_ADDR,NULL,NULL, &mcastAddr);
527: ddpSent = TRUE;
528: }
529: break;
530:
531: case NBP_BRRQ:
532: {
533: register int zno; /* zone table entry numb */
534: register int ztind; /* zone bitmap index into RT_entry */
535: register int ztbit; /* zone bit to check within above index */
536: register int zhome=0; /* true if home zone == destination zone */
537: register int i;
538: register gbuf_t *m2, *m3;
539: register int fromUs = FALSE;
540: register at_socket ourSkt; /* originating skt */
541:
542: ddp = DATA_DDP(m); /* for router & MH local only */
543: if ((MULTIHOME_MODE && !FROM_US(ddp))&& !ROUTING_MODE) {
544: dPrintf(D_M_NBP,D_L_USR2,
545: ("nbp_handler: BRREQ:non router or MH local\n"));
546:
547: break;
548: }
549: p = nbp2zone(nbp, gbuf_wptr(m));
550: if ((p == NULL) || !(zno = zt_find_zname(p))) {
551: break;
552: }
553: if (MULTIHOME_MODE && ifID->ifRouterState == NO_ROUTER) {
554: ((at_nvestr_t*)p)->len = 1;
555: ((at_nvestr_t*)p)->str[0] = '*';
556: }
557: if (isZoneLocal((at_nvestr_t*)p)) {
558: zhome = TRUE; /* one of our ports is in destination zone */
559: }
560: if (FROM_US(ddp)){ /* save, before we munge it */
561: fromUs = TRUE;
562: ourSkt = ddp->src_socket;
563: dPrintf(D_M_NBP,D_L_USR2,
564: ("nbp_handler:BRRQ from us net:%d\n",
565: (int)NET_VALUE(ddp->src_net)));
566: }
567: /* from ZT_CLR_ZMAP */
568: i = zno - 1;
569: ztind = i >> 3;
570: ztbit = 0x80 >> (i % 8);
571: for (i=0,rt=RT_table; i<RT_MAXENTRY; i++,rt++) {
572: if (!(rt->ZoneBitMap[ztind] & ztbit)) /* if zone not in route, skip*/
573: continue;
574: /* dPrintf(D_M_NBP, D_L_USR3,
575: ("nbp_handler: BRREQ: port:%d, entry %d\n",
576: rt->NetPort, i));
577: */
578:
579: ifID = ifID_table[rt->NetPort];
580: if (!ifID || !IFID_VALID(ifID)) {
581: dPrintf(D_M_NBP, D_L_ERROR,
582: ("nbp_handler:BRRQ: ifID %s\n",
583: !ifID ? "not found" : "invalid"));
584: break;
585: }
586:
587: ddp = DATA_DDP(m);
588: ddp->src_node = ifID->ifThisNode.atalk_node;
589: NET_NET(ddp->src_net, ifID->ifThisNode.atalk_net);
590: ddp->src_socket = NBP_SOCKET;
591: if (!(m2 = (gbuf_t *)gbuf_copym((gbuf_t *)m))) {
592: dPrintf(D_M_NBP,D_L_ERROR,
593: ("nbp_handler: BRREQ:gbuf_copym failed\n"));
594: break;
595: }
596:
597: ddp = DATA_DDP(m2);
598: nbp = DATA_NBP(m2);
599: /* nbp->tuple[0].enu_addr.socket = NBP_SOCKET; */
600: if (MULTIHOME_MODE && fromUs ) {
601: /* set the return address of the lookup to that of the
602: interface it's going out on so that replies come back
603: on that net */
604: dPrintf(D_M_NBP,D_L_USR3,
605: ("nbp_handler: BRREQ: src changed to %d.%d.%d\n",
606: NET_VALUE(ifID->ifThisNode.atalk_net),
607: ifID->ifThisNode.atalk_node, ourSkt));
608: NET_NET(nbp->tuple[0].enu_addr.net,ifID->ifThisNode.atalk_net);
609: nbp->tuple[0].enu_addr.node = ifID->ifThisNode.atalk_node;
610: nbp->tuple[0].enu_addr.socket = ourSkt;
611: ddp->src_socket = NBP_SOCKET;
612: }
613: else
614: dPrintf(D_M_NBP, D_L_USR3,
615: ("nbp_handler: BRREQ: not from us\n"));
616:
617: dPrintf(D_M_NBP, D_L_USR3,
618: ("nbp_handler dist:%d\n", rt->NetDist));
619: if (rt->NetDist == 0) { /* if direct connect, *we* do the LKUP */
620: nbp->control = NBP_LKUP;
621: NET_ASSIGN(ddp->dst_net, 0);
622: ddp->dst_node = 255;
623: if (!zt_get_zmcast(ifID, p, &mcastAddr)) {
624: dPrintf(D_M_NBP,D_L_ERROR,
625: ("nbp_handler: BRRQ:zt_get_zmcast error\n"));
626: break;
627: }
628: if ((ifID->ifType == IFTYPE_FDDITALK)
629: || (ifID->ifType == IFTYPE_TOKENTALK))
630: ddp_bit_reverse(&mcastAddr);
631: ddp_router_output(m2, ifID, ET_ADDR, NULL, NULL, &mcastAddr);
632: }
633: else { /* else fwd to router */
634: ddp->dst_node = 0;
635: if (rt->NetStart == 0) /* if Ltalk */
636: NET_ASSIGN(ddp->dst_net, rt->NetStop);
637: else
638: NET_ASSIGN(ddp->dst_net, rt->NetStart);
639: nbp->control = NBP_FWDRQ;
640: ddp_router_output(m2, ifID, AT_ADDR, rt->NextIRNet, rt->NextIRNode, NULL);
641: }
642: }
643: if (!zhome)
644: break;
645:
646: if (!(m3 = (gbuf_t *)gbuf_copym((gbuf_t *)m))) {
647: dPrintf(D_M_NBP,D_L_ERROR,
648: ("nbp_handler: BRREQ:gbuf_copym failed\n"));
649: break;
650: }
651:
652: ddp = DATA_DDP(m3);
653: nbp = DATA_NBP(m3);
654:
655: nbp->control = NBP_LKUP;
656: NET_ASSIGN(ddp->dst_net, 0);
657: ddp->dst_node = 255;
658: dPrintf(D_M_NBP,D_L_INFO,
659: ("nbp_handler: BRRQ:loop back for us\n"));
660: nbp_handler(m3, ifID_table[IFID_HOME]);
661: break;
662: }
663:
664: case NBP_LKUP_REPLY:
665:
666: if (MULTIHOME_MODE || !ROUTING_MODE) /* for routers only! */
667: break;
668:
669: ddp = DATA_DDP(m);
670:
671: dPrintf(D_M_NBP,D_L_WARNING,
672: ("nbp_handler: routing needed for LKUP_REPLY: from %d.%d\n",
673: NET_VALUE(ddp->src_net), ddp->src_node));
674: routing_needed(m, ifID, TRUE);
675: ddpSent = TRUE;
676: break;
677:
678: default :
679:
680: dPrintf(D_M_NBP,D_L_ERROR,
681: ("nbp_handler: unhandled pkt: type:%d\n", nbp->control));
682:
683: routing_needed(m, ifID, TRUE);
684: ddpSent = TRUE;
685: break;
686: } /* switch control */
687: if (!ddpSent)
688: gbuf_freem(m);
689: return;
690: }
691:
692:
693: static void zip_handler (m)
694: gbuf_t *m;
695: {
696: at_ddp_t *ddp = DATA_DDP(m);
697: register at_zip_t *zip = ZIP_ZIP(ddp);
698: register char old_zone_len;
699: register char new_zone_len;
700: register char mcast_len;
701: char *new_zone;
702:
703: switch (zip->command) {
704: case ZIP_NOTIFY :
705: /* ZipNotify packet forwarded by ZIP module...
706: * change the zone name this_zone.
707: */
708: old_zone_len = zip->data[4];
709: mcast_len = zip->data[4+old_zone_len+1];
710: new_zone_len = zip->data[4+old_zone_len+1+mcast_len+1];
711: new_zone = &zip->data[4+old_zone_len+1+mcast_len+1];
712: bcopy(new_zone, &this_zone, new_zone_len + 1);
713: break;
714: default :
715: /* ignore all the packets we don't know about */
716: break;
717: } /* switch command */
718: return;
719: }
720:
721:
722: static void rtmp_handler (m)
723: gbuf_t *m;
724: {
725: at_ddp_t *ddp = DATA_DDP(m);
726: at_rtmp *rtmp = (at_rtmp *)ddp->data;
727: at_net new_net;
728: register nve_entry_t *nve_entry;
729:
730: NET_NET(new_net, rtmp->at_rtmp_this_net);
731: for (nve_entry = name_registry.fwd; nve_entry != &name_registry ;
732: nve_entry = nve_entry->fwd)
733: NET_NET(nve_entry->address.net, new_net);
734: }
735:
736:
737: static int nbp_validate_n_hash (nbp_req, wild_ok, checkLocal)
738: register nbp_req_t *nbp_req;
739: register int wild_ok;
740: register int checkLocal; /* if true check if local zone */
741: {
742: register at_nvestr_t *object, *type, *zone;
743: at_nbptuple_t *tuple;
744: register int i, part_wild;
745: u_int nbp_strhash();
746:
747: tuple = DATA_NBP(nbp_req->request)->tuple;
748: nbp_req->flags = 0;
749: #ifdef COMMENTED_OUT
750: {
751: int net,node,skt;
752: net = NET_VALUE(tuple->enu_addr.net);
753: node = tuple->enu_addr.node;
754: skt = tuple->enu_addr.socket;
755: dPrintf(D_M_NBP_LOW,D_L_USR4,
756: ("nbp_validate: tuple addr:%d:%d:%d\n",net,node,skt));
757: }
758: #endif /* COMMENTED_OUT */
759:
760: object = (at_nvestr_t *)tuple->enu_name;
761: type = (at_nvestr_t *)(&object->str[object->len]);
762: zone = (at_nvestr_t *)(&type->str[type->len]);
763:
764: if (object->len > NBP_NVE_STR_SIZE || type->len > NBP_NVE_STR_SIZE ||
765: zone->len > NBP_NVE_STR_SIZE) {
766: errno = EINVAL;
767: return (-1);
768: }
769:
770: #ifdef NBP_DEBUG
771: {
772: char xzone[35],xobject[35],xtype[35];
773: strncpy(xzone,zone->str, zone->len);
774: strncpy(xobject,object->str, object->len);
775: strncpy(xtype,type->str, type->len);
776: xobject[object->len] = '\0';
777: xzone[zone->len] = '\0';
778: xtype[type->len] = '\0';
779: dPrintf(D_M_NBP_LOW, D_L_USR4,
780: ("nbp_validate: looking for %s:%s@%s\n",
781: xobject, xtype, xzone));
782: }
783: #endif /* NBP_DEBUG */
784: /* Is this request for our zone ?? */
785: nbp_req->nve.zone.len = zone->len;
786: nbp_req->nve.zone_hash = 0;
787: bcopy(zone->str,nbp_req->nve.zone.str, zone->len);
788: if (checkLocal && !isZoneLocal(zone)) {
789: char str[35];
790: strncpy(str,zone->str,zone->len);
791: str[zone->len] = '\0';
792: dPrintf(D_M_NBP_LOW,D_L_WARNING,
793: ("nbp_val_n_hash bad zone: %s\n", str));
794: errno = EINVAL;
795: return(-1);
796: }
797: if (Extended_net) {
798: /* EtherTalk...
799: * The zone name in the request must match either "*" or
800: * our zone name (this_zone). Zero length zone field is the
801: * same as "*".
802: */
803: if (zone->len != 0) {
804: if (!(zone->len == 1 && zone->str[0] == '*')) {
805: nbp_req->nve.zone_hash =
806: nbp_strhash(& nbp_req->nve.zone);
807: }
808: #ifdef COMMENTED_OUT
809: /* we allow multi-zone registration now, so
810: the actual zone name will be checked in
811: nbp_search_nve() */
812: if (nbp_strcmp(zone, &this_zone, NULL) != 0) {
813: errno = EINVAL;
814: return (-1);
815: }
816: #endif /* COMMENTED_OUT */
817: }
818: } else {
819: /* LocalTalk...
820: * "this_zone" variable will not have been initialized, since
821: * there's no interaction between NBP and ZIP for LocalTalk.
822: * We are assuming that the zone name field in a lookup
823: * request packet will always contain a legal value.
824: * One check that could be performed here (but is not) is :
825: * make sure that if there's no router around on the
826: * net, the zone name in the lookup request must be "*". If
827: * it's anything else, reject the packet.
828: */
829: }
830:
831: nbp_req->nve.address = tuple->enu_addr;
832: nbp_req->nve.object.len = object->len;
833: nbp_req->nve.object_hash = 0;
834: if (object->len == 1 && (object->str[0] == NBP_ORD_WILDCARD ||
835: object->str[0] == NBP_SPL_WILDCARD)) {
836: if (wild_ok)
837: nbp_req->flags |= NBP_WILD_OBJECT;
838: else {
839: errno = EINVAL;
840: return (-1);
841: }
842: } else{
843: for (i = part_wild = 0; (unsigned) i<object->len; i++) {
844: if (object->str[i] == NBP_SPL_WILDCARD)
845: if (wild_ok)
846: if (part_wild) {
847: errno = EINVAL;
848: return (-1);
849: } else
850: part_wild++;
851: else {
852: errno = EINVAL;
853: return (-1);
854: }
855: nbp_req->nve.object.str[i] = object->str[i];
856: }
857: if (!part_wild)
858: nbp_req->nve.object_hash =
859: nbp_strhash(&nbp_req->nve.object);
860: }
861:
862: nbp_req->nve.type.len = type->len;
863: nbp_req->nve.type_hash = 0;
864: if (type->len == 1 && (type->str[0] == NBP_ORD_WILDCARD ||
865: type->str[0] == NBP_SPL_WILDCARD)) {
866: if (wild_ok)
867: nbp_req->flags |= NBP_WILD_TYPE;
868: else {
869: errno = EINVAL;
870: return (-1);
871: }
872: } else {
873: for (i = part_wild = 0; (unsigned) i<type->len; i++) {
874: if (type->str[i] == NBP_SPL_WILDCARD)
875: if (wild_ok)
876: if (part_wild) {
877: errno = EINVAL;
878: return (-1);
879: } else
880: part_wild++;
881: else {
882: errno = EINVAL;
883: return (-1);
884: }
885: nbp_req->nve.type.str[i] = type->str[i];
886: }
887: if (!part_wild)
888: nbp_req->nve.type_hash =
889: nbp_strhash(&nbp_req->nve.type);
890: }
891: #ifdef NBP_DEBUG
892: {
893: char zone[35],object[35],type[35];
894: strncpy(zone,nbp_req->nve.zone.str, nbp_req->nve.zone.len);
895: strncpy(object,nbp_req->nve.object.str, nbp_req->nve.object.len);
896: strncpy(type,nbp_req->nve.type.str, nbp_req->nve.type.len);
897: object[nbp_req->nve.object.len] = '\0';
898: zone[nbp_req->nve.zone.len] = '\0';
899: type[nbp_req->nve.type.len] = '\0';
900: dPrintf(D_M_NBP_LOW,D_L_USR4,
901: ("nbp_validate: after hash: %s:%s@%s\n",
902: object, type, zone));
903: }
904: #endif /* NBP_DEBUG */
905: return(0);
906: }
907:
908:
909: /* Upshifts in place */
910: static void nbp_upshift (str, count)
911: register u_char *str;
912: register int count;
913: {
914: register int i, j;
915: register u_char ch;
916: static unsigned char lower_case[] =
917: {0x8a, 0x8c, 0x8d, 0x8e, 0x96, 0x9a, 0x9f, 0xbe,
918: 0xbf, 0xcf, 0x9b, 0x8b, 0x88, 0};
919: static unsigned char upper_case[] =
920: {0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0xae,
921: 0xaf, 0xce, 0xcd, 0xcc, 0xcb, 0};
922:
923: for (j=0 ; j<count ; j++) {
924: ch = str[j];
925: if (ch >= 'a' && ch <= 'z')
926: str[j] = ch + 'A' - 'a';
927: else if (ch & 0x80)
928: for (i=0; lower_case[i]; i++)
929: if (ch == lower_case[i])
930: str[j] = upper_case[i];
931: }
932: }
933:
934:
935: static u_int nbp_strhash (nvestr)
936: register at_nvestr_t *nvestr;
937: {
938: /* upshift while hashing */
939: register u_int hash = 0;
940: register int i, len;
941: union {
942: u_char h_4char[4];
943: int h_int;
944: } un;
945:
946: for (i=0; (unsigned) i < nvestr->len; i+=sizeof(int)) {
947: len = MIN((nvestr->len-i), sizeof(int));
948: if (len == sizeof(int))
949: bcopy(&(nvestr->str[i]), &un, sizeof(un));
950: else {
951: un.h_int = -1;
952: for ( ; (unsigned) i<nvestr->len; i++)
953: un.h_4char[i % sizeof(int)] = nvestr->str[i];
954: }
955: nbp_upshift (un.h_4char, len);
956: hash ^= un.h_int;
957: }
958:
959: return (hash);
960: }
961:
962:
963: static nve_entry_t *nbp_search_nve (nbp_req, ifID)
964: register nbp_req_t *nbp_req;
965: register at_if_t *ifID; /* NULL ok */
966: {
967: register nve_entry_t *nve_entry;
968:
969: #ifdef NBP_DEBUG
970: {
971: char zone[35],object[35],type[35];
972: strncpy(zone,nbp_req->nve.zone.str, nbp_req->nve.zone.len);
973: strncpy(object,nbp_req->nve.object.str, nbp_req->nve.object.len);
974: strncpy(type,nbp_req->nve.type.str, nbp_req->nve.type.len);
975: object[nbp_req->nve.object.len] = '\0';
976: zone[nbp_req->nve.zone.len] = '\0';
977: type[nbp_req->nve.type.len] = '\0';
978: dPrintf(D_M_NBP_LOW, D_L_USR4,
979: ("nbp_search: looking for %s:%s@%s resp:0x%x\n",object,type,zone,
980: (u_int) nbp_req->response));
981: }
982: #endif /* NBP_DEBUG */
983: ATDISABLE(nve_lock_pri,NVE_LOCK);
984: for (nve_entry = name_registry.fwd; nve_entry != &name_registry ;
985: nve_entry = nve_entry->fwd) {
986:
987: if ((nbp_req->nve.zone_hash) &&
988: ((nbp_req->nve.zone_hash !=
989: nve_entry->zone_hash) &&
990: (nbp_req->nve.zone_hash != hzonehash)
991: )
992: ) {
993: dPrintf(D_M_NBP_LOW,D_L_USR4,
994: ("nbp_search: no match for zone, req hash:%x\n",
995: nbp_req->nve.zone_hash));
996: continue;
997: }
998: else { /* for this entry's zone OR no zone in request or entry */
999: /* only in singleport mode (!MULTIPORT_MODE) with empty PRAM
1000: can an entry have '*' for it's zone
1001: */
1002: at_nvestr_t *ezone=&nve_entry->zone;
1003: at_nvestr_t *rzone=&nbp_req->nve.zone;
1004: /* if (!(rzone->len == 1 && rzone->str[0] == '*')) { */
1005: if (!DEFAULT_ZONE(rzone) && !DEFAULT_ZONE(ezone)) {
1006: if (nbp_strcmp (rzone, ezone, 0) != 0)
1007: continue;
1008: }
1009: else {
1010: if (MULTIHOME_MODE && ifID &&
1011: NET_NOTEQ(nve_entry->address.net, ifID->ifThisNode.atalk_net)) {
1012: dPrintf(D_M_NBP, D_L_USR4,
1013: ("nbp search ifID (%d) & req net (%d) not eq\n",
1014: NET_VALUE(nve_entry->address.net),
1015: NET_VALUE(ifID->ifThisNode.atalk_net)));
1016: continue;
1017: }
1018: dPrintf(D_M_NBP, D_L_USR4,
1019: ("nbp search ifID (%d) & req net (%d) equal\n",
1020: NET_VALUE(nve_entry->address.net),
1021: NET_VALUE(ifID->ifThisNode.atalk_net)));
1022: }
1023:
1024: }
1025: if (!(nbp_req->flags & NBP_WILD_OBJECT)) {
1026: if ((nbp_req->nve.object_hash) &&
1027: (nbp_req->nve.object_hash !=
1028: nve_entry->object_hash))
1029: continue;
1030: else {
1031: if (nbp_strcmp (&nbp_req->nve.object,
1032: &nve_entry->object,
1033: NBP_SPL_WILDCARD) != 0)
1034: continue;
1035: }
1036: }
1037:
1038:
1039: if (!(nbp_req->flags & NBP_WILD_TYPE)) {
1040: if ((nbp_req->nve.type_hash) &&
1041: (nbp_req->nve.type_hash !=nve_entry->type_hash))
1042: continue;
1043: else {
1044: if (nbp_strcmp (&nbp_req->nve.type,
1045: &nve_entry->type,
1046: NBP_SPL_WILDCARD) != 0)
1047: continue;
1048: }
1049: }
1050:
1051: /* Found a match! */
1052: #ifdef NBP_DEBUG
1053: {
1054: char zone[35],object[35],type[35];
1055: int net;
1056: net = NET_VALUE(nve_entry->address.net);
1057: strncpy(zone,nbp_req->nve.zone.str, nbp_req->nve.zone.len);
1058: strncpy(object,nbp_req->nve.object.str, nbp_req->nve.object.len);
1059: strncpy(type,nbp_req->nve.type.str, nbp_req->nve.type.len);
1060: object[nbp_req->nve.object.len] = '\0';
1061: zone[nbp_req->nve.zone.len] = '\0';
1062: type[nbp_req->nve.type.len] = '\0';
1063: dPrintf(D_M_NBP_LOW, D_L_USR2,
1064: ("nbp_search: found %s:%s@%s net:%d\n",
1065: object, type, zone, net));
1066: }
1067: #endif /* NBP_DEBUG */
1068: if (nbp_req->func != NULL) {
1069: if ((*(nbp_req->func))(nbp_req, nve_entry) != 0) {
1070: /* errno expected to be set by func */
1071: ATENABLE(nve_lock_pri,NVE_LOCK);
1072: return (NULL);
1073: }
1074: } else {
1075: ATENABLE(nve_lock_pri,NVE_LOCK);
1076: return (nve_entry);
1077: }
1078: }
1079: ATENABLE(nve_lock_pri,NVE_LOCK);
1080:
1081: errno = 0;
1082: return (NULL);
1083: }
1084:
1085:
1086: static int nbp_lkup_reply (nbp_req, nve_entry)
1087: register nbp_req_t *nbp_req;
1088: register nve_entry_t *nve_entry;
1089: {
1090: register at_nbptuple_t *tuple;
1091: register int tuple_size, buf_len;
1092: register int obj_len, type_len;
1093:
1094: /* size of the current tuple we want to write... */
1095: tuple_size = nve_entry->object.len + 1 + /* object */
1096: nve_entry->type.len + 1 + /* type */
1097: 2 + /* zone */
1098: sizeof (at_inet_t) + 1; /* addr + enum */
1099:
1100: buf_len = ((nbp_req->flags & NBP_WILD_MASK) ? DDP_DATA_SIZE:tuple_size);
1101: if (nbp_req->response == NULL) {
1102: if (nbp_setup_resp (nbp_req, buf_len) != 0)
1103: /* errno expected to be set by nbp_setup_resp() */
1104: return (-1);
1105: }
1106:
1107: if ((nbp_req->space_unused < tuple_size) ||
1108: (DATA_NBP(nbp_req->response)->tuple_count == NBP_TUPLE_MAX)) {
1109: if (nbp_send_resp (nbp_req) != 0)
1110: return (-1);
1111: if (nbp_setup_resp (nbp_req, buf_len) != 0)
1112: return (-1);
1113: }
1114:
1115: /* At this point, we have a response buffer that can accommodate the
1116: * tuple we want to write. Write it!
1117: */
1118: tuple = (at_nbptuple_t *)gbuf_wptr(nbp_req->response);
1119: tuple->enu_addr = nve_entry->address;
1120: tuple->enu_enum = nve_entry->enumerator;
1121: obj_len = nve_entry->object.len + 1;
1122: bcopy(&nve_entry->object, &tuple->enu_name[0], obj_len);
1123: type_len = nve_entry->type.len + 1;
1124: bcopy(&nve_entry->type, &tuple->enu_name[obj_len], type_len);
1125: tuple->enu_name[obj_len + type_len] = 1;
1126: tuple->enu_name[obj_len + type_len + 1] = '*';
1127:
1128: nbp_req->space_unused -= tuple_size;
1129: gbuf_winc(nbp_req->response, tuple_size);
1130:
1131: /* increment the tuple count in header by 1 */
1132: DATA_NBP(nbp_req->response)->tuple_count++;
1133:
1134: return (0);
1135: }
1136:
1137:
1138: static int nbp_strcmp (str1, str2, embedded_wildcard)
1139: register at_nvestr_t *str1, *str2;
1140: register u_char embedded_wildcard; /* If str1 may contain a character
1141: * that's to be treated as an
1142: * embedded wildcard, this character
1143: * is it. Making this special case
1144: * since for zone names, squiggly
1145: * equal is not to be treated as a
1146: * wildcard.
1147: */
1148: {
1149: u_char ch1,ch2;
1150: register int i1, i2;
1151: register int reverse = 0;
1152: register int left_index;
1153:
1154: /* Embedded wildcard, if any, could only be in the first string (str1).
1155: * returns 0 if two strings are equal (modulo case), -1 otherwise
1156: */
1157:
1158: if (str1->len == 0 || str2->len == 0) {
1159: return (-1);
1160: }
1161:
1162: /* Wildcards are not allowed in str2.
1163: *
1164: * If str1 could potentially contain an embedded wildcard, since the
1165: * embedded wildcard matches ZERO OR MORE characters, str1 can not be
1166: * more than 1 character longer than str2.
1167: *
1168: * If str1 is not supposed to have embedded wildcards, the two strs
1169: * must be of equal length.
1170: */
1171: if ((embedded_wildcard && (str2->len < (unsigned) (str1->len-1))) ||
1172: (!embedded_wildcard && (str2->len != str1->len))) {
1173: return (-1);
1174: }
1175:
1176: for (i1 = i2 = left_index = 0; (unsigned) i1 < str1->len ;) {
1177: ch1 = str1->str[i1];
1178: ch2 = str2->str[i2];
1179:
1180: if (embedded_wildcard && (ch1==embedded_wildcard)) {
1181: /* hit the embedded wild card... start comparing from
1182: * the other end of the string.
1183: */
1184: reverse++;
1185: /* But, if embedded wildcard was the last character of
1186: * the string, the two strings match, so return okay.
1187: */
1188: if (i1 == str1->len-1) {
1189: return (0);
1190: }
1191:
1192: i1 = str1->len - 1;
1193: i2 = str2->len - 1;
1194:
1195: continue;
1196: }
1197:
1198: nbp_upshift(&ch1, 1);
1199: nbp_upshift(&ch2, 1);
1200:
1201: if (ch1 != ch2) {
1202: return (-1);
1203: }
1204:
1205: if (reverse) {
1206: i1--; i2--;
1207: if (i1 == left_index) {
1208: return (0);
1209: }
1210: } else {
1211: i1++; i2++; left_index++;
1212: }
1213: }
1214: return (0);
1215: }
1216:
1217:
1218: static void nbp_setup_hdr (nbp_req)
1219: register nbp_req_t *nbp_req;
1220: {
1221: register at_ddp_t *ddp;
1222: register at_nbp_t *nbp;
1223:
1224: ddp = DATA_DDP(nbp_req->response);
1225: nbp = DATA_NBP(nbp_req->response);
1226:
1227: ddp->type = NBP_DDP_TYPE;
1228: UAS_ASSIGN(ddp->checksum, 0);
1229: ddp->unused = ddp->hopcount = 0;
1230:
1231: switch(DATA_NBP(nbp_req->request)->control) {
1232: case NBP_LKUP :
1233: ddp->dst_socket = nbp_req->nve.address.socket;
1234: ddp->dst_node = nbp_req->nve.address.node;
1235: NET_NET(ddp->dst_net, nbp_req->nve.address.net);
1236: nbp->control = NBP_LKUP_REPLY;
1237: break;
1238: case NBP_REGISTER :
1239: case NBP_DELETE :
1240: ddp->dst_socket = DATA_DDP(nbp_req->request)->src_socket;
1241: ddp->dst_node = DATA_DDP(nbp_req->request)->src_node;
1242: NET_NET(ddp->dst_net, DATA_DDP(nbp_req->request)->src_net);
1243: nbp->control = NBP_STATUS_REPLY;
1244: break;
1245: }
1246: nbp->at_nbp_id = DATA_NBP(nbp_req->request)->at_nbp_id;
1247: return;
1248: }
1249:
1250:
1251: static int nbp_setup_resp (nbp_req, tuples_size)
1252: register nbp_req_t *nbp_req;
1253: register int tuples_size;
1254: {
1255: int buf_size = tuples_size + DDP_X_HDR_SIZE + NBP_HDR_SIZE;
1256: nbp_req->response = gbuf_alloc(AT_WR_OFFSET+buf_size, PRI_MED);
1257: if (nbp_req->response == NULL) {
1258: errno = ENOBUFS;
1259: return(-1);
1260: }
1261: gbuf_rinc(nbp_req->response, AT_WR_OFFSET);
1262: gbuf_wset(nbp_req->response, DDP_X_HDR_SIZE + NBP_HDR_SIZE);
1263: nbp_setup_hdr(nbp_req);
1264:
1265: DATA_NBP(nbp_req->response)->tuple_count = 0;
1266: nbp_req->space_unused = tuples_size;
1267:
1268: return (0);
1269: } /* nbp_setup_resp */
1270:
1271:
1272: static int nbp_send_resp (nbp_req)
1273: register nbp_req_t *nbp_req;
1274: {
1275: int status;
1276:
1277: status = ddp_output(&nbp_req->response, (at_socket)NBP_SOCKET, NULL);
1278:
1279: if (status)
1280: gbuf_freem(nbp_req->response);
1281: nbp_req->response = NULL;
1282: errno = status;
1283: return(errno?-1:0);
1284: }
1285:
1286: static int nbp_insert_entry (nve_entry)
1287: nve_entry_t *nve_entry;
1288: {
1289: gbuf_t *tag;
1290: nve_entry_t *new_entry;
1291: int i;
1292: at_if_t *ifID;
1293: at_nvestr_t *zone;
1294: int multiZone = 0; /* true if we should do multiple registrations */
1295: int defaultZone = 0; /* true if zone is '*' */
1296:
1297: /* Got an nve entry on hand.... allocate a buffer, copy the entry
1298: * on to it and stick it in the registry.
1299: */
1300: if (nve_entry->zone.str[0] == '*')
1301: defaultZone=TRUE;
1302: if (defaultZone && MULTIHOME_MODE) {
1303: multiZone = TRUE;
1304: }
1305: for (ifID = ifID_table[0],i=0; ifID; ifID=ifID_table[++i]) {
1306: if (!defaultZone && MULTIPORT_MODE ) {
1307: /* if registering for a specific zone and we have multiple
1308: I/F's running, find the first I/F containing the
1309: requested zone
1310: */
1311: int zno;
1312: char ifs_in_zone[IF_TOTAL_MAX];
1313: if (!(zno = zt_find_zname(&nve_entry->zone))) {
1314: errno = ENOENT;
1315: return(-1);
1316: }
1317: getIfUsage(zno-1, ifs_in_zone);
1318: for(; ifID; ifID=ifID_table[++i])
1319: if (ifs_in_zone[i])
1320: break;
1321: if (!ifID) {
1322: errno = ENOENT;
1323: return(-1);
1324: }
1325: }
1326:
1327: if ((tag = gbuf_alloc(sizeof(nve_entry_t), PRI_HI)) == NULL){
1328: errno = ENOBUFS;
1329: return (-1);
1330: }
1331: gbuf_wset(tag, sizeof(nve_entry_t));
1332: new_entry = (nve_entry_t *)gbuf_rptr(tag);
1333: bcopy(nve_entry, new_entry, sizeof(nve_entry_t));
1334: NET_NET(new_entry->address.net, ifID->ifThisNode.atalk_net);
1335: new_entry->address.node = ifID->ifThisNode.atalk_node;
1336: if (multiZone ){
1337: new_entry->zone = ZT_table[ifID->ifDefZone-1].Zone;
1338: new_entry->zone_hash = nbp_strhash(&new_entry->zone);
1339: }
1340:
1341: if (defaultZone && !multiZone ) {
1342: /* put actual zone name in entry instead of "*" */
1343: /* if single port mode and no zone name, then a router
1344: is down, so use pram zone name hint from elap cfg */
1345: if (!MULTIPORT_MODE && ifID->ifZoneName.str[0] == '*') {
1346: elap_specifics_t *elapp;
1347: elapp = (elap_specifics_t*)(ifID_table[IFID_HOME]->ifLapp);
1348: zone = &elapp->cfg.zonename;
1349: }
1350: else {
1351: zone = &ifID_table[IFID_HOME]->ifZoneName;
1352: }
1353: new_entry->zone = *zone;
1354: if ( new_entry->zone.len == 0 ) {
1355: new_entry->zone.str[0] = '*';
1356: new_entry->zone.len = 1;
1357: }
1358: new_entry->zone_hash = nbp_strhash(&new_entry->zone);
1359: }
1360: new_entry->tag = tag;
1361: #ifdef NEXT
1362: /* Fixes PR 2243737: didn't deregister nbp entity properly */
1363: new_entry->pid = current_proc()->p_pid;
1364: #else
1365: new_entry->pid = getpid();
1366: #endif
1367:
1368: ATDISABLE(nve_lock_pri,NVE_LOCK);
1369: ddp_insque(new_entry, name_registry.fwd);
1370: ATENABLE(nve_lock_pri,NVE_LOCK);
1371: at_statep->flags |= AT_ST_NBP_CHANGED;
1372: #ifdef NBP_DEBUG
1373: {
1374: char zone[35],object[35],type[35];
1375: strncpy(zone,new_entry->zone.str, new_entry->zone.len);
1376: strncpy(object,new_entry->object.str, new_entry->object.len);
1377: strncpy(type,new_entry->type.str, new_entry->type.len);
1378: object[new_entry->object.len] = '\0';
1379: zone[new_entry->zone.len] = '\0';
1380: type[new_entry->type.len] = '\0';
1381: dPrintf(D_M_NBP_LOW, D_L_USR4,
1382: ("nbp_insert:adding %s:%s@%s i/f:%s ",
1383: object, type, zone, ifID->ifName));
1384: dPrintf(D_M_NBP_LOW, D_L_USR4,
1385: ("addr:%d.%d\n",
1386: NET_VALUE(new_entry->address.net),
1387: new_entry->address.node));
1388: }
1389: #endif /* NBP_DEBUG */
1390: nbp_add_multicast(&new_entry->zone, ifID);
1391: if (!multiZone)
1392: break;
1393: }
1394: return (0);
1395: }
1396:
1397: nbp_add_multicast(zone, ifID)
1398: at_nvestr_t *zone;
1399: at_if_t *ifID;
1400: {
1401: char data[ETHERNET_ADDR_LEN];
1402: int i;
1403:
1404: if (zone->str[0] == '*')
1405: return;
1406: {
1407: char str[35];
1408: strncpy(str,zone->str,zone->len);
1409: str[zone->len] = '\0';
1410: dPrintf(D_M_NBP_LOW, D_L_USR3,
1411: ("nbp_add_multi getting mc for %s\n", str));
1412: }
1413: zt_get_zmcast(ifID, zone, data);
1414: if ((ifID->ifType == IFTYPE_FDDITALK)
1415: || (ifID->ifType == IFTYPE_TOKENTALK))
1416: ddp_bit_reverse(data);
1417: dPrintf(D_M_NBP_LOW,D_L_USR3,
1418: ("nbp_add_multi adding 0x%x%x port:%d ifID:0x%x if:%s\n",
1419: *(unsigned*)data, (*(unsigned *)(data+2))&0x0000ffff,
1420: i, (u_int) ifID, ifID->ifName));
1421:
1422: elap_control(ifID, ELAP_REG_ZONE_MCAST, data);
1423: }
1424:
1425:
1426: static void nbp_delete_entry (nve_entry)
1427: nve_entry_t *nve_entry;
1428: {
1429: ddp_remque(nve_entry);
1430: gbuf_freem(nve_entry->tag);
1431: at_statep->flags |= AT_ST_NBP_CHANGED;
1432: }
1433:
1434:
1435: static int nbp_enum_gen (nve_entry)
1436: register nve_entry_t *nve_entry;
1437: {
1438: register int new_enum = 0;
1439: register nve_entry_t *ne;
1440:
1441: ATDISABLE(nve_lock_pri,NVE_LOCK);
1442: re_do:
1443: for (ne = name_registry.fwd; ne != &name_registry; ne = ne->fwd) {
1444: if ((*(int *)&ne->address == *(int *)&nve_entry->address) &&
1445: (ne->enumerator == new_enum)) {
1446: if (new_enum == 255) {
1447: errno = EADDRNOTAVAIL;
1448: ATENABLE(nve_lock_pri,NVE_LOCK);
1449: return (-1);
1450: } else {
1451: new_enum++;
1452: goto re_do;
1453: }
1454: }
1455: }
1456:
1457: ATENABLE(nve_lock_pri,NVE_LOCK);
1458: nve_entry->enumerator = new_enum;
1459: return (0);
1460: }
1461:
1462:
1463: getNbpTableSize()
1464:
1465: /* for SNMP, returns size in # of entries */
1466: {
1467: register nve_entry_t *nve;
1468: register int i=0;
1469:
1470: ATDISABLE(nve_lock_pri,NVE_LOCK);
1471: for (nve = name_registry.fwd; nve != &name_registry; nve = nve->fwd, i++)
1472: ;
1473: ATENABLE(nve_lock_pri,NVE_LOCK);
1474: return(i);
1475: }
1476:
1477: getNbpTable(p,s,c)
1478: snmpNbpEntry_t *p;
1479: int s; /* starting entry */
1480: int c; /* # entries to copy */
1481:
1482: /* for SNMP, returns section of nbp table */
1483:
1484: {
1485: register nve_entry_t *nve;
1486: register int i=0;
1487: static int nextNo=0; /* entry that *next points to */
1488: static nve_entry_t *next = (nve_entry_t*)NULL;
1489:
1490: if (s && next && nextNo == s) {
1491: nve = next;
1492: i = nextNo;
1493: }
1494: else
1495: nve = name_registry.fwd;
1496:
1497: ATDISABLE(nve_lock_pri,NVE_LOCK);
1498: for ( ; nve != &name_registry && c ; nve = nve->fwd, p++,i++) {
1499: if (i>= s) {
1500: p->nbpe_object = nve->object;
1501: p->nbpe_type = nve->type;
1502: c--;
1503: }
1504: }
1505: ATENABLE(nve_lock_pri,NVE_LOCK);
1506: if (nve != &name_registry) {
1507: next = nve;
1508: nextNo = i;
1509: }else {
1510: next = (nve_entry_t*)NULL;
1511: nextNo = 0;
1512: }
1513: }
1514:
1515:
1516: #define ZONES_PER_BLK 31 /* 31 fits within a 1k blk) */
1517: #define ZONE_BLK_SIZE ZONES_PER_BLK * sizeof(at_nvestr_t)
1518:
1519: setLocalZones(newzones, size)
1520: at_nvestr_t *newzones;
1521: int size;
1522: /* updates list of zones which are local to all active ports
1523: missing zones are not deleted, only missing zones are added.
1524: */
1525: {
1526: int bytesread=0; /* #bytes read from tuple */
1527: int i=0, dupe;
1528: gbuf_t *m;
1529: at_nvestr_t *pnve, *pnew = newzones;
1530:
1531: if (!lzones) {
1532: if(!(lzones = gbuf_alloc(ZONE_BLK_SIZE, PRI_MED)))
1533: return(ENOBUFS);
1534: gbuf_wset(lzones,0);
1535: }
1536: while (bytesread < size) { /* for each new zone */
1537: {
1538: char str[35];
1539: strncpy(str,pnew->str,pnew->len);
1540: str[pnew->len] = '\0';
1541: }
1542: m = lzones;
1543: pnve = (at_nvestr_t*)gbuf_rptr(m);
1544: dupe = 0;
1545: for (i=0; i<lzonecnt && !dupe; i++,pnve++) {
1546: if (i && !(i%ZONES_PER_BLK))
1547: if (gbuf_cont(m)) {
1548: m = gbuf_cont(m);
1549: pnve = (at_nvestr_t*)gbuf_rptr(m);
1550: }
1551: else
1552: break;
1553: if (pnew->len != pnve->len)
1554: continue;
1555: if ((pnew->len > 33) || (pnew->len <0) ) {
1556: return(0);
1557: }
1558: if (!strncmp(pnew->str, pnve->str, pnew->len)) {
1559: dupe=1;
1560: continue;
1561: }
1562: }
1563: if (!dupe) {
1564: /* add new zone */
1565: if (lzonecnt && !(lzonecnt%ZONES_PER_BLK)) {
1566: if(!(gbuf_cont(m) = gbuf_alloc(ZONE_BLK_SIZE, PRI_MED)))
1567: return(ENOBUFS);
1568: gbuf_wset(gbuf_cont(m),0);
1569: pnve = (at_nvestr_t*)gbuf_rptr(gbuf_cont(m));
1570: }
1571: strncpy(pnve->str,pnew->str,pnew->len);
1572: pnve->len = pnew->len;
1573: lzonecnt++;
1574: }
1575: bytesread += (pnew->len+1);
1576: pnew = (at_nvestr_t*) (((char *)pnew) + pnew->len + 1);
1577: }
1578: /* showLocalZones1(); */
1579: return(0);
1580: }
1581:
1582: /**********
1583: showLocalZones1()
1584: {
1585: int i;
1586: at_nvestr_t *pnve;
1587: gbuf_t *m;
1588: char str[35];
1589:
1590: for (i=0; ; i++) {
1591: if (!(pnve = getLocalZone(i))) {
1592: break;
1593: }
1594: strncpy(str,pnve->str,pnve->len);
1595: str[pnve->len] = '\0';
1596: }
1597: }
1598:
1599: *********/
1600:
1601: isZoneLocal(zone)
1602: at_nvestr_t *zone;
1603: {
1604: at_nvestr_t *pnve;
1605: int i;
1606: if ((zone->len == 1 && zone->str[0] == '*') || zone->len == 0)
1607: return(1);
1608: for (i=0; ; i++) {
1609: if (!(pnve = getLocalZone(i)))
1610: break;
1611: if (!nbp_strcmp(pnve,zone,0))
1612: return(1);
1613: }
1614: return(0);
1615: }
1616:
1617:
1618: #define NULL_PNVESTR (at_nvestr_t *) 0
1619:
1620: at_nvestr_t *getLocalZone(zno)
1621: int zno; /* zone number in virtual list to
1622: return, 0 for first zone */
1623: /* returns pointer to a new local zone number zno,
1624: returns null when no zones left.
1625: */
1626: {
1627: if_zone_t ifz;
1628: ifz.ifzn.zone = zno;
1629: if (ROUTING_MODE || MULTIHOME_MODE)
1630: return(getRTRLocalZone(&ifz));
1631: else
1632: return(getSPLocalZone(zno));
1633: }
1634:
1635:
1636: at_nvestr_t *getSPLocalZone(zno)
1637: int zno; /* zone number in virtual list to
1638: return, 0 for first zone */
1639: /* single port mode version */
1640: {
1641: int curz=0; /* current zone */
1642: gbuf_t *m;
1643: at_nvestr_t *pnve;
1644:
1645: if (lzones) {
1646: m = lzones;
1647: pnve = (at_nvestr_t*)gbuf_rptr(m);
1648: }
1649: else
1650: return(NULL_PNVESTR);
1651: if ( zno>=lzonecnt )
1652: return(NULL_PNVESTR);
1653: for (curz=0; curz<zno; curz++,pnve++ ) {
1654: if ( curz<lzonecnt ) {
1655: if (curz && !(curz%ZONES_PER_BLK) ) {
1656: if (gbuf_cont(m)) {
1657: m = gbuf_cont(m);
1658: pnve = (at_nvestr_t*)gbuf_rptr(m);
1659: }
1660: else {
1661: return(NULL_PNVESTR);
1662: }
1663: }
1664: if ((pnve->len > NBP_NVE_STR_SIZE) || (pnve->len <0) ) {
1665: return(NULL_PNVESTR);
1666: }
1667: }
1668: else
1669: return(NULL_PNVESTR);
1670: }
1671: return(pnve);
1672: }
1673:
1674:
1675:
1676:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.