/* Internal server test. Call with locks applied. May test a single server ip or several collectively. */ static void retest(int i, int j) { time_t s_ts; servparm_t *srv=&DA_INDEX(servers,i); int nsrvs=DA_NEL(srv->atup_a); if(!nsrvs) return; if(j>=0) { if(j<nsrvs) nsrvs=j+1; /* test just one */ } else { j=0; /* test a range of servers */ } if(!scheme_ok(srv)) { s_ts=time(NULL); for(;j<nsrvs;++j) { atup_t *at=&DA_INDEX(srv->atup_a,j); at->is_up=0; at->i_ts=s_ts; } } else if(srv->uptest==C_NONE) { s_ts=time(NULL); for(;j<nsrvs;++j) { DA_INDEX(srv->atup_a,j).i_ts=s_ts; } } else if(srv->uptest==C_QUERY || (srv->uptest==C_PING && is_inaddr_any(&srv->ping_a))) { /* test each ip address separately */ for(;j<nsrvs;++j) { atup_t *at=&DA_INDEX(srv->atup_a,j); s_ts=time(NULL); at->is_up=uptest(srv,j); if(signal_interrupt) break; at->i_ts=s_ts; } } else { /* test ip addresses collectively */ int res; s_ts=time(NULL); res=uptest(srv,j); for(;j<nsrvs;++j) { atup_t *at=&DA_INDEX(srv->atup_a,j); at->is_up=res; if(signal_interrupt && srv->uptest==C_PING) continue; at->i_ts=s_ts; } } }
bool is_filter_exact_match(struct adapter *adap, struct ch_filter_specification *fs) { struct tp_params *tp = &adap->params.tp; u64 hash_filter_mask = tp->hash_filter_mask; u32 mask; if (!is_hashfilter(adap)) return false; if (fs->type) { if (is_inaddr_any(fs->val.fip, AF_INET6) || !is_addr_all_mask(fs->mask.fip, AF_INET6)) return false; if (is_inaddr_any(fs->val.lip, AF_INET6) || !is_addr_all_mask(fs->mask.lip, AF_INET6)) return false; } else { if (is_inaddr_any(fs->val.fip, AF_INET) || !is_addr_all_mask(fs->mask.fip, AF_INET)) return false; if (is_inaddr_any(fs->val.lip, AF_INET) || !is_addr_all_mask(fs->mask.lip, AF_INET)) return false; } if (!fs->val.lport || fs->mask.lport != 0xffff) return false; if (!fs->val.fport || fs->mask.fport != 0xffff) return false; if (tp->fcoe_shift >= 0) { mask = (hash_filter_mask >> tp->fcoe_shift) & FT_FCOE_W; if (mask && !fs->mask.fcoe) return false; }
/* Report the current configuration to the file descriptor f (for the status fifo, see status.c) */ int report_conf_stat(int f) { int i,n,retval=0; fsprintf_or_return(f,"\nConfiguration:\n==============\nGlobal:\n-------\n"); fsprintf_or_return(f,"\tCache size: %li kB\n",global.perm_cache); fsprintf_or_return(f,"\tServer directory: %s\n",global.cache_dir); fsprintf_or_return(f,"\tScheme file (for Linux pcmcia support): %s\n",global.scheme_file); fsprintf_or_return(f,"\tServer port: %i\n",global.port); { char buf[ADDRSTR_MAXLEN]; fsprintf_or_return(f,"\tServer IP (%s=any available one): %s\n", SEL_IPVER("0.0.0.0","::"), pdnsd_a2str(&global.a,buf,ADDRSTR_MAXLEN)); if(!is_inaddr_any(&global.out_a)) { fsprintf_or_return(f,"\tIP bound to interface used for querying remote servers: %s\n", pdnsd_a2str(&global.out_a,buf,ADDRSTR_MAXLEN)); } } #ifdef ENABLE_IPV6 if(!run_ipv4) { char buf[ADDRSTR_MAXLEN]; fsprintf_or_return(f,"\tIPv4 to IPv6 prefix: %s\n",inet_ntop(AF_INET6,&global.ipv4_6_prefix,buf,ADDRSTR_MAXLEN)?:"?.?.?.?"); }
bool is_filter_exact_match(struct adapter *adap, struct ch_filter_specification *fs) { struct tp_params *tp = &adap->params.tp; u64 hash_filter_mask = tp->hash_filter_mask; u64 ntuple_mask = 0; if (!is_hashfilter(adap)) return false; if (fs->type) { if (is_inaddr_any(fs->val.fip, AF_INET6) || !is_addr_all_mask(fs->mask.fip, AF_INET6)) return false; if (is_inaddr_any(fs->val.lip, AF_INET6) || !is_addr_all_mask(fs->mask.lip, AF_INET6)) return false; } else { if (is_inaddr_any(fs->val.fip, AF_INET) || !is_addr_all_mask(fs->mask.fip, AF_INET)) return false; if (is_inaddr_any(fs->val.lip, AF_INET) || !is_addr_all_mask(fs->mask.lip, AF_INET)) return false; } if (!fs->val.lport || fs->mask.lport != 0xffff) return false; if (!fs->val.fport || fs->mask.fport != 0xffff) return false; /* calculate tuple mask and compare with mask configured in hw */ if (tp->fcoe_shift >= 0) ntuple_mask |= (u64)fs->mask.fcoe << tp->fcoe_shift; if (tp->port_shift >= 0) ntuple_mask |= (u64)fs->mask.iport << tp->port_shift; if (tp->vnic_shift >= 0) { if ((adap->params.tp.ingress_config & VNIC_F)) ntuple_mask |= (u64)fs->mask.pfvf_vld << tp->vnic_shift; else ntuple_mask |= (u64)fs->mask.ovlan_vld << tp->vnic_shift; } if (tp->vlan_shift >= 0) ntuple_mask |= (u64)fs->mask.ivlan << tp->vlan_shift; if (tp->tos_shift >= 0) ntuple_mask |= (u64)fs->mask.tos << tp->tos_shift; if (tp->protocol_shift >= 0) ntuple_mask |= (u64)fs->mask.proto << tp->protocol_shift; if (tp->ethertype_shift >= 0) ntuple_mask |= (u64)fs->mask.ethtype << tp->ethertype_shift; if (tp->macmatch_shift >= 0) ntuple_mask |= (u64)fs->mask.macidx << tp->macmatch_shift; if (tp->matchtype_shift >= 0) ntuple_mask |= (u64)fs->mask.matchtype << tp->matchtype_shift; if (tp->frag_shift >= 0) ntuple_mask |= (u64)fs->mask.frag << tp->frag_shift; if (ntuple_mask != hash_filter_mask) return false; return true; }
/* * Execute an individual uptest. Call with locks applied */ static int uptest (servparm_t *serv, int j) { int ret=0, count_running_ping=0; pdnsd_a *s_addr= PDNSD_A2_TO_A(&DA_INDEX(serv->atup_a,j).a); DEBUG_PDNSDA_MSG("performing uptest (type=%s) for %s\n",const_name(serv->uptest),PDNSDA2STR(s_addr)); /* Unlock the mutex because some of the tests may take a while. */ ++server_data_users; if((serv->uptest==C_PING || serv->uptest==C_QUERY) && pthread_equal(pthread_self(),servstat_thrid)) { /* Inform other threads that a ping is in progress. */ count_running_ping=1; ++server_status_ping; } pthread_mutex_unlock(&servers_lock); switch (serv->uptest) { case C_NONE: /* Don't change */ ret=DA_INDEX(serv->atup_a,j).is_up; break; case C_PING: ret=ping(is_inaddr_any(&serv->ping_a) ? s_addr : &serv->ping_a, serv->ping_timeout,PINGREPEAT)!=-1; break; case C_IF: case C_DEV: case C_DIALD: ret=if_up(serv->interface); #if (TARGET==TARGET_LINUX) if (ret!=0) { if(serv->uptest==C_DEV) ret=dev_up(serv->interface,serv->device); else if (serv->uptest==C_DIALD) ret=dev_up("diald",serv->device); } #endif break; case C_EXEC: { pid_t pid; if ((pid=fork())==-1) { DEBUG_MSG("Could not fork to perform exec uptest: %s\n",strerror(errno)); break; } else if (pid==0) { /* child */ /* * If we ran as setuid or setgid, do not inherit this to the * command. This is just a last guard. Running pdnsd as setuid() * or setgid() is a no-no. */ if (setgid(getgid()) == -1 || setuid(getuid()) == -1) { log_error("Could not reset uid or gid: %s",strerror(errno)); _exit(1); } /* Try to setuid() to a different user as specified. Good when you don't want the test command to run as root */ if (!run_as(serv->uptest_usr)) { _exit(1); } { struct rlimit rl; int i; /* * Mark all open fd's FD_CLOEXEC for paranoia reasons. */ if (getrlimit(RLIMIT_NOFILE, &rl) == -1) { log_error("getrlimit() failed: %s",strerror(errno)); _exit(1); } for (i = 0; i < rl.rlim_max; i++) { if (fcntl(i, F_SETFD, FD_CLOEXEC) == -1 && errno != EBADF) { log_error("fcntl(F_SETFD) failed: %s",strerror(errno)); _exit(1); } } } execl("/bin/sh", "uptest_sh","-c",serv->uptest_cmd,(char *)NULL); _exit(1); /* failed execl */ } else { /* parent */ int status; pid_t wpid = waitpid(pid,&status,0); if (wpid==pid) { if(WIFEXITED(status)) { int exitstatus=WEXITSTATUS(status); DEBUG_MSG("uptest command \"%s\" exited with status %d\n", serv->uptest_cmd, exitstatus); ret=(exitstatus==0); } #if DEBUG>0 else if(WIFSIGNALED(status)) { DEBUG_MSG("uptest command \"%s\" was terminated by signal %d\n", serv->uptest_cmd, WTERMSIG(status)); } else { DEBUG_MSG("status of uptest command \"%s\" is of unkown type (0x%x)\n", serv->uptest_cmd, status); } #endif } #if DEBUG>0 else if (wpid==-1) { DEBUG_MSG("Error while waiting for uptest command \"%s\" to terminate: " "waitpid for pid %d failed: %s\n", serv->uptest_cmd, pid, strerror(errno)); } else { DEBUG_MSG("Error while waiting for uptest command \"%s\" to terminate: " "waitpid returned %d, expected pid %d\n", serv->uptest_cmd, wpid, pid); } #endif } } break; case C_QUERY: ret=query_uptest(s_addr, serv->port, serv->timeout>=global.timeout?serv->timeout:global.timeout, PINGREPEAT); } /* end of switch */ pthread_mutex_lock(&servers_lock); if(count_running_ping) --server_status_ping; PDNSD_ASSERT(server_data_users>0, "server_data_users non-positive before attempt to decrement it"); if (--server_data_users==0) pthread_cond_broadcast(&server_data_cond); DEBUG_PDNSDA_MSG("result of uptest for %s: %s\n", PDNSDA2STR(s_addr), ret?"OK":"failed"); return ret; }