Пример #1
0
struct ip4trie_node *
ip4trie_addnode(struct ip4trie *trie, ip4addr_t prefix, unsigned bits,
                struct mempool *mp) {
  struct ip4trie_node *node, **last;

  for(last = &trie->ip4t_root;
      (node = *last) != NULL;
      last = bitset(prefix, node->ip4t_bits) ?
         &node->ip4t_right : &node->ip4t_left) {

    if (node->ip4t_bits > bits ||
       !prefixmatch(node->ip4t_prefix, prefix, node->ip4t_bits)) {
      /* new node should be inserted before the given node */
      struct ip4trie_node *newnode;

      /* Find number of common (equal) bits */
      ip4addr_t diff = (prefix ^ node->ip4t_prefix) & ip4mask(bits);
      unsigned cbits;
      if (!diff) /* no difference, all bits are the same */
        cbits = bits;
      else {
        cbits = 0;
        while((diff & ip4mask(cbits+1)) == 0)
          ++cbits;
      }
      ++trie->ip4t_nnodes;
      if (!(newnode = createnode(prefix & ip4mask(cbits), cbits, mp)))
        return NULL;
      linknode(newnode, node);
      *last = newnode;
      if (cbits == bits)
        return newnode;
      /* so we just inserted a glue node, now insert real one */
      ++trie->ip4t_nnodes;
      if (!(node = createnode(prefix, bits, mp)))
          return NULL;
      linknode(newnode, node);
      return node;
    }

    /* node's prefix matches */
    if (node->ip4t_bits == bits)/* if number of bits are the same too, */
      return node;		/* ..we're found exactly the same prefix */

  }

  /* no more nodes, create simple new node */
  ++trie->ip4t_nnodes;
  if (!(node = createnode(prefix, bits, mp)))
    return NULL;
  *last = node;
  return node;
}
Пример #2
0
int ip4range(const char *s, ip4addr_t *ap, ip4addr_t *bp, char **np) {
    int bits = ip4prefix(s, ap, (char**)&s);

    if (bits < 0)
        return eret(np, s);
    else if (*s == '-') {	/* a-z */
        int bbits = ip4prefix(s + 1, bp, (char**)&s);
        if (bbits < 0) return eret(np, s);
        if (bbits == 8) { /* treat 127.0.0.1-2 as 127.0.0.1-127.0.0.2 */
            *bp = (*bp >> (bits - 8)) | (*ap & ip4mask(bits - 8));
            bbits = bits;
        }
Пример #3
0
static int
ds_ip4set_line(struct dataset *ds, char *s, struct dsctx *dsc) {
    struct dsdata *dsd = ds->ds_dsd;
    ip4addr_t a, b;
    const char *rr;
    unsigned rrl;

    int not;
    int bits;

    if (*s == ':') {
        if (!(rrl = parse_a_txt(s, &rr, def_rr, dsc)))
            return 1;
        if (!(dsd->def_rr = mp_dmemdup(ds->ds_mp, rr, rrl)))
            return 0;
        return 1;
    }

    if (*s == '!') {
        not = 1;
        ++s;
        SKIPSPACE(s);
    }
    else
        not = 0;
    if ((bits = ip4range(s, &a, &b, &s)) <= 0 ||
            (*s && !ISSPACE(*s) && !ISCOMMENT(*s) && *s != ':')) {
        dswarn(dsc, "invalid address");
        return 1;
    }
    if (accept_in_cidr)
        a &= ip4mask(bits);
    else if (a & ~ip4mask(bits)) {
        dswarn(dsc, "invalid range (non-zero host part)");
        return 1;
    }
    if (dsc->dsc_ip4maxrange && dsc->dsc_ip4maxrange <= (b - a)) {
        dswarn(dsc, "too large range (%u) ignored (%u max)",
               b - a + 1, dsc->dsc_ip4maxrange);
        return 1;
    }
    if (not)
        rr = NULL;
    else {
        SKIPSPACE(s);
        if (!*s || ISCOMMENT(*s))
            rr = dsd->def_rr;
        else if (!(rrl = parse_a_txt(s, &rr, dsd->def_rr, dsc)))
            return 1;
        else if (!(rr = mp_dmemdup(ds->ds_mp, rr, rrl)))
            return 0;
    }

    /*XXX some comments about funny ip4range_expand et al */

#define fn(idx,start,count) ds_ip4set_addent(dsd, idx, start, count, rr)

    /* helper macro for ip4range_expand:
     * deal with last octet, shifting a and b when done
     */
#define ip4range_expand_octet(bits)			\
  if ((a | 255u) >= b) {				\
    if (b - a == 255u)					\
      return fn((bits>>3)+1, a<<bits, 1);		\
    else						\
      return fn(bits>>3, a<<bits, b - a + 1);		\
  }							\
  if (a & 255u) {					\
    if (!fn(bits>>3, a<<bits, 256u - (a & 255u)))	\
      return 0;						\
    a = (a >> 8) + 1;					\
  }							\
  else							\
    a >>= 8;						\
  if ((b & 255u) != 255u) {				\
    if (!fn((bits>>3), (b & ~255u)<<bits, (b&255u)+1))	\
      return 0;						\
    b = (b >> 8) - 1;					\
  }							\
  else							\
    b >>= 8

    ip4range_expand_octet(0);
    ip4range_expand_octet(8);
    ip4range_expand_octet(16);
    return fn(3, a << 24, b - a + 1);

}