コード例 #1
0
static void create_main_server(void) {
  pool *main_pool;

  main_pool = make_sub_pool(permanent_pool);
  pr_pool_tag(main_pool, "testsuite#main_server pool");

  server_list = xaset_create(main_pool, NULL);

  main_server = (server_rec *) pcalloc(main_pool, sizeof(server_rec));
  xaset_insert(server_list, (xasetmember_t *) main_server);

  main_server->pool = main_pool;
  main_server->conf = xaset_create(main_pool, NULL);
  main_server->set = server_list;
  main_server->sid = 1;
  main_server->notes = pr_table_nalloc(main_pool, 0, 8);

  /* TCP KeepAlive is enabled by default, with the system defaults. */
  main_server->tcp_keepalive = palloc(main_server->pool,
    sizeof(struct tcp_keepalive));
  main_server->tcp_keepalive->keepalive_enabled = TRUE;
  main_server->tcp_keepalive->keepalive_idle = -1;
  main_server->tcp_keepalive->keepalive_count = -1;
  main_server->tcp_keepalive->keepalive_intvl = -1;

  main_server->ServerName = "Test Server";
  main_server->ServerPort = 21;
}
コード例 #2
0
ファイル: child.c プロジェクト: OPSF/uClinux
int child_add(pid_t pid, int fd) {
  pool *p;
  pr_child_t *ch;

  /* If no child-tracking list has been allocated, create one. */
  if (!child_pool) {
    child_pool = make_sub_pool(permanent_pool);
    pr_pool_tag(child_pool, "Child Pool");
  }

  if (!child_list)
    child_list = xaset_create(make_sub_pool(child_pool), NULL);

  p = make_sub_pool(child_pool);
  pr_pool_tag(p, "child session pool");

  ch = pcalloc(p, sizeof(pr_child_t));
  ch->ch_pool = p;  
  ch->ch_pid = pid;
  time(&ch->ch_when);
  ch->ch_pipefd = fd;
  ch->ch_dead = FALSE;

  xaset_insert(child_list, (xasetmember_t *) ch);
  child_listlen++;

  return 0;
}
コード例 #3
0
ファイル: support.c プロジェクト: netdna/proftpd
void schedule(void (*f)(void*,void*,void*,void*),int nloops, void *a1,
    void *a2, void *a3, void *a4) {
  pool *p, *sub_pool;
  sched_t *s;

  if (scheds == NULL) {
    p = make_sub_pool(permanent_pool);
    pr_pool_tag(p, "Schedules Pool");
    scheds = xaset_create(p, NULL);

  } else {
    p = scheds->pool;
  }

  sub_pool = make_sub_pool(p);
  pr_pool_tag(sub_pool, "schedule pool");

  s = pcalloc(sub_pool, sizeof(sched_t));
  s->pool = sub_pool;
  s->f = f;
  s->a1 = a1;
  s->a2 = a2;
  s->a3 = a3;
  s->a4 = a4;
  s->loops = nloops;
  xaset_insert(scheds, (xasetmember_t *) s);
}
コード例 #4
0
ファイル: sets.c プロジェクト: OPSF/uClinux
xaset_t *xaset_union(pool *work_pool, xaset_t *set1, xaset_t *set2,
    size_t msize, XASET_MCOPY copyf) {
  xaset_t *newset;
  xasetmember_t *setp,*n;
  xaset_t *setv[3];
  xaset_t **setcp;

  setv[0] = set1; setv[1] = set2; setv[2] = NULL;

  if (!set1 || !set2 || (!msize && !copyf)) {
    errno = EINVAL;
    return NULL;
  }

  work_pool = (work_pool ? work_pool :
    (set1->pool ? set1->pool : set2->pool));

  if (!(newset = xaset_create(work_pool, set1->xas_compare)))
    return NULL;

  for (setcp = setv; *setcp; setcp++)
    for (setp = (*setcp)->xas_list; setp; setp=setp->next) {
      n = copyf ? copyf(setp) : (xasetmember_t*) palloc(work_pool, msize);
      if (!n)
        return NULL;			/* Could cleanup here */

      if (!copyf)
        memcpy(n, setp, msize);

      if (xaset_insert_sort(newset, n, 0) == -1)
        return NULL;
    }

  return newset;
}
コード例 #5
0
ファイル: support.c プロジェクト: predever/proftpd
void schedule(void (*cb)(void *, void *, void *, void *), int nloops,
    void *arg1, void *arg2, void *arg3, void *arg4) {
  pool *p, *sub_pool;
  sched_t *s;

  if (cb == NULL ||
      nloops < 0) {
    return;
  }

  if (scheds == NULL) {
    p = make_sub_pool(permanent_pool);
    pr_pool_tag(p, "Schedules Pool");
    scheds = xaset_create(p, NULL);

  } else {
    p = scheds->pool;
  }

  sub_pool = make_sub_pool(p);
  pr_pool_tag(sub_pool, "schedule pool");

  s = pcalloc(sub_pool, sizeof(sched_t));
  s->pool = sub_pool;
  s->cb = cb;
  s->arg1 = arg1;
  s->arg2 = arg2;
  s->arg3 = arg3;
  s->arg4 = arg4;
  s->nloops = nloops;
  xaset_insert(scheds, (xasetmember_t *) s);
}
コード例 #6
0
ファイル: sets.c プロジェクト: OPSF/uClinux
xaset_t *xaset_subtract(pool *work_pool, xaset_t *set1, xaset_t *set2,
    size_t msize, XASET_MCOPY copyf) {
  xaset_t *newset;
  xasetmember_t *set1p,*set2p,*n,**pos;
  int c;

  if (!set1 || !set2 || (!msize && !copyf)) {
    errno = EINVAL;
    return NULL;
  }

  work_pool = (work_pool ? work_pool :
    (set1->pool ? set1->pool : set2->pool));

  if (!(newset = xaset_create(work_pool, set1->xas_compare)))
    return NULL;

  pos = &newset->xas_list;

  /* NOTE: xaset_insert_sort is not used here for performance
     reasons. */

  for (set1p = set1->xas_list, set2p = set2->xas_list; set1p;
      set1p = set1p->next) {
    if (!set2p || (c = set1->xas_compare(set1p, set2p)) < 0) {
      /* Copy if set2 is exhausted or set1p's "value" is less than
         set2p's. */
      n = copyf ? copyf(set1p) : (xasetmember_t *) palloc(work_pool, msize);
      if (!n)
        return NULL;			/* Could cleanup here */

      if (!copyf)
        memcpy(n, set1p, msize);

      /* Create links */
      n->prev = *pos;
      n->next = NULL;
      if (*pos)
        pos = &(*pos)->next;
      *pos = n;

    } else if (c >= 0) {

      /* Traverse set2 until we reach a point where set2 is
         exhausted or set2p is "greater" than set1p */
      while ((set2p = set2p->next) != NULL &&
            set1->xas_compare(set1p, set2p) > 0) ;

      /* In case there are dupes in set1, examine the next (if any)
         value(s) and skip if necessary */
      while (set1p->next && set1->xas_compare(set1p, set1p->next) == 0)
        set1p = set1p->next;
    }
  }

  return newset;
}
コード例 #7
0
ファイル: timers.c プロジェクト: netdna/proftpd
int pr_timer_reset(int timerno, module *mod) {
  struct timer *t = NULL;

  if (!timers) {
    errno = EPERM;
    return -1;
  }

  if (_indispatch) {
    errno = EINTR;
    return -1;
  }

  pr_alarms_block();

  if (!recycled)
    recycled = xaset_create(timer_pool, NULL);

  for (t = (struct timer *) timers->xas_list; t; t = t->next) {
    if (t->timerno == timerno &&
        (t->mod == mod || mod == ANY_MODULE)) {
      t->count = t->interval;
      xaset_remove(timers, (xasetmember_t *) t);
      xaset_insert(recycled, (xasetmember_t *) t);
      nalarms++;

      /* The handle_alarm() function also readjusts the timers lists
       * as part of its processing, so it needs to be called when a timer
       * is reset.
       */
      handle_alarm();
      break;
    }
  }

  pr_alarms_unblock();

  if (t != NULL) {
    pr_trace_msg("timer", 7, "reset timer ID %d ('%s', for module '%s')",
      t->timerno, t->desc, t->mod ? t->mod->name : "[none]");
    return t->timerno;
  }

  return 0;
}
コード例 #8
0
ファイル: sets.c プロジェクト: proftpd/proftpd
/* Perform an exact copy of the entire set, returning the new set.  msize
 * specifies the size of each member.  If copyfunc is non-NULL, it is called
 * instead to copy each member.  Returns NULL if out of memory condition
 * occurs.
 */
xaset_t *xaset_copy(pool *p, xaset_t *set, size_t msize, XASET_MCOPY copyfunc) {
  xaset_t *new_set;
  xasetmember_t *n, *m, **pos;

  if (set == NULL) {
    errno = EINVAL;
    return NULL;
  }

  if (!copyfunc && !msize) {
    errno = EINVAL;
    return NULL;
  }

  p = (p ? p : set->pool);

  new_set = xaset_create(p, set->xas_compare);
  if (new_set == NULL)
    return NULL;

  pos = &new_set->xas_list;

  /* NOTE: xaset_insert_sort is not used here for performance reasons. */

  for (m = set->xas_list; m; m = m->next) {
    n = copyfunc ? copyfunc(m) : (xasetmember_t *) palloc(p, msize);
    if (!n)
      return NULL;			/* Could clean up here */

    if (!copyfunc)
      memcpy(n, m, msize);

    /* Create links */
    n->prev = *pos;
    n->next = NULL;
    if (*pos)
      pos = &(*pos)->next;
    *pos = n;
  }

  return new_set;
}
コード例 #9
0
ファイル: sets.c プロジェクト: OPSF/uClinux
xaset_t *xaset_copy(pool *work_pool, xaset_t *set, size_t msize,
    XASET_MCOPY copyf) {
  xaset_t *newset;
  xasetmember_t *n,*p,**pos;

  if (!copyf && !msize) {
    errno = EINVAL;
    return NULL;
  }

  work_pool = (work_pool ? work_pool : set->pool);

  if (!(newset = xaset_create(work_pool, set->xas_compare)))
    return NULL;

  pos = &newset->xas_list;

  /* NOTE: xaset_insert_sort is not used here for performance
     reasons. */

  for (p = set->xas_list; p; p=p->next) {
    n = copyf ? copyf(p) : (xasetmember_t *) palloc(work_pool, msize);
    if (!n)
      return NULL;			/* Could clean up here */

    if (!copyf)
      memcpy(n, p, msize);

    /* Create links */
    n->prev = *pos;
    n->next = NULL;
    if (*pos)
      pos = &(*pos)->next;
    *pos = n;
  }

  return newset;
}
コード例 #10
0
ファイル: timers.c プロジェクト: netdna/proftpd
/* This function does the work of iterating through the list of registered
 * timers, checking to see if their callbacks should be invoked and whether
 * they should be removed from the registration list. Its return value is
 * the amount of time remaining on the first timer in the list.
 */
static int process_timers(int elapsed) {
  struct timer *t = NULL, *next = NULL;

  if (!recycled)
    recycled = xaset_create(timer_pool, NULL);

  if (!elapsed &&
      !recycled->xas_list) {

    if (!timers)
      return 0;

    return (timers->xas_list ? ((struct timer *) timers->xas_list)->count : 0);
  }

  /* Critical code, no interruptions please */
  if (_indispatch)
    return 0;

  pr_alarms_block();
  _indispatch++;

  if (elapsed) {
    for (t = (struct timer *) timers->xas_list; t; t = next) {
      /* If this timer has already been handled, skip */
      next = t->next;

      if (t->remove) {
        /* Move the timer onto the free_timers chain, for later reuse. */
        xaset_remove(timers, (xasetmember_t *) t);
        xaset_insert(free_timers, (xasetmember_t *) t);

      } else if ((t->count -= elapsed) <= 0) {
        /* This timer's interval has elapsed, so trigger its callback. */

        pr_trace_msg("timer", 4,
          "%ld %s for timer ID %d ('%s', for module '%s') elapsed, invoking "
          "callback (%p)", t->interval,
          t->interval != 1 ? "seconds" : "second", t->timerno,
          t->desc ? t->desc : "<unknown>",
          t->mod ? t->mod->name : "<none>", t->callback);

        if (t->callback(t->interval, t->timerno, t->interval - t->count,
            t->mod) == 0) {

          /* A return value of zero means this timer is done, and can be
           * removed.
           */
          xaset_remove(timers, (xasetmember_t *) t);
          xaset_insert(free_timers, (xasetmember_t *) t);

        } else {
          /* A non-zero return value from a timer callback signals that
           * the timer should be reused/restarted.
           */
          pr_trace_msg("timer", 6, "restarting timer ID %d ('%s'), as per "
            "callback", t->timerno, t->desc ? t->desc : "<unknown>");

          xaset_remove(timers, (xasetmember_t *) t);
          t->count = t->interval;
          xaset_insert(recycled, (xasetmember_t *) t);
        }
      }
    }
  }

  /* Put the recycled timers back into the main timer list. */
  while ((t = (struct timer *) recycled->xas_list) != NULL) {
    xaset_remove(recycled, (xasetmember_t *) t);
    xaset_insert_sort(timers, (xasetmember_t *) t, TRUE);
  }

  _indispatch--;
  pr_alarms_unblock();

  /* If no active timers remain in the list, there is no reason to set the
   * SIGALRM handle.
   */
  return (timers->xas_list ? ((struct timer *) timers->xas_list)->count : 0);
}
コード例 #11
0
ファイル: timers.c プロジェクト: netdna/proftpd
int pr_timer_add(int seconds, int timerno, module *mod, callback_t cb,
    const char *desc) {
  struct timer *t = NULL;

  if (seconds <= 0 ||
      cb == NULL ||
      desc == NULL) {
    errno = EINVAL;
    return -1;
  }

  if (!timers)
    timers = xaset_create(timer_pool, (XASET_COMPARE) timer_cmp);

  /* Check to see that, if specified, the timerno is not already in use. */
  if (timerno >= 0) {
    for (t = (struct timer *) timers->xas_list; t; t = t->next) {
      if (t->timerno == timerno) {
        errno = EPERM;
        return -1;
      }
    }
  }

  if (!free_timers)
    free_timers = xaset_create(timer_pool, NULL);

  /* Try to use an old timer first */
  pr_alarms_block();
  t = (struct timer *) free_timers->xas_list;
  if (t != NULL) {
    xaset_remove(free_timers, (xasetmember_t *) t);

  } else {

    if (timer_pool == NULL) {
      timer_pool = make_sub_pool(permanent_pool);
      pr_pool_tag(timer_pool, "Timer Pool");
    }

    /* Must allocate a new one */
    t = palloc(timer_pool, sizeof(struct timer));
  }

  if (timerno < 0) {
    /* Dynamic timer */
    if (dynamic_timerno < PR_TIMER_DYNAMIC_TIMERNO) {
      dynamic_timerno = PR_TIMER_DYNAMIC_TIMERNO;
    }

    timerno = dynamic_timerno++;
  }

  t->timerno = timerno;
  t->count = t->interval = seconds;
  t->callback = cb;
  t->mod = mod;
  t->remove = 0;
  t->desc = desc;

  /* If called while _indispatch, add to the recycled list to prevent
   * list corruption
   */

  if (_indispatch) {
    if (!recycled)
      recycled = xaset_create(timer_pool, NULL);
    xaset_insert(recycled, (xasetmember_t *) t);

  } else {
    xaset_insert_sort(timers, (xasetmember_t *) t, TRUE);
    nalarms++;
    set_sig_alarm();

    /* The handle_alarm() function also readjusts the timers lists
     * as part of its processing, so it needs to be called when a timer
     * is added.
     */
    handle_alarm();
  }

  pr_alarms_unblock();

  pr_trace_msg("timer", 7, "added timer ID %d ('%s', for module '%s'), "
    "triggering in %ld %s", t->timerno, t->desc,
    t->mod ? t->mod->name : "[none]", t->interval,
    t->interval != 1 ? "seconds" : "second");
  return timerno;
}
コード例 #12
0
ファイル: stash.c プロジェクト: proftpd/proftpd
int pr_stash_add_symbol(pr_stash_type_t sym_type, void *data) {
  struct stash *sym = NULL;
  unsigned int hash;
  int idx = 0;
  xaset_t **symbol_table;
  size_t sym_namelen = 0;

  if (data == NULL) {
    errno = EINVAL;
    return -1;
  }

  switch (sym_type) {
    case PR_SYM_CONF:
      sym = sym_alloc();
      sym->sym_type = PR_SYM_CONF;
      sym->sym_name = ((conftable *) data)->directive;
      sym->sym_module = ((conftable *) data)->m;
      sym->ptr.sym_conf = data;
      symbol_table = conf_symbol_table;
      break;

    case PR_SYM_CMD:
      sym = sym_alloc();
      sym->sym_type = PR_SYM_CMD;
      sym->sym_name = ((cmdtable *) data)->command;
      sym->sym_module = ((cmdtable *) data)->m;
      sym->ptr.sym_cmd = data;
      symbol_table = cmd_symbol_table;
      break;

    case PR_SYM_AUTH:
      sym = sym_alloc();
      sym->sym_type = PR_SYM_AUTH;
      sym->sym_name = ((authtable *) data)->name;
      sym->sym_module = ((authtable *) data)->m;
      sym->ptr.sym_auth = data;
      symbol_table = auth_symbol_table;
      break;

    case PR_SYM_HOOK:
      sym = sym_alloc();
      sym->sym_type = PR_SYM_HOOK;
      sym->sym_name = ((cmdtable *) data)->command;
      sym->sym_module = ((cmdtable *) data)->m;
      sym->ptr.sym_hook = data;
      symbol_table = hook_symbol_table;
      break;

    default:
      errno = EINVAL;
      return -1;
  }

  /* XXX Should we check for null sym->sym_module as well? */
  if (sym->sym_name == NULL) {
    destroy_pool(sym->sym_pool);
    errno = EPERM;
    return -1;
  }

  sym_namelen = strlen(sym->sym_name);
  if (sym_namelen == 0) {
    destroy_pool(sym->sym_pool);
    errno = EPERM;
    return -1;
  }

  /* Don't forget to include one for the terminating NUL. */
  sym->sym_namelen = sym_namelen + 1;

  hash = sym_type_hash(sym_type, sym->sym_name, sym->sym_namelen);
  idx = hash % PR_TUNABLE_HASH_TABLE_SIZE;
  sym->sym_hash = hash;

  if (!symbol_table[idx]) {
    symbol_table[idx] = xaset_create(symbol_pool, (XASET_COMPARE) sym_cmp);
  }

  xaset_insert_sort(symbol_table[idx], (xasetmember_t *) sym, TRUE);
  return 0;
}
コード例 #13
0
ファイル: parser.c プロジェクト: proftpd/proftpd
config_rec *pr_parser_config_ctxt_open(const char *name) {
  config_rec *c = NULL, *parent = *parser_curr_config;
  pool *c_pool = NULL, *parent_pool = NULL;
  xaset_t **set = NULL;

  if (name == NULL) {
    errno = EINVAL;
    return NULL;
  }

  if (parent) {
    parent_pool = parent->pool;
    set = &parent->subset;

  } else {
    parent_pool = (*parser_curr_server)->pool;
    set = &(*parser_curr_server)->conf;
  }

  /* Allocate a sub-pool for this config_rec.
   *
   * Note: special exception for <Global> configs: the parent pool is
   * 'global_config_pool' (a pool just for that context), not the pool of the
   * parent server.  This keeps <Global> config recs from being freed
   * prematurely, and helps to avoid memory leaks.
   */
  if (strncasecmp(name, "<Global>", 9) == 0) {
    if (global_config_pool == NULL) {
      global_config_pool = make_sub_pool(permanent_pool);
      pr_pool_tag(global_config_pool, "<Global> Pool");
    }

    parent_pool = global_config_pool;
  }

  c_pool = make_sub_pool(parent_pool);
  pr_pool_tag(c_pool, "sub-config pool");

  c = (config_rec *) pcalloc(c_pool, sizeof(config_rec));

  if (!*set) {
    pool *set_pool = make_sub_pool(parent_pool);
    *set = xaset_create(set_pool, NULL);
    (*set)->pool = set_pool;
  }

  xaset_insert(*set, (xasetmember_t *) c);

  c->pool = c_pool;
  c->set = *set;
  c->parent = parent;
  c->name = pstrdup(c->pool, name);

  if (parent) {
    if (parent->config_type == CONF_DYNDIR) {
      c->flags |= CF_DYNAMIC;
    }
  }

  (void) pr_parser_config_ctxt_push(c);
  return c;
}
コード例 #14
0
static int counter_sess_init(void) {
  config_rec *c;

  c = find_config(main_server->conf, CONF_PARAM, "CounterEngine", FALSE);
  if (c != NULL) {
    counter_engine = *((int *) c->argv[0]);
  }

  if (counter_engine == FALSE) {
    return 0;
  }

  c = find_config(main_server->conf, CONF_PARAM, "CounterLog", FALSE);
  if (c != NULL) {
    const char *path = c->argv[0];

    if (strcasecmp(path, "none") != 0) {
      int res, xerrno;

      PRIVS_ROOT
      res = pr_log_openfile(path, &counter_logfd, 0660);
      xerrno = errno;
      PRIVS_RELINQUISH;

      if (res < 0) {
        pr_log_debug(DEBUG2, MOD_COUNTER_VERSION
          ": error opening CounterLog '%s': %s", path, strerror(xerrno));
        counter_logfd = -1;
      }
    }
  }

  /* Find all CounterFile directives for this vhost, and make sure they
   * have open handles.  We need to do this here, and not in a POST_CMD
   * PASS handler because of the need to open handles that may be outside
   * of a chroot.
   */
  c = find_config(main_server->conf, CONF_PARAM, "CounterFile", TRUE);
  while (c != NULL) {
    int xerrno = 0;
    const char *area = NULL, *path;
    pr_fh_t *fh;
    struct counter_fh *cfh;

    pr_signals_handle();

    path = c->argv[0];

    if (c->parent != NULL) {
      if (c->parent->config_type == CONF_ANON ||
          c->parent->config_type == CONF_DIR) {
        area = c->parent->name;

      } else {
        (void) pr_log_writefile(counter_logfd, MOD_COUNTER_VERSION,
          "unhandled configuration parent type (%d) for CounterFile, skipping",
          c->parent->config_type);
        c = find_config_next(c, c->next, CONF_PARAM, "CounterFile", TRUE);
        continue;
      }

    } else {
      /* Toplevel CounterFile directive, in "server config" or <VirtualHost>
       * sections.
       */
      area = "/";
    }

    PRIVS_ROOT
    fh = pr_fsio_open(path, O_RDWR|O_CREAT);
    xerrno = errno;
    PRIVS_RELINQUISH

    if (fh == NULL) {
      pr_log_debug(DEBUG1, MOD_COUNTER_VERSION
        ": error opening CounterFile '%s': %s", path, strerror(xerrno));
      counter_engine = FALSE;

      if (counter_fhs != NULL) {
        for (cfh = (struct counter_fh *) counter_fhs->xas_list; cfh;
            cfh = cfh->next) {
          (void) pr_fsio_close(cfh->fh);
        }
      }

      return 0;
    }

    (void) pr_log_writefile(counter_logfd, MOD_COUNTER_VERSION,
      "opened CounterFile '%s'", path);

    if (counter_fhs == NULL) {
      counter_fhs = xaset_create(counter_pool, NULL);
    }

    cfh = pcalloc(counter_pool, sizeof(struct counter_fh));

    /* Ignore any trailing slash. */
    cfh->arealen = strlen(area);
    if (cfh->arealen > 1 &&
        area[cfh->arealen-1] == '/') {
      cfh->arealen--;
    }

    cfh->area = pstrndup(counter_pool, area, cfh->arealen);

    /* Mark any areas that use glob(3) characters. */
    if (strpbrk(cfh->area, "[*?") != NULL) {
      cfh->isglob = TRUE;
    }

    cfh->fh = fh;

    xaset_insert(counter_fhs, (xasetmember_t *) cfh);

    c = find_config_next(c, c->next, CONF_PARAM, "CounterFile", TRUE);
  }

  if (counter_fhs == NULL) {
    (void) pr_log_writefile(counter_logfd, MOD_COUNTER_VERSION,
      "no CounterFiles configured, disabling module");
    counter_engine = FALSE;
    return 0;
  }

  pr_event_register(&counter_module, "core.exit", counter_exit_ev, NULL);

  /* If mod_vroot is present, we need to do a little more magic to counter
   * the mod_vroot magic.
   */
  if (pr_module_exists("mod_vroot.c") == TRUE) {
    pr_event_register(&counter_module, "core.chroot", counter_chroot_ev, NULL);
  }

  return 0;
}
コード例 #15
0
ファイル: bindings.c プロジェクト: dbarba74/proftpd
conn_t *pr_ipbind_get_listening_conn(server_rec *server, pr_netaddr_t *addr,
    unsigned int port) {
  conn_t *l;
  pool *p;
  struct listener_rec *lr;

  if (listening_conn_list) {
    for (lr = (struct listener_rec *) listening_conn_list->xas_list; lr;
        lr = lr->next) {
      int use_elt = FALSE;

      pr_signals_handle();

      if (addr != NULL &&
          lr->addr != NULL) {
        const char *lr_ipstr = NULL;

        lr_ipstr = pr_netaddr_get_ipstr(lr->addr);

        /* Note: lr_ipstr should never be null.  If it is, it means that
         * the lr->addr object never had its IP address resolved/stashed,
         * and in attempting to do, getnameinfo(3) failed for some reason.
         *
         * The IP address on which it's listening, if not available via
         * lr->addr, should thus be available via lr->conn->local_addr.
         */

        if (lr_ipstr == NULL &&
            lr->conn != NULL) {
          lr_ipstr = pr_netaddr_get_ipstr(lr->conn->local_addr);
        }

        if (lr_ipstr != NULL) {
          if (strcmp(pr_netaddr_get_ipstr(addr), lr_ipstr) == 0 &&
              port == lr->port) {
            use_elt = TRUE;
          }
        }

      } else if (addr == NULL &&
                 port == lr->port) {
        use_elt = TRUE;
      }

      if (use_elt) { 
        lr->claimed = TRUE;
        return lr->conn;
      }
    }
  }

  if (listening_conn_pool == NULL) {
    listening_conn_pool = make_sub_pool(permanent_pool);
    pr_pool_tag(listening_conn_pool, "Listening Connection Pool");

    listening_conn_list = xaset_create(listening_conn_pool, NULL);
  }

  p = make_sub_pool(listening_conn_pool); 
  pr_pool_tag(p, "Listening conn subpool");

  l = pr_inet_create_conn(p, -1, addr, port, FALSE);
  if (l == NULL) {
    return NULL;
  }

  /* Inform any interested listeners that this socket was opened. */
  pr_inet_generate_socket_event("core.ctrl-listen", server, l->local_addr,
    l->listen_fd);

  lr = pcalloc(p, sizeof(struct listener_rec));
  lr->pool = p;
  lr->conn = l;
  lr->addr = pr_netaddr_dup(p, addr);
  if (lr->addr == NULL &&
      errno != EINVAL) {
    return NULL;
  }
  lr->port = port;
  lr->claimed = TRUE;

  xaset_insert(listening_conn_list, (xasetmember_t *) lr);
  return l;
}
コード例 #16
0
ファイル: configdb.c プロジェクト: proftpd/proftpd
END_TEST

START_TEST (config_merge_down_test) {
  xaset_t *set;
  config_rec *c, *src, *dst;
  const char *name;

  mark_point();
  pr_config_merge_down(NULL, FALSE);

  mark_point();
  set = xaset_create(p, NULL);
  pr_config_merge_down(set, FALSE);

  name = "foo";
  c = add_config_param_set(&set, name, 0);

  mark_point();
  pr_config_merge_down(set, FALSE);

  name = "bar";
  c = add_config_param_set(&set, name, 1, "baz");
  c->flags |= CF_MERGEDOWN;

  mark_point();
  pr_config_merge_down(set, FALSE);

  name = "BAZ";
  c = add_config_param_set(&set, name, 2, "quxx", "Quzz");
  c->flags |= CF_MERGEDOWN_MULTI;

  mark_point();
  pr_config_merge_down(set, FALSE);

  /* Add a config to the subsets, with the same name and same args. */
  name = "<Anonymous>";
  src = add_config_param_set(&set, name, 0);
  src->config_type = CONF_ANON;

  mark_point();
  pr_config_merge_down(set, FALSE);

  name = "<Directory>";
  dst = add_config_param_set(&set, name, 1, "/baz");
  dst->config_type = CONF_DIR;

  name = "foo";
  c = add_config_param_set(&(src->subset), name, 1, "alef");
  c->flags |= CF_MERGEDOWN;

  c = add_config_param_set(&(dst->subset), name, 1, "alef");
  c->flags |= CF_MERGEDOWN;

  mark_point();
  pr_config_merge_down(set, FALSE);

  /* Add a config to the subsets, with the same name and diff args. */
  name = "alef";
  c = add_config_param_set(&(src->subset), name, 1, "alef");
  c->flags |= CF_MERGEDOWN;

  c = add_config_param_set(&(dst->subset), name, 2, "bet", "vet");
  c->flags |= CF_MERGEDOWN;

  c = add_config_param_set(&(src->subset), "Bet", 3, "1", "2", "3");
  c->config_type = CONF_LIMIT;
  c->flags |= CF_MERGEDOWN;

  mark_point();
  pr_config_merge_down(set, FALSE);
}