/* Print all ATM PCBs */

#include <sys/param.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netnatm/natm.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>

size_t needed;
char *buf, *beg, *lim;
int mib0[4] = { CTL_NET, AF_NATM, PROTO_NATMAAL0, NATMAAL0CTL_PCBS };
int mib5[4] = { CTL_NET, AF_NATM, PROTO_NATMAAL5, NATMAAL5CTL_PCBS };
struct natm_usrpcb *pp;
struct in_addr *a;

main() {
	if (sysctl(mib0, 4, NULL, &needed, NULL, 0) < 0) {
		perror("sysctl0");
		exit(1);
	}
	if (needed == 0) {
		printf("empty AAL0 PCB list\n");
		goto dump5;
	} else
		printf("AAL0 PCB list:\n");
	if ((buf = malloc(needed)) == NULL) {
		fprintf(stderr, "malloc0 failed\n");
		exit(1);
	}
	if (sysctl(mib0, 4, buf, &needed, NULL, 0) < 0) {
		perror("sysctl0'");
		exit(1);
	}
	beg = buf;
	lim = buf + needed;

	while (buf < lim) {
		char v[64];

		pp = (struct natm_usrpcb *)buf;
		a = (struct in_addr *)&pp->addr.s6_addr[12];
		printf("\tif=%s %d vpi/vci=%d/%d flag=%d ref=%d addr=%s\n",
		       pp->ifname, pp->phflg,
		       pp->vpi, pp->vci,
		       pp->flags, pp->refcnt,
		       IN6_IS_ADDR_V4MAPPED(&pp->addr) ? inet_ntoa(*a) :
			inet_ntop(AF_INET6, &pp->addr, v, sizeof(v)));
		buf += sizeof(*pp);
	}
	if (buf != lim) {
		fprintf(stderr, "buffer0 mismatch\n");
		exit(1);
	}
	free(beg);

    dump5:
	if (sysctl(mib5, 4, NULL, &needed, NULL, 0) < 0) {
		perror("sysctl5");
		exit(1);
	}
	if (needed == 0) {
		printf("empty AAL5 PCB list\n");
		exit(0);
	} else
		printf("AAL5 PCB list:\n");
	if ((buf = malloc(needed)) == NULL) {
		fprintf(stderr, "malloc5 failed\n");
		exit(1);
	}
	if (sysctl(mib5, 4, buf, &needed, NULL, 0) < 0) {
		perror("sysctl5'");
		exit(1);
	}
	lim = buf + needed;

	while (buf < lim) {
		char v[64];

		pp = (struct natm_usrpcb *)buf;
		a = (struct in_addr *)&pp->addr.s6_addr[12];
		printf("\tif=%s %d vpi/vci=%d/%d flag=%d ref=%d addr=%s\n",
		       pp->ifname, pp->phflg,
		       pp->vpi, pp->vci,
		       pp->flags, pp->refcnt,
		       IN6_IS_ADDR_V4MAPPED(&pp->addr) ? inet_ntoa(*a) :
			inet_ntop(AF_INET6, &pp->addr, v, sizeof(v)));
		buf += sizeof(*pp);
	}
	if (buf != lim) {
		fprintf(stderr, "buffer5 mismatch\n");
		exit(1);
	}
	exit(0);
}

