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