Add SCTP_DEFAULT_PRINFO socket option.
Fix the SCTP_DEFAULT_SNDINFO socket option: Don't clear the PR SCTP policy when setting sinfo_flags. MFC after: 1 month.
This commit is contained in:
parent
090f90cf61
commit
6037f89c81
@ -118,6 +118,7 @@ struct sctp_paramhdr {
|
||||
#define SCTP_RECVRCVINFO 0x0000001f
|
||||
#define SCTP_RECVNXTINFO 0x00000020
|
||||
#define SCTP_DEFAULT_SNDINFO 0x00000021
|
||||
#define SCTP_DEFAULT_PRINFO 0x00000022
|
||||
|
||||
/*
|
||||
* read-only options
|
||||
|
@ -162,6 +162,12 @@ struct sctp_prinfo {
|
||||
uint32_t pr_value;
|
||||
};
|
||||
|
||||
struct sctp_default_prinfo {
|
||||
uint16_t pr_policy;
|
||||
uint32_t pr_value;
|
||||
sctp_assoc_t pr_assoc_id;
|
||||
};
|
||||
|
||||
struct sctp_authinfo {
|
||||
uint16_t auth_keyid;
|
||||
};
|
||||
|
@ -3030,6 +3030,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
if (stcb) {
|
||||
info->snd_sid = stcb->asoc.def_send.sinfo_stream;
|
||||
info->snd_flags = stcb->asoc.def_send.sinfo_flags;
|
||||
info->snd_flags &= 0xfff0;
|
||||
info->snd_ppid = stcb->asoc.def_send.sinfo_ppid;
|
||||
info->snd_context = stcb->asoc.def_send.sinfo_context;
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
@ -3038,6 +3039,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
SCTP_INP_RLOCK(inp);
|
||||
info->snd_sid = inp->def_send.sinfo_stream;
|
||||
info->snd_flags = inp->def_send.sinfo_flags;
|
||||
info->snd_flags &= 0xfff0;
|
||||
info->snd_ppid = inp->def_send.sinfo_ppid;
|
||||
info->snd_context = inp->def_send.sinfo_context;
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
@ -3051,6 +3053,33 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SCTP_DEFAULT_PRINFO:
|
||||
{
|
||||
struct sctp_default_prinfo *info;
|
||||
|
||||
SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, *optsize);
|
||||
SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
|
||||
|
||||
if (stcb) {
|
||||
info->pr_policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
|
||||
info->pr_value = stcb->asoc.def_send.sinfo_timetolive;
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
} else {
|
||||
if (info->pr_assoc_id == SCTP_FUTURE_ASSOC) {
|
||||
SCTP_INP_RLOCK(inp);
|
||||
info->pr_policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
|
||||
info->pr_value = inp->def_send.sinfo_timetolive;
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
} else {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
error = EINVAL;
|
||||
}
|
||||
}
|
||||
if (error == 0) {
|
||||
*optsize = sizeof(struct sctp_default_prinfo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
|
||||
error = ENOPROTOOPT;
|
||||
@ -5043,6 +5072,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
case SCTP_DEFAULT_SNDINFO:
|
||||
{
|
||||
struct sctp_sndinfo *info;
|
||||
uint16_t policy;
|
||||
|
||||
SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, optsize);
|
||||
SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
|
||||
@ -5050,7 +5080,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
if (stcb) {
|
||||
if (info->snd_sid < stcb->asoc.streamoutcnt) {
|
||||
stcb->asoc.def_send.sinfo_stream = info->snd_sid;
|
||||
policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
|
||||
stcb->asoc.def_send.sinfo_flags = info->snd_flags;
|
||||
stcb->asoc.def_send.sinfo_flags |= policy;
|
||||
stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
|
||||
stcb->asoc.def_send.sinfo_context = info->snd_context;
|
||||
} else {
|
||||
@ -5063,7 +5095,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
(info->snd_assoc_id == SCTP_ALL_ASSOC)) {
|
||||
SCTP_INP_WLOCK(inp);
|
||||
inp->def_send.sinfo_stream = info->snd_sid;
|
||||
policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
|
||||
inp->def_send.sinfo_flags = info->snd_flags;
|
||||
inp->def_send.sinfo_flags |= policy;
|
||||
inp->def_send.sinfo_ppid = info->snd_ppid;
|
||||
inp->def_send.sinfo_context = info->snd_context;
|
||||
SCTP_INP_WUNLOCK(inp);
|
||||
@ -5075,7 +5109,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
SCTP_TCB_LOCK(stcb);
|
||||
if (info->snd_sid < stcb->asoc.streamoutcnt) {
|
||||
stcb->asoc.def_send.sinfo_stream = info->snd_sid;
|
||||
policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
|
||||
stcb->asoc.def_send.sinfo_flags = info->snd_flags;
|
||||
stcb->asoc.def_send.sinfo_flags |= policy;
|
||||
stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
|
||||
stcb->asoc.def_send.sinfo_context = info->snd_context;
|
||||
}
|
||||
@ -5086,6 +5122,44 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SCTP_DEFAULT_PRINFO:
|
||||
{
|
||||
struct sctp_default_prinfo *info;
|
||||
|
||||
SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, optsize);
|
||||
SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
|
||||
|
||||
if (PR_SCTP_INVALID_POLICY(info->pr_policy)) {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
if (stcb) {
|
||||
stcb->asoc.def_send.sinfo_flags &= 0xfff0;
|
||||
stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
} else {
|
||||
if ((info->pr_assoc_id == SCTP_FUTURE_ASSOC) ||
|
||||
(info->pr_assoc_id == SCTP_ALL_ASSOC)) {
|
||||
SCTP_INP_WLOCK(inp);
|
||||
inp->def_send.sinfo_flags &= 0xfff0;
|
||||
inp->def_send.sinfo_flags |= info->pr_policy;
|
||||
SCTP_INP_WUNLOCK(inp);
|
||||
}
|
||||
if ((info->pr_assoc_id == SCTP_CURRENT_ASSOC) ||
|
||||
(info->pr_assoc_id == SCTP_ALL_ASSOC)) {
|
||||
SCTP_INP_RLOCK(inp);
|
||||
LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
|
||||
SCTP_TCB_LOCK(stcb);
|
||||
stcb->asoc.def_send.sinfo_flags &= 0xfff0;
|
||||
stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
}
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
|
||||
error = ENOPROTOOPT;
|
||||
|
Loading…
Reference in New Issue
Block a user