summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorhsu <hsu@FreeBSD.org>2002-06-14 08:35:21 +0000
committerhsu <hsu@FreeBSD.org>2002-06-14 08:35:21 +0000
commitabda76de0b81d58e1eb0e275c4e384fe97cca491 (patch)
tree4544f6f0f46695f374bc2a22ee6af0eecc9a671f /sys
parent0c8a9db6f99a60d7dd69784a1c0e0f6d254fdcc3 (diff)
downloadFreeBSD-src-abda76de0b81d58e1eb0e275c4e384fe97cca491.zip
FreeBSD-src-abda76de0b81d58e1eb0e275c4e384fe97cca491.tar.gz
Notify functions can destroy the pcb, so they have to return an
indication of whether this happenned so the calling function knows whether or not to unlock the pcb. Submitted by: Jennifer Yang (yangjihui@yahoo.com) Bug reported by: Sid Carter (sidcarter@symonds.net)
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet/in_pcb.c5
-rw-r--r--sys/netinet/in_pcb.h5
-rw-r--r--sys/netinet/tcp_subr.c39
-rw-r--r--sys/netinet/tcp_timewait.c39
-rw-r--r--sys/netinet/tcp_var.h9
-rw-r--r--sys/netinet/udp_usrreq.c5
-rw-r--r--sys/netinet/udp_var.h3
-rw-r--r--sys/netinet6/in6_pcb.c5
-rw-r--r--sys/netinet6/in6_pcb.h5
-rw-r--r--sys/netinet6/raw_ip6.c2
-rw-r--r--sys/netinet6/udp6_usrreq.c2
11 files changed, 73 insertions, 46 deletions
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 2c539b3..744cfc2 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -669,7 +669,7 @@ in_pcbnotifyall(pcbinfo, faddr, errno, notify)
struct inpcbinfo *pcbinfo;
struct in_addr faddr;
int errno;
- void (*notify)(struct inpcb *, int);
+ struct inpcb *(*notify)(struct inpcb *, int);
{
struct inpcb *inp, *ninp;
struct inpcbhead *head;
@@ -777,7 +777,7 @@ in_losing(inp)
* After a routing change, flush old routing
* and allocate a (hopefully) better one.
*/
-void
+struct inpcb *
in_rtchange(inp, errno)
register struct inpcb *inp;
int errno;
@@ -790,6 +790,7 @@ in_rtchange(inp, errno)
* output is attempted.
*/
}
+ return inp;
}
/*
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
index fa3f29e..1d9a21d 100644
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -324,7 +324,8 @@ extern int ipport_hilastauto;
void in_pcbpurgeif0(struct inpcbinfo *, struct ifnet *);
void in_losing(struct inpcb *);
-void in_rtchange(struct inpcb *, int);
+struct inpcb *
+ in_rtchange(struct inpcb *, int);
int in_pcballoc(struct socket *, struct inpcbinfo *, struct thread *);
int in_pcbbind(struct inpcb *, struct sockaddr *, struct thread *);
int in_pcbconnect(struct inpcb *, struct sockaddr *, struct thread *);
@@ -340,7 +341,7 @@ struct inpcb *
in_pcblookup_hash(struct inpcbinfo *, struct in_addr, u_int,
struct in_addr, u_int, int, struct ifnet *);
void in_pcbnotifyall(struct inpcbinfo *pcbinfo, struct in_addr,
- int, void (*)(struct inpcb *, int));
+ int, struct inpcb *(*)(struct inpcb *, int));
void in_pcbrehash(struct inpcb *);
int in_setpeeraddr(struct socket *so, struct sockaddr **nam, struct inpcbinfo *pcbinfo);
int in_setsockaddr(struct socket *so, struct sockaddr **nam, struct inpcbinfo *pcbinfo);;
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index ebb2479..5b1e834 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -145,7 +145,7 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, isn_reseed_interval, CTLFLAG_RW,
&tcp_isn_reseed_interval, 0, "Seconds between reseeding of ISN secret");
static void tcp_cleartaocache(void);
-static void tcp_notify(struct inpcb *, int);
+static struct inpcb *tcp_notify(struct inpcb *, int);
/*
* Target size of TCP PCB hash tables. Must be a power of two.
@@ -774,7 +774,7 @@ tcp_drain()
* Do not wake up user since there currently is no mechanism for
* reporting soft errors (yet - a kqueue filter may be added).
*/
-static void
+static struct inpcb *
tcp_notify(inp, error)
struct inpcb *inp;
int error;
@@ -791,12 +791,15 @@ tcp_notify(inp, error)
if (tp->t_state == TCPS_ESTABLISHED &&
(error == EHOSTUNREACH || error == ENETUNREACH ||
error == EHOSTDOWN)) {
- return;
+ return inp;
} else if (tp->t_state < TCPS_ESTABLISHED && tp->t_rxtshift > 3 &&
- tp->t_softerror)
+ tp->t_softerror) {
tcp_drop(tp, error);
- else
+ return (struct inpcb *)0;
+ } else {
tp->t_softerror = error;
+ return inp;
+ }
#if 0
wakeup((caddr_t) &so->so_timeo);
sorwakeup(so);
@@ -1028,7 +1031,7 @@ tcp_ctlinput(cmd, sa, vip)
struct in_addr faddr;
struct inpcb *inp;
struct tcpcb *tp;
- void (*notify)(struct inpcb *, int) = tcp_notify;
+ struct inpcb *(*notify)(struct inpcb *, int) = tcp_notify;
tcp_seq icmp_seq;
int s;
@@ -1064,9 +1067,10 @@ tcp_ctlinput(cmd, sa, vip)
tp = intotcpcb(inp);
if (SEQ_GEQ(icmp_seq, tp->snd_una) &&
SEQ_LT(icmp_seq, tp->snd_max))
- (*notify)(inp, inetctlerrmap[cmd]);
+ inp = (*notify)(inp, inetctlerrmap[cmd]);
}
- INP_UNLOCK(inp);
+ if (inp)
+ INP_UNLOCK(inp);
} else {
struct in_conninfo inc;
@@ -1093,7 +1097,7 @@ tcp6_ctlinput(cmd, sa, d)
void *d;
{
struct tcphdr th;
- void (*notify)(struct inpcb *, int) = tcp_notify;
+ struct inpcb *(*notify)(struct inpcb *, int) = tcp_notify;
struct ip6_hdr *ip6;
struct mbuf *m;
struct ip6ctlparam *ip6cp = NULL;
@@ -1240,7 +1244,7 @@ tcp_new_isn(tp)
* When a source quench is received, close congestion window
* to one segment. We will gradually open it again as we proceed.
*/
-void
+struct inpcb *
tcp_quench(inp, errno)
struct inpcb *inp;
int errno;
@@ -1249,6 +1253,7 @@ tcp_quench(inp, errno)
if (tp)
tp->snd_cwnd = tp->t_maxseg;
+ return (inp);
}
/*
@@ -1256,15 +1261,18 @@ tcp_quench(inp, errno)
* connection state is SYN-SENT, drop the connection. This behavior
* is controlled by the icmp_may_rst sysctl.
*/
-void
+struct inpcb *
tcp_drop_syn_sent(inp, errno)
struct inpcb *inp;
int errno;
{
struct tcpcb *tp = intotcpcb(inp);
- if (tp && tp->t_state == TCPS_SYN_SENT)
+ if (tp && tp->t_state == TCPS_SYN_SENT) {
tcp_drop(tp, errno);
+ return (struct inpcb *)0;
+ }
+ return inp;
}
/*
@@ -1273,7 +1281,7 @@ tcp_drop_syn_sent(inp, errno)
* since we know the packet we just sent was dropped.
* This duplicates some code in the tcp_mss() function in tcp_input.c.
*/
-void
+struct inpcb *
tcp_mtudisc(inp, errno)
struct inpcb *inp;
int errno;
@@ -1301,7 +1309,7 @@ tcp_mtudisc(inp, errno)
isipv6 ? tcp_v6mssdflt :
#endif /* INET6 */
tcp_mssdflt;
- return;
+ return inp;
}
taop = rmx_taop(rt->rt_rmx);
offered = taop->tao_mssopt;
@@ -1336,7 +1344,7 @@ tcp_mtudisc(inp, errno)
* recomputed. For Further Study.
*/
if (tp->t_maxopd <= mss)
- return;
+ return inp;
tp->t_maxopd = mss;
if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP &&
@@ -1362,6 +1370,7 @@ tcp_mtudisc(inp, errno)
tp->snd_nxt = tp->snd_una;
tcp_output(tp);
}
+ return inp;
}
/*
diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c
index ebb2479..5b1e834 100644
--- a/sys/netinet/tcp_timewait.c
+++ b/sys/netinet/tcp_timewait.c
@@ -145,7 +145,7 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, isn_reseed_interval, CTLFLAG_RW,
&tcp_isn_reseed_interval, 0, "Seconds between reseeding of ISN secret");
static void tcp_cleartaocache(void);
-static void tcp_notify(struct inpcb *, int);
+static struct inpcb *tcp_notify(struct inpcb *, int);
/*
* Target size of TCP PCB hash tables. Must be a power of two.
@@ -774,7 +774,7 @@ tcp_drain()
* Do not wake up user since there currently is no mechanism for
* reporting soft errors (yet - a kqueue filter may be added).
*/
-static void
+static struct inpcb *
tcp_notify(inp, error)
struct inpcb *inp;
int error;
@@ -791,12 +791,15 @@ tcp_notify(inp, error)
if (tp->t_state == TCPS_ESTABLISHED &&
(error == EHOSTUNREACH || error == ENETUNREACH ||
error == EHOSTDOWN)) {
- return;
+ return inp;
} else if (tp->t_state < TCPS_ESTABLISHED && tp->t_rxtshift > 3 &&
- tp->t_softerror)
+ tp->t_softerror) {
tcp_drop(tp, error);
- else
+ return (struct inpcb *)0;
+ } else {
tp->t_softerror = error;
+ return inp;
+ }
#if 0
wakeup((caddr_t) &so->so_timeo);
sorwakeup(so);
@@ -1028,7 +1031,7 @@ tcp_ctlinput(cmd, sa, vip)
struct in_addr faddr;
struct inpcb *inp;
struct tcpcb *tp;
- void (*notify)(struct inpcb *, int) = tcp_notify;
+ struct inpcb *(*notify)(struct inpcb *, int) = tcp_notify;
tcp_seq icmp_seq;
int s;
@@ -1064,9 +1067,10 @@ tcp_ctlinput(cmd, sa, vip)
tp = intotcpcb(inp);
if (SEQ_GEQ(icmp_seq, tp->snd_una) &&
SEQ_LT(icmp_seq, tp->snd_max))
- (*notify)(inp, inetctlerrmap[cmd]);
+ inp = (*notify)(inp, inetctlerrmap[cmd]);
}
- INP_UNLOCK(inp);
+ if (inp)
+ INP_UNLOCK(inp);
} else {
struct in_conninfo inc;
@@ -1093,7 +1097,7 @@ tcp6_ctlinput(cmd, sa, d)
void *d;
{
struct tcphdr th;
- void (*notify)(struct inpcb *, int) = tcp_notify;
+ struct inpcb *(*notify)(struct inpcb *, int) = tcp_notify;
struct ip6_hdr *ip6;
struct mbuf *m;
struct ip6ctlparam *ip6cp = NULL;
@@ -1240,7 +1244,7 @@ tcp_new_isn(tp)
* When a source quench is received, close congestion window
* to one segment. We will gradually open it again as we proceed.
*/
-void
+struct inpcb *
tcp_quench(inp, errno)
struct inpcb *inp;
int errno;
@@ -1249,6 +1253,7 @@ tcp_quench(inp, errno)
if (tp)
tp->snd_cwnd = tp->t_maxseg;
+ return (inp);
}
/*
@@ -1256,15 +1261,18 @@ tcp_quench(inp, errno)
* connection state is SYN-SENT, drop the connection. This behavior
* is controlled by the icmp_may_rst sysctl.
*/
-void
+struct inpcb *
tcp_drop_syn_sent(inp, errno)
struct inpcb *inp;
int errno;
{
struct tcpcb *tp = intotcpcb(inp);
- if (tp && tp->t_state == TCPS_SYN_SENT)
+ if (tp && tp->t_state == TCPS_SYN_SENT) {
tcp_drop(tp, errno);
+ return (struct inpcb *)0;
+ }
+ return inp;
}
/*
@@ -1273,7 +1281,7 @@ tcp_drop_syn_sent(inp, errno)
* since we know the packet we just sent was dropped.
* This duplicates some code in the tcp_mss() function in tcp_input.c.
*/
-void
+struct inpcb *
tcp_mtudisc(inp, errno)
struct inpcb *inp;
int errno;
@@ -1301,7 +1309,7 @@ tcp_mtudisc(inp, errno)
isipv6 ? tcp_v6mssdflt :
#endif /* INET6 */
tcp_mssdflt;
- return;
+ return inp;
}
taop = rmx_taop(rt->rt_rmx);
offered = taop->tao_mssopt;
@@ -1336,7 +1344,7 @@ tcp_mtudisc(inp, errno)
* recomputed. For Further Study.
*/
if (tp->t_maxopd <= mss)
- return;
+ return inp;
tp->t_maxopd = mss;
if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP &&
@@ -1362,6 +1370,7 @@ tcp_mtudisc(inp, errno)
tp->snd_nxt = tp->snd_una;
tcp_output(tp);
}
+ return inp;
}
/*
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index bce5d29..a58bdf5 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -451,12 +451,15 @@ void tcp_init(void);
void tcp_input(struct mbuf *, int);
void tcp_mss(struct tcpcb *, int);
int tcp_mssopt(struct tcpcb *);
-void tcp_drop_syn_sent(struct inpcb *, int);
-void tcp_mtudisc(struct inpcb *, int);
+struct inpcb *
+ tcp_drop_syn_sent(struct inpcb *, int);
+struct inpcb *
+ tcp_mtudisc(struct inpcb *, int);
struct tcpcb *
tcp_newtcpcb(struct inpcb *);
int tcp_output(struct tcpcb *);
-void tcp_quench(struct inpcb *, int);
+struct inpcb *
+ tcp_quench(struct inpcb *, int);
void tcp_respond(struct tcpcb *, void *,
struct tcphdr *, struct mbuf *, tcp_seq, tcp_seq, int);
struct rtentry *
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index dd73d77..df18c9a 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -514,7 +514,7 @@ udp_append(last, ip, n, off)
* Notify a udp user of an asynchronous error;
* just wake up so that he can collect error status.
*/
-void
+struct inpcb *
udp_notify(inp, errno)
register struct inpcb *inp;
int errno;
@@ -522,6 +522,7 @@ udp_notify(inp, errno)
inp->inp_socket->so_error = errno;
sorwakeup(inp->inp_socket);
sowwakeup(inp->inp_socket);
+ return inp;
}
void
@@ -532,7 +533,7 @@ udp_ctlinput(cmd, sa, vip)
{
struct ip *ip = vip;
struct udphdr *uh;
- void (*notify)(struct inpcb *, int) = udp_notify;
+ struct inpcb *(*notify)(struct inpcb *, int) = udp_notify;
struct in_addr faddr;
struct inpcb *inp;
int s;
diff --git a/sys/netinet/udp_var.h b/sys/netinet/udp_var.h
index b966396..66db23f 100644
--- a/sys/netinet/udp_var.h
+++ b/sys/netinet/udp_var.h
@@ -107,7 +107,8 @@ void udp_ctlinput(int, struct sockaddr *, void *);
void udp_init(void);
void udp_input(struct mbuf *, int);
-void udp_notify(struct inpcb *inp, int errno);
+struct inpcb *
+ udp_notify(struct inpcb *inp, int errno);
int udp_shutdown(struct socket *so);
#endif
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
index f1b92a3..083ed03 100644
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -768,7 +768,7 @@ in6_pcbnotify(head, dst, fport_arg, src, lport_arg, cmd, notify)
const struct sockaddr *src;
u_int fport_arg, lport_arg;
int cmd;
- void (*notify) __P((struct inpcb *, int));
+ struct inpcb *(*notify) __P((struct inpcb *, int));
{
struct inpcb *inp, *ninp;
struct sockaddr_in6 sa6_src, *sa6_dst;
@@ -1006,7 +1006,7 @@ in6_losing(in6p)
* After a routing change, flush old routing
* and allocate a (hopefully) better one.
*/
-void
+struct inpcb *
in6_rtchange(inp, errno)
struct inpcb *inp;
int errno;
@@ -1019,6 +1019,7 @@ in6_rtchange(inp, errno)
* output is attempted.
*/
}
+ return inp;
}
/*
diff --git a/sys/netinet6/in6_pcb.h b/sys/netinet6/in6_pcb.h
index 9b0acca..5098a12 100644
--- a/sys/netinet6/in6_pcb.h
+++ b/sys/netinet6/in6_pcb.h
@@ -92,8 +92,9 @@ struct inpcb *
u_int, int, struct ifnet *));
void in6_pcbnotify __P((struct inpcbhead *, struct sockaddr *,
u_int, const struct sockaddr *, u_int, int,
- void (*)(struct inpcb *, int)));
-void in6_rtchange __P((struct inpcb *, int));
+ struct inpcb *(*)(struct inpcb *, int)));
+struct inpcb *
+ in6_rtchange __P((struct inpcb *, int));
int in6_setpeeraddr __P((struct socket *so, struct sockaddr **nam));
int in6_setsockaddr __P((struct socket *so, struct sockaddr **nam));
int in6_mapped_sockaddr __P((struct socket *so, struct sockaddr **nam));
diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c
index 2dcec0c..c4652af 100644
--- a/sys/netinet6/raw_ip6.c
+++ b/sys/netinet6/raw_ip6.c
@@ -254,7 +254,7 @@ rip6_ctlinput(cmd, sa, d)
int off = 0;
struct ip6ctlparam *ip6cp = NULL;
const struct sockaddr_in6 *sa6_src = NULL;
- void (*notify) __P((struct inpcb *, int)) = in6_rtchange;
+ struct inpcb *(*notify) __P((struct inpcb *, int)) = in6_rtchange;
if (sa->sa_family != AF_INET6 ||
sa->sa_len != sizeof(struct sockaddr_in6))
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c
index 20913e6..53439d0 100644
--- a/sys/netinet6/udp6_usrreq.c
+++ b/sys/netinet6/udp6_usrreq.c
@@ -407,7 +407,7 @@ udp6_ctlinput(cmd, sa, d)
int off = 0;
struct ip6ctlparam *ip6cp = NULL;
const struct sockaddr_in6 *sa6_src = NULL;
- void (*notify) __P((struct inpcb *, int)) = udp_notify;
+ struct inpcb *(*notify) __P((struct inpcb *, int)) = udp_notify;
struct udp_portonly {
u_int16_t uh_sport;
u_int16_t uh_dport;
OpenPOWER on IntegriCloud