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