aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/in_proto.c2
-rw-r--r--sys/netinet/tcp_subr.c2
-rw-r--r--sys/netinet/tcp_syncache.c49
-rw-r--r--sys/netinet/tcp_timer.c7
-rw-r--r--sys/netinet/udp_usrreq.c49
-rw-r--r--sys/netinet/udp_var.h1
6 files changed, 76 insertions, 34 deletions
diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c
index e534fdd77635..129dc1cfe892 100644
--- a/sys/netinet/in_proto.c
+++ b/sys/netinet/in_proto.c
@@ -110,6 +110,8 @@ SYSCTL_NODE(_net_inet, IPPROTO_ICMP, icmp, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
"ICMP");
SYSCTL_NODE(_net_inet, IPPROTO_UDP, udp, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
"UDP");
+SYSCTL_NODE(_net_inet, IPPROTO_UDPLITE, udplite, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
+ "UDP-Lite");
SYSCTL_NODE(_net_inet, IPPROTO_TCP, tcp, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
"TCP");
#if defined(SCTP) || defined(SCTP_SUPPORT)
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 6829d2a743f2..81b378f496c9 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -654,7 +654,7 @@ tcp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *inp,
}
}
m->m_pkthdr.tcp_tun_port = port = uh->uh_sport;
- bcopy(th, uh, m->m_len - off);
+ bcopy(th, uh, m->m_len - off - sizeof(struct udphdr));
m->m_len -= sizeof(struct udphdr);
m->m_pkthdr.len -= sizeof(struct udphdr);
/*
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index 1c585378dc5b..713f6a35ad45 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -1056,6 +1056,8 @@ abort:
*
* On syncache_socket() success the newly created socket
* has its underlying inp locked.
+ *
+ * *lsop is updated, if and only if 1 is returned.
*/
int
syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
@@ -1103,12 +1105,14 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
* a valid syncookie.
*/
SCH_UNLOCK(sch);
- if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
log(LOG_DEBUG, "%s; %s: Spurious ACK, "
"segment rejected "
"(syncookies disabled)\n",
s, __func__);
- goto failed;
+ free(s, M_TCPLOG);
+ }
+ return (0);
}
if (sch->sch_last_overflow <
time_uptime - SYNCOOKIE_LIFETIME) {
@@ -1117,12 +1121,14 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
* don't even check for a valid syncookie.
*/
SCH_UNLOCK(sch);
- if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
log(LOG_DEBUG, "%s; %s: Spurious ACK, "
"segment rejected "
"(no syncache entry)\n",
s, __func__);
- goto failed;
+ free(s, M_TCPLOG);
+ }
+ return (0);
}
SCH_UNLOCK(sch);
}
@@ -1135,11 +1141,13 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
sc = &scs;
TCPSTAT_INC(tcps_sc_recvcookie);
} else {
- if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
log(LOG_DEBUG, "%s; %s: Segment failed "
"SYNCOOKIE authentication, segment rejected "
"(probably spoofed)\n", s, __func__);
- goto failed;
+ free(s, M_TCPLOG);
+ }
+ return (0);
}
#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
/* If received ACK has MD5 signature, check it. */
@@ -1167,7 +1175,7 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
/*
* If listening socket requested TCP digests, check that
* received ACK has signature and it is correct.
- * If not, drop the ACK and leave sc entry in th cache,
+ * If not, drop the ACK and leave sc entry in the cache,
* because SYN was received with correct signature.
*/
if (sc->sc_flags & SCF_SIGNATURE) {
@@ -1213,9 +1221,9 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
"%s; %s: SEG.TSval %u < TS.Recent %u, "
"segment dropped\n", s, __func__,
to->to_tsval, sc->sc_tsreflect);
- free(s, M_TCPLOG);
}
SCH_UNLOCK(sch);
+ free(s, M_TCPLOG);
return (-1); /* Do not send RST */
}
@@ -1232,7 +1240,6 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
"expected, segment processed normally\n",
s, __func__);
free(s, M_TCPLOG);
- s = NULL;
}
}
@@ -1319,16 +1326,6 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
if (sc != &scs)
syncache_free(sc);
return (1);
-failed:
- if (sc != NULL) {
- TCPSTATES_DEC(TCPS_SYN_RECEIVED);
- if (sc != &scs)
- syncache_free(sc);
- }
- if (s != NULL)
- free(s, M_TCPLOG);
- *lsop = NULL;
- return (0);
}
static struct socket *
@@ -1390,6 +1387,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
struct tcpcb *tp;
struct socket *rv = NULL;
struct syncache *sc = NULL;
+ struct ucred *cred;
struct syncache_head *sch;
struct mbuf *ipopts = NULL;
u_int ltflags;
@@ -1418,6 +1416,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
*/
KASSERT(SOLISTENING(so), ("%s: %p not listening", __func__, so));
tp = sototcpcb(so);
+ cred = V_tcp_syncache.see_other ? NULL : crhold(so->so_cred);
#ifdef INET6
if (inc->inc_flags & INC_ISIPV6) {
@@ -1646,16 +1645,16 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
/*
* sc_cred is only used in syncache_pcblist() to list TCP endpoints in
* TCPS_SYN_RECEIVED state when V_tcp_syncache.see_other is false.
- * Therefore, store the credentials and take a reference count only
- * when needed:
+ * Therefore, store the credentials only when needed:
* - sc is allocated from the zone and not using the on stack instance.
* - the sysctl variable net.inet.tcp.syncache.see_other is false.
* The reference count is decremented when a zone allocated sc is
* freed in syncache_free().
*/
- if (sc != &scs && !V_tcp_syncache.see_other)
- sc->sc_cred = crhold(so->so_cred);
- else
+ if (sc != &scs && !V_tcp_syncache.see_other) {
+ sc->sc_cred = cred;
+ cred = NULL;
+ } else
sc->sc_cred = NULL;
sc->sc_port = port;
sc->sc_ipopts = ipopts;
@@ -1793,6 +1792,8 @@ donenoprobe:
tcp_fastopen_decrement_counter(tfo_pending);
tfo_expanded:
+ if (cred != NULL)
+ crfree(cred);
if (sc == NULL || sc == &scs) {
#ifdef MAC
mac_syncache_destroy(&maclabel);
diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c
index 65a9fbc84ff7..1c687e94bb4a 100644
--- a/sys/netinet/tcp_timer.c
+++ b/sys/netinet/tcp_timer.c
@@ -515,9 +515,12 @@ tcp_timer_persist(struct tcpcb *tp)
if (progdrop || (tp->t_rxtshift >= V_tcp_retries &&
(ticks - tp->t_rcvtime >= tcp_maxpersistidle ||
ticks - tp->t_rcvtime >= TCP_REXMTVAL(tp) * tcp_totbackoff))) {
- if (!progdrop)
+ if (progdrop) {
+ tcp_log_end_status(tp, TCP_EI_STATUS_PROGRESS);
+ } else {
TCPSTAT_INC(tcps_persistdrop);
- tcp_log_end_status(tp, TCP_EI_STATUS_PERSIST_MAX);
+ tcp_log_end_status(tp, TCP_EI_STATUS_PERSIST_MAX);
+ }
goto dropit;
}
/*
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index f44bd1838d07..a1000dadf583 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -786,7 +786,8 @@ udplite_ctlinput(struct icmp *icmp)
static int
udp_pcblist(SYSCTL_HANDLER_ARGS)
{
- struct inpcb_iterator inpi = INP_ALL_ITERATOR(&V_udbinfo,
+ struct inpcbinfo *pcbinfo = udp_get_inpcbinfo(arg2);
+ struct inpcb_iterator inpi = INP_ALL_ITERATOR(pcbinfo,
INPLOOKUP_RLOCKPCB);
struct xinpgen xig;
struct inpcb *inp;
@@ -798,7 +799,7 @@ udp_pcblist(SYSCTL_HANDLER_ARGS)
if (req->oldptr == 0) {
int n;
- n = V_udbinfo.ipi_count;
+ n = pcbinfo->ipi_count;
n += imax(n / 8, 10);
req->oldidx = 2 * (sizeof xig) + n * sizeof(struct xinpcb);
return (0);
@@ -809,8 +810,8 @@ udp_pcblist(SYSCTL_HANDLER_ARGS)
bzero(&xig, sizeof(xig));
xig.xig_len = sizeof xig;
- xig.xig_count = V_udbinfo.ipi_count;
- xig.xig_gen = V_udbinfo.ipi_gencnt;
+ xig.xig_count = pcbinfo->ipi_count;
+ xig.xig_gen = pcbinfo->ipi_gencnt;
xig.xig_sogen = so_gencnt;
error = SYSCTL_OUT(req, &xig, sizeof xig);
if (error)
@@ -837,9 +838,9 @@ udp_pcblist(SYSCTL_HANDLER_ARGS)
* that something happened while we were processing this
* request, and it might be necessary to retry.
*/
- xig.xig_gen = V_udbinfo.ipi_gencnt;
+ xig.xig_gen = pcbinfo->ipi_gencnt;
xig.xig_sogen = so_gencnt;
- xig.xig_count = V_udbinfo.ipi_count;
+ xig.xig_count = pcbinfo->ipi_count;
error = SYSCTL_OUT(req, &xig, sizeof xig);
}
@@ -847,10 +848,15 @@ udp_pcblist(SYSCTL_HANDLER_ARGS)
}
SYSCTL_PROC(_net_inet_udp, UDPCTL_PCBLIST, pcblist,
- CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
+ CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, IPPROTO_UDP,
udp_pcblist, "S,xinpcb",
"List of active UDP sockets");
+SYSCTL_PROC(_net_inet_udplite, OID_AUTO, pcblist,
+ CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, IPPROTO_UDPLITE,
+ udp_pcblist, "S,xinpcb",
+ "List of active UDP-Lite sockets");
+
#ifdef INET
static int
udp_getcred(SYSCTL_HANDLER_ARGS)
@@ -1140,7 +1146,19 @@ udp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
else
INP_RLOCK(inp);
NET_EPOCH_ENTER(et);
+#ifdef INET6
+ if ((flags & PRUS_IPV6) != 0) {
+ if ((inp->in6p_outputopts != NULL) &&
+ (inp->in6p_outputopts->ip6po_tclass != -1))
+ tos = (u_char)inp->in6p_outputopts->ip6po_tclass;
+ else
+ tos = 0;
+ } else {
+ tos = inp->inp_ip_tos;
+ }
+#else
tos = inp->inp_ip_tos;
+#endif
if (control != NULL) {
/*
* XXX: Currently, we assume all the optional information is
@@ -1164,6 +1182,23 @@ udp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
error = udp_v4mapped_pktinfo(cm, &src, inp, flags);
if (error != 0)
break;
+ if (((flags & PRUS_IPV6) != 0) &&
+ (cm->cmsg_level == IPPROTO_IPV6) &&
+ (cm->cmsg_type == IPV6_TCLASS)) {
+ int tclass;
+
+ if (cm->cmsg_len != CMSG_LEN(sizeof(int))) {
+ error = EINVAL;
+ break;
+ }
+ tclass = *(int *)CMSG_DATA(cm);
+ if (tclass < -1 || tclass > 255) {
+ error = EINVAL;
+ break;
+ }
+ if (tclass != -1)
+ tos = (u_char)tclass;
+ }
#endif
if (cm->cmsg_level != IPPROTO_IP)
continue;
diff --git a/sys/netinet/udp_var.h b/sys/netinet/udp_var.h
index 51272e7c9349..569b7b8d5240 100644
--- a/sys/netinet/udp_var.h
+++ b/sys/netinet/udp_var.h
@@ -141,6 +141,7 @@ void kmod_udpstat_inc(int statnum);
kmod_udpstat_inc(offsetof(struct udpstat, name) / sizeof(uint64_t))
SYSCTL_DECL(_net_inet_udp);
+SYSCTL_DECL(_net_inet_udplite);
VNET_DECLARE(struct inpcbinfo, udbinfo);
VNET_DECLARE(struct inpcbinfo, ulitecbinfo);