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