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