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