summaryrefslogtreecommitdiffstats
path: root/usr.bin/sockstat
diff options
context:
space:
mode:
authortuexen <tuexen@FreeBSD.org>2015-06-13 20:05:20 +0000
committertuexen <tuexen@FreeBSD.org>2015-06-13 20:05:20 +0000
commit71580aec19d3f3cf7fc42270746e3aa095e68255 (patch)
tree6c8eaf8277dfe8bc622f1b55b8c1d5b6adbbb721 /usr.bin/sockstat
parent300f572dc3341b1c535f7c5f3b29b361b81f3fd0 (diff)
downloadFreeBSD-src-71580aec19d3f3cf7fc42270746e3aa095e68255.zip
FreeBSD-src-71580aec19d3f3cf7fc42270746e3aa095e68255.tar.gz
Allow more than one local or remote address per socket. This is needed to
support SCTP (and MPTCP in the future). No functional change for existing protocols. MFC after: 3 days
Diffstat (limited to 'usr.bin/sockstat')
-rw-r--r--usr.bin/sockstat/sockstat.c157
1 files changed, 103 insertions, 54 deletions
diff --git a/usr.bin/sockstat/sockstat.c b/usr.bin/sockstat/sockstat.c
index 2e45ae6..ccd965e 100644
--- a/usr.bin/sockstat/sockstat.c
+++ b/usr.bin/sockstat/sockstat.c
@@ -84,6 +84,11 @@ static int *ports;
#define SET_PORT(p) do { ports[p / INT_BIT] |= 1 << (p % INT_BIT); } while (0)
#define CHK_PORT(p) (ports[p / INT_BIT] & (1 << (p % INT_BIT)))
+struct addr {
+ struct sockaddr_storage address;
+ struct addr *next;
+};
+
struct sock {
void *socket;
void *pcb;
@@ -92,8 +97,8 @@ struct sock {
int family;
int proto;
const char *protoname;
- struct sockaddr_storage laddr;
- struct sockaddr_storage faddr;
+ struct addr *laddr;
+ struct addr *faddr;
struct sock *next;
};
@@ -257,6 +262,7 @@ gather_inet(int proto)
struct inpcb *inp;
struct xsocket *so;
struct sock *sock;
+ struct addr *laddr, *faddr;
const char *varname, *protoname;
size_t len, bufsize;
void *buf;
@@ -368,21 +374,29 @@ gather_inet(int proto)
}
if ((sock = calloc(1, sizeof *sock)) == NULL)
err(1, "malloc()");
+ if ((laddr = calloc(1, sizeof *laddr)) == NULL)
+ err(1, "malloc()");
+ if ((faddr = calloc(1, sizeof *faddr)) == NULL)
+ err(1, "malloc()");
sock->socket = so->xso_so;
sock->proto = proto;
if (inp->inp_vflag & INP_IPV4) {
sock->family = AF_INET;
- sockaddr(&sock->laddr, sock->family,
+ sockaddr(&laddr->address, sock->family,
&inp->inp_laddr, inp->inp_lport);
- sockaddr(&sock->faddr, sock->family,
+ sockaddr(&faddr->address, sock->family,
&inp->inp_faddr, inp->inp_fport);
} else if (inp->inp_vflag & INP_IPV6) {
sock->family = AF_INET6;
- sockaddr(&sock->laddr, sock->family,
+ sockaddr(&laddr->address, sock->family,
&inp->in6p_laddr, inp->inp_lport);
- sockaddr(&sock->faddr, sock->family,
+ sockaddr(&faddr->address, sock->family,
&inp->in6p_faddr, inp->inp_fport);
}
+ laddr->next = NULL;
+ faddr->next = NULL;
+ sock->laddr = laddr;
+ sock->faddr = faddr;
sock->vflag = inp->inp_vflag;
sock->protoname = protoname;
hash = (int)((uintptr_t)sock->socket % HASHSIZE);
@@ -399,6 +413,7 @@ gather_unix(int proto)
struct xunpgen *xug, *exug;
struct xunpcb *xup;
struct sock *sock;
+ struct addr *laddr, *faddr;
const char *varname, *protoname;
size_t len, bufsize;
void *buf;
@@ -457,16 +472,24 @@ gather_unix(int proto)
continue;
if ((sock = calloc(1, sizeof *sock)) == NULL)
err(1, "malloc()");
+ if ((laddr = calloc(1, sizeof *laddr)) == NULL)
+ err(1, "malloc()");
+ if ((faddr = calloc(1, sizeof *faddr)) == NULL)
+ err(1, "malloc()");
sock->socket = xup->xu_socket.xso_so;
sock->pcb = xup->xu_unpp;
sock->proto = proto;
sock->family = AF_UNIX;
sock->protoname = protoname;
if (xup->xu_unp.unp_addr != NULL)
- sock->laddr =
+ laddr->address =
*(struct sockaddr_storage *)(void *)&xup->xu_addr;
else if (xup->xu_unp.unp_conn != NULL)
- *(void **)&sock->faddr = xup->xu_unp.unp_conn;
+ *(void **)&(faddr->address) = xup->xu_unp.unp_conn;
+ laddr->next = NULL;
+ faddr->next = NULL;
+ sock->laddr = laddr;
+ sock->faddr = faddr;
hash = (int)((uintptr_t)sock->socket % HASHSIZE);
sock->next = sockhash[hash];
sockhash[hash] = sock;
@@ -575,23 +598,28 @@ static int
check_ports(struct sock *s)
{
int port;
+ struct addr *addr;
if (ports == NULL)
return (1);
if ((s->family != AF_INET) && (s->family != AF_INET6))
return (1);
- if (s->family == AF_INET)
- port = ntohs(((struct sockaddr_in *)(&s->laddr))->sin_port);
- else
- port = ntohs(((struct sockaddr_in6 *)(&s->laddr))->sin6_port);
- if (CHK_PORT(port))
- return (1);
- if (s->family == AF_INET)
- port = ntohs(((struct sockaddr_in *)(&s->faddr))->sin_port);
- else
- port = ntohs(((struct sockaddr_in6 *)(&s->faddr))->sin6_port);
- if (CHK_PORT(port))
- return (1);
+ for (addr = s->laddr; addr != NULL; addr = addr->next) {
+ if (addr->address.ss_family == AF_INET)
+ port = ntohs(((struct sockaddr_in *)(&addr->address))->sin_port);
+ else
+ port = ntohs(((struct sockaddr_in6 *)(&addr->address))->sin6_port);
+ if (CHK_PORT(port))
+ return (1);
+ }
+ for (addr = s->faddr; addr != NULL; addr = addr->next) {
+ if (addr->address.ss_family == AF_INET)
+ port = ntohs(((struct sockaddr_in *)&(addr->address))->sin_port);
+ else
+ port = ntohs(((struct sockaddr_in6 *)&(addr->address))->sin6_port);
+ if (CHK_PORT(port))
+ return (1);
+ }
return (0);
}
@@ -600,6 +628,7 @@ displaysock(struct sock *s, int pos)
{
void *p;
int hash;
+ struct addr *laddr, *faddr;
while (pos < 29)
pos += xprintf(" ");
@@ -608,45 +637,65 @@ displaysock(struct sock *s, int pos)
pos += xprintf("4 ");
if (s->vflag & INP_IPV6)
pos += xprintf("6 ");
- while (pos < 36)
- pos += xprintf(" ");
- switch (s->family) {
- case AF_INET:
- case AF_INET6:
- pos += printaddr(&s->laddr);
- if (s->family == AF_INET6 && pos >= 58)
+ laddr = s->laddr;
+ faddr = s->faddr;
+ while (laddr != NULL || faddr != NULL) {
+ while (pos < 36)
pos += xprintf(" ");
- while (pos < 58)
- pos += xprintf(" ");
- pos += printaddr(&s->faddr);
- break;
- case AF_UNIX:
- /* server */
- if (s->laddr.ss_len > 0) {
- pos += printaddr(&s->laddr);
+ switch (s->family) {
+ case AF_INET:
+ case AF_INET6:
+ if (laddr != NULL) {
+ pos += printaddr(&laddr->address);
+ if (s->family == AF_INET6 && pos >= 58)
+ pos += xprintf(" ");
+ }
+ while (pos < 58)
+ pos += xprintf(" ");
+ if (faddr != NULL)
+ pos += printaddr(&faddr->address);
break;
- }
- /* client */
- p = *(void **)&s->faddr;
- if (p == NULL) {
- pos += xprintf("(not connected)");
+ case AF_UNIX:
+ if ((laddr == NULL) || (faddr == NULL))
+ errx(1, "laddr = %p or faddr = %p is NULL",
+ (void *)laddr, (void *)faddr);
+ /* server */
+ if (laddr->address.ss_len > 0) {
+ pos += printaddr(&laddr->address);
+ break;
+ }
+ /* client */
+ p = *(void **)&(faddr->address);
+ if (p == NULL) {
+ pos += xprintf("(not connected)");
+ break;
+ }
+ pos += xprintf("-> ");
+ for (hash = 0; hash < HASHSIZE; ++hash) {
+ for (s = sockhash[hash]; s != NULL; s = s->next)
+ if (s->pcb == p)
+ break;
+ if (s != NULL)
+ break;
+ }
+ if (s == NULL ||
+ s->laddr == NULL ||
+ s->laddr->address.ss_len == 0)
+ pos += xprintf("??");
+ else
+ pos += printaddr(&s->laddr->address);
break;
+ default:
+ abort();
}
- pos += xprintf("-> ");
- for (hash = 0; hash < HASHSIZE; ++hash) {
- for (s = sockhash[hash]; s != NULL; s = s->next)
- if (s->pcb == p)
- break;
- if (s != NULL)
- break;
+ if (laddr != NULL)
+ laddr = laddr->next;
+ if (faddr != NULL)
+ faddr = faddr->next;
+ if ((laddr != NULL) || (faddr != NULL)) {
+ xprintf("\n");
+ pos = 0;
}
- if (s == NULL || s->laddr.ss_len == 0)
- pos += xprintf("??");
- else
- pos += printaddr(&s->laddr);
- break;
- default:
- abort();
}
xprintf("\n");
}
OpenPOWER on IntegriCloud