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
This commit is contained in:
Michael Tuexen 2015-06-13 20:05:20 +00:00
parent 7e80c6b0e2
commit e6f718c750
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=284353

View File

@ -84,6 +84,11 @@ static int *ports;
#define SET_PORT(p) do { ports[p / INT_BIT] |= 1 << (p % INT_BIT); } while (0) #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))) #define CHK_PORT(p) (ports[p / INT_BIT] & (1 << (p % INT_BIT)))
struct addr {
struct sockaddr_storage address;
struct addr *next;
};
struct sock { struct sock {
void *socket; void *socket;
void *pcb; void *pcb;
@ -92,8 +97,8 @@ struct sock {
int family; int family;
int proto; int proto;
const char *protoname; const char *protoname;
struct sockaddr_storage laddr; struct addr *laddr;
struct sockaddr_storage faddr; struct addr *faddr;
struct sock *next; struct sock *next;
}; };
@ -257,6 +262,7 @@ gather_inet(int proto)
struct inpcb *inp; struct inpcb *inp;
struct xsocket *so; struct xsocket *so;
struct sock *sock; struct sock *sock;
struct addr *laddr, *faddr;
const char *varname, *protoname; const char *varname, *protoname;
size_t len, bufsize; size_t len, bufsize;
void *buf; void *buf;
@ -368,21 +374,29 @@ gather_inet(int proto)
} }
if ((sock = calloc(1, sizeof *sock)) == NULL) if ((sock = calloc(1, sizeof *sock)) == NULL)
err(1, "malloc()"); 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->socket = so->xso_so;
sock->proto = proto; sock->proto = proto;
if (inp->inp_vflag & INP_IPV4) { if (inp->inp_vflag & INP_IPV4) {
sock->family = AF_INET; sock->family = AF_INET;
sockaddr(&sock->laddr, sock->family, sockaddr(&laddr->address, sock->family,
&inp->inp_laddr, inp->inp_lport); &inp->inp_laddr, inp->inp_lport);
sockaddr(&sock->faddr, sock->family, sockaddr(&faddr->address, sock->family,
&inp->inp_faddr, inp->inp_fport); &inp->inp_faddr, inp->inp_fport);
} else if (inp->inp_vflag & INP_IPV6) { } else if (inp->inp_vflag & INP_IPV6) {
sock->family = AF_INET6; sock->family = AF_INET6;
sockaddr(&sock->laddr, sock->family, sockaddr(&laddr->address, sock->family,
&inp->in6p_laddr, inp->inp_lport); &inp->in6p_laddr, inp->inp_lport);
sockaddr(&sock->faddr, sock->family, sockaddr(&faddr->address, sock->family,
&inp->in6p_faddr, inp->inp_fport); &inp->in6p_faddr, inp->inp_fport);
} }
laddr->next = NULL;
faddr->next = NULL;
sock->laddr = laddr;
sock->faddr = faddr;
sock->vflag = inp->inp_vflag; sock->vflag = inp->inp_vflag;
sock->protoname = protoname; sock->protoname = protoname;
hash = (int)((uintptr_t)sock->socket % HASHSIZE); hash = (int)((uintptr_t)sock->socket % HASHSIZE);
@ -399,6 +413,7 @@ gather_unix(int proto)
struct xunpgen *xug, *exug; struct xunpgen *xug, *exug;
struct xunpcb *xup; struct xunpcb *xup;
struct sock *sock; struct sock *sock;
struct addr *laddr, *faddr;
const char *varname, *protoname; const char *varname, *protoname;
size_t len, bufsize; size_t len, bufsize;
void *buf; void *buf;
@ -457,16 +472,24 @@ gather_unix(int proto)
continue; continue;
if ((sock = calloc(1, sizeof *sock)) == NULL) if ((sock = calloc(1, sizeof *sock)) == NULL)
err(1, "malloc()"); 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->socket = xup->xu_socket.xso_so;
sock->pcb = xup->xu_unpp; sock->pcb = xup->xu_unpp;
sock->proto = proto; sock->proto = proto;
sock->family = AF_UNIX; sock->family = AF_UNIX;
sock->protoname = protoname; sock->protoname = protoname;
if (xup->xu_unp.unp_addr != NULL) if (xup->xu_unp.unp_addr != NULL)
sock->laddr = laddr->address =
*(struct sockaddr_storage *)(void *)&xup->xu_addr; *(struct sockaddr_storage *)(void *)&xup->xu_addr;
else if (xup->xu_unp.unp_conn != NULL) 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); hash = (int)((uintptr_t)sock->socket % HASHSIZE);
sock->next = sockhash[hash]; sock->next = sockhash[hash];
sockhash[hash] = sock; sockhash[hash] = sock;
@ -575,23 +598,28 @@ static int
check_ports(struct sock *s) check_ports(struct sock *s)
{ {
int port; int port;
struct addr *addr;
if (ports == NULL) if (ports == NULL)
return (1); return (1);
if ((s->family != AF_INET) && (s->family != AF_INET6)) if ((s->family != AF_INET) && (s->family != AF_INET6))
return (1); return (1);
if (s->family == AF_INET) for (addr = s->laddr; addr != NULL; addr = addr->next) {
port = ntohs(((struct sockaddr_in *)(&s->laddr))->sin_port); if (addr->address.ss_family == AF_INET)
else port = ntohs(((struct sockaddr_in *)(&addr->address))->sin_port);
port = ntohs(((struct sockaddr_in6 *)(&s->laddr))->sin6_port); else
if (CHK_PORT(port)) port = ntohs(((struct sockaddr_in6 *)(&addr->address))->sin6_port);
return (1); if (CHK_PORT(port))
if (s->family == AF_INET) return (1);
port = ntohs(((struct sockaddr_in *)(&s->faddr))->sin_port); }
else for (addr = s->faddr; addr != NULL; addr = addr->next) {
port = ntohs(((struct sockaddr_in6 *)(&s->faddr))->sin6_port); if (addr->address.ss_family == AF_INET)
if (CHK_PORT(port)) port = ntohs(((struct sockaddr_in *)&(addr->address))->sin_port);
return (1); else
port = ntohs(((struct sockaddr_in6 *)&(addr->address))->sin6_port);
if (CHK_PORT(port))
return (1);
}
return (0); return (0);
} }
@ -600,6 +628,7 @@ displaysock(struct sock *s, int pos)
{ {
void *p; void *p;
int hash; int hash;
struct addr *laddr, *faddr;
while (pos < 29) while (pos < 29)
pos += xprintf(" "); pos += xprintf(" ");
@ -608,45 +637,65 @@ displaysock(struct sock *s, int pos)
pos += xprintf("4 "); pos += xprintf("4 ");
if (s->vflag & INP_IPV6) if (s->vflag & INP_IPV6)
pos += xprintf("6 "); pos += xprintf("6 ");
while (pos < 36) laddr = s->laddr;
pos += xprintf(" "); faddr = s->faddr;
switch (s->family) { while (laddr != NULL || faddr != NULL) {
case AF_INET: while (pos < 36)
case AF_INET6:
pos += printaddr(&s->laddr);
if (s->family == AF_INET6 && pos >= 58)
pos += xprintf(" "); pos += xprintf(" ");
while (pos < 58) switch (s->family) {
pos += xprintf(" "); case AF_INET:
pos += printaddr(&s->faddr); case AF_INET6:
break; if (laddr != NULL) {
case AF_UNIX: pos += printaddr(&laddr->address);
/* server */ if (s->family == AF_INET6 && pos >= 58)
if (s->laddr.ss_len > 0) { pos += xprintf(" ");
pos += printaddr(&s->laddr); }
while (pos < 58)
pos += xprintf(" ");
if (faddr != NULL)
pos += printaddr(&faddr->address);
break; break;
} case AF_UNIX:
/* client */ if ((laddr == NULL) || (faddr == NULL))
p = *(void **)&s->faddr; errx(1, "laddr = %p or faddr = %p is NULL",
if (p == NULL) { (void *)laddr, (void *)faddr);
pos += xprintf("(not connected)"); /* server */
break; if (laddr->address.ss_len > 0) {
} pos += printaddr(&laddr->address);
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; 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();
}
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"); xprintf("\n");
} }