Use the pru_flush infrastructure to avoid a panic

PR:		122710
MFC after:	1 week
This commit is contained in:
Randall Stewart 2008-04-14 18:13:33 +00:00
parent 276ca5012c
commit eadccaccf0
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=178202
3 changed files with 65 additions and 3 deletions

View File

@ -2182,6 +2182,20 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
/* out of memory or ?? */
return (NULL);
}
#ifdef SCTP_MBUF_LOGGING
if (sctp_logging_level & SCTP_MBUF_LOGGING_ENABLE) {
struct mbuf *mat;
mat = m_sig;
while (mat) {
if (SCTP_BUF_IS_EXTENDED(mat)) {
sctp_log_mb(mat, SCTP_MBUF_SPLIT);
}
mat = SCTP_BUF_NEXT(mat);
}
}
#endif
/*
* compute the signature/digest for the cookie
*/
@ -2795,7 +2809,7 @@ sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp,
}
}
/* stop the timer */
sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_22);
sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_22);
SCTP_STAT_INCR_COUNTER32(sctps_shutdown);
/* free the TCB */
SCTPDBG(SCTP_DEBUG_INPUT2,
@ -4807,6 +4821,19 @@ __attribute__((noinline))
SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset, SCTP_SIZE32(chk_length),
M_DONTWAIT);
if (SCTP_BUF_NEXT(mm)) {
#ifdef SCTP_MBUF_LOGGING
if (sctp_logging_level & SCTP_MBUF_LOGGING_ENABLE) {
struct mbuf *mat;
mat = SCTP_BUF_NEXT(mm);
while (mat) {
if (SCTP_BUF_IS_EXTENDED(mat)) {
sctp_log_mb(mat, SCTP_MBUF_ICOPY);
}
mat = SCTP_BUF_NEXT(mat);
}
}
#endif
sctp_queue_op_err(stcb, mm);
} else {
sctp_m_freem(mm);

View File

@ -918,6 +918,37 @@ sctp_disconnect(struct socket *so)
}
}
int
sctp_flush(struct socket *so, int how)
{
/*
* We will just clear out the values and let subsequent close clear
* out the data, if any. Note if the user did a shutdown(SHUT_RD)
* they will not be able to read the data, the socket will block
* that from happening.
*/
if ((how == PRU_FLUSH_RD) || (how == PRU_FLUSH_RDWR)) {
/*
* First make sure the sb will be happy, we don't use these
* except maybe the count
*/
so->so_rcv.sb_cc = 0;
so->so_rcv.sb_mbcnt = 0;
so->so_rcv.sb_mb = NULL;
}
if ((how == PRU_FLUSH_WR) || (how == PRU_FLUSH_RDWR)) {
/*
* First make sure the sb will be happy, we don't use these
* except maybe the count
*/
so->so_snd.sb_cc = 0;
so->so_snd.sb_mbcnt = 0;
so->so_snd.sb_mb = NULL;
}
return (0);
}
int
sctp_shutdown(struct socket *so)
{
@ -4008,10 +4039,11 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
SCTP_INP_INCR_REF(inp);
SCTP_ASOC_CREATE_LOCK(inp);
create_lock_on = 1;
SCTP_INP_INCR_REF(inp);
if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
/* Should I really unlock ? */
@ -4063,7 +4095,7 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
if (stcb == NULL) {
SCTP_INP_DECR_REF(inp);
} else {
SCTP_TCB_LOCK(stcb);
SCTP_TCB_UNLOCK(stcb);
}
}
if (stcb != NULL) {
@ -4433,6 +4465,7 @@ struct pr_usrreqs sctp_usrreqs = {
.pru_close = sctp_close,
.pru_detach = sctp_close,
.pru_sopoll = sopoll_generic,
.pru_flush = sctp_flush,
.pru_disconnect = sctp_disconnect,
.pru_listen = sctp_listen,
.pru_peeraddr = sctp_peeraddr,

View File

@ -307,6 +307,8 @@ void sctp_init __P((void));
void sctp_pcbinfo_cleanup(void);
int sctp_flush(struct socket *, int);
int sctp_shutdown __P((struct socket *));
void sctp_notify
__P((struct sctp_inpcb *, struct ip *ip, struct sctphdr *,