xref: /titanic_52/usr/src/cmd/tsol/tnd/tnd.c (revision 137fc0ce181055ab4899162833a2b94bd6e3c359)
1f875b4ebSrica /*
2f875b4ebSrica  * CDDL HEADER START
3f875b4ebSrica  *
4f875b4ebSrica  * The contents of this file are subject to the terms of the
5f875b4ebSrica  * Common Development and Distribution License (the "License").
6f875b4ebSrica  * You may not use this file except in compliance with the License.
7f875b4ebSrica  *
8f875b4ebSrica  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9f875b4ebSrica  * or http://www.opensolaris.org/os/licensing.
10f875b4ebSrica  * See the License for the specific language governing permissions
11f875b4ebSrica  * and limitations under the License.
12f875b4ebSrica  *
13f875b4ebSrica  * When distributing Covered Code, include this CDDL HEADER in each
14f875b4ebSrica  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15f875b4ebSrica  * If applicable, add the following below this CDDL HEADER, with the
16f875b4ebSrica  * fields enclosed by brackets "[]" replaced with your own identifying
17f875b4ebSrica  * information: Portions Copyright [yyyy] [name of copyright owner]
18f875b4ebSrica  *
19f875b4ebSrica  * CDDL HEADER END
20f875b4ebSrica  */
21f875b4ebSrica 
22f875b4ebSrica /*
23f875b4ebSrica  *  Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24f875b4ebSrica  *  Use is subject to license terms.
25f875b4ebSrica  */
26f875b4ebSrica 
27f875b4ebSrica #pragma ident	"%Z%%M%	%I%	%E% SMI"
28f875b4ebSrica 
29f875b4ebSrica #include <sys/types.h>
30f875b4ebSrica #include <time.h>
31f875b4ebSrica #include <unistd.h>
32f875b4ebSrica #include <stdio.h>
33f875b4ebSrica #include <sys/fcntl.h>
34f875b4ebSrica #include <sys/stat.h>
35f875b4ebSrica #include <fcntl.h>
36f875b4ebSrica #include <locale.h>
37f875b4ebSrica #include <langinfo.h>
38f875b4ebSrica #include <search.h>
39f875b4ebSrica #include <tsol/label.h>
40f875b4ebSrica #include <errno.h>
41f875b4ebSrica #include <sys/tsol/tndb.h>
42f875b4ebSrica #include <sys/socket.h>
43f875b4ebSrica #include <netinet/in.h>
44f875b4ebSrica #include <arpa/inet.h>
45f875b4ebSrica #include <netdb.h>
46f875b4ebSrica #include <signal.h>
47f875b4ebSrica #include <sys/signal.h>
48f875b4ebSrica #include <string.h>
49f875b4ebSrica #include <stdlib.h>
50f875b4ebSrica #include <unistd.h>
51f875b4ebSrica #include <stdarg.h>
52f875b4ebSrica #include <syslog.h>
53f875b4ebSrica #include <ctype.h>
54f875b4ebSrica #include <pwd.h>
55f875b4ebSrica #include <grp.h>
56f875b4ebSrica #include <door.h>
57f875b4ebSrica #include <synch.h>
58f875b4ebSrica #include <sys/tsol/tsyscall.h>
59f875b4ebSrica #include <nss_dbdefs.h>
60f875b4ebSrica #include <libtsnet.h>
61f875b4ebSrica #include <zone.h>
62f875b4ebSrica 
63f875b4ebSrica #include "tnd.h"
64f875b4ebSrica 
65f875b4ebSrica static FILE *tnlog_open(char *);
66f875b4ebSrica static void usage();
67f875b4ebSrica static void parse_opts(int, char **);
68f875b4ebSrica static int check_debugl(int);
69f875b4ebSrica static void load_tp();
70f875b4ebSrica static void load_tp_entry();
71f875b4ebSrica static void tnd_serve();
72f875b4ebSrica static void detachfromtty();
73f875b4ebSrica static void terminate();
74f875b4ebSrica static void noop();
75f875b4ebSrica static char *gettime();
76f875b4ebSrica static int isnumber(char *);
77f875b4ebSrica static void poll_now();
78f875b4ebSrica static int nss_get_tp();
79f875b4ebSrica static int nss_get_rh();
80f875b4ebSrica static void timer();
81f875b4ebSrica static void load_rh_marked();
82f875b4ebSrica static int rhtable_search_and_update(struct tsol_rhent *ent, int duplflag);
83f875b4ebSrica static int is_better_match(in_addr_t newaddr, int indx, tnrh_tlb_t *tlbt);
84f875b4ebSrica static int walk_cache_table(in_addr_t newaddr, char *name,
85f875b4ebSrica     int indx, tnd_tnrhdb_t *src);
86f875b4ebSrica static tnrh_tlb_t *lookup_cache_table(in_addr_t addr);
87f875b4ebSrica static int update_cache_table(tsol_rhent_t *ent, tnd_tnrhdb_t *src);
88f875b4ebSrica static void update_rh_entry(int op, struct tsol_rhent *rhentp);
89f875b4ebSrica static int handle_unvisited_nodes();
90f875b4ebSrica static in_addr_t rh_index_to_mask(uint_t masklen);
91f875b4ebSrica static tnrh_tlb_ipv6_t *lookup_cache_table_v6(in6_addr_t addr);
92f875b4ebSrica static in6_addr_t *rh_index_to_mask_v6(uint_t masklen, in6_addr_t *bitmask);
93f875b4ebSrica static void load_rh_marked_v6();
94f875b4ebSrica static int
95f875b4ebSrica     rhtable_search_and_update_v6(struct tsol_rhent *ent, int duplflag);
96f875b4ebSrica static int walk_cache_table_v6(in6_addr_t newaddr, char *name,
97f875b4ebSrica     int indx, tnd_tnrhdb_t *src);
98f875b4ebSrica static int update_cache_table_v6(tsol_rhent_t *ent, tnd_tnrhdb_t *src);
99f875b4ebSrica static int handle_unvisited_nodes_v6();
100f875b4ebSrica 
101f875b4ebSrica #ifdef DEBUG
102f875b4ebSrica static void print_entry(tsol_rhent_t *ent, int af);
103f875b4ebSrica static void print_tlbt(tnrh_tlb_t *tlbt);
104f875b4ebSrica static void rhtable_print();
105f875b4ebSrica static void cachetable_print();
106f875b4ebSrica static void rhtable_walk(void (*action)());
107f875b4ebSrica static void cachetable_print_v6();
108f875b4ebSrica static void rhtable_print_v6();
109f875b4ebSrica static void rhtable_walk_v6(void (*action)());
110f875b4ebSrica #endif /* DEBUG */
111f875b4ebSrica 
112f875b4ebSrica /*
113f875b4ebSrica  * The following constants and structures and the functions
114f875b4ebSrica  * that operate on them are similar to the ip_ire.c and ip6_ire.c
115f875b4ebSrica  * code in the kernel.
116f875b4ebSrica  */
117f875b4ebSrica #define	TNRH_TABLE_HASH_SIZE 256
118f875b4ebSrica #define	IP_ABITS 32
119f875b4ebSrica #define	IP_MASK_TABLE_SIZE (IP_ABITS + 1)
120f875b4ebSrica #define	RH_HOST_MASK (in_addr_t)0xffffffffU
121f875b4ebSrica 
122f875b4ebSrica #define	IPV6_ABITS 128
123f875b4ebSrica #define	IPV6_MASK_TABLE_SIZE (IPV6_ABITS + 1)
124f875b4ebSrica #define	s6_addr8 _S6_un._S6_u8
125f875b4ebSrica #define	s6_addr32 _S6_un._S6_u32
126f875b4ebSrica 
127f875b4ebSrica /*
128f875b4ebSrica  * Exclusive-or the 6 bytes that are likely to contain the MAC
129f875b4ebSrica  * address. Assumes table_size does not exceed 256.
130f875b4ebSrica  * Assumes EUI-64 format for good hashing.
131f875b4ebSrica  */
132f875b4ebSrica #define	TNRH_ADDR_HASH_V6(addr)				\
133f875b4ebSrica 	(((addr).s6_addr8[8] ^ (addr).s6_addr8[9] ^	\
134f875b4ebSrica 	(addr).s6_addr8[10] ^ (addr).s6_addr8[13] ^	\
135f875b4ebSrica 	(addr).s6_addr8[14] ^ (addr).s6_addr8[15]) % TNRH_TABLE_HASH_SIZE)
136f875b4ebSrica 
137f875b4ebSrica #define	TNRH_ADDR_MASK_HASH_V6(addr, mask)	\
138f875b4ebSrica 	((((addr).s6_addr8[8] & (mask).s6_addr8[8]) ^	\
139f875b4ebSrica 	((addr).s6_addr8[9] & (mask).s6_addr8[9]) ^	\
140f875b4ebSrica 	((addr).s6_addr8[10] & (mask).s6_addr8[10]) ^	\
141f875b4ebSrica 	((addr).s6_addr8[13] & (mask).s6_addr8[13]) ^	\
142f875b4ebSrica 	((addr).s6_addr8[14] & (mask).s6_addr8[14]) ^	\
143f875b4ebSrica 	((addr).s6_addr8[15] & (mask).s6_addr8[15])) % TNRH_TABLE_HASH_SIZE)
144f875b4ebSrica 
145f875b4ebSrica /* Mask comparison: is IPv6 addr a, and'ed with mask m, equal to addr b? */
146f875b4ebSrica #define	V6_MASK_EQ(a, m, b)	\
147f875b4ebSrica 	((((a).s6_addr32[0] & (m).s6_addr32[0]) == (b).s6_addr32[0]) && \
148f875b4ebSrica 	(((a).s6_addr32[1] & (m).s6_addr32[1]) == (b).s6_addr32[1]) &&  \
149f875b4ebSrica 	(((a).s6_addr32[2] & (m).s6_addr32[2]) == (b).s6_addr32[2]) &&  \
150f875b4ebSrica 	(((a).s6_addr32[3] & (m).s6_addr32[3]) == (b).s6_addr32[3]))
151f875b4ebSrica 
152f875b4ebSrica 
153f875b4ebSrica const in6_addr_t ipv6_all_zeros = { 0, 0, 0, 0 };
154f875b4ebSrica 
155f875b4ebSrica /*
156f875b4ebSrica  * This is a table of hash tables to keep
157f875b4ebSrica  * all the name service entries. We don't have
158f875b4ebSrica  * a separate hash bucket structure, instead mantain
159f875b4ebSrica  * a pointer to the hash chain.
160f875b4ebSrica  */
161f875b4ebSrica tnd_tnrhdb_t **tnrh_entire_table[IP_MASK_TABLE_SIZE];
162f875b4ebSrica tnd_tnrhdb_t **tnrh_entire_table_v6[IPV6_MASK_TABLE_SIZE];
163f875b4ebSrica 
164f875b4ebSrica /* reader/writer lock for tnrh_entire_table */
165f875b4ebSrica rwlock_t entire_rwlp;
166f875b4ebSrica rwlock_t entire_rwlp_v6;
167f875b4ebSrica 
168f875b4ebSrica 
169f875b4ebSrica /*
170f875b4ebSrica  * This is a hash table which keeps fully resolved
171f875b4ebSrica  * tnrhdb entries <IP address, Host type>. We don't have
172f875b4ebSrica  * a separate hash bucket structure, instead
173f875b4ebSrica  * mantain a pointer to the hash chain.
174f875b4ebSrica  */
175f875b4ebSrica tnrh_tlb_t *tnrh_cache_table[TNRH_TABLE_HASH_SIZE];
176f875b4ebSrica tnrh_tlb_ipv6_t *tnrh_cache_table_v6[TNRH_TABLE_HASH_SIZE];
177f875b4ebSrica 
178f875b4ebSrica /* reader/writer lock for tnrh_cache_table */
179f875b4ebSrica rwlock_t cache_rwlp;
180f875b4ebSrica rwlock_t cache_rwlp_v6;
181f875b4ebSrica 
182f875b4ebSrica FILE	 *logf;
183f875b4ebSrica int	 debugl = 0;
184f875b4ebSrica int	 poll_interval = TND_DEF_POLL_TIME;
185f875b4ebSrica int	 delay_poll_flag = 0;
186f875b4ebSrica 
187f875b4ebSrica void	*tp_tree;
188f875b4ebSrica 
189f875b4ebSrica #define	_SZ_TIME_BUF 100
190f875b4ebSrica char time_buf[_SZ_TIME_BUF];
191f875b4ebSrica 
192f875b4ebSrica #define	cprint(s, param) { \
193f875b4ebSrica 		register FILE *consl; \
194f875b4ebSrica \
195f875b4ebSrica 		if ((consl = fopen("/dev/msglog", "w")) != NULL) { \
196f875b4ebSrica 		    setbuf(consl, NULL); \
197f875b4ebSrica 		    (void) fprintf(consl, "tnd: "); \
198f875b4ebSrica 		    (void) fprintf(consl, s, param); \
199f875b4ebSrica 		    (void) fclose(consl); \
200f875b4ebSrica 			} \
201f875b4ebSrica 	    }
202f875b4ebSrica 
203f875b4ebSrica #define	RHENT_BUF_SIZE 300
204f875b4ebSrica #define	TPENT_BUF_SIZE 2000
205f875b4ebSrica 
206f875b4ebSrica /* 128 privs * (24 bytes + 1 deliminator)= 3200 bytes + 1200 cushion */
207f875b4ebSrica #define	STRING_PRIVS_SIZE 4800
208f875b4ebSrica #define	ID_ENT_SIZE 500
209f875b4ebSrica 
210*137fc0ceSrica int
211f875b4ebSrica main(int argc, char **argv)
212f875b4ebSrica {
213f875b4ebSrica 
214f875b4ebSrica 
215f875b4ebSrica 	const ucred_t	*uc = NULL;
216f875b4ebSrica 	const priv_set_t	*pset;
217f875b4ebSrica 	struct sigaction act;
218f875b4ebSrica 
219f875b4ebSrica 	/* set the locale for only the messages system (all else is clean) */
220f875b4ebSrica 	(void) setlocale(LC_ALL, "");
221f875b4ebSrica #ifndef TEXT_DOMAIN			/* Should be defined by cc -D */
222f875b4ebSrica #define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it weren't */
223f875b4ebSrica #endif
224f875b4ebSrica 	(void) textdomain(TEXT_DOMAIN);
225f875b4ebSrica 
226f875b4ebSrica 	if (getzoneid() != GLOBAL_ZONEID) {
227f875b4ebSrica 		syslog(LOG_ERR,	"can not run tnd from a local zone");
228f875b4ebSrica 		exit(-1);
229f875b4ebSrica 	}
230f875b4ebSrica 
231f875b4ebSrica 
232f875b4ebSrica 	if (((uc = ucred_get(getpid())) == NULL) ||
233f875b4ebSrica 	    ((pset = ucred_getprivset(uc, PRIV_EFFECTIVE)) == NULL)) {
234f875b4ebSrica 		syslog(LOG_ERR,	"don't have privilege set");
235f875b4ebSrica 		exit(-1);
236f875b4ebSrica 	}
237f875b4ebSrica 
238f875b4ebSrica 	if (!priv_ismember(pset, PRIV_SYS_NET_CONFIG)) {
239f875b4ebSrica 		syslog(LOG_ERR,	"don't have privilege to run tnd");
240f875b4ebSrica 		exit(-1);
241f875b4ebSrica 	}
242f875b4ebSrica 
243f875b4ebSrica 
244f875b4ebSrica 	/* parse command line options */
245f875b4ebSrica 	(void) parse_opts(argc, argv);
246f875b4ebSrica 
247f875b4ebSrica 	/*
248f875b4ebSrica 	 * Initialize reader/writer locks. To be
249f875b4ebSrica 	 * used within this process only.
250f875b4ebSrica 	 */
251f875b4ebSrica 	if ((rwlock_init(&entire_rwlp, USYNC_THREAD, 0) != 0) ||
252f875b4ebSrica 	    (rwlock_init(&entire_rwlp_v6, USYNC_THREAD, 0) != 0) ||
253f875b4ebSrica 	    (rwlock_init(&cache_rwlp, USYNC_THREAD, 0) != 0) ||
254f875b4ebSrica 	    (rwlock_init(&cache_rwlp_v6, USYNC_THREAD, 0) != 0)) {
255f875b4ebSrica 		syslog(LOG_ERR, "cannot initialize lock");
256f875b4ebSrica 		exit(-1);
257f875b4ebSrica 	}
258f875b4ebSrica 
259f875b4ebSrica 	/* catch the usual termination signals for graceful exit */
260f875b4ebSrica 	(void) sigset(SIGINT, terminate);
261f875b4ebSrica 	(void) sigset(SIGTERM, terminate);
262f875b4ebSrica 	(void) sigset(SIGQUIT, terminate);
263f875b4ebSrica 	(void) sigset(SIGUSR1, noop);
264f875b4ebSrica 
265f875b4ebSrica 	act.sa_handler = timer;
266f875b4ebSrica 	act.sa_flags = SA_RESTART;
267f875b4ebSrica 	(void *) sigemptyset(&act.sa_mask);
268f875b4ebSrica 	(void *) sigaddset(&act.sa_mask, SIGALRM);
269f875b4ebSrica 	(void *) sigaddset(&act.sa_mask, SIGHUP);
270f875b4ebSrica 	(void *) sigaction(SIGALRM, &act, NULL);
271f875b4ebSrica 	(void *) sigaction(SIGHUP, &act, NULL);
272f875b4ebSrica 
273f875b4ebSrica 	if (debugl == MAX_TND_DEBUG) {
274f875b4ebSrica 		(void) fprintf(logf, "%s : ", gettime());
275f875b4ebSrica 		(void) fprintf(logf, gettext("tnd started. pid= %d\n"),
276f875b4ebSrica 		    getpid());
277f875b4ebSrica 		(void) fprintf(logf, "%s : ", gettime());
278f875b4ebSrica 		(void) fprintf(logf,
279f875b4ebSrica 		    gettext("max level debugging! not forking\n"));
280f875b4ebSrica 		(void) fflush(logf);
281f875b4ebSrica 	} else {
282f875b4ebSrica 		detachfromtty();
283f875b4ebSrica 	}
284f875b4ebSrica 
285f875b4ebSrica 	if (!delay_poll_flag) {
286f875b4ebSrica 		(void) sigprocmask(SIG_BLOCK, &act.sa_mask, NULL);
287f875b4ebSrica 		timer();
288f875b4ebSrica 		(void) sigprocmask(SIG_UNBLOCK, &act.sa_mask, NULL);
289f875b4ebSrica 	}
290f875b4ebSrica 
291f875b4ebSrica 	if (debugl != MAX_TND_DEBUG) {
292f875b4ebSrica 		(void) sigsend(P_PID, getppid(), SIGUSR1);
293f875b4ebSrica 	}
294f875b4ebSrica 
295f875b4ebSrica 	(void) tnd_serve();
296f875b4ebSrica 
297f875b4ebSrica 	/* NOT REACHED */
298f875b4ebSrica 	return (0);
299f875b4ebSrica }
300f875b4ebSrica 
301f875b4ebSrica 
302f875b4ebSrica /*
303f875b4ebSrica  * Compare addresses after masking off unneeded bits.
304f875b4ebSrica  * We do this to handle addresses where prefix_len is
305f875b4ebSrica  * less than the bit length.
306f875b4ebSrica  */
307f875b4ebSrica static int
308f875b4ebSrica rhaddr_compar_mask(struct sockaddr_in *tp1, struct tnd_tnrhdb_c *tp2, int i)
309f875b4ebSrica {
310f875b4ebSrica 	struct sockaddr_in *saddrp;
311f875b4ebSrica 	in_addr_t tmpmask = rh_index_to_mask(i);
312f875b4ebSrica 
313f875b4ebSrica 	saddrp = (struct sockaddr_in *)(&tp2->rh_ent.rh_address.ip_addr_v4);
314f875b4ebSrica 
315f875b4ebSrica #ifdef DEBUG
316f875b4ebSrica 	(void) fprintf(logf, gettext("rhaddr_compar_mask mask = 0x%4x, \
317f875b4ebSrica 	    tp1 = 0x%4x, tp2 = 0x%4x\n"), tmpmask, (tp1->sin_addr),
318f875b4ebSrica 	    (saddrp->sin_addr.s_addr & tmpmask));
319f875b4ebSrica 	(void) fprintf(logf, gettext("rhaddr_compar_mask return = %d\n"),
320f875b4ebSrica 	    (tp1->sin_addr.s_addr == (saddrp->sin_addr.s_addr & tmpmask)));
321f875b4ebSrica #endif
322f875b4ebSrica 	return (tp1->sin_addr.s_addr == (saddrp->sin_addr.s_addr & tmpmask));
323f875b4ebSrica }
324f875b4ebSrica 
325f875b4ebSrica 
326f875b4ebSrica /*
327f875b4ebSrica  * we use this where exact match is needed.
328f875b4ebSrica  */
329f875b4ebSrica static int
330f875b4ebSrica rhaddr_compar(struct sockaddr_in *tp1, struct tnd_tnrhdb_c *tp2)
331f875b4ebSrica {
332f875b4ebSrica 	struct sockaddr_in *saddrp;
333f875b4ebSrica 
334f875b4ebSrica 	saddrp = (struct sockaddr_in *)(&tp2->rh_ent.rh_address.ip_addr_v4);
335f875b4ebSrica 
336f875b4ebSrica #ifdef DEBUG
337f875b4ebSrica 	(void) fprintf(logf, gettext("\t tp1 saddrp IP : %s %s\n"),
338f875b4ebSrica 	    inet_ntoa(tp1->sin_addr), inet_ntoa(saddrp->sin_addr));
339f875b4ebSrica #endif
340f875b4ebSrica 
341f875b4ebSrica 	return (tp1->sin_addr.s_addr == saddrp->sin_addr.s_addr);
342f875b4ebSrica }
343f875b4ebSrica 
344f875b4ebSrica /*
345f875b4ebSrica  * Compare v6 addresses after masking off unneeded bits.
346f875b4ebSrica  * We do this to handle addresses where prefix_len is
347f875b4ebSrica  * less than the bit length.
348f875b4ebSrica  */
349f875b4ebSrica static int
350f875b4ebSrica rhaddr_compar_mask_v6(struct sockaddr_in6 *tp1, struct tnd_tnrhdb_c *tp2, int i)
351f875b4ebSrica {
352f875b4ebSrica 	struct sockaddr_in6 *saddrp;
353f875b4ebSrica 	in6_addr_t tmpmask;
354f875b4ebSrica 
355f875b4ebSrica 	(void) rh_index_to_mask_v6(i, &tmpmask);
356f875b4ebSrica 	saddrp = (struct sockaddr_in6 *)(&tp2->rh_ent.rh_address.ip_addr_v6);
357f875b4ebSrica 	return (V6_MASK_EQ(tp1->sin6_addr, tmpmask, saddrp->sin6_addr));
358f875b4ebSrica }
359f875b4ebSrica 
360f875b4ebSrica /*
361f875b4ebSrica  * we use this where v6 exact match is needed.
362f875b4ebSrica  */
363f875b4ebSrica static int
364f875b4ebSrica rhaddr_compar_v6(struct sockaddr_in6 *tp1, struct tnd_tnrhdb_c *tp2)
365f875b4ebSrica {
366f875b4ebSrica 	struct sockaddr_in6 *saddrp;
367f875b4ebSrica 
368f875b4ebSrica 	saddrp = (struct sockaddr_in6 *)(&tp2->rh_ent.rh_address.ip_addr_v6);
369f875b4ebSrica 	return (IN6_ARE_ADDR_EQUAL(&tp1->sin6_addr, &saddrp->sin6_addr));
370f875b4ebSrica }
371f875b4ebSrica 
372f875b4ebSrica static int
373f875b4ebSrica get_hashvalue(in_addr_t addr)
374f875b4ebSrica {
375f875b4ebSrica 	unsigned char *bp;
376f875b4ebSrica 
377f875b4ebSrica 	bp = (unsigned char *) &addr;
378f875b4ebSrica 	return ((bp[0] ^ bp[1] ^ bp[2] ^ bp[3]) % TNRH_TABLE_HASH_SIZE);
379f875b4ebSrica }
380f875b4ebSrica 
381f875b4ebSrica /*
382f875b4ebSrica  * Convert length for a mask to the mask.
383f875b4ebSrica  */
384f875b4ebSrica static in_addr_t
385f875b4ebSrica rh_index_to_mask(uint_t masklen)
386f875b4ebSrica {
387f875b4ebSrica 	if (masklen == 0)
388f875b4ebSrica 		return (0);
389f875b4ebSrica 	return (htonl(RH_HOST_MASK << (IP_ABITS - masklen)));
390f875b4ebSrica }
391f875b4ebSrica 
392f875b4ebSrica /*
393f875b4ebSrica  * Convert length for a mask to the mask.
394f875b4ebSrica  * Returns the argument bitmask.
395f875b4ebSrica  */
396f875b4ebSrica static in6_addr_t *
397f875b4ebSrica rh_index_to_mask_v6(uint_t masklen, in6_addr_t *bitmask)
398f875b4ebSrica {
399f875b4ebSrica 	uint32_t *ptr;
400f875b4ebSrica 
401f875b4ebSrica 	*bitmask = ipv6_all_zeros;
402f875b4ebSrica 
403f875b4ebSrica 	ptr = (uint32_t *)bitmask;
404f875b4ebSrica 	while (masklen > 32) {
405f875b4ebSrica 		*ptr++ = 0xffffffffU;
406f875b4ebSrica 		masklen -= 32;
407f875b4ebSrica 	}
408f875b4ebSrica 	*ptr = htonl(0xffffffffU << (32 - masklen));
409f875b4ebSrica 	return (bitmask);
410f875b4ebSrica }
411f875b4ebSrica 
412f875b4ebSrica 
413f875b4ebSrica static void
414f875b4ebSrica parse_opts(argc, argv)
415f875b4ebSrica 	int argc;
416f875b4ebSrica 	char **argv;
417f875b4ebSrica {
418f875b4ebSrica 	char *logfile = TNDLOG;
419f875b4ebSrica 	extern char *optarg;
420f875b4ebSrica 	int c;
421f875b4ebSrica 
422f875b4ebSrica 	while ((c = getopt(argc, argv, "d:f:p:n")) != EOF)
423f875b4ebSrica 	    switch (c) {
424f875b4ebSrica 	    case 'd':
425f875b4ebSrica 		if (isnumber(optarg)) {
426f875b4ebSrica 		    debugl = atoi(optarg);
427f875b4ebSrica 		    if (check_debugl(debugl) == -1)
428f875b4ebSrica 		    debugl = 1; /* default to 1 */
429f875b4ebSrica 		} else {
430f875b4ebSrica 		    usage();
431f875b4ebSrica 		    exit(1);
432f875b4ebSrica 		}
433f875b4ebSrica 		break;
434f875b4ebSrica 	    case 'f':
435f875b4ebSrica 		logfile = optarg;
436f875b4ebSrica 		break;
437f875b4ebSrica 	    case 'p':
438f875b4ebSrica 		if (isnumber(optarg)) {
439f875b4ebSrica 		    poll_interval = atoi(optarg);
440f875b4ebSrica 		    if (poll_interval == 0)
441f875b4ebSrica 			usage();
442f875b4ebSrica 		} else {
443f875b4ebSrica 		    usage();
444f875b4ebSrica 		}
445f875b4ebSrica 		break;
446f875b4ebSrica 	    case 'n':
447f875b4ebSrica 		delay_poll_flag = 1;
448f875b4ebSrica 		break;
449f875b4ebSrica 	    case '?':
450f875b4ebSrica 		usage();
451f875b4ebSrica 	    }
452f875b4ebSrica 
453f875b4ebSrica 	logf = tnlog_open(logfile);
454f875b4ebSrica }
455f875b4ebSrica 
456f875b4ebSrica static int
457f875b4ebSrica check_debugl(debug_level)
458f875b4ebSrica 	int debug_level;
459f875b4ebSrica {
460f875b4ebSrica 	if (debug_level > MAX_TND_DEBUG) {
461f875b4ebSrica 	    if ((debugl > 0) && (logf != NULL)) {
462f875b4ebSrica 		(void) fprintf(logf, "%s : ", gettime());
463f875b4ebSrica 		(void) fprintf(logf,
464f875b4ebSrica 		    gettext("invalid debug level: %d, not changed!\n"),
465f875b4ebSrica 			debug_level);
466f875b4ebSrica 		(void) fflush(logf);
467f875b4ebSrica 	    }
468f875b4ebSrica 	    cprint("invalid debug level: %d, not changed!\n",
469f875b4ebSrica 		debug_level);
470f875b4ebSrica 	    return (-1);
471f875b4ebSrica 	}
472f875b4ebSrica 	return (0);
473f875b4ebSrica }
474f875b4ebSrica 
475f875b4ebSrica static FILE *
476f875b4ebSrica tnlog_open(logfile)
477f875b4ebSrica 	char *logfile;
478f875b4ebSrica {
479f875b4ebSrica 	FILE *fp;
480f875b4ebSrica 
481f875b4ebSrica 	if ((fp = fopen(logfile, "a")) == NULL) {
482f875b4ebSrica 		syslog(LOG_ERR, "unable to open logfile %s",
483f875b4ebSrica 			logfile);
484f875b4ebSrica 		exit(-1);
485f875b4ebSrica 	}
486f875b4ebSrica 	(void) fprintf(fp, "%s : ", gettime());
487f875b4ebSrica 	(void) fprintf(fp, gettext("tnd starting\n"));
488f875b4ebSrica 
489f875b4ebSrica 	return (fp);
490f875b4ebSrica }
491f875b4ebSrica 
492f875b4ebSrica static void
493f875b4ebSrica detachfromtty()
494f875b4ebSrica {
495f875b4ebSrica 	pid_t tnd_pid;
496f875b4ebSrica 
497f875b4ebSrica 	(void) close(0);
498f875b4ebSrica 	(void) close(1);
499f875b4ebSrica 	(void) close(2);
500f875b4ebSrica 	switch (tnd_pid = fork()) {
501f875b4ebSrica 	case (pid_t)-1:
502f875b4ebSrica 		if (debugl && (logf != NULL)) {
503f875b4ebSrica 			(void) fprintf(logf, "%s : ", gettime());
504f875b4ebSrica 			(void) fprintf(logf,
505f875b4ebSrica 			    gettext("fork() failed: %s\n"), strerror(errno));
506f875b4ebSrica 			(void) fflush(logf);
507f875b4ebSrica 		}
508f875b4ebSrica 		cprint("fork() failed: %s\n", strerror(errno));
509f875b4ebSrica 		break;
510f875b4ebSrica 	case 0:
511f875b4ebSrica 		break;
512f875b4ebSrica 	default:
513f875b4ebSrica 		if (debugl && (logf != NULL)) {
514f875b4ebSrica 			(void) fprintf(logf, "%s : ", gettime());
515f875b4ebSrica 			(void) fprintf(logf,
516f875b4ebSrica 			    gettext("tnd started. pid= %d\n"), tnd_pid);
517f875b4ebSrica 			(void) fflush(logf);
518f875b4ebSrica 		}
519f875b4ebSrica 		/*
520f875b4ebSrica 		 * Suspend parent till child signals it. We catch the signal
521f875b4ebSrica 		 * in order to return correct exit value.
522f875b4ebSrica 		 */
523f875b4ebSrica 
524f875b4ebSrica 		(void) pause();
525f875b4ebSrica 		exit(0);
526f875b4ebSrica 	}
527f875b4ebSrica 	(void) setsid();
528f875b4ebSrica 	(void) open("/dev/null", O_RDWR, 0);
529f875b4ebSrica 	(void) dup(0);
530f875b4ebSrica 	(void) dup(0);
531f875b4ebSrica }
532f875b4ebSrica 
533f875b4ebSrica static void
534f875b4ebSrica usage()
535f875b4ebSrica {
536f875b4ebSrica 	(void) fprintf(stderr, gettext(
537f875b4ebSrica 	    "Usage:\n\ttnd [-d debug-level][-f debug-file]"
538f875b4ebSrica 	    "[-p poll-interval]\n"));
539f875b4ebSrica 
540f875b4ebSrica 	exit(1);
541f875b4ebSrica }
542f875b4ebSrica 
543f875b4ebSrica static int
544f875b4ebSrica isnumber(s)
545f875b4ebSrica char *s;
546f875b4ebSrica {
547*137fc0ceSrica 	register int c;
548f875b4ebSrica 
549f875b4ebSrica 	/* LINTED */
550f875b4ebSrica 	while (c = *s++)
551f875b4ebSrica 		if (!isdigit(c))
552f875b4ebSrica 			return (0);
553f875b4ebSrica 	return (1);
554f875b4ebSrica }
555f875b4ebSrica 
556f875b4ebSrica 
557f875b4ebSrica /*
558f875b4ebSrica  * match any entry in any tree
559f875b4ebSrica  *	used in tree removal
560f875b4ebSrica  */
561f875b4ebSrica /* ARGSUSED */
562f875b4ebSrica static int
563f875b4ebSrica any_compar(const void *v1, const void *v2)
564f875b4ebSrica {
565f875b4ebSrica 	return (0);
566f875b4ebSrica }
567f875b4ebSrica 
568f875b4ebSrica static int
569f875b4ebSrica tp_compar(const void *v1, const void *v2)
570f875b4ebSrica {
571f875b4ebSrica 	struct tnd_tnrhtp_c	*tp1 = (struct tnd_tnrhtp_c *)v1;
572f875b4ebSrica 	struct tnd_tnrhtp_c	*tp2 = (struct tnd_tnrhtp_c *)v2;
573f875b4ebSrica 	return (strcmp(tp1->tp_ent.name, tp2->tp_ent.name));
574f875b4ebSrica }
575f875b4ebSrica 
576f875b4ebSrica /*
577f875b4ebSrica  * Build tree of tp entries, tossing duplicates
578f875b4ebSrica  */
579f875b4ebSrica static int
580f875b4ebSrica nss_get_tp()
581f875b4ebSrica {
582f875b4ebSrica 	tsol_tpent_t tp; /* to store result */
583f875b4ebSrica 	tsol_tpent_t *tpp;
584f875b4ebSrica 	struct tnd_tnrhtp_c *new, **old;
585f875b4ebSrica 	int count = 0;
586f875b4ebSrica 
587f875b4ebSrica 	tpp = &tp;
588f875b4ebSrica 
589f875b4ebSrica 	tsol_settpent(1);
590f875b4ebSrica 
591f875b4ebSrica 	while ((tpp = (tsol_tpent_t *)tsol_gettpent()) != NULL) {
592f875b4ebSrica 		if ((new = (struct tnd_tnrhtp_c *)
593f875b4ebSrica 		    calloc(1, sizeof (struct tnd_tnrhtp_c))) == NULL)
594f875b4ebSrica 			continue;
595f875b4ebSrica 		(void) memcpy(&new->tp_ent, tpp, sizeof (tp));
596f875b4ebSrica 		old = (struct tnd_tnrhtp_c **)tsearch(new, &tp_tree, tp_compar);
597f875b4ebSrica 		if (*old != new)
598f875b4ebSrica 			free(new);
599f875b4ebSrica 		else
600f875b4ebSrica 			count++;
601f875b4ebSrica 	}
602f875b4ebSrica 	tsol_endtpent();
603f875b4ebSrica 
604f875b4ebSrica 	return (count);
605f875b4ebSrica }
606f875b4ebSrica 
607f875b4ebSrica /* load tp ents into kernel */
608f875b4ebSrica static void
609f875b4ebSrica load_tp()
610f875b4ebSrica {
611f875b4ebSrica 	twalk(tp_tree, load_tp_entry);
612f875b4ebSrica }
613f875b4ebSrica 
614f875b4ebSrica 
615f875b4ebSrica static void
616f875b4ebSrica /* LINTED */
617f875b4ebSrica load_tp_entry(struct tnd_tnrhtp_c **tppp, VISIT visit, int level)
618f875b4ebSrica {
619f875b4ebSrica 	struct tnd_tnrhtp_c *tpp;
620f875b4ebSrica 
621f875b4ebSrica 	if (!(visit == postorder || visit == leaf))
622f875b4ebSrica 		return;
623f875b4ebSrica 
624f875b4ebSrica 	tpp = *tppp;
625f875b4ebSrica 	if (tnrhtp(TNDB_LOAD, &tpp->tp_ent)) {
626f875b4ebSrica 		if (debugl && (logf != NULL)) {
627f875b4ebSrica 			(void) fprintf(logf, "%s : ", gettime());
628f875b4ebSrica 			(void) fprintf(logf, gettext("tnrhtp() failed 0: %s\n"),
629f875b4ebSrica 			    strerror(errno));
630f875b4ebSrica 			(void) fprintf(logf,
631f875b4ebSrica 			    gettext("load of remote-host template "
632f875b4ebSrica 			    "%s into kernel cache failed\n"),
633f875b4ebSrica 			    tpp->tp_ent.name);
634f875b4ebSrica 			(void) fflush(logf);
635f875b4ebSrica 		}
636f875b4ebSrica 		cprint("tnrhtp() failed here 1: %s\n", strerror(errno));
637f875b4ebSrica 	}
638f875b4ebSrica }
639f875b4ebSrica 
640f875b4ebSrica static void
641f875b4ebSrica tp_flush_cache()
642f875b4ebSrica {
643f875b4ebSrica 	struct tnd_tnrhtp_c	dummy;
644f875b4ebSrica 	struct tnd_tnrhtp_c	*tp;
645f875b4ebSrica 
646f875b4ebSrica 	while (tp = tfind(&dummy, tp_tree, any_compar)) {
647f875b4ebSrica 		(void) tdelete(tp, &tp_tree, tp_compar);
648f875b4ebSrica 		free(tp);
649f875b4ebSrica 	}
650f875b4ebSrica }
651f875b4ebSrica 
652f875b4ebSrica /*
653f875b4ebSrica  * Build/update the table of rh entries from the
654f875b4ebSrica  * name service sources, files, ldap etc.
655f875b4ebSrica  */
656f875b4ebSrica static int
657f875b4ebSrica nss_get_rh()
658f875b4ebSrica {
659f875b4ebSrica 	int found_entry = 0;
660f875b4ebSrica 	int count = 0;
661f875b4ebSrica 	int newflag = 0;
662f875b4ebSrica 	struct tsol_rhent rh; /* to store result */
663f875b4ebSrica 	struct tsol_rhent *rhp;
664f875b4ebSrica 	tsol_tpent_t tp;
665f875b4ebSrica 	sa_family_t af;
666f875b4ebSrica 	int v6cnt = 0;
667f875b4ebSrica 
668f875b4ebSrica 	rhp = &rh;
669f875b4ebSrica 
670f875b4ebSrica 	tsol_setrhent(1);
671f875b4ebSrica 	while ((rhp = (struct tsol_rhent *)
672f875b4ebSrica 	    tsol_getrhent()) != NULL) {
673f875b4ebSrica 		/*
674f875b4ebSrica 		 * Check if this is a known template name
675f875b4ebSrica 		 * Entries with missing template in kernel will be logged
676f875b4ebSrica 		 * and not added to cache.
677f875b4ebSrica 		 */
678f875b4ebSrica 
679f875b4ebSrica 		(void) fprintf(logf, gettext("getrhent template name: %s\n"),
680f875b4ebSrica 		    rhp->rh_template);
681f875b4ebSrica 
682f875b4ebSrica 		(void) strncpy(tp.name, rhp->rh_template, TNTNAMSIZ - 1);
683f875b4ebSrica 		if (tnrhtp(TNDB_GET, &tp) != 0) {
684f875b4ebSrica 			if (debugl && (logf != NULL))
685f875b4ebSrica 				(void) fprintf(logf,
686f875b4ebSrica 				    gettext("Unknown template name: %s\n"),
687f875b4ebSrica 				    rhp->rh_template);
688f875b4ebSrica 			cprint(gettext("Unknown template name: %s\n"),
689f875b4ebSrica 			    rhp->rh_template);
690f875b4ebSrica 			continue;
691f875b4ebSrica 		}
692f875b4ebSrica 		found_entry++;		/* found a valid tnrhdb entry */
693f875b4ebSrica 		af = rhp->rh_address.ta_family;
694f875b4ebSrica 
695f875b4ebSrica 		if (af == AF_INET) {
696f875b4ebSrica #ifdef DEBUG
697f875b4ebSrica 			(void) fprintf(logf, gettext("nss_get_rh() v4\n"));
698f875b4ebSrica #endif
699f875b4ebSrica 			(void) rw_wrlock(&entire_rwlp);
700f875b4ebSrica 			(void) rw_wrlock(&cache_rwlp);
701f875b4ebSrica 
702f875b4ebSrica 			/*
703f875b4ebSrica 			 * Both cache table and entire table can be modified
704f875b4ebSrica 			 * by this function. So, get both locks.
705f875b4ebSrica 			 */
706f875b4ebSrica 			newflag = rhtable_search_and_update(rhp, 1);
707f875b4ebSrica 
708f875b4ebSrica 			(void) rw_unlock(&cache_rwlp);
709f875b4ebSrica 			(void) rw_unlock(&entire_rwlp);
710f875b4ebSrica 		} else if (af == AF_INET6) {
711f875b4ebSrica #ifdef DEBUG
712f875b4ebSrica 			(void) fprintf(logf, gettext("nss_get_rh() v6\n"));
713f875b4ebSrica #endif
714f875b4ebSrica 			v6cnt++;
715f875b4ebSrica 			(void) rw_wrlock(&entire_rwlp_v6);
716f875b4ebSrica 			(void) rw_wrlock(&cache_rwlp_v6);
717f875b4ebSrica 
718f875b4ebSrica 			/*
719f875b4ebSrica 			 * Both cache table and entire table can be modified
720f875b4ebSrica 			 * by this function. So, get both locks.
721f875b4ebSrica 			 */
722f875b4ebSrica 			newflag = rhtable_search_and_update_v6(rhp, 1);
723f875b4ebSrica 
724f875b4ebSrica 			(void) rw_unlock(&cache_rwlp_v6);
725f875b4ebSrica 			(void) rw_unlock(&entire_rwlp_v6);
726f875b4ebSrica 		}
727f875b4ebSrica 		if (newflag)
728f875b4ebSrica 			count++;
729f875b4ebSrica 	}
730f875b4ebSrica 	tsol_endrhent();
731f875b4ebSrica 
732f875b4ebSrica 	/*
733f875b4ebSrica 	 * If the first tsol_getrhent() failed, we bail out and
734f875b4ebSrica 	 * try again at the next poll interval, just in case the
735f875b4ebSrica 	 * name service was not reachable the first time.
736f875b4ebSrica 	 */
737f875b4ebSrica 	if (!found_entry) {
738f875b4ebSrica #ifdef	DEBUG
739f875b4ebSrica 		if (logf != NULL)
740f875b4ebSrica 			(void) fprintf(logf,
741f875b4ebSrica 			    gettext("Unable to contact ldap server?\n"));
742f875b4ebSrica #endif
743f875b4ebSrica 		return (count);
744f875b4ebSrica 	}
745f875b4ebSrica 
746f875b4ebSrica 	(void) rw_wrlock(&entire_rwlp);
747f875b4ebSrica 	(void) rw_wrlock(&cache_rwlp);
748f875b4ebSrica 	/*
749f875b4ebSrica 	 * Handle deletions in the name service entries
750f875b4ebSrica 	 * Both cache table and entire table can be modified
751f875b4ebSrica 	 * by this function. So, get both locks.
752f875b4ebSrica 	 */
753f875b4ebSrica 	count += handle_unvisited_nodes();
754f875b4ebSrica 
755f875b4ebSrica 	(void) rw_unlock(&cache_rwlp);
756f875b4ebSrica 	(void) rw_unlock(&entire_rwlp);
757f875b4ebSrica 
758f875b4ebSrica 	if (v6cnt > 0) {
759f875b4ebSrica 		(void) rw_wrlock(&entire_rwlp_v6);
760f875b4ebSrica 		(void) rw_wrlock(&cache_rwlp_v6);
761f875b4ebSrica 		/*
762f875b4ebSrica 		 * Handle deletions in the name service entries
763f875b4ebSrica 		 * Both cache table and entire table can be modified
764f875b4ebSrica 		 * by this function. So, get both locks.
765f875b4ebSrica 		 */
766f875b4ebSrica 		count += handle_unvisited_nodes_v6();
767f875b4ebSrica 
768f875b4ebSrica 		(void) rw_unlock(&cache_rwlp_v6);
769f875b4ebSrica 		(void) rw_unlock(&entire_rwlp_v6);
770f875b4ebSrica 	}
771f875b4ebSrica 
772f875b4ebSrica 	return (count);
773f875b4ebSrica }
774f875b4ebSrica 
775f875b4ebSrica /*
776f875b4ebSrica  * Check if any deletions in  the name service tables
777f875b4ebSrica  * affect the cache entries. We need to do this
778f875b4ebSrica  * in order to not flush the entrie kernel tnrhdb
779f875b4ebSrica  * cache every time we poll the name services.
780f875b4ebSrica  */
781f875b4ebSrica static int
782f875b4ebSrica handle_unvisited_nodes()
783f875b4ebSrica {
784f875b4ebSrica 	int i, j, cnt = 0;
785f875b4ebSrica 	tnrh_tlb_t *tlbt;
786f875b4ebSrica 	tnd_tnrhdb_t *rhent, *prev;
787f875b4ebSrica 
788f875b4ebSrica 	for (i = 0; i < TNRH_TABLE_HASH_SIZE; i++)
789f875b4ebSrica 		if ((tlbt = tnrh_cache_table[i]) != NULL)
790f875b4ebSrica 			do {
791f875b4ebSrica 				if (tlbt->src->visited == 0) {
792f875b4ebSrica 					/*
793f875b4ebSrica 					 * Mark for deletion of both our cache
794f875b4ebSrica 					 * entry and the kernel cache entry.
795f875b4ebSrica 					 */
796f875b4ebSrica 					tlbt->reload = TNDB_DELETE;
797f875b4ebSrica 					cnt++;
798f875b4ebSrica 				}
799f875b4ebSrica 
800f875b4ebSrica 				tlbt = tlbt->next;
801f875b4ebSrica 			} while (tlbt != NULL);
802f875b4ebSrica 
803f875b4ebSrica 	/*
804f875b4ebSrica 	 * Remove any unvisited nodes. This can
805f875b4ebSrica 	 * happen if they are not in use by any cache entry. Then,
806f875b4ebSrica 	 * mark all nodes in entire_table, un-visited, for next iteration.
807f875b4ebSrica 	 */
808f875b4ebSrica 
809f875b4ebSrica 	for (i = 0; i <= IP_ABITS; i++) {
810f875b4ebSrica 		if (tnrh_entire_table[i] == NULL)
811f875b4ebSrica 			continue;
812f875b4ebSrica 
813f875b4ebSrica 		for (j = 0; j < TNRH_TABLE_HASH_SIZE; j++) {
814f875b4ebSrica 			prev = rhent = tnrh_entire_table[i][j];
815f875b4ebSrica 
816f875b4ebSrica 			while (rhent != NULL) {
817f875b4ebSrica 				if (rhent->visited == 0) {
818f875b4ebSrica 					/*
819f875b4ebSrica 					 * Check if start node
820f875b4ebSrica 					 */
821f875b4ebSrica 					if (rhent == tnrh_entire_table[i][j]) {
822f875b4ebSrica 						prev = tnrh_entire_table[i][j] =
823f875b4ebSrica 						    rhent->rh_next;
824f875b4ebSrica 					} else {
825f875b4ebSrica 						/* bypass the deleted node */
826f875b4ebSrica 						prev->rh_next = rhent->rh_next;
827f875b4ebSrica 						prev = prev->rh_next;
828f875b4ebSrica 					}
829f875b4ebSrica 
830f875b4ebSrica 					free(rhent);
831f875b4ebSrica 
832f875b4ebSrica 					if (prev == NULL)
833f875b4ebSrica 						break;
834f875b4ebSrica 					else {
835f875b4ebSrica 						rhent = prev;
836f875b4ebSrica 						continue;
837f875b4ebSrica 					}
838f875b4ebSrica 				} else
839f875b4ebSrica 					rhent->visited = 0;
840f875b4ebSrica 
841f875b4ebSrica 				prev = rhent;
842f875b4ebSrica 				rhent = rhent->rh_next;
843f875b4ebSrica 			}
844f875b4ebSrica 		}
845f875b4ebSrica 	}
846f875b4ebSrica 
847f875b4ebSrica 	return (cnt);
848f875b4ebSrica }
849f875b4ebSrica 
850f875b4ebSrica /*
851f875b4ebSrica  * Check if any deletions in  the name service tables
852f875b4ebSrica  * affect the cache entries. We need to do this
853f875b4ebSrica  * in order to not flush the entrie kernel tnrhdb
854f875b4ebSrica  * cache every time we poll the name services.
855f875b4ebSrica  */
856f875b4ebSrica static int
857f875b4ebSrica handle_unvisited_nodes_v6()
858f875b4ebSrica {
859f875b4ebSrica 	int i, j, cnt = 0;
860f875b4ebSrica 	tnrh_tlb_ipv6_t *tlbt;
861f875b4ebSrica 	tnd_tnrhdb_t *rhent, *prev;
862f875b4ebSrica 
863f875b4ebSrica 	for (i = 0; i < TNRH_TABLE_HASH_SIZE; i++)
864f875b4ebSrica 	if ((tlbt = tnrh_cache_table_v6[i]) != NULL)
865f875b4ebSrica 	do {
866f875b4ebSrica 		if (tlbt->src->visited == 0) {
867f875b4ebSrica 			/*
868f875b4ebSrica 			 * Mark for deletion of both our cache entry
869f875b4ebSrica 			 * and the kernel cache entry.
870f875b4ebSrica 			 */
871f875b4ebSrica 			tlbt->reload = TNDB_DELETE;
872f875b4ebSrica 			cnt++;
873f875b4ebSrica 		}
874f875b4ebSrica 
875f875b4ebSrica 		tlbt = tlbt->next;
876f875b4ebSrica 	} while (tlbt != NULL);
877f875b4ebSrica 
878f875b4ebSrica 	/*
879f875b4ebSrica 	 * Remove any unvisited nodes. This can
880f875b4ebSrica 	 * happen if they are not in use by any cache entry. Then,
881f875b4ebSrica 	 * mark all nodes in entire_table, un-visited, for next iteration.
882f875b4ebSrica 	 */
883f875b4ebSrica 
884f875b4ebSrica 	for (i = 0; i <= IPV6_ABITS; i++) {
885f875b4ebSrica 	if (tnrh_entire_table_v6[i] == NULL)
886f875b4ebSrica 		continue;
887f875b4ebSrica 
888f875b4ebSrica 	for (j = 0; j < TNRH_TABLE_HASH_SIZE; j++) {
889f875b4ebSrica 		prev = rhent = tnrh_entire_table_v6[i][j];
890f875b4ebSrica 
891f875b4ebSrica 		while (rhent != NULL) {
892f875b4ebSrica 		if (rhent->visited == 0) {	/* delete the node */
893f875b4ebSrica 			/* Check if start node */
894f875b4ebSrica 			if (rhent == tnrh_entire_table_v6[i][j]) {
895f875b4ebSrica 				prev = tnrh_entire_table_v6[i][j] =
896f875b4ebSrica 				    rhent->rh_next;
897f875b4ebSrica 			} else {
898f875b4ebSrica 				/* bypass the deleted node */
899f875b4ebSrica 				prev->rh_next = rhent->rh_next;
900f875b4ebSrica 				prev = prev->rh_next;
901f875b4ebSrica 			}
902f875b4ebSrica 
903f875b4ebSrica 			free(rhent);
904f875b4ebSrica 			if (prev == NULL)
905f875b4ebSrica 				break;
906f875b4ebSrica 			else {
907f875b4ebSrica 				rhent = prev;
908f875b4ebSrica 				continue;
909f875b4ebSrica 			}
910f875b4ebSrica 		} else
911f875b4ebSrica 			rhent->visited = 0;
912f875b4ebSrica 
913f875b4ebSrica 		prev = rhent;
914f875b4ebSrica 		rhent = rhent->rh_next;
915f875b4ebSrica 		}
916f875b4ebSrica 	}
917f875b4ebSrica 	}
918f875b4ebSrica 
919f875b4ebSrica 	return (cnt);
920f875b4ebSrica }
921f875b4ebSrica 
922f875b4ebSrica 
923f875b4ebSrica /*
924f875b4ebSrica  * Search the hash chain for the address. If not found,
925f875b4ebSrica  * add the entry to the hash table. If necessary,
926f875b4ebSrica  * construct the hash table.
927f875b4ebSrica  * If the rh entry is in table, we may update its template name
928f875b4ebSrica  */
929f875b4ebSrica static int
930f875b4ebSrica rhtable_search_and_update(struct tsol_rhent *ent, int duplflag)
931f875b4ebSrica {
932f875b4ebSrica 	struct sockaddr_in *saddrp;
933f875b4ebSrica 	unsigned char hash;
934f875b4ebSrica 	tnd_tnrhdb_t *rhent;
935f875b4ebSrica 	int i;
936f875b4ebSrica 	int rflag = 1;
937f875b4ebSrica 
938f875b4ebSrica 	struct tnd_tnrhdb_c *new;
939f875b4ebSrica 
940f875b4ebSrica 	saddrp = (struct sockaddr_in *)&ent->rh_address.ip_addr_v4;
941f875b4ebSrica 	hash = (unsigned char) get_hashvalue(saddrp->sin_addr.s_addr);
942f875b4ebSrica 	i = ent->rh_prefix;
943f875b4ebSrica 
944f875b4ebSrica #ifdef DEBUG
945f875b4ebSrica 	(void) fprintf(logf, gettext("\trhtable_search_and_update IP address:\
946f875b4ebSrica 		%s\n"), inet_ntoa(saddrp->sin_addr));
947f875b4ebSrica #endif
948f875b4ebSrica 
949f875b4ebSrica 	if (tnrh_entire_table[i] == NULL) {
950f875b4ebSrica 		if ((tnrh_entire_table[i] = (tnd_tnrhdb_t **)calloc(
951f875b4ebSrica 		    TNRH_TABLE_HASH_SIZE, sizeof (tnd_tnrhdb_t *))) == NULL) {
952f875b4ebSrica 			return (0);
953f875b4ebSrica 		}
954f875b4ebSrica 	}
955f875b4ebSrica 
956f875b4ebSrica 	rhent = tnrh_entire_table[i][hash];
957f875b4ebSrica #ifdef DEBUG
958f875b4ebSrica 	(void) fprintf(logf, gettext("\tsearch_and_update i = %d hash = %d\n"),
959f875b4ebSrica 	    i, hash);
960f875b4ebSrica 	if (rhent != NULL) {
961f875b4ebSrica 		(void) fprintf(logf, gettext("\trhent visited  = %d\n"),
962f875b4ebSrica 		    rhent->visited);
963f875b4ebSrica 		print_entry(&rhent->rh_ent, AF_INET);
964f875b4ebSrica 	} else {
965f875b4ebSrica 		(void) fprintf(logf, gettext("\tsearch_and_update null\n"));
966f875b4ebSrica 	}
967f875b4ebSrica #endif
968f875b4ebSrica 	while (rhent != NULL) {
969f875b4ebSrica 		if (rhaddr_compar(saddrp, rhent) == 1) {
970f875b4ebSrica 			/* Check if this is a duplicate entry */
971f875b4ebSrica 			if ((rhent->visited == 1) && duplflag)
972f875b4ebSrica 				return (0);
973f875b4ebSrica 
974f875b4ebSrica 			if (duplflag)
975f875b4ebSrica 				rhent->visited = 1;
976f875b4ebSrica 
977f875b4ebSrica 			if (strcmp(ent->rh_template,
978f875b4ebSrica 			    rhent->rh_ent.rh_template) != 0) {
979f875b4ebSrica 				/*
980f875b4ebSrica 				 * Template is changed in the name service.
981f875b4ebSrica 				 * Use the new template.
982f875b4ebSrica 				 */
983f875b4ebSrica 				(void) strcpy(rhent->rh_ent.rh_template,
984f875b4ebSrica 				    ent->rh_template);
985f875b4ebSrica 				/*
986f875b4ebSrica 				 * Check if this modified entry
987f875b4ebSrica 				 * affects the cache table.
988f875b4ebSrica 				 */
989f875b4ebSrica 				rflag = update_cache_table(ent, rhent);
990f875b4ebSrica 				return (rflag);
991f875b4ebSrica 			} else
992f875b4ebSrica 				return (0);
993f875b4ebSrica 		}
994f875b4ebSrica 		rhent = rhent->rh_next;
995f875b4ebSrica 	}
996f875b4ebSrica 
997f875b4ebSrica 	/* Not found. Add the entry */
998f875b4ebSrica 	new = (struct tnd_tnrhdb_c *)calloc(1,
999f875b4ebSrica 	    sizeof (struct tnd_tnrhdb_c));
1000f875b4ebSrica 	if (new == NULL)
1001f875b4ebSrica 		return (0);
1002f875b4ebSrica 	(void) memcpy(&new->rh_ent, ent, sizeof (struct tsol_rhent));
1003f875b4ebSrica 	if (duplflag)
1004f875b4ebSrica 		new->visited = 1;	/* Mark all new nodes visited */
1005f875b4ebSrica 
1006f875b4ebSrica 	/* linked list. Insert in the beginning */
1007f875b4ebSrica 	new->rh_next = tnrh_entire_table[i][hash];
1008f875b4ebSrica 	tnrh_entire_table[i][hash] = new;
1009f875b4ebSrica #ifdef DEBUG
1010f875b4ebSrica 	(void) fprintf(logf, gettext("rhtable added i = %d, hash = %d\n"),
1011f875b4ebSrica 	    i, hash);
1012f875b4ebSrica #endif
1013f875b4ebSrica 
1014f875b4ebSrica 	/* Check if the new entry affects the cache table */
1015f875b4ebSrica 	rflag = update_cache_table(ent, new);
1016f875b4ebSrica 
1017f875b4ebSrica #ifdef DEBUG
1018f875b4ebSrica 	(void) fprintf(logf, gettext("search_and_update rflag=%d\n"), rflag);
1019f875b4ebSrica #endif
1020f875b4ebSrica 	return (rflag);
1021f875b4ebSrica }
1022f875b4ebSrica 
1023f875b4ebSrica /*
1024f875b4ebSrica  * Search the hash chain for the address. If not found,
1025f875b4ebSrica  * add the entry to the hash table. If necessary,
1026f875b4ebSrica  * construct the hash table.
1027f875b4ebSrica  */
1028f875b4ebSrica static int
1029f875b4ebSrica rhtable_search_and_update_v6(struct tsol_rhent *ent, int duplflag)
1030f875b4ebSrica {
1031f875b4ebSrica 	struct sockaddr_in6 *saddrp;
1032f875b4ebSrica 	unsigned char hash;
1033f875b4ebSrica 	tnd_tnrhdb_t *rhent;
1034f875b4ebSrica 	int i;
1035f875b4ebSrica 	int rflag = 1;
1036f875b4ebSrica 
1037f875b4ebSrica 	struct tnd_tnrhdb_c *new;
1038f875b4ebSrica 	in6_addr_t tmpmask6;
1039f875b4ebSrica 
1040f875b4ebSrica 	saddrp = (struct sockaddr_in6 *)&ent->rh_address.ip_addr_v6;
1041f875b4ebSrica 	i = ent->rh_prefix;
1042f875b4ebSrica 	(void) rh_index_to_mask_v6(i, &tmpmask6);
1043f875b4ebSrica 	hash = (unsigned char) TNRH_ADDR_MASK_HASH_V6(saddrp->sin6_addr,
1044f875b4ebSrica 	    tmpmask6);
1045f875b4ebSrica 
1046f875b4ebSrica 	if (tnrh_entire_table_v6[i] == NULL) {
1047f875b4ebSrica 		if ((tnrh_entire_table_v6[i] = (tnd_tnrhdb_t **)calloc(
1048f875b4ebSrica 		    TNRH_TABLE_HASH_SIZE, sizeof (tnd_tnrhdb_t *))) == NULL) {
1049f875b4ebSrica 			return (0);
1050f875b4ebSrica 		}
1051f875b4ebSrica 	}
1052f875b4ebSrica 
1053f875b4ebSrica 	rhent = tnrh_entire_table_v6[i][hash];
1054f875b4ebSrica 	while (rhent != NULL) {
1055f875b4ebSrica 		if (rhaddr_compar_v6(saddrp, rhent) == 1) {
1056f875b4ebSrica 			/* Check if this is a duplicate entry */
1057f875b4ebSrica 			if ((rhent->visited == 1) && duplflag)
1058f875b4ebSrica 				return (0);
1059f875b4ebSrica 
1060f875b4ebSrica 			if (duplflag)
1061f875b4ebSrica 				rhent->visited = 1;
1062f875b4ebSrica 
1063f875b4ebSrica 			if (strcmp(ent->rh_template,
1064f875b4ebSrica 			    rhent->rh_ent.rh_template) != 0) {
1065f875b4ebSrica 				/*
1066f875b4ebSrica 				 * Template is changed in the name service.
1067f875b4ebSrica 				 * Use the new template.
1068f875b4ebSrica 				 */
1069f875b4ebSrica 				(void) strcpy(rhent->rh_ent.rh_template,
1070f875b4ebSrica 				    ent->rh_template);
1071f875b4ebSrica 				/*
1072f875b4ebSrica 				 * Check if this modified entry
1073f875b4ebSrica 				 * affects the cache table.
1074f875b4ebSrica 				 */
1075f875b4ebSrica 				rflag = update_cache_table_v6(ent, rhent);
1076f875b4ebSrica 				return (rflag);
1077f875b4ebSrica 			} else
1078f875b4ebSrica 				return (0);
1079f875b4ebSrica 		}
1080f875b4ebSrica 		rhent = rhent->rh_next;
1081f875b4ebSrica 	}
1082f875b4ebSrica 
1083f875b4ebSrica 	/* Not found. Add the entry */
1084f875b4ebSrica 	new = (struct tnd_tnrhdb_c *)calloc(1, sizeof (struct tnd_tnrhdb_c));
1085f875b4ebSrica 	if (new == NULL)
1086f875b4ebSrica 		return (0);
1087f875b4ebSrica 	(void) memcpy(&new->rh_ent, ent, sizeof (struct tsol_rhent));
1088f875b4ebSrica 	if (duplflag)
1089f875b4ebSrica 		new->visited = 1;	/* Mark all new nodes visited */
1090f875b4ebSrica 
1091f875b4ebSrica 	/* linked list. Insert in the beginning */
1092f875b4ebSrica 	new->rh_next = tnrh_entire_table_v6[i][hash];
1093f875b4ebSrica 	tnrh_entire_table_v6[i][hash] = new;
1094f875b4ebSrica 
1095f875b4ebSrica 	/* Check if the new entry affects the cache table */
1096f875b4ebSrica 	rflag = update_cache_table_v6(ent, new);
1097f875b4ebSrica 
1098f875b4ebSrica 	return (rflag);
1099f875b4ebSrica }
1100f875b4ebSrica 
1101f875b4ebSrica /*
1102f875b4ebSrica  * The array element i points to the hash table.
1103f875b4ebSrica  * Search the hash chain for the address.
1104f875b4ebSrica  */
1105f875b4ebSrica static struct tnd_tnrhdb_c *
1106f875b4ebSrica rhtable_lookup(struct sockaddr_in *saddrp, int i)
1107f875b4ebSrica {
1108f875b4ebSrica 	unsigned char hash;
1109f875b4ebSrica 	tnd_tnrhdb_t *rhent;
1110f875b4ebSrica 
1111f875b4ebSrica 	if (tnrh_entire_table[i] == NULL)
1112f875b4ebSrica 		return (NULL);
1113f875b4ebSrica 
1114f875b4ebSrica 	hash = (unsigned char) get_hashvalue(saddrp->sin_addr.s_addr);
1115f875b4ebSrica 	rhent = tnrh_entire_table[i][hash];
1116f875b4ebSrica 
1117f875b4ebSrica #ifdef DEBUG
1118f875b4ebSrica 	(void) fprintf(logf, gettext("rhtable_lookup i = %d, hash = %d\n"),
1119f875b4ebSrica 	    i, hash);
1120f875b4ebSrica #endif
1121f875b4ebSrica 
1122f875b4ebSrica 	while (rhent != NULL) {
1123f875b4ebSrica #ifdef DEBUG
1124f875b4ebSrica 	struct sockaddr_in *saddrp2;
1125f875b4ebSrica 	saddrp2 = (struct sockaddr_in *)(&rhent->rh_ent.rh_address.ip_addr_v4);
1126f875b4ebSrica 	(void) fprintf(logf, gettext("rhtable_lookup addr = %s, tmpl = %s\n"),
1127f875b4ebSrica 	    inet_ntoa(saddrp2->sin_addr), rhent->rh_ent.rh_template);
1128f875b4ebSrica #endif
1129f875b4ebSrica 		if (rhaddr_compar_mask(saddrp, rhent, i) == 1)
1130f875b4ebSrica 			return (rhent);
1131f875b4ebSrica 		rhent = rhent->rh_next;
1132f875b4ebSrica 	}
1133f875b4ebSrica 
1134f875b4ebSrica #ifdef DEBUG
1135f875b4ebSrica 	(void) fprintf(logf, gettext("\trhtable_lookup failed\n"));
1136f875b4ebSrica #endif
1137f875b4ebSrica 
1138f875b4ebSrica 	/* Not found */
1139f875b4ebSrica 	return (NULL);
1140f875b4ebSrica }
1141f875b4ebSrica 
1142f875b4ebSrica /*
1143f875b4ebSrica  * The array element i points to the hash table.
1144f875b4ebSrica  * Search the hash chain for the address.
1145f875b4ebSrica  */
1146f875b4ebSrica static struct tnd_tnrhdb_c *
1147f875b4ebSrica rhtable_lookup_v6(struct sockaddr_in6 *saddrp, in6_addr_t mask, int i)
1148f875b4ebSrica {
1149f875b4ebSrica 	unsigned char hash;
1150f875b4ebSrica 	tnd_tnrhdb_t *rhent;
1151f875b4ebSrica 
1152f875b4ebSrica 	if (tnrh_entire_table_v6[i] == NULL)
1153f875b4ebSrica 		return (NULL);
1154f875b4ebSrica 
1155f875b4ebSrica 	hash = (unsigned char) TNRH_ADDR_MASK_HASH_V6(saddrp->sin6_addr, mask);
1156f875b4ebSrica 	rhent = tnrh_entire_table_v6[i][hash];
1157f875b4ebSrica 
1158f875b4ebSrica 	while (rhent != NULL) {
1159f875b4ebSrica 		if (rhaddr_compar_mask_v6(saddrp, rhent, i) == 1)
1160f875b4ebSrica 			return (rhent);
1161f875b4ebSrica 		rhent = rhent->rh_next;
1162f875b4ebSrica 	}
1163f875b4ebSrica 
1164f875b4ebSrica 	/* Not found */
1165f875b4ebSrica 	return (NULL);
1166f875b4ebSrica }
1167f875b4ebSrica 
1168f875b4ebSrica void
1169f875b4ebSrica add_cache_entry(in_addr_t addr, char *name, int indx,
1170f875b4ebSrica     tnd_tnrhdb_t *src)
1171f875b4ebSrica {
1172f875b4ebSrica 	unsigned char hash;
1173f875b4ebSrica 	tnrh_tlb_t *tlbt;
1174f875b4ebSrica 
1175f875b4ebSrica 	hash = (unsigned char) get_hashvalue(addr);
1176f875b4ebSrica 
1177f875b4ebSrica 	/* Look if some other thread already added this entry */
1178f875b4ebSrica 	if (lookup_cache_table(addr) != NULL)
1179f875b4ebSrica 		return;
1180f875b4ebSrica #ifdef DEBUG
1181f875b4ebSrica 	(void) fprintf(logf, gettext("\tenter add_cache_entry\n"));
1182f875b4ebSrica #endif
1183f875b4ebSrica 	if ((tlbt = (tnrh_tlb_t *)calloc(1, sizeof (tnrh_tlb_t))) == NULL)
1184f875b4ebSrica 		return;
1185f875b4ebSrica 	tlbt->addr = addr;
1186f875b4ebSrica 	(void) strncpy(tlbt->template_name, name, TNTNAMSIZ-1);
1187f875b4ebSrica 	tlbt->masklen_used = indx;
1188f875b4ebSrica 	tlbt->reload = TNDB_LOAD;
1189f875b4ebSrica 	tlbt->src = src;
1190f875b4ebSrica 
1191f875b4ebSrica #ifdef DEBUG
1192f875b4ebSrica 	(void) fprintf(logf, gettext("adding cache entry\n"));
1193f875b4ebSrica 	print_tlbt(tlbt);
1194f875b4ebSrica #endif
1195f875b4ebSrica 	/* Add to the chain */
1196f875b4ebSrica 	if (tnrh_cache_table[hash] == NULL) {
1197f875b4ebSrica 		tnrh_cache_table[hash] = tlbt;
1198f875b4ebSrica 	} else {
1199f875b4ebSrica 		/* Add in the beginning */
1200f875b4ebSrica 		tlbt->next = tnrh_cache_table[hash];
1201f875b4ebSrica 		tnrh_cache_table[hash] = tlbt;
1202f875b4ebSrica 	}
1203f875b4ebSrica }
1204f875b4ebSrica 
1205f875b4ebSrica static tnrh_tlb_t *
1206f875b4ebSrica lookup_cache_table(in_addr_t addr)
1207f875b4ebSrica {
1208f875b4ebSrica 	tnrh_tlb_t *tlbt = NULL;
1209f875b4ebSrica 	unsigned char hash;
1210f875b4ebSrica 
1211f875b4ebSrica 	hash = (unsigned char) get_hashvalue(addr);
1212f875b4ebSrica 	tlbt = tnrh_cache_table[hash];
1213f875b4ebSrica 	while (tlbt != NULL) {
1214f875b4ebSrica 		if (addr == tlbt->addr)
1215f875b4ebSrica 			break;
1216f875b4ebSrica 		tlbt = tlbt->next;
1217f875b4ebSrica 	}
1218f875b4ebSrica 	return (tlbt);
1219f875b4ebSrica }
1220f875b4ebSrica 
1221f875b4ebSrica static void
1222f875b4ebSrica add_cache_entry_v6(in6_addr_t addr, char *name, int indx,
1223f875b4ebSrica 				tnd_tnrhdb_t *src)
1224f875b4ebSrica {
1225f875b4ebSrica 	unsigned char hash;
1226f875b4ebSrica 	tnrh_tlb_ipv6_t *tlbt;
1227f875b4ebSrica 
1228f875b4ebSrica 	hash = (unsigned char) TNRH_ADDR_HASH_V6(addr);
1229f875b4ebSrica 
1230f875b4ebSrica 	/* Look if some other thread already added this entry */
1231f875b4ebSrica 	if (lookup_cache_table_v6(addr) != NULL)
1232f875b4ebSrica 		return;
1233f875b4ebSrica 
1234f875b4ebSrica 	if ((tlbt = (tnrh_tlb_ipv6_t *)calloc(1,
1235f875b4ebSrica 	    sizeof (tnrh_tlb_ipv6_t))) == NULL)
1236f875b4ebSrica 		return;
1237f875b4ebSrica 	(void) memcpy(&tlbt->addr, &addr, sizeof (in6_addr_t));
1238f875b4ebSrica 	(void) strncpy(tlbt->template_name, name, TNTNAMSIZ-1);
1239f875b4ebSrica 	tlbt->masklen_used = indx;
1240f875b4ebSrica 	tlbt->reload = TNDB_LOAD;
1241f875b4ebSrica 	tlbt->src = src;
1242f875b4ebSrica 
1243f875b4ebSrica 	/* Add to the chain */
1244f875b4ebSrica 	if (tnrh_cache_table_v6[hash] == NULL) {
1245f875b4ebSrica 		tnrh_cache_table_v6[hash] = tlbt;
1246f875b4ebSrica 	} else {
1247f875b4ebSrica 		/* Add in the beginning */
1248f875b4ebSrica 		tlbt->next = tnrh_cache_table_v6[hash];
1249f875b4ebSrica 		tnrh_cache_table_v6[hash] = tlbt;
1250f875b4ebSrica 	}
1251f875b4ebSrica }
1252f875b4ebSrica 
1253f875b4ebSrica static tnrh_tlb_ipv6_t *
1254f875b4ebSrica lookup_cache_table_v6(in6_addr_t addr)
1255f875b4ebSrica {
1256f875b4ebSrica 	tnrh_tlb_ipv6_t *tlbt = NULL;
1257f875b4ebSrica 	unsigned char hash;
1258f875b4ebSrica 
1259f875b4ebSrica 	hash = (unsigned char) TNRH_ADDR_HASH_V6(addr);
1260f875b4ebSrica 	tlbt = tnrh_cache_table_v6[hash];
1261f875b4ebSrica 	while (tlbt != NULL) {
1262f875b4ebSrica 		if (IN6_ARE_ADDR_EQUAL(&addr, &tlbt->addr))
1263f875b4ebSrica 			break;
1264f875b4ebSrica 		tlbt = tlbt->next;
1265f875b4ebSrica 	}
1266f875b4ebSrica 	return (tlbt);
1267f875b4ebSrica }
1268f875b4ebSrica 
1269f875b4ebSrica 
1270f875b4ebSrica /*
1271f875b4ebSrica  * Walk the cache table and check if this IP address/address prefix
1272f875b4ebSrica  * will be a better match for an existing entry in the cache.
1273f875b4ebSrica  * will add cache if not already exists
1274f875b4ebSrica  */
1275f875b4ebSrica static int
1276f875b4ebSrica update_cache_table(tsol_rhent_t *ent, tnd_tnrhdb_t *src)
1277f875b4ebSrica {
1278f875b4ebSrica 	int i;
1279f875b4ebSrica 	char result[TNTNAMSIZ];
1280f875b4ebSrica 	in_addr_t tmpmask;
1281f875b4ebSrica 	in_addr_t addr;
1282f875b4ebSrica 	struct sockaddr_in *saddrp;
1283f875b4ebSrica 	tnrh_tlb_t *tlbt;
1284f875b4ebSrica 	struct tnd_tnrhdb_c	*rhp;
1285f875b4ebSrica 	int rflag = 0;
1286f875b4ebSrica 
1287f875b4ebSrica 	saddrp = (struct sockaddr_in *)&ent->rh_address.ip_addr_v4;
1288f875b4ebSrica 	addr = saddrp->sin_addr.s_addr;
1289f875b4ebSrica 
1290f875b4ebSrica 	(void) rw_rdlock(&cache_rwlp);
1291f875b4ebSrica 	tlbt = lookup_cache_table(addr);
1292f875b4ebSrica 	(void) rw_unlock(&cache_rwlp);
1293f875b4ebSrica 
1294f875b4ebSrica 	if (tlbt == NULL) {
1295f875b4ebSrica 		(void) rw_rdlock(&entire_rwlp);
1296f875b4ebSrica 		for (i = (IP_MASK_TABLE_SIZE - 1); i >= 0; i--) {
1297f875b4ebSrica #ifdef DEBUG
1298f875b4ebSrica 			(void) fprintf(logf, "update_cache_table i = %d\n", i);
1299f875b4ebSrica #endif
1300f875b4ebSrica 			if (tnrh_entire_table[i] == NULL)
1301f875b4ebSrica 				continue;
1302f875b4ebSrica 
1303f875b4ebSrica 			tmpmask = rh_index_to_mask(i);
1304f875b4ebSrica 			saddrp->sin_addr.s_addr &= tmpmask;
1305f875b4ebSrica #ifdef DEBUG
1306f875b4ebSrica 			(void) fprintf(logf,
1307f875b4ebSrica 			    "update_cache_table found i = %d\n", i);
1308f875b4ebSrica 			(void) fprintf(logf, "\ti = %d, tmpmask = 0x%4x\n",
1309f875b4ebSrica 			    i, tmpmask);
1310f875b4ebSrica #endif
1311f875b4ebSrica 			rhp = (struct tnd_tnrhdb_c *)rhtable_lookup(saddrp, i);
1312f875b4ebSrica 			if (rhp != NULL) {
1313f875b4ebSrica 				(void) strcpy(result, rhp->rh_ent.rh_template);
1314f875b4ebSrica 				/* Add this result to the cache also */
1315f875b4ebSrica 				(void) rw_wrlock(&cache_rwlp);
1316f875b4ebSrica 				add_cache_entry(addr, result, i, rhp);
1317f875b4ebSrica 				rflag++;
1318f875b4ebSrica 				(void) rw_unlock(&cache_rwlp);
1319f875b4ebSrica 				break;
1320f875b4ebSrica 			} else {
1321f875b4ebSrica #ifdef DEBUG
1322f875b4ebSrica 				(void) fprintf(logf,
1323f875b4ebSrica 				    "rhtable_lookup return null !!");
1324f875b4ebSrica #endif
1325f875b4ebSrica 			}
1326f875b4ebSrica 		}
1327f875b4ebSrica 		(void) rw_unlock(&entire_rwlp);
1328f875b4ebSrica 	}
1329f875b4ebSrica 
1330f875b4ebSrica 	rflag += walk_cache_table(addr, ent->rh_template, ent->rh_prefix, src);
1331f875b4ebSrica 	return (rflag);
1332f875b4ebSrica }
1333f875b4ebSrica 
1334f875b4ebSrica /*
1335f875b4ebSrica  * Walk the cache table and check if this IP address/address prefix
1336f875b4ebSrica  * will be a better match for an existing entry in the cache.
1337f875b4ebSrica  */
1338f875b4ebSrica static int
1339f875b4ebSrica update_cache_table_v6(tsol_rhent_t *ent, tnd_tnrhdb_t *src)
1340f875b4ebSrica {
1341f875b4ebSrica 	int i;
1342f875b4ebSrica 	char result[TNTNAMSIZ];
1343f875b4ebSrica 	in6_addr_t addr;
1344f875b4ebSrica 	struct sockaddr_in6 *saddrp;
1345f875b4ebSrica 	tnrh_tlb_ipv6_t *tlbt;
1346f875b4ebSrica 	struct tnd_tnrhdb_c	*rhp;
1347f875b4ebSrica 	in6_addr_t tmpmask6;
1348f875b4ebSrica 	int rflag = 0;
1349f875b4ebSrica 
1350f875b4ebSrica 	saddrp = (struct sockaddr_in6 *)&ent->rh_address.ip_addr_v6;
1351f875b4ebSrica 	(void) memcpy(&addr, &saddrp->sin6_addr, sizeof (in6_addr_t));
1352f875b4ebSrica 
1353f875b4ebSrica 	/* Look in the cache first */
1354f875b4ebSrica 	(void) rw_rdlock(&cache_rwlp);
1355f875b4ebSrica 	tlbt = lookup_cache_table_v6(addr);
1356f875b4ebSrica 	(void) rw_unlock(&cache_rwlp);
1357f875b4ebSrica 
1358f875b4ebSrica 
1359f875b4ebSrica 	if (tlbt == NULL) {
1360f875b4ebSrica 		(void) rw_rdlock(&entire_rwlp_v6);
1361f875b4ebSrica 		for (i = (IPV6_MASK_TABLE_SIZE - 1); i >= 0; i--) {
1362f875b4ebSrica 			if (tnrh_entire_table_v6[i] == NULL)
1363f875b4ebSrica 				continue;
1364f875b4ebSrica 			(void) rh_index_to_mask_v6(i, &tmpmask6);
1365f875b4ebSrica 			rhp = (struct tnd_tnrhdb_c *)
1366f875b4ebSrica 			    rhtable_lookup_v6(saddrp, tmpmask6, i);
1367f875b4ebSrica 			if (rhp != NULL) {
1368f875b4ebSrica 				(void) strcpy(result, rhp->rh_ent.rh_template);
1369f875b4ebSrica 				/* Add this result to the cache also */
1370f875b4ebSrica 				(void) rw_wrlock(&cache_rwlp_v6);
1371f875b4ebSrica 				add_cache_entry_v6(addr, result, i, rhp);
1372f875b4ebSrica 				rflag++;
1373f875b4ebSrica 				(void) rw_unlock(&cache_rwlp_v6);
1374f875b4ebSrica 				break;
1375f875b4ebSrica 			}
1376f875b4ebSrica 		}
1377f875b4ebSrica 		(void) rw_unlock(&entire_rwlp_v6);
1378f875b4ebSrica 	}
1379f875b4ebSrica 
1380f875b4ebSrica 	rflag += walk_cache_table_v6(addr, ent->rh_template,
1381f875b4ebSrica 	    ent->rh_prefix, src);
1382f875b4ebSrica 	return (rflag);
1383f875b4ebSrica }
1384f875b4ebSrica 
1385f875b4ebSrica 
1386f875b4ebSrica /*
1387f875b4ebSrica  * Check if this prefix addr will be a better match
1388f875b4ebSrica  * for an existing entry.
1389f875b4ebSrica  */
1390f875b4ebSrica static int
1391f875b4ebSrica is_better_match(in_addr_t newaddr, int indx, tnrh_tlb_t *tlbt)
1392f875b4ebSrica {
1393f875b4ebSrica 	if (tlbt->masklen_used <= indx) {
1394f875b4ebSrica 		in_addr_t tmpmask = rh_index_to_mask(indx);
1395f875b4ebSrica 
1396f875b4ebSrica 		if ((newaddr) == (tlbt->addr & tmpmask))
1397f875b4ebSrica 			return (1);
1398f875b4ebSrica 	}
1399f875b4ebSrica 
1400f875b4ebSrica 	return (0);
1401f875b4ebSrica }
1402f875b4ebSrica 
1403f875b4ebSrica /*
1404f875b4ebSrica  * Walk the cache table and update entries if needed.
1405f875b4ebSrica  * Mark entries for reload to kernel, if somehow their
1406f875b4ebSrica  * template changed.
1407f875b4ebSrica  * why is_better_match() is called???
1408f875b4ebSrica  */
1409f875b4ebSrica static int
1410f875b4ebSrica walk_cache_table(in_addr_t newaddr, char *name, int indx, tnd_tnrhdb_t *src)
1411f875b4ebSrica {
1412f875b4ebSrica 	int i;
1413f875b4ebSrica 	tnrh_tlb_t *tlbt;
1414f875b4ebSrica 	int rflag = 0;
1415f875b4ebSrica 
1416f875b4ebSrica 	for (i = 0; i < TNRH_TABLE_HASH_SIZE; i++) {
1417f875b4ebSrica 		tlbt = tnrh_cache_table[i];
1418f875b4ebSrica 
1419f875b4ebSrica 		while (tlbt != NULL) {
1420f875b4ebSrica 			if (is_better_match(newaddr, indx, tlbt)) {
1421f875b4ebSrica 				tlbt->masklen_used = indx;
1422f875b4ebSrica 				tlbt->src = src;
1423f875b4ebSrica 				/*
1424f875b4ebSrica 				 * Reload to the kernel only if the
1425f875b4ebSrica 				 * host type changed. There is no need
1426f875b4ebSrica 				 * to load, if only the mask used has changed,
1427f875b4ebSrica 				 * since the kernel does not need that
1428f875b4ebSrica 				 * information.
1429f875b4ebSrica 				 */
1430f875b4ebSrica 				if (strcmp(name, tlbt->template_name) != 0) {
1431f875b4ebSrica 					(void) strncpy(tlbt->template_name,
1432f875b4ebSrica 					    name, TNTNAMSIZ-1);
1433f875b4ebSrica 					tlbt->reload = TNDB_LOAD;
1434f875b4ebSrica 					rflag ++;
1435f875b4ebSrica 				}
1436f875b4ebSrica 			}
1437f875b4ebSrica 
1438f875b4ebSrica 			tlbt = tlbt->next;
1439f875b4ebSrica 		}
1440f875b4ebSrica 	}
1441f875b4ebSrica #ifdef DEBUG
1442f875b4ebSrica 	(void) fprintf(logf, gettext("walk_cache_table rflag=%d\n"), rflag);
1443f875b4ebSrica #endif
1444f875b4ebSrica 	return (rflag);
1445f875b4ebSrica }
1446f875b4ebSrica 
1447f875b4ebSrica /*
1448f875b4ebSrica  * Check if this prefix addr will be a better match
1449f875b4ebSrica  * for an existing entry.
1450f875b4ebSrica  */
1451f875b4ebSrica static int
1452f875b4ebSrica is_better_match_v6(in6_addr_t newaddr, int indx, tnrh_tlb_ipv6_t *tlbt)
1453f875b4ebSrica {
1454f875b4ebSrica 	in6_addr_t tmpmask;
1455f875b4ebSrica 
1456f875b4ebSrica 	if (tlbt->masklen_used <= indx) {
1457f875b4ebSrica 		(void) rh_index_to_mask_v6(indx, &tmpmask);
1458f875b4ebSrica 
1459f875b4ebSrica 		if (V6_MASK_EQ(newaddr, tmpmask, tlbt->addr))
1460f875b4ebSrica 			return (1);
1461f875b4ebSrica 	}
1462f875b4ebSrica 
1463f875b4ebSrica 	return (0);
1464f875b4ebSrica }
1465f875b4ebSrica 
1466f875b4ebSrica 
1467f875b4ebSrica /*
1468f875b4ebSrica  * Walk the cache table and update entries if needed.
1469f875b4ebSrica  * Mark entries for reload to kernel, if somehow their
1470f875b4ebSrica  * template changed.
1471f875b4ebSrica  */
1472f875b4ebSrica static int
1473f875b4ebSrica walk_cache_table_v6(in6_addr_t newaddr, char *name, int indx, tnd_tnrhdb_t *src)
1474f875b4ebSrica {
1475f875b4ebSrica 	int i;
1476f875b4ebSrica 	tnrh_tlb_ipv6_t *tlbt;
1477f875b4ebSrica 	int rflag = 0;
1478f875b4ebSrica 
1479f875b4ebSrica 	for (i = 0; i < TNRH_TABLE_HASH_SIZE; i++) {
1480f875b4ebSrica 		tlbt = tnrh_cache_table_v6[i];
1481f875b4ebSrica 
1482f875b4ebSrica 		while (tlbt != NULL) {
1483f875b4ebSrica 			if (is_better_match_v6(newaddr, indx, tlbt)) {
1484f875b4ebSrica 				tlbt->masklen_used = indx;
1485f875b4ebSrica 				tlbt->src = src;
1486f875b4ebSrica 				/*
1487f875b4ebSrica 				 * Reload to the kernel only if the
1488f875b4ebSrica 				 * host type changed. There is no need
1489f875b4ebSrica 				 * to load, if only the mask used has changed,
1490f875b4ebSrica 				 * since the kernel does not need that
1491f875b4ebSrica 				 * information.
1492f875b4ebSrica 				 */
1493f875b4ebSrica 				if (strcmp(name, tlbt->template_name) != 0) {
1494f875b4ebSrica 					(void) strncpy(tlbt->template_name,
1495f875b4ebSrica 					    name, TNTNAMSIZ-1);
1496f875b4ebSrica 					tlbt->reload = TNDB_LOAD;
1497f875b4ebSrica 					rflag ++;
1498f875b4ebSrica 				}
1499f875b4ebSrica 			}
1500f875b4ebSrica 
1501f875b4ebSrica 			tlbt = tlbt->next;
1502f875b4ebSrica 		}
1503f875b4ebSrica 	}
1504f875b4ebSrica 
1505f875b4ebSrica 	return (rflag);
1506f875b4ebSrica }
1507f875b4ebSrica 
1508f875b4ebSrica /*
1509f875b4ebSrica  * load/delete marked rh ents into kernel
1510f875b4ebSrica  * depending on the reload flag by invoking tnrh().
1511f875b4ebSrica  * It will mark other entries as TNDB_NOOP
1512f875b4ebSrica  */
1513f875b4ebSrica static void
1514f875b4ebSrica load_rh_marked()
1515f875b4ebSrica {
1516f875b4ebSrica 	int i;
1517f875b4ebSrica 	tnrh_tlb_t *tlbt, *prev;
1518f875b4ebSrica 	struct tsol_rhent rhentp;
1519f875b4ebSrica 
1520f875b4ebSrica 	(void) memset((char *)&rhentp, '\0', sizeof (rhentp));
1521f875b4ebSrica 
1522f875b4ebSrica 	for (i = 0; i < TNRH_TABLE_HASH_SIZE; i++) {
1523f875b4ebSrica 
1524f875b4ebSrica 		prev = tlbt = tnrh_cache_table[i];
1525f875b4ebSrica 
1526f875b4ebSrica 		while (tlbt != NULL) {
1527f875b4ebSrica 			if ((tlbt->reload == TNDB_LOAD) ||
1528f875b4ebSrica 			    (tlbt->reload == TNDB_DELETE)) {
1529f875b4ebSrica 			/*
1530f875b4ebSrica 			 * We have to call tnrh() with tsol_rhent argument.
1531f875b4ebSrica 			 * Construct such a struct from the tlbt struct we have.
1532f875b4ebSrica 			 */
1533f875b4ebSrica 				rhentp.rh_address.ip_addr_v4.sin_addr.s_addr =
1534f875b4ebSrica 				    tlbt->addr;
1535f875b4ebSrica 				rhentp.rh_address.ip_addr_v4.sin_family =
1536f875b4ebSrica 				    AF_INET;
1537f875b4ebSrica 				rhentp.rh_prefix = tlbt->masklen_used;
1538f875b4ebSrica 				(void) strcpy(rhentp.rh_template,
1539f875b4ebSrica 				    tlbt->template_name);
1540f875b4ebSrica 
1541f875b4ebSrica #ifdef DEBUG
1542f875b4ebSrica 				(void) fprintf(logf, "load op =%d\n",
1543f875b4ebSrica 				    tlbt->reload);
1544f875b4ebSrica 				print_tlbt(tlbt);
1545f875b4ebSrica #endif
1546f875b4ebSrica 				update_rh_entry(tlbt->reload, &rhentp);
1547f875b4ebSrica 
1548f875b4ebSrica 				if (tlbt->reload == TNDB_DELETE) {
1549f875b4ebSrica 					if (tlbt == tnrh_cache_table[i]) {
1550f875b4ebSrica 						tnrh_cache_table[i] =
1551f875b4ebSrica 						    tlbt->next;
1552f875b4ebSrica 						prev = tnrh_cache_table[i];
1553f875b4ebSrica 					} else {
1554f875b4ebSrica 						prev->next = tlbt->next;
1555f875b4ebSrica 						prev = prev->next;
1556f875b4ebSrica 					}
1557f875b4ebSrica 
1558f875b4ebSrica 					free(tlbt);
1559f875b4ebSrica 					if (prev == NULL)
1560f875b4ebSrica 						break;
1561f875b4ebSrica 					else {
1562f875b4ebSrica 						tlbt = prev;
1563f875b4ebSrica 						continue;
1564f875b4ebSrica 					}
1565f875b4ebSrica 				}
1566f875b4ebSrica 				tlbt->reload = TNDB_NOOP;
1567f875b4ebSrica 			}
1568f875b4ebSrica 
1569f875b4ebSrica 			prev = tlbt;
1570f875b4ebSrica 			tlbt = tlbt->next;
1571f875b4ebSrica 		}
1572f875b4ebSrica 	}
1573f875b4ebSrica 
1574f875b4ebSrica }
1575f875b4ebSrica 
1576f875b4ebSrica /* load marked rh ents into kernel */
1577f875b4ebSrica static void
1578f875b4ebSrica load_rh_marked_v6()
1579f875b4ebSrica {
1580f875b4ebSrica 	int i;
1581f875b4ebSrica 	tnrh_tlb_ipv6_t *tlbt, *prev;
1582f875b4ebSrica 	struct tsol_rhent rhentp;
1583f875b4ebSrica 
1584f875b4ebSrica 	(void) memset((char *)&rhentp, '\0', sizeof (rhentp));
1585f875b4ebSrica 
1586f875b4ebSrica 	for (i = 0; i < TNRH_TABLE_HASH_SIZE; i++) {
1587f875b4ebSrica 		prev = tlbt = tnrh_cache_table_v6[i];
1588f875b4ebSrica 
1589f875b4ebSrica 		while (tlbt != NULL) {
1590f875b4ebSrica 		if ((tlbt->reload == TNDB_LOAD) ||
1591f875b4ebSrica 		    (tlbt->reload == TNDB_DELETE)) {
1592f875b4ebSrica 			/*
1593f875b4ebSrica 			 * We have to call tnrh() with tsol_rhent argument.
1594f875b4ebSrica 			 * Construct such a struct from the tlbt struct we have.
1595f875b4ebSrica 			 */
1596f875b4ebSrica 			(void) memcpy(&rhentp.rh_address.ip_addr_v6.sin6_addr,
1597f875b4ebSrica 			    &tlbt->addr, sizeof (in6_addr_t));
1598f875b4ebSrica 			rhentp.rh_address.ip_addr_v6.sin6_family = AF_INET6;
1599f875b4ebSrica 			rhentp.rh_prefix = tlbt->masklen_used;
1600f875b4ebSrica 			(void) strcpy(rhentp.rh_template, tlbt->template_name);
1601f875b4ebSrica 
1602f875b4ebSrica 			update_rh_entry(tlbt->reload, &rhentp);
1603f875b4ebSrica 
1604f875b4ebSrica 			if (tlbt->reload == TNDB_DELETE) {
1605f875b4ebSrica 				if (tlbt == tnrh_cache_table_v6[i]) {
1606f875b4ebSrica 					tnrh_cache_table_v6[i] =
1607f875b4ebSrica 					    tlbt->next;
1608f875b4ebSrica 					prev = tnrh_cache_table_v6[i];
1609f875b4ebSrica 				} else {
1610f875b4ebSrica 					prev->next = tlbt->next;
1611f875b4ebSrica 					prev = prev->next;
1612f875b4ebSrica 				}
1613f875b4ebSrica 
1614f875b4ebSrica 				free(tlbt);
1615f875b4ebSrica 				if (prev == NULL)
1616f875b4ebSrica 					break;
1617f875b4ebSrica 				else {
1618f875b4ebSrica 					tlbt = prev;
1619f875b4ebSrica 					continue;
1620f875b4ebSrica 				}
1621f875b4ebSrica 			}
1622f875b4ebSrica 			tlbt->reload = TNDB_NOOP;
1623f875b4ebSrica 		}
1624f875b4ebSrica 
1625f875b4ebSrica 		prev = tlbt;
1626f875b4ebSrica 		tlbt = tlbt->next;
1627f875b4ebSrica 	}
1628f875b4ebSrica 	}
1629f875b4ebSrica 
1630f875b4ebSrica }
1631f875b4ebSrica 
1632f875b4ebSrica /*
1633f875b4ebSrica  * Does the real load/delete for the entry depending on op code.
1634f875b4ebSrica  */
1635f875b4ebSrica 
1636f875b4ebSrica static void
1637f875b4ebSrica update_rh_entry(int op, struct tsol_rhent *rhentp)
1638f875b4ebSrica {
1639f875b4ebSrica #ifdef DEBUG
1640f875b4ebSrica 	(void) fprintf(logf, gettext("\t###update_rh_entry op = %d\n"), op);
1641f875b4ebSrica 	print_entry(rhentp, AF_INET);
1642f875b4ebSrica #endif
1643f875b4ebSrica 	if (tnrh(op, rhentp) != 0) {
1644f875b4ebSrica 		if (debugl && (logf != NULL)) {
1645f875b4ebSrica 			(void) fprintf(logf, "%s : ", gettime());
1646f875b4ebSrica 			(void) fprintf(logf, gettext("tnrh() failed: %s\n"),
1647f875b4ebSrica 			    strerror(errno));
1648f875b4ebSrica 			if (op == TNDB_LOAD)
1649f875b4ebSrica 			(void) fprintf(logf,
1650f875b4ebSrica 			    gettext("load of remote host database "
1651f875b4ebSrica 			    "%s into kernel cache failed\n"),
1652f875b4ebSrica 			    rhentp->rh_template);
1653f875b4ebSrica 			if (op == TNDB_DELETE)
1654f875b4ebSrica 			(void) fprintf(logf,
1655f875b4ebSrica 			    gettext("delete of remote host database "
1656f875b4ebSrica 			    "%s from kernel cache failed\n"),
1657f875b4ebSrica 			    rhentp->rh_template);
1658f875b4ebSrica 			(void) fflush(logf);
1659f875b4ebSrica 		}
1660f875b4ebSrica 		cprint("tnrh() failed..: %s\n", strerror(errno));
1661f875b4ebSrica 	}
1662f875b4ebSrica }
1663f875b4ebSrica 
1664f875b4ebSrica static void
1665f875b4ebSrica timer()
1666f875b4ebSrica {
1667f875b4ebSrica 	poll_now();
1668f875b4ebSrica 	(void) alarm(poll_interval);
1669f875b4ebSrica }
1670f875b4ebSrica 
1671f875b4ebSrica #define	max(a, b)	((a) > (b) ? (a) : (b))
1672f875b4ebSrica 
1673f875b4ebSrica static void
1674f875b4ebSrica poll_now()
1675f875b4ebSrica {
1676f875b4ebSrica 
1677f875b4ebSrica 	(void) fprintf(logf, "enter poll_now at %s \n", gettime());
1678f875b4ebSrica 	(void) fflush(logf);
1679f875b4ebSrica 
1680f875b4ebSrica 	if (nss_get_tp() > 0) {
1681f875b4ebSrica 		load_tp();
1682f875b4ebSrica 		tp_flush_cache();
1683f875b4ebSrica 	}
1684f875b4ebSrica 
1685f875b4ebSrica #ifdef DEBUG
1686f875b4ebSrica 	(void) fprintf(logf, "now search for tnrhdb update %s \n", gettime());
1687f875b4ebSrica #endif
1688f875b4ebSrica 
1689f875b4ebSrica 	if (nss_get_rh() > 0) {
1690f875b4ebSrica 		if (logf != NULL) {
1691f875b4ebSrica 			(void) fprintf(logf, "tnrhdb needs update %s \n",
1692f875b4ebSrica 			    gettime());
1693f875b4ebSrica 		}
1694f875b4ebSrica 
1695f875b4ebSrica 		(void) rw_wrlock(&cache_rwlp);
1696f875b4ebSrica 		/* This function will cleanup cache table */
1697f875b4ebSrica 		load_rh_marked();
1698f875b4ebSrica 		(void) rw_unlock(&cache_rwlp);
1699f875b4ebSrica 
1700f875b4ebSrica 		(void) rw_wrlock(&cache_rwlp_v6);
1701f875b4ebSrica 		/* This function will cleanup cache table */
1702f875b4ebSrica 		load_rh_marked_v6();
1703f875b4ebSrica 		(void) rw_unlock(&cache_rwlp_v6);
1704f875b4ebSrica 	}
1705f875b4ebSrica 
1706f875b4ebSrica #ifdef DEBUG
1707f875b4ebSrica 	if (logf != NULL) {
1708f875b4ebSrica 		cachetable_print();
1709f875b4ebSrica 		cachetable_print_v6();
1710f875b4ebSrica 
1711f875b4ebSrica 		(void) fprintf(logf, "rh table begin\n");
1712f875b4ebSrica 		rhtable_print();
1713f875b4ebSrica 		rhtable_print_v6();
1714f875b4ebSrica 		(void) fprintf(logf, "rh table end \n");
1715f875b4ebSrica 		(void) fprintf(logf, "-------------------------\n\n");
1716f875b4ebSrica 		(void) fflush(logf);
1717f875b4ebSrica 	}
1718f875b4ebSrica #endif
1719f875b4ebSrica }
1720f875b4ebSrica 
1721f875b4ebSrica static void
1722f875b4ebSrica tnd_serve()
1723f875b4ebSrica {
1724f875b4ebSrica 	for (;;) {
1725f875b4ebSrica 		(void) pause();
1726f875b4ebSrica 	}
1727f875b4ebSrica }
1728f875b4ebSrica 
1729f875b4ebSrica static void
1730f875b4ebSrica terminate()
1731f875b4ebSrica {
1732f875b4ebSrica 	if (debugl && (logf != NULL)) {
1733f875b4ebSrica 		(void) fprintf(logf, "%s : ", gettime());
1734f875b4ebSrica 		(void) fprintf(logf, gettext("tnd terminating on signal.\n"));
1735f875b4ebSrica 		(void) fflush(logf);
1736f875b4ebSrica 	}
1737f875b4ebSrica 	exit(1);
1738f875b4ebSrica }
1739f875b4ebSrica 
1740f875b4ebSrica static void
1741f875b4ebSrica noop()
1742f875b4ebSrica {
1743f875b4ebSrica }
1744f875b4ebSrica 
1745f875b4ebSrica static char *
1746f875b4ebSrica gettime()
1747f875b4ebSrica {
1748f875b4ebSrica 	time_t now;
1749f875b4ebSrica 	struct tm *tp, tm;
1750f875b4ebSrica 	char *fmt;
1751f875b4ebSrica 
1752f875b4ebSrica 	(void) time(&now);
1753f875b4ebSrica 	tp = localtime(&now);
1754f875b4ebSrica 	(void) memcpy(&tm, tp, sizeof (struct tm));
1755f875b4ebSrica 	fmt = nl_langinfo(_DATE_FMT);
1756f875b4ebSrica 
1757f875b4ebSrica 	(void) strftime(time_buf, _SZ_TIME_BUF, fmt, &tm);
1758f875b4ebSrica 
1759f875b4ebSrica 	return (time_buf);
1760f875b4ebSrica }
1761f875b4ebSrica /*
1762f875b4ebSrica  * debugging routines
1763f875b4ebSrica  */
1764f875b4ebSrica 
1765f875b4ebSrica 
1766f875b4ebSrica #ifdef DEBUG
1767f875b4ebSrica static void
1768f875b4ebSrica print_cache_entry(tnrh_tlb_t *tlbt)
1769f875b4ebSrica {
1770f875b4ebSrica 	struct in_addr addr;
1771f875b4ebSrica 
1772f875b4ebSrica 	addr.s_addr = tlbt->addr;
1773f875b4ebSrica 	(void) fprintf(logf, "\tIP address: %s", inet_ntoa(addr));
1774f875b4ebSrica 	(void) fprintf(logf, "\tTemplate name: %s", tlbt->template_name);
1775f875b4ebSrica 	(void) fprintf(logf, "\tMask length used: %d\n", tlbt->masklen_used);
1776f875b4ebSrica }
1777f875b4ebSrica 
1778f875b4ebSrica static void
1779f875b4ebSrica print_cache_entry_v6(tnrh_tlb_ipv6_t *tlbt)
1780f875b4ebSrica {
1781f875b4ebSrica 	char abuf[INET6_ADDRSTRLEN];
1782f875b4ebSrica 
1783f875b4ebSrica 	(void) fprintf(logf, "\tIP address: %s",
1784f875b4ebSrica 	    inet_ntop(AF_INET6, &tlbt->addr, abuf, sizeof (abuf)));
1785f875b4ebSrica 	(void) fprintf(logf, "\tTemplate name: %s", tlbt->template_name);
1786f875b4ebSrica 	(void) fprintf(logf, "\tMask length used: %d\n", tlbt->masklen_used);
1787f875b4ebSrica }
1788f875b4ebSrica 
1789f875b4ebSrica static void
1790f875b4ebSrica cachetable_print()
1791f875b4ebSrica {
1792f875b4ebSrica 	int i;
1793f875b4ebSrica 	tnrh_tlb_t *tlbt;
1794f875b4ebSrica 
1795f875b4ebSrica 	(void) fprintf(logf, "-------------------------\n");
1796f875b4ebSrica 	(void) fprintf(logf, "Cache table begin\n");
1797f875b4ebSrica 
1798f875b4ebSrica 	for (i = 0; i < TNRH_TABLE_HASH_SIZE; i++) {
1799f875b4ebSrica 		if ((tlbt = tnrh_cache_table[i]) != NULL)
1800f875b4ebSrica 			print_cache_entry(tlbt);
1801f875b4ebSrica 	}
1802f875b4ebSrica 
1803f875b4ebSrica 	(void) fprintf(logf, "Cache table end \n");
1804f875b4ebSrica 	(void) fprintf(logf, "-------------------------\n\n");
1805f875b4ebSrica }
1806f875b4ebSrica 
1807f875b4ebSrica static void
1808f875b4ebSrica cachetable_print_v6()
1809f875b4ebSrica {
1810f875b4ebSrica 	int i;
1811f875b4ebSrica 	tnrh_tlb_ipv6_t *tlbt;
1812f875b4ebSrica 
1813f875b4ebSrica 	(void) fprintf(logf, "-------------------------\n");
1814f875b4ebSrica 	(void) fprintf(logf, "Cache table begin\n");
1815f875b4ebSrica 
1816f875b4ebSrica 	for (i = 0; i < TNRH_TABLE_HASH_SIZE; i++) {
1817f875b4ebSrica 		if ((tlbt = tnrh_cache_table_v6[i]) != NULL)
1818f875b4ebSrica 			print_cache_entry_v6(tlbt);
1819f875b4ebSrica 	}
1820f875b4ebSrica 
1821f875b4ebSrica 	(void) fprintf(logf, "Cache table end \n");
1822f875b4ebSrica 	(void) fprintf(logf, "-------------------------\n\n");
1823f875b4ebSrica }
1824f875b4ebSrica 
1825f875b4ebSrica 
1826f875b4ebSrica static void
1827f875b4ebSrica print_entry(tsol_rhent_t *ent, int af)
1828f875b4ebSrica {
1829f875b4ebSrica 	struct sockaddr_in *saddrp;
1830f875b4ebSrica 	struct sockaddr_in6 *saddrp6;
1831f875b4ebSrica 	char abuf[INET6_ADDRSTRLEN];
1832f875b4ebSrica 
1833f875b4ebSrica 	if (af == AF_INET) {
1834f875b4ebSrica 		saddrp = (struct sockaddr_in *)&ent->rh_address.ip_addr_v4;
1835f875b4ebSrica 		(void) fprintf(logf, gettext("\tIP address: %s"),
1836f875b4ebSrica 		    inet_ntoa(saddrp->sin_addr));
1837f875b4ebSrica 	} else if (af == AF_INET6) {
1838f875b4ebSrica 		saddrp6 = (struct sockaddr_in6 *)&ent->rh_address.ip_addr_v6;
1839f875b4ebSrica 		(void) fprintf(logf, gettext("\tIP address: %s"),
1840f875b4ebSrica 		    inet_ntop(AF_INET6, &saddrp6->sin6_addr, abuf,
1841f875b4ebSrica 		    sizeof (abuf)));
1842f875b4ebSrica 	}
1843f875b4ebSrica 
1844f875b4ebSrica 	(void) fprintf(logf,
1845f875b4ebSrica 	    gettext("\tTemplate name: %s"), ent->rh_template);
1846f875b4ebSrica 	(void) fprintf(logf, gettext("\tprefix_len: %d\n"), ent->rh_prefix);
1847f875b4ebSrica 	(void) fflush(logf);
1848f875b4ebSrica }
1849f875b4ebSrica 
1850f875b4ebSrica static void
1851f875b4ebSrica print_tlbt(tnrh_tlb_t *tlbt)
1852f875b4ebSrica {
1853f875b4ebSrica 	(void) fprintf(logf, "tlbt addr = 0x%4x name = %s \
1854f875b4ebSrica 	    mask = %u, reload = %d\n", tlbt->addr, tlbt->template_name,
1855f875b4ebSrica 	    tlbt->masklen_used, tlbt->reload);
1856f875b4ebSrica }
1857f875b4ebSrica 
1858f875b4ebSrica static void
1859f875b4ebSrica rhtable_print()
1860f875b4ebSrica {
1861f875b4ebSrica 	rhtable_walk(print_entry);
1862f875b4ebSrica 	(void) fprintf(logf, "-----------------------------\n\n");
1863f875b4ebSrica }
1864f875b4ebSrica 
1865f875b4ebSrica static void
1866f875b4ebSrica rhtable_print_v6()
1867f875b4ebSrica {
1868f875b4ebSrica 	rhtable_walk_v6(print_entry);
1869f875b4ebSrica 	(void) fprintf(logf, "-----------------------------\n\n");
1870f875b4ebSrica }
1871f875b4ebSrica 
1872f875b4ebSrica /*
1873f875b4ebSrica  * Walk through all the entries in tnrh_entire_table[][]
1874f875b4ebSrica  * and execute the function passing the entry as argument.
1875f875b4ebSrica  */
1876f875b4ebSrica static void
1877f875b4ebSrica rhtable_walk(void (*action)())
1878f875b4ebSrica {
1879f875b4ebSrica 	int i, j;
1880f875b4ebSrica 	tnd_tnrhdb_t *rhent;
1881f875b4ebSrica 
1882f875b4ebSrica 	for (i = 0; i <= IP_ABITS; i++) {
1883f875b4ebSrica 		if (tnrh_entire_table[i] == NULL)
1884f875b4ebSrica 			continue;
1885f875b4ebSrica 
1886f875b4ebSrica 		for (j = 0; j < TNRH_TABLE_HASH_SIZE; j++) {
1887f875b4ebSrica 			rhent = tnrh_entire_table[i][j];
1888f875b4ebSrica 
1889f875b4ebSrica 			while (rhent != NULL) {
1890f875b4ebSrica 				action(&rhent->rh_ent, AF_INET);
1891f875b4ebSrica 				rhent = rhent->rh_next;
1892f875b4ebSrica 			}
1893f875b4ebSrica 		}
1894f875b4ebSrica 	}
1895f875b4ebSrica }
1896f875b4ebSrica 
1897f875b4ebSrica /*
1898f875b4ebSrica  * Walk through all the entries in tnrh_entire_table_v6[][]
1899f875b4ebSrica  * and execute the function passing the entry as argument.
1900f875b4ebSrica  */
1901f875b4ebSrica static void
1902f875b4ebSrica rhtable_walk_v6(void (*action)())
1903f875b4ebSrica {
1904f875b4ebSrica 	int i, j;
1905f875b4ebSrica 	tnd_tnrhdb_t *rhent;
1906f875b4ebSrica 
1907f875b4ebSrica 	for (i = 0; i <= IPV6_ABITS; i++) {
1908f875b4ebSrica 		if (tnrh_entire_table_v6[i] == NULL)
1909f875b4ebSrica 			continue;
1910f875b4ebSrica 
1911f875b4ebSrica 		for (j = 0; j < TNRH_TABLE_HASH_SIZE; j++) {
1912f875b4ebSrica 			rhent = tnrh_entire_table_v6[i][j];
1913f875b4ebSrica 
1914f875b4ebSrica 			while (rhent != NULL) {
1915f875b4ebSrica 				action(&rhent->rh_ent, AF_INET6);
1916f875b4ebSrica 				rhent = rhent->rh_next;
1917f875b4ebSrica 			}
1918f875b4ebSrica 		}
1919f875b4ebSrica 	}
1920f875b4ebSrica }
1921f875b4ebSrica #endif /* DEBUG */
1922