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