예제 #1
0
파일: rbldnsd.c 프로젝트: 0xxon/rbldnsd
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);
}
예제 #2
0
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);
}
예제 #3
0
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);
}
예제 #4
0
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);
}
예제 #5
0
파일: rbldnsd.c 프로젝트: 0xxon/rbldnsd
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;
  }
}
예제 #6
0
파일: rbldnsd.c 프로젝트: 0xxon/rbldnsd
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;
}
예제 #7
0
파일: rbldnsd.c 프로젝트: 0xxon/rbldnsd
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);
  }
}
예제 #8
0
파일: rbldnsd.c 프로젝트: 0xxon/rbldnsd
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;
}
예제 #9
0
파일: rbldnsd.c 프로젝트: 0xxon/rbldnsd
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;
}
예제 #10
0
파일: rbldnsd.c 프로젝트: 0xxon/rbldnsd
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;
}
예제 #11
0
파일: rbldnsd.c 프로젝트: 0xxon/rbldnsd
void oom(void) {
  if (initialized)
    dslog(LOG_ERR, 0, "out of memory loading dataset");
  else
    error(0, "out of memory");
}