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