diff options
author | Frank Filz <ffilz@us.ibm.com> | 2005-12-22 14:36:46 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-01-03 16:11:11 -0500 |
commit | 52ccb8e90c0ace233b8b740f2fc5de0dbd706b27 (patch) | |
tree | d2c06dd7b26e70c8dccf31971508005fdc82cbb2 /net/sctp/socket.c | |
parent | fd9662555cc35f8bf9242cd7bba8b44ae168a68b (diff) |
[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>
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r-- | net/sctp/socket.c | 511 |
1 files changed, 385 insertions, 126 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 9df888e932c5..adb5ee62c2a6 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -1941,106 +1941,275 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval, | |||
1941 | * address's parameters: | 1941 | * address's parameters: |
1942 | * | 1942 | * |
1943 | * struct sctp_paddrparams { | 1943 | * struct sctp_paddrparams { |
1944 | * sctp_assoc_t spp_assoc_id; | 1944 | * sctp_assoc_t spp_assoc_id; |
1945 | * struct sockaddr_storage spp_address; | 1945 | * struct sockaddr_storage spp_address; |
1946 | * uint32_t spp_hbinterval; | 1946 | * uint32_t spp_hbinterval; |
1947 | * uint16_t spp_pathmaxrxt; | 1947 | * uint16_t spp_pathmaxrxt; |
1948 | * }; | 1948 | * uint32_t spp_pathmtu; |
1949 | * | 1949 | * uint32_t spp_sackdelay; |
1950 | * spp_assoc_id - (UDP style socket) This is filled in the application, | 1950 | * uint32_t spp_flags; |
1951 | * and identifies the association for this query. | 1951 | * }; |
1952 | * | ||
1953 | * spp_assoc_id - (one-to-many style socket) This is filled in the | ||
1954 | * application, and identifies the association for | ||
1955 | * this query. | ||
1952 | * spp_address - This specifies which address is of interest. | 1956 | * spp_address - This specifies which address is of interest. |
1953 | * spp_hbinterval - This contains the value of the heartbeat interval, | 1957 | * spp_hbinterval - This contains the value of the heartbeat interval, |
1954 | * in milliseconds. A value of 0, when modifying the | 1958 | * in milliseconds. If a value of zero |
1955 | * parameter, specifies that the heartbeat on this | 1959 | * is present in this field then no changes are to |
1956 | * address should be disabled. A value of UINT32_MAX | 1960 | * be made to this parameter. |
1957 | * (4294967295), when modifying the parameter, | ||
1958 | * specifies that a heartbeat should be sent | ||
1959 | * immediately to the peer address, and the current | ||
1960 | * interval should remain unchanged. | ||
1961 | * spp_pathmaxrxt - This contains the maximum number of | 1961 | * spp_pathmaxrxt - This contains the maximum number of |
1962 | * retransmissions before this address shall be | 1962 | * retransmissions before this address shall be |
1963 | * considered unreachable. | 1963 | * considered unreachable. If a value of zero |
1964 | * is present in this field then no changes are to | ||
1965 | * be made to this parameter. | ||
1966 | * spp_pathmtu - When Path MTU discovery is disabled the value | ||
1967 | * specified here will be the "fixed" path mtu. | ||
1968 | * Note that if the spp_address field is empty | ||
1969 | * then all associations on this address will | ||
1970 | * have this fixed path mtu set upon them. | ||
1971 | * | ||
1972 | * spp_sackdelay - When delayed sack is enabled, this value specifies | ||
1973 | * the number of milliseconds that sacks will be delayed | ||
1974 | * for. This value will apply to all addresses of an | ||
1975 | * association if the spp_address field is empty. Note | ||
1976 | * also, that if delayed sack is enabled and this | ||
1977 | * value is set to 0, no change is made to the last | ||
1978 | * recorded delayed sack timer value. | ||
1979 | * | ||
1980 | * spp_flags - These flags are used to control various features | ||
1981 | * on an association. The flag field may contain | ||
1982 | * zero or more of the following options. | ||
1983 | * | ||
1984 | * SPP_HB_ENABLE - Enable heartbeats on the | ||
1985 | * specified address. Note that if the address | ||
1986 | * field is empty all addresses for the association | ||
1987 | * have heartbeats enabled upon them. | ||
1988 | * | ||
1989 | * SPP_HB_DISABLE - Disable heartbeats on the | ||
1990 | * speicifed address. Note that if the address | ||
1991 | * field is empty all addresses for the association | ||
1992 | * will have their heartbeats disabled. Note also | ||
1993 | * that SPP_HB_ENABLE and SPP_HB_DISABLE are | ||
1994 | * mutually exclusive, only one of these two should | ||
1995 | * be specified. Enabling both fields will have | ||
1996 | * undetermined results. | ||
1997 | * | ||
1998 | * SPP_HB_DEMAND - Request a user initiated heartbeat | ||
1999 | * to be made immediately. | ||
2000 | * | ||
2001 | * SPP_PMTUD_ENABLE - This field will enable PMTU | ||
2002 | * discovery upon the specified address. Note that | ||
2003 | * if the address feild is empty then all addresses | ||
2004 | * on the association are effected. | ||
2005 | * | ||
2006 | * SPP_PMTUD_DISABLE - This field will disable PMTU | ||
2007 | * discovery upon the specified address. Note that | ||
2008 | * if the address feild is empty then all addresses | ||
2009 | * on the association are effected. Not also that | ||
2010 | * SPP_PMTUD_ENABLE and SPP_PMTUD_DISABLE are mutually | ||
2011 | * exclusive. Enabling both will have undetermined | ||
2012 | * results. | ||
2013 | * | ||
2014 | * SPP_SACKDELAY_ENABLE - Setting this flag turns | ||
2015 | * on delayed sack. The time specified in spp_sackdelay | ||
2016 | * is used to specify the sack delay for this address. Note | ||
2017 | * that if spp_address is empty then all addresses will | ||
2018 | * enable delayed sack and take on the sack delay | ||
2019 | * value specified in spp_sackdelay. | ||
2020 | * SPP_SACKDELAY_DISABLE - Setting this flag turns | ||
2021 | * off delayed sack. If the spp_address field is blank then | ||
2022 | * delayed sack is disabled for the entire association. Note | ||
2023 | * also that this field is mutually exclusive to | ||
2024 | * SPP_SACKDELAY_ENABLE, setting both will have undefined | ||
2025 | * results. | ||
1964 | */ | 2026 | */ |
2027 | int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, | ||
2028 | struct sctp_transport *trans, | ||
2029 | struct sctp_association *asoc, | ||
2030 | struct sctp_sock *sp, | ||
2031 | int hb_change, | ||
2032 | int pmtud_change, | ||
2033 | int sackdelay_change) | ||
2034 | { | ||
2035 | int error; | ||
2036 | |||
2037 | if (params->spp_flags & SPP_HB_DEMAND && trans) { | ||
2038 | error = sctp_primitive_REQUESTHEARTBEAT (trans->asoc, trans); | ||
2039 | if (error) | ||
2040 | return error; | ||
2041 | } | ||
2042 | |||
2043 | if (params->spp_hbinterval) { | ||
2044 | if (trans) { | ||
2045 | trans->hbinterval = msecs_to_jiffies(params->spp_hbinterval); | ||
2046 | } else if (asoc) { | ||
2047 | asoc->hbinterval = msecs_to_jiffies(params->spp_hbinterval); | ||
2048 | } else { | ||
2049 | sp->hbinterval = params->spp_hbinterval; | ||
2050 | } | ||
2051 | } | ||
2052 | |||
2053 | if (hb_change) { | ||
2054 | if (trans) { | ||
2055 | trans->param_flags = | ||
2056 | (trans->param_flags & ~SPP_HB) | hb_change; | ||
2057 | } else if (asoc) { | ||
2058 | asoc->param_flags = | ||
2059 | (asoc->param_flags & ~SPP_HB) | hb_change; | ||
2060 | } else { | ||
2061 | sp->param_flags = | ||
2062 | (sp->param_flags & ~SPP_HB) | hb_change; | ||
2063 | } | ||
2064 | } | ||
2065 | |||
2066 | if (params->spp_pathmtu) { | ||
2067 | if (trans) { | ||
2068 | trans->pathmtu = params->spp_pathmtu; | ||
2069 | sctp_assoc_sync_pmtu(asoc); | ||
2070 | } else if (asoc) { | ||
2071 | asoc->pathmtu = params->spp_pathmtu; | ||
2072 | sctp_frag_point(sp, params->spp_pathmtu); | ||
2073 | } else { | ||
2074 | sp->pathmtu = params->spp_pathmtu; | ||
2075 | } | ||
2076 | } | ||
2077 | |||
2078 | if (pmtud_change) { | ||
2079 | if (trans) { | ||
2080 | int update = (trans->param_flags & SPP_PMTUD_DISABLE) && | ||
2081 | (params->spp_flags & SPP_PMTUD_ENABLE); | ||
2082 | trans->param_flags = | ||
2083 | (trans->param_flags & ~SPP_PMTUD) | pmtud_change; | ||
2084 | if (update) { | ||
2085 | sctp_transport_pmtu(trans); | ||
2086 | sctp_assoc_sync_pmtu(asoc); | ||
2087 | } | ||
2088 | } else if (asoc) { | ||
2089 | asoc->param_flags = | ||
2090 | (asoc->param_flags & ~SPP_PMTUD) | pmtud_change; | ||
2091 | } else { | ||
2092 | sp->param_flags = | ||
2093 | (sp->param_flags & ~SPP_PMTUD) | pmtud_change; | ||
2094 | } | ||
2095 | } | ||
2096 | |||
2097 | if (params->spp_sackdelay) { | ||
2098 | if (trans) { | ||
2099 | trans->sackdelay = | ||
2100 | msecs_to_jiffies(params->spp_sackdelay); | ||
2101 | } else if (asoc) { | ||
2102 | asoc->sackdelay = | ||
2103 | msecs_to_jiffies(params->spp_sackdelay); | ||
2104 | } else { | ||
2105 | sp->sackdelay = params->spp_sackdelay; | ||
2106 | } | ||
2107 | } | ||
2108 | |||
2109 | if (sackdelay_change) { | ||
2110 | if (trans) { | ||
2111 | trans->param_flags = | ||
2112 | (trans->param_flags & ~SPP_SACKDELAY) | | ||
2113 | sackdelay_change; | ||
2114 | } else if (asoc) { | ||
2115 | asoc->param_flags = | ||
2116 | (asoc->param_flags & ~SPP_SACKDELAY) | | ||
2117 | sackdelay_change; | ||
2118 | } else { | ||
2119 | sp->param_flags = | ||
2120 | (sp->param_flags & ~SPP_SACKDELAY) | | ||
2121 | sackdelay_change; | ||
2122 | } | ||
2123 | } | ||
2124 | |||
2125 | if (params->spp_pathmaxrxt) { | ||
2126 | if (trans) { | ||
2127 | trans->pathmaxrxt = params->spp_pathmaxrxt; | ||
2128 | } else if (asoc) { | ||
2129 | asoc->pathmaxrxt = params->spp_pathmaxrxt; | ||
2130 | } else { | ||
2131 | sp->pathmaxrxt = params->spp_pathmaxrxt; | ||
2132 | } | ||
2133 | } | ||
2134 | |||
2135 | return 0; | ||
2136 | } | ||
2137 | |||
1965 | static int sctp_setsockopt_peer_addr_params(struct sock *sk, | 2138 | static int sctp_setsockopt_peer_addr_params(struct sock *sk, |
1966 | char __user *optval, int optlen) | 2139 | char __user *optval, int optlen) |
1967 | { | 2140 | { |
1968 | struct sctp_paddrparams params; | 2141 | struct sctp_paddrparams params; |
1969 | struct sctp_transport *trans; | 2142 | struct sctp_transport *trans = NULL; |
2143 | struct sctp_association *asoc = NULL; | ||
2144 | struct sctp_sock *sp = sctp_sk(sk); | ||
1970 | int error; | 2145 | int error; |
2146 | int hb_change, pmtud_change, sackdelay_change; | ||
1971 | 2147 | ||
1972 | if (optlen != sizeof(struct sctp_paddrparams)) | 2148 | if (optlen != sizeof(struct sctp_paddrparams)) |
1973 | return -EINVAL; | 2149 | return - EINVAL; |
2150 | |||
1974 | if (copy_from_user(¶ms, optval, optlen)) | 2151 | if (copy_from_user(¶ms, optval, optlen)) |
1975 | return -EFAULT; | 2152 | return -EFAULT; |
1976 | 2153 | ||
1977 | /* | 2154 | /* Validate flags and value parameters. */ |
1978 | * API 7. Socket Options (setting the default value for the endpoint) | 2155 | hb_change = params.spp_flags & SPP_HB; |
1979 | * All options that support specific settings on an association by | 2156 | pmtud_change = params.spp_flags & SPP_PMTUD; |
1980 | * filling in either an association id variable or a sockaddr_storage | 2157 | sackdelay_change = params.spp_flags & SPP_SACKDELAY; |
1981 | * SHOULD also support setting of the same value for the entire endpoint | 2158 | |
1982 | * (i.e. future associations). To accomplish this the following logic is | 2159 | if (hb_change == SPP_HB || |
1983 | * used when setting one of these options: | 2160 | pmtud_change == SPP_PMTUD || |
1984 | 2161 | sackdelay_change == SPP_SACKDELAY || | |
1985 | * c) If neither the sockaddr_storage or association identification is | 2162 | params.spp_sackdelay > 500 || |
1986 | * set i.e. the sockaddr_storage is set to all 0's (INADDR_ANY) and | 2163 | (params.spp_pathmtu |
1987 | * the association identification is 0, the settings are a default | 2164 | && params.spp_pathmtu < SCTP_DEFAULT_MINSEGMENT)) |
1988 | * and to be applied to the endpoint (all future associations). | 2165 | return -EINVAL; |
1989 | */ | ||
1990 | 2166 | ||
1991 | /* update default value for endpoint (all future associations) */ | 2167 | /* If an address other than INADDR_ANY is specified, and |
1992 | if (!params.spp_assoc_id && | 2168 | * no transport is found, then the request is invalid. |
1993 | sctp_is_any(( union sctp_addr *)¶ms.spp_address)) { | 2169 | */ |
1994 | /* Manual heartbeat on an endpoint is invalid. */ | 2170 | if (!sctp_is_any(( union sctp_addr *)¶ms.spp_address)) { |
1995 | if (0xffffffff == params.spp_hbinterval) | 2171 | trans = sctp_addr_id2transport(sk, ¶ms.spp_address, |
2172 | params.spp_assoc_id); | ||
2173 | if (!trans) | ||
1996 | return -EINVAL; | 2174 | return -EINVAL; |
1997 | else if (params.spp_hbinterval) | ||
1998 | sctp_sk(sk)->paddrparam.spp_hbinterval = | ||
1999 | params.spp_hbinterval; | ||
2000 | if (params.spp_pathmaxrxt) | ||
2001 | sctp_sk(sk)->paddrparam.spp_pathmaxrxt = | ||
2002 | params.spp_pathmaxrxt; | ||
2003 | return 0; | ||
2004 | } | 2175 | } |
2005 | 2176 | ||
2006 | trans = sctp_addr_id2transport(sk, ¶ms.spp_address, | 2177 | /* Get association, if assoc_id != 0 and the socket is a one |
2007 | params.spp_assoc_id); | 2178 | * to many style socket, and an association was not found, then |
2008 | if (!trans) | 2179 | * the id was invalid. |
2180 | */ | ||
2181 | asoc = sctp_id2assoc(sk, params.spp_assoc_id); | ||
2182 | if (!asoc && params.spp_assoc_id && sctp_style(sk, UDP)) | ||
2009 | return -EINVAL; | 2183 | return -EINVAL; |
2010 | 2184 | ||
2011 | /* Applications can enable or disable heartbeats for any peer address | 2185 | /* Heartbeat demand can only be sent on a transport or |
2012 | * of an association, modify an address's heartbeat interval, force a | 2186 | * association, but not a socket. |
2013 | * heartbeat to be sent immediately, and adjust the address's maximum | ||
2014 | * number of retransmissions sent before an address is considered | ||
2015 | * unreachable. | ||
2016 | * | ||
2017 | * The value of the heartbeat interval, in milliseconds. A value of | ||
2018 | * UINT32_MAX (4294967295), when modifying the parameter, specifies | ||
2019 | * that a heartbeat should be sent immediately to the peer address, | ||
2020 | * and the current interval should remain unchanged. | ||
2021 | */ | ||
2022 | if (0xffffffff == params.spp_hbinterval) { | ||
2023 | error = sctp_primitive_REQUESTHEARTBEAT (trans->asoc, trans); | ||
2024 | if (error) | ||
2025 | return error; | ||
2026 | } else { | ||
2027 | /* The value of the heartbeat interval, in milliseconds. A value of 0, | ||
2028 | * when modifying the parameter, specifies that the heartbeat on this | ||
2029 | * address should be disabled. | ||
2030 | */ | 2187 | */ |
2031 | if (params.spp_hbinterval) { | 2188 | if (params.spp_flags & SPP_HB_DEMAND && !trans && !asoc) |
2032 | trans->hb_allowed = 1; | 2189 | return -EINVAL; |
2033 | trans->hb_interval = | 2190 | |
2034 | msecs_to_jiffies(params.spp_hbinterval); | 2191 | /* Process parameters. */ |
2035 | } else | 2192 | error = sctp_apply_peer_addr_params(¶ms, trans, asoc, sp, |
2036 | trans->hb_allowed = 0; | 2193 | hb_change, pmtud_change, |
2037 | } | 2194 | sackdelay_change); |
2038 | 2195 | ||
2039 | /* spp_pathmaxrxt contains the maximum number of retransmissions | 2196 | if (error) |
2040 | * before this address shall be considered unreachable. | 2197 | return error; |
2198 | |||
2199 | /* If changes are for association, also apply parameters to each | ||
2200 | * transport. | ||
2041 | */ | 2201 | */ |
2042 | if (params.spp_pathmaxrxt) | 2202 | if (!trans && asoc) { |
2043 | trans->max_retrans = params.spp_pathmaxrxt; | 2203 | struct list_head *pos; |
2204 | |||
2205 | list_for_each(pos, &asoc->peer.transport_addr_list) { | ||
2206 | trans = list_entry(pos, struct sctp_transport, | ||
2207 | transports); | ||
2208 | sctp_apply_peer_addr_params(¶ms, trans, asoc, sp, | ||
2209 | hb_change, pmtud_change, | ||
2210 | sackdelay_change); | ||
2211 | } | ||
2212 | } | ||
2044 | 2213 | ||
2045 | return 0; | 2214 | return 0; |
2046 | } | 2215 | } |
@@ -2334,7 +2503,7 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optl | |||
2334 | /* Update the frag_point of the existing associations. */ | 2503 | /* Update the frag_point of the existing associations. */ |
2335 | list_for_each(pos, &(sp->ep->asocs)) { | 2504 | list_for_each(pos, &(sp->ep->asocs)) { |
2336 | asoc = list_entry(pos, struct sctp_association, asocs); | 2505 | asoc = list_entry(pos, struct sctp_association, asocs); |
2337 | asoc->frag_point = sctp_frag_point(sp, asoc->pmtu); | 2506 | asoc->frag_point = sctp_frag_point(sp, asoc->pathmtu); |
2338 | } | 2507 | } |
2339 | 2508 | ||
2340 | return 0; | 2509 | return 0; |
@@ -2715,8 +2884,13 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) | |||
2715 | /* Default Peer Address Parameters. These defaults can | 2884 | /* Default Peer Address Parameters. These defaults can |
2716 | * be modified via SCTP_PEER_ADDR_PARAMS | 2885 | * be modified via SCTP_PEER_ADDR_PARAMS |
2717 | */ | 2886 | */ |
2718 | sp->paddrparam.spp_hbinterval = jiffies_to_msecs(sctp_hb_interval); | 2887 | sp->hbinterval = jiffies_to_msecs(sctp_hb_interval); |
2719 | sp->paddrparam.spp_pathmaxrxt = sctp_max_retrans_path; | 2888 | sp->pathmaxrxt = sctp_max_retrans_path; |
2889 | sp->pathmtu = 0; // allow default discovery | ||
2890 | sp->sackdelay = sctp_sack_timeout; | ||
2891 | sp->param_flags = SPP_HB_ENABLE | | ||
2892 | SPP_PMTUD_ENABLE | | ||
2893 | SPP_SACKDELAY_ENABLE; | ||
2720 | 2894 | ||
2721 | /* If enabled no SCTP message fragmentation will be performed. | 2895 | /* If enabled no SCTP message fragmentation will be performed. |
2722 | * Configure through SCTP_DISABLE_FRAGMENTS socket option. | 2896 | * Configure through SCTP_DISABLE_FRAGMENTS socket option. |
@@ -2865,7 +3039,7 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, | |||
2865 | status.sstat_primary.spinfo_cwnd = transport->cwnd; | 3039 | status.sstat_primary.spinfo_cwnd = transport->cwnd; |
2866 | status.sstat_primary.spinfo_srtt = transport->srtt; | 3040 | status.sstat_primary.spinfo_srtt = transport->srtt; |
2867 | status.sstat_primary.spinfo_rto = jiffies_to_msecs(transport->rto); | 3041 | status.sstat_primary.spinfo_rto = jiffies_to_msecs(transport->rto); |
2868 | status.sstat_primary.spinfo_mtu = transport->pmtu; | 3042 | status.sstat_primary.spinfo_mtu = transport->pathmtu; |
2869 | 3043 | ||
2870 | if (status.sstat_primary.spinfo_state == SCTP_UNKNOWN) | 3044 | if (status.sstat_primary.spinfo_state == SCTP_UNKNOWN) |
2871 | status.sstat_primary.spinfo_state = SCTP_ACTIVE; | 3045 | status.sstat_primary.spinfo_state = SCTP_ACTIVE; |
@@ -2924,7 +3098,7 @@ static int sctp_getsockopt_peer_addr_info(struct sock *sk, int len, | |||
2924 | pinfo.spinfo_cwnd = transport->cwnd; | 3098 | pinfo.spinfo_cwnd = transport->cwnd; |
2925 | pinfo.spinfo_srtt = transport->srtt; | 3099 | pinfo.spinfo_srtt = transport->srtt; |
2926 | pinfo.spinfo_rto = jiffies_to_msecs(transport->rto); | 3100 | pinfo.spinfo_rto = jiffies_to_msecs(transport->rto); |
2927 | pinfo.spinfo_mtu = transport->pmtu; | 3101 | pinfo.spinfo_mtu = transport->pathmtu; |
2928 | 3102 | ||
2929 | if (pinfo.spinfo_state == SCTP_UNKNOWN) | 3103 | if (pinfo.spinfo_state == SCTP_UNKNOWN) |
2930 | pinfo.spinfo_state = SCTP_ACTIVE; | 3104 | pinfo.spinfo_state = SCTP_ACTIVE; |
@@ -3086,69 +3260,154 @@ out: | |||
3086 | * address's parameters: | 3260 | * address's parameters: |
3087 | * | 3261 | * |
3088 | * struct sctp_paddrparams { | 3262 | * struct sctp_paddrparams { |
3089 | * sctp_assoc_t spp_assoc_id; | 3263 | * sctp_assoc_t spp_assoc_id; |
3090 | * struct sockaddr_storage spp_address; | 3264 | * struct sockaddr_storage spp_address; |
3091 | * uint32_t spp_hbinterval; | 3265 | * uint32_t spp_hbinterval; |
3092 | * uint16_t spp_pathmaxrxt; | 3266 | * uint16_t spp_pathmaxrxt; |
3093 | * }; | 3267 | * uint32_t spp_pathmtu; |
3094 | * | 3268 | * uint32_t spp_sackdelay; |
3095 | * spp_assoc_id - (UDP style socket) This is filled in the application, | 3269 | * uint32_t spp_flags; |
3096 | * and identifies the association for this query. | 3270 | * }; |
3271 | * | ||
3272 | * spp_assoc_id - (one-to-many style socket) This is filled in the | ||
3273 | * application, and identifies the association for | ||
3274 | * this query. | ||
3097 | * spp_address - This specifies which address is of interest. | 3275 | * spp_address - This specifies which address is of interest. |
3098 | * spp_hbinterval - This contains the value of the heartbeat interval, | 3276 | * spp_hbinterval - This contains the value of the heartbeat interval, |
3099 | * in milliseconds. A value of 0, when modifying the | 3277 | * in milliseconds. If a value of zero |
3100 | * parameter, specifies that the heartbeat on this | 3278 | * is present in this field then no changes are to |
3101 | * address should be disabled. A value of UINT32_MAX | 3279 | * be made to this parameter. |
3102 | * (4294967295), when modifying the parameter, | ||
3103 | * specifies that a heartbeat should be sent | ||
3104 | * immediately to the peer address, and the current | ||
3105 | * interval should remain unchanged. | ||
3106 | * spp_pathmaxrxt - This contains the maximum number of | 3280 | * spp_pathmaxrxt - This contains the maximum number of |
3107 | * retransmissions before this address shall be | 3281 | * retransmissions before this address shall be |
3108 | * considered unreachable. | 3282 | * considered unreachable. If a value of zero |
3283 | * is present in this field then no changes are to | ||
3284 | * be made to this parameter. | ||
3285 | * spp_pathmtu - When Path MTU discovery is disabled the value | ||
3286 | * specified here will be the "fixed" path mtu. | ||
3287 | * Note that if the spp_address field is empty | ||
3288 | * then all associations on this address will | ||
3289 | * have this fixed path mtu set upon them. | ||
3290 | * | ||
3291 | * spp_sackdelay - When delayed sack is enabled, this value specifies | ||
3292 | * the number of milliseconds that sacks will be delayed | ||
3293 | * for. This value will apply to all addresses of an | ||
3294 | * association if the spp_address field is empty. Note | ||
3295 | * also, that if delayed sack is enabled and this | ||
3296 | * value is set to 0, no change is made to the last | ||
3297 | * recorded delayed sack timer value. | ||
3298 | * | ||
3299 | * spp_flags - These flags are used to control various features | ||
3300 | * on an association. The flag field may contain | ||
3301 | * zero or more of the following options. | ||
3302 | * | ||
3303 | * SPP_HB_ENABLE - Enable heartbeats on the | ||
3304 | * specified address. Note that if the address | ||
3305 | * field is empty all addresses for the association | ||
3306 | * have heartbeats enabled upon them. | ||
3307 | * | ||
3308 | * SPP_HB_DISABLE - Disable heartbeats on the | ||
3309 | * speicifed address. Note that if the address | ||
3310 | * field is empty all addresses for the association | ||
3311 | * will have their heartbeats disabled. Note also | ||
3312 | * that SPP_HB_ENABLE and SPP_HB_DISABLE are | ||
3313 | * mutually exclusive, only one of these two should | ||
3314 | * be specified. Enabling both fields will have | ||
3315 | * undetermined results. | ||
3316 | * | ||
3317 | * SPP_HB_DEMAND - Request a user initiated heartbeat | ||
3318 | * to be made immediately. | ||
3319 | * | ||
3320 | * SPP_PMTUD_ENABLE - This field will enable PMTU | ||
3321 | * discovery upon the specified address. Note that | ||
3322 | * if the address feild is empty then all addresses | ||
3323 | * on the association are effected. | ||
3324 | * | ||
3325 | * SPP_PMTUD_DISABLE - This field will disable PMTU | ||
3326 | * discovery upon the specified address. Note that | ||
3327 | * if the address feild is empty then all addresses | ||
3328 | * on the association are effected. Not also that | ||
3329 | * SPP_PMTUD_ENABLE and SPP_PMTUD_DISABLE are mutually | ||
3330 | * exclusive. Enabling both will have undetermined | ||
3331 | * results. | ||
3332 | * | ||
3333 | * SPP_SACKDELAY_ENABLE - Setting this flag turns | ||
3334 | * on delayed sack. The time specified in spp_sackdelay | ||
3335 | * is used to specify the sack delay for this address. Note | ||
3336 | * that if spp_address is empty then all addresses will | ||
3337 | * enable delayed sack and take on the sack delay | ||
3338 | * value specified in spp_sackdelay. | ||
3339 | * SPP_SACKDELAY_DISABLE - Setting this flag turns | ||
3340 | * off delayed sack. If the spp_address field is blank then | ||
3341 | * delayed sack is disabled for the entire association. Note | ||
3342 | * also that this field is mutually exclusive to | ||
3343 | * SPP_SACKDELAY_ENABLE, setting both will have undefined | ||
3344 | * results. | ||
3109 | */ | 3345 | */ |
3110 | static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len, | 3346 | static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len, |
3111 | char __user *optval, int __user *optlen) | 3347 | char __user *optval, int __user *optlen) |
3112 | { | 3348 | { |
3113 | struct sctp_paddrparams params; | 3349 | struct sctp_paddrparams params; |
3114 | struct sctp_transport *trans; | 3350 | struct sctp_transport *trans = NULL; |
3351 | struct sctp_association *asoc = NULL; | ||
3352 | struct sctp_sock *sp = sctp_sk(sk); | ||
3115 | 3353 | ||
3116 | if (len != sizeof(struct sctp_paddrparams)) | 3354 | if (len != sizeof(struct sctp_paddrparams)) |
3117 | return -EINVAL; | 3355 | return -EINVAL; |
3356 | |||
3118 | if (copy_from_user(¶ms, optval, len)) | 3357 | if (copy_from_user(¶ms, optval, len)) |
3119 | return -EFAULT; | 3358 | return -EFAULT; |
3120 | 3359 | ||
3121 | /* If no association id is specified retrieve the default value | 3360 | /* If an address other than INADDR_ANY is specified, and |
3122 | * for the endpoint that will be used for all future associations | 3361 | * no transport is found, then the request is invalid. |
3123 | */ | 3362 | */ |
3124 | if (!params.spp_assoc_id && | 3363 | if (!sctp_is_any(( union sctp_addr *)¶ms.spp_address)) { |
3125 | sctp_is_any(( union sctp_addr *)¶ms.spp_address)) { | 3364 | trans = sctp_addr_id2transport(sk, ¶ms.spp_address, |
3126 | params.spp_hbinterval = sctp_sk(sk)->paddrparam.spp_hbinterval; | 3365 | params.spp_assoc_id); |
3127 | params.spp_pathmaxrxt = sctp_sk(sk)->paddrparam.spp_pathmaxrxt; | 3366 | if (!trans) { |
3128 | 3367 | SCTP_DEBUG_PRINTK("Failed no transport\n"); | |
3129 | goto done; | 3368 | return -EINVAL; |
3369 | } | ||
3130 | } | 3370 | } |
3131 | 3371 | ||
3132 | trans = sctp_addr_id2transport(sk, ¶ms.spp_address, | 3372 | /* Get association, if assoc_id != 0 and the socket is a one |
3133 | params.spp_assoc_id); | 3373 | * to many style socket, and an association was not found, then |
3134 | if (!trans) | 3374 | * the id was invalid. |
3135 | return -EINVAL; | ||
3136 | |||
3137 | /* The value of the heartbeat interval, in milliseconds. A value of 0, | ||
3138 | * when modifying the parameter, specifies that the heartbeat on this | ||
3139 | * address should be disabled. | ||
3140 | */ | 3375 | */ |
3141 | if (!trans->hb_allowed) | 3376 | asoc = sctp_id2assoc(sk, params.spp_assoc_id); |
3142 | params.spp_hbinterval = 0; | 3377 | if (!asoc && params.spp_assoc_id && sctp_style(sk, UDP)) { |
3143 | else | 3378 | SCTP_DEBUG_PRINTK("Failed no association\n"); |
3144 | params.spp_hbinterval = jiffies_to_msecs(trans->hb_interval); | 3379 | return -EINVAL; |
3380 | } | ||
3145 | 3381 | ||
3146 | /* spp_pathmaxrxt contains the maximum number of retransmissions | 3382 | if (trans) { |
3147 | * before this address shall be considered unreachable. | 3383 | /* Fetch transport values. */ |
3148 | */ | 3384 | params.spp_hbinterval = jiffies_to_msecs(trans->hbinterval); |
3149 | params.spp_pathmaxrxt = trans->max_retrans; | 3385 | params.spp_pathmtu = trans->pathmtu; |
3386 | params.spp_pathmaxrxt = trans->pathmaxrxt; | ||
3387 | params.spp_sackdelay = jiffies_to_msecs(trans->sackdelay); | ||
3388 | |||
3389 | /*draft-11 doesn't say what to return in spp_flags*/ | ||
3390 | params.spp_flags = trans->param_flags; | ||
3391 | } else if (asoc) { | ||
3392 | /* Fetch association values. */ | ||
3393 | params.spp_hbinterval = jiffies_to_msecs(asoc->hbinterval); | ||
3394 | params.spp_pathmtu = asoc->pathmtu; | ||
3395 | params.spp_pathmaxrxt = asoc->pathmaxrxt; | ||
3396 | params.spp_sackdelay = jiffies_to_msecs(asoc->sackdelay); | ||
3397 | |||
3398 | /*draft-11 doesn't say what to return in spp_flags*/ | ||
3399 | params.spp_flags = asoc->param_flags; | ||
3400 | } else { | ||
3401 | /* Fetch socket values. */ | ||
3402 | params.spp_hbinterval = sp->hbinterval; | ||
3403 | params.spp_pathmtu = sp->pathmtu; | ||
3404 | params.spp_sackdelay = sp->sackdelay; | ||
3405 | params.spp_pathmaxrxt = sp->pathmaxrxt; | ||
3406 | |||
3407 | /*draft-11 doesn't say what to return in spp_flags*/ | ||
3408 | params.spp_flags = sp->param_flags; | ||
3409 | } | ||
3150 | 3410 | ||
3151 | done: | ||
3152 | if (copy_to_user(optval, ¶ms, len)) | 3411 | if (copy_to_user(optval, ¶ms, len)) |
3153 | return -EFAULT; | 3412 | return -EFAULT; |
3154 | 3413 | ||