BIND9 Reject DNS Root Queries

bind: blackhole for invalid recursive queries?
Disabling Root DNS Server queries on Redhat linux
Ubuntu server 12.04 bind9 dns query rejected

Using FreeBSD’s BPF device with C/C++

Socket Compiler Error

Compile Error in using /usr/include/net/if.h
compile problems on freebsd

SVNWEB

sys/pf
sbin/pfctl

[root@gateway ~]# pfctl -t hacker -T add 192.168.0.2 192.168.0.3 192.168.0.4
1 table created.
3/3 addresses added.

[root@gateway ~]# pfctl -f /etc/pf.conf

[root@gateway ~]# pfctl -t hacker -T show
   192.168.1.1

[root@gateway ~]# pfctl -t hacker -T add 192.168.0.2 192.168.0.3 192.168.0.4
3/3 addresses added.

[root@gateway ~]# pfctl -t hacker -T show
   192.168.0.2
   192.168.0.3
   192.168.0.4
   192.168.1.1
     DIOCRADDADDRS struct pfioc_table *io
	     Add one or	more addresses to a table.  On entry, pfrio_table con-
	     tains the table ID	and pfrio_buffer must point to an array	of
	     struct pfr_addr containing	at least pfrio_size elements to	add to
	     the table.	 pfrio_esize must be the size of struct	pfr_addr.  On
	     exit, pfrio_nadd contains the number of addresses effectively
	     added.

	     struct pfr_addr {
		     union {
			     struct in_addr   _pfra_ip4addr;
			     struct in6_addr  _pfra_ip6addr;
		     }		      pfra_u;
		     u_int8_t	      pfra_af;
		     u_int8_t	      pfra_net;
		     u_int8_t	      pfra_not;
		     u_int8_t	      pfra_fback;
	     };
	     #define pfra_ip4addr    pfra_u._pfra_ip4addr
	     #define pfra_ip6addr    pfra_u._pfra_ip6addr
/usr/include/sys/ioctl.h: ioctl                (dev, DIOCRADDADDRS, &io)
sbin/pfctl/pfctl_radix.c: pfr_add_addrs        (tbl=0xbfbfd198, addr=0x28826100, size=3, nadd=0xbfbfd16c, flags=0)
sbin/pfctl/pfctl_table.c: pfctl_table          (argc=3, argv=0xbfbfdc90, tname=0xbfbfddd3 "hacker", command=0x808831c "add", file=0x0, anchor=0xbfbfd808 "", opts=0)
sbin/pfctl/pfctl_table.c: pfctl_command_tables (argc=3, argv=0xbfbfdc90, tname=0xbfbfddd3 "hacker", command=0x808831c "add", file=0x0, anchor=0xbfbfd808 "", opts=0)
sbin/pfctl/pfctl.c:       main                 (argc=3, argv=0xbfbfdc90)


tbl:
$1 = (struct pfr_table *) 0xbfbfd198
$2 = { pfrt_anchor = '\0' 
       pfrt_name   = "hacker", 
       pfrt_flags  = 0,
       pfrt_fback  = 0 '\0'}

addr:
$3 = (struct pfr_addr *) 0x28826100
$4 = { pfra_u = { _pfra_ip4addr = { s_addr = 33597632 },
                  _pfra_ip6addr = { [...] }
                },
       pfra_af = 2 '\002',
       pfra_net = 32 ' ', 
       pfra_not = 0 '\0',
       pfra_fback = 0 '\0'}

pfctl_radix.c:418    pfr_buf_add          (b=0xbfbfd188, e=0xbfbfcfb0)
pfctl_parser.c:1704  append_addr_host     (b=0xbfbfd188, n=0x28814460, test=0, not=0)
pfctl_parser.c:1659  append_addr          (b=0xbfbfd188, s=0xbfbfddf9 "192.168.0.4", test=0)
pfctl_table.c:418    load_addr            (b=0xbfbfd188, argc=0, argv=0xbfbfdc9c, file=0x0, nonetwork=0)
pfctl_table.c:201    pfctl_table          (argc=3, argv=0xbfbfdc90, tname=0xbfbfddd3 "hacker", command=0x808831c "add", file=0x0, anchor=0xbfbfd808 "", opts=0)
pfctl_table.c:124    pfctl_command_tables (argc=3, argv=0xbfbfdc90, tname=0xbfbfddd3 "hacker", command=0x808831c "add", file=0x0, anchor=0xbfbfd808 "", opts=0)
pfctl.c:2328         main                 (argc=3, argv=0xbfbfdc90)
typedef char *          caddr_t;        /* core address */
typedef const char *    c_caddr_t;      /* core address, pointer to const */
/*
 * Internet address (a structure for historical reasons)
 */
struct in_addr {
	in_addr_t s_addr;
};

Essential Socket Functions

int
main(int argc, char *argv[])
{
    [...]
    while ((ch = getopt(argc, argv,
        "a:AdD:eqf:F:ghi:k:K:mnNOo::Pp:rRs:t:T:vx:z")) != -1) {
        switch (ch) {
        [...]
        case 't':
            tableopt = optarg;
            break;
        case 'T':
            tblcmdopt = pfctl_lookup_option(optarg, tblcmdopt_list);
            if (tblcmdopt == NULL) {
                warnx("Unknown table command '%s'", optarg);
                usage();
            }
            break;
        [...]
        }
    }
    [...]
    if (tblcmdopt != NULL) {
        error = pfctl_command_tables(argc, argv, tableopt,
            tblcmdopt, rulesopt, anchorname, opts);
        rulesopt = NULL;
    }
    [...]
}
enum {
    PFRB_TABLES = 1,
    PFRB_TSTATS,
    PFRB_ADDRS,
    PFRB_ASTATS,
    PFRB_IFACES,
    PFRB_TRANS,
    PFRB_MAX
};

struct pfr_buffer {
    int                 pfrb_type;      /* type of content, see enum above */
    int                 pfrb_size;      /* number of objects in buffer */
    int                 pfrb_msize;     /* maximum number of objects in buffer */
    void               *pfrb_caddr;     /* malloc'ated memory area */
};

/*  int            int            int              void *                */
   {pfrb_type = 3, pfrb_size = 0, pfrb_msize = 0,  pfrb_caddr = 0x0}
   {pfrb_type = 3, pfrb_size = 1, pfrb_msize = 64, pfrb_caddr = 0x28826100}
   {pfrb_type = 3, pfrb_size = 2, pfrb_msize = 64, pfrb_caddr = 0x28826100}


struct pfioc_table {
    struct pfr_table    pfrio_table;
    void               *pfrio_buffer;
    int                 pfrio_esize;
    int                 pfrio_size;
    int                 pfrio_size2;
    int                 pfrio_nadd;
    int                 pfrio_ndel;
    int                 pfrio_nchange;
    int                 pfrio_flags;
    u_int32_t           pfrio_ticket;
};

struct pfr_table {
    char                pfrt_anchor[MAXPATHLEN];
    char                pfrt_name[PF_TABLE_NAME_SIZE];
    u_int32_t           pfrt_flags;
    u_int8_t            pfrt_fback;
};

/*  char *              char *                       u_int32_t       u_int8_t          */
   {pfrt_anchor = '\0', pfrt_name = "hacker", '\0' , pfrt_flags = 0, pfrt_fback = 0 '\0'}

pfrt_flags:
#define PFR_TFLAG_PERSIST       0x00000001
#define PFR_TFLAG_CONST         0x00000002
#define PFR_TFLAG_ACTIVE        0x00000004
#define PFR_TFLAG_INACTIVE      0x00000008
#define PFR_TFLAG_REFERENCED    0x00000010
#define PFR_TFLAG_REFDANCHOR    0x00000020
#define PFR_TFLAG_USRMASK       0x00000003
#define PFR_TFLAG_SETMASK       0x0000003C
#define PFR_TFLAG_ALLMASK       0x0000003F

struct pfr_table.pfrt_fback:
struct pfr_addr.pfra_fback:
enum {
    PFR_FB_NONE,
    PFR_FB_MATCH,
    PFR_FB_ADDED,
    PFR_FB_DELETED,
    PFR_FB_CHANGED,
    PFR_FB_CLEARED,
    PFR_FB_DUPLICATE,
    PFR_FB_NOTMATCH,
    PFR_FB_CONFLICT,
    PFR_FB_MAX
};

struct pfr_addr {
    union {
        struct in_addr   _pfra_ip4addr;
        struct in6_addr  _pfra_ip6addr;
    }                pfra_u;
    u_int8_t         pfra_af;        /**< AF_INET or AF_INET6 */
    u_int8_t         pfra_net;
    u_int8_t         pfra_not;
    u_int8_t         pfra_fback;
};
#define pfra_ip4addr    pfra_u._pfra_ip4addr
#define pfra_ip6addr    pfra_u._pfra_ip6addr

/* union                                                           */
   { pfra_u = { _pfra_ip4addr = { s_addr = 33597632 },
                _pfra_ip6addr = {__u6_addr = { __u6_addr8  = { ... },
                                               __u6_addr16 = { ... },
                                               __u6_addr32 = { ... }
                                             }
                                }
              },
/*   u_int8_t      u_int8_t        u_int8_t       u_int8_t         */
     pfra_af = 2 , pfra_net = 32 , pfra_not = 0 , pfra_fback = 0   }

/***************************************************************/

#define v4      pfa.v4
#define v6      pfa.v6
#define addr8   pfa.addr8
#define addr16  pfa.addr16
#define addr32  pfa.addr32

struct pf_addr {
    union {
        struct in_addr          v4;
        struct in6_addr         v6;
        u_int8_t                addr8[16];
        u_int16_t               addr16[8];
        u_int32_t               addr32[4];
    }                           pfa;           /* 128-bit address */
};

struct pf_addr_wrap {
    union {
        struct {
            struct pf_addr      addr;
            struct pf_addr      mask;
        }                       a;
        char                    ifname[IFNAMSIZ];
        char                    tblname[PF_TABLE_NAME_SIZE];
    }                           v;
    union {
        struct pfi_dynaddr     *dyn;
        struct pfr_ktable      *tbl;
        int                     dyncnt;
        int                     tblcnt;
    }                           p;
    u_int8_t                    type;          /* PF_ADDR_* */
    u_int8_t                    iflags;        /* PFI_AFLAG_* */
};

#define CREATE_TABLE do {                                   \
    table.pfrt_flags |= PFR_TFLAG_PERSIST;                  \
    if ((!(opts & PF_OPT_NOACTION) ||                       \
        (opts & PF_OPT_DUMMYACTION)) &&                     \
        (pfr_add_tables(&table, 1, &nadd, flags)) &&        \
        (errno != EPERM)) {                                 \
            radix_perror();                                 \
            goto _error;                                    \
    }                                                       \
    if (nadd) {                                             \
        warn_namespace_collision(table.pfrt_name);          \
        xprintf(opts, "%d table created", nadd);            \
        if (opts & PF_OPT_NOACTION)                         \
            return (0);                                     \
    }                                                       \
    table.pfrt_flags &= ~PFR_TFLAG_PERSIST;                 \
} while(0)                           

int
pfctl_command_tables(int argc, char *argv[], char *tname,
    const char *command, char *file, const char *anchor, int opts)
{
	if (tname == NULL || command == NULL)
		usage();
	return pfctl_table(argc, argv, tname, command, file, anchor, opts);
}

int
pfctl_table(int argc, char *argv[], char *tname, const char *command,
    char *file, const char *anchor, int opts)
{
    struct pfr_table    table;
    struct pfr_buffer   b, b2;
    struct pfr_addr    *a, *a2;
    int                 nadd = 0;

    [...]

    strlcpy(table.pfrt_name, tname, sizeof(table.pfrt_name);      /**< copy table name */

    [...]
    } else if (!strcmp(command, "add")) {
        b.pfrb_type = PFRB_ADDRS;                                 /**< set type to ADDR */
        if (load_addr(&b, argc, argv, file, 0))                   /**< load_addr(): parse arguments and pass it to struct pfr_buffer */
            goto _error;
        CREATE_TABLE;
        if (opts & PF_OPT_VERBOSE)
            flags |= PFR_FLAG_FEEDBACK;
        RVTEST(pfr_add_addrs(&table, b.pfrb_caddr, b.pfrb_size, &nadd, flags));    /**< pfr_add_addrs(): 
        xprintf(opts, "%d/%d addresses added", nadd, b.pfrb_size);
        if (opts & PF_OPT_VERBOSE)
            PFRB_FOREACH(a, &b)
                if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback)
                    print_addrx(a, NULL, opts & PF_OPT_USEDNS);
    }
    [...]
}

int
load_addr(struct pfr_buffer *b, int argc, char *argv[], char *file,
    int nonetwork)
{
    while (argc--)
        if (append_addr(b, *argv++, nonetwork)) {
            if (errno)
                warn("cannot decode %s", argv[-1]);
            return (-1);
        }
    if (pfr_buf_load(b, file, nonetwork, append_addr)) {
        warn("cannot load %s", file);
        return (-1);
    }
    return (0);
}
struct node_host {
    struct pf_addr_wrap  addr;
    struct pf_addr       bcast;
    struct pf_addr       peer;
    sa_family_t          af;
    u_int8_t             not;
    u_int32_t            ifindex;   /* link-local IPv6 addrs */
    char                *ifname;
    u_int                ifa_flags;
    struct node_host    *next;
    struct node_host    *tail;
};
/*
 * convert a hostname to a list of addresses and put them in the given buffer.
 * test:
 *  if set to 1, only simple addresses are accepted (no netblock, no "!").
 */
int
append_addr(struct pfr_buffer *b, char *s, int test)
{
    char             *r;
    struct node_host    *h, *n;
    int          rv, not = 0;

    for (r = s; *r == '!'; r++)
        not = !not;
    if ((n = host(r)) == NULL) {
        errno = 0;
        return (-1);
    }
    rv = append_addr_host(b, n, test, not);
    do {
        h = n;
        n = n->next;
        free(h);
    } while (n != NULL);
    return (rv);
}

/*
 * same as previous function, but with a pre-parsed input and the ability
 * to "negate" the result. Does not free the node_host list.
 * not:
 *      setting it to 1 is equivalent to adding "!" in front of parameter s.
 */
int
append_addr_host(struct pfr_buffer *b, struct node_host *n, int test, int not)
{
    int          bits;
    struct pfr_addr      addr;

    do {
        bzero(&addr, sizeof(addr));
        addr.pfra_not = n->not ^ not;
        addr.pfra_af = n->af;
        addr.pfra_net = unmask(&n->addr.v.a.mask, n->af);            /**< assign netmask, node_host -> pfr_addr */
        switch (n->af) {
        case AF_INET:
            addr.pfra_ip4addr.s_addr = n->addr.v.a.addr.addr32[0];   /**< assign address, node_host -> pfr_addr */
            bits = 32;
            break;
        case AF_INET6:
            memcpy(&addr.pfra_ip6addr, &n->addr.v.a.addr.v6,
                sizeof(struct in6_addr));
            bits = 128;
            break;
        default:
            errno = EINVAL;
            return (-1);
        }
        if ((test && (not || addr.pfra_net != bits)) ||              /**< test = 0, not = 0 => bypass these lines */
            addr.pfra_net > bits) {
            errno = EINVAL;
            return (-1);
        }
        if (pfr_buf_add(b, &addr))
            return (-1);
    } while ((n = n->next) != NULL);

    return (0);
}

struct node_host *
host(const char *s)
{
    struct node_host    *h = NULL;
    int          mask, v4mask, v6mask, cont = 1;
    char            *p, *q, *ps;

    if ((p = strrchr(s, '/')) != NULL) {
        mask = strtol(p+1, &q, 0);
        if (!q || *q || mask > 128 || q == (p+1)) {
            fprintf(stderr, "invalid netmask '%s'\n", p);
            return (NULL);
        }
        if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL)
            err(1, "host: malloc");
        strlcpy(ps, s, strlen(s) - strlen(p) + 1);
        v4mask = v6mask = mask;
    } else {
        if ((ps = strdup(s)) == NULL)
            err(1, "host: strdup");
        v4mask = 32;
        v6mask = 128;
        mask = -1;
    }

    /* interface with this name exists? */
    if (cont && (h = host_if(ps, mask)) != NULL)
        cont = 0;

    /* IPv4 address? */
    if (cont && (h = host_v4(s, mask)) != NULL)
        cont = 0;

    /* IPv6 address? */
    if (cont && (h = host_v6(ps, v6mask)) != NULL)
        cont = 0;

    /* dns lookup */
    if (cont && (h = host_dns(ps, v4mask, v6mask)) != NULL)
        cont = 0;
    free(ps);

    if (h == NULL || cont == 1) {
        fprintf(stderr, "no IP address found for %s\n", s);
        return (NULL);
    }
    return (h);
}

struct node_host *
host_v4(const char *s, int mask)
{
    struct node_host    *h = NULL;
    struct in_addr       ina;
    int          bits = 32;

    memset(&ina, 0, sizeof(struct in_addr));
    if (strrchr(s, '/') != NULL) {
        if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1)     /**< parse string, return netmask bits */
            return (NULL);
    } else {
        if (inet_pton(AF_INET, s, &ina) != 1)
            return (NULL);
    }

    h = calloc(1, sizeof(struct node_host));
    if (h == NULL)
        err(1, "address: calloc");
    h->ifname = NULL;
    h->af = AF_INET;
    h->addr.v.a.addr.addr32[0] = ina.s_addr;
    set_ipmask(h, bits);                                                     /**< set IP mask */
    h->next = NULL;
    h->tail = h;

    return (h);
}

void
set_ipmask(struct node_host *h, u_int8_t b)
{
    struct pf_addr  *m, *n;
    int      i, j = 0;

    m = &h->addr.v.a.mask;
    memset(m, 0, sizeof(*m));

    while (b >= 32) {
        m->addr32[j++] = 0xffffffff;
        b -= 32;
    }
    for (i = 31; i > 31-b; --i)
        m->addr32[j] |= (1 << i);
    if (b)
        m->addr32[j] = htonl(m->addr32[j]);

    /* Mask off bits of the address that will never be used. */
    n = &h->addr.v.a.addr;
    if (h->addr.type == PF_ADDR_ADDRMASK)
        for (i = 0; i < 4; i++)
            n->addr32[i] = n->addr32[i] & m->addr32[i];
}
/* buffer management code */

size_t buf_esize[PFRB_MAX] = { 0,
    sizeof(struct pfr_table), sizeof(struct pfr_tstats),
    sizeof(struct pfr_addr), sizeof(struct pfr_astats),
    sizeof(struct pfi_kif), sizeof(struct pfioc_trans_e)
};

/*
 * add one element to the buffer
 */
int
pfr_buf_add(struct pfr_buffer *b, const void *e)
{
    size_t bs;

    if (b == NULL || b->pfrb_type <= 0 || b->pfrb_type >= PFRB_MAX ||
        e == NULL) {
        errno = EINVAL;
        return (-1);
    }
    bs = buf_esize[b->pfrb_type];           /**< choose buffer size, ex. sizeof(struct pfr_addr) */
    if (b->pfrb_size == b->pfrb_msize)      /**< no space left */
        if (pfr_buf_grow(b, 0))             /**< increase buffer */
            return (-1);
    memcpy(((caddr_t)b->pfrb_caddr) + bs * b->pfrb_size, e, bs);
    b->pfrb_size++;
    return (0);
}

int
pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
    int *nadd, int flags)
{
    struct pfioc_table io;

    if (tbl == NULL || size < 0 || (size && addr == NULL)) {
        errno = EINVAL;
        return (-1);
    }
    bzero(&io, sizeof io);
    io.pfrio_flags = flags;
    io.pfrio_table = *tbl;
    io.pfrio_buffer = addr;
    io.pfrio_esize = sizeof(*addr);
    io.pfrio_size = size;
    if (ioctl(dev, DIOCRADDADDRS, &io))
        return (-1);
    if (nadd != NULL)
        *nadd = io.pfrio_nadd;
    return (0);
}

Pointer Handling

Pointer Arithmetic

arr[ i ] == * ( arr + i )

ex.
sizeof(unsigned long) = 64-bit = 8 byte
unsigned long arr[2];
&arr[0] = (arr + 0) = 0x608ea0
&arr[1] = (arr + 1) = 0x608ea8
(gdb) p &entry.allocator[0]         (gdb) p &((ethernet_header_t *) entry.allocator)[0]  
$19 = (header_t *) 0x608e90         $21 = (struct _ethernet_header_t *) 0x608e90


(gdb) p &entry.allocator[1]         (gdb) p &((ethernet_header_t *) entry.allocator)[1]
$20 = (header_t *) 0x608eb8         $22 = (struct _ethernet_header_t *) 0x608ed0
   
            
(gdb) p sizeof(header_t)            (gdb) p sizeof(ethernet_header_t)
$24 = 40 = 0x28                     $23 = 64 = 0x40

  0x608e90                            0x608e90
+ 0x000028                          + 0x000040
----------                          ----------
  0x608eb8                            0x608ed0
===========                         ===========

Leave a Reply

Your email address will not be published. Required fields are marked *