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