mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-27 09:02:06 +00:00
[SCTP]: Update SCTP_PEER_ADDR_PARAMS socket option to the latest api draft.
This patch adds support to set/get heartbeat interval, maximum number of retransmissions, pathmtu, sackdelay time for a particular transport/ association/socket as per the latest SCTP sockets api draft11. Signed-off-by: Frank Filz <ffilz@us.ibm.com> Signed-off-by: Sridhar Samudrala <sri@us.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
fd9662555c
commit
52ccb8e90c
9 changed files with 602 additions and 227 deletions
|
@ -1941,106 +1941,275 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval,
|
|||
* address's parameters:
|
||||
*
|
||||
* struct sctp_paddrparams {
|
||||
* sctp_assoc_t spp_assoc_id;
|
||||
* struct sockaddr_storage spp_address;
|
||||
* uint32_t spp_hbinterval;
|
||||
* uint16_t spp_pathmaxrxt;
|
||||
* };
|
||||
* sctp_assoc_t spp_assoc_id;
|
||||
* struct sockaddr_storage spp_address;
|
||||
* uint32_t spp_hbinterval;
|
||||
* uint16_t spp_pathmaxrxt;
|
||||
* uint32_t spp_pathmtu;
|
||||
* uint32_t spp_sackdelay;
|
||||
* uint32_t spp_flags;
|
||||
* };
|
||||
*
|
||||
* spp_assoc_id - (UDP style socket) This is filled in the application,
|
||||
* and identifies the association for this query.
|
||||
* spp_assoc_id - (one-to-many style socket) This is filled in the
|
||||
* application, and identifies the association for
|
||||
* this query.
|
||||
* spp_address - This specifies which address is of interest.
|
||||
* spp_hbinterval - This contains the value of the heartbeat interval,
|
||||
* in milliseconds. A value of 0, when modifying the
|
||||
* parameter, specifies that the heartbeat on this
|
||||
* address should be disabled. A value of UINT32_MAX
|
||||
* (4294967295), when modifying the parameter,
|
||||
* specifies that a heartbeat should be sent
|
||||
* immediately to the peer address, and the current
|
||||
* interval should remain unchanged.
|
||||
* in milliseconds. If a value of zero
|
||||
* is present in this field then no changes are to
|
||||
* be made to this parameter.
|
||||
* spp_pathmaxrxt - This contains the maximum number of
|
||||
* retransmissions before this address shall be
|
||||
* considered unreachable.
|
||||
* considered unreachable. If a value of zero
|
||||
* is present in this field then no changes are to
|
||||
* be made to this parameter.
|
||||
* spp_pathmtu - When Path MTU discovery is disabled the value
|
||||
* specified here will be the "fixed" path mtu.
|
||||
* Note that if the spp_address field is empty
|
||||
* then all associations on this address will
|
||||
* have this fixed path mtu set upon them.
|
||||
*
|
||||
* spp_sackdelay - When delayed sack is enabled, this value specifies
|
||||
* the number of milliseconds that sacks will be delayed
|
||||
* for. This value will apply to all addresses of an
|
||||
* association if the spp_address field is empty. Note
|
||||
* also, that if delayed sack is enabled and this
|
||||
* value is set to 0, no change is made to the last
|
||||
* recorded delayed sack timer value.
|
||||
*
|
||||
* spp_flags - These flags are used to control various features
|
||||
* on an association. The flag field may contain
|
||||
* zero or more of the following options.
|
||||
*
|
||||
* SPP_HB_ENABLE - Enable heartbeats on the
|
||||
* specified address. Note that if the address
|
||||
* field is empty all addresses for the association
|
||||
* have heartbeats enabled upon them.
|
||||
*
|
||||
* SPP_HB_DISABLE - Disable heartbeats on the
|
||||
* speicifed address. Note that if the address
|
||||
* field is empty all addresses for the association
|
||||
* will have their heartbeats disabled. Note also
|
||||
* that SPP_HB_ENABLE and SPP_HB_DISABLE are
|
||||
* mutually exclusive, only one of these two should
|
||||
* be specified. Enabling both fields will have
|
||||
* undetermined results.
|
||||
*
|
||||
* SPP_HB_DEMAND - Request a user initiated heartbeat
|
||||
* to be made immediately.
|
||||
*
|
||||
* SPP_PMTUD_ENABLE - This field will enable PMTU
|
||||
* discovery upon the specified address. Note that
|
||||
* if the address feild is empty then all addresses
|
||||
* on the association are effected.
|
||||
*
|
||||
* SPP_PMTUD_DISABLE - This field will disable PMTU
|
||||
* discovery upon the specified address. Note that
|
||||
* if the address feild is empty then all addresses
|
||||
* on the association are effected. Not also that
|
||||
* SPP_PMTUD_ENABLE and SPP_PMTUD_DISABLE are mutually
|
||||
* exclusive. Enabling both will have undetermined
|
||||
* results.
|
||||
*
|
||||
* SPP_SACKDELAY_ENABLE - Setting this flag turns
|
||||
* on delayed sack. The time specified in spp_sackdelay
|
||||
* is used to specify the sack delay for this address. Note
|
||||
* that if spp_address is empty then all addresses will
|
||||
* enable delayed sack and take on the sack delay
|
||||
* value specified in spp_sackdelay.
|
||||
* SPP_SACKDELAY_DISABLE - Setting this flag turns
|
||||
* off delayed sack. If the spp_address field is blank then
|
||||
* delayed sack is disabled for the entire association. Note
|
||||
* also that this field is mutually exclusive to
|
||||
* SPP_SACKDELAY_ENABLE, setting both will have undefined
|
||||
* results.
|
||||
*/
|
||||
static int sctp_setsockopt_peer_addr_params(struct sock *sk,
|
||||
char __user *optval, int optlen)
|
||||
int sctp_apply_peer_addr_params(struct sctp_paddrparams *params,
|
||||
struct sctp_transport *trans,
|
||||
struct sctp_association *asoc,
|
||||
struct sctp_sock *sp,
|
||||
int hb_change,
|
||||
int pmtud_change,
|
||||
int sackdelay_change)
|
||||
{
|
||||
struct sctp_paddrparams params;
|
||||
struct sctp_transport *trans;
|
||||
int error;
|
||||
|
||||
if (optlen != sizeof(struct sctp_paddrparams))
|
||||
return -EINVAL;
|
||||
if (copy_from_user(¶ms, optval, optlen))
|
||||
return -EFAULT;
|
||||
|
||||
/*
|
||||
* API 7. Socket Options (setting the default value for the endpoint)
|
||||
* All options that support specific settings on an association by
|
||||
* filling in either an association id variable or a sockaddr_storage
|
||||
* SHOULD also support setting of the same value for the entire endpoint
|
||||
* (i.e. future associations). To accomplish this the following logic is
|
||||
* used when setting one of these options:
|
||||
|
||||
* c) If neither the sockaddr_storage or association identification is
|
||||
* set i.e. the sockaddr_storage is set to all 0's (INADDR_ANY) and
|
||||
* the association identification is 0, the settings are a default
|
||||
* and to be applied to the endpoint (all future associations).
|
||||
*/
|
||||
|
||||
/* update default value for endpoint (all future associations) */
|
||||
if (!params.spp_assoc_id &&
|
||||
sctp_is_any(( union sctp_addr *)¶ms.spp_address)) {
|
||||
/* Manual heartbeat on an endpoint is invalid. */
|
||||
if (0xffffffff == params.spp_hbinterval)
|
||||
return -EINVAL;
|
||||
else if (params.spp_hbinterval)
|
||||
sctp_sk(sk)->paddrparam.spp_hbinterval =
|
||||
params.spp_hbinterval;
|
||||
if (params.spp_pathmaxrxt)
|
||||
sctp_sk(sk)->paddrparam.spp_pathmaxrxt =
|
||||
params.spp_pathmaxrxt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
trans = sctp_addr_id2transport(sk, ¶ms.spp_address,
|
||||
params.spp_assoc_id);
|
||||
if (!trans)
|
||||
return -EINVAL;
|
||||
|
||||
/* Applications can enable or disable heartbeats for any peer address
|
||||
* of an association, modify an address's heartbeat interval, force a
|
||||
* heartbeat to be sent immediately, and adjust the address's maximum
|
||||
* number of retransmissions sent before an address is considered
|
||||
* unreachable.
|
||||
*
|
||||
* The value of the heartbeat interval, in milliseconds. A value of
|
||||
* UINT32_MAX (4294967295), when modifying the parameter, specifies
|
||||
* that a heartbeat should be sent immediately to the peer address,
|
||||
* and the current interval should remain unchanged.
|
||||
*/
|
||||
if (0xffffffff == params.spp_hbinterval) {
|
||||
if (params->spp_flags & SPP_HB_DEMAND && trans) {
|
||||
error = sctp_primitive_REQUESTHEARTBEAT (trans->asoc, trans);
|
||||
if (error)
|
||||
return error;
|
||||
} else {
|
||||
/* The value of the heartbeat interval, in milliseconds. A value of 0,
|
||||
* when modifying the parameter, specifies that the heartbeat on this
|
||||
* address should be disabled.
|
||||
*/
|
||||
if (params.spp_hbinterval) {
|
||||
trans->hb_allowed = 1;
|
||||
trans->hb_interval =
|
||||
msecs_to_jiffies(params.spp_hbinterval);
|
||||
} else
|
||||
trans->hb_allowed = 0;
|
||||
}
|
||||
|
||||
/* spp_pathmaxrxt contains the maximum number of retransmissions
|
||||
* before this address shall be considered unreachable.
|
||||
if (params->spp_hbinterval) {
|
||||
if (trans) {
|
||||
trans->hbinterval = msecs_to_jiffies(params->spp_hbinterval);
|
||||
} else if (asoc) {
|
||||
asoc->hbinterval = msecs_to_jiffies(params->spp_hbinterval);
|
||||
} else {
|
||||
sp->hbinterval = params->spp_hbinterval;
|
||||
}
|
||||
}
|
||||
|
||||
if (hb_change) {
|
||||
if (trans) {
|
||||
trans->param_flags =
|
||||
(trans->param_flags & ~SPP_HB) | hb_change;
|
||||
} else if (asoc) {
|
||||
asoc->param_flags =
|
||||
(asoc->param_flags & ~SPP_HB) | hb_change;
|
||||
} else {
|
||||
sp->param_flags =
|
||||
(sp->param_flags & ~SPP_HB) | hb_change;
|
||||
}
|
||||
}
|
||||
|
||||
if (params->spp_pathmtu) {
|
||||
if (trans) {
|
||||
trans->pathmtu = params->spp_pathmtu;
|
||||
sctp_assoc_sync_pmtu(asoc);
|
||||
} else if (asoc) {
|
||||
asoc->pathmtu = params->spp_pathmtu;
|
||||
sctp_frag_point(sp, params->spp_pathmtu);
|
||||
} else {
|
||||
sp->pathmtu = params->spp_pathmtu;
|
||||
}
|
||||
}
|
||||
|
||||
if (pmtud_change) {
|
||||
if (trans) {
|
||||
int update = (trans->param_flags & SPP_PMTUD_DISABLE) &&
|
||||
(params->spp_flags & SPP_PMTUD_ENABLE);
|
||||
trans->param_flags =
|
||||
(trans->param_flags & ~SPP_PMTUD) | pmtud_change;
|
||||
if (update) {
|
||||
sctp_transport_pmtu(trans);
|
||||
sctp_assoc_sync_pmtu(asoc);
|
||||
}
|
||||
} else if (asoc) {
|
||||
asoc->param_flags =
|
||||
(asoc->param_flags & ~SPP_PMTUD) | pmtud_change;
|
||||
} else {
|
||||
sp->param_flags =
|
||||
(sp->param_flags & ~SPP_PMTUD) | pmtud_change;
|
||||
}
|
||||
}
|
||||
|
||||
if (params->spp_sackdelay) {
|
||||
if (trans) {
|
||||
trans->sackdelay =
|
||||
msecs_to_jiffies(params->spp_sackdelay);
|
||||
} else if (asoc) {
|
||||
asoc->sackdelay =
|
||||
msecs_to_jiffies(params->spp_sackdelay);
|
||||
} else {
|
||||
sp->sackdelay = params->spp_sackdelay;
|
||||
}
|
||||
}
|
||||
|
||||
if (sackdelay_change) {
|
||||
if (trans) {
|
||||
trans->param_flags =
|
||||
(trans->param_flags & ~SPP_SACKDELAY) |
|
||||
sackdelay_change;
|
||||
} else if (asoc) {
|
||||
asoc->param_flags =
|
||||
(asoc->param_flags & ~SPP_SACKDELAY) |
|
||||
sackdelay_change;
|
||||
} else {
|
||||
sp->param_flags =
|
||||
(sp->param_flags & ~SPP_SACKDELAY) |
|
||||
sackdelay_change;
|
||||
}
|
||||
}
|
||||
|
||||
if (params->spp_pathmaxrxt) {
|
||||
if (trans) {
|
||||
trans->pathmaxrxt = params->spp_pathmaxrxt;
|
||||
} else if (asoc) {
|
||||
asoc->pathmaxrxt = params->spp_pathmaxrxt;
|
||||
} else {
|
||||
sp->pathmaxrxt = params->spp_pathmaxrxt;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sctp_setsockopt_peer_addr_params(struct sock *sk,
|
||||
char __user *optval, int optlen)
|
||||
{
|
||||
struct sctp_paddrparams params;
|
||||
struct sctp_transport *trans = NULL;
|
||||
struct sctp_association *asoc = NULL;
|
||||
struct sctp_sock *sp = sctp_sk(sk);
|
||||
int error;
|
||||
int hb_change, pmtud_change, sackdelay_change;
|
||||
|
||||
if (optlen != sizeof(struct sctp_paddrparams))
|
||||
return - EINVAL;
|
||||
|
||||
if (copy_from_user(¶ms, optval, optlen))
|
||||
return -EFAULT;
|
||||
|
||||
/* Validate flags and value parameters. */
|
||||
hb_change = params.spp_flags & SPP_HB;
|
||||
pmtud_change = params.spp_flags & SPP_PMTUD;
|
||||
sackdelay_change = params.spp_flags & SPP_SACKDELAY;
|
||||
|
||||
if (hb_change == SPP_HB ||
|
||||
pmtud_change == SPP_PMTUD ||
|
||||
sackdelay_change == SPP_SACKDELAY ||
|
||||
params.spp_sackdelay > 500 ||
|
||||
(params.spp_pathmtu
|
||||
&& params.spp_pathmtu < SCTP_DEFAULT_MINSEGMENT))
|
||||
return -EINVAL;
|
||||
|
||||
/* If an address other than INADDR_ANY is specified, and
|
||||
* no transport is found, then the request is invalid.
|
||||
*/
|
||||
if (params.spp_pathmaxrxt)
|
||||
trans->max_retrans = params.spp_pathmaxrxt;
|
||||
if (!sctp_is_any(( union sctp_addr *)¶ms.spp_address)) {
|
||||
trans = sctp_addr_id2transport(sk, ¶ms.spp_address,
|
||||
params.spp_assoc_id);
|
||||
if (!trans)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Get association, if assoc_id != 0 and the socket is a one
|
||||
* to many style socket, and an association was not found, then
|
||||
* the id was invalid.
|
||||
*/
|
||||
asoc = sctp_id2assoc(sk, params.spp_assoc_id);
|
||||
if (!asoc && params.spp_assoc_id && sctp_style(sk, UDP))
|
||||
return -EINVAL;
|
||||
|
||||
/* Heartbeat demand can only be sent on a transport or
|
||||
* association, but not a socket.
|
||||
*/
|
||||
if (params.spp_flags & SPP_HB_DEMAND && !trans && !asoc)
|
||||
return -EINVAL;
|
||||
|
||||
/* Process parameters. */
|
||||
error = sctp_apply_peer_addr_params(¶ms, trans, asoc, sp,
|
||||
hb_change, pmtud_change,
|
||||
sackdelay_change);
|
||||
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* If changes are for association, also apply parameters to each
|
||||
* transport.
|
||||
*/
|
||||
if (!trans && asoc) {
|
||||
struct list_head *pos;
|
||||
|
||||
list_for_each(pos, &asoc->peer.transport_addr_list) {
|
||||
trans = list_entry(pos, struct sctp_transport,
|
||||
transports);
|
||||
sctp_apply_peer_addr_params(¶ms, trans, asoc, sp,
|
||||
hb_change, pmtud_change,
|
||||
sackdelay_change);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2334,7 +2503,7 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optl
|
|||
/* Update the frag_point of the existing associations. */
|
||||
list_for_each(pos, &(sp->ep->asocs)) {
|
||||
asoc = list_entry(pos, struct sctp_association, asocs);
|
||||
asoc->frag_point = sctp_frag_point(sp, asoc->pmtu);
|
||||
asoc->frag_point = sctp_frag_point(sp, asoc->pathmtu);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -2715,8 +2884,13 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
|
|||
/* Default Peer Address Parameters. These defaults can
|
||||
* be modified via SCTP_PEER_ADDR_PARAMS
|
||||
*/
|
||||
sp->paddrparam.spp_hbinterval = jiffies_to_msecs(sctp_hb_interval);
|
||||
sp->paddrparam.spp_pathmaxrxt = sctp_max_retrans_path;
|
||||
sp->hbinterval = jiffies_to_msecs(sctp_hb_interval);
|
||||
sp->pathmaxrxt = sctp_max_retrans_path;
|
||||
sp->pathmtu = 0; // allow default discovery
|
||||
sp->sackdelay = sctp_sack_timeout;
|
||||
sp->param_flags = SPP_HB_ENABLE |
|
||||
SPP_PMTUD_ENABLE |
|
||||
SPP_SACKDELAY_ENABLE;
|
||||
|
||||
/* If enabled no SCTP message fragmentation will be performed.
|
||||
* Configure through SCTP_DISABLE_FRAGMENTS socket option.
|
||||
|
@ -2865,7 +3039,7 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len,
|
|||
status.sstat_primary.spinfo_cwnd = transport->cwnd;
|
||||
status.sstat_primary.spinfo_srtt = transport->srtt;
|
||||
status.sstat_primary.spinfo_rto = jiffies_to_msecs(transport->rto);
|
||||
status.sstat_primary.spinfo_mtu = transport->pmtu;
|
||||
status.sstat_primary.spinfo_mtu = transport->pathmtu;
|
||||
|
||||
if (status.sstat_primary.spinfo_state == SCTP_UNKNOWN)
|
||||
status.sstat_primary.spinfo_state = SCTP_ACTIVE;
|
||||
|
@ -2924,7 +3098,7 @@ static int sctp_getsockopt_peer_addr_info(struct sock *sk, int len,
|
|||
pinfo.spinfo_cwnd = transport->cwnd;
|
||||
pinfo.spinfo_srtt = transport->srtt;
|
||||
pinfo.spinfo_rto = jiffies_to_msecs(transport->rto);
|
||||
pinfo.spinfo_mtu = transport->pmtu;
|
||||
pinfo.spinfo_mtu = transport->pathmtu;
|
||||
|
||||
if (pinfo.spinfo_state == SCTP_UNKNOWN)
|
||||
pinfo.spinfo_state = SCTP_ACTIVE;
|
||||
|
@ -3086,69 +3260,154 @@ out:
|
|||
* address's parameters:
|
||||
*
|
||||
* struct sctp_paddrparams {
|
||||
* sctp_assoc_t spp_assoc_id;
|
||||
* struct sockaddr_storage spp_address;
|
||||
* uint32_t spp_hbinterval;
|
||||
* uint16_t spp_pathmaxrxt;
|
||||
* };
|
||||
* sctp_assoc_t spp_assoc_id;
|
||||
* struct sockaddr_storage spp_address;
|
||||
* uint32_t spp_hbinterval;
|
||||
* uint16_t spp_pathmaxrxt;
|
||||
* uint32_t spp_pathmtu;
|
||||
* uint32_t spp_sackdelay;
|
||||
* uint32_t spp_flags;
|
||||
* };
|
||||
*
|
||||
* spp_assoc_id - (UDP style socket) This is filled in the application,
|
||||
* and identifies the association for this query.
|
||||
* spp_assoc_id - (one-to-many style socket) This is filled in the
|
||||
* application, and identifies the association for
|
||||
* this query.
|
||||
* spp_address - This specifies which address is of interest.
|
||||
* spp_hbinterval - This contains the value of the heartbeat interval,
|
||||
* in milliseconds. A value of 0, when modifying the
|
||||
* parameter, specifies that the heartbeat on this
|
||||
* address should be disabled. A value of UINT32_MAX
|
||||
* (4294967295), when modifying the parameter,
|
||||
* specifies that a heartbeat should be sent
|
||||
* immediately to the peer address, and the current
|
||||
* interval should remain unchanged.
|
||||
* in milliseconds. If a value of zero
|
||||
* is present in this field then no changes are to
|
||||
* be made to this parameter.
|
||||
* spp_pathmaxrxt - This contains the maximum number of
|
||||
* retransmissions before this address shall be
|
||||
* considered unreachable.
|
||||
* considered unreachable. If a value of zero
|
||||
* is present in this field then no changes are to
|
||||
* be made to this parameter.
|
||||
* spp_pathmtu - When Path MTU discovery is disabled the value
|
||||
* specified here will be the "fixed" path mtu.
|
||||
* Note that if the spp_address field is empty
|
||||
* then all associations on this address will
|
||||
* have this fixed path mtu set upon them.
|
||||
*
|
||||
* spp_sackdelay - When delayed sack is enabled, this value specifies
|
||||
* the number of milliseconds that sacks will be delayed
|
||||
* for. This value will apply to all addresses of an
|
||||
* association if the spp_address field is empty. Note
|
||||
* also, that if delayed sack is enabled and this
|
||||
* value is set to 0, no change is made to the last
|
||||
* recorded delayed sack timer value.
|
||||
*
|
||||
* spp_flags - These flags are used to control various features
|
||||
* on an association. The flag field may contain
|
||||
* zero or more of the following options.
|
||||
*
|
||||
* SPP_HB_ENABLE - Enable heartbeats on the
|
||||
* specified address. Note that if the address
|
||||
* field is empty all addresses for the association
|
||||
* have heartbeats enabled upon them.
|
||||
*
|
||||
* SPP_HB_DISABLE - Disable heartbeats on the
|
||||
* speicifed address. Note that if the address
|
||||
* field is empty all addresses for the association
|
||||
* will have their heartbeats disabled. Note also
|
||||
* that SPP_HB_ENABLE and SPP_HB_DISABLE are
|
||||
* mutually exclusive, only one of these two should
|
||||
* be specified. Enabling both fields will have
|
||||
* undetermined results.
|
||||
*
|
||||
* SPP_HB_DEMAND - Request a user initiated heartbeat
|
||||
* to be made immediately.
|
||||
*
|
||||
* SPP_PMTUD_ENABLE - This field will enable PMTU
|
||||
* discovery upon the specified address. Note that
|
||||
* if the address feild is empty then all addresses
|
||||
* on the association are effected.
|
||||
*
|
||||
* SPP_PMTUD_DISABLE - This field will disable PMTU
|
||||
* discovery upon the specified address. Note that
|
||||
* if the address feild is empty then all addresses
|
||||
* on the association are effected. Not also that
|
||||
* SPP_PMTUD_ENABLE and SPP_PMTUD_DISABLE are mutually
|
||||
* exclusive. Enabling both will have undetermined
|
||||
* results.
|
||||
*
|
||||
* SPP_SACKDELAY_ENABLE - Setting this flag turns
|
||||
* on delayed sack. The time specified in spp_sackdelay
|
||||
* is used to specify the sack delay for this address. Note
|
||||
* that if spp_address is empty then all addresses will
|
||||
* enable delayed sack and take on the sack delay
|
||||
* value specified in spp_sackdelay.
|
||||
* SPP_SACKDELAY_DISABLE - Setting this flag turns
|
||||
* off delayed sack. If the spp_address field is blank then
|
||||
* delayed sack is disabled for the entire association. Note
|
||||
* also that this field is mutually exclusive to
|
||||
* SPP_SACKDELAY_ENABLE, setting both will have undefined
|
||||
* results.
|
||||
*/
|
||||
static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len,
|
||||
char __user *optval, int __user *optlen)
|
||||
char __user *optval, int __user *optlen)
|
||||
{
|
||||
struct sctp_paddrparams params;
|
||||
struct sctp_transport *trans;
|
||||
struct sctp_paddrparams params;
|
||||
struct sctp_transport *trans = NULL;
|
||||
struct sctp_association *asoc = NULL;
|
||||
struct sctp_sock *sp = sctp_sk(sk);
|
||||
|
||||
if (len != sizeof(struct sctp_paddrparams))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(¶ms, optval, len))
|
||||
return -EFAULT;
|
||||
|
||||
/* If no association id is specified retrieve the default value
|
||||
* for the endpoint that will be used for all future associations
|
||||
/* If an address other than INADDR_ANY is specified, and
|
||||
* no transport is found, then the request is invalid.
|
||||
*/
|
||||
if (!params.spp_assoc_id &&
|
||||
sctp_is_any(( union sctp_addr *)¶ms.spp_address)) {
|
||||
params.spp_hbinterval = sctp_sk(sk)->paddrparam.spp_hbinterval;
|
||||
params.spp_pathmaxrxt = sctp_sk(sk)->paddrparam.spp_pathmaxrxt;
|
||||
|
||||
goto done;
|
||||
if (!sctp_is_any(( union sctp_addr *)¶ms.spp_address)) {
|
||||
trans = sctp_addr_id2transport(sk, ¶ms.spp_address,
|
||||
params.spp_assoc_id);
|
||||
if (!trans) {
|
||||
SCTP_DEBUG_PRINTK("Failed no transport\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
trans = sctp_addr_id2transport(sk, ¶ms.spp_address,
|
||||
params.spp_assoc_id);
|
||||
if (!trans)
|
||||
/* Get association, if assoc_id != 0 and the socket is a one
|
||||
* to many style socket, and an association was not found, then
|
||||
* the id was invalid.
|
||||
*/
|
||||
asoc = sctp_id2assoc(sk, params.spp_assoc_id);
|
||||
if (!asoc && params.spp_assoc_id && sctp_style(sk, UDP)) {
|
||||
SCTP_DEBUG_PRINTK("Failed no association\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* The value of the heartbeat interval, in milliseconds. A value of 0,
|
||||
* when modifying the parameter, specifies that the heartbeat on this
|
||||
* address should be disabled.
|
||||
*/
|
||||
if (!trans->hb_allowed)
|
||||
params.spp_hbinterval = 0;
|
||||
else
|
||||
params.spp_hbinterval = jiffies_to_msecs(trans->hb_interval);
|
||||
if (trans) {
|
||||
/* Fetch transport values. */
|
||||
params.spp_hbinterval = jiffies_to_msecs(trans->hbinterval);
|
||||
params.spp_pathmtu = trans->pathmtu;
|
||||
params.spp_pathmaxrxt = trans->pathmaxrxt;
|
||||
params.spp_sackdelay = jiffies_to_msecs(trans->sackdelay);
|
||||
|
||||
/* spp_pathmaxrxt contains the maximum number of retransmissions
|
||||
* before this address shall be considered unreachable.
|
||||
*/
|
||||
params.spp_pathmaxrxt = trans->max_retrans;
|
||||
/*draft-11 doesn't say what to return in spp_flags*/
|
||||
params.spp_flags = trans->param_flags;
|
||||
} else if (asoc) {
|
||||
/* Fetch association values. */
|
||||
params.spp_hbinterval = jiffies_to_msecs(asoc->hbinterval);
|
||||
params.spp_pathmtu = asoc->pathmtu;
|
||||
params.spp_pathmaxrxt = asoc->pathmaxrxt;
|
||||
params.spp_sackdelay = jiffies_to_msecs(asoc->sackdelay);
|
||||
|
||||
/*draft-11 doesn't say what to return in spp_flags*/
|
||||
params.spp_flags = asoc->param_flags;
|
||||
} else {
|
||||
/* Fetch socket values. */
|
||||
params.spp_hbinterval = sp->hbinterval;
|
||||
params.spp_pathmtu = sp->pathmtu;
|
||||
params.spp_sackdelay = sp->sackdelay;
|
||||
params.spp_pathmaxrxt = sp->pathmaxrxt;
|
||||
|
||||
/*draft-11 doesn't say what to return in spp_flags*/
|
||||
params.spp_flags = sp->param_flags;
|
||||
}
|
||||
|
||||
done:
|
||||
if (copy_to_user(optval, ¶ms, len))
|
||||
return -EFAULT;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue