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
main(int argc,char ** argv)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
rhaddr_compar_mask(struct sockaddr_in * tp1,struct tnd_tnrhdb_c * tp2,int i)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
rhaddr_compar(struct sockaddr_in * tp1,struct tnd_tnrhdb_c * tp2)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
rhaddr_compar_mask_v6(struct sockaddr_in6 * tp1,struct tnd_tnrhdb_c * tp2,int i)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
rhaddr_compar_v6(struct sockaddr_in6 * tp1,struct tnd_tnrhdb_c * tp2)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
get_hashvalue(in_addr_t addr)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
rh_index_to_mask(uint_t masklen)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 *
rh_index_to_mask_v6(uint_t masklen,in6_addr_t * bitmask)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
parse_opts(argc,argv)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
check_debugl(debug_level)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 *
tnlog_open(logfile)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
detachfromtty()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
usage()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
isnumber(s)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
any_compar(const void * v1,const void * v2)563f875b4ebSrica any_compar(const void *v1, const void *v2)
564f875b4ebSrica {
565f875b4ebSrica return (0);
566f875b4ebSrica }
567f875b4ebSrica
568f875b4ebSrica static int
tp_compar(const void * v1,const void * v2)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
nss_get_tp()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
load_tp()609f875b4ebSrica load_tp()
610f875b4ebSrica {
611f875b4ebSrica twalk(tp_tree, load_tp_entry);
612f875b4ebSrica }
613f875b4ebSrica
614f875b4ebSrica
615f875b4ebSrica static void
616f875b4ebSrica /* LINTED */
load_tp_entry(struct tnd_tnrhtp_c ** tppp,VISIT visit,int level)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
tp_flush_cache()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
nss_get_rh()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
handle_unvisited_nodes()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
handle_unvisited_nodes_v6()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
rhtable_search_and_update(struct tsol_rhent * ent,int duplflag)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
rhtable_search_and_update_v6(struct tsol_rhent * ent,int duplflag)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 *
rhtable_lookup(struct sockaddr_in * saddrp,int i)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 *
rhtable_lookup_v6(struct sockaddr_in6 * saddrp,in6_addr_t mask,int i)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
add_cache_entry(in_addr_t addr,char * name,int indx,tnd_tnrhdb_t * src)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 *
lookup_cache_table(in_addr_t addr)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
add_cache_entry_v6(in6_addr_t addr,char * name,int indx,tnd_tnrhdb_t * src)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 *
lookup_cache_table_v6(in6_addr_t addr)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
update_cache_table(tsol_rhent_t * ent,tnd_tnrhdb_t * src)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
update_cache_table_v6(tsol_rhent_t * ent,tnd_tnrhdb_t * src)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
is_better_match(in_addr_t newaddr,int indx,tnrh_tlb_t * tlbt)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
walk_cache_table(in_addr_t newaddr,char * name,int indx,tnd_tnrhdb_t * src)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
is_better_match_v6(in6_addr_t newaddr,int indx,tnrh_tlb_ipv6_t * tlbt)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
walk_cache_table_v6(in6_addr_t newaddr,char * name,int indx,tnd_tnrhdb_t * src)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
load_rh_marked()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
load_rh_marked_v6()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
update_rh_entry(int op,struct tsol_rhent * rhentp)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
timer()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
poll_now()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
tnd_serve()1722f875b4ebSrica tnd_serve()
1723f875b4ebSrica {
1724f875b4ebSrica for (;;) {
1725f875b4ebSrica (void) pause();
1726f875b4ebSrica }
1727f875b4ebSrica }
1728f875b4ebSrica
1729f875b4ebSrica static void
terminate()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
noop()1741f875b4ebSrica noop()
1742f875b4ebSrica {
1743f875b4ebSrica }
1744f875b4ebSrica
1745f875b4ebSrica static char *
gettime()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
print_cache_entry(tnrh_tlb_t * tlbt)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
print_cache_entry_v6(tnrh_tlb_ipv6_t * tlbt)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
cachetable_print()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
cachetable_print_v6()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
print_entry(tsol_rhent_t * ent,int af)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
print_tlbt(tnrh_tlb_t * tlbt)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
rhtable_print()1859f875b4ebSrica rhtable_print()
1860f875b4ebSrica {
1861f875b4ebSrica rhtable_walk(print_entry);
1862f875b4ebSrica (void) fprintf(logf, "-----------------------------\n\n");
1863f875b4ebSrica }
1864f875b4ebSrica
1865f875b4ebSrica static void
rhtable_print_v6()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
rhtable_walk(void (* action)())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
rhtable_walk_v6(void (* action)())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