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:
parent
85f6c317ea
commit
3ce144ea88
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=98211
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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);;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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 *
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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));
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user