aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2008-05-09 18:14:11 -0400
committerDavid S. Miller <davem@davemloft.net>2008-05-09 18:14:11 -0400
commit88a0a948e752bb9b617a8c55417a9fd9b0257199 (patch)
tree029e51ae711181e0c3e27432f54e9992b998525f /net
parentd364d9276b54af16fcb4db83f1315b620daec102 (diff)
sctp: Support the new specification of sctp_connectx()
The specification of sctp_connectx() has been changed to return an association id. We've added a new socket option that will return the association id as the return value from the setsockopt() call. The library that implements sctp_connectx() interface will implement both socket options. Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/sctp/socket.c70
1 files changed, 59 insertions, 11 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 66985871401b..81600eea05d2 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -956,7 +956,8 @@ out:
956 */ 956 */
957static int __sctp_connect(struct sock* sk, 957static int __sctp_connect(struct sock* sk,
958 struct sockaddr *kaddrs, 958 struct sockaddr *kaddrs,
959 int addrs_size) 959 int addrs_size,
960 sctp_assoc_t *assoc_id)
960{ 961{
961 struct sctp_sock *sp; 962 struct sctp_sock *sp;
962 struct sctp_endpoint *ep; 963 struct sctp_endpoint *ep;
@@ -1111,6 +1112,8 @@ static int __sctp_connect(struct sock* sk,
1111 timeo = sock_sndtimeo(sk, f_flags & O_NONBLOCK); 1112 timeo = sock_sndtimeo(sk, f_flags & O_NONBLOCK);
1112 1113
1113 err = sctp_wait_for_connect(asoc, &timeo); 1114 err = sctp_wait_for_connect(asoc, &timeo);
1115 if (!err && assoc_id)
1116 *assoc_id = asoc->assoc_id;
1114 1117
1115 /* Don't free association on exit. */ 1118 /* Don't free association on exit. */
1116 asoc = NULL; 1119 asoc = NULL;
@@ -1128,7 +1131,8 @@ out_free:
1128/* Helper for tunneling sctp_connectx() requests through sctp_setsockopt() 1131/* Helper for tunneling sctp_connectx() requests through sctp_setsockopt()
1129 * 1132 *
1130 * API 8.9 1133 * API 8.9
1131 * int sctp_connectx(int sd, struct sockaddr *addrs, int addrcnt); 1134 * int sctp_connectx(int sd, struct sockaddr *addrs, int addrcnt,
1135 * sctp_assoc_t *asoc);
1132 * 1136 *
1133 * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses. 1137 * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses.
1134 * If the sd is an IPv6 socket, the addresses passed can either be IPv4 1138 * If the sd is an IPv6 socket, the addresses passed can either be IPv4
@@ -1144,8 +1148,10 @@ out_free:
1144 * representation is termed a "packed array" of addresses). The caller 1148 * representation is termed a "packed array" of addresses). The caller
1145 * specifies the number of addresses in the array with addrcnt. 1149 * specifies the number of addresses in the array with addrcnt.
1146 * 1150 *
1147 * On success, sctp_connectx() returns 0. On failure, sctp_connectx() returns 1151 * On success, sctp_connectx() returns 0. It also sets the assoc_id to
1148 * -1, and sets errno to the appropriate error code. 1152 * the association id of the new association. On failure, sctp_connectx()
1153 * returns -1, and sets errno to the appropriate error code. The assoc_id
1154 * is not touched by the kernel.
1149 * 1155 *
1150 * For SCTP, the port given in each socket address must be the same, or 1156 * For SCTP, the port given in each socket address must be the same, or
1151 * sctp_connectx() will fail, setting errno to EINVAL. 1157 * sctp_connectx() will fail, setting errno to EINVAL.
@@ -1182,11 +1188,12 @@ out_free:
1182 * addrs The pointer to the addresses in user land 1188 * addrs The pointer to the addresses in user land
1183 * addrssize Size of the addrs buffer 1189 * addrssize Size of the addrs buffer
1184 * 1190 *
1185 * Returns 0 if ok, <0 errno code on error. 1191 * Returns >=0 if ok, <0 errno code on error.
1186 */ 1192 */
1187SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk, 1193SCTP_STATIC int __sctp_setsockopt_connectx(struct sock* sk,
1188 struct sockaddr __user *addrs, 1194 struct sockaddr __user *addrs,
1189 int addrs_size) 1195 int addrs_size,
1196 sctp_assoc_t *assoc_id)
1190{ 1197{
1191 int err = 0; 1198 int err = 0;
1192 struct sockaddr *kaddrs; 1199 struct sockaddr *kaddrs;
@@ -1209,13 +1216,46 @@ SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk,
1209 if (__copy_from_user(kaddrs, addrs, addrs_size)) { 1216 if (__copy_from_user(kaddrs, addrs, addrs_size)) {
1210 err = -EFAULT; 1217 err = -EFAULT;
1211 } else { 1218 } else {
1212 err = __sctp_connect(sk, kaddrs, addrs_size); 1219 err = __sctp_connect(sk, kaddrs, addrs_size, assoc_id);
1213 } 1220 }
1214 1221
1215 kfree(kaddrs); 1222 kfree(kaddrs);
1223
1216 return err; 1224 return err;
1217} 1225}
1218 1226
1227/*
1228 * This is an older interface. It's kept for backward compatibility
1229 * to the option that doesn't provide association id.
1230 */
1231SCTP_STATIC int sctp_setsockopt_connectx_old(struct sock* sk,
1232 struct sockaddr __user *addrs,
1233 int addrs_size)
1234{
1235 return __sctp_setsockopt_connectx(sk, addrs, addrs_size, NULL);
1236}
1237
1238/*
1239 * New interface for the API. The since the API is done with a socket
1240 * option, to make it simple we feed back the association id is as a return
1241 * indication to the call. Error is always negative and association id is
1242 * always positive.
1243 */
1244SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk,
1245 struct sockaddr __user *addrs,
1246 int addrs_size)
1247{
1248 sctp_assoc_t assoc_id = 0;
1249 int err = 0;
1250
1251 err = __sctp_setsockopt_connectx(sk, addrs, addrs_size, &assoc_id);
1252
1253 if (err)
1254 return err;
1255 else
1256 return assoc_id;
1257}
1258
1219/* API 3.1.4 close() - UDP Style Syntax 1259/* API 3.1.4 close() - UDP Style Syntax
1220 * Applications use close() to perform graceful shutdown (as described in 1260 * Applications use close() to perform graceful shutdown (as described in
1221 * Section 10.1 of [SCTP]) on ALL the associations currently represented 1261 * Section 10.1 of [SCTP]) on ALL the associations currently represented
@@ -3206,10 +3246,18 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
3206 optlen, SCTP_BINDX_REM_ADDR); 3246 optlen, SCTP_BINDX_REM_ADDR);
3207 break; 3247 break;
3208 3248
3249 case SCTP_SOCKOPT_CONNECTX_OLD:
3250 /* 'optlen' is the size of the addresses buffer. */
3251 retval = sctp_setsockopt_connectx_old(sk,
3252 (struct sockaddr __user *)optval,
3253 optlen);
3254 break;
3255
3209 case SCTP_SOCKOPT_CONNECTX: 3256 case SCTP_SOCKOPT_CONNECTX:
3210 /* 'optlen' is the size of the addresses buffer. */ 3257 /* 'optlen' is the size of the addresses buffer. */
3211 retval = sctp_setsockopt_connectx(sk, (struct sockaddr __user *)optval, 3258 retval = sctp_setsockopt_connectx(sk,
3212 optlen); 3259 (struct sockaddr __user *)optval,
3260 optlen);
3213 break; 3261 break;
3214 3262
3215 case SCTP_DISABLE_FRAGMENTS: 3263 case SCTP_DISABLE_FRAGMENTS:
@@ -3336,7 +3384,7 @@ SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *addr,
3336 /* Pass correct addr len to common routine (so it knows there 3384 /* Pass correct addr len to common routine (so it knows there
3337 * is only one address being passed. 3385 * is only one address being passed.
3338 */ 3386 */
3339 err = __sctp_connect(sk, addr, af->sockaddr_len); 3387 err = __sctp_connect(sk, addr, af->sockaddr_len, NULL);
3340 } 3388 }
3341 3389
3342 sctp_release_sock(sk); 3390 sctp_release_sock(sk);