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