]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netat/ddp_nbp.c
2 * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 * Copyright (c) 1988, 1989, 1997, 1998 Apple Computer, Inc.
33 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
38 #include <sys/errno.h>
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <machine/spl.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
45 #include <sys/filedesc.h>
46 #include <sys/fcntl.h>
48 #include <sys/ioctl.h>
49 #include <sys/malloc.h>
50 #include <sys/socket.h>
51 #include <sys/socketvar.h>
54 #include <net/if_types.h>
56 #include <netat/sysglue.h>
57 #include <netat/appletalk.h>
58 #include <netat/at_var.h>
59 #include <netat/ddp.h>
60 #include <netat/nbp.h>
61 #include <netat/zip.h>
62 #include <netat/rtmp.h>
63 #include <netat/routing_tables.h> /* router */
64 #include <netat/at_snmp.h>
65 #include <netat/at_pcb.h>
66 #include <netat/debug.h>
68 /* reaching for DDP and NBP headers in the datagram */
69 #define DATA_DDP(mp) ((at_ddp_t *)(gbuf_rptr(mp)))
70 #define DATA_NBP(mp) ((at_nbp_t *)((DATA_DDP(mp))->data))
72 /* Get to the nve_entry_t part ofthe buffer */
73 #define NVE_ENTRY(mp) (nve_entry_t *)(gbuf_rptr(mp))
76 #define MIN(a,b) ((a)>(b)?(b):(a))
79 #define errno nbperrno
82 extern at_ifaddr_t
*ifID_table
[];
83 extern at_ifaddr_t
*ifID_home
;
85 TAILQ_HEAD(name_registry
, _nve_
) name_registry
;
91 static gbuf_t
*lzones
=0; /* head of local zones list */
92 static int lzonecnt
=0; /* # zones stored in lzones */
93 static u_int hzonehash
=0; /* hash val of home zone */
94 static int nve_lock_pri
;
96 static int nbp_lkup_reply(nbp_req_t
*, nve_entry_t
*);
97 static int nbp_strcmp(at_nvestr_t
*, at_nvestr_t
*, u_char
);
98 static int nbp_setup_resp(nbp_req_t
*, int);
99 static int nbp_send_resp(nbp_req_t
*);
100 static int nbp_validate_n_hash(nbp_req_t
*, int, int);
101 static nve_entry_t
*nbp_search_nve();
102 static int isZoneLocal(at_nvestr_t
*);
105 #define NVE_LOCK nve_lock
108 void nbp_delete_entry();
109 extern int at_reg_mcast();
110 extern at_nvestr_t
*getRTRLocalZone(zone_usage_t
*);
111 extern void nbp_add_multicast( at_nvestr_t
*, at_ifaddr_t
*);
113 static long nbp_id_count
= 0;
115 void sethzonehash(elapp
)
118 if (elapp
->startup_zone
.len
) {
119 hzonehash
= nbp_strhash(&elapp
->startup_zone
);
125 /* delete all NVE's and release buffers */
126 register nve_entry_t
*nve_entry
, *nve_next
;
128 ATDISABLE(nve_lock_pri
,NVE_LOCK
);
129 for ((nve_entry
= TAILQ_FIRST(&name_registry
)); nve_entry
; nve_entry
= nve_next
) {
130 nve_next
= TAILQ_NEXT(nve_entry
, nve_link
);
132 /* NB: nbp_delete_entry calls TAILQ_REMOVE */
133 nbp_delete_entry(nve_entry
);
135 ATENABLE(nve_lock_pri
,NVE_LOCK
);
145 u_char
*nbp2zone(nbp
, maxp
)
152 p
= (u_char
*)&nbp
->tuple
[0].enu_entity
; /* p -> object */
153 if (p
>= maxp
) return NULL
;
154 p
+= (*p
+1); /* p -> type */
155 if (p
>= maxp
) return NULL
;
156 p
+= (*p
+1); /* p -> zone */
157 if (p
>= maxp
) return NULL
;
158 if ((p
+ *p
) >= maxp
) return NULL
;
162 void nbp_input(m
, ifID
)
164 register at_ifaddr_t
*ifID
;
167 register at_ddp_t
*ddp
= DATA_DDP(m
);
168 register at_nbp_t
*nbp
= DATA_NBP(m
);
169 register nve_entry_t
*nve_entry
, *next_nve
;
170 register RT_entry
*rt
;
171 register int ddpSent
= FALSE
; /* true if we re-sent this pkt (don't free) */
172 struct etalk_addr mcastAddr
;
176 /* from original nbp_input() when this function was nbp_handler() */
177 if ((gbuf_type(m
) != MT_DATA
&& gbuf_type(m
) != MSG_DATA
) ||
178 ddp
->type
!= DDP_NBP
) {
183 /* Some initializations */
184 nbp_req
.response
= NULL
;
186 nbp_req
.space_unused
= nbp_req
.flags
= 0;
188 dPrintf(D_M_NBP_LOW
, D_L_USR1
,
189 ("nbp_input control:%d tuplecount:%d id:%d\n",
190 nbp
->control
, nbp
->tuple_count
, nbp
->at_nbp_id
));
191 switch (nbp
->control
) {
196 dst_net
= NET_VALUE(ddp
->dst_net
);
197 dPrintf(D_M_NBP_LOW
, D_L_USR2
, (" LKUP %s\n",
198 ifID
!= ifID_home
? "non-home" : "home"));
199 if ( ROUTING_MODE
&& (NET_VALUE(ddp
->dst_net
) != 0)
200 && ((dst_net
< ifID
->ifThisCableStart
)
201 || (dst_net
> ifID
->ifThisCableEnd
)) ) {
202 routing_needed(m
, ifID
, TRUE
);
208 if (nbp_validate_n_hash (&nbp_req
, TRUE
, FALSE
) == 0) {
209 nbp_req
.func
= nbp_lkup_reply
;
210 (void) nbp_search_nve(&nbp_req
, ifID
);
211 if (nbp_req
.response
) {
212 nbp_send_resp(&nbp_req
);
217 char zone
[35],object
[35],type
[35];
218 strncpy(zone
,nbp_req
.nve
.zone
.str
, nbp_req
.nve
.zone
.len
);
219 strncpy(object
,nbp_req
.nve
.object
.str
, nbp_req
.nve
.object
.len
);
220 strncpy(type
,nbp_req
.nve
.type
.str
, nbp_req
.nve
.type
.len
);
221 object
[nbp_req
.nve
.object
.len
] = '\0';
222 zone
[nbp_req
.nve
.zone
.len
] = '\0';
223 type
[nbp_req
.nve
.type
.len
] = '\0';
224 if (ifID
!= ifID_home
)
225 dPrintf(D_M_NBP_LOW
,D_L_USR2
,
226 ("nbp_LKUP for:%s:%s@%s", object
, type
, zone
));
228 #endif /* NBP_DEBUG */
233 register int zhome
=0;
234 /* true if home zone == destination zone */
237 register int error_found
=0;
238 register at_ifaddr_t
*ifIDorig
;
240 if (!ROUTING_MODE
) /* for routers only! */
245 for (i
= 0 ; i
< RT_maxentry
; i
++) {
247 if ((rt
->EntryState
& RTE_STATE_PERMANENT
) &&
248 NET_VALUE(ddp
->dst_net
) >= rt
->NetStart
&&
249 NET_VALUE(ddp
->dst_net
) <= rt
->NetStop
252 if (rt
->NetPort
>= IF_TOTAL_MAX
) {
253 dPrintf(D_M_NBP
,D_L_ERROR
,
254 ("nbp_input:FWDREQ: bad port# from RT_table\n"));
258 ifID
= ifID_table
[rt
->NetPort
];
260 dPrintf(D_M_NBP
,D_L_ERROR
,
261 ("nbp_input:FWDREQ: ifID %s\n",
262 !ifID
? "not found" : "invalid"));
266 if (ifID
->ifState
== LAP_OFFLINE
) {
267 dPrintf(D_M_NBP
,D_L_ERROR
,
268 ("nbp_input:FWDREQ: ifID offline (port %d)\n",
276 if (error_found
) /* the port is not correct */
279 if (!ifID
) { /* this packet is not for us, let the routing engine handle it */
280 routing_needed(m
, ifIDorig
, TRUE
);
286 * At this point, we have a valid Forward request for one of our
287 * directly connected port. Convert it to a NBP Lookup
290 nbp
->control
= NBP_LKUP
;
291 NET_ASSIGN(ddp
->dst_net
, 0);
295 /*### LD 01/18/94 Check if the dest is also the home zone. */
297 p
= nbp2zone(nbp
, gbuf_wptr(m
));
298 if ((p
== NULL
) || !(zno
= zt_find_zname(p
))) {
299 dPrintf(D_M_NBP
,D_L_WARNING
,
300 ("nbp_input: FWDRQ:zone not found\n"));
303 if (isZoneLocal((at_nvestr_t
*)p
))
304 zhome
= TRUE
; /* one of our ports is in destination zone */
305 if (!zt_get_zmcast(ifID
, p
, &mcastAddr
)) {
306 dPrintf(D_M_NBP
,D_L_ERROR
,
307 ("nbp_input: FDWREQ:zt_get_zmcast error\n"));
312 if (zhome
) { /*### LD 01/18/95 In case our home is here, call back nbp */
314 if (!(m2
= (gbuf_t
*)gbuf_copym((gbuf_t
*)m
))) {
315 dPrintf(D_M_NBP
,D_L_ERROR
,
316 ("nbp_input: FWDRQ:gbuf_copym failed\n"));
322 nbp
->control
= NBP_LKUP
;
323 NET_ASSIGN(ddp
->dst_net
, 0);
325 dPrintf(D_M_NBP
,D_L_INFO
,
326 ("nbp_input: FWDRQ:loop back for us\n"));
327 nbp_input(m2
, ifID_home
);
330 if (FDDI_OR_TOKENRING(ifID
->aa_ifp
->if_type
))
331 ddp_bit_reverse(&mcastAddr
);
332 ddp_router_output(m
, ifID
, ET_ADDR
,NULL
,NULL
, &mcastAddr
);
339 register int zno
; /* zone table entry numb */
340 register int ztind
; /* zone bitmap index into RT_entry */
341 register int ztbit
; /* zone bit to check within above index */
342 register int zhome
=0; /* true if home zone == destination zone */
344 register gbuf_t
*m2
, *m3
;
345 register int fromUs
= FALSE
;
346 register at_socket ourSkt
; /* originating skt */
348 /* for router & MH local only */
349 if ((!(MULTIHOME_MODE
&& FROM_US(ddp
))) && !ROUTING_MODE
) {
350 dPrintf(D_M_NBP
,D_L_USR2
,
351 ("nbp_input: BRREQ:non router or MH local\n"));
355 p
= nbp2zone(nbp
, gbuf_wptr(m
));
356 if ((p
== NULL
) || !(zno
= zt_find_zname(p
))) {
359 if (MULTIHOME_MODE
&& ifID
->ifRouterState
== NO_ROUTER
) {
360 ((at_nvestr_t
*)p
)->len
= 1;
361 ((at_nvestr_t
*)p
)->str
[0] = '*';
363 if (isZoneLocal((at_nvestr_t
*)p
)) {
364 zhome
= TRUE
; /* one of our ports is in destination zone */
366 if (FROM_US(ddp
)){ /* save, before we munge it */
368 ourSkt
= ddp
->src_socket
;
369 dPrintf(D_M_NBP
,D_L_USR2
,
370 ("nbp_input:BRRQ from us net:%d\n",
371 (int)NET_VALUE(ddp
->src_net
)));
373 /* from ZT_CLR_ZMAP */
376 ztbit
= 0x80 >> (i
% 8);
377 for (i
=0,rt
=RT_table
; i
<RT_maxentry
; i
++,rt
++) {
378 if (!(rt
->ZoneBitMap
[ztind
] & ztbit
)) /* if zone not in route, skip*/
380 /* dPrintf(D_M_NBP, D_L_USR3,
381 ("nbp_input: BRREQ: port:%d, entry %d\n",
385 ifID
= ifID_table
[rt
->NetPort
];
387 dPrintf(D_M_NBP
, D_L_ERROR
,
388 ("nbp_input:BRRQ: ifID %s\n",
389 !ifID
? "not found" : "invalid"));
394 ddp
->src_node
= ifID
->ifThisNode
.s_node
;
395 NET_ASSIGN(ddp
->src_net
, ifID
->ifThisNode
.s_net
);
396 ddp
->src_socket
= NBP_SOCKET
;
397 if (!(m2
= (gbuf_t
*)gbuf_copym((gbuf_t
*)m
))) {
398 dPrintf(D_M_NBP
,D_L_ERROR
,
399 ("nbp_input: BRREQ:gbuf_copym failed\n"));
405 /* nbp->tuple[0].enu_addr.socket = NBP_SOCKET; */
406 if (MULTIHOME_MODE
&& fromUs
) {
407 /* set the return address of the lookup to that of the
408 interface it's going out on so that replies come back
410 dPrintf(D_M_NBP
,D_L_USR3
,
411 ("nbp_input: BRREQ: src changed to %d.%d.%d\n",
412 ifID
->ifThisNode
.s_net
,
413 ifID
->ifThisNode
.s_node
, ourSkt
));
414 nbp
->tuple
[0].enu_addr
.net
= ifID
->ifThisNode
.s_net
;
415 nbp
->tuple
[0].enu_addr
.node
= ifID
->ifThisNode
.s_node
;
416 nbp
->tuple
[0].enu_addr
.socket
= ourSkt
;
417 ddp
->src_socket
= NBP_SOCKET
;
420 dPrintf(D_M_NBP
, D_L_USR3
,
421 ("nbp_input: BRREQ: not from us\n"));
423 dPrintf(D_M_NBP
, D_L_USR3
,
424 ("nbp_input dist:%d\n", rt
->NetDist
));
425 if (rt
->NetDist
== 0) { /* if direct connect, *we* do the LKUP */
426 nbp
->control
= NBP_LKUP
;
427 NET_ASSIGN(ddp
->dst_net
, 0);
429 if (!zt_get_zmcast(ifID
, p
, &mcastAddr
)) {
430 dPrintf(D_M_NBP
,D_L_ERROR
,
431 ("nbp_input: BRRQ:zt_get_zmcast error\n"));
434 if (FDDI_OR_TOKENRING(ifID
->aa_ifp
->if_type
))
435 ddp_bit_reverse(&mcastAddr
);
436 ddp_router_output(m2
, ifID
, ET_ADDR
, NULL
, NULL
, &mcastAddr
);
438 else { /* else fwd to router */
440 if (rt
->NetStart
== 0) /* if Ltalk */
441 NET_ASSIGN(ddp
->dst_net
, rt
->NetStop
);
443 NET_ASSIGN(ddp
->dst_net
, rt
->NetStart
);
444 nbp
->control
= NBP_FWDRQ
;
445 ddp_router_output(m2
, ifID
, AT_ADDR
,
446 rt
->NextIRNet
, rt
->NextIRNode
,
453 if (!(m3
= (gbuf_t
*)gbuf_copym((gbuf_t
*)m
))) {
454 dPrintf(D_M_NBP
,D_L_ERROR
,
455 ("nbp_input: BRREQ:gbuf_copym failed\n"));
462 nbp
->control
= NBP_LKUP
;
463 NET_ASSIGN(ddp
->dst_net
, 0);
465 dPrintf(D_M_NBP
,D_L_INFO
, ("nbp_input: BRRQ:loop back for us\n"));
466 nbp_input(m3
, ifID_home
);
472 if (!ROUTING_MODE
) /* for routers only! */
475 dPrintf(D_M_NBP
,D_L_WARNING
,
476 ("nbp_input: routing needed for LKUP_REPLY: from %d.%d\n",
477 NET_VALUE(ddp
->src_net
), ddp
->src_node
));
478 routing_needed(m
, ifID
, TRUE
);
483 dPrintf(D_M_NBP
,D_L_ERROR
,
484 ("nbp_input: unhandled pkt: type:%d\n", nbp
->control
));
486 routing_needed(m
, ifID
, TRUE
);
489 } /* switch control */
496 static int nbp_validate_n_hash (nbp_req
, wild_ok
, checkLocal
)
497 register nbp_req_t
*nbp_req
;
498 register int wild_ok
;
499 register int checkLocal
; /* if true check if local zone */
501 register at_nvestr_t
*object
, *type
, *zone
;
502 at_nbptuple_t
*tuple
;
503 register int i
, part_wild
;
505 tuple
= DATA_NBP(nbp_req
->request
)->tuple
;
510 net
= tuple
->enu_addr
.net
;
511 node
= tuple
->enu_addr
.node
;
512 skt
= tuple
->enu_addr
.socket
;
513 dPrintf(D_M_NBP_LOW
,D_L_USR4
,
514 ("nbp_validate: tuple addr:%d:%d:%d\n",net
,node
,skt
));
516 #endif /* COMMENTED_OUT */
518 /* tuple is in the compressed (no "filler") format */
519 object
= (at_nvestr_t
*)&tuple
->enu_entity
;
520 type
= (at_nvestr_t
*)(&object
->str
[object
->len
]);
521 zone
= (at_nvestr_t
*)(&type
->str
[type
->len
]);
523 if (object
->len
> NBP_NVE_STR_SIZE
|| type
->len
> NBP_NVE_STR_SIZE
||
524 zone
->len
> NBP_NVE_STR_SIZE
) {
525 dPrintf(D_M_NBP_LOW
, D_L_WARNING
,
526 ("nbp_val_n_hash: bad str len\n"));
533 char xzone
[35],xobject
[35],xtype
[35];
534 strncpy(xzone
,zone
->str
, zone
->len
);
535 strncpy(xobject
,object
->str
, object
->len
);
536 strncpy(xtype
,type
->str
, type
->len
);
537 xobject
[object
->len
] = '\0';
538 xzone
[zone
->len
] = '\0';
539 xtype
[type
->len
] = '\0';
540 dPrintf(D_M_NBP_LOW
, D_L_USR4
,
541 ("nbp_validate: looking for %s:%s@%s\n",
542 xobject
, xtype
, xzone
));
544 #endif /* NBP_DEBUG */
545 /* Is this request for our zone ?? */
546 nbp_req
->nve
.zone
.len
= zone
->len
;
547 nbp_req
->nve
.zone_hash
= 0;
548 bcopy(zone
->str
,nbp_req
->nve
.zone
.str
, zone
->len
);
550 if (checkLocal
&& !isZoneLocal(zone
)) {
552 strncpy(str
,zone
->str
,zone
->len
);
553 str
[zone
->len
] = '\0';
554 dPrintf(D_M_NBP_LOW
,D_L_WARNING
,
555 ("nbp_val_n_hash bad zone: %s\n", str
));
560 if (!DEFAULT_ZONE(zone
)) {
561 nbp_req
->nve
.zone_hash
= nbp_strhash(& nbp_req
->nve
.zone
);
564 nbp_req
->nve
.address
= tuple
->enu_addr
;
565 nbp_req
->nve
.object
.len
= object
->len
;
566 nbp_req
->nve
.object_hash
= 0;
567 if (object
->len
== 1 && (object
->str
[0] == NBP_ORD_WILDCARD
||
568 object
->str
[0] == NBP_SPL_WILDCARD
)) {
570 nbp_req
->flags
|= NBP_WILD_OBJECT
;
572 dPrintf(D_M_NBP_LOW
, D_L_WARNING
,
573 ("nbp_val_n_hash: wild not okay\n"));
578 for (i
= part_wild
= 0; (unsigned) i
<object
->len
; i
++) {
579 if (object
->str
[i
] == NBP_SPL_WILDCARD
)
582 dPrintf(D_M_NBP_LOW
, D_L_WARNING
,
583 ("nbp_val_n_hash: too many parts wild\n"));
589 dPrintf(D_M_NBP_LOW
, D_L_WARNING
,
590 ("nbp_val_n_hash: wild not okay2\n"));
594 nbp_req
->nve
.object
.str
[i
] = object
->str
[i
];
597 nbp_req
->nve
.object_hash
=
598 nbp_strhash(&nbp_req
->nve
.object
);
601 nbp_req
->nve
.type
.len
= type
->len
;
602 nbp_req
->nve
.type_hash
= 0;
603 if (type
->len
== 1 && (type
->str
[0] == NBP_ORD_WILDCARD
||
604 type
->str
[0] == NBP_SPL_WILDCARD
)) {
606 nbp_req
->flags
|= NBP_WILD_TYPE
;
608 dPrintf(D_M_NBP_LOW
, D_L_WARNING
,
609 ("nbp_val_n_hash: wild not okay3\n"));
614 for (i
= part_wild
= 0; (unsigned) i
<type
->len
; i
++) {
615 if (type
->str
[i
] == NBP_SPL_WILDCARD
)
618 dPrintf(D_M_NBP_LOW
, D_L_WARNING
,
619 ("nbp_val_n_hash: too many parts wild2\n"));
628 nbp_req
->nve
.type
.str
[i
] = type
->str
[i
];
631 nbp_req
->nve
.type_hash
=
632 nbp_strhash(&nbp_req
->nve
.type
);
636 char zone
[35],object
[35],type
[35];
637 strncpy(zone
,nbp_req
->nve
.zone
.str
, nbp_req
->nve
.zone
.len
);
638 strncpy(object
,nbp_req
->nve
.object
.str
, nbp_req
->nve
.object
.len
);
639 strncpy(type
,nbp_req
->nve
.type
.str
, nbp_req
->nve
.type
.len
);
640 object
[nbp_req
->nve
.object
.len
] = '\0';
641 zone
[nbp_req
->nve
.zone
.len
] = '\0';
642 type
[nbp_req
->nve
.type
.len
] = '\0';
643 dPrintf(D_M_NBP_LOW
,D_L_USR4
,
644 ("nbp_validate: after hash: %s:%s@%s\n",
645 object
, type
, zone
));
647 #endif /* NBP_DEBUG */
649 } /* nbp_validate_n_hash */
652 /* Upshifts in place */
653 static void nbp_upshift (str
, count
)
654 register u_char
*str
;
659 static unsigned char lower_case
[] =
660 {0x8a, 0x8c, 0x8d, 0x8e, 0x96, 0x9a, 0x9f, 0xbe,
661 0xbf, 0xcf, 0x9b, 0x8b, 0x88, 0};
662 static unsigned char upper_case
[] =
663 {0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0xae,
664 0xaf, 0xce, 0xcd, 0xcc, 0xcb, 0};
666 for (j
=0 ; j
<count
; j
++) {
668 if (ch
>= 'a' && ch
<= 'z')
669 str
[j
] = ch
+ 'A' - 'a';
671 for (i
=0; lower_case
[i
]; i
++)
672 if (ch
== lower_case
[i
])
673 str
[j
] = upper_case
[i
];
678 u_int
nbp_strhash (nvestr
)
679 register at_nvestr_t
*nvestr
;
681 /* upshift while hashing */
682 register u_int hash
= 0;
689 for (i
=0; (unsigned) i
< nvestr
->len
; i
+=sizeof(int)) {
690 len
= MIN((nvestr
->len
-i
), sizeof(int));
691 if (len
== sizeof(int))
692 bcopy(&(nvestr
->str
[i
]), &un
, sizeof(un
));
695 for ( ; (unsigned) i
<nvestr
->len
; i
++)
696 un
.h_4char
[i
% sizeof(int)] = nvestr
->str
[i
];
698 nbp_upshift (un
.h_4char
, len
);
705 static nve_entry_t
*nbp_search_nve (nbp_req
, ifID
)
706 register nbp_req_t
*nbp_req
;
707 register at_ifaddr_t
*ifID
; /* NULL ok */
709 register nve_entry_t
*nve_entry
;
713 char zone
[35],object
[35],type
[35];
714 strncpy(zone
,nbp_req
->nve
.zone
.str
, nbp_req
->nve
.zone
.len
);
715 strncpy(object
,nbp_req
->nve
.object
.str
, nbp_req
->nve
.object
.len
);
716 strncpy(type
,nbp_req
->nve
.type
.str
, nbp_req
->nve
.type
.len
);
717 object
[nbp_req
->nve
.object
.len
] = '\0';
718 zone
[nbp_req
->nve
.zone
.len
] = '\0';
719 type
[nbp_req
->nve
.type
.len
] = '\0';
720 dPrintf(D_M_NBP_LOW
, D_L_USR4
,
721 ("nbp_search: looking for %s:%s@%s resp:0x%x\n",object
,type
,zone
,
722 (u_int
) nbp_req
->response
));
724 #endif /* NBP_DEBUG */
725 ATDISABLE(nve_lock_pri
,NVE_LOCK
);
726 TAILQ_FOREACH(nve_entry
, &name_registry
, nve_link
) {
727 if ((nbp_req
->nve
.zone_hash
) &&
728 ((nbp_req
->nve
.zone_hash
!=
729 nve_entry
->zone_hash
) &&
730 (nbp_req
->nve
.zone_hash
!= hzonehash
)
733 dPrintf(D_M_NBP_LOW
,D_L_USR4
,
734 ("nbp_search: no match for zone, req hash:%x\n",
735 nbp_req
->nve
.zone_hash
));
738 else { /* for this entry's zone OR no zone in request or entry */
739 /* only in singleport mode (!MULTIPORT_MODE) with
740 empty PRAM can an entry have '*' for it's zone
742 at_nvestr_t
*ezone
=&nve_entry
->zone
;
743 at_nvestr_t
*rzone
=&nbp_req
->nve
.zone
;
744 if (!DEFAULT_ZONE(rzone
) && !DEFAULT_ZONE(ezone
)) {
745 if (nbp_strcmp (rzone
, ezone
, 0) != 0)
749 if (MULTIHOME_MODE
&& ifID
&&
750 (nve_entry
->address
.net
!=
751 ifID
->ifThisNode
.s_net
)) {
752 dPrintf(D_M_NBP
, D_L_USR4
,
753 ("nbp search ifID (%d) & req net (%d) not eq\n",
754 nve_entry
->address
.net
,
755 ifID
->ifThisNode
.s_net
));
759 dPrintf(D_M_NBP
, D_L_USR4
,
760 ("nbp search ifID (%d) & req net (%d) equal\n",
761 nve_entry
->address
.net
,
762 ifID
->ifThisNode
.s_net
));
766 if (!(nbp_req
->flags
& NBP_WILD_OBJECT
)) {
767 if ((nbp_req
->nve
.object_hash
) &&
768 (nbp_req
->nve
.object_hash
!=
769 nve_entry
->object_hash
))
772 if (nbp_strcmp (&nbp_req
->nve
.object
,
774 NBP_SPL_WILDCARD
) != 0)
780 if (!(nbp_req
->flags
& NBP_WILD_TYPE
)) {
781 if ((nbp_req
->nve
.type_hash
) &&
782 (nbp_req
->nve
.type_hash
!=nve_entry
->type_hash
))
785 if (nbp_strcmp (&nbp_req
->nve
.type
,
787 NBP_SPL_WILDCARD
) != 0)
795 char zone
[35],object
[35],type
[35];
797 strncpy(zone
,nbp_req
->nve
.zone
.str
, nbp_req
->nve
.zone
.len
);
798 strncpy(object
,nbp_req
->nve
.object
.str
, nbp_req
->nve
.object
.len
);
799 strncpy(type
,nbp_req
->nve
.type
.str
, nbp_req
->nve
.type
.len
);
800 object
[nbp_req
->nve
.object
.len
] = '\0';
801 zone
[nbp_req
->nve
.zone
.len
] = '\0';
802 type
[nbp_req
->nve
.type
.len
] = '\0';
803 dPrintf(D_M_NBP_LOW
, D_L_USR2
,
804 ("nbp_search: found %s:%s@%s net:%d\n",
805 object
, type
, zone
, (int)nve_entry
->address
.net
));
807 #endif /* NBP_DEBUG */
808 if (nbp_req
->func
!= NULL
) {
809 if ((*(nbp_req
->func
))(nbp_req
, nve_entry
) != 0) {
810 /* errno expected to be set by func */
811 ATENABLE(nve_lock_pri
,NVE_LOCK
);
815 ATENABLE(nve_lock_pri
,NVE_LOCK
);
819 ATENABLE(nve_lock_pri
,NVE_LOCK
);
823 } /* nbp_search_nve */
825 static int nbp_lkup_reply (nbp_req
, nve_entry
)
826 register nbp_req_t
*nbp_req
;
827 register nve_entry_t
*nve_entry
;
829 register at_nbptuple_t
*tuple
;
830 register int tuple_size
, buf_len
;
831 register int obj_len
, type_len
;
834 /* size of the current tuple we want to write... */
835 tuple_size
= nve_entry
->object
.len
+ 1 + /* object */
836 nve_entry
->type
.len
+ 1 + /* type */
838 sizeof (at_inet_t
) + 1; /* addr + enum */
840 buf_len
= ((nbp_req
->flags
& NBP_WILD_MASK
) ? DDP_DATA_SIZE
:tuple_size
);
841 if (nbp_req
->response
== NULL
) {
842 if (nbp_setup_resp (nbp_req
, buf_len
) != 0)
843 /* errno expected to be set by nbp_setup_resp() */
847 if ((nbp_req
->space_unused
< tuple_size
) ||
848 (DATA_NBP(nbp_req
->response
)->tuple_count
== NBP_TUPLE_MAX
)) {
849 if (nbp_send_resp (nbp_req
) != 0)
851 if (nbp_setup_resp (nbp_req
, buf_len
) != 0)
855 /* At this point, we have a response buffer that can accommodate the
856 * tuple we want to write. Write it!
858 tuple
= (at_nbptuple_t
*)gbuf_wptr(nbp_req
->response
);
859 tuple
->enu_addr
= nve_entry
->address
;
860 tuple
->enu_enum
= nve_entry
->enumerator
;
862 /* tuple is in the compressed (no "filler") format */
863 p
= (u_char
*)&tuple
->enu_entity
.object
;
864 obj_len
= nve_entry
->object
.len
+ 1;
865 bcopy(&nve_entry
->object
, p
, obj_len
);
867 type_len
= nve_entry
->type
.len
+ 1;
868 bcopy(&nve_entry
->type
, p
, type_len
);
873 nbp_req
->space_unused
-= tuple_size
;
874 gbuf_winc(nbp_req
->response
, tuple_size
);
876 /* increment the tuple count in header by 1 */
877 DATA_NBP(nbp_req
->response
)->tuple_count
++;
883 static int nbp_strcmp (str1
, str2
, embedded_wildcard
)
884 register at_nvestr_t
*str1
, *str2
;
885 register u_char embedded_wildcard
; /* If str1 may contain a character
886 * that's to be treated as an
887 * embedded wildcard, this character
888 * is it. Making this special case
889 * since for zone names, squiggly
890 * equal is not to be treated as a
896 register int reverse
= 0;
897 register int left_index
;
899 /* Embedded wildcard, if any, could only be in the first string (str1).
900 * returns 0 if two strings are equal (modulo case), -1 otherwise
903 if (str1
->len
== 0 || str2
->len
== 0) {
907 /* Wildcards are not allowed in str2.
909 * If str1 could potentially contain an embedded wildcard, since the
910 * embedded wildcard matches ZERO OR MORE characters, str1 can not be
911 * more than 1 character longer than str2.
913 * If str1 is not supposed to have embedded wildcards, the two strs
914 * must be of equal length.
916 if ((embedded_wildcard
&& (str2
->len
< (unsigned) (str1
->len
-1))) ||
917 (!embedded_wildcard
&& (str2
->len
!= str1
->len
))) {
921 for (i1
= i2
= left_index
= 0; (unsigned) i1
< str1
->len
;) {
925 if (embedded_wildcard
&& (ch1
==embedded_wildcard
)) {
926 /* hit the embedded wild card... start comparing from
927 * the other end of the string.
930 /* But, if embedded wildcard was the last character of
931 * the string, the two strings match, so return okay.
933 if (i1
== str1
->len
-1) {
943 nbp_upshift(&ch1
, 1);
944 nbp_upshift(&ch2
, 1);
952 if (i1
== left_index
) {
956 i1
++; i2
++; left_index
++;
963 static void nbp_setup_hdr (nbp_req
)
964 register nbp_req_t
*nbp_req
;
966 register at_ddp_t
*ddp
;
967 register at_nbp_t
*nbp
;
969 ddp
= DATA_DDP(nbp_req
->response
);
970 nbp
= DATA_NBP(nbp_req
->response
);
973 UAS_ASSIGN(ddp
->checksum
, 0);
974 ddp
->unused
= ddp
->hopcount
= 0;
976 switch(DATA_NBP(nbp_req
->request
)->control
) {
978 ddp
->dst_socket
= nbp_req
->nve
.address
.socket
;
979 ddp
->dst_node
= nbp_req
->nve
.address
.node
;
980 NET_ASSIGN(ddp
->dst_net
, nbp_req
->nve
.address
.net
);
981 nbp
->control
= NBP_LKUP_REPLY
;
984 nbp
->at_nbp_id
= DATA_NBP(nbp_req
->request
)->at_nbp_id
;
989 static int nbp_setup_resp (nbp_req
, tuples_size
)
990 register nbp_req_t
*nbp_req
;
991 register int tuples_size
;
993 int buf_size
= tuples_size
+ DDP_X_HDR_SIZE
+ NBP_HDR_SIZE
;
994 nbp_req
->response
= gbuf_alloc(AT_WR_OFFSET
+buf_size
, PRI_MED
);
995 if (nbp_req
->response
== NULL
) {
999 gbuf_rinc(nbp_req
->response
, AT_WR_OFFSET
);
1000 gbuf_wset(nbp_req
->response
, DDP_X_HDR_SIZE
+ NBP_HDR_SIZE
);
1001 nbp_setup_hdr(nbp_req
);
1003 DATA_NBP(nbp_req
->response
)->tuple_count
= 0;
1004 nbp_req
->space_unused
= tuples_size
;
1007 } /* nbp_setup_resp */
1010 static int nbp_send_resp (nbp_req
)
1011 register nbp_req_t
*nbp_req
;
1015 status
= ddp_output(&nbp_req
->response
, (at_socket
)NBP_SOCKET
, FALSE
);
1016 nbp_req
->response
= NULL
;
1021 void nbp_add_multicast(zone
, ifID
)
1025 char data
[ETHERNET_ADDR_LEN
];
1028 if (zone
->str
[0] == '*')
1033 strncpy(str
,zone
->str
,zone
->len
);
1034 str
[zone
->len
] = '\0';
1035 dPrintf(D_M_NBP_LOW
, D_L_USR3
,
1036 ("nbp_add_multi getting mc for %s\n", str
));
1038 zt_get_zmcast(ifID
, zone
, data
);
1039 if (FDDI_OR_TOKENRING(ifID
->aa_ifp
->if_type
))
1040 ddp_bit_reverse(data
);
1041 dPrintf(D_M_NBP_LOW
,D_L_USR3
,
1042 ("nbp_add_multi adding 0x%x%x port:%d ifID:0x%x if:%s\n",
1043 *(unsigned*)data
, (*(unsigned *)(data
+2))&0x0000ffff,
1044 i
, (u_int
) ifID
, ifID
->ifName
));
1046 bcopy((caddr_t
)data
, (caddr_t
)&ifID
->ZoneMcastAddr
, ETHERNET_ADDR_LEN
);
1047 (void)at_reg_mcast(ifID
, (caddr_t
)&ifID
->ZoneMcastAddr
);
1053 /* for SNMP, returns size in # of entries */
1055 register nve_entry_t
*nve
;
1058 ATDISABLE(nve_lock_pri
,NVE_LOCK
);
1059 for (nve
= TAILQ_FIRST(&name_registry
); nve
; nve
= TAILQ_NEXT(nve
, nve_link
), i
++)
1061 ATENABLE(nve_lock_pri
,NVE_LOCK
);
1065 getNbpTable(p
, s
, c
)
1067 int s
; /* starting entry */
1068 int c
; /* # entries to copy */
1070 /* for SNMP, returns section of nbp table */
1072 register nve_entry_t
*nve
;
1074 static int nextNo
=0; /* entry that *next points to */
1075 static nve_entry_t
*next
= (nve_entry_t
*)NULL
;
1077 if (s
&& next
&& nextNo
== s
) {
1082 nve
= TAILQ_FIRST(&name_registry
);
1084 ATDISABLE(nve_lock_pri
,NVE_LOCK
);
1085 for ( ; nve
&& c
; nve
= TAILQ_NEXT(nve
, nve_link
), p
++,i
++) {
1087 p
->nbpe_object
= nve
->object
;
1088 p
->nbpe_type
= nve
->type
;
1092 ATENABLE(nve_lock_pri
,NVE_LOCK
);
1097 next
= (nve_entry_t
*)NULL
;
1103 #define ZONES_PER_BLK 31 /* 31 fits within a 1k blk) */
1104 #define ZONE_BLK_SIZE ZONES_PER_BLK * sizeof(at_nvestr_t)
1106 int setLocalZones(newzones
, size
)
1107 at_nvestr_t
*newzones
;
1109 /* updates list of zones which are local to all active ports
1110 missing zones are not deleted, only missing zones are added.
1113 int bytesread
=0; /* #bytes read from tuple */
1116 at_nvestr_t
*pnve
, *pnew
= newzones
;
1119 if(!(lzones
= gbuf_alloc(ZONE_BLK_SIZE
, PRI_MED
)))
1121 gbuf_wset(lzones
,0);
1123 while (bytesread
< size
) { /* for each new zone */
1126 strncpy(str
,pnew
->str
,pnew
->len
);
1127 str
[pnew
->len
] = '\0';
1130 pnve
= (at_nvestr_t
*)gbuf_rptr(m
);
1132 for (i
=0; i
<lzonecnt
&& !dupe
; i
++,pnve
++) {
1133 if (i
&& !(i%ZONES_PER_BLK
))
1136 pnve
= (at_nvestr_t
*)gbuf_rptr(m
);
1140 if (pnew
->len
!= pnve
->len
)
1142 if (pnew
->len
> NBP_NVE_STR_SIZE
) {
1145 if (!strncmp(pnew
->str
, pnve
->str
, pnew
->len
)) {
1152 if (lzonecnt
&& !(lzonecnt%ZONES_PER_BLK
)) {
1153 if(!(gbuf_cont(m
) = gbuf_alloc(ZONE_BLK_SIZE
, PRI_MED
)))
1155 gbuf_wset(gbuf_cont(m
),0);
1156 pnve
= (at_nvestr_t
*)gbuf_rptr(gbuf_cont(m
));
1158 strncpy(pnve
->str
,pnew
->str
,pnew
->len
);
1159 pnve
->len
= pnew
->len
;
1162 bytesread
+= (pnew
->len
+1);
1163 pnew
= (at_nvestr_t
*) (((char *)pnew
) + pnew
->len
+ 1);
1165 /* showLocalZones1(); */
1178 if (!(pnve = getLocalZone(i))) {
1181 strncpy(str,pnve->str,pnve->len);
1182 str[pnve->len] = '\0';
1193 if (DEFAULT_ZONE(zone
))
1196 if (!(pnve
= getLocalZone(i
)))
1198 if (!nbp_strcmp(pnve
,zone
,0))
1205 #define NULL_PNVESTR (at_nvestr_t *) 0
1207 at_nvestr_t
*getLocalZone(zno
)
1208 int zno
; /* zone number in virtual list to
1209 return, 0 for first zone */
1210 /* returns pointer to a new local zone number zno,
1211 returns null when no zones left.
1215 ifz
.zone_index
= zno
;
1217 return(getRTRLocalZone(&ifz
));
1219 return(getSPLocalZone(zno
));
1223 at_nvestr_t
*getSPLocalZone(zno
)
1224 int zno
; /* zone number in virtual list to
1225 return, 0 for first zone */
1226 /* single port mode version */
1228 int curz
=0; /* current zone */
1234 pnve
= (at_nvestr_t
*)gbuf_rptr(m
);
1237 return(NULL_PNVESTR
);
1238 if ( zno
>=lzonecnt
)
1239 return(NULL_PNVESTR
);
1240 for (curz
=0; curz
<zno
; curz
++,pnve
++ ) {
1241 if ( curz
<lzonecnt
) {
1242 if (curz
&& !(curz%ZONES_PER_BLK
) ) {
1245 pnve
= (at_nvestr_t
*)gbuf_rptr(m
);
1248 return(NULL_PNVESTR
);
1251 if (pnve
->len
> NBP_NVE_STR_SIZE
) {
1252 return(NULL_PNVESTR
);
1256 return(NULL_PNVESTR
);
1261 /* The following functions are used in name registration and removal */
1263 int nbp_fillin_nve(entity
, nve
)
1264 at_entity_t
*entity
;
1269 if (entity
->object
.len
> NBP_NVE_STR_SIZE
||
1270 entity
->type
.len
> NBP_NVE_STR_SIZE
||
1271 entity
->zone
.len
> NBP_NVE_STR_SIZE
) {
1272 dPrintf(D_M_NBP_LOW
, D_L_WARNING
,
1273 ("nbp_fillin_nve: bad str len\n"));
1278 nve
->zone
= entity
->zone
;
1280 if (!isZoneLocal(&entity
->zone
)) {
1284 /* if there's no zone, '*' gets filled in when entry is created */
1285 if (!DEFAULT_ZONE(&entity
->zone
))
1286 nve
->zone_hash
= nbp_strhash(&nve
->zone
);
1288 nve
->object
= entity
->object
;
1289 nve
->object_hash
= 0;
1290 if (entity
->object
.len
== 1 &&
1291 (entity
->object
.str
[0] == NBP_ORD_WILDCARD
||
1292 entity
->object
.str
[0] == NBP_SPL_WILDCARD
)) {
1293 dPrintf(D_M_NBP_LOW
, D_L_WARNING
,
1294 ("nbp_fillin_nve: wildcard\n"));
1298 for (i
= 0; i
< entity
->object
.len
; i
++) {
1299 if (entity
->object
.str
[i
] == NBP_SPL_WILDCARD
) {
1300 dPrintf(D_M_NBP_LOW
, D_L_WARNING
,
1301 ("nbp_fillin_nve: wildcard2\n"));
1306 nve
->object_hash
= nbp_strhash(&nve
->object
);
1308 nve
->type
= entity
->type
;
1310 if (entity
->type
.len
== 1 &&
1311 (entity
->type
.str
[0] == NBP_ORD_WILDCARD
||
1312 entity
->type
.str
[0] == NBP_SPL_WILDCARD
)) {
1316 for (i
= 0; i
< entity
->type
.len
; i
++) {
1317 if (entity
->type
.str
[i
] == NBP_SPL_WILDCARD
) {
1318 dPrintf(D_M_NBP_LOW
, D_L_WARNING
,
1319 ("nbp_fillin_nve: wildcard3\n"));
1324 nve
->type_hash
= nbp_strhash(&nve
->type
);
1327 } /* nbp_fillin_nve */
1329 nve_entry_t
*nbp_find_nve(nve
)
1332 register nve_entry_t
*nve_entry
;
1334 ATDISABLE(nve_lock_pri
,NVE_LOCK
);
1335 TAILQ_FOREACH(nve_entry
, &name_registry
, nve_link
) {
1336 if (nve
->zone_hash
&&
1337 ((nve
->zone_hash
!= nve_entry
->zone_hash
) &&
1338 (nve
->zone_hash
!= hzonehash
))) {
1339 dPrintf(D_M_NBP_LOW
,D_L_USR4
,
1340 ("nbp_find_nve: no match for zone, req hash:%x\n",
1345 if ((nve
->object_hash
) &&
1346 (nve
->object_hash
!= nve_entry
->object_hash
))
1349 if ((nve
->type_hash
) &&
1350 (nve
->type_hash
!= nve_entry
->type_hash
))
1353 /* Found a match! */
1354 ATENABLE(nve_lock_pri
,NVE_LOCK
);
1357 ATENABLE(nve_lock_pri
,NVE_LOCK
);
1360 } /* nbp_find_nve */
1362 static int nbp_enum_gen (nve_entry
)
1363 register nve_entry_t
*nve_entry
;
1365 register int new_enum
= 0;
1366 register nve_entry_t
*ne
;
1368 ATDISABLE(nve_lock_pri
,NVE_LOCK
);
1370 TAILQ_FOREACH(ne
, &name_registry
, nve_link
) {
1371 if ((*(int *)&ne
->address
== *(int *)&nve_entry
->address
) &&
1372 (ne
->enumerator
== new_enum
)) {
1373 if (new_enum
== 255) {
1374 ATENABLE(nve_lock_pri
,NVE_LOCK
);
1375 return(EADDRNOTAVAIL
);
1383 ATENABLE(nve_lock_pri
,NVE_LOCK
);
1384 nve_entry
->enumerator
= new_enum
;
1388 int nbp_new_nve_entry(nve_entry
, ifID
)
1389 nve_entry_t
*nve_entry
;
1393 nve_entry_t
*new_entry
;
1397 if (!(valid_at_addr((at_inet_t
*)&nve_entry
->address
))) {
1398 dPrintf(D_M_NBP_LOW
, D_L_WARNING
,
1399 ("nbp_new_nve_entry: valid_at_addr\n"));
1402 if ((error
= nbp_enum_gen(nve_entry
)))
1405 nve_entry
->unique_nbp_id
= ++nbp_id_count
;
1407 /* Got an nve entry on hand.... allocate a buffer, copy the entry
1408 * on to it and stick it in the registry.
1410 if ((tag
= gbuf_alloc(sizeof(nve_entry_t
), PRI_HI
)) == NULL
){
1413 gbuf_wset(tag
, sizeof(nve_entry_t
));
1414 new_entry
= (nve_entry_t
*)gbuf_rptr(tag
);
1415 bcopy(nve_entry
, new_entry
, sizeof(nve_entry_t
));
1417 if (DEFAULT_ZONE(&nve_entry
->zone
)) {
1418 /* put actual zone name in entry instead of "*" */
1419 /* if single port mode and no zone name, then a router
1420 is down, so use pram zone name hint from elap cfg */
1421 if (!MULTIPORT_MODE
&& ifID_home
->ifZoneName
.str
[0] == '*') {
1422 zone
= &ifID_home
->startup_zone
;
1424 zone
= &ifID_home
->ifZoneName
;
1426 new_entry
->zone
= *zone
;
1427 if ( new_entry
->zone
.len
== 0 ) {
1428 new_entry
->zone
.str
[0] = '*';
1429 new_entry
->zone
.len
= 1;
1431 new_entry
->zone_hash
= nbp_strhash(&new_entry
->zone
);
1433 new_entry
->tag
= tag
;
1434 new_entry
->pid
= proc_selfpid();
1436 ATDISABLE(nve_lock_pri
,NVE_LOCK
);
1437 TAILQ_INSERT_TAIL(&name_registry
, new_entry
, nve_link
);
1438 ATENABLE(nve_lock_pri
,NVE_LOCK
);
1439 at_state
.flags
|= AT_ST_NBP_CHANGED
;
1443 char zone
[35],object
[35],type
[35];
1444 strncpy(zone
,new_entry
->zone
.str
, new_entry
->zone
.len
);
1445 strncpy(object
,new_entry
->object
.str
, new_entry
->object
.len
);
1446 strncpy(type
,new_entry
->type
.str
, new_entry
->type
.len
);
1447 object
[new_entry
->object
.len
] = '\0';
1448 zone
[new_entry
->zone
.len
] = '\0';
1449 type
[new_entry
->type
.len
] = '\0';
1450 dPrintf(D_M_NBP_LOW
, D_L_USR4
,
1451 ("nbp_insert: adding %s:%s@%s addr:%d.%d ",
1453 new_entry
->address
.net
, new_entry
->address
.node
));
1455 #endif /* NBP_DEBUG */
1457 nbp_add_multicast(&new_entry
->zone
, ifID
);
1459 } /* nbp_new_nve_entry */
1461 void nbp_delete_entry (nve_entry
)
1462 nve_entry_t
*nve_entry
;
1464 TAILQ_REMOVE(&name_registry
, nve_entry
, nve_link
);
1465 gbuf_freem(nve_entry
->tag
);
1466 at_state
.flags
|= AT_ST_NBP_CHANGED
;
1469 /* Registration of an NBP entity in multihoming mode, from AIOCNBPREG
1471 int nbp_mh_reg(nbpP
)
1475 at_ifaddr_t
*ifID
= 0;
1477 int finished
= FALSE
;
1479 if (nbp_fillin_nve(&nbpP
->name
, &nve
) != 0) {
1481 dPrintf(D_M_NBP_LOW
, D_L_WARNING
,
1482 ("nbp_mh_reg: bad tuple\n"));
1485 nve
.address
= nbpP
->addr
;
1486 nve
.ddptype
= nbpP
->ddptype
;
1488 if (DEFAULT_ZONE(&nbpP
->name
.zone
)) {
1489 /* multihoming mode with the default zone specified */
1491 /* now find the matching interfaces */
1492 TAILQ_FOREACH(ifID
, &at_ifQueueHd
, aa_link
) {
1493 if (nbpP
->addr
.net
|| nbpP
->addr
.node
) {
1494 /* if address is specified */
1495 if ((nbpP
->addr
.net
!= ifID
->ifThisNode
.s_net
||
1496 nbpP
->addr
.node
!= ifID
->ifThisNode
.s_node
))
1499 /* the address was specified, and
1500 we found the matching interface */
1503 /* address is not specified, so fill in
1504 the address for the interface */
1505 nve
.address
.net
= ifID
->ifThisNode
.s_net
;
1506 nve
.address
.node
= ifID
->ifThisNode
.s_node
;
1508 nve
.zone
= ifID
->ifZoneName
;
1509 nve
.zone_hash
= nbp_strhash(&nve
.zone
);
1510 if (nbp_find_nve(&nve
))
1512 if (nbp_new_nve_entry(&nve
, ifID
) == 0)
1515 if (registered
&& !nbpP
->addr
.net
&& !nbpP
->addr
.node
) {
1516 nbpP
->addr
.net
= ifID_home
->ifThisNode
.s_net
;
1517 nbpP
->addr
.node
= ifID_home
->ifThisNode
.s_node
;
1520 /* multihoming mode with a specific zone specified */
1521 /* see which segments (interfaces) are seeded for this zone */
1523 at_ifnames_t ifs_in_zone
;
1524 if (!(zno
= zt_find_zname(&nve
.zone
))) {
1525 dPrintf(D_M_NBP_LOW
, D_L_WARNING
,
1526 ("nbp_mh_reg: didn't find zone name\n"));
1529 getIfUsage(zno
-1, &ifs_in_zone
);
1531 /* now find the matching interfaces */
1532 TAILQ_FOREACH(ifID
, &at_ifQueueHd
, aa_link
) {
1533 if (!ifs_in_zone
.at_if
[ifID
->ifPort
])
1534 /* zone doesn't match */
1537 /* the zone matches, so unless the
1538 address is specified and doesn't
1539 match, we only need to do this once */
1542 if (nbpP
->addr
.net
|| nbpP
->addr
.node
) {
1543 /* address is specified */
1545 if ((nbpP
->addr
.net
!= ifID
->ifThisNode
.s_net
||
1546 nbpP
->addr
.node
!= ifID
->ifThisNode
.s_node
))
1549 /* the address was specified, and
1550 we found the matching interface */
1553 /* address is not specified, so fill in
1554 the address for the interface */
1555 nve
.address
.net
= ifID
->ifThisNode
.s_net
;
1556 nve
.address
.node
= ifID
->ifThisNode
.s_node
;
1558 if (nbp_find_nve(&nve
))
1560 if (nbp_new_nve_entry(&nve
, ifID
) == 0)
1562 if (registered
&& !nbpP
->addr
.net
&& !nbpP
->addr
.node
) {
1563 nbpP
->addr
.net
= ifID
->ifThisNode
.s_net
;
1564 nbpP
->addr
.node
= ifID
->ifThisNode
.s_node
;
1569 nbpP
->unique_nbp_id
= (registered
> 1)? 0: nve
.unique_nbp_id
;
1574 return(EADDRNOTAVAIL
);