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