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