mirror of
https://github.com/freebsd/freebsd-src
synced 2024-09-06 17:18:32 +00:00
o Add handling of an IPv4-mapped IPv6 address.
o Use SYSCTL_IN() macro instead of direct call of copyin(9). Submitted by: ume o Move sysctl_drop() implementation to sys/netinet/tcp_subr.c where most of tcp sysctls live. o There are net.inet[6].tcp[6].getcred sysctls already, no needs in a separate struct tcp_ident_mapping. Suggested by: ume
This commit is contained in:
parent
9271f7b6d5
commit
9945c0e21f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=141886
|
@ -2119,3 +2119,101 @@ tcp_signature_compute(struct mbuf *m, int off0, int len, int optlen,
|
|||
return (0);
|
||||
}
|
||||
#endif /* TCP_SIGNATURE */
|
||||
|
||||
static int
|
||||
sysctl_drop(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
/* addrs[0] is a foreign socket, addrs[1] is a local one. */
|
||||
struct sockaddr_storage addrs[2];
|
||||
struct inpcb *inp;
|
||||
struct tcpcb *tp;
|
||||
struct sockaddr_in *fin, *lin;
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 *fin6, *lin6;
|
||||
struct in6_addr f6, l6;
|
||||
#endif
|
||||
int error;
|
||||
|
||||
inp = NULL;
|
||||
fin = lin = NULL;
|
||||
#ifdef INET6
|
||||
fin6 = lin6 = NULL;
|
||||
#endif
|
||||
error = 0;
|
||||
|
||||
if (req->oldptr != NULL || req->oldlen != 0)
|
||||
return (EINVAL);
|
||||
if (req->newptr == NULL)
|
||||
return (EPERM);
|
||||
if (req->newlen < sizeof(addrs))
|
||||
return (ENOMEM);
|
||||
error = SYSCTL_IN(req, &addrs, sizeof(addrs));
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
switch (addrs[0].ss_family) {
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
fin6 = (struct sockaddr_in6 *)&addrs[0];
|
||||
lin6 = (struct sockaddr_in6 *)&addrs[1];
|
||||
if (fin6->sin6_len != sizeof(struct sockaddr_in6) ||
|
||||
lin6->sin6_len != sizeof(struct sockaddr_in6))
|
||||
return (EINVAL);
|
||||
if (IN6_IS_ADDR_V4MAPPED(&fin6->sin6_addr)) {
|
||||
if (!IN6_IS_ADDR_V4MAPPED(&lin6->sin6_addr))
|
||||
return (EINVAL);
|
||||
in6_sin6_2_sin_in_sock((struct sockaddr *)&addrs[0]);
|
||||
in6_sin6_2_sin_in_sock((struct sockaddr *)&addrs[1]);
|
||||
fin = (struct sockaddr_in *)&addrs[0];
|
||||
lin = (struct sockaddr_in *)&addrs[1];
|
||||
break;
|
||||
}
|
||||
error = in6_embedscope(&f6, fin6, NULL, NULL);
|
||||
if (error)
|
||||
return (EINVAL);
|
||||
error = in6_embedscope(&l6, lin6, NULL, NULL);
|
||||
if (error)
|
||||
return (EINVAL);
|
||||
break;
|
||||
#endif
|
||||
case AF_INET:
|
||||
fin = (struct sockaddr_in *)&addrs[0];
|
||||
lin = (struct sockaddr_in *)&addrs[1];
|
||||
if (fin->sin_len != sizeof(struct sockaddr_in) ||
|
||||
lin->sin_len != sizeof(struct sockaddr_in))
|
||||
return (EINVAL);
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
INP_INFO_WLOCK(&tcbinfo);
|
||||
switch (addrs[0].ss_family) {
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
inp = in6_pcblookup_hash(&tcbinfo, &f6, fin6->sin6_port,
|
||||
&l6, lin6->sin6_port, 0, NULL);
|
||||
break;
|
||||
#endif
|
||||
case AF_INET:
|
||||
inp = in_pcblookup_hash(&tcbinfo, fin->sin_addr, fin->sin_port,
|
||||
lin->sin_addr, lin->sin_port, 0, NULL);
|
||||
break;
|
||||
}
|
||||
if (inp != NULL) {
|
||||
INP_LOCK(inp);
|
||||
if ((tp = intotcpcb(inp)) &&
|
||||
((inp->inp_socket->so_options & SO_ACCEPTCONN) == 0)) {
|
||||
tp = tcp_drop(tp, ECONNABORTED);
|
||||
if (tp != NULL)
|
||||
INP_UNLOCK(inp);
|
||||
} else
|
||||
INP_UNLOCK(inp);
|
||||
} else
|
||||
error = ESRCH;
|
||||
INP_INFO_WUNLOCK(&tcbinfo);
|
||||
return (error);
|
||||
}
|
||||
|
||||
SYSCTL_PROC(_net_inet_tcp, TCPCTL_DROP, drop,
|
||||
CTLTYPE_STRUCT|CTLFLAG_WR|CTLFLAG_SKIP, NULL,
|
||||
0, sysctl_drop, "", "Drop TCP connection");
|
||||
|
|
|
@ -2119,3 +2119,101 @@ tcp_signature_compute(struct mbuf *m, int off0, int len, int optlen,
|
|||
return (0);
|
||||
}
|
||||
#endif /* TCP_SIGNATURE */
|
||||
|
||||
static int
|
||||
sysctl_drop(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
/* addrs[0] is a foreign socket, addrs[1] is a local one. */
|
||||
struct sockaddr_storage addrs[2];
|
||||
struct inpcb *inp;
|
||||
struct tcpcb *tp;
|
||||
struct sockaddr_in *fin, *lin;
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 *fin6, *lin6;
|
||||
struct in6_addr f6, l6;
|
||||
#endif
|
||||
int error;
|
||||
|
||||
inp = NULL;
|
||||
fin = lin = NULL;
|
||||
#ifdef INET6
|
||||
fin6 = lin6 = NULL;
|
||||
#endif
|
||||
error = 0;
|
||||
|
||||
if (req->oldptr != NULL || req->oldlen != 0)
|
||||
return (EINVAL);
|
||||
if (req->newptr == NULL)
|
||||
return (EPERM);
|
||||
if (req->newlen < sizeof(addrs))
|
||||
return (ENOMEM);
|
||||
error = SYSCTL_IN(req, &addrs, sizeof(addrs));
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
switch (addrs[0].ss_family) {
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
fin6 = (struct sockaddr_in6 *)&addrs[0];
|
||||
lin6 = (struct sockaddr_in6 *)&addrs[1];
|
||||
if (fin6->sin6_len != sizeof(struct sockaddr_in6) ||
|
||||
lin6->sin6_len != sizeof(struct sockaddr_in6))
|
||||
return (EINVAL);
|
||||
if (IN6_IS_ADDR_V4MAPPED(&fin6->sin6_addr)) {
|
||||
if (!IN6_IS_ADDR_V4MAPPED(&lin6->sin6_addr))
|
||||
return (EINVAL);
|
||||
in6_sin6_2_sin_in_sock((struct sockaddr *)&addrs[0]);
|
||||
in6_sin6_2_sin_in_sock((struct sockaddr *)&addrs[1]);
|
||||
fin = (struct sockaddr_in *)&addrs[0];
|
||||
lin = (struct sockaddr_in *)&addrs[1];
|
||||
break;
|
||||
}
|
||||
error = in6_embedscope(&f6, fin6, NULL, NULL);
|
||||
if (error)
|
||||
return (EINVAL);
|
||||
error = in6_embedscope(&l6, lin6, NULL, NULL);
|
||||
if (error)
|
||||
return (EINVAL);
|
||||
break;
|
||||
#endif
|
||||
case AF_INET:
|
||||
fin = (struct sockaddr_in *)&addrs[0];
|
||||
lin = (struct sockaddr_in *)&addrs[1];
|
||||
if (fin->sin_len != sizeof(struct sockaddr_in) ||
|
||||
lin->sin_len != sizeof(struct sockaddr_in))
|
||||
return (EINVAL);
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
INP_INFO_WLOCK(&tcbinfo);
|
||||
switch (addrs[0].ss_family) {
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
inp = in6_pcblookup_hash(&tcbinfo, &f6, fin6->sin6_port,
|
||||
&l6, lin6->sin6_port, 0, NULL);
|
||||
break;
|
||||
#endif
|
||||
case AF_INET:
|
||||
inp = in_pcblookup_hash(&tcbinfo, fin->sin_addr, fin->sin_port,
|
||||
lin->sin_addr, lin->sin_port, 0, NULL);
|
||||
break;
|
||||
}
|
||||
if (inp != NULL) {
|
||||
INP_LOCK(inp);
|
||||
if ((tp = intotcpcb(inp)) &&
|
||||
((inp->inp_socket->so_options & SO_ACCEPTCONN) == 0)) {
|
||||
tp = tcp_drop(tp, ECONNABORTED);
|
||||
if (tp != NULL)
|
||||
INP_UNLOCK(inp);
|
||||
} else
|
||||
INP_UNLOCK(inp);
|
||||
} else
|
||||
error = ESRCH;
|
||||
INP_INFO_WUNLOCK(&tcbinfo);
|
||||
return (error);
|
||||
}
|
||||
|
||||
SYSCTL_PROC(_net_inet_tcp, TCPCTL_DROP, drop,
|
||||
CTLTYPE_STRUCT|CTLFLAG_WR|CTLFLAG_SKIP, NULL,
|
||||
0, sysctl_drop, "", "Drop TCP connection");
|
||||
|
|
|
@ -1272,90 +1272,3 @@ tcp_usrclosed(tp)
|
|||
}
|
||||
return (tp);
|
||||
}
|
||||
|
||||
static int
|
||||
sysctl_drop(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct tcp_ident_mapping tir;
|
||||
struct inpcb *inp;
|
||||
struct tcpcb *tp;
|
||||
struct sockaddr_in *fin, *lin;
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 *fin6, *lin6;
|
||||
struct in6_addr f6, l6;
|
||||
#endif
|
||||
int error;
|
||||
|
||||
inp = NULL;
|
||||
fin = lin = NULL;
|
||||
#ifdef INET6
|
||||
fin6 = lin6 = NULL;
|
||||
#endif
|
||||
error = 0;
|
||||
|
||||
if (req->oldptr != NULL || req->oldlen != 0)
|
||||
return (EINVAL);
|
||||
if (req->newptr == NULL)
|
||||
return (EPERM);
|
||||
if (req->newlen < sizeof(tir))
|
||||
return (ENOMEM);
|
||||
if ((error = copyin(req->newptr, &tir, sizeof(tir))) != 0)
|
||||
return (error);
|
||||
|
||||
switch (tir.faddr.ss_family) {
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
fin6 = (struct sockaddr_in6 *)&tir.faddr;
|
||||
lin6 = (struct sockaddr_in6 *)&tir.laddr;
|
||||
if (fin6->sin6_len != sizeof(struct sockaddr_in6) ||
|
||||
lin6->sin6_len != sizeof(struct sockaddr_in6))
|
||||
return (EINVAL);
|
||||
error = in6_embedscope(&f6, fin6, NULL, NULL);
|
||||
if (error)
|
||||
return (EINVAL);
|
||||
error = in6_embedscope(&l6, lin6, NULL, NULL);
|
||||
if (error)
|
||||
return (EINVAL);
|
||||
break;
|
||||
#endif
|
||||
case AF_INET:
|
||||
fin = (struct sockaddr_in *)&tir.faddr;
|
||||
lin = (struct sockaddr_in *)&tir.laddr;
|
||||
if (fin->sin_len != sizeof(struct sockaddr_in) ||
|
||||
lin->sin_len != sizeof(struct sockaddr_in))
|
||||
return (EINVAL);
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
INP_INFO_WLOCK(&tcbinfo);
|
||||
switch (tir.faddr.ss_family) {
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
inp = in6_pcblookup_hash(&tcbinfo, &f6, fin6->sin6_port,
|
||||
&l6, lin6->sin6_port, 0, NULL);
|
||||
break;
|
||||
#endif
|
||||
case AF_INET:
|
||||
inp = in_pcblookup_hash(&tcbinfo, fin->sin_addr, fin->sin_port,
|
||||
lin->sin_addr, lin->sin_port, 0, NULL);
|
||||
break;
|
||||
}
|
||||
if (inp != NULL) {
|
||||
INP_LOCK(inp);
|
||||
if ((tp = intotcpcb(inp)) &&
|
||||
((inp->inp_socket->so_options & SO_ACCEPTCONN) == 0)) {
|
||||
tp = tcp_drop(tp, ECONNABORTED);
|
||||
if (tp != NULL)
|
||||
INP_UNLOCK(inp);
|
||||
} else
|
||||
INP_UNLOCK(inp);
|
||||
} else
|
||||
error = ESRCH;
|
||||
INP_INFO_WUNLOCK(&tcbinfo);
|
||||
return (error);
|
||||
}
|
||||
|
||||
SYSCTL_PROC(_net_inet_tcp, TCPCTL_DROP, drop,
|
||||
CTLTYPE_STRUCT|CTLFLAG_WR|CTLFLAG_SKIP, NULL,
|
||||
0, sysctl_drop, "", "Drop TCP connection");
|
||||
|
|
|
@ -451,11 +451,6 @@ struct xtcpcb {
|
|||
};
|
||||
#endif
|
||||
|
||||
struct tcp_ident_mapping {
|
||||
struct sockaddr_storage faddr, laddr;
|
||||
uid_t euid, ruid;
|
||||
};
|
||||
|
||||
/*
|
||||
* Names for TCP sysctl objects
|
||||
*/
|
||||
|
|
|
@ -38,7 +38,8 @@ int
|
|||
main(int argc, char *argv[])
|
||||
{
|
||||
struct addrinfo hints, *ail, *aif, *laddr, *faddr;
|
||||
struct tcp_ident_mapping tir;
|
||||
/* addrs[0] is a foreign socket, addrs[1] is a local one. */
|
||||
struct sockaddr_storage addrs[2];
|
||||
int mib[] = { CTL_NET, PF_INET, IPPROTO_TCP, TCPCTL_DROP };
|
||||
int gaierr, rval = 0;
|
||||
char fhbuf[NI_MAXHOST], fsbuf[NI_MAXSERV], lhbuf[NI_MAXHOST],
|
||||
|
@ -61,8 +62,8 @@ main(int argc, char *argv[])
|
|||
for (aif = faddr; aif; aif = aif->ai_next) {
|
||||
if (ail->ai_family != aif->ai_family)
|
||||
continue;
|
||||
memcpy(&tir.faddr, aif->ai_addr, aif->ai_addrlen);
|
||||
memcpy(&tir.laddr, ail->ai_addr, ail->ai_addrlen);
|
||||
memcpy(&addrs[0], aif->ai_addr, aif->ai_addrlen);
|
||||
memcpy(&addrs[1], ail->ai_addr, ail->ai_addrlen);
|
||||
if (getnameinfo(aif->ai_addr, aif->ai_addrlen,
|
||||
fhbuf, sizeof(fhbuf),
|
||||
fsbuf, sizeof(fsbuf),
|
||||
|
@ -74,7 +75,7 @@ main(int argc, char *argv[])
|
|||
NI_NUMERICHOST | NI_NUMERICSERV) == -1)
|
||||
err(1, "getnameinfo");
|
||||
if (sysctl(mib, sizeof (mib) / sizeof (int), NULL,
|
||||
NULL, &tir, sizeof(tir)) == -1) {
|
||||
NULL, &addrs, sizeof(addrs)) == -1) {
|
||||
rval = 1;
|
||||
warn("%s %s %s %s", lhbuf, lsbuf, fhbuf, fsbuf);
|
||||
} else
|
||||
|
|
Loading…
Reference in a new issue