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