Exemple #1
0
static void
display_states(const struct pfioc_states *ps, int verbose __unused, FILE* f)
{
    struct pfsync_state *p = NULL;
    struct pfsync_state_peer *src, *dst;
    struct protoent *proto;
    int nb_states;
    int i;
    uint64_t id;

    p = ps->ps_states;
    nb_states = ps->ps_len / sizeof(struct pfsync_state);

    for (i = 0; i < nb_states; i++, p++) {
        fprintf(f, "state %s ", p->direction == PF_OUT ? "out" : "in");
        fprintf(f, "on %s ", p->ifname);

        if ((proto = getprotobynumber(p->proto)) != NULL)
            fprintf(f, "proto %s ", proto->p_name);
        else
            fprintf(f, "proto %u ", p->proto);


        if (PF_ANEQ(&p->lan.addr, &p->gwy.addr, p->af) ||
                (p->lan.port != p->gwy.port)) {

            char buf1[64], buf2[64], buf3[64];
            fprintf(f, "from %s to %s using %s",
                    print_host(&p->lan, p->af, buf1, sizeof(buf1)),
                    print_host(&p->ext, p->af, buf2, sizeof(buf2)),
                    print_host(&p->gwy, p->af, buf3, sizeof(buf3)));
        } else {
            char buf1[64], buf2[64];
            fprintf(f, "from %s to %s",
                    print_host(&p->lan, p->af, buf1, sizeof(buf1)),
                    print_host(&p->ext, p->af, buf2, sizeof(buf2)));
        }

        memcpy(&id, p->id, sizeof(p->id));
        fprintf(f, " id %" PRIu64 " cid %" PRIu32 " expire %" PRIu32 " timeout %" PRIu8,
                id , p->creatorid, p->expire, p->timeout);

        if (p->direction == PF_OUT) {
            src = &p->src;
            dst = &p->dst;
        } else {
            src = &p->dst;
            dst = &p->src;
        }

        fprintf(f, " src ");
        print_peer(src, p->proto, f);
        fprintf(f, " dst ");
        print_peer(dst, p->proto, f);

        fprintf(f, "\n");
    }
}
Exemple #2
0
void
print_state(struct pfsync_state *s, int opts)
{
	struct pfsync_state_peer *src, *dst;
	struct pfsync_state_key *sk, *nk;
	struct protoent *p;
	int min, sec;

	if (s->direction == PF_OUT) {
		src = &s->src;
		dst = &s->dst;
		sk = &s->key[PF_SK_STACK];
		nk = &s->key[PF_SK_WIRE];
		if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6) 
			sk->port[0] = nk->port[0];
	} else {
		src = &s->dst;
		dst = &s->src;
		sk = &s->key[PF_SK_WIRE];
		nk = &s->key[PF_SK_STACK];
		if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6) 
			sk->port[1] = nk->port[1];
	}
	printf("%s ", s->ifname);
	if ((p = getprotobynumber(s->proto)) != NULL)
		printf("%s ", p->p_name);
	else
		printf("%u ", s->proto);

	print_host(&nk->addr[1], nk->port[1], s->af, opts);
	if (PF_ANEQ(&nk->addr[1], &sk->addr[1], s->af) ||
	    nk->port[1] != sk->port[1]) {
		printf(" (");
		print_host(&sk->addr[1], sk->port[1], s->af, opts);
		printf(")");
	}
	if (s->direction == PF_OUT)
		printf(" -> ");
	else
		printf(" <- ");
	print_host(&nk->addr[0], nk->port[0], s->af, opts);
	if (PF_ANEQ(&nk->addr[0], &sk->addr[0], s->af) ||
	    nk->port[0] != sk->port[0]) {
		printf(" (");
		print_host(&sk->addr[0], sk->port[0], s->af, opts);
		printf(")");
	}

	printf("    ");
	if (s->proto == IPPROTO_TCP) {
		if (src->state <= TCPS_TIME_WAIT &&
		    dst->state <= TCPS_TIME_WAIT)
			printf("   %s:%s\n", tcpstates[src->state],
			    tcpstates[dst->state]);
		else if (src->state == PF_TCPS_PROXY_SRC ||
		    dst->state == PF_TCPS_PROXY_SRC)
			printf("   PROXY:SRC\n");
		else if (src->state == PF_TCPS_PROXY_DST ||
		    dst->state == PF_TCPS_PROXY_DST)
			printf("   PROXY:DST\n");
		else
			printf("   <BAD STATE LEVELS %u:%u>\n",
			    src->state, dst->state);
		if (opts & PF_OPT_VERBOSE) {
			printf("   ");
			print_seq(src);
			if (src->wscale && dst->wscale)
				printf(" wscale %u",
				    src->wscale & PF_WSCALE_MASK);
			printf("  ");
			print_seq(dst);
			if (src->wscale && dst->wscale)
				printf(" wscale %u",
				    dst->wscale & PF_WSCALE_MASK);
			printf("\n");
		}
	} else if (s->proto == IPPROTO_UDP && src->state < PFUDPS_NSTATES &&
	    dst->state < PFUDPS_NSTATES) {
		const char *states[] = PFUDPS_NAMES;

		printf("   %s:%s\n", states[src->state], states[dst->state]);
#ifndef INET6
	} else if (s->proto != IPPROTO_ICMP && src->state < PFOTHERS_NSTATES &&
	    dst->state < PFOTHERS_NSTATES) {
#else
	} else if (s->proto != IPPROTO_ICMP && s->proto != IPPROTO_ICMPV6 &&
	    src->state < PFOTHERS_NSTATES && dst->state < PFOTHERS_NSTATES) {
#endif
		/* XXX ICMP doesn't really have state levels */
		const char *states[] = PFOTHERS_NAMES;

		printf("   %s:%s\n", states[src->state], states[dst->state]);
	} else {
		printf("   %u:%u\n", src->state, dst->state);
	}

	if (opts & PF_OPT_VERBOSE) {
		u_int64_t packets[2];
		u_int64_t bytes[2];
		u_int32_t creation = ntohl(s->creation);
		u_int32_t expire = ntohl(s->expire);

		sec = creation % 60;
		creation /= 60;
		min = creation % 60;
		creation /= 60;
		printf("   age %.2u:%.2u:%.2u", creation, min, sec);
		sec = expire % 60;
		expire /= 60;
		min = expire % 60;
		expire /= 60;
		printf(", expires in %.2u:%.2u:%.2u", expire, min, sec);

		bcopy(s->packets[0], &packets[0], sizeof(u_int64_t));
		bcopy(s->packets[1], &packets[1], sizeof(u_int64_t));
		bcopy(s->bytes[0], &bytes[0], sizeof(u_int64_t));
		bcopy(s->bytes[1], &bytes[1], sizeof(u_int64_t));
		printf(", %ju:%ju pkts, %ju:%ju bytes",
		    (uintmax_t )be64toh(packets[0]),
		    (uintmax_t )be64toh(packets[1]),
		    (uintmax_t )be64toh(bytes[0]),
		    (uintmax_t )be64toh(bytes[1]));
		if (ntohl(s->anchor) != -1)
			printf(", anchor %u", ntohl(s->anchor));
		if (ntohl(s->rule) != -1)
			printf(", rule %u", ntohl(s->rule));
		if (s->state_flags & PFSTATE_SLOPPY)
			printf(", sloppy");
		if (s->sync_flags & PFSYNC_FLAG_SRCNODE)
			printf(", source-track");
		if (s->sync_flags & PFSYNC_FLAG_NATSRCNODE)
			printf(", sticky-address");
		printf("\n");
	}
	if (opts & PF_OPT_VERBOSE2) {
		u_int64_t id;

		bcopy(&s->id, &id, sizeof(u_int64_t));
		printf("   id: %016jx creatorid: %08x",
		    (uintmax_t )be64toh(id), ntohl(s->creatorid));
		printf("\n");
	}
}
Exemple #3
0
void
print_state(struct pfsync_state *s, int opts)
{
	struct pfsync_state_peer *src, *dst;
	struct pfsync_state_key *sk, *nk;
	struct protoent *p;
	int min, sec;

	if (s->direction == PF_OUT) {
		src = &s->src;
		dst = &s->dst;
		sk = &s->key[PF_SK_STACK];
		nk = &s->key[PF_SK_WIRE];
		if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6) 
			sk->port[0] = nk->port[0];
	} else {
		src = &s->dst;
		dst = &s->src;
		sk = &s->key[PF_SK_WIRE];
		nk = &s->key[PF_SK_STACK];
		if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6) 
			sk->port[1] = nk->port[1];
	}
	printf("%s ", s->ifname);
	if ((p = getprotobynumber(s->proto)) != NULL)
		printf("%s ", p->p_name);
	else
		printf("%u ", s->proto);

	print_host(&nk->addr[1], nk->port[1], s->af, opts);
	if (PF_ANEQ(&nk->addr[1], &sk->addr[1], s->af) ||
	    nk->port[1] != sk->port[1]) {
		printf(" (");
		print_host(&sk->addr[1], sk->port[1], s->af, opts);
		printf(")");
	}
	if (s->direction == PF_OUT)
		printf(" -> ");
	else
		printf(" <- ");
	print_host(&nk->addr[0], nk->port[0], s->af, opts);
	if (PF_ANEQ(&nk->addr[0], &sk->addr[0], s->af) ||
	    nk->port[0] != sk->port[0]) {
		printf(" (");
		print_host(&sk->addr[0], sk->port[0], s->af, opts);
		printf(")");
	}

	printf("    ");
	if (s->proto == IPPROTO_TCP) {
		if (src->state <= TCPS_TIME_WAIT &&
		    dst->state <= TCPS_TIME_WAIT)
			printf("   %s:%s\n", tcpstates[src->state],
			    tcpstates[dst->state]);
		else if (src->state == PF_TCPS_PROXY_SRC ||
		    dst->state == PF_TCPS_PROXY_SRC)
			printf("   PROXY:SRC\n");
		else if (src->state == PF_TCPS_PROXY_DST ||
		    dst->state == PF_TCPS_PROXY_DST)
			printf("   PROXY:DST\n");
		else
			printf("   <BAD STATE LEVELS %u:%u>\n",
			    src->state, dst->state);
		if (opts & PF_OPT_VERBOSE) {
			printf("   ");
			print_seq(src);
			if (src->wscale && dst->wscale)
				printf(" wscale %u",
				    src->wscale & PF_WSCALE_MASK);
			printf("  ");
			print_seq(dst);
			if (src->wscale && dst->wscale)
				printf(" wscale %u",
				    dst->wscale & PF_WSCALE_MASK);
			printf("\n");
		}
	} else if (s->proto == IPPROTO_UDP && src->state < PFUDPS_NSTATES &&
	    dst->state < PFUDPS_NSTATES) {
		const char *states[] = PFUDPS_NAMES;

		printf("   %s:%s\n", states[src->state], states[dst->state]);
	} else if (s->proto != IPPROTO_ICMP && src->state < PFOTHERS_NSTATES &&
	    dst->state < PFOTHERS_NSTATES) {
		/* XXX ICMP doesn't really have state levels */
		const char *states[] = PFOTHERS_NAMES;

		printf("   %s:%s\n", states[src->state], states[dst->state]);
	} else {
		printf("   %u:%u\n", src->state, dst->state);
	}

	if (opts & PF_OPT_VERBOSE) {
		u_int64_t packets[2];
		u_int64_t bytes[2];
		u_int32_t creation = ntohl(s->creation);
		u_int32_t expire = ntohl(s->expire);

		printf("   rule %u", ntohl(s->rule));
		if (ntohl(s->anchor) != -1)
			printf(", anchor %u", ntohl(s->anchor));
		printf(", flags:");
		if (s->state_flags & PFSTATE_ALLOWOPTS)
			printf(" allowopts");
		if (s->state_flags & PFSTATE_SLOPPY)
			printf(" sloppy");
		if (s->state_flags & PFSTATE_STACK_GLOBAL)
			printf(" global");
		if (s->state_flags & PFSTATE_CREATEINPROG)
			printf(" creating");
		if (s->state_flags & PFSTATE_HALF_DUPLEX)
			printf(" (TRANSLATION COLLISION)");
		if (s->sync_flags & PFSYNC_FLAG_SRCNODE)
			printf(" source-track");
		if (s->sync_flags & PFSYNC_FLAG_NATSRCNODE)
			printf(" sticky-address");
		switch(s->pickup_mode) {
		case PF_PICKUPS_UNSPECIFIED:
			break;
		case PF_PICKUPS_DISABLED:
			printf(" no-pickups");
			break;
		case PF_PICKUPS_HASHONLY:
			printf(" hash-only");
			break;
		case PF_PICKUPS_ENABLED:
			printf(" pickups");
			break;
		}
		printf("\n");

		sec = creation % 60;
		creation /= 60;
		min = creation % 60;
		creation /= 60;
		printf("   age %.2u:%.2u:%.2u", creation, min, sec);
		sec = expire % 60;
		expire /= 60;
		min = expire % 60;
		expire /= 60;
		printf(", expires in %.2u:%.2u:%.2u", expire, min, sec);

		bcopy(s->packets[0], &packets[0], sizeof(u_int64_t));
		bcopy(s->packets[1], &packets[1], sizeof(u_int64_t));
		bcopy(s->bytes[0], &bytes[0], sizeof(u_int64_t));
		bcopy(s->bytes[1], &bytes[1], sizeof(u_int64_t));
		printf(", %" PRIu64 ":%" PRIu64 " pkts, %" PRIu64 ":%"
		       PRIu64 " bytes\n",
		    be64toh(packets[0]),
		    be64toh(packets[1]),
		    be64toh(bytes[0]),
		    be64toh(bytes[1]));
	}
	if (opts & PF_OPT_VERBOSE2) {
		u_int64_t id;

		bcopy(&s->id, &id, sizeof(u_int64_t));
		printf("   id: %016jx creatorid: %08x cpuid: %-3d",
		       be64toh(id),  ntohl(s->creatorid), s->cpuid);
		printf("\n");		    
	}
}
Exemple #4
0
static void
print_state(netdissect_options *ndo, struct pfsync_state *s)
{
	struct pfsync_state_peer *src, *dst;
	struct pfsync_state_key *sk, *nk;
	int min, sec;

	if (s->direction == PF_OUT) {
		src = &s->src;
		dst = &s->dst;
		sk = &s->key[PF_SK_STACK];
		nk = &s->key[PF_SK_WIRE];
		if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6)
			sk->port[0] = nk->port[0];
	} else {
		src = &s->dst;
		dst = &s->src;
		sk = &s->key[PF_SK_WIRE];
		nk = &s->key[PF_SK_STACK];
		if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6)
			sk->port[1] = nk->port[1];
	}
	ND_PRINT((ndo, "\t%s ", s->ifname));
	ND_PRINT((ndo, "proto %u ", s->proto));

	print_host(ndo, &nk->addr[1], nk->port[1], s->af, NULL);
	if (PF_ANEQ(&nk->addr[1], &sk->addr[1], s->af) ||
	    nk->port[1] != sk->port[1]) {
		ND_PRINT((ndo, " ("));
		print_host(ndo, &sk->addr[1], sk->port[1], s->af, NULL);
		ND_PRINT((ndo, ")"));
	}
	if (s->direction == PF_OUT)
		ND_PRINT((ndo, " -> "));
	else
		ND_PRINT((ndo, " <- "));
	print_host(ndo, &nk->addr[0], nk->port[0], s->af, NULL);
	if (PF_ANEQ(&nk->addr[0], &sk->addr[0], s->af) ||
	    nk->port[0] != sk->port[0]) {
		ND_PRINT((ndo, " ("));
		print_host(ndo, &sk->addr[0], sk->port[0], s->af, NULL);
		ND_PRINT((ndo, ")"));
	}

	print_src_dst(ndo, src, dst, s->proto);

	if (vflag > 1) {
		uint64_t packets[2];
		uint64_t bytes[2];
		uint32_t creation = ntohl(s->creation);
		uint32_t expire = ntohl(s->expire);

		sec = creation % 60;
		creation /= 60;
		min = creation % 60;
		creation /= 60;
		ND_PRINT((ndo, "\n\tage %.2u:%.2u:%.2u", creation, min, sec));
		sec = expire % 60;
		expire /= 60;
		min = expire % 60;
		expire /= 60;
		ND_PRINT((ndo, ", expires in %.2u:%.2u:%.2u", expire, min, sec));

		bcopy(s->packets[0], &packets[0], sizeof(uint64_t));
		bcopy(s->packets[1], &packets[1], sizeof(uint64_t));
		bcopy(s->bytes[0], &bytes[0], sizeof(uint64_t));
		bcopy(s->bytes[1], &bytes[1], sizeof(uint64_t));
		ND_PRINT((ndo, ", %ju:%ju pkts, %ju:%ju bytes",
		    be64toh(packets[0]), be64toh(packets[1]),
		    be64toh(bytes[0]), be64toh(bytes[1])));
		if (s->anchor != ntohl(-1))
			ND_PRINT((ndo, ", anchor %u", ntohl(s->anchor)));
		if (s->rule != ntohl(-1))
			ND_PRINT((ndo, ", rule %u", ntohl(s->rule)));
	}
	if (vflag > 1) {
		uint64_t id;

		bcopy(&s->id, &id, sizeof(uint64_t));
		ND_PRINT((ndo, "\n\tid: %016jx creatorid: %08x",
		    (uintmax_t )be64toh(id), ntohl(s->creatorid)));
	}
}
Exemple #5
0
void
print_state(struct pfsync_state *s, int opts)
{
	struct pfsync_state_peer *src, *dst;
	struct pfsync_state_key *sk, *nk;
	int min, sec, sidx, didx;

	if (s->direction == PF_OUT) {
		src = &s->src;
		dst = &s->dst;
		sk = &s->key[PF_SK_STACK];
		nk = &s->key[PF_SK_WIRE];
		if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6) 
			sk->port[0] = nk->port[0];
	} else {
		src = &s->dst;
		dst = &s->src;
		sk = &s->key[PF_SK_WIRE];
		nk = &s->key[PF_SK_STACK];
		if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6) 
			sk->port[1] = nk->port[1];
	}
	printf("%s ", s->ifname);
	printf("%s ", ipproto_string(s->proto));

	if (nk->af != sk->af)
		sidx = 1, didx = 0;
	else
		sidx = 0, didx = 1;

	print_host(&nk->addr[didx], nk->port[didx], nk->af, nk->rdomain, NULL, opts);
	if (nk->af != sk->af || PF_ANEQ(&nk->addr[1], &sk->addr[1], nk->af) ||
	    nk->port[1] != sk->port[1]) {
		printf(" (");
		print_host(&sk->addr[1], sk->port[1], sk->af, sk->rdomain,
		    NULL, opts);
		printf(")");
	}
	if (s->direction == PF_OUT)
		printf(" -> ");
	else
		printf(" <- ");
	print_host(&nk->addr[sidx], nk->port[sidx], nk->af, nk->rdomain, NULL,
	    opts);
	if (nk->af != sk->af || PF_ANEQ(&nk->addr[0], &sk->addr[0], nk->af) ||
	    nk->port[0] != sk->port[0]) {
		printf(" (");
		print_host(&sk->addr[0], sk->port[0], sk->af, sk->rdomain, NULL,
		    opts);
		printf(")");
	}

	printf("    ");
	if (s->proto == IPPROTO_TCP) {
		if (src->state <= TCPS_TIME_WAIT &&
		    dst->state <= TCPS_TIME_WAIT)
			printf("\n   %s:%s", tcpstates[src->state],
			    tcpstates[dst->state]);
		else if (src->state == PF_TCPS_PROXY_SRC ||
		    dst->state == PF_TCPS_PROXY_SRC)
			printf("\n   PROXY:SRC");
		else if (src->state == PF_TCPS_PROXY_DST ||
		    dst->state == PF_TCPS_PROXY_DST)
			printf("\n   PROXY:DST");
		else
			printf("\n   <BAD STATE LEVELS %u:%u>",
			    src->state, dst->state);
		if (opts & PF_OPT_VERBOSE) {
			printf("\n   ");
			print_seq(src);
			if (src->wscale && dst->wscale)
				printf(" wscale %u",
				    src->wscale & PF_WSCALE_MASK);
			printf("  ");
			print_seq(dst);
			if (src->wscale && dst->wscale)
				printf(" wscale %u",
				    dst->wscale & PF_WSCALE_MASK);
		}
	} else if (s->proto == IPPROTO_UDP && src->state < PFUDPS_NSTATES &&
	    dst->state < PFUDPS_NSTATES) {
		const char *states[] = PFUDPS_NAMES;

		printf("   %s:%s", states[src->state], states[dst->state]);
	} else if (s->proto != IPPROTO_ICMP && src->state < PFOTHERS_NSTATES &&
	    dst->state < PFOTHERS_NSTATES) {
		/* XXX ICMP doesn't really have state levels */
		const char *states[] = PFOTHERS_NAMES;

		printf("   %s:%s", states[src->state], states[dst->state]);
	} else {
		printf("   %u:%u", src->state, dst->state);
	}

	if (opts & PF_OPT_VERBOSE) {
		u_int64_t packets[2];
		u_int64_t bytes[2];
		u_int32_t creation = ntohl(s->creation);
		u_int32_t expire = ntohl(s->expire);

		sec = creation % 60;
		creation /= 60;
		min = creation % 60;
		creation /= 60;
		printf("\n   age %.2u:%.2u:%.2u", creation, min, sec);
		sec = expire % 60;
		expire /= 60;
		min = expire % 60;
		expire /= 60;
		printf(", expires in %.2u:%.2u:%.2u", expire, min, sec);

		bcopy(s->packets[0], &packets[0], sizeof(u_int64_t));
		bcopy(s->packets[1], &packets[1], sizeof(u_int64_t));
		bcopy(s->bytes[0], &bytes[0], sizeof(u_int64_t));
		bcopy(s->bytes[1], &bytes[1], sizeof(u_int64_t));
		printf(", %llu:%llu pkts, %llu:%llu bytes",
		    betoh64(packets[0]),
		    betoh64(packets[1]),
		    betoh64(bytes[0]),
		    betoh64(bytes[1]));
		if (s->anchor != -1)
			printf(", anchor %u", ntohl(s->anchor));
		if (s->rule != -1)
			printf(", rule %u", ntohl(s->rule));
	}
	if (opts & PF_OPT_VERBOSE2) {
		u_int64_t id;

		bcopy(&s->id, &id, sizeof(u_int64_t));
		printf("\n   id: %016llx creatorid: %08x",
		    betoh64(id), ntohl(s->creatorid));
	}
}
Exemple #6
0
void
print_state(struct pf_state *s, int opts)
{
    struct pf_state_peer *src, *dst;
    struct protoent *p;
    u_int8_t hrs, min, sec;

    if (s->direction == PF_OUT) {
        src = &s->src;
        dst = &s->dst;
    } else {
        src = &s->dst;
        dst = &s->src;
    }
    if ((p = getprotobynumber(s->proto)) != NULL)
        printf("%s ", p->p_name);
    else
        printf("%u ", s->proto);
    if (PF_ANEQ(&s->lan.addr, &s->gwy.addr, s->af) ||
            (s->lan.port != s->gwy.port)) {
        print_host(&s->lan, s->af);
        if (s->direction == PF_OUT)
            printf(" -> ");
        else
            printf(" <- ");
    }
    print_host(&s->gwy, s->af);
    if (s->direction == PF_OUT)
        printf(" -> ");
    else
        printf(" <- ");
    print_host(&s->ext, s->af);

    printf("    ");
    if (s->proto == IPPROTO_TCP) {
        if (src->state <= TCPS_TIME_WAIT &&
                dst->state <= TCPS_TIME_WAIT) {
            printf("   %s:%s\n", tcpstates[src->state],
                   tcpstates[dst->state]);
        } else {
            printf("   <BAD STATE LEVELS>\n");
        }
        if (opts & PF_OPT_VERBOSE) {
            printf("   ");
            print_seq(src);
            printf("  ");
            print_seq(dst);
            printf("\n");
        }
    } else {
        printf("   %u:%u\n", src->state, dst->state);
    }

    if (opts & PF_OPT_VERBOSE) {
        sec = s->creation % 60;
        s->creation /= 60;
        min = s->creation % 60;
        s->creation /= 60;
        hrs = s->creation;
        printf("   age %.2u:%.2u:%.2u", hrs, min, sec);
        sec = s->expire % 60;
        s->expire /= 60;
        min = s->expire % 60;
        s->expire /= 60;
        hrs = s->expire;
        printf(", expires in %.2u:%.2u:%.2u", hrs, min, sec);
        printf(", %u pkts, %u bytes\n", s->packets, s->bytes);
    }
}