14746Srica /*
24746Srica * CDDL HEADER START
34746Srica *
44746Srica * The contents of this file are subject to the terms of the
54746Srica * Common Development and Distribution License (the "License").
64746Srica * You may not use this file except in compliance with the License.
74746Srica *
84746Srica * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94746Srica * or http://www.opensolaris.org/os/licensing.
104746Srica * See the License for the specific language governing permissions
114746Srica * and limitations under the License.
124746Srica *
134746Srica * When distributing Covered Code, include this CDDL HEADER in each
144746Srica * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154746Srica * If applicable, add the following below this CDDL HEADER, with the
164746Srica * fields enclosed by brackets "[]" replaced with your own identifying
174746Srica * information: Portions Copyright [yyyy] [name of copyright owner]
184746Srica *
194746Srica * CDDL HEADER END
204746Srica */
214746Srica
224746Srica /*
234746Srica * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
244746Srica * Use is subject to license terms.
254746Srica */
264746Srica
274746Srica #pragma ident "%Z%%M% %I% %E% SMI"
284746Srica
294746Srica #include <sys/types.h>
304746Srica #include <time.h>
314746Srica #include <unistd.h>
324746Srica #include <stdio.h>
334746Srica #include <sys/fcntl.h>
344746Srica #include <sys/stat.h>
354746Srica #include <fcntl.h>
364746Srica #include <locale.h>
374746Srica #include <langinfo.h>
384746Srica #include <search.h>
394746Srica #include <tsol/label.h>
404746Srica #include <errno.h>
414746Srica #include <sys/tsol/tndb.h>
424746Srica #include <sys/socket.h>
434746Srica #include <netinet/in.h>
444746Srica #include <arpa/inet.h>
454746Srica #include <netdb.h>
464746Srica #include <signal.h>
474746Srica #include <sys/signal.h>
484746Srica #include <string.h>
494746Srica #include <stdlib.h>
504746Srica #include <unistd.h>
514746Srica #include <stdarg.h>
524746Srica #include <syslog.h>
534746Srica #include <ctype.h>
544746Srica #include <pwd.h>
554746Srica #include <grp.h>
564746Srica #include <door.h>
574746Srica #include <synch.h>
584746Srica #include <sys/tsol/tsyscall.h>
594746Srica #include <nss_dbdefs.h>
604746Srica #include <libtsnet.h>
614746Srica #include <zone.h>
624746Srica
634746Srica #include "tnd.h"
644746Srica
654746Srica static FILE *tnlog_open(char *);
664746Srica static void usage();
674746Srica static void parse_opts(int, char **);
684746Srica static int check_debugl(int);
694746Srica static void load_tp();
704746Srica static void load_tp_entry();
714746Srica static void tnd_serve();
724746Srica static void detachfromtty();
734746Srica static void terminate();
744746Srica static void noop();
754746Srica static char *gettime();
764746Srica static int isnumber(char *);
774746Srica static void poll_now();
784746Srica static int nss_get_tp();
794746Srica static int nss_get_rh();
804746Srica static void timer();
814746Srica static void load_rh_marked();
824746Srica static int rhtable_search_and_update(struct tsol_rhent *ent, int duplflag);
834746Srica static int is_better_match(in_addr_t newaddr, int indx, tnrh_tlb_t *tlbt);
844746Srica static int walk_cache_table(in_addr_t newaddr, char *name,
854746Srica int indx, tnd_tnrhdb_t *src);
864746Srica static tnrh_tlb_t *lookup_cache_table(in_addr_t addr);
874746Srica static int update_cache_table(tsol_rhent_t *ent, tnd_tnrhdb_t *src);
884746Srica static void update_rh_entry(int op, struct tsol_rhent *rhentp);
894746Srica static int handle_unvisited_nodes();
904746Srica static in_addr_t rh_index_to_mask(uint_t masklen);
914746Srica static tnrh_tlb_ipv6_t *lookup_cache_table_v6(in6_addr_t addr);
924746Srica static in6_addr_t *rh_index_to_mask_v6(uint_t masklen, in6_addr_t *bitmask);
934746Srica static void load_rh_marked_v6();
944746Srica static int
954746Srica rhtable_search_and_update_v6(struct tsol_rhent *ent, int duplflag);
964746Srica static int walk_cache_table_v6(in6_addr_t newaddr, char *name,
974746Srica int indx, tnd_tnrhdb_t *src);
984746Srica static int update_cache_table_v6(tsol_rhent_t *ent, tnd_tnrhdb_t *src);
994746Srica static int handle_unvisited_nodes_v6();
1004746Srica
1014746Srica #ifdef DEBUG
1024746Srica static void print_entry(tsol_rhent_t *ent, int af);
1034746Srica static void print_tlbt(tnrh_tlb_t *tlbt);
1044746Srica static void rhtable_print();
1054746Srica static void cachetable_print();
1064746Srica static void rhtable_walk(void (*action)());
1074746Srica static void cachetable_print_v6();
1084746Srica static void rhtable_print_v6();
1094746Srica static void rhtable_walk_v6(void (*action)());
1104746Srica #endif /* DEBUG */
1114746Srica
1124746Srica /*
1134746Srica * The following constants and structures and the functions
1144746Srica * that operate on them are similar to the ip_ire.c and ip6_ire.c
1154746Srica * code in the kernel.
1164746Srica */
1174746Srica #define TNRH_TABLE_HASH_SIZE 256
1184746Srica #define IP_ABITS 32
1194746Srica #define IP_MASK_TABLE_SIZE (IP_ABITS + 1)
1204746Srica #define RH_HOST_MASK (in_addr_t)0xffffffffU
1214746Srica
1224746Srica #define IPV6_ABITS 128
1234746Srica #define IPV6_MASK_TABLE_SIZE (IPV6_ABITS + 1)
1244746Srica #define s6_addr8 _S6_un._S6_u8
1254746Srica #define s6_addr32 _S6_un._S6_u32
1264746Srica
1274746Srica /*
1284746Srica * Exclusive-or the 6 bytes that are likely to contain the MAC
1294746Srica * address. Assumes table_size does not exceed 256.
1304746Srica * Assumes EUI-64 format for good hashing.
1314746Srica */
1324746Srica #define TNRH_ADDR_HASH_V6(addr) \
1334746Srica (((addr).s6_addr8[8] ^ (addr).s6_addr8[9] ^ \
1344746Srica (addr).s6_addr8[10] ^ (addr).s6_addr8[13] ^ \
1354746Srica (addr).s6_addr8[14] ^ (addr).s6_addr8[15]) % TNRH_TABLE_HASH_SIZE)
1364746Srica
1374746Srica #define TNRH_ADDR_MASK_HASH_V6(addr, mask) \
1384746Srica ((((addr).s6_addr8[8] & (mask).s6_addr8[8]) ^ \
1394746Srica ((addr).s6_addr8[9] & (mask).s6_addr8[9]) ^ \
1404746Srica ((addr).s6_addr8[10] & (mask).s6_addr8[10]) ^ \
1414746Srica ((addr).s6_addr8[13] & (mask).s6_addr8[13]) ^ \
1424746Srica ((addr).s6_addr8[14] & (mask).s6_addr8[14]) ^ \
1434746Srica ((addr).s6_addr8[15] & (mask).s6_addr8[15])) % TNRH_TABLE_HASH_SIZE)
1444746Srica
1454746Srica /* Mask comparison: is IPv6 addr a, and'ed with mask m, equal to addr b? */
1464746Srica #define V6_MASK_EQ(a, m, b) \
1474746Srica ((((a).s6_addr32[0] & (m).s6_addr32[0]) == (b).s6_addr32[0]) && \
1484746Srica (((a).s6_addr32[1] & (m).s6_addr32[1]) == (b).s6_addr32[1]) && \
1494746Srica (((a).s6_addr32[2] & (m).s6_addr32[2]) == (b).s6_addr32[2]) && \
1504746Srica (((a).s6_addr32[3] & (m).s6_addr32[3]) == (b).s6_addr32[3]))
1514746Srica
1524746Srica
1534746Srica const in6_addr_t ipv6_all_zeros = { 0, 0, 0, 0 };
1544746Srica
1554746Srica /*
1564746Srica * This is a table of hash tables to keep
1574746Srica * all the name service entries. We don't have
1584746Srica * a separate hash bucket structure, instead mantain
1594746Srica * a pointer to the hash chain.
1604746Srica */
1614746Srica tnd_tnrhdb_t **tnrh_entire_table[IP_MASK_TABLE_SIZE];
1624746Srica tnd_tnrhdb_t **tnrh_entire_table_v6[IPV6_MASK_TABLE_SIZE];
1634746Srica
1644746Srica /* reader/writer lock for tnrh_entire_table */
1654746Srica rwlock_t entire_rwlp;
1664746Srica rwlock_t entire_rwlp_v6;
1674746Srica
1684746Srica
1694746Srica /*
1704746Srica * This is a hash table which keeps fully resolved
1714746Srica * tnrhdb entries <IP address, Host type>. We don't have
1724746Srica * a separate hash bucket structure, instead
1734746Srica * mantain a pointer to the hash chain.
1744746Srica */
1754746Srica tnrh_tlb_t *tnrh_cache_table[TNRH_TABLE_HASH_SIZE];
1764746Srica tnrh_tlb_ipv6_t *tnrh_cache_table_v6[TNRH_TABLE_HASH_SIZE];
1774746Srica
1784746Srica /* reader/writer lock for tnrh_cache_table */
1794746Srica rwlock_t cache_rwlp;
1804746Srica rwlock_t cache_rwlp_v6;
1814746Srica
1824746Srica FILE *logf;
1834746Srica int debugl = 0;
1844746Srica int poll_interval = TND_DEF_POLL_TIME;
1854746Srica int delay_poll_flag = 0;
1864746Srica
1874746Srica void *tp_tree;
1884746Srica
1894746Srica #define _SZ_TIME_BUF 100
1904746Srica char time_buf[_SZ_TIME_BUF];
1914746Srica
1924746Srica #define cprint(s, param) { \
1934746Srica register FILE *consl; \
1944746Srica \
1954746Srica if ((consl = fopen("/dev/msglog", "w")) != NULL) { \
1964746Srica setbuf(consl, NULL); \
1974746Srica (void) fprintf(consl, "tnd: "); \
1984746Srica (void) fprintf(consl, s, param); \
1994746Srica (void) fclose(consl); \
2004746Srica } \
2014746Srica }
2024746Srica
2034746Srica #define RHENT_BUF_SIZE 300
2044746Srica #define TPENT_BUF_SIZE 2000
2054746Srica
2064746Srica /* 128 privs * (24 bytes + 1 deliminator)= 3200 bytes + 1200 cushion */
2074746Srica #define STRING_PRIVS_SIZE 4800
2084746Srica #define ID_ENT_SIZE 500
2094746Srica
210*4751Srica int
main(int argc,char ** argv)2114746Srica main(int argc, char **argv)
2124746Srica {
2134746Srica
2144746Srica
2154746Srica const ucred_t *uc = NULL;
2164746Srica const priv_set_t *pset;
2174746Srica struct sigaction act;
2184746Srica
2194746Srica /* set the locale for only the messages system (all else is clean) */
2204746Srica (void) setlocale(LC_ALL, "");
2214746Srica #ifndef TEXT_DOMAIN /* Should be defined by cc -D */
2224746Srica #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
2234746Srica #endif
2244746Srica (void) textdomain(TEXT_DOMAIN);
2254746Srica
2264746Srica if (getzoneid() != GLOBAL_ZONEID) {
2274746Srica syslog(LOG_ERR, "can not run tnd from a local zone");
2284746Srica exit(-1);
2294746Srica }
2304746Srica
2314746Srica
2324746Srica if (((uc = ucred_get(getpid())) == NULL) ||
2334746Srica ((pset = ucred_getprivset(uc, PRIV_EFFECTIVE)) == NULL)) {
2344746Srica syslog(LOG_ERR, "don't have privilege set");
2354746Srica exit(-1);
2364746Srica }
2374746Srica
2384746Srica if (!priv_ismember(pset, PRIV_SYS_NET_CONFIG)) {
2394746Srica syslog(LOG_ERR, "don't have privilege to run tnd");
2404746Srica exit(-1);
2414746Srica }
2424746Srica
2434746Srica
2444746Srica /* parse command line options */
2454746Srica (void) parse_opts(argc, argv);
2464746Srica
2474746Srica /*
2484746Srica * Initialize reader/writer locks. To be
2494746Srica * used within this process only.
2504746Srica */
2514746Srica if ((rwlock_init(&entire_rwlp, USYNC_THREAD, 0) != 0) ||
2524746Srica (rwlock_init(&entire_rwlp_v6, USYNC_THREAD, 0) != 0) ||
2534746Srica (rwlock_init(&cache_rwlp, USYNC_THREAD, 0) != 0) ||
2544746Srica (rwlock_init(&cache_rwlp_v6, USYNC_THREAD, 0) != 0)) {
2554746Srica syslog(LOG_ERR, "cannot initialize lock");
2564746Srica exit(-1);
2574746Srica }
2584746Srica
2594746Srica /* catch the usual termination signals for graceful exit */
2604746Srica (void) sigset(SIGINT, terminate);
2614746Srica (void) sigset(SIGTERM, terminate);
2624746Srica (void) sigset(SIGQUIT, terminate);
2634746Srica (void) sigset(SIGUSR1, noop);
2644746Srica
2654746Srica act.sa_handler = timer;
2664746Srica act.sa_flags = SA_RESTART;
2674746Srica (void *) sigemptyset(&act.sa_mask);
2684746Srica (void *) sigaddset(&act.sa_mask, SIGALRM);
2694746Srica (void *) sigaddset(&act.sa_mask, SIGHUP);
2704746Srica (void *) sigaction(SIGALRM, &act, NULL);
2714746Srica (void *) sigaction(SIGHUP, &act, NULL);
2724746Srica
2734746Srica if (debugl == MAX_TND_DEBUG) {
2744746Srica (void) fprintf(logf, "%s : ", gettime());
2754746Srica (void) fprintf(logf, gettext("tnd started. pid= %d\n"),
2764746Srica getpid());
2774746Srica (void) fprintf(logf, "%s : ", gettime());
2784746Srica (void) fprintf(logf,
2794746Srica gettext("max level debugging! not forking\n"));
2804746Srica (void) fflush(logf);
2814746Srica } else {
2824746Srica detachfromtty();
2834746Srica }
2844746Srica
2854746Srica if (!delay_poll_flag) {
2864746Srica (void) sigprocmask(SIG_BLOCK, &act.sa_mask, NULL);
2874746Srica timer();
2884746Srica (void) sigprocmask(SIG_UNBLOCK, &act.sa_mask, NULL);
2894746Srica }
2904746Srica
2914746Srica if (debugl != MAX_TND_DEBUG) {
2924746Srica (void) sigsend(P_PID, getppid(), SIGUSR1);
2934746Srica }
2944746Srica
2954746Srica (void) tnd_serve();
2964746Srica
2974746Srica /* NOT REACHED */
2984746Srica return (0);
2994746Srica }
3004746Srica
3014746Srica
3024746Srica /*
3034746Srica * Compare addresses after masking off unneeded bits.
3044746Srica * We do this to handle addresses where prefix_len is
3054746Srica * less than the bit length.
3064746Srica */
3074746Srica static int
rhaddr_compar_mask(struct sockaddr_in * tp1,struct tnd_tnrhdb_c * tp2,int i)3084746Srica rhaddr_compar_mask(struct sockaddr_in *tp1, struct tnd_tnrhdb_c *tp2, int i)
3094746Srica {
3104746Srica struct sockaddr_in *saddrp;
3114746Srica in_addr_t tmpmask = rh_index_to_mask(i);
3124746Srica
3134746Srica saddrp = (struct sockaddr_in *)(&tp2->rh_ent.rh_address.ip_addr_v4);
3144746Srica
3154746Srica #ifdef DEBUG
3164746Srica (void) fprintf(logf, gettext("rhaddr_compar_mask mask = 0x%4x, \
3174746Srica tp1 = 0x%4x, tp2 = 0x%4x\n"), tmpmask, (tp1->sin_addr),
3184746Srica (saddrp->sin_addr.s_addr & tmpmask));
3194746Srica (void) fprintf(logf, gettext("rhaddr_compar_mask return = %d\n"),
3204746Srica (tp1->sin_addr.s_addr == (saddrp->sin_addr.s_addr & tmpmask)));
3214746Srica #endif
3224746Srica return (tp1->sin_addr.s_addr == (saddrp->sin_addr.s_addr & tmpmask));
3234746Srica }
3244746Srica
3254746Srica
3264746Srica /*
3274746Srica * we use this where exact match is needed.
3284746Srica */
3294746Srica static int
rhaddr_compar(struct sockaddr_in * tp1,struct tnd_tnrhdb_c * tp2)3304746Srica rhaddr_compar(struct sockaddr_in *tp1, struct tnd_tnrhdb_c *tp2)
3314746Srica {
3324746Srica struct sockaddr_in *saddrp;
3334746Srica
3344746Srica saddrp = (struct sockaddr_in *)(&tp2->rh_ent.rh_address.ip_addr_v4);
3354746Srica
3364746Srica #ifdef DEBUG
3374746Srica (void) fprintf(logf, gettext("\t tp1 saddrp IP : %s %s\n"),
3384746Srica inet_ntoa(tp1->sin_addr), inet_ntoa(saddrp->sin_addr));
3394746Srica #endif
3404746Srica
3414746Srica return (tp1->sin_addr.s_addr == saddrp->sin_addr.s_addr);
3424746Srica }
3434746Srica
3444746Srica /*
3454746Srica * Compare v6 addresses after masking off unneeded bits.
3464746Srica * We do this to handle addresses where prefix_len is
3474746Srica * less than the bit length.
3484746Srica */
3494746Srica static int
rhaddr_compar_mask_v6(struct sockaddr_in6 * tp1,struct tnd_tnrhdb_c * tp2,int i)3504746Srica rhaddr_compar_mask_v6(struct sockaddr_in6 *tp1, struct tnd_tnrhdb_c *tp2, int i)
3514746Srica {
3524746Srica struct sockaddr_in6 *saddrp;
3534746Srica in6_addr_t tmpmask;
3544746Srica
3554746Srica (void) rh_index_to_mask_v6(i, &tmpmask);
3564746Srica saddrp = (struct sockaddr_in6 *)(&tp2->rh_ent.rh_address.ip_addr_v6);
3574746Srica return (V6_MASK_EQ(tp1->sin6_addr, tmpmask, saddrp->sin6_addr));
3584746Srica }
3594746Srica
3604746Srica /*
3614746Srica * we use this where v6 exact match is needed.
3624746Srica */
3634746Srica static int
rhaddr_compar_v6(struct sockaddr_in6 * tp1,struct tnd_tnrhdb_c * tp2)3644746Srica rhaddr_compar_v6(struct sockaddr_in6 *tp1, struct tnd_tnrhdb_c *tp2)
3654746Srica {
3664746Srica struct sockaddr_in6 *saddrp;
3674746Srica
3684746Srica saddrp = (struct sockaddr_in6 *)(&tp2->rh_ent.rh_address.ip_addr_v6);
3694746Srica return (IN6_ARE_ADDR_EQUAL(&tp1->sin6_addr, &saddrp->sin6_addr));
3704746Srica }
3714746Srica
3724746Srica static int
get_hashvalue(in_addr_t addr)3734746Srica get_hashvalue(in_addr_t addr)
3744746Srica {
3754746Srica unsigned char *bp;
3764746Srica
3774746Srica bp = (unsigned char *) &addr;
3784746Srica return ((bp[0] ^ bp[1] ^ bp[2] ^ bp[3]) % TNRH_TABLE_HASH_SIZE);
3794746Srica }
3804746Srica
3814746Srica /*
3824746Srica * Convert length for a mask to the mask.
3834746Srica */
3844746Srica static in_addr_t
rh_index_to_mask(uint_t masklen)3854746Srica rh_index_to_mask(uint_t masklen)
3864746Srica {
3874746Srica if (masklen == 0)
3884746Srica return (0);
3894746Srica return (htonl(RH_HOST_MASK << (IP_ABITS - masklen)));
3904746Srica }
3914746Srica
3924746Srica /*
3934746Srica * Convert length for a mask to the mask.
3944746Srica * Returns the argument bitmask.
3954746Srica */
3964746Srica static in6_addr_t *
rh_index_to_mask_v6(uint_t masklen,in6_addr_t * bitmask)3974746Srica rh_index_to_mask_v6(uint_t masklen, in6_addr_t *bitmask)
3984746Srica {
3994746Srica uint32_t *ptr;
4004746Srica
4014746Srica *bitmask = ipv6_all_zeros;
4024746Srica
4034746Srica ptr = (uint32_t *)bitmask;
4044746Srica while (masklen > 32) {
4054746Srica *ptr++ = 0xffffffffU;
4064746Srica masklen -= 32;
4074746Srica }
4084746Srica *ptr = htonl(0xffffffffU << (32 - masklen));
4094746Srica return (bitmask);
4104746Srica }
4114746Srica
4124746Srica
4134746Srica static void
parse_opts(argc,argv)4144746Srica parse_opts(argc, argv)
4154746Srica int argc;
4164746Srica char **argv;
4174746Srica {
4184746Srica char *logfile = TNDLOG;
4194746Srica extern char *optarg;
4204746Srica int c;
4214746Srica
4224746Srica while ((c = getopt(argc, argv, "d:f:p:n")) != EOF)
4234746Srica switch (c) {
4244746Srica case 'd':
4254746Srica if (isnumber(optarg)) {
4264746Srica debugl = atoi(optarg);
4274746Srica if (check_debugl(debugl) == -1)
4284746Srica debugl = 1; /* default to 1 */
4294746Srica } else {
4304746Srica usage();
4314746Srica exit(1);
4324746Srica }
4334746Srica break;
4344746Srica case 'f':
4354746Srica logfile = optarg;
4364746Srica break;
4374746Srica case 'p':
4384746Srica if (isnumber(optarg)) {
4394746Srica poll_interval = atoi(optarg);
4404746Srica if (poll_interval == 0)
4414746Srica usage();
4424746Srica } else {
4434746Srica usage();
4444746Srica }
4454746Srica break;
4464746Srica case 'n':
4474746Srica delay_poll_flag = 1;
4484746Srica break;
4494746Srica case '?':
4504746Srica usage();
4514746Srica }
4524746Srica
4534746Srica logf = tnlog_open(logfile);
4544746Srica }
4554746Srica
4564746Srica static int
check_debugl(debug_level)4574746Srica check_debugl(debug_level)
4584746Srica int debug_level;
4594746Srica {
4604746Srica if (debug_level > MAX_TND_DEBUG) {
4614746Srica if ((debugl > 0) && (logf != NULL)) {
4624746Srica (void) fprintf(logf, "%s : ", gettime());
4634746Srica (void) fprintf(logf,
4644746Srica gettext("invalid debug level: %d, not changed!\n"),
4654746Srica debug_level);
4664746Srica (void) fflush(logf);
4674746Srica }
4684746Srica cprint("invalid debug level: %d, not changed!\n",
4694746Srica debug_level);
4704746Srica return (-1);
4714746Srica }
4724746Srica return (0);
4734746Srica }
4744746Srica
4754746Srica static FILE *
tnlog_open(logfile)4764746Srica tnlog_open(logfile)
4774746Srica char *logfile;
4784746Srica {
4794746Srica FILE *fp;
4804746Srica
4814746Srica if ((fp = fopen(logfile, "a")) == NULL) {
4824746Srica syslog(LOG_ERR, "unable to open logfile %s",
4834746Srica logfile);
4844746Srica exit(-1);
4854746Srica }
4864746Srica (void) fprintf(fp, "%s : ", gettime());
4874746Srica (void) fprintf(fp, gettext("tnd starting\n"));
4884746Srica
4894746Srica return (fp);
4904746Srica }
4914746Srica
4924746Srica static void
detachfromtty()4934746Srica detachfromtty()
4944746Srica {
4954746Srica pid_t tnd_pid;
4964746Srica
4974746Srica (void) close(0);
4984746Srica (void) close(1);
4994746Srica (void) close(2);
5004746Srica switch (tnd_pid = fork()) {
5014746Srica case (pid_t)-1:
5024746Srica if (debugl && (logf != NULL)) {
5034746Srica (void) fprintf(logf, "%s : ", gettime());
5044746Srica (void) fprintf(logf,
5054746Srica gettext("fork() failed: %s\n"), strerror(errno));
5064746Srica (void) fflush(logf);
5074746Srica }
5084746Srica cprint("fork() failed: %s\n", strerror(errno));
5094746Srica break;
5104746Srica case 0:
5114746Srica break;
5124746Srica default:
5134746Srica if (debugl && (logf != NULL)) {
5144746Srica (void) fprintf(logf, "%s : ", gettime());
5154746Srica (void) fprintf(logf,
5164746Srica gettext("tnd started. pid= %d\n"), tnd_pid);
5174746Srica (void) fflush(logf);
5184746Srica }
5194746Srica /*
5204746Srica * Suspend parent till child signals it. We catch the signal
5214746Srica * in order to return correct exit value.
5224746Srica */
5234746Srica
5244746Srica (void) pause();
5254746Srica exit(0);
5264746Srica }
5274746Srica (void) setsid();
5284746Srica (void) open("/dev/null", O_RDWR, 0);
5294746Srica (void) dup(0);
5304746Srica (void) dup(0);
5314746Srica }
5324746Srica
5334746Srica static void
usage()5344746Srica usage()
5354746Srica {
5364746Srica (void) fprintf(stderr, gettext(
5374746Srica "Usage:\n\ttnd [-d debug-level][-f debug-file]"
5384746Srica "[-p poll-interval]\n"));
5394746Srica
5404746Srica exit(1);
5414746Srica }
5424746Srica
5434746Srica static int
isnumber(s)5444746Srica isnumber(s)
5454746Srica char *s;
5464746Srica {
547*4751Srica register int c;
5484746Srica
5494746Srica /* LINTED */
5504746Srica while (c = *s++)
5514746Srica if (!isdigit(c))
5524746Srica return (0);
5534746Srica return (1);
5544746Srica }
5554746Srica
5564746Srica
5574746Srica /*
5584746Srica * match any entry in any tree
5594746Srica * used in tree removal
5604746Srica */
5614746Srica /* ARGSUSED */
5624746Srica static int
any_compar(const void * v1,const void * v2)5634746Srica any_compar(const void *v1, const void *v2)
5644746Srica {
5654746Srica return (0);
5664746Srica }
5674746Srica
5684746Srica static int
tp_compar(const void * v1,const void * v2)5694746Srica tp_compar(const void *v1, const void *v2)
5704746Srica {
5714746Srica struct tnd_tnrhtp_c *tp1 = (struct tnd_tnrhtp_c *)v1;
5724746Srica struct tnd_tnrhtp_c *tp2 = (struct tnd_tnrhtp_c *)v2;
5734746Srica return (strcmp(tp1->tp_ent.name, tp2->tp_ent.name));
5744746Srica }
5754746Srica
5764746Srica /*
5774746Srica * Build tree of tp entries, tossing duplicates
5784746Srica */
5794746Srica static int
nss_get_tp()5804746Srica nss_get_tp()
5814746Srica {
5824746Srica tsol_tpent_t tp; /* to store result */
5834746Srica tsol_tpent_t *tpp;
5844746Srica struct tnd_tnrhtp_c *new, **old;
5854746Srica int count = 0;
5864746Srica
5874746Srica tpp = &tp;
5884746Srica
5894746Srica tsol_settpent(1);
5904746Srica
5914746Srica while ((tpp = (tsol_tpent_t *)tsol_gettpent()) != NULL) {
5924746Srica if ((new = (struct tnd_tnrhtp_c *)
5934746Srica calloc(1, sizeof (struct tnd_tnrhtp_c))) == NULL)
5944746Srica continue;
5954746Srica (void) memcpy(&new->tp_ent, tpp, sizeof (tp));
5964746Srica old = (struct tnd_tnrhtp_c **)tsearch(new, &tp_tree, tp_compar);
5974746Srica if (*old != new)
5984746Srica free(new);
5994746Srica else
6004746Srica count++;
6014746Srica }
6024746Srica tsol_endtpent();
6034746Srica
6044746Srica return (count);
6054746Srica }
6064746Srica
6074746Srica /* load tp ents into kernel */
6084746Srica static void
load_tp()6094746Srica load_tp()
6104746Srica {
6114746Srica twalk(tp_tree, load_tp_entry);
6124746Srica }
6134746Srica
6144746Srica
6154746Srica static void
6164746Srica /* LINTED */
load_tp_entry(struct tnd_tnrhtp_c ** tppp,VISIT visit,int level)6174746Srica load_tp_entry(struct tnd_tnrhtp_c **tppp, VISIT visit, int level)
6184746Srica {
6194746Srica struct tnd_tnrhtp_c *tpp;
6204746Srica
6214746Srica if (!(visit == postorder || visit == leaf))
6224746Srica return;
6234746Srica
6244746Srica tpp = *tppp;
6254746Srica if (tnrhtp(TNDB_LOAD, &tpp->tp_ent)) {
6264746Srica if (debugl && (logf != NULL)) {
6274746Srica (void) fprintf(logf, "%s : ", gettime());
6284746Srica (void) fprintf(logf, gettext("tnrhtp() failed 0: %s\n"),
6294746Srica strerror(errno));
6304746Srica (void) fprintf(logf,
6314746Srica gettext("load of remote-host template "
6324746Srica "%s into kernel cache failed\n"),
6334746Srica tpp->tp_ent.name);
6344746Srica (void) fflush(logf);
6354746Srica }
6364746Srica cprint("tnrhtp() failed here 1: %s\n", strerror(errno));
6374746Srica }
6384746Srica }
6394746Srica
6404746Srica static void
tp_flush_cache()6414746Srica tp_flush_cache()
6424746Srica {
6434746Srica struct tnd_tnrhtp_c dummy;
6444746Srica struct tnd_tnrhtp_c *tp;
6454746Srica
6464746Srica while (tp = tfind(&dummy, tp_tree, any_compar)) {
6474746Srica (void) tdelete(tp, &tp_tree, tp_compar);
6484746Srica free(tp);
6494746Srica }
6504746Srica }
6514746Srica
6524746Srica /*
6534746Srica * Build/update the table of rh entries from the
6544746Srica * name service sources, files, ldap etc.
6554746Srica */
6564746Srica static int
nss_get_rh()6574746Srica nss_get_rh()
6584746Srica {
6594746Srica int found_entry = 0;
6604746Srica int count = 0;
6614746Srica int newflag = 0;
6624746Srica struct tsol_rhent rh; /* to store result */
6634746Srica struct tsol_rhent *rhp;
6644746Srica tsol_tpent_t tp;
6654746Srica sa_family_t af;
6664746Srica int v6cnt = 0;
6674746Srica
6684746Srica rhp = &rh;
6694746Srica
6704746Srica tsol_setrhent(1);
6714746Srica while ((rhp = (struct tsol_rhent *)
6724746Srica tsol_getrhent()) != NULL) {
6734746Srica /*
6744746Srica * Check if this is a known template name
6754746Srica * Entries with missing template in kernel will be logged
6764746Srica * and not added to cache.
6774746Srica */
6784746Srica
6794746Srica (void) fprintf(logf, gettext("getrhent template name: %s\n"),
6804746Srica rhp->rh_template);
6814746Srica
6824746Srica (void) strncpy(tp.name, rhp->rh_template, TNTNAMSIZ - 1);
6834746Srica if (tnrhtp(TNDB_GET, &tp) != 0) {
6844746Srica if (debugl && (logf != NULL))
6854746Srica (void) fprintf(logf,
6864746Srica gettext("Unknown template name: %s\n"),
6874746Srica rhp->rh_template);
6884746Srica cprint(gettext("Unknown template name: %s\n"),
6894746Srica rhp->rh_template);
6904746Srica continue;
6914746Srica }
6924746Srica found_entry++; /* found a valid tnrhdb entry */
6934746Srica af = rhp->rh_address.ta_family;
6944746Srica
6954746Srica if (af == AF_INET) {
6964746Srica #ifdef DEBUG
6974746Srica (void) fprintf(logf, gettext("nss_get_rh() v4\n"));
6984746Srica #endif
6994746Srica (void) rw_wrlock(&entire_rwlp);
7004746Srica (void) rw_wrlock(&cache_rwlp);
7014746Srica
7024746Srica /*
7034746Srica * Both cache table and entire table can be modified
7044746Srica * by this function. So, get both locks.
7054746Srica */
7064746Srica newflag = rhtable_search_and_update(rhp, 1);
7074746Srica
7084746Srica (void) rw_unlock(&cache_rwlp);
7094746Srica (void) rw_unlock(&entire_rwlp);
7104746Srica } else if (af == AF_INET6) {
7114746Srica #ifdef DEBUG
7124746Srica (void) fprintf(logf, gettext("nss_get_rh() v6\n"));
7134746Srica #endif
7144746Srica v6cnt++;
7154746Srica (void) rw_wrlock(&entire_rwlp_v6);
7164746Srica (void) rw_wrlock(&cache_rwlp_v6);
7174746Srica
7184746Srica /*
7194746Srica * Both cache table and entire table can be modified
7204746Srica * by this function. So, get both locks.
7214746Srica */
7224746Srica newflag = rhtable_search_and_update_v6(rhp, 1);
7234746Srica
7244746Srica (void) rw_unlock(&cache_rwlp_v6);
7254746Srica (void) rw_unlock(&entire_rwlp_v6);
7264746Srica }
7274746Srica if (newflag)
7284746Srica count++;
7294746Srica }
7304746Srica tsol_endrhent();
7314746Srica
7324746Srica /*
7334746Srica * If the first tsol_getrhent() failed, we bail out and
7344746Srica * try again at the next poll interval, just in case the
7354746Srica * name service was not reachable the first time.
7364746Srica */
7374746Srica if (!found_entry) {
7384746Srica #ifdef DEBUG
7394746Srica if (logf != NULL)
7404746Srica (void) fprintf(logf,
7414746Srica gettext("Unable to contact ldap server?\n"));
7424746Srica #endif
7434746Srica return (count);
7444746Srica }
7454746Srica
7464746Srica (void) rw_wrlock(&entire_rwlp);
7474746Srica (void) rw_wrlock(&cache_rwlp);
7484746Srica /*
7494746Srica * Handle deletions in the name service entries
7504746Srica * Both cache table and entire table can be modified
7514746Srica * by this function. So, get both locks.
7524746Srica */
7534746Srica count += handle_unvisited_nodes();
7544746Srica
7554746Srica (void) rw_unlock(&cache_rwlp);
7564746Srica (void) rw_unlock(&entire_rwlp);
7574746Srica
7584746Srica if (v6cnt > 0) {
7594746Srica (void) rw_wrlock(&entire_rwlp_v6);
7604746Srica (void) rw_wrlock(&cache_rwlp_v6);
7614746Srica /*
7624746Srica * Handle deletions in the name service entries
7634746Srica * Both cache table and entire table can be modified
7644746Srica * by this function. So, get both locks.
7654746Srica */
7664746Srica count += handle_unvisited_nodes_v6();
7674746Srica
7684746Srica (void) rw_unlock(&cache_rwlp_v6);
7694746Srica (void) rw_unlock(&entire_rwlp_v6);
7704746Srica }
7714746Srica
7724746Srica return (count);
7734746Srica }
7744746Srica
7754746Srica /*
7764746Srica * Check if any deletions in the name service tables
7774746Srica * affect the cache entries. We need to do this
7784746Srica * in order to not flush the entrie kernel tnrhdb
7794746Srica * cache every time we poll the name services.
7804746Srica */
7814746Srica static int
handle_unvisited_nodes()7824746Srica handle_unvisited_nodes()
7834746Srica {
7844746Srica int i, j, cnt = 0;
7854746Srica tnrh_tlb_t *tlbt;
7864746Srica tnd_tnrhdb_t *rhent, *prev;
7874746Srica
7884746Srica for (i = 0; i < TNRH_TABLE_HASH_SIZE; i++)
7894746Srica if ((tlbt = tnrh_cache_table[i]) != NULL)
7904746Srica do {
7914746Srica if (tlbt->src->visited == 0) {
7924746Srica /*
7934746Srica * Mark for deletion of both our cache
7944746Srica * entry and the kernel cache entry.
7954746Srica */
7964746Srica tlbt->reload = TNDB_DELETE;
7974746Srica cnt++;
7984746Srica }
7994746Srica
8004746Srica tlbt = tlbt->next;
8014746Srica } while (tlbt != NULL);
8024746Srica
8034746Srica /*
8044746Srica * Remove any unvisited nodes. This can
8054746Srica * happen if they are not in use by any cache entry. Then,
8064746Srica * mark all nodes in entire_table, un-visited, for next iteration.
8074746Srica */
8084746Srica
8094746Srica for (i = 0; i <= IP_ABITS; i++) {
8104746Srica if (tnrh_entire_table[i] == NULL)
8114746Srica continue;
8124746Srica
8134746Srica for (j = 0; j < TNRH_TABLE_HASH_SIZE; j++) {
8144746Srica prev = rhent = tnrh_entire_table[i][j];
8154746Srica
8164746Srica while (rhent != NULL) {
8174746Srica if (rhent->visited == 0) {
8184746Srica /*
8194746Srica * Check if start node
8204746Srica */
8214746Srica if (rhent == tnrh_entire_table[i][j]) {
8224746Srica prev = tnrh_entire_table[i][j] =
8234746Srica rhent->rh_next;
8244746Srica } else {
8254746Srica /* bypass the deleted node */
8264746Srica prev->rh_next = rhent->rh_next;
8274746Srica prev = prev->rh_next;
8284746Srica }
8294746Srica
8304746Srica free(rhent);
8314746Srica
8324746Srica if (prev == NULL)
8334746Srica break;
8344746Srica else {
8354746Srica rhent = prev;
8364746Srica continue;
8374746Srica }
8384746Srica } else
8394746Srica rhent->visited = 0;
8404746Srica
8414746Srica prev = rhent;
8424746Srica rhent = rhent->rh_next;
8434746Srica }
8444746Srica }
8454746Srica }
8464746Srica
8474746Srica return (cnt);
8484746Srica }
8494746Srica
8504746Srica /*
8514746Srica * Check if any deletions in the name service tables
8524746Srica * affect the cache entries. We need to do this
8534746Srica * in order to not flush the entrie kernel tnrhdb
8544746Srica * cache every time we poll the name services.
8554746Srica */
8564746Srica static int
handle_unvisited_nodes_v6()8574746Srica handle_unvisited_nodes_v6()
8584746Srica {
8594746Srica int i, j, cnt = 0;
8604746Srica tnrh_tlb_ipv6_t *tlbt;
8614746Srica tnd_tnrhdb_t *rhent, *prev;
8624746Srica
8634746Srica for (i = 0; i < TNRH_TABLE_HASH_SIZE; i++)
8644746Srica if ((tlbt = tnrh_cache_table_v6[i]) != NULL)
8654746Srica do {
8664746Srica if (tlbt->src->visited == 0) {
8674746Srica /*
8684746Srica * Mark for deletion of both our cache entry
8694746Srica * and the kernel cache entry.
8704746Srica */
8714746Srica tlbt->reload = TNDB_DELETE;
8724746Srica cnt++;
8734746Srica }
8744746Srica
8754746Srica tlbt = tlbt->next;
8764746Srica } while (tlbt != NULL);
8774746Srica
8784746Srica /*
8794746Srica * Remove any unvisited nodes. This can
8804746Srica * happen if they are not in use by any cache entry. Then,
8814746Srica * mark all nodes in entire_table, un-visited, for next iteration.
8824746Srica */
8834746Srica
8844746Srica for (i = 0; i <= IPV6_ABITS; i++) {
8854746Srica if (tnrh_entire_table_v6[i] == NULL)
8864746Srica continue;
8874746Srica
8884746Srica for (j = 0; j < TNRH_TABLE_HASH_SIZE; j++) {
8894746Srica prev = rhent = tnrh_entire_table_v6[i][j];
8904746Srica
8914746Srica while (rhent != NULL) {
8924746Srica if (rhent->visited == 0) { /* delete the node */
8934746Srica /* Check if start node */
8944746Srica if (rhent == tnrh_entire_table_v6[i][j]) {
8954746Srica prev = tnrh_entire_table_v6[i][j] =
8964746Srica rhent->rh_next;
8974746Srica } else {
8984746Srica /* bypass the deleted node */
8994746Srica prev->rh_next = rhent->rh_next;
9004746Srica prev = prev->rh_next;
9014746Srica }
9024746Srica
9034746Srica free(rhent);
9044746Srica if (prev == NULL)
9054746Srica break;
9064746Srica else {
9074746Srica rhent = prev;
9084746Srica continue;
9094746Srica }
9104746Srica } else
9114746Srica rhent->visited = 0;
9124746Srica
9134746Srica prev = rhent;
9144746Srica rhent = rhent->rh_next;
9154746Srica }
9164746Srica }
9174746Srica }
9184746Srica
9194746Srica return (cnt);
9204746Srica }
9214746Srica
9224746Srica
9234746Srica /*
9244746Srica * Search the hash chain for the address. If not found,
9254746Srica * add the entry to the hash table. If necessary,
9264746Srica * construct the hash table.
9274746Srica * If the rh entry is in table, we may update its template name
9284746Srica */
9294746Srica static int
rhtable_search_and_update(struct tsol_rhent * ent,int duplflag)9304746Srica rhtable_search_and_update(struct tsol_rhent *ent, int duplflag)
9314746Srica {
9324746Srica struct sockaddr_in *saddrp;
9334746Srica unsigned char hash;
9344746Srica tnd_tnrhdb_t *rhent;
9354746Srica int i;
9364746Srica int rflag = 1;
9374746Srica
9384746Srica struct tnd_tnrhdb_c *new;
9394746Srica
9404746Srica saddrp = (struct sockaddr_in *)&ent->rh_address.ip_addr_v4;
9414746Srica hash = (unsigned char) get_hashvalue(saddrp->sin_addr.s_addr);
9424746Srica i = ent->rh_prefix;
9434746Srica
9444746Srica #ifdef DEBUG
9454746Srica (void) fprintf(logf, gettext("\trhtable_search_and_update IP address:\
9464746Srica %s\n"), inet_ntoa(saddrp->sin_addr));
9474746Srica #endif
9484746Srica
9494746Srica if (tnrh_entire_table[i] == NULL) {
9504746Srica if ((tnrh_entire_table[i] = (tnd_tnrhdb_t **)calloc(
9514746Srica TNRH_TABLE_HASH_SIZE, sizeof (tnd_tnrhdb_t *))) == NULL) {
9524746Srica return (0);
9534746Srica }
9544746Srica }
9554746Srica
9564746Srica rhent = tnrh_entire_table[i][hash];
9574746Srica #ifdef DEBUG
9584746Srica (void) fprintf(logf, gettext("\tsearch_and_update i = %d hash = %d\n"),
9594746Srica i, hash);
9604746Srica if (rhent != NULL) {
9614746Srica (void) fprintf(logf, gettext("\trhent visited = %d\n"),
9624746Srica rhent->visited);
9634746Srica print_entry(&rhent->rh_ent, AF_INET);
9644746Srica } else {
9654746Srica (void) fprintf(logf, gettext("\tsearch_and_update null\n"));
9664746Srica }
9674746Srica #endif
9684746Srica while (rhent != NULL) {
9694746Srica if (rhaddr_compar(saddrp, rhent) == 1) {
9704746Srica /* Check if this is a duplicate entry */
9714746Srica if ((rhent->visited == 1) && duplflag)
9724746Srica return (0);
9734746Srica
9744746Srica if (duplflag)
9754746Srica rhent->visited = 1;
9764746Srica
9774746Srica if (strcmp(ent->rh_template,
9784746Srica rhent->rh_ent.rh_template) != 0) {
9794746Srica /*
9804746Srica * Template is changed in the name service.
9814746Srica * Use the new template.
9824746Srica */
9834746Srica (void) strcpy(rhent->rh_ent.rh_template,
9844746Srica ent->rh_template);
9854746Srica /*
9864746Srica * Check if this modified entry
9874746Srica * affects the cache table.
9884746Srica */
9894746Srica rflag = update_cache_table(ent, rhent);
9904746Srica return (rflag);
9914746Srica } else
9924746Srica return (0);
9934746Srica }
9944746Srica rhent = rhent->rh_next;
9954746Srica }
9964746Srica
9974746Srica /* Not found. Add the entry */
9984746Srica new = (struct tnd_tnrhdb_c *)calloc(1,
9994746Srica sizeof (struct tnd_tnrhdb_c));
10004746Srica if (new == NULL)
10014746Srica return (0);
10024746Srica (void) memcpy(&new->rh_ent, ent, sizeof (struct tsol_rhent));
10034746Srica if (duplflag)
10044746Srica new->visited = 1; /* Mark all new nodes visited */
10054746Srica
10064746Srica /* linked list. Insert in the beginning */
10074746Srica new->rh_next = tnrh_entire_table[i][hash];
10084746Srica tnrh_entire_table[i][hash] = new;
10094746Srica #ifdef DEBUG
10104746Srica (void) fprintf(logf, gettext("rhtable added i = %d, hash = %d\n"),
10114746Srica i, hash);
10124746Srica #endif
10134746Srica
10144746Srica /* Check if the new entry affects the cache table */
10154746Srica rflag = update_cache_table(ent, new);
10164746Srica
10174746Srica #ifdef DEBUG
10184746Srica (void) fprintf(logf, gettext("search_and_update rflag=%d\n"), rflag);
10194746Srica #endif
10204746Srica return (rflag);
10214746Srica }
10224746Srica
10234746Srica /*
10244746Srica * Search the hash chain for the address. If not found,
10254746Srica * add the entry to the hash table. If necessary,
10264746Srica * construct the hash table.
10274746Srica */
10284746Srica static int
rhtable_search_and_update_v6(struct tsol_rhent * ent,int duplflag)10294746Srica rhtable_search_and_update_v6(struct tsol_rhent *ent, int duplflag)
10304746Srica {
10314746Srica struct sockaddr_in6 *saddrp;
10324746Srica unsigned char hash;
10334746Srica tnd_tnrhdb_t *rhent;
10344746Srica int i;
10354746Srica int rflag = 1;
10364746Srica
10374746Srica struct tnd_tnrhdb_c *new;
10384746Srica in6_addr_t tmpmask6;
10394746Srica
10404746Srica saddrp = (struct sockaddr_in6 *)&ent->rh_address.ip_addr_v6;
10414746Srica i = ent->rh_prefix;
10424746Srica (void) rh_index_to_mask_v6(i, &tmpmask6);
10434746Srica hash = (unsigned char) TNRH_ADDR_MASK_HASH_V6(saddrp->sin6_addr,
10444746Srica tmpmask6);
10454746Srica
10464746Srica if (tnrh_entire_table_v6[i] == NULL) {
10474746Srica if ((tnrh_entire_table_v6[i] = (tnd_tnrhdb_t **)calloc(
10484746Srica TNRH_TABLE_HASH_SIZE, sizeof (tnd_tnrhdb_t *))) == NULL) {
10494746Srica return (0);
10504746Srica }
10514746Srica }
10524746Srica
10534746Srica rhent = tnrh_entire_table_v6[i][hash];
10544746Srica while (rhent != NULL) {
10554746Srica if (rhaddr_compar_v6(saddrp, rhent) == 1) {
10564746Srica /* Check if this is a duplicate entry */
10574746Srica if ((rhent->visited == 1) && duplflag)
10584746Srica return (0);
10594746Srica
10604746Srica if (duplflag)
10614746Srica rhent->visited = 1;
10624746Srica
10634746Srica if (strcmp(ent->rh_template,
10644746Srica rhent->rh_ent.rh_template) != 0) {
10654746Srica /*
10664746Srica * Template is changed in the name service.
10674746Srica * Use the new template.
10684746Srica */
10694746Srica (void) strcpy(rhent->rh_ent.rh_template,
10704746Srica ent->rh_template);
10714746Srica /*
10724746Srica * Check if this modified entry
10734746Srica * affects the cache table.
10744746Srica */
10754746Srica rflag = update_cache_table_v6(ent, rhent);
10764746Srica return (rflag);
10774746Srica } else
10784746Srica return (0);
10794746Srica }
10804746Srica rhent = rhent->rh_next;
10814746Srica }
10824746Srica
10834746Srica /* Not found. Add the entry */
10844746Srica new = (struct tnd_tnrhdb_c *)calloc(1, sizeof (struct tnd_tnrhdb_c));
10854746Srica if (new == NULL)
10864746Srica return (0);
10874746Srica (void) memcpy(&new->rh_ent, ent, sizeof (struct tsol_rhent));
10884746Srica if (duplflag)
10894746Srica new->visited = 1; /* Mark all new nodes visited */
10904746Srica
10914746Srica /* linked list. Insert in the beginning */
10924746Srica new->rh_next = tnrh_entire_table_v6[i][hash];
10934746Srica tnrh_entire_table_v6[i][hash] = new;
10944746Srica
10954746Srica /* Check if the new entry affects the cache table */
10964746Srica rflag = update_cache_table_v6(ent, new);
10974746Srica
10984746Srica return (rflag);
10994746Srica }
11004746Srica
11014746Srica /*
11024746Srica * The array element i points to the hash table.
11034746Srica * Search the hash chain for the address.
11044746Srica */
11054746Srica static struct tnd_tnrhdb_c *
rhtable_lookup(struct sockaddr_in * saddrp,int i)11064746Srica rhtable_lookup(struct sockaddr_in *saddrp, int i)
11074746Srica {
11084746Srica unsigned char hash;
11094746Srica tnd_tnrhdb_t *rhent;
11104746Srica
11114746Srica if (tnrh_entire_table[i] == NULL)
11124746Srica return (NULL);
11134746Srica
11144746Srica hash = (unsigned char) get_hashvalue(saddrp->sin_addr.s_addr);
11154746Srica rhent = tnrh_entire_table[i][hash];
11164746Srica
11174746Srica #ifdef DEBUG
11184746Srica (void) fprintf(logf, gettext("rhtable_lookup i = %d, hash = %d\n"),
11194746Srica i, hash);
11204746Srica #endif
11214746Srica
11224746Srica while (rhent != NULL) {
11234746Srica #ifdef DEBUG
11244746Srica struct sockaddr_in *saddrp2;
11254746Srica saddrp2 = (struct sockaddr_in *)(&rhent->rh_ent.rh_address.ip_addr_v4);
11264746Srica (void) fprintf(logf, gettext("rhtable_lookup addr = %s, tmpl = %s\n"),
11274746Srica inet_ntoa(saddrp2->sin_addr), rhent->rh_ent.rh_template);
11284746Srica #endif
11294746Srica if (rhaddr_compar_mask(saddrp, rhent, i) == 1)
11304746Srica return (rhent);
11314746Srica rhent = rhent->rh_next;
11324746Srica }
11334746Srica
11344746Srica #ifdef DEBUG
11354746Srica (void) fprintf(logf, gettext("\trhtable_lookup failed\n"));
11364746Srica #endif
11374746Srica
11384746Srica /* Not found */
11394746Srica return (NULL);
11404746Srica }
11414746Srica
11424746Srica /*
11434746Srica * The array element i points to the hash table.
11444746Srica * Search the hash chain for the address.
11454746Srica */
11464746Srica static struct tnd_tnrhdb_c *
rhtable_lookup_v6(struct sockaddr_in6 * saddrp,in6_addr_t mask,int i)11474746Srica rhtable_lookup_v6(struct sockaddr_in6 *saddrp, in6_addr_t mask, int i)
11484746Srica {
11494746Srica unsigned char hash;
11504746Srica tnd_tnrhdb_t *rhent;
11514746Srica
11524746Srica if (tnrh_entire_table_v6[i] == NULL)
11534746Srica return (NULL);
11544746Srica
11554746Srica hash = (unsigned char) TNRH_ADDR_MASK_HASH_V6(saddrp->sin6_addr, mask);
11564746Srica rhent = tnrh_entire_table_v6[i][hash];
11574746Srica
11584746Srica while (rhent != NULL) {
11594746Srica if (rhaddr_compar_mask_v6(saddrp, rhent, i) == 1)
11604746Srica return (rhent);
11614746Srica rhent = rhent->rh_next;
11624746Srica }
11634746Srica
11644746Srica /* Not found */
11654746Srica return (NULL);
11664746Srica }
11674746Srica
11684746Srica void
add_cache_entry(in_addr_t addr,char * name,int indx,tnd_tnrhdb_t * src)11694746Srica add_cache_entry(in_addr_t addr, char *name, int indx,
11704746Srica tnd_tnrhdb_t *src)
11714746Srica {
11724746Srica unsigned char hash;
11734746Srica tnrh_tlb_t *tlbt;
11744746Srica
11754746Srica hash = (unsigned char) get_hashvalue(addr);
11764746Srica
11774746Srica /* Look if some other thread already added this entry */
11784746Srica if (lookup_cache_table(addr) != NULL)
11794746Srica return;
11804746Srica #ifdef DEBUG
11814746Srica (void) fprintf(logf, gettext("\tenter add_cache_entry\n"));
11824746Srica #endif
11834746Srica if ((tlbt = (tnrh_tlb_t *)calloc(1, sizeof (tnrh_tlb_t))) == NULL)
11844746Srica return;
11854746Srica tlbt->addr = addr;
11864746Srica (void) strncpy(tlbt->template_name, name, TNTNAMSIZ-1);
11874746Srica tlbt->masklen_used = indx;
11884746Srica tlbt->reload = TNDB_LOAD;
11894746Srica tlbt->src = src;
11904746Srica
11914746Srica #ifdef DEBUG
11924746Srica (void) fprintf(logf, gettext("adding cache entry\n"));
11934746Srica print_tlbt(tlbt);
11944746Srica #endif
11954746Srica /* Add to the chain */
11964746Srica if (tnrh_cache_table[hash] == NULL) {
11974746Srica tnrh_cache_table[hash] = tlbt;
11984746Srica } else {
11994746Srica /* Add in the beginning */
12004746Srica tlbt->next = tnrh_cache_table[hash];
12014746Srica tnrh_cache_table[hash] = tlbt;
12024746Srica }
12034746Srica }
12044746Srica
12054746Srica static tnrh_tlb_t *
lookup_cache_table(in_addr_t addr)12064746Srica lookup_cache_table(in_addr_t addr)
12074746Srica {
12084746Srica tnrh_tlb_t *tlbt = NULL;
12094746Srica unsigned char hash;
12104746Srica
12114746Srica hash = (unsigned char) get_hashvalue(addr);
12124746Srica tlbt = tnrh_cache_table[hash];
12134746Srica while (tlbt != NULL) {
12144746Srica if (addr == tlbt->addr)
12154746Srica break;
12164746Srica tlbt = tlbt->next;
12174746Srica }
12184746Srica return (tlbt);
12194746Srica }
12204746Srica
12214746Srica static void
add_cache_entry_v6(in6_addr_t addr,char * name,int indx,tnd_tnrhdb_t * src)12224746Srica add_cache_entry_v6(in6_addr_t addr, char *name, int indx,
12234746Srica tnd_tnrhdb_t *src)
12244746Srica {
12254746Srica unsigned char hash;
12264746Srica tnrh_tlb_ipv6_t *tlbt;
12274746Srica
12284746Srica hash = (unsigned char) TNRH_ADDR_HASH_V6(addr);
12294746Srica
12304746Srica /* Look if some other thread already added this entry */
12314746Srica if (lookup_cache_table_v6(addr) != NULL)
12324746Srica return;
12334746Srica
12344746Srica if ((tlbt = (tnrh_tlb_ipv6_t *)calloc(1,
12354746Srica sizeof (tnrh_tlb_ipv6_t))) == NULL)
12364746Srica return;
12374746Srica (void) memcpy(&tlbt->addr, &addr, sizeof (in6_addr_t));
12384746Srica (void) strncpy(tlbt->template_name, name, TNTNAMSIZ-1);
12394746Srica tlbt->masklen_used = indx;
12404746Srica tlbt->reload = TNDB_LOAD;
12414746Srica tlbt->src = src;
12424746Srica
12434746Srica /* Add to the chain */
12444746Srica if (tnrh_cache_table_v6[hash] == NULL) {
12454746Srica tnrh_cache_table_v6[hash] = tlbt;
12464746Srica } else {
12474746Srica /* Add in the beginning */
12484746Srica tlbt->next = tnrh_cache_table_v6[hash];
12494746Srica tnrh_cache_table_v6[hash] = tlbt;
12504746Srica }
12514746Srica }
12524746Srica
12534746Srica static tnrh_tlb_ipv6_t *
lookup_cache_table_v6(in6_addr_t addr)12544746Srica lookup_cache_table_v6(in6_addr_t addr)
12554746Srica {
12564746Srica tnrh_tlb_ipv6_t *tlbt = NULL;
12574746Srica unsigned char hash;
12584746Srica
12594746Srica hash = (unsigned char) TNRH_ADDR_HASH_V6(addr);
12604746Srica tlbt = tnrh_cache_table_v6[hash];
12614746Srica while (tlbt != NULL) {
12624746Srica if (IN6_ARE_ADDR_EQUAL(&addr, &tlbt->addr))
12634746Srica break;
12644746Srica tlbt = tlbt->next;
12654746Srica }
12664746Srica return (tlbt);
12674746Srica }
12684746Srica
12694746Srica
12704746Srica /*
12714746Srica * Walk the cache table and check if this IP address/address prefix
12724746Srica * will be a better match for an existing entry in the cache.
12734746Srica * will add cache if not already exists
12744746Srica */
12754746Srica static int
update_cache_table(tsol_rhent_t * ent,tnd_tnrhdb_t * src)12764746Srica update_cache_table(tsol_rhent_t *ent, tnd_tnrhdb_t *src)
12774746Srica {
12784746Srica int i;
12794746Srica char result[TNTNAMSIZ];
12804746Srica in_addr_t tmpmask;
12814746Srica in_addr_t addr;
12824746Srica struct sockaddr_in *saddrp;
12834746Srica tnrh_tlb_t *tlbt;
12844746Srica struct tnd_tnrhdb_c *rhp;
12854746Srica int rflag = 0;
12864746Srica
12874746Srica saddrp = (struct sockaddr_in *)&ent->rh_address.ip_addr_v4;
12884746Srica addr = saddrp->sin_addr.s_addr;
12894746Srica
12904746Srica (void) rw_rdlock(&cache_rwlp);
12914746Srica tlbt = lookup_cache_table(addr);
12924746Srica (void) rw_unlock(&cache_rwlp);
12934746Srica
12944746Srica if (tlbt == NULL) {
12954746Srica (void) rw_rdlock(&entire_rwlp);
12964746Srica for (i = (IP_MASK_TABLE_SIZE - 1); i >= 0; i--) {
12974746Srica #ifdef DEBUG
12984746Srica (void) fprintf(logf, "update_cache_table i = %d\n", i);
12994746Srica #endif
13004746Srica if (tnrh_entire_table[i] == NULL)
13014746Srica continue;
13024746Srica
13034746Srica tmpmask = rh_index_to_mask(i);
13044746Srica saddrp->sin_addr.s_addr &= tmpmask;
13054746Srica #ifdef DEBUG
13064746Srica (void) fprintf(logf,
13074746Srica "update_cache_table found i = %d\n", i);
13084746Srica (void) fprintf(logf, "\ti = %d, tmpmask = 0x%4x\n",
13094746Srica i, tmpmask);
13104746Srica #endif
13114746Srica rhp = (struct tnd_tnrhdb_c *)rhtable_lookup(saddrp, i);
13124746Srica if (rhp != NULL) {
13134746Srica (void) strcpy(result, rhp->rh_ent.rh_template);
13144746Srica /* Add this result to the cache also */
13154746Srica (void) rw_wrlock(&cache_rwlp);
13164746Srica add_cache_entry(addr, result, i, rhp);
13174746Srica rflag++;
13184746Srica (void) rw_unlock(&cache_rwlp);
13194746Srica break;
13204746Srica } else {
13214746Srica #ifdef DEBUG
13224746Srica (void) fprintf(logf,
13234746Srica "rhtable_lookup return null !!");
13244746Srica #endif
13254746Srica }
13264746Srica }
13274746Srica (void) rw_unlock(&entire_rwlp);
13284746Srica }
13294746Srica
13304746Srica rflag += walk_cache_table(addr, ent->rh_template, ent->rh_prefix, src);
13314746Srica return (rflag);
13324746Srica }
13334746Srica
13344746Srica /*
13354746Srica * Walk the cache table and check if this IP address/address prefix
13364746Srica * will be a better match for an existing entry in the cache.
13374746Srica */
13384746Srica static int
update_cache_table_v6(tsol_rhent_t * ent,tnd_tnrhdb_t * src)13394746Srica update_cache_table_v6(tsol_rhent_t *ent, tnd_tnrhdb_t *src)
13404746Srica {
13414746Srica int i;
13424746Srica char result[TNTNAMSIZ];
13434746Srica in6_addr_t addr;
13444746Srica struct sockaddr_in6 *saddrp;
13454746Srica tnrh_tlb_ipv6_t *tlbt;
13464746Srica struct tnd_tnrhdb_c *rhp;
13474746Srica in6_addr_t tmpmask6;
13484746Srica int rflag = 0;
13494746Srica
13504746Srica saddrp = (struct sockaddr_in6 *)&ent->rh_address.ip_addr_v6;
13514746Srica (void) memcpy(&addr, &saddrp->sin6_addr, sizeof (in6_addr_t));
13524746Srica
13534746Srica /* Look in the cache first */
13544746Srica (void) rw_rdlock(&cache_rwlp);
13554746Srica tlbt = lookup_cache_table_v6(addr);
13564746Srica (void) rw_unlock(&cache_rwlp);
13574746Srica
13584746Srica
13594746Srica if (tlbt == NULL) {
13604746Srica (void) rw_rdlock(&entire_rwlp_v6);
13614746Srica for (i = (IPV6_MASK_TABLE_SIZE - 1); i >= 0; i--) {
13624746Srica if (tnrh_entire_table_v6[i] == NULL)
13634746Srica continue;
13644746Srica (void) rh_index_to_mask_v6(i, &tmpmask6);
13654746Srica rhp = (struct tnd_tnrhdb_c *)
13664746Srica rhtable_lookup_v6(saddrp, tmpmask6, i);
13674746Srica if (rhp != NULL) {
13684746Srica (void) strcpy(result, rhp->rh_ent.rh_template);
13694746Srica /* Add this result to the cache also */
13704746Srica (void) rw_wrlock(&cache_rwlp_v6);
13714746Srica add_cache_entry_v6(addr, result, i, rhp);
13724746Srica rflag++;
13734746Srica (void) rw_unlock(&cache_rwlp_v6);
13744746Srica break;
13754746Srica }
13764746Srica }
13774746Srica (void) rw_unlock(&entire_rwlp_v6);
13784746Srica }
13794746Srica
13804746Srica rflag += walk_cache_table_v6(addr, ent->rh_template,
13814746Srica ent->rh_prefix, src);
13824746Srica return (rflag);
13834746Srica }
13844746Srica
13854746Srica
13864746Srica /*
13874746Srica * Check if this prefix addr will be a better match
13884746Srica * for an existing entry.
13894746Srica */
13904746Srica static int
is_better_match(in_addr_t newaddr,int indx,tnrh_tlb_t * tlbt)13914746Srica is_better_match(in_addr_t newaddr, int indx, tnrh_tlb_t *tlbt)
13924746Srica {
13934746Srica if (tlbt->masklen_used <= indx) {
13944746Srica in_addr_t tmpmask = rh_index_to_mask(indx);
13954746Srica
13964746Srica if ((newaddr) == (tlbt->addr & tmpmask))
13974746Srica return (1);
13984746Srica }
13994746Srica
14004746Srica return (0);
14014746Srica }
14024746Srica
14034746Srica /*
14044746Srica * Walk the cache table and update entries if needed.
14054746Srica * Mark entries for reload to kernel, if somehow their
14064746Srica * template changed.
14074746Srica * why is_better_match() is called???
14084746Srica */
14094746Srica static int
walk_cache_table(in_addr_t newaddr,char * name,int indx,tnd_tnrhdb_t * src)14104746Srica walk_cache_table(in_addr_t newaddr, char *name, int indx, tnd_tnrhdb_t *src)
14114746Srica {
14124746Srica int i;
14134746Srica tnrh_tlb_t *tlbt;
14144746Srica int rflag = 0;
14154746Srica
14164746Srica for (i = 0; i < TNRH_TABLE_HASH_SIZE; i++) {
14174746Srica tlbt = tnrh_cache_table[i];
14184746Srica
14194746Srica while (tlbt != NULL) {
14204746Srica if (is_better_match(newaddr, indx, tlbt)) {
14214746Srica tlbt->masklen_used = indx;
14224746Srica tlbt->src = src;
14234746Srica /*
14244746Srica * Reload to the kernel only if the
14254746Srica * host type changed. There is no need
14264746Srica * to load, if only the mask used has changed,
14274746Srica * since the kernel does not need that
14284746Srica * information.
14294746Srica */
14304746Srica if (strcmp(name, tlbt->template_name) != 0) {
14314746Srica (void) strncpy(tlbt->template_name,
14324746Srica name, TNTNAMSIZ-1);
14334746Srica tlbt->reload = TNDB_LOAD;
14344746Srica rflag ++;
14354746Srica }
14364746Srica }
14374746Srica
14384746Srica tlbt = tlbt->next;
14394746Srica }
14404746Srica }
14414746Srica #ifdef DEBUG
14424746Srica (void) fprintf(logf, gettext("walk_cache_table rflag=%d\n"), rflag);
14434746Srica #endif
14444746Srica return (rflag);
14454746Srica }
14464746Srica
14474746Srica /*
14484746Srica * Check if this prefix addr will be a better match
14494746Srica * for an existing entry.
14504746Srica */
14514746Srica static int
is_better_match_v6(in6_addr_t newaddr,int indx,tnrh_tlb_ipv6_t * tlbt)14524746Srica is_better_match_v6(in6_addr_t newaddr, int indx, tnrh_tlb_ipv6_t *tlbt)
14534746Srica {
14544746Srica in6_addr_t tmpmask;
14554746Srica
14564746Srica if (tlbt->masklen_used <= indx) {
14574746Srica (void) rh_index_to_mask_v6(indx, &tmpmask);
14584746Srica
14594746Srica if (V6_MASK_EQ(newaddr, tmpmask, tlbt->addr))
14604746Srica return (1);
14614746Srica }
14624746Srica
14634746Srica return (0);
14644746Srica }
14654746Srica
14664746Srica
14674746Srica /*
14684746Srica * Walk the cache table and update entries if needed.
14694746Srica * Mark entries for reload to kernel, if somehow their
14704746Srica * template changed.
14714746Srica */
14724746Srica static int
walk_cache_table_v6(in6_addr_t newaddr,char * name,int indx,tnd_tnrhdb_t * src)14734746Srica walk_cache_table_v6(in6_addr_t newaddr, char *name, int indx, tnd_tnrhdb_t *src)
14744746Srica {
14754746Srica int i;
14764746Srica tnrh_tlb_ipv6_t *tlbt;
14774746Srica int rflag = 0;
14784746Srica
14794746Srica for (i = 0; i < TNRH_TABLE_HASH_SIZE; i++) {
14804746Srica tlbt = tnrh_cache_table_v6[i];
14814746Srica
14824746Srica while (tlbt != NULL) {
14834746Srica if (is_better_match_v6(newaddr, indx, tlbt)) {
14844746Srica tlbt->masklen_used = indx;
14854746Srica tlbt->src = src;
14864746Srica /*
14874746Srica * Reload to the kernel only if the
14884746Srica * host type changed. There is no need
14894746Srica * to load, if only the mask used has changed,
14904746Srica * since the kernel does not need that
14914746Srica * information.
14924746Srica */
14934746Srica if (strcmp(name, tlbt->template_name) != 0) {
14944746Srica (void) strncpy(tlbt->template_name,
14954746Srica name, TNTNAMSIZ-1);
14964746Srica tlbt->reload = TNDB_LOAD;
14974746Srica rflag ++;
14984746Srica }
14994746Srica }
15004746Srica
15014746Srica tlbt = tlbt->next;
15024746Srica }
15034746Srica }
15044746Srica
15054746Srica return (rflag);
15064746Srica }
15074746Srica
15084746Srica /*
15094746Srica * load/delete marked rh ents into kernel
15104746Srica * depending on the reload flag by invoking tnrh().
15114746Srica * It will mark other entries as TNDB_NOOP
15124746Srica */
15134746Srica static void
load_rh_marked()15144746Srica load_rh_marked()
15154746Srica {
15164746Srica int i;
15174746Srica tnrh_tlb_t *tlbt, *prev;
15184746Srica struct tsol_rhent rhentp;
15194746Srica
15204746Srica (void) memset((char *)&rhentp, '\0', sizeof (rhentp));
15214746Srica
15224746Srica for (i = 0; i < TNRH_TABLE_HASH_SIZE; i++) {
15234746Srica
15244746Srica prev = tlbt = tnrh_cache_table[i];
15254746Srica
15264746Srica while (tlbt != NULL) {
15274746Srica if ((tlbt->reload == TNDB_LOAD) ||
15284746Srica (tlbt->reload == TNDB_DELETE)) {
15294746Srica /*
15304746Srica * We have to call tnrh() with tsol_rhent argument.
15314746Srica * Construct such a struct from the tlbt struct we have.
15324746Srica */
15334746Srica rhentp.rh_address.ip_addr_v4.sin_addr.s_addr =
15344746Srica tlbt->addr;
15354746Srica rhentp.rh_address.ip_addr_v4.sin_family =
15364746Srica AF_INET;
15374746Srica rhentp.rh_prefix = tlbt->masklen_used;
15384746Srica (void) strcpy(rhentp.rh_template,
15394746Srica tlbt->template_name);
15404746Srica
15414746Srica #ifdef DEBUG
15424746Srica (void) fprintf(logf, "load op =%d\n",
15434746Srica tlbt->reload);
15444746Srica print_tlbt(tlbt);
15454746Srica #endif
15464746Srica update_rh_entry(tlbt->reload, &rhentp);
15474746Srica
15484746Srica if (tlbt->reload == TNDB_DELETE) {
15494746Srica if (tlbt == tnrh_cache_table[i]) {
15504746Srica tnrh_cache_table[i] =
15514746Srica tlbt->next;
15524746Srica prev = tnrh_cache_table[i];
15534746Srica } else {
15544746Srica prev->next = tlbt->next;
15554746Srica prev = prev->next;
15564746Srica }
15574746Srica
15584746Srica free(tlbt);
15594746Srica if (prev == NULL)
15604746Srica break;
15614746Srica else {
15624746Srica tlbt = prev;
15634746Srica continue;
15644746Srica }
15654746Srica }
15664746Srica tlbt->reload = TNDB_NOOP;
15674746Srica }
15684746Srica
15694746Srica prev = tlbt;
15704746Srica tlbt = tlbt->next;
15714746Srica }
15724746Srica }
15734746Srica
15744746Srica }
15754746Srica
15764746Srica /* load marked rh ents into kernel */
15774746Srica static void
load_rh_marked_v6()15784746Srica load_rh_marked_v6()
15794746Srica {
15804746Srica int i;
15814746Srica tnrh_tlb_ipv6_t *tlbt, *prev;
15824746Srica struct tsol_rhent rhentp;
15834746Srica
15844746Srica (void) memset((char *)&rhentp, '\0', sizeof (rhentp));
15854746Srica
15864746Srica for (i = 0; i < TNRH_TABLE_HASH_SIZE; i++) {
15874746Srica prev = tlbt = tnrh_cache_table_v6[i];
15884746Srica
15894746Srica while (tlbt != NULL) {
15904746Srica if ((tlbt->reload == TNDB_LOAD) ||
15914746Srica (tlbt->reload == TNDB_DELETE)) {
15924746Srica /*
15934746Srica * We have to call tnrh() with tsol_rhent argument.
15944746Srica * Construct such a struct from the tlbt struct we have.
15954746Srica */
15964746Srica (void) memcpy(&rhentp.rh_address.ip_addr_v6.sin6_addr,
15974746Srica &tlbt->addr, sizeof (in6_addr_t));
15984746Srica rhentp.rh_address.ip_addr_v6.sin6_family = AF_INET6;
15994746Srica rhentp.rh_prefix = tlbt->masklen_used;
16004746Srica (void) strcpy(rhentp.rh_template, tlbt->template_name);
16014746Srica
16024746Srica update_rh_entry(tlbt->reload, &rhentp);
16034746Srica
16044746Srica if (tlbt->reload == TNDB_DELETE) {
16054746Srica if (tlbt == tnrh_cache_table_v6[i]) {
16064746Srica tnrh_cache_table_v6[i] =
16074746Srica tlbt->next;
16084746Srica prev = tnrh_cache_table_v6[i];
16094746Srica } else {
16104746Srica prev->next = tlbt->next;
16114746Srica prev = prev->next;
16124746Srica }
16134746Srica
16144746Srica free(tlbt);
16154746Srica if (prev == NULL)
16164746Srica break;
16174746Srica else {
16184746Srica tlbt = prev;
16194746Srica continue;
16204746Srica }
16214746Srica }
16224746Srica tlbt->reload = TNDB_NOOP;
16234746Srica }
16244746Srica
16254746Srica prev = tlbt;
16264746Srica tlbt = tlbt->next;
16274746Srica }
16284746Srica }
16294746Srica
16304746Srica }
16314746Srica
16324746Srica /*
16334746Srica * Does the real load/delete for the entry depending on op code.
16344746Srica */
16354746Srica
16364746Srica static void
update_rh_entry(int op,struct tsol_rhent * rhentp)16374746Srica update_rh_entry(int op, struct tsol_rhent *rhentp)
16384746Srica {
16394746Srica #ifdef DEBUG
16404746Srica (void) fprintf(logf, gettext("\t###update_rh_entry op = %d\n"), op);
16414746Srica print_entry(rhentp, AF_INET);
16424746Srica #endif
16434746Srica if (tnrh(op, rhentp) != 0) {
16444746Srica if (debugl && (logf != NULL)) {
16454746Srica (void) fprintf(logf, "%s : ", gettime());
16464746Srica (void) fprintf(logf, gettext("tnrh() failed: %s\n"),
16474746Srica strerror(errno));
16484746Srica if (op == TNDB_LOAD)
16494746Srica (void) fprintf(logf,
16504746Srica gettext("load of remote host database "
16514746Srica "%s into kernel cache failed\n"),
16524746Srica rhentp->rh_template);
16534746Srica if (op == TNDB_DELETE)
16544746Srica (void) fprintf(logf,
16554746Srica gettext("delete of remote host database "
16564746Srica "%s from kernel cache failed\n"),
16574746Srica rhentp->rh_template);
16584746Srica (void) fflush(logf);
16594746Srica }
16604746Srica cprint("tnrh() failed..: %s\n", strerror(errno));
16614746Srica }
16624746Srica }
16634746Srica
16644746Srica static void
timer()16654746Srica timer()
16664746Srica {
16674746Srica poll_now();
16684746Srica (void) alarm(poll_interval);
16694746Srica }
16704746Srica
16714746Srica #define max(a, b) ((a) > (b) ? (a) : (b))
16724746Srica
16734746Srica static void
poll_now()16744746Srica poll_now()
16754746Srica {
16764746Srica
16774746Srica (void) fprintf(logf, "enter poll_now at %s \n", gettime());
16784746Srica (void) fflush(logf);
16794746Srica
16804746Srica if (nss_get_tp() > 0) {
16814746Srica load_tp();
16824746Srica tp_flush_cache();
16834746Srica }
16844746Srica
16854746Srica #ifdef DEBUG
16864746Srica (void) fprintf(logf, "now search for tnrhdb update %s \n", gettime());
16874746Srica #endif
16884746Srica
16894746Srica if (nss_get_rh() > 0) {
16904746Srica if (logf != NULL) {
16914746Srica (void) fprintf(logf, "tnrhdb needs update %s \n",
16924746Srica gettime());
16934746Srica }
16944746Srica
16954746Srica (void) rw_wrlock(&cache_rwlp);
16964746Srica /* This function will cleanup cache table */
16974746Srica load_rh_marked();
16984746Srica (void) rw_unlock(&cache_rwlp);
16994746Srica
17004746Srica (void) rw_wrlock(&cache_rwlp_v6);
17014746Srica /* This function will cleanup cache table */
17024746Srica load_rh_marked_v6();
17034746Srica (void) rw_unlock(&cache_rwlp_v6);
17044746Srica }
17054746Srica
17064746Srica #ifdef DEBUG
17074746Srica if (logf != NULL) {
17084746Srica cachetable_print();
17094746Srica cachetable_print_v6();
17104746Srica
17114746Srica (void) fprintf(logf, "rh table begin\n");
17124746Srica rhtable_print();
17134746Srica rhtable_print_v6();
17144746Srica (void) fprintf(logf, "rh table end \n");
17154746Srica (void) fprintf(logf, "-------------------------\n\n");
17164746Srica (void) fflush(logf);
17174746Srica }
17184746Srica #endif
17194746Srica }
17204746Srica
17214746Srica static void
tnd_serve()17224746Srica tnd_serve()
17234746Srica {
17244746Srica for (;;) {
17254746Srica (void) pause();
17264746Srica }
17274746Srica }
17284746Srica
17294746Srica static void
terminate()17304746Srica terminate()
17314746Srica {
17324746Srica if (debugl && (logf != NULL)) {
17334746Srica (void) fprintf(logf, "%s : ", gettime());
17344746Srica (void) fprintf(logf, gettext("tnd terminating on signal.\n"));
17354746Srica (void) fflush(logf);
17364746Srica }
17374746Srica exit(1);
17384746Srica }
17394746Srica
17404746Srica static void
noop()17414746Srica noop()
17424746Srica {
17434746Srica }
17444746Srica
17454746Srica static char *
gettime()17464746Srica gettime()
17474746Srica {
17484746Srica time_t now;
17494746Srica struct tm *tp, tm;
17504746Srica char *fmt;
17514746Srica
17524746Srica (void) time(&now);
17534746Srica tp = localtime(&now);
17544746Srica (void) memcpy(&tm, tp, sizeof (struct tm));
17554746Srica fmt = nl_langinfo(_DATE_FMT);
17564746Srica
17574746Srica (void) strftime(time_buf, _SZ_TIME_BUF, fmt, &tm);
17584746Srica
17594746Srica return (time_buf);
17604746Srica }
17614746Srica /*
17624746Srica * debugging routines
17634746Srica */
17644746Srica
17654746Srica
17664746Srica #ifdef DEBUG
17674746Srica static void
print_cache_entry(tnrh_tlb_t * tlbt)17684746Srica print_cache_entry(tnrh_tlb_t *tlbt)
17694746Srica {
17704746Srica struct in_addr addr;
17714746Srica
17724746Srica addr.s_addr = tlbt->addr;
17734746Srica (void) fprintf(logf, "\tIP address: %s", inet_ntoa(addr));
17744746Srica (void) fprintf(logf, "\tTemplate name: %s", tlbt->template_name);
17754746Srica (void) fprintf(logf, "\tMask length used: %d\n", tlbt->masklen_used);
17764746Srica }
17774746Srica
17784746Srica static void
print_cache_entry_v6(tnrh_tlb_ipv6_t * tlbt)17794746Srica print_cache_entry_v6(tnrh_tlb_ipv6_t *tlbt)
17804746Srica {
17814746Srica char abuf[INET6_ADDRSTRLEN];
17824746Srica
17834746Srica (void) fprintf(logf, "\tIP address: %s",
17844746Srica inet_ntop(AF_INET6, &tlbt->addr, abuf, sizeof (abuf)));
17854746Srica (void) fprintf(logf, "\tTemplate name: %s", tlbt->template_name);
17864746Srica (void) fprintf(logf, "\tMask length used: %d\n", tlbt->masklen_used);
17874746Srica }
17884746Srica
17894746Srica static void
cachetable_print()17904746Srica cachetable_print()
17914746Srica {
17924746Srica int i;
17934746Srica tnrh_tlb_t *tlbt;
17944746Srica
17954746Srica (void) fprintf(logf, "-------------------------\n");
17964746Srica (void) fprintf(logf, "Cache table begin\n");
17974746Srica
17984746Srica for (i = 0; i < TNRH_TABLE_HASH_SIZE; i++) {
17994746Srica if ((tlbt = tnrh_cache_table[i]) != NULL)
18004746Srica print_cache_entry(tlbt);
18014746Srica }
18024746Srica
18034746Srica (void) fprintf(logf, "Cache table end \n");
18044746Srica (void) fprintf(logf, "-------------------------\n\n");
18054746Srica }
18064746Srica
18074746Srica static void
cachetable_print_v6()18084746Srica cachetable_print_v6()
18094746Srica {
18104746Srica int i;
18114746Srica tnrh_tlb_ipv6_t *tlbt;
18124746Srica
18134746Srica (void) fprintf(logf, "-------------------------\n");
18144746Srica (void) fprintf(logf, "Cache table begin\n");
18154746Srica
18164746Srica for (i = 0; i < TNRH_TABLE_HASH_SIZE; i++) {
18174746Srica if ((tlbt = tnrh_cache_table_v6[i]) != NULL)
18184746Srica print_cache_entry_v6(tlbt);
18194746Srica }
18204746Srica
18214746Srica (void) fprintf(logf, "Cache table end \n");
18224746Srica (void) fprintf(logf, "-------------------------\n\n");
18234746Srica }
18244746Srica
18254746Srica
18264746Srica static void
print_entry(tsol_rhent_t * ent,int af)18274746Srica print_entry(tsol_rhent_t *ent, int af)
18284746Srica {
18294746Srica struct sockaddr_in *saddrp;
18304746Srica struct sockaddr_in6 *saddrp6;
18314746Srica char abuf[INET6_ADDRSTRLEN];
18324746Srica
18334746Srica if (af == AF_INET) {
18344746Srica saddrp = (struct sockaddr_in *)&ent->rh_address.ip_addr_v4;
18354746Srica (void) fprintf(logf, gettext("\tIP address: %s"),
18364746Srica inet_ntoa(saddrp->sin_addr));
18374746Srica } else if (af == AF_INET6) {
18384746Srica saddrp6 = (struct sockaddr_in6 *)&ent->rh_address.ip_addr_v6;
18394746Srica (void) fprintf(logf, gettext("\tIP address: %s"),
18404746Srica inet_ntop(AF_INET6, &saddrp6->sin6_addr, abuf,
18414746Srica sizeof (abuf)));
18424746Srica }
18434746Srica
18444746Srica (void) fprintf(logf,
18454746Srica gettext("\tTemplate name: %s"), ent->rh_template);
18464746Srica (void) fprintf(logf, gettext("\tprefix_len: %d\n"), ent->rh_prefix);
18474746Srica (void) fflush(logf);
18484746Srica }
18494746Srica
18504746Srica static void
print_tlbt(tnrh_tlb_t * tlbt)18514746Srica print_tlbt(tnrh_tlb_t *tlbt)
18524746Srica {
18534746Srica (void) fprintf(logf, "tlbt addr = 0x%4x name = %s \
18544746Srica mask = %u, reload = %d\n", tlbt->addr, tlbt->template_name,
18554746Srica tlbt->masklen_used, tlbt->reload);
18564746Srica }
18574746Srica
18584746Srica static void
rhtable_print()18594746Srica rhtable_print()
18604746Srica {
18614746Srica rhtable_walk(print_entry);
18624746Srica (void) fprintf(logf, "-----------------------------\n\n");
18634746Srica }
18644746Srica
18654746Srica static void
rhtable_print_v6()18664746Srica rhtable_print_v6()
18674746Srica {
18684746Srica rhtable_walk_v6(print_entry);
18694746Srica (void) fprintf(logf, "-----------------------------\n\n");
18704746Srica }
18714746Srica
18724746Srica /*
18734746Srica * Walk through all the entries in tnrh_entire_table[][]
18744746Srica * and execute the function passing the entry as argument.
18754746Srica */
18764746Srica static void
rhtable_walk(void (* action)())18774746Srica rhtable_walk(void (*action)())
18784746Srica {
18794746Srica int i, j;
18804746Srica tnd_tnrhdb_t *rhent;
18814746Srica
18824746Srica for (i = 0; i <= IP_ABITS; i++) {
18834746Srica if (tnrh_entire_table[i] == NULL)
18844746Srica continue;
18854746Srica
18864746Srica for (j = 0; j < TNRH_TABLE_HASH_SIZE; j++) {
18874746Srica rhent = tnrh_entire_table[i][j];
18884746Srica
18894746Srica while (rhent != NULL) {
18904746Srica action(&rhent->rh_ent, AF_INET);
18914746Srica rhent = rhent->rh_next;
18924746Srica }
18934746Srica }
18944746Srica }
18954746Srica }
18964746Srica
18974746Srica /*
18984746Srica * Walk through all the entries in tnrh_entire_table_v6[][]
18994746Srica * and execute the function passing the entry as argument.
19004746Srica */
19014746Srica static void
rhtable_walk_v6(void (* action)())19024746Srica rhtable_walk_v6(void (*action)())
19034746Srica {
19044746Srica int i, j;
19054746Srica tnd_tnrhdb_t *rhent;
19064746Srica
19074746Srica for (i = 0; i <= IPV6_ABITS; i++) {
19084746Srica if (tnrh_entire_table_v6[i] == NULL)
19094746Srica continue;
19104746Srica
19114746Srica for (j = 0; j < TNRH_TABLE_HASH_SIZE; j++) {
19124746Srica rhent = tnrh_entire_table_v6[i][j];
19134746Srica
19144746Srica while (rhent != NULL) {
19154746Srica action(&rhent->rh_ent, AF_INET6);
19164746Srica rhent = rhent->rh_next;
19174746Srica }
19184746Srica }
19194746Srica }
19204746Srica }
19214746Srica #endif /* DEBUG */
1922