/*- * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 69): * wrote this file. As long as you retain this notice you * can do whatever you want with this stuff. If we meet some day, and you think * this stuff is worth it, you can buy me a beer in return. -Shteryana Shopova * ---------------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct pfa_entry { struct pfr_astats pfas; u_int index; TAILQ_ENTRY(pfa_entry) link; }; TAILQ_HEAD(pfa_table, pfa_entry); static struct pfa_table pfa_table; static time_t pfa_table_age; static int pfa_table_count; static int dev = -1; static int pfa_table_addrs(u_int sidx, struct pfr_table *pt) { struct pfioc_table io; struct pfr_astats *t = NULL; struct pfa_entry *e; int i, numaddrs = 1; if (pt == NULL) return (-1); memset(&io, 0, sizeof(io)); strlcpy(io.pfrio_table.pfrt_name, pt->pfrt_name, sizeof(pt->pfrt_name)); for (;;) { if ((t = reallocf(t, numaddrs * sizeof(struct pfr_astats))) == NULL) { syslog(LOG_ERR, "pfa_table_addrs(): reallocf(): %s", strerror(errno)); numaddrs = -1; break; } memset(t, 0, sizeof(*t)); io.pfrio_size = numaddrs; io.pfrio_buffer = t; io.pfrio_esize = sizeof(struct pfr_astats); if (ioctl(dev, DIOCRGETASTATS, &io)) { syslog(LOG_ERR, "pfa_table_addrs(): ioctl() on %s: %s", pt->pfrt_name, strerror(errno)); numaddrs = -1; break; } if (numaddrs >= io.pfrio_size) break; numaddrs = io.pfrio_size; } for (i = 0; i < numaddrs; i++) { if ((e = malloc(sizeof(struct pfa_entry))) == NULL) { syslog(LOG_ERR, "pfa_table_addrs(): reallocf(): %s", strerror(errno)); numaddrs = -1; break; } e->index = sidx + i; memcpy(&e->pfas, t + i, sizeof(struct pfr_astats)); TAILQ_INSERT_TAIL(&pfa_table, e, link); } free(t); return (numaddrs); } static int pfa_refresh(void) { struct pfioc_table io; struct pfr_table *pt = NULL, *it = NULL; struct pfa_entry *e; int i, numtbls = 1, cidx, naddrs; while (!TAILQ_EMPTY(&pfa_table)) { e = TAILQ_FIRST(&pfa_table); TAILQ_REMOVE(&pfa_table, e, link); free(e); } bzero(&io, sizeof(io)); io.pfrio_esize = sizeof(struct pfr_table); for (;;) { if ((pt = reallocf(pt, numtbls * sizeof(struct pfr_table))) == NULL) { syslog(LOG_ERR, "pfa_refresh(): reallocf() numtbls=%d: %s", numtbls, strerror(errno)); goto err2; } bzero(pt, sizeof(*pt)); io.pfrio_size = numtbls; io.pfrio_buffer = pt; if (ioctl(dev, DIOCRGETTABLES, &io)) { syslog(LOG_ERR, "pfa_refresh(): ioctl(DIOCRGETTABLES): %s", strerror(errno)); goto err2; } if (numtbls >= io.pfrio_size) break; numtbls = io.pfrio_size; } printf("pfa_refresh(): read %d tables\n", io.pfrio_size); cidx = 1; for (it = pt, i = 0; i < numtbls; it++, i++) { /* * Skip the table if not active - ioctl(DIOCRGETASTATS) will * return ESRCH for this entry anyway. */ printf("%s - flags: 0x%x\n", it->pfrt_name, it->pfrt_flags); if (!(it->pfrt_flags & PFR_TFLAG_ACTIVE)) continue; if ((naddrs = pfa_table_addrs(cidx, it)) < 0) goto err1; cidx += naddrs; } pfa_table_age = time(NULL); pfa_table_count = cidx; free(pt); return (0); err1: while (!TAILQ_EMPTY(&pfa_table)) { e = TAILQ_FIRST(&pfa_table); TAILQ_REMOVE(&pfa_table, e, link); free(e); } err2: free(pt); return(-1); } int main(int argc, char **argv) { struct pfa_entry *a1, *a2; if ((dev = open("/dev/pf", O_RDONLY)) == -1) { printf("pf_init(): open(): %s\n", strerror(errno)); return (-1); } TAILQ_INIT(&pfa_table); pfa_refresh(); a1 = TAILQ_FIRST(&pfa_table); while (a1 != NULL) { printf("%d: net ", a1->index); if (a1->pfas.pfras_a.pfra_af == AF_INET) printf("0x%x\n", a1->pfas.pfras_a.pfra_ip4addr.s_addr); else if (a1->pfas.pfras_a.pfra_af == AF_INET6) printf("some IPv6 stuff\n"); a2 = TAILQ_NEXT(a1, link); free(a1); a1 = a2; } exit (0); }