static void do_signalled(void) { sigprocmask(SIG_SETMASK, &ssblock, NULL); if (signalled & SIGNALLED_TERM) { if (fork_on_reload < 0) { /* this is a temp child; dump stats and exit */ ipc_write_stats(1); if (flog && !flushlog) fflush(flog); _exit(0); } dslog(LOG_INFO, 0, "terminating"); #ifndef NO_STATS if (statsfile) dumpstats(); logstats(0); if (statsfile) dumpstats_z(); #endif exit(0); } #ifndef NO_STATS if (signalled & SIGNALLED_SSTATS && statsfile) dumpstats(); if (signalled & SIGNALLED_LSTATS) { logstats(signalled & SIGNALLED_ZSTATS); if (signalled & SIGNALLED_ZSTATS && statsfile) dumpstats_z(); } #endif if (signalled & SIGNALLED_RELOG) reopenlog(); if (signalled & SIGNALLED_RELOAD) do_reload(fork_on_reload); signalled = 0; sigprocmask(SIG_SETMASK, &ssempty, NULL); }
void dsloaded(struct dsctx *dsc, const char *fmt, ...) { va_list ap; if (dsc->dsc_warns > MAXWARN) dslog(LOG_WARNING, dsc, "%d more warnings suppressed", dsc->dsc_warns - MAXWARN); va_start(ap, fmt); if (dsc->dsc_subset) vdslog(LOG_INFO, dsc, fmt, ap); else { struct tm *tm = gmtime(&dsc->dsc_ds->ds_stamp); char buf[128]; vssprintf(buf, sizeof(buf), fmt, ap); dslog(LOG_INFO, dsc, "%04d%02d%02d %02d%02d%02d: %s", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, buf); } va_end(ap); }
void zlog(int level, const struct zone *zone, const char *fmt, ...) { va_list ap; char buf[128]; char name[DNS_MAXDOMAIN+1]; va_start(ap, fmt); vssprintf(buf, sizeof(buf), fmt, ap); va_end(ap); dns_dntop(zone->z_dn, name, sizeof(name)); dslog(level, 0, "zone %.70s: %s", name, buf); }
void mvContours::match_contour_with_database (CvSeq* contour1, int &best_match_index, double &best_match_diff, int method, std::vector<HU_MOMENTS> hu_moments_vector) { HU_MOMENTS hus_to_match; get_hu_moments (contour1, hus_to_match); best_match_diff = 1000000; #ifdef MATCH_CONTOURS_DEBUG printf ("Matching Contours:\n"); #endif for (unsigned i = 0; i < hu_moments_vector.size(); i++) { HU_MOMENTS hus_template = hu_moments_vector[i]; double curr_diff = 0; // calculate curr_diff for (int j = 0; j < 7; j++) { double m1 = dslog(hus_to_match[j]); double m2 = dslog(hus_template[j]); if (isnan(m1)) m1 = -100000000; if (isnan(m2)) m2 = -100000000; if (method == CONTOURS_MATCH_NORMAL) curr_diff += fabs(m1 - m2); else if (method == CONTOURS_MATCH_RECIP) curr_diff += fabs(1.0/m1 - 1.0/m2); else if (method == CONTOURS_MATCH_RECIP) curr_diff += fabs((m1-m2)/m1); } #ifdef MATCH_CONTOURS_DEBUG printf ("contour %d: %9.6lf\n", i, curr_diff); #endif if (i == 0 || curr_diff < best_match_diff) { best_match_index = i; best_match_diff = curr_diff; } } DEBUG_PRINT ("Best Match Diff = %9.6lf\n", best_match_diff); }
static void logstats(int reset) { time_t t = time(NULL); time_t d = t - stats_time; struct dnsstats tot = gstats; char name[DNS_MAXDOMAIN+1]; struct zone *z; #define C(x) " " #x "=%" PRI_DNSCNT for(z = zonelist; z; z = z->z_next) { #define add(x) tot.x += z->z_stats.x add(b_in); add(b_out); add(q_ok); add(q_nxd); add(q_err); #undef add dns_dntop(z->z_dn, name, sizeof(name)); dslog(LOG_INFO, 0, "stats for %ldsecs zone %.60s:" C(tot) C(ok) C(nxd) C(err) C(in) C(out), (long)d, name, z->z_stats.q_ok + z->z_stats.q_nxd + z->z_stats.q_err, z->z_stats.q_ok, z->z_stats.q_nxd, z->z_stats.q_err, z->z_stats.b_in, z->z_stats.b_out); } dslog(LOG_INFO, 0, "stats for %ldsec:" C(tot) C(ok) C(nxd) C(err) C(in) C(out), (long)d, tot.q_ok + tot.q_nxd + tot.q_err, tot.q_ok, tot.q_nxd, tot.q_err, tot.b_in, tot.b_out); #undef C if (reset) { for(z = zonelist; z; z = z->z_next) { memset(&z->z_stats, 0, sizeof(z->z_stats)); memset(&z->z_pstats, 0, sizeof(z->z_pstats)); } memset(&gstats, 0, sizeof(gstats)); memset(&gptot, 0, sizeof(gptot)); stats_time = t; } }
static void newsocket(struct sockaddr_in *sin) { int fd; const char *host = ip4atos(ntohl(sin->sin_addr.s_addr)); if (numsock >= MAXSOCK) error(0, "too many listening sockets (%d max)", MAXSOCK); fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (fd < 0) error(errno, "unable to create socket"); if (bind(fd, (struct sockaddr *)sin, sizeof(*sin)) < 0) error(errno, "unable to bind to %s/%d", host, ntohs(sin->sin_port)); dslog(LOG_INFO, 0, "listening on %s/%d", host, ntohs(sin->sin_port)); sock[numsock++] = fd; }
static void reopenlog(void) { if (logfile) { int fd; if (flog) fclose(flog); fd = open(logfile, O_WRONLY|O_APPEND|O_CREAT|O_NONBLOCK|O_LARGEFILE, 0644); if (fd < 0 || (flog = fdopen(fd, "a")) == NULL) { dslog(LOG_WARNING, 0, "error (re)opening logfile `%.50s': %s", logfile, strerror(errno)); if (fd >= 0) close(fd); flog = NULL; } } else if (flog && !flushlog) { /* log to stdout */ clearerr(flog); fflush(flog); } }
static int newsocket(struct addrinfo *ai) { int fd; char host[NI_MAXHOST], serv[NI_MAXSERV]; if (numsock >= MAXSOCK) error(0, "too many listening sockets (%d max)", MAXSOCK); fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (fd < 0) { if (errno == EAFNOSUPPORT) return 0; error(errno, "unable to create socket"); } getnameinfo(ai->ai_addr, ai->ai_addrlen, host, sizeof(host), serv, sizeof(serv), NI_NUMERICHOST|NI_NUMERICSERV); if (bind(fd, ai->ai_addr, ai->ai_addrlen) < 0) error(errno, "unable to bind to %s/%s", host, serv); dslog(LOG_INFO, 0, "listening on %s/%s", host, serv); sock[numsock++] = fd; return 1; }
static int do_reload(int do_fork) { int r; char ibuf[150]; int ip; struct dataset *ds; struct zone *zone; pid_t cpid = 0; /* child pid; =0 to make gcc happy */ int cfd = 0; /* child stats fd; =0 to make gcc happy */ #ifndef NO_TIMES struct tms tms; clock_t utm, etm; #ifndef HZ static clock_t HZ; #endif #endif /* NO_TIMES */ ds = nextdataset2reload(NULL); if (!ds && call_hook(reload_check, (zonelist)) == 0) { check_expires(); return 1; /* nothing to reload */ } if (do_fork) { int pfd[2]; if (flog && !flushlog) fflush(flog); /* forking reload. if anything fails, just do a non-forking one */ if (pipe(pfd) < 0) do_fork = 0; else if ((cpid = fork()) < 0) { /* fork failed, close the pipe */ close(pfd[0]); close(pfd[1]); do_fork = 0; } else if (!cpid) { /* child, continue answering queries */ signal(SIGALRM, SIG_IGN); signal(SIGHUP, SIG_IGN); #ifndef NO_STATS signal(SIGUSR1, SIG_IGN); signal(SIGUSR2, SIG_IGN); #endif close(pfd[0]); /* set up the fd#1 to write stats later on SIGTERM */ if (pfd[1] != 1) { dup2(pfd[1], 1); close(pfd[1]); } fork_on_reload = -1; return 1; } else { close(pfd[1]); cfd = pfd[0]; } } #ifndef NO_TIMES #ifndef HZ if (!HZ) HZ = sysconf(_SC_CLK_TCK); #endif etm = times(&tms); utm = tms.tms_utime; #endif /* NO_TIMES */ r = 1; while(ds) { if (!loaddataset(ds)) r = 0; ds = nextdataset2reload(ds); } for (zone = zonelist; zone; zone = zone->z_next) { time_t stamp = 0; time_t expires = 0; const struct dssoa *dssoa = NULL; const struct dsns *dsns = NULL; unsigned nsttl = 0; struct dslist *dsl; for(dsl = zone->z_dsl; dsl; dsl = dsl->dsl_next) { const struct dataset *ds = dsl->dsl_ds; if (!ds->ds_stamp) { stamp = 0; break; } if (stamp < ds->ds_stamp) stamp = ds->ds_stamp; if (ds->ds_expires && (!expires || expires > ds->ds_expires)) expires = ds->ds_expires; if (!dssoa) dssoa = ds->ds_dssoa; if (!dsns) dsns = ds->ds_dsns, nsttl = ds->ds_nsttl; } zone->z_expires = expires; zone->z_stamp = stamp; if (!stamp) { zlog(LOG_WARNING, zone, "not all datasets are loaded, zone will not be serviced"); r = 0; } else if (!update_zone_soa(zone, dssoa) || !update_zone_ns(zone, dsns, nsttl, zonelist)) zlog(LOG_WARNING, zone, "NS or SOA RRs are too long, will be ignored"); } if (call_hook(reload, (zonelist)) != 0) r = 0; ip = ssprintf(ibuf, sizeof(ibuf), "zones reloaded"); #ifndef NO_TIMES etm = times(&tms) - etm; utm = tms.tms_utime - utm; # define sec(tm) (unsigned long)(tm/HZ), (unsigned long)((tm*100/HZ)%100) ip += ssprintf(ibuf + ip, sizeof(ibuf) - ip, ", time %lu.%lue/%lu.%luu sec", sec(etm), sec(utm)); # undef sec #endif /* NO_TIMES */ #ifndef NO_MEMINFO { struct mallinfo mi = mallinfo(); # define kb(x) ((mi.x + 512)>>10) ip += ssprintf(ibuf + ip, sizeof(ibuf) - ip, ", mem arena=%d free=%d mmap=%d Kb", kb(arena), kb(fordblks), kb(hblkhd)); # undef kb } #endif /* NO_MEMINFO */ dslog(LOG_INFO, 0, ibuf); check_expires(); /* ok, (something) loaded. */ if (do_fork) { /* here we should notify query-answering child (send SIGTERM to it), * and wait for it to complete. * Unfortunately at least on linux, the SIGTERM sometimes gets ignored * by the child process, so we're trying several times here, in a loop. */ int s, n; fd_set fds; struct timeval tv; for(n = 1; ++n;) { if (kill(cpid, SIGTERM) != 0) dslog(LOG_WARNING, 0, "kill(qchild): %s", strerror(errno)); FD_ZERO(&fds); FD_SET(cfd, &fds); tv.tv_sec = 0; tv.tv_usec = 500000; s = select(cfd+1, &fds, NULL, NULL, &tv); if (s > 0) break; dslog(LOG_WARNING, 0, "waiting for qchild process: %s, retrying", s ? strerror(errno) : "timeout"); } ipc_read_stats(cfd); close(cfd); wait(&s); } return r; }
static void init(int argc, char **argv) { int c; char *p; const char *user = NULL; const char *rootdir = NULL, *workdir = NULL, *pidfile = NULL; const char *bindaddr[MAXSOCK]; int nba = 0; uid_t uid = 0; gid_t gid = 0; int nodaemon = 0, quickstart = 0, dump = 0, nover = 0, forkon = 0; int family = AF_UNSPEC; int cfd = -1; const struct zone *z; #ifndef NO_DSO char *ext = NULL, *extarg = NULL; int (*extinit)(const char *arg, struct zone *zonelist) = NULL; #endif if ((progname = strrchr(argv[0], '/')) != NULL) argv[0] = ++progname; else progname = argv[0]; if (argc <= 1) usage(1); const char *const getopt_fmt = "u:r:b:w:t:c:p:nel:Lqs:h46dvaAfCx:X:zg"; while((c = getopt(argc, argv, getopt_fmt)) != EOF) switch(c) { case 'u': user = optarg; break; case 'r': rootdir = optarg; break; case 'b': if (nba >= MAXSOCK) error(0, "too many addresses to listen on (%d max)", MAXSOCK); bindaddr[nba++] = optarg; break; #ifndef NO_IPv6 case '4': family = AF_INET; break; case '6': family = AF_INET6; break; #else case '4': break; case '6': error(0, "IPv6 support isn't compiled in"); #endif case 'w': workdir = optarg; break; case 'p': pidfile = optarg; break; case 't': p = optarg; if (*p == ':') ++p; else { if (!(p = parse_time(p, &def_ttl)) || !def_ttl || (*p && *p++ != ':')) error(0, "invalid ttl (-t) value `%.50s'", optarg); } if (*p == ':') ++p; else if (*p) { if (!(p = parse_time(p, &min_ttl)) || (*p && *p++ != ':')) error(0, "invalid minttl (-t) value `%.50s'", optarg); } if (*p == ':') ++p; else if (*p) { if (!(p = parse_time(p, &max_ttl)) || (*p && *p++ != ':')) error(0, "invalid maxttl (-t) value `%.50s'", optarg); } if (*p) error(0, "invalid value for -t (ttl) option: `%.50s'", optarg); if ((min_ttl && max_ttl && min_ttl > max_ttl) || (min_ttl && def_ttl < min_ttl) || (max_ttl && def_ttl > max_ttl)) error(0, "inconsistent def:min:max ttl: %u:%u:%u", def_ttl, min_ttl, max_ttl); break; case 'c': if (!(p = parse_time(optarg, &recheck)) || *p) error(0, "invalid check interval (-c) value `%.50s'", optarg); break; case 'n': nodaemon = 1; break; case 'e': accept_in_cidr = 1; break; case 'l': logfile = optarg; if (*logfile != '+') flushlog = 0; else ++logfile, flushlog = 1; if (!*logfile) logfile = NULL, flushlog = 0; else if (logfile[0] == '-' && logfile[1] == '\0') logfile = NULL, flog = stdout; break; case 'L': verbose = 1; break; break; case 's': #ifdef NO_STATS fprintf(stderr, "%s: warning: no statistics counters support is compiled in\n", progname); #else statsfile = optarg; if (*statsfile != '+') stats_relative = 0; else ++statsfile, stats_relative = 1; if (!*statsfile) statsfile = NULL; #endif break; case 'q': quickstart = 1; break; case 'd': #ifdef NO_MASTER_DUMP error(0, "master-format dump option (-d) isn't compiled in"); #endif dump = 1; break; case 'v': show_version = nover++ ? NULL : "rbldnsd"; break; case 'a': lazy = 1; break; case 'A': lazy = 0; break; case 'f': forkon = 1; break; case 'C': nouncompress = 1; break; #ifndef NO_DSO case 'x': ext = optarg; break; case 'X': extarg = optarg; break; #else case 'x': case 'X': error(0, "extension support is not compiled in"); #endif #ifndef NO_ANONYMIZE case 'z': anonymize = 1; break; #else case 'z': error(0, "anonymization support is not compiled in"); #endif #ifndef NO_GEOIP case 'g': geoip = 1; break; case 'G': geoip = 1; geoip_path = optarg; break; #else case 'g': case 'G': error(0, "geoip support is not compiled in"); #endif case 'h': usage(0); default: error(0, "type `%.50s -h' for help", progname); } if (!(argc -= optind)) error(0, "no zone(s) to service specified (-h for help)"); argv += optind; #ifndef NO_MASTER_DUMP if (dump) { time_t now; logto = LOGTO_STDERR; for(c = 0; c < argc; ++c) zonelist = addzone(zonelist, argv[c]); init_zones_caches(zonelist); if (rootdir && (chdir(rootdir) < 0 || chroot(rootdir) < 0)) error(errno, "unable to chroot to %.50s", rootdir); if (workdir && chdir(workdir) < 0) error(errno, "unable to chdir to %.50s", workdir); if (!do_reload(0)) error(0, "zone loading errors, aborting"); now = time(NULL); printf("; zone dump made %s", ctime(&now)); printf("; rbldnsd version %s\n", version); for (z = zonelist; z; z = z->z_next) dumpzone(z, stdout); fflush(stdout); exit(ferror(stdout) ? 1 : 0); } #endif if (!nba) error(0, "no address to listen on (-b option) specified"); tzset(); if (nodaemon) logto = LOGTO_STDOUT|LOGTO_STDERR; else { /* fork early so that logging will be from right pid */ int pfd[2]; if (pipe(pfd) < 0) error(errno, "pipe() failed"); c = fork(); if (c < 0) error(errno, "fork() failed"); if (c > 0) { close(pfd[1]); if (read(pfd[0], &c, 1) < 1) exit(1); else exit(0); } cfd = pfd[1]; close(pfd[0]); openlog(progname, LOG_PID|LOG_NDELAY, LOG_DAEMON); logto = LOGTO_STDERR|LOGTO_SYSLOG; if (!quickstart && !flog) logto |= LOGTO_STDOUT; } initsockets(bindaddr, nba, family); #ifndef NO_DSO if (ext) { void *handle = dlopen(ext, RTLD_NOW); if (!handle) error(0, "unable to load extension `%s': %s", ext, dlerror()); extinit = dlsym(handle, "rbldnsd_extension_init"); if (!extinit) error(0, "unable to find extension init routine in `%s'", ext); } #endif if (!user && !(uid = getuid())) user = "******"; if (!user) p = NULL; else { if ((p = strchr(user, ':')) != NULL) *p++ = '\0'; if ((c = satoi(user)) >= 0) uid = c, gid = c; else { struct passwd *pw = getpwnam(user); if (!pw) error(0, "unknown user `%s'", user); uid = pw->pw_uid; gid = pw->pw_gid; endpwent(); } } if (!uid) error(0, "daemon should not run as root, specify -u option"); if (p) { if ((c = satoi(p)) >= 0) gid = c; else { struct group *gr = getgrnam(p); if (!gr) error(0, "unknown group `%s'", p); gid = gr->gr_gid; endgrent(); } p[-1] = ':'; } if (pidfile) { int fdpid; char buf[40]; c = sprintf(buf, "%ld\n", (long)getpid()); fdpid = open(pidfile, O_CREAT|O_WRONLY|O_TRUNC, 0644); if (fdpid < 0 || write(fdpid, buf, c) < c) error(errno, "unable to write pidfile"); close(fdpid); } if (rootdir && (chdir(rootdir) < 0 || chroot(rootdir) < 0)) error(errno, "unable to chroot to %.50s", rootdir); if (workdir && chdir(workdir) < 0) error(errno, "unable to chdir to %.50s", workdir); if (user) if (setgroups(1, &gid) < 0 || setgid(gid) < 0 || setuid(uid) < 0) error(errno, "unable to setuid(%d:%d)", (int)uid, (int)gid); for(c = 0; c < argc; ++c) zonelist = addzone(zonelist, argv[c]); init_zones_caches(zonelist); #ifndef NO_DSO if (extinit && extinit(extarg, zonelist) != 0) error(0, "unable to iniitialize extension `%s'", ext); #endif if (!quickstart && !do_reload(0)) error(0, "zone loading errors, aborting"); /* count number of zones */ for(c = 0, z = zonelist; z; z = z->z_next) ++c; numzones = c; #if STATS_IPC_IOVEC stats_iov = (struct iovec *)emalloc(numzones * sizeof(struct iovec)); for(c = 0, z = zonelist; z; z = z->z_next, ++c) { stats_iov[c].iov_base = (char*)&z->z_stats; stats_iov[c].iov_len = sizeof(z->z_stats); } #endif dslog(LOG_INFO, 0, "rbldnsd version %s started (%d socket(s), %d zone(s))", version, numsock, numzones); initialized = 1; if (cfd >= 0) { write(cfd, "", 1); close(cfd); close(0); close(2); if (!flog) close(1); setsid(); logto = LOGTO_SYSLOG; } if (quickstart) do_reload(0); /* only set "main" fork_on_reload after first reload */ fork_on_reload = forkon; }
void oom(void) { if (initialized) dslog(LOG_ERR, 0, "out of memory loading dataset"); else error(0, "out of memory"); }