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