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)
This commit is contained in:
Jeffrey Hsu 2002-06-14 08:35:21 +00:00
parent 85f6c317ea
commit 3ce144ea88
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=98211
11 changed files with 73 additions and 46 deletions

View File

@ -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;
}
/*

View File

@ -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);;

View File

@ -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;
}
/*

View File

@ -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;
}
/*

View File

@ -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 *

View File

@ -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;

View File

@ -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

View File

@ -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;
}
/*

View File

@ -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));

View File

@ -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))

View File

@ -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;