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