1911106dfSjm199354 /* 2911106dfSjm199354 * CDDL HEADER START 3911106dfSjm199354 * 4911106dfSjm199354 * The contents of this file are subject to the terms of the 5911106dfSjm199354 * Common Development and Distribution License (the "License"). 6911106dfSjm199354 * You may not use this file except in compliance with the License. 7911106dfSjm199354 * 8911106dfSjm199354 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9911106dfSjm199354 * or http://www.opensolaris.org/os/licensing. 10911106dfSjm199354 * See the License for the specific language governing permissions 11911106dfSjm199354 * and limitations under the License. 12911106dfSjm199354 * 13911106dfSjm199354 * When distributing Covered Code, include this CDDL HEADER in each 14911106dfSjm199354 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15911106dfSjm199354 * If applicable, add the following below this CDDL HEADER, with the 16911106dfSjm199354 * fields enclosed by brackets "[]" replaced with your own identifying 17911106dfSjm199354 * information: Portions Copyright [yyyy] [name of copyright owner] 18911106dfSjm199354 * 19911106dfSjm199354 * CDDL HEADER END 20911106dfSjm199354 */ 21911106dfSjm199354 /* 2253c11029Sjm199354 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23911106dfSjm199354 * Use is subject to license terms. 24911106dfSjm199354 */ 25911106dfSjm199354 26911106dfSjm199354 #pragma ident "%Z%%M% %I% %E% SMI" 27911106dfSjm199354 28911106dfSjm199354 /* 29911106dfSjm199354 * vs_eng.c manages the vs_engines array of scan engine. 30911106dfSjm199354 * Access to the array and other private data is protected by vs_eng_mutex. 31911106dfSjm199354 * A caller can wait for an available engine connection on vs_eng_cv 32911106dfSjm199354 * 33911106dfSjm199354 */ 34911106dfSjm199354 35911106dfSjm199354 #include <sys/types.h> 36911106dfSjm199354 #include <sys/synch.h> 37911106dfSjm199354 #include <sys/socket.h> 38911106dfSjm199354 #include <sys/filio.h> 39911106dfSjm199354 #include <sys/ioctl.h> 40911106dfSjm199354 #include <sys/debug.h> 41bfc848c6Sjm199354 #include <sys/time.h> 42911106dfSjm199354 #include <netinet/in.h> 43911106dfSjm199354 #include <netinet/tcp.h> 44911106dfSjm199354 #include <arpa/inet.h> 45911106dfSjm199354 #include <unistd.h> 46911106dfSjm199354 #include <stdlib.h> 47911106dfSjm199354 #include <string.h> 48911106dfSjm199354 #include <syslog.h> 49911106dfSjm199354 #include <errno.h> 50911106dfSjm199354 #include <poll.h> 51911106dfSjm199354 #include <pthread.h> 52911106dfSjm199354 #include <time.h> 53911106dfSjm199354 54bfc848c6Sjm199354 #include <signal.h> 55bfc848c6Sjm199354 #include <thread.h> 56bfc848c6Sjm199354 57911106dfSjm199354 #include "vs_incl.h" 58911106dfSjm199354 59bfc848c6Sjm199354 /* max connections per scan engine */ 60bfc848c6Sjm199354 #define VS_CXN_MAX VS_VAL_SE_MAXCONN_MAX 61bfc848c6Sjm199354 62bfc848c6Sjm199354 /* 63bfc848c6Sjm199354 * vs_eng_state_t - connection state 64bfc848c6Sjm199354 * 65bfc848c6Sjm199354 * Each configured scan engine supports up to vse_cfg.vep_maxconn 66bfc848c6Sjm199354 * connections. These connections are represented by a vs_connection_t 67bfc848c6Sjm199354 * which defines the connection state, associated socket descriptor 68bfc848c6Sjm199354 * and how long the connection has been available. A connection 69bfc848c6Sjm199354 * that has been available but unused for vs_inactivity_timeout 70bfc848c6Sjm199354 * seconds will be closed by the housekeeper thread. 71bfc848c6Sjm199354 * 72bfc848c6Sjm199354 * When a scan engine is reconfigured to have less connections 73bfc848c6Sjm199354 * (or is disabled) any of he superflous connections which are in 74bfc848c6Sjm199354 * AVAILABLE state are closed (DISCONNECTED). Others are set to 75bfc848c6Sjm199354 * CLOSE_PENDING to be closed (DISCONNECTED) when the engine is 76bfc848c6Sjm199354 * released (when the current request completes). 77bfc848c6Sjm199354 * 78bfc848c6Sjm199354 * +---------------------+ 79bfc848c6Sjm199354 * |---------->| VS_ENG_DISCONNECTED |<-----------------| 80bfc848c6Sjm199354 * | +---------------------+ | 81bfc848c6Sjm199354 * | | | 82bfc848c6Sjm199354 * | | eng_get | 83bfc848c6Sjm199354 * | v | release/ 84bfc848c6Sjm199354 * | shutdown +---------------------+ reconfig | shutdown 85bfc848c6Sjm199354 * |<----------| VS_ENG_RESERVED | -----------| | 86bfc848c6Sjm199354 * | +---------------------+ | | 87bfc848c6Sjm199354 * | | v | 88bfc848c6Sjm199354 * | | +----------------------+ 89bfc848c6Sjm199354 * | | connect | VS_ENG_CLOSE_PENDING | 90bfc848c6Sjm199354 * | | +----------------------+ 91bfc848c6Sjm199354 * | v ^ 92bfc848c6Sjm199354 * | shutdown +---------------------+ | 93bfc848c6Sjm199354 * |<----------| VS_ENG_INUSE |------------| 94bfc848c6Sjm199354 * | +---------------------+ reconfig/error 95bfc848c6Sjm199354 * | | ^ 96bfc848c6Sjm199354 * | | release | eng_get 97bfc848c6Sjm199354 * | reconfig/ | | 98bfc848c6Sjm199354 * | timeout/ v | 99bfc848c6Sjm199354 * | shutdown +---------------------+ 100bfc848c6Sjm199354 * |<----------| VS_ENG_AVAILABLE | 101bfc848c6Sjm199354 * +---------------------+ 102bfc848c6Sjm199354 * 103bfc848c6Sjm199354 */ 104bfc848c6Sjm199354 105bfc848c6Sjm199354 typedef enum { 106bfc848c6Sjm199354 VS_ENG_DISCONNECTED = 0, 107bfc848c6Sjm199354 VS_ENG_RESERVED, 108bfc848c6Sjm199354 VS_ENG_INUSE, 109bfc848c6Sjm199354 VS_ENG_AVAILABLE, 110bfc848c6Sjm199354 VS_ENG_CLOSE_PENDING 111bfc848c6Sjm199354 } vs_eng_state_t; 112bfc848c6Sjm199354 113bfc848c6Sjm199354 typedef struct vs_connection { 114bfc848c6Sjm199354 vs_eng_state_t vsc_state; 115bfc848c6Sjm199354 int vsc_sockfd; 116bfc848c6Sjm199354 struct timeval vsc_avail_time; 117bfc848c6Sjm199354 } vs_connection_t; 118911106dfSjm199354 119911106dfSjm199354 typedef struct vs_engine { 120bfc848c6Sjm199354 vs_props_se_t vse_cfg; /* host, port, maxconn */ 121bfc848c6Sjm199354 int vse_inuse; /* # connections in use */ 122bfc848c6Sjm199354 boolean_t vse_error; 123bfc848c6Sjm199354 vs_connection_t vse_cxns[VS_CXN_MAX]; 124911106dfSjm199354 } vs_engine_t; 125911106dfSjm199354 126911106dfSjm199354 static vs_engine_t vs_engines[VS_SE_MAX]; 127911106dfSjm199354 128911106dfSjm199354 static int vs_eng_next; /* round-robin "finger" */ 129911106dfSjm199354 static int vs_eng_count; /* how many configured engines */ 130911106dfSjm199354 static int vs_eng_total_maxcon; /* total configured connections */ 131911106dfSjm199354 static int vs_eng_total_inuse; /* total connections in use */ 132911106dfSjm199354 static int vs_eng_wait_count; /* # threads waiting for connection */ 133911106dfSjm199354 134911106dfSjm199354 static pthread_mutex_t vs_eng_mutex = PTHREAD_MUTEX_INITIALIZER; 135911106dfSjm199354 static pthread_cond_t vs_eng_cv; 136bfc848c6Sjm199354 int vs_inactivity_timeout = 60; /* seconds */ 137bfc848c6Sjm199354 int vs_reuse_connection = 1; 138911106dfSjm199354 139bfc848c6Sjm199354 time_t vs_eng_wait = VS_ENG_WAIT_DFLT; 140911106dfSjm199354 141911106dfSjm199354 /* local functions */ 142bfc848c6Sjm199354 static int vs_eng_connect(char *, int); 143bfc848c6Sjm199354 static boolean_t vs_eng_check_errors(void); 144bfc848c6Sjm199354 static int vs_eng_find_connection(int *, int *, boolean_t); 145bfc848c6Sjm199354 static int vs_eng_find_next(boolean_t); 146911106dfSjm199354 static int vs_eng_compare(int, char *, int); 147bfc848c6Sjm199354 static void vs_eng_config_close(vs_engine_t *, int); 148bfc848c6Sjm199354 static void *vs_eng_housekeeper(void *); 149911106dfSjm199354 150911106dfSjm199354 151911106dfSjm199354 #ifdef FIONBIO 152911106dfSjm199354 /* non-blocking connect */ 153bfc848c6Sjm199354 static int nbio_connect(int, const struct sockaddr *, int); 154911106dfSjm199354 int vs_connect_timeout = 5000; /* milliseconds */ 155911106dfSjm199354 #endif /* FIONBIO */ 156911106dfSjm199354 157911106dfSjm199354 158911106dfSjm199354 /* 159911106dfSjm199354 * vs_eng_init 160911106dfSjm199354 */ 161911106dfSjm199354 void 162911106dfSjm199354 vs_eng_init() 163911106dfSjm199354 { 164bfc848c6Sjm199354 pthread_t tid; 165bfc848c6Sjm199354 166911106dfSjm199354 (void) pthread_cond_init(&vs_eng_cv, NULL); 167911106dfSjm199354 (void) pthread_mutex_lock(&vs_eng_mutex); 168911106dfSjm199354 169bfc848c6Sjm199354 (void) memset(vs_engines, 0, sizeof (vs_engine_t) * VS_SE_MAX); 170bfc848c6Sjm199354 171911106dfSjm199354 vs_eng_total_maxcon = 0; 172911106dfSjm199354 vs_eng_total_inuse = 0; 173911106dfSjm199354 vs_eng_count = 0; 174911106dfSjm199354 vs_eng_next = 0; 175911106dfSjm199354 176911106dfSjm199354 (void) pthread_mutex_unlock(&vs_eng_mutex); 177bfc848c6Sjm199354 178bfc848c6Sjm199354 (void) pthread_create(&tid, NULL, vs_eng_housekeeper, NULL); 179911106dfSjm199354 } 180911106dfSjm199354 181911106dfSjm199354 182911106dfSjm199354 /* 183911106dfSjm199354 * vs_eng_config 184911106dfSjm199354 * 185911106dfSjm199354 * Configure scan engine connections. 186911106dfSjm199354 * 187911106dfSjm199354 * If a scan engine has been reconfigured (different host or port) 18853c11029Sjm199354 * the scan engine's error count is reset. 18953c11029Sjm199354 * 190bfc848c6Sjm199354 * If the host/port has changed, the engine has been disabled 191bfc848c6Sjm199354 * or less connections are configured now, connections need 192bfc848c6Sjm199354 * to be closed or placed in CLOSE_PENDING state (vs_eng_config_close) 193bfc848c6Sjm199354 * 194911106dfSjm199354 * vs_icap_config is invoked to reset engine-specific data stored 19553c11029Sjm199354 * in vs_icap. 196911106dfSjm199354 * 197911106dfSjm199354 */ 198911106dfSjm199354 void 199911106dfSjm199354 vs_eng_config(vs_props_all_t *config) 200911106dfSjm199354 { 201911106dfSjm199354 int i; 202911106dfSjm199354 vs_props_se_t *cfg; 20353c11029Sjm199354 vs_engine_t *eng; 204911106dfSjm199354 205911106dfSjm199354 (void) pthread_mutex_lock(&vs_eng_mutex); 206911106dfSjm199354 207911106dfSjm199354 vs_eng_count = 0; 208911106dfSjm199354 vs_eng_total_maxcon = 0; 209911106dfSjm199354 210911106dfSjm199354 for (i = 0; i < VS_SE_MAX; i++) { 211911106dfSjm199354 cfg = &config->va_se[i]; 21253c11029Sjm199354 eng = &vs_engines[i]; 213911106dfSjm199354 214bfc848c6Sjm199354 if (vs_eng_compare(i, cfg->vep_host, cfg->vep_port) != 0) { 215bfc848c6Sjm199354 vs_eng_config_close(eng, 0); 216bfc848c6Sjm199354 eng->vse_error = B_FALSE; 217bfc848c6Sjm199354 } 218911106dfSjm199354 219911106dfSjm199354 if (cfg->vep_enable) { 220bfc848c6Sjm199354 if (cfg->vep_maxconn < eng->vse_cfg.vep_maxconn) 221bfc848c6Sjm199354 vs_eng_config_close(eng, cfg->vep_maxconn); 222bfc848c6Sjm199354 22353c11029Sjm199354 eng->vse_cfg = *cfg; 224911106dfSjm199354 vs_eng_total_maxcon += cfg->vep_maxconn; 225911106dfSjm199354 vs_eng_count++; 226911106dfSjm199354 } else { 227bfc848c6Sjm199354 vs_eng_config_close(eng, 0); 22853c11029Sjm199354 (void) memset(&eng->vse_cfg, 0, sizeof (vs_props_se_t)); 229911106dfSjm199354 } 230911106dfSjm199354 23153c11029Sjm199354 vs_icap_config(i, eng->vse_cfg.vep_host, eng->vse_cfg.vep_port); 232911106dfSjm199354 } 233911106dfSjm199354 234911106dfSjm199354 if ((vs_eng_total_maxcon <= 0) || (vs_eng_count == 0)) 235*c8dbf746Sjm199354 syslog(LOG_NOTICE, "Scan Engine - no engines configured"); 236911106dfSjm199354 237911106dfSjm199354 (void) pthread_mutex_unlock(&vs_eng_mutex); 238911106dfSjm199354 } 239911106dfSjm199354 240911106dfSjm199354 241911106dfSjm199354 /* 242bfc848c6Sjm199354 * vs_eng_config_close 243911106dfSjm199354 * 244bfc848c6Sjm199354 * If the host/port has changed, the engine has been disabled 245bfc848c6Sjm199354 * or less connections are configured now, connections need 246bfc848c6Sjm199354 * to be closed or placed in CLOSE_PENDING state 247bfc848c6Sjm199354 */ 248bfc848c6Sjm199354 static void 249bfc848c6Sjm199354 vs_eng_config_close(vs_engine_t *eng, int start_idx) 250bfc848c6Sjm199354 { 251bfc848c6Sjm199354 int i; 252bfc848c6Sjm199354 vs_connection_t *cxn; 253bfc848c6Sjm199354 254bfc848c6Sjm199354 for (i = start_idx; i < eng->vse_cfg.vep_maxconn; i++) { 255bfc848c6Sjm199354 cxn = &(eng->vse_cxns[i]); 256bfc848c6Sjm199354 257bfc848c6Sjm199354 switch (cxn->vsc_state) { 258bfc848c6Sjm199354 case VS_ENG_RESERVED: 259bfc848c6Sjm199354 case VS_ENG_INUSE: 260bfc848c6Sjm199354 cxn->vsc_state = VS_ENG_CLOSE_PENDING; 261bfc848c6Sjm199354 break; 262bfc848c6Sjm199354 case VS_ENG_AVAILABLE: 263bfc848c6Sjm199354 (void) close(cxn->vsc_sockfd); 264bfc848c6Sjm199354 cxn->vsc_sockfd = -1; 265bfc848c6Sjm199354 cxn->vsc_state = VS_ENG_DISCONNECTED; 266bfc848c6Sjm199354 break; 267bfc848c6Sjm199354 case VS_ENG_CLOSE_PENDING: 268bfc848c6Sjm199354 case VS_ENG_DISCONNECTED: 269bfc848c6Sjm199354 break; 270bfc848c6Sjm199354 } 271bfc848c6Sjm199354 } 272bfc848c6Sjm199354 } 273bfc848c6Sjm199354 274bfc848c6Sjm199354 275bfc848c6Sjm199354 /* 276bfc848c6Sjm199354 * vs_eng_fini 277911106dfSjm199354 */ 278911106dfSjm199354 void 279911106dfSjm199354 vs_eng_fini() 280911106dfSjm199354 { 281911106dfSjm199354 (void) pthread_cond_destroy(&vs_eng_cv); 282bfc848c6Sjm199354 } 283bfc848c6Sjm199354 284bfc848c6Sjm199354 285bfc848c6Sjm199354 /* 286bfc848c6Sjm199354 * vs_eng_housekeeper 287bfc848c6Sjm199354 * 288bfc848c6Sjm199354 * Wakeup every (vs_inactivity_timeout / 2) seconds and close 289bfc848c6Sjm199354 * any connections that are in AVAILABLE state but have not 290bfc848c6Sjm199354 * been used for vs_inactivity_timeout seconds. 291bfc848c6Sjm199354 */ 292bfc848c6Sjm199354 /* ARGSUSED */ 293bfc848c6Sjm199354 static void * 294bfc848c6Sjm199354 vs_eng_housekeeper(void *arg) 295bfc848c6Sjm199354 { 296bfc848c6Sjm199354 struct timeval now; 297bfc848c6Sjm199354 long expire; 298bfc848c6Sjm199354 int i, j; 299bfc848c6Sjm199354 vs_engine_t *eng; 300bfc848c6Sjm199354 vs_connection_t *cxn; 301bfc848c6Sjm199354 302bfc848c6Sjm199354 for (;;) { 303bfc848c6Sjm199354 (void) sleep(vs_inactivity_timeout / 2); 304bfc848c6Sjm199354 305bfc848c6Sjm199354 if (vscand_get_state() == VS_STATE_SHUTDOWN) 306bfc848c6Sjm199354 break; 307bfc848c6Sjm199354 308bfc848c6Sjm199354 (void) gettimeofday(&now, NULL); 309bfc848c6Sjm199354 expire = now.tv_sec - vs_inactivity_timeout; 310bfc848c6Sjm199354 311bfc848c6Sjm199354 (void) pthread_mutex_lock(&vs_eng_mutex); 312bfc848c6Sjm199354 for (i = 0; i < VS_SE_MAX; i++) { 313bfc848c6Sjm199354 eng = &(vs_engines[i]); 314bfc848c6Sjm199354 for (j = 0; j < eng->vse_cfg.vep_maxconn; j++) { 315bfc848c6Sjm199354 cxn = &(eng->vse_cxns[j]); 316bfc848c6Sjm199354 317bfc848c6Sjm199354 if ((cxn->vsc_state == VS_ENG_AVAILABLE) && 318bfc848c6Sjm199354 (cxn->vsc_avail_time.tv_sec < expire)) { 319bfc848c6Sjm199354 (void) close(cxn->vsc_sockfd); 320bfc848c6Sjm199354 cxn->vsc_sockfd = -1; 321bfc848c6Sjm199354 cxn->vsc_state = VS_ENG_DISCONNECTED; 322bfc848c6Sjm199354 } 323bfc848c6Sjm199354 } 324bfc848c6Sjm199354 } 325bfc848c6Sjm199354 (void) pthread_mutex_unlock(&vs_eng_mutex); 326bfc848c6Sjm199354 } 327bfc848c6Sjm199354 328bfc848c6Sjm199354 return (NULL); 329911106dfSjm199354 } 330911106dfSjm199354 331911106dfSjm199354 332911106dfSjm199354 /* 333911106dfSjm199354 * vs_eng_set_error 334911106dfSjm199354 * 335911106dfSjm199354 * If the engine identified in conn (host, port) matches the 336911106dfSjm199354 * engine in vs_engines set or clear the error state of the 337911106dfSjm199354 * engine and update the error statistics. 338911106dfSjm199354 * 339bfc848c6Sjm199354 * If error == 0, clear the error state(B_FALSE), else set 340bfc848c6Sjm199354 * the error state (B_TRUE) and increment engine error stats 341911106dfSjm199354 */ 342911106dfSjm199354 void 343bfc848c6Sjm199354 vs_eng_set_error(vs_eng_ctx_t *eng_ctx, int error) 344911106dfSjm199354 { 345bfc848c6Sjm199354 int eidx = eng_ctx->vse_eidx; 346bfc848c6Sjm199354 int cidx = eng_ctx->vse_cidx; 347bfc848c6Sjm199354 vs_engine_t *eng; 348911106dfSjm199354 349911106dfSjm199354 (void) pthread_mutex_lock(&vs_eng_mutex); 350911106dfSjm199354 351bfc848c6Sjm199354 eng = &(vs_engines[eidx]); 352bfc848c6Sjm199354 353bfc848c6Sjm199354 if (vs_eng_compare(eidx, eng_ctx->vse_host, eng_ctx->vse_port) == 0) 354bfc848c6Sjm199354 eng->vse_error = (error == 0) ? B_FALSE : B_TRUE; 355bfc848c6Sjm199354 356bfc848c6Sjm199354 if (error != 0) { 357bfc848c6Sjm199354 eng->vse_cxns[cidx].vsc_state = VS_ENG_CLOSE_PENDING; 358bfc848c6Sjm199354 vs_stats_eng_err(eng_ctx->vse_engid); 359bfc848c6Sjm199354 } 360911106dfSjm199354 361911106dfSjm199354 (void) pthread_mutex_unlock(&vs_eng_mutex); 362911106dfSjm199354 } 363911106dfSjm199354 364911106dfSjm199354 365911106dfSjm199354 /* 366911106dfSjm199354 * vs_eng_get 367911106dfSjm199354 * Get next available scan engine connection. 368bfc848c6Sjm199354 * If retry == B_TRUE look for a scan engine with no errors. 369911106dfSjm199354 * 370911106dfSjm199354 * Returns: 0 - success 371911106dfSjm199354 * -1 - error 372911106dfSjm199354 */ 373911106dfSjm199354 int 374bfc848c6Sjm199354 vs_eng_get(vs_eng_ctx_t *eng_ctx, boolean_t retry) 375911106dfSjm199354 { 376911106dfSjm199354 struct timespec tswait; 377bfc848c6Sjm199354 int eidx, cidx, sockfd; 378bfc848c6Sjm199354 vs_engine_t *eng; 379bfc848c6Sjm199354 vs_connection_t *cxn; 380911106dfSjm199354 381911106dfSjm199354 (void) pthread_mutex_lock(&vs_eng_mutex); 382911106dfSjm199354 383911106dfSjm199354 /* 384bfc848c6Sjm199354 * If no engines connections configured OR 385911106dfSjm199354 * retry and only one engine configured, give up 386911106dfSjm199354 */ 387bfc848c6Sjm199354 if ((vs_eng_total_maxcon <= 0) || 388bfc848c6Sjm199354 ((retry == B_TRUE) && (vs_eng_count <= 1))) { 389911106dfSjm199354 (void) pthread_mutex_unlock(&vs_eng_mutex); 390911106dfSjm199354 return (-1); 391911106dfSjm199354 } 392911106dfSjm199354 393911106dfSjm199354 tswait.tv_sec = vs_eng_wait; 394911106dfSjm199354 tswait.tv_nsec = 0; 395911106dfSjm199354 396911106dfSjm199354 while ((vscand_get_state() != VS_STATE_SHUTDOWN) && 397bfc848c6Sjm199354 (vs_eng_find_connection(&eidx, &cidx, retry) == -1)) { 398911106dfSjm199354 /* If retry and all configured engines have errors, give up */ 399bfc848c6Sjm199354 if (retry && vs_eng_check_errors() == B_TRUE) { 400911106dfSjm199354 (void) pthread_mutex_unlock(&vs_eng_mutex); 401911106dfSjm199354 return (-1); 402911106dfSjm199354 } 403911106dfSjm199354 404911106dfSjm199354 /* wait for a connection to become available */ 405911106dfSjm199354 vs_eng_wait_count++; 406911106dfSjm199354 if (pthread_cond_reltimedwait_np(&vs_eng_cv, &vs_eng_mutex, 407911106dfSjm199354 &tswait) < 0) { 408*c8dbf746Sjm199354 syslog(LOG_NOTICE, "Scan Engine " 409911106dfSjm199354 "- timeout waiting for available engine"); 410911106dfSjm199354 vs_eng_wait_count--; 411911106dfSjm199354 (void) pthread_mutex_unlock(&vs_eng_mutex); 412911106dfSjm199354 return (-1); 413911106dfSjm199354 } 414911106dfSjm199354 vs_eng_wait_count--; 415911106dfSjm199354 } 416911106dfSjm199354 417911106dfSjm199354 if (vscand_get_state() == VS_STATE_SHUTDOWN) { 418911106dfSjm199354 (void) pthread_mutex_unlock(&vs_eng_mutex); 419911106dfSjm199354 return (-1); 420911106dfSjm199354 } 421911106dfSjm199354 422bfc848c6Sjm199354 eng = &(vs_engines[eidx]); 423bfc848c6Sjm199354 cxn = &(eng->vse_cxns[cidx]); 424911106dfSjm199354 425911106dfSjm199354 /* update in use counts */ 426bfc848c6Sjm199354 eng->vse_inuse++; 427911106dfSjm199354 vs_eng_total_inuse++; 428911106dfSjm199354 429911106dfSjm199354 /* update round-robin index */ 430911106dfSjm199354 if (!retry) 431bfc848c6Sjm199354 vs_eng_next = (eidx == VS_SE_MAX) ? 0 : eidx + 1; 432bfc848c6Sjm199354 433bfc848c6Sjm199354 /* populate vs_eng_ctx_t */ 434bfc848c6Sjm199354 eng_ctx->vse_eidx = eidx; 435bfc848c6Sjm199354 eng_ctx->vse_cidx = cidx; 436bfc848c6Sjm199354 (void) strlcpy(eng_ctx->vse_engid, eng->vse_cfg.vep_engid, 437bfc848c6Sjm199354 sizeof (eng_ctx->vse_engid)); 438bfc848c6Sjm199354 (void) strlcpy(eng_ctx->vse_host, eng->vse_cfg.vep_host, 439bfc848c6Sjm199354 sizeof (eng_ctx->vse_host)); 440bfc848c6Sjm199354 eng_ctx->vse_port = eng->vse_cfg.vep_port; 441bfc848c6Sjm199354 eng_ctx->vse_sockfd = cxn->vsc_sockfd; 442bfc848c6Sjm199354 443bfc848c6Sjm199354 if (cxn->vsc_state == VS_ENG_INUSE) { 444bfc848c6Sjm199354 (void) pthread_mutex_unlock(&vs_eng_mutex); 445bfc848c6Sjm199354 return (0); 446bfc848c6Sjm199354 } 447bfc848c6Sjm199354 448bfc848c6Sjm199354 /* state == VS_ENG_RESERVED, need to connect */ 449911106dfSjm199354 450911106dfSjm199354 (void) pthread_mutex_unlock(&vs_eng_mutex); 451911106dfSjm199354 452bfc848c6Sjm199354 sockfd = vs_eng_connect(eng_ctx->vse_host, eng_ctx->vse_port); 453bfc848c6Sjm199354 454bfc848c6Sjm199354 /* retry a failed connection once */ 455bfc848c6Sjm199354 if (sockfd == -1) { 456bfc848c6Sjm199354 (void) sleep(1); 457bfc848c6Sjm199354 sockfd = vs_eng_connect(eng_ctx->vse_host, eng_ctx->vse_port); 458bfc848c6Sjm199354 } 459bfc848c6Sjm199354 460bfc848c6Sjm199354 if (sockfd == -1) { 461*c8dbf746Sjm199354 syslog(LOG_NOTICE, "Scan Engine - connection error (%s:%d) %s", 462bfc848c6Sjm199354 eng_ctx->vse_host, eng_ctx->vse_port, 463bfc848c6Sjm199354 errno ? strerror(errno) : ""); 464bfc848c6Sjm199354 vs_eng_set_error(eng_ctx, 1); 465bfc848c6Sjm199354 vs_eng_release(eng_ctx); 466bfc848c6Sjm199354 return (-1); 467bfc848c6Sjm199354 } 468bfc848c6Sjm199354 469bfc848c6Sjm199354 (void) pthread_mutex_lock(&vs_eng_mutex); 470bfc848c6Sjm199354 switch (cxn->vsc_state) { 471bfc848c6Sjm199354 case VS_ENG_DISCONNECTED: 472bfc848c6Sjm199354 /* SHUTDOWN occured */ 473bfc848c6Sjm199354 (void) pthread_mutex_unlock(&vs_eng_mutex); 474bfc848c6Sjm199354 vs_eng_release(eng_ctx); 475bfc848c6Sjm199354 return (-1); 476bfc848c6Sjm199354 case VS_ENG_RESERVED: 477bfc848c6Sjm199354 cxn->vsc_state = VS_ENG_INUSE; 478bfc848c6Sjm199354 break; 479bfc848c6Sjm199354 case VS_ENG_CLOSE_PENDING: 480bfc848c6Sjm199354 /* reconfigure occured. Connection will be closed after use */ 481bfc848c6Sjm199354 break; 482bfc848c6Sjm199354 case VS_ENG_INUSE: 483bfc848c6Sjm199354 case VS_ENG_AVAILABLE: 484bfc848c6Sjm199354 default: 485bfc848c6Sjm199354 ASSERT(0); 486bfc848c6Sjm199354 break; 487bfc848c6Sjm199354 } 488bfc848c6Sjm199354 489bfc848c6Sjm199354 cxn->vsc_sockfd = sockfd; 490bfc848c6Sjm199354 eng_ctx->vse_sockfd = sockfd; 491bfc848c6Sjm199354 492bfc848c6Sjm199354 (void) pthread_mutex_unlock(&vs_eng_mutex); 493911106dfSjm199354 return (0); 494911106dfSjm199354 } 495911106dfSjm199354 496911106dfSjm199354 497911106dfSjm199354 /* 498911106dfSjm199354 * vs_eng_check_errors 499911106dfSjm199354 * 500bfc848c6Sjm199354 * Check if all engines with maxconn > 0 are in error state 501911106dfSjm199354 * 502bfc848c6Sjm199354 * Returns: B_TRUE - all (valid) engines are in error state 503bfc848c6Sjm199354 * B_FALSE - otherwise 504911106dfSjm199354 */ 505bfc848c6Sjm199354 static boolean_t 506911106dfSjm199354 vs_eng_check_errors() 507911106dfSjm199354 { 508911106dfSjm199354 int i; 509911106dfSjm199354 510911106dfSjm199354 for (i = 0; i < VS_SE_MAX; i++) { 511911106dfSjm199354 if (vs_engines[i].vse_cfg.vep_maxconn > 0 && 512bfc848c6Sjm199354 (vs_engines[i].vse_error == B_FALSE)) 513bfc848c6Sjm199354 return (B_FALSE); 514bfc848c6Sjm199354 } 515bfc848c6Sjm199354 516bfc848c6Sjm199354 return (B_TRUE); 517bfc848c6Sjm199354 } 518bfc848c6Sjm199354 519bfc848c6Sjm199354 520bfc848c6Sjm199354 /* 521bfc848c6Sjm199354 * vs_eng_find_connection 522bfc848c6Sjm199354 * 523bfc848c6Sjm199354 * Identify the next engine to be used (vs_eng_find_next()). 524bfc848c6Sjm199354 * Select the engine's first connection in AVAILABLE state. 525bfc848c6Sjm199354 * If no connection is in AVAILABLE state, select the first 526bfc848c6Sjm199354 * that is in DISCONNECTED state. 527bfc848c6Sjm199354 * 528bfc848c6Sjm199354 * Returns: 0 success 529bfc848c6Sjm199354 * -1 no engine connections available (eng_idx & cxn_idx undefined) 530bfc848c6Sjm199354 */ 531bfc848c6Sjm199354 static int 532bfc848c6Sjm199354 vs_eng_find_connection(int *eng_idx, int *cxn_idx, boolean_t retry) 533bfc848c6Sjm199354 { 534bfc848c6Sjm199354 int i, idx; 535bfc848c6Sjm199354 vs_engine_t *eng; 536bfc848c6Sjm199354 vs_connection_t *cxn; 537bfc848c6Sjm199354 538bfc848c6Sjm199354 /* identify engine */ 539bfc848c6Sjm199354 if ((idx = vs_eng_find_next(retry)) == -1) 540bfc848c6Sjm199354 return (-1); 541bfc848c6Sjm199354 542bfc848c6Sjm199354 eng = &(vs_engines[idx]); 543bfc848c6Sjm199354 *eng_idx = idx; 544bfc848c6Sjm199354 545bfc848c6Sjm199354 /* identify connection */ 546bfc848c6Sjm199354 idx = -1; 547bfc848c6Sjm199354 for (i = 0; i < eng->vse_cfg.vep_maxconn; i++) { 548bfc848c6Sjm199354 cxn = &(eng->vse_cxns[i]); 549bfc848c6Sjm199354 if (cxn->vsc_state == VS_ENG_AVAILABLE) { 550bfc848c6Sjm199354 *cxn_idx = i; 551bfc848c6Sjm199354 cxn->vsc_state = VS_ENG_INUSE; 552911106dfSjm199354 return (0); 553911106dfSjm199354 } 554911106dfSjm199354 555bfc848c6Sjm199354 if ((idx == -1) && 556bfc848c6Sjm199354 (cxn->vsc_state == VS_ENG_DISCONNECTED)) { 557bfc848c6Sjm199354 idx = i; 558bfc848c6Sjm199354 } 559bfc848c6Sjm199354 } 560bfc848c6Sjm199354 561bfc848c6Sjm199354 if (idx == -1) 562bfc848c6Sjm199354 return (-1); 563bfc848c6Sjm199354 564bfc848c6Sjm199354 eng->vse_cxns[idx].vsc_state = VS_ENG_RESERVED; 565bfc848c6Sjm199354 *cxn_idx = idx; 566bfc848c6Sjm199354 return (0); 567911106dfSjm199354 } 568911106dfSjm199354 569911106dfSjm199354 570911106dfSjm199354 /* 571911106dfSjm199354 * vs_eng_find_next 572911106dfSjm199354 * 573911106dfSjm199354 * Returns: -1 no engine connections available 574911106dfSjm199354 * idx of engine to use 575911106dfSjm199354 */ 576911106dfSjm199354 static int 577bfc848c6Sjm199354 vs_eng_find_next(boolean_t retry) 578911106dfSjm199354 { 579911106dfSjm199354 int i; 580911106dfSjm199354 581911106dfSjm199354 for (i = vs_eng_next; i < VS_SE_MAX; i++) { 582bfc848c6Sjm199354 if (vs_engines[i].vse_inuse < 583911106dfSjm199354 vs_engines[i].vse_cfg.vep_maxconn) { 584bfc848c6Sjm199354 if (!retry || (vs_engines[i].vse_error == B_FALSE)) 585911106dfSjm199354 return (i); 586911106dfSjm199354 } 587911106dfSjm199354 } 588911106dfSjm199354 589911106dfSjm199354 for (i = 0; i < vs_eng_next; i++) { 590bfc848c6Sjm199354 if (vs_engines[i].vse_inuse < 591911106dfSjm199354 vs_engines[i].vse_cfg.vep_maxconn) { 592bfc848c6Sjm199354 if (!retry || (vs_engines[i].vse_error == B_FALSE)) 593911106dfSjm199354 return (i); 594911106dfSjm199354 } 595911106dfSjm199354 } 596911106dfSjm199354 597911106dfSjm199354 return (-1); 598911106dfSjm199354 } 599911106dfSjm199354 600911106dfSjm199354 601911106dfSjm199354 /* 602911106dfSjm199354 * vs_eng_release 603911106dfSjm199354 */ 604911106dfSjm199354 void 605bfc848c6Sjm199354 vs_eng_release(const vs_eng_ctx_t *eng_ctx) 606911106dfSjm199354 { 607bfc848c6Sjm199354 int eidx = eng_ctx->vse_eidx; 608bfc848c6Sjm199354 int cidx = eng_ctx->vse_cidx; 609bfc848c6Sjm199354 vs_connection_t *cxn; 610911106dfSjm199354 611911106dfSjm199354 (void) pthread_mutex_lock(&vs_eng_mutex); 612bfc848c6Sjm199354 cxn = &(vs_engines[eidx].vse_cxns[cidx]); 613bfc848c6Sjm199354 614bfc848c6Sjm199354 switch (cxn->vsc_state) { 615bfc848c6Sjm199354 case VS_ENG_DISCONNECTED: 616bfc848c6Sjm199354 break; 617bfc848c6Sjm199354 case VS_ENG_RESERVED: 618bfc848c6Sjm199354 cxn->vsc_state = VS_ENG_DISCONNECTED; 619bfc848c6Sjm199354 break; 620bfc848c6Sjm199354 case VS_ENG_INUSE: 621bfc848c6Sjm199354 if (vs_reuse_connection) { 622bfc848c6Sjm199354 cxn->vsc_state = VS_ENG_AVAILABLE; 623bfc848c6Sjm199354 (void) gettimeofday(&cxn->vsc_avail_time, NULL); 624bfc848c6Sjm199354 break; 625bfc848c6Sjm199354 } 626bfc848c6Sjm199354 /* LINTED E_CASE_FALL_THROUGH - close connection */ 627bfc848c6Sjm199354 case VS_ENG_CLOSE_PENDING: 628bfc848c6Sjm199354 (void) close(cxn->vsc_sockfd); 629bfc848c6Sjm199354 cxn->vsc_sockfd = -1; 630bfc848c6Sjm199354 cxn->vsc_state = VS_ENG_DISCONNECTED; 631bfc848c6Sjm199354 break; 632bfc848c6Sjm199354 case VS_ENG_AVAILABLE: 633bfc848c6Sjm199354 default: 634bfc848c6Sjm199354 ASSERT(0); 635bfc848c6Sjm199354 break; 636bfc848c6Sjm199354 } 637911106dfSjm199354 638911106dfSjm199354 /* decrement in use counts */ 639bfc848c6Sjm199354 vs_engines[eidx].vse_inuse--; 640911106dfSjm199354 vs_eng_total_inuse--; 641911106dfSjm199354 642911106dfSjm199354 /* wake up next thread waiting for a connection */ 643911106dfSjm199354 (void) pthread_cond_signal(&vs_eng_cv); 644911106dfSjm199354 645911106dfSjm199354 (void) pthread_mutex_unlock(&vs_eng_mutex); 646911106dfSjm199354 } 647911106dfSjm199354 648911106dfSjm199354 649911106dfSjm199354 /* 650911106dfSjm199354 * vs_eng_close_connections 651bfc848c6Sjm199354 * 652bfc848c6Sjm199354 * Set vs_eng_total_maxcon to 0 to ensure no new engine sessions 653bfc848c6Sjm199354 * can be initiated. 654911106dfSjm199354 * Close all open connections to abort in-progress scans. 655bfc848c6Sjm199354 * Set connection state to DISCONNECTED. 656911106dfSjm199354 */ 657bfc848c6Sjm199354 void 658911106dfSjm199354 vs_eng_close_connections(void) 659911106dfSjm199354 { 660bfc848c6Sjm199354 int i, j; 661bfc848c6Sjm199354 vs_connection_t *cxn; 662bfc848c6Sjm199354 663bfc848c6Sjm199354 (void) pthread_mutex_lock(&vs_eng_mutex); 664bfc848c6Sjm199354 vs_eng_total_maxcon = 0; 665911106dfSjm199354 666911106dfSjm199354 for (i = 0; i < VS_SE_MAX; i++) { 667bfc848c6Sjm199354 for (j = 0; j < VS_CXN_MAX; j++) { 668bfc848c6Sjm199354 cxn = &(vs_engines[i].vse_cxns[j]); 669bfc848c6Sjm199354 670bfc848c6Sjm199354 switch (cxn->vsc_state) { 671bfc848c6Sjm199354 case VS_ENG_INUSE: 672bfc848c6Sjm199354 case VS_ENG_AVAILABLE: 673bfc848c6Sjm199354 case VS_ENG_CLOSE_PENDING: 674bfc848c6Sjm199354 (void) close(cxn->vsc_sockfd); 675bfc848c6Sjm199354 cxn->vsc_sockfd = -1; 676bfc848c6Sjm199354 break; 677bfc848c6Sjm199354 case VS_ENG_DISCONNECTED: 678bfc848c6Sjm199354 case VS_ENG_RESERVED: 679bfc848c6Sjm199354 default: 680bfc848c6Sjm199354 break; 681bfc848c6Sjm199354 682bfc848c6Sjm199354 } 683bfc848c6Sjm199354 684bfc848c6Sjm199354 cxn->vsc_state = VS_ENG_DISCONNECTED; 685911106dfSjm199354 } 686911106dfSjm199354 } 687bfc848c6Sjm199354 (void) pthread_mutex_unlock(&vs_eng_mutex); 688911106dfSjm199354 } 689911106dfSjm199354 690911106dfSjm199354 691911106dfSjm199354 /* 692911106dfSjm199354 * vs_eng_connect 693911106dfSjm199354 * open socket connection to remote scan engine 694bfc848c6Sjm199354 * 695bfc848c6Sjm199354 * Returns: sockfd or -1 (error) 696911106dfSjm199354 */ 697bfc848c6Sjm199354 static int 698bfc848c6Sjm199354 vs_eng_connect(char *host, int port) 699911106dfSjm199354 { 700bfc848c6Sjm199354 int rc, sockfd, opt_nodelay, opt_keepalive, opt_reuseaddr, err_num; 701911106dfSjm199354 struct sockaddr_in addr; 702911106dfSjm199354 struct hostent *hp; 703911106dfSjm199354 704bfc848c6Sjm199354 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 705911106dfSjm199354 return (-1); 706911106dfSjm199354 707bfc848c6Sjm199354 hp = getipnodebyname(host, AF_INET, 0, &err_num); 708bfc848c6Sjm199354 if (hp == NULL) { 709bfc848c6Sjm199354 (void) close(sockfd); 710911106dfSjm199354 return (-1); 711bfc848c6Sjm199354 } 712911106dfSjm199354 713911106dfSjm199354 (void) memset(&addr, 0, sizeof (addr)); 714911106dfSjm199354 (void) memcpy(&addr.sin_addr, hp->h_addr, hp->h_length); 715bfc848c6Sjm199354 addr.sin_port = htons(port); 716911106dfSjm199354 addr.sin_family = hp->h_addrtype; 717911106dfSjm199354 freehostent(hp); 718911106dfSjm199354 719911106dfSjm199354 #ifdef FIONBIO /* Use non-blocking mode for connect. */ 720bfc848c6Sjm199354 rc = nbio_connect(sockfd, (struct sockaddr *)&addr, 721911106dfSjm199354 sizeof (struct sockaddr)); 722911106dfSjm199354 #else 723bfc848c6Sjm199354 rc = connect(sockfd, (struct sockaddr *)&addr, 724911106dfSjm199354 sizeof (struct sockaddr)); 725911106dfSjm199354 #endif 726911106dfSjm199354 727bfc848c6Sjm199354 opt_nodelay = 1; 728bfc848c6Sjm199354 opt_keepalive = 1; 729bfc848c6Sjm199354 opt_reuseaddr = 1; 730911106dfSjm199354 731bfc848c6Sjm199354 if ((rc < 0) || 732bfc848c6Sjm199354 (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, 733bfc848c6Sjm199354 &opt_nodelay, sizeof (opt_nodelay)) < 0) || 734bfc848c6Sjm199354 (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, 735bfc848c6Sjm199354 &opt_keepalive, sizeof (opt_keepalive)) < 0) || 736bfc848c6Sjm199354 (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, 737bfc848c6Sjm199354 &opt_reuseaddr, sizeof (opt_reuseaddr)) < 0)) { 738bfc848c6Sjm199354 (void) close(sockfd); 739911106dfSjm199354 return (-1); 740911106dfSjm199354 } 741911106dfSjm199354 742bfc848c6Sjm199354 return (sockfd); 743911106dfSjm199354 } 744911106dfSjm199354 745911106dfSjm199354 746911106dfSjm199354 /* 747911106dfSjm199354 * nbio_connect 748911106dfSjm199354 * 749911106dfSjm199354 * Attempt to do a non-blocking connect call. 750911106dfSjm199354 * Wait for a maximum of "vs_connect_timeout" millisec, then check for 751911106dfSjm199354 * socket error to determine if connect successful or not. 752911106dfSjm199354 */ 753911106dfSjm199354 #ifdef FIONBIO 754911106dfSjm199354 static int 755bfc848c6Sjm199354 nbio_connect(int sockfd, const struct sockaddr *sa, int sa_len) 756911106dfSjm199354 { 757911106dfSjm199354 struct pollfd pfd; 758911106dfSjm199354 int nbio, rc; 759911106dfSjm199354 int error, len = sizeof (error); 760911106dfSjm199354 761911106dfSjm199354 nbio = 1; 762bfc848c6Sjm199354 if ((ioctl(sockfd, FIONBIO, &nbio)) < 0) 763bfc848c6Sjm199354 return (connect(sockfd, sa, sa_len)); 764911106dfSjm199354 765bfc848c6Sjm199354 if ((rc = connect(sockfd, sa, sa_len)) != 0) { 766911106dfSjm199354 if (errno == EINPROGRESS || errno == EINTR) { 767bfc848c6Sjm199354 errno = 0; 768bfc848c6Sjm199354 pfd.fd = sockfd; 769911106dfSjm199354 pfd.events = POLLOUT; 770911106dfSjm199354 pfd.revents = 0; 771911106dfSjm199354 772911106dfSjm199354 if ((rc = poll(&pfd, 1, vs_connect_timeout)) <= 0) { 773911106dfSjm199354 if (rc == 0) 774911106dfSjm199354 errno = ETIMEDOUT; 775911106dfSjm199354 rc = -1; 776911106dfSjm199354 } else { 777bfc848c6Sjm199354 if ((pfd.revents & 778bfc848c6Sjm199354 (POLLHUP | POLLERR | POLLNVAL)) || 779bfc848c6Sjm199354 (!(pfd.revents & POLLOUT))) { 780bfc848c6Sjm199354 rc = -1; 781bfc848c6Sjm199354 } else { 782bfc848c6Sjm199354 rc = getsockopt(sockfd, SOL_SOCKET, 783bfc848c6Sjm199354 SO_ERROR, &error, &len); 784911106dfSjm199354 if (rc != 0 || error != 0) 785911106dfSjm199354 rc = -1; 786bfc848c6Sjm199354 if (error != 0) 787bfc848c6Sjm199354 errno = error; 788bfc848c6Sjm199354 } 789911106dfSjm199354 } 790911106dfSjm199354 } 791911106dfSjm199354 } 792911106dfSjm199354 793911106dfSjm199354 nbio = 0; 794bfc848c6Sjm199354 (void) ioctl(sockfd, FIONBIO, &nbio); 795911106dfSjm199354 796911106dfSjm199354 return (rc); 797911106dfSjm199354 } 798911106dfSjm199354 #endif 799911106dfSjm199354 800911106dfSjm199354 801911106dfSjm199354 /* 802911106dfSjm199354 * vs_eng_scanstamp_current 803911106dfSjm199354 * 804911106dfSjm199354 * Check if scanstamp matches that of ANY engine with no errors. 805911106dfSjm199354 * We cannot include engines with errors as they may have been 806911106dfSjm199354 * inaccessible for a long time and thus we may have an old 807911106dfSjm199354 * scanstamp value for them. 808911106dfSjm199354 * If a match is found the scanstamp is considered to be current 809911106dfSjm199354 * 810911106dfSjm199354 * returns: 1 if current, 0 otherwise 811911106dfSjm199354 */ 812911106dfSjm199354 int 813911106dfSjm199354 vs_eng_scanstamp_current(vs_scanstamp_t scanstamp) 814911106dfSjm199354 { 815911106dfSjm199354 int i; 816911106dfSjm199354 817911106dfSjm199354 /* if scan stamp is null, not current */ 818911106dfSjm199354 if (scanstamp[0] == '\0') 819911106dfSjm199354 return (0); 820911106dfSjm199354 82153c11029Sjm199354 /* if scanstamp matches that of any enabled engine with no errors */ 822911106dfSjm199354 (void) pthread_mutex_lock(&vs_eng_mutex); 823911106dfSjm199354 for (i = 0; i < VS_SE_MAX; i++) { 82453c11029Sjm199354 if ((vs_engines[i].vse_cfg.vep_enable) && 825bfc848c6Sjm199354 (vs_engines[i].vse_error == B_FALSE) && 826911106dfSjm199354 (vs_icap_compare_scanstamp(i, scanstamp) == 0)) 827911106dfSjm199354 break; 828911106dfSjm199354 } 829911106dfSjm199354 (void) pthread_mutex_unlock(&vs_eng_mutex); 830911106dfSjm199354 831911106dfSjm199354 return ((i < VS_SE_MAX) ? 1 : 0); 832911106dfSjm199354 } 833911106dfSjm199354 834911106dfSjm199354 835911106dfSjm199354 /* 836911106dfSjm199354 * vs_eng_compare 837911106dfSjm199354 * compare host and port with that stored for engine idx 838911106dfSjm199354 * 839911106dfSjm199354 * Returns: 0 - if equal 840911106dfSjm199354 */ 841911106dfSjm199354 static int 842911106dfSjm199354 vs_eng_compare(int idx, char *host, int port) 843911106dfSjm199354 { 844911106dfSjm199354 if (vs_engines[idx].vse_cfg.vep_port != port) 845911106dfSjm199354 return (-1); 846911106dfSjm199354 847911106dfSjm199354 if (strcmp(vs_engines[idx].vse_cfg.vep_host, host) != 0) 848911106dfSjm199354 return (-1); 849911106dfSjm199354 850911106dfSjm199354 return (0); 851911106dfSjm199354 } 852