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