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
[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; };
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
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 =========== ===========