summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/netinet/in_pcb.c103
-rw-r--r--sys/netinet/in_pcb.h5
-rw-r--r--sys/netinet/tcp_subr.c65
-rw-r--r--sys/netinet/tcp_timewait.c65
-rw-r--r--sys/netinet/tcp_var.h1
-rw-r--r--sys/netinet/udp_usrreq.c29
6 files changed, 72 insertions, 196 deletions
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 0a8e95238cd1..d87b2a8cce9b 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -62,8 +62,6 @@
#include <netinet/in_pcb.h>
#include <netinet/in_var.h>
#include <netinet/ip_var.h>
-#include <netinet/tcp.h>
-#include <netinet/tcp_var.h>
#ifdef INET6
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
@@ -657,110 +655,27 @@ in_setpeeraddr(so, nam)
return 0;
}
-/*
- * Pass some notification to all connections of a protocol
- * associated with address dst. The local address and/or port numbers
- * may be specified to limit the search. The "usual action" will be
- * taken, depending on the ctlinput cmd. The caller must filter any
- * cmds that are uninteresting (e.g., no error in the map).
- * Call the protocol specific routine (if any) to report
- * any errors for each matching socket.
- *
- * If tcp_seq_check != 0 it also checks if tcp_sequence is
- * a valid TCP sequence number for the session.
- */
void
-in_pcbnotify(head, dst, fport_arg, laddr, lport_arg, cmd, notify, tcp_sequence, tcp_seq_check)
+in_pcbnotifyall(head, faddr, errno, notify)
struct inpcbhead *head;
- struct sockaddr *dst;
- u_int fport_arg, lport_arg;
- struct in_addr laddr;
- int cmd;
- void (*notify) __P((struct inpcb *, int));
- u_int32_t tcp_sequence;
- int tcp_seq_check;
-{
- register struct inpcb *inp, *oinp;
struct in_addr faddr;
- u_short fport = fport_arg, lport = lport_arg;
- int errno, s;
-
- if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET)
- return;
- faddr = ((struct sockaddr_in *)dst)->sin_addr;
- if (faddr.s_addr == INADDR_ANY)
- return;
-
- errno = inetctlerrmap[cmd];
- s = splnet();
- for (inp = LIST_FIRST(head); inp != NULL;) {
-#ifdef INET6
- if ((inp->inp_vflag & INP_IPV4) == 0) {
- inp = LIST_NEXT(inp, inp_list);
- continue;
- }
-#endif
- if (inp->inp_faddr.s_addr != faddr.s_addr ||
- inp->inp_socket == 0 || inp->inp_lport != lport ||
- inp->inp_laddr.s_addr != laddr.s_addr ||
- inp->inp_fport != fport) {
- inp = LIST_NEXT(inp, inp_list);
- continue;
- }
- /*
- * If tcp_seq_check is set, then skip sessions where
- * the sequence number is not one of a unacknowledged
- * packet.
- *
- * If it doesn't match, we break the loop, as only a
- * single session can match on src/dst ip addresses
- * and TCP port numbers.
- */
- if ((tcp_seq_check == 1) && (tcp_seq_vs_sess(inp, tcp_sequence) == 0))
- break;
- oinp = inp;
- inp = LIST_NEXT(inp, inp_list);
- if (notify)
- (*notify)(oinp, errno);
- }
- splx(s);
-}
-
-void
-in_pcbnotifyall(head, dst, cmd, notify)
- struct inpcbhead *head;
- struct sockaddr *dst;
- int cmd;
+ int errno;
void (*notify) __P((struct inpcb *, int));
{
- register struct inpcb *inp, *oinp;
- struct in_addr faddr;
- int errno, s;
-
- if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET)
- return;
- faddr = ((struct sockaddr_in *)dst)->sin_addr;
- if (faddr.s_addr == INADDR_ANY)
- return;
+ struct inpcb *inp, *ninp;
+ int s;
- errno = inetctlerrmap[cmd];
s = splnet();
- for (inp = LIST_FIRST(head); inp != NULL;) {
+ for (inp = LIST_FIRST(head); inp != NULL; inp = ninp) {
+ ninp = LIST_NEXT(inp, inp_list);
#ifdef INET6
- if ((inp->inp_vflag & INP_IPV4) == 0) {
- inp = LIST_NEXT(inp, inp_list);
+ if ((inp->inp_vflag & INP_IPV4) == 0)
continue;
- }
#endif
if (inp->inp_faddr.s_addr != faddr.s_addr ||
- inp->inp_socket == 0) {
- inp = LIST_NEXT(inp, inp_list);
+ inp->inp_socket == NULL)
continue;
- }
- oinp = inp;
- inp = LIST_NEXT(inp, inp_list);
- if (notify)
- (*notify)(oinp, errno);
+ (*notify)(inp, errno);
}
splx(s);
}
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
index 7e4cfbe37517..f4abb4d0a440 100644
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -290,10 +290,7 @@ struct inpcb *
in_pcblookup_hash __P((struct inpcbinfo *,
struct in_addr, u_int, struct in_addr, u_int,
int, struct ifnet *));
-void in_pcbnotify __P((struct inpcbhead *, struct sockaddr *,
- u_int, struct in_addr, u_int, int, void (*)(struct inpcb *, int),
- u_int32_t, int));
-void in_pcbnotifyall __P((struct inpcbhead *, struct sockaddr *,
+void in_pcbnotifyall __P((struct inpcbhead *, struct in_addr,
int, void (*)(struct inpcb *, int)));
void in_pcbrehash __P((struct inpcb *));
int in_setpeeraddr __P((struct socket *so, struct sockaddr **nam));
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index c1505974a4fb..b70d2b5a8817 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -976,41 +976,46 @@ tcp_ctlinput(cmd, sa, vip)
{
struct ip *ip = vip;
struct tcphdr *th;
+ struct in_addr faddr;
+ struct inpcb *inp;
+ struct tcpcb *tp;
void (*notify) __P((struct inpcb *, int)) = tcp_notify;
- tcp_seq tcp_sequence = 0;
- int tcp_seq_check = 0;
+ tcp_seq icmp_seq;
+ int s;
+
+ faddr = ((struct sockaddr_in *)sa)->sin_addr;
+ if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY)
+ return;
if (cmd == PRC_QUENCH)
notify = tcp_quench;
- else if (icmp_may_rst && cmd == PRC_UNREACH_ADMIN_PROHIB && ip) {
- tcp_seq_check = 1;
+ else if (icmp_may_rst && cmd == PRC_UNREACH_ADMIN_PROHIB && ip)
notify = tcp_drop_syn_sent;
- } else if (cmd == PRC_MSGSIZE)
+ else if (cmd == PRC_MSGSIZE)
notify = tcp_mtudisc;
else if (PRC_IS_REDIRECT(cmd)) {
- /*
- * Redirects go to all references to the destination,
- * and use in_rtchange to invalidate the route cache.
- */
ip = 0;
notify = in_rtchange;
} else if (cmd == PRC_HOSTDEAD)
- /*
- * Dead host indications: notify all references to the
- * destination.
- */
ip = 0;
else if ((unsigned)cmd > PRC_NCMDS || inetctlerrmap[cmd] == 0)
return;
if (ip) {
+ s = splnet();
th = (struct tcphdr *)((caddr_t)ip
+ (IP_VHL_HL(ip->ip_vhl) << 2));
- if (tcp_seq_check == 1)
- tcp_sequence = ntohl(th->th_seq);
- in_pcbnotify(&tcb, sa, th->th_dport, ip->ip_src, th->th_sport,
- cmd, notify, tcp_sequence, tcp_seq_check);
+ inp = in_pcblookup_hash(&tcbinfo, faddr, th->th_dport,
+ ip->ip_src, th->th_sport, 0, NULL);
+ if (inp != NULL && inp->inp_socket != NULL) {
+ icmp_seq = htonl(th->th_seq);
+ tp = intotcpcb(inp);
+ if (SEQ_GEQ(icmp_seq, tp->snd_una) &&
+ SEQ_LT(icmp_seq, tp->snd_max))
+ (*notify)(inp, inetctlerrmap[cmd]);
+ }
+ splx(s);
} else
- in_pcbnotifyall(&tcb, sa, cmd, notify);
+ in_pcbnotifyall(&tcb, faddr, inetctlerrmap[cmd], notify);
}
#ifdef INET6
@@ -1097,30 +1102,6 @@ tcp6_ctlinput(cmd, sa, d)
#endif /* INET6 */
/*
- * Check if the supplied TCP sequence number is a sequence number
- * for a sent but unacknowledged packet on the given TCP session.
- */
-int
-tcp_seq_vs_sess(inp, tcp_sequence)
- struct inpcb *inp;
- tcp_seq tcp_sequence;
-{
- struct tcpcb *tp = intotcpcb(inp);
- /*
- * If the sequence number is less than that of the last
- * unacknowledged packet, or greater than that of the
- * last sent, the given sequence number is not that
- * of a sent but unacknowledged packet for this session.
- */
- if (SEQ_LT(tcp_sequence, tp->snd_una) ||
- SEQ_GT(tcp_sequence, tp->snd_max)) {
- return(0);
- } else {
- return(1);
- }
-}
-
-/*
* When a source quench is received, close congestion window
* to one segment. We will gradually open it again as we proceed.
*/
diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c
index c1505974a4fb..b70d2b5a8817 100644
--- a/sys/netinet/tcp_timewait.c
+++ b/sys/netinet/tcp_timewait.c
@@ -976,41 +976,46 @@ tcp_ctlinput(cmd, sa, vip)
{
struct ip *ip = vip;
struct tcphdr *th;
+ struct in_addr faddr;
+ struct inpcb *inp;
+ struct tcpcb *tp;
void (*notify) __P((struct inpcb *, int)) = tcp_notify;
- tcp_seq tcp_sequence = 0;
- int tcp_seq_check = 0;
+ tcp_seq icmp_seq;
+ int s;
+
+ faddr = ((struct sockaddr_in *)sa)->sin_addr;
+ if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY)
+ return;
if (cmd == PRC_QUENCH)
notify = tcp_quench;
- else if (icmp_may_rst && cmd == PRC_UNREACH_ADMIN_PROHIB && ip) {
- tcp_seq_check = 1;
+ else if (icmp_may_rst && cmd == PRC_UNREACH_ADMIN_PROHIB && ip)
notify = tcp_drop_syn_sent;
- } else if (cmd == PRC_MSGSIZE)
+ else if (cmd == PRC_MSGSIZE)
notify = tcp_mtudisc;
else if (PRC_IS_REDIRECT(cmd)) {
- /*
- * Redirects go to all references to the destination,
- * and use in_rtchange to invalidate the route cache.
- */
ip = 0;
notify = in_rtchange;
} else if (cmd == PRC_HOSTDEAD)
- /*
- * Dead host indications: notify all references to the
- * destination.
- */
ip = 0;
else if ((unsigned)cmd > PRC_NCMDS || inetctlerrmap[cmd] == 0)
return;
if (ip) {
+ s = splnet();
th = (struct tcphdr *)((caddr_t)ip
+ (IP_VHL_HL(ip->ip_vhl) << 2));
- if (tcp_seq_check == 1)
- tcp_sequence = ntohl(th->th_seq);
- in_pcbnotify(&tcb, sa, th->th_dport, ip->ip_src, th->th_sport,
- cmd, notify, tcp_sequence, tcp_seq_check);
+ inp = in_pcblookup_hash(&tcbinfo, faddr, th->th_dport,
+ ip->ip_src, th->th_sport, 0, NULL);
+ if (inp != NULL && inp->inp_socket != NULL) {
+ icmp_seq = htonl(th->th_seq);
+ tp = intotcpcb(inp);
+ if (SEQ_GEQ(icmp_seq, tp->snd_una) &&
+ SEQ_LT(icmp_seq, tp->snd_max))
+ (*notify)(inp, inetctlerrmap[cmd]);
+ }
+ splx(s);
} else
- in_pcbnotifyall(&tcb, sa, cmd, notify);
+ in_pcbnotifyall(&tcb, faddr, inetctlerrmap[cmd], notify);
}
#ifdef INET6
@@ -1097,30 +1102,6 @@ tcp6_ctlinput(cmd, sa, d)
#endif /* INET6 */
/*
- * Check if the supplied TCP sequence number is a sequence number
- * for a sent but unacknowledged packet on the given TCP session.
- */
-int
-tcp_seq_vs_sess(inp, tcp_sequence)
- struct inpcb *inp;
- tcp_seq tcp_sequence;
-{
- struct tcpcb *tp = intotcpcb(inp);
- /*
- * If the sequence number is less than that of the last
- * unacknowledged packet, or greater than that of the
- * last sent, the given sequence number is not that
- * of a sent but unacknowledged packet for this session.
- */
- if (SEQ_LT(tcp_sequence, tp->snd_una) ||
- SEQ_GT(tcp_sequence, tp->snd_max)) {
- return(0);
- } else {
- return(1);
- }
-}
-
-/*
* When a source quench is received, close congestion window
* to one segment. We will gradually open it again as we proceed.
*/
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index dc69d3e0c11e..e361caf57756 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -392,7 +392,6 @@ void tcp_mtudisc __P((struct inpcb *, int));
struct tcpcb *
tcp_newtcpcb __P((struct inpcb *));
int tcp_output __P((struct tcpcb *));
-int tcp_seq_vs_sess __P((struct inpcb *, tcp_seq));
void tcp_quench __P((struct inpcb *, int));
void tcp_respond __P((struct tcpcb *, void *,
struct tcphdr *, struct mbuf *, tcp_seq, tcp_seq, int));
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 2e7fe8958857..1dd3eee9f216 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -504,31 +504,34 @@ udp_ctlinput(cmd, sa, vip)
struct sockaddr *sa;
void *vip;
{
- register struct ip *ip = vip;
- register struct udphdr *uh;
+ struct ip *ip = vip;
+ struct udphdr *uh;
void (*notify) __P((struct inpcb *, int)) = udp_notify;
+ struct in_addr faddr;
+ struct inpcb *inp;
+ int s;
+
+ faddr = ((struct sockaddr_in *)sa)->sin_addr;
+ if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY)
+ return;
if (PRC_IS_REDIRECT(cmd)) {
- /*
- * Redirects go to all references to the destination,
- * and use in_rtchange to invalidate the route cache.
- */
ip = 0;
notify = in_rtchange;
} else if (cmd == PRC_HOSTDEAD)
- /*
- * Dead host indications: notify all references to the
- * destination.
- */
ip = 0;
else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0)
return;
if (ip) {
+ s = splnet();
uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
- in_pcbnotify(&udb, sa, uh->uh_dport, ip->ip_src, uh->uh_sport,
- cmd, notify, 0, 0);
+ inp = in_pcblookup_hash(&udbinfo, faddr, uh->uh_dport,
+ ip->ip_src, uh->uh_sport, 0, NULL);
+ if (inp != NULL && inp->inp_socket != NULL)
+ (*notify)(inp, inetctlerrmap[cmd]);
+ splx(s);
} else
- in_pcbnotifyall(&udb, sa, cmd, notify);
+ in_pcbnotifyall(&udb, faddr, inetctlerrmap[cmd], notify);
}
static int