diff options
-rw-r--r-- | net/tipc/socket.c | 143 |
1 files changed, 72 insertions, 71 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 348e4ff881ab..df1960384364 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -1248,77 +1248,78 @@ static void wakeupdispatch(struct tipc_port *tport) | |||
1248 | static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | 1248 | static int connect(struct socket *sock, struct sockaddr *dest, int destlen, |
1249 | int flags) | 1249 | int flags) |
1250 | { | 1250 | { |
1251 | struct tipc_sock *tsock = tipc_sk(sock->sk); | 1251 | struct tipc_sock *tsock = tipc_sk(sock->sk); |
1252 | struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest; | 1252 | struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest; |
1253 | struct msghdr m = {NULL,}; | 1253 | struct msghdr m = {NULL,}; |
1254 | struct sk_buff *buf; | 1254 | struct sk_buff *buf; |
1255 | struct tipc_msg *msg; | 1255 | struct tipc_msg *msg; |
1256 | int res; | 1256 | int res; |
1257 | 1257 | ||
1258 | /* For now, TIPC does not allow use of connect() with DGRAM or RDM types */ | 1258 | /* For now, TIPC does not allow use of connect() with DGRAM/RDM types */ |
1259 | 1259 | ||
1260 | if (sock->state == SS_READY) | 1260 | if (sock->state == SS_READY) |
1261 | return -EOPNOTSUPP; | 1261 | return -EOPNOTSUPP; |
1262 | 1262 | ||
1263 | /* For now, TIPC does not support the non-blocking form of connect() */ | 1263 | /* For now, TIPC does not support the non-blocking form of connect() */ |
1264 | 1264 | ||
1265 | if (flags & O_NONBLOCK) | 1265 | if (flags & O_NONBLOCK) |
1266 | return -EWOULDBLOCK; | 1266 | return -EWOULDBLOCK; |
1267 | 1267 | ||
1268 | /* Issue Posix-compliant error code if socket is in the wrong state */ | 1268 | /* Issue Posix-compliant error code if socket is in the wrong state */ |
1269 | 1269 | ||
1270 | if (sock->state == SS_LISTENING) | 1270 | if (sock->state == SS_LISTENING) |
1271 | return -EOPNOTSUPP; | 1271 | return -EOPNOTSUPP; |
1272 | if (sock->state == SS_CONNECTING) | 1272 | if (sock->state == SS_CONNECTING) |
1273 | return -EALREADY; | 1273 | return -EALREADY; |
1274 | if (sock->state != SS_UNCONNECTED) | 1274 | if (sock->state != SS_UNCONNECTED) |
1275 | return -EISCONN; | 1275 | return -EISCONN; |
1276 | 1276 | ||
1277 | /* | 1277 | /* |
1278 | * Reject connection attempt using multicast address | 1278 | * Reject connection attempt using multicast address |
1279 | * | 1279 | * |
1280 | * Note: send_msg() validates the rest of the address fields, | 1280 | * Note: send_msg() validates the rest of the address fields, |
1281 | * so there's no need to do it here | 1281 | * so there's no need to do it here |
1282 | */ | 1282 | */ |
1283 | 1283 | ||
1284 | if (dst->addrtype == TIPC_ADDR_MCAST) | 1284 | if (dst->addrtype == TIPC_ADDR_MCAST) |
1285 | return -EINVAL; | 1285 | return -EINVAL; |
1286 | 1286 | ||
1287 | /* Send a 'SYN-' to destination */ | 1287 | /* Send a 'SYN-' to destination */ |
1288 | 1288 | ||
1289 | m.msg_name = dest; | 1289 | m.msg_name = dest; |
1290 | m.msg_namelen = destlen; | 1290 | m.msg_namelen = destlen; |
1291 | if ((res = send_msg(NULL, sock, &m, 0)) < 0) { | 1291 | res = send_msg(NULL, sock, &m, 0); |
1292 | sock->state = SS_DISCONNECTING; | 1292 | if (res < 0) { |
1293 | return res; | 1293 | sock->state = SS_DISCONNECTING; |
1294 | } | 1294 | return res; |
1295 | 1295 | } | |
1296 | if (mutex_lock_interruptible(&tsock->lock)) | 1296 | |
1297 | return -ERESTARTSYS; | 1297 | if (mutex_lock_interruptible(&tsock->lock)) |
1298 | 1298 | return -ERESTARTSYS; | |
1299 | /* Wait for destination's 'ACK' response */ | 1299 | |
1300 | 1300 | /* Wait for destination's 'ACK' response */ | |
1301 | res = wait_event_interruptible_timeout(*sock->sk->sk_sleep, | 1301 | |
1302 | skb_queue_len(&sock->sk->sk_receive_queue), | 1302 | res = wait_event_interruptible_timeout(*sock->sk->sk_sleep, |
1303 | sock->sk->sk_rcvtimeo); | 1303 | skb_queue_len(&sock->sk->sk_receive_queue), |
1304 | buf = skb_peek(&sock->sk->sk_receive_queue); | 1304 | sock->sk->sk_rcvtimeo); |
1305 | if (res > 0) { | 1305 | buf = skb_peek(&sock->sk->sk_receive_queue); |
1306 | msg = buf_msg(buf); | 1306 | if (res > 0) { |
1307 | res = auto_connect(sock, tsock, msg); | 1307 | msg = buf_msg(buf); |
1308 | if (!res) { | 1308 | res = auto_connect(sock, tsock, msg); |
1309 | if (!msg_data_sz(msg)) | 1309 | if (!res) { |
1310 | advance_queue(tsock); | 1310 | if (!msg_data_sz(msg)) |
1311 | } | 1311 | advance_queue(tsock); |
1312 | } else { | 1312 | } |
1313 | if (res == 0) { | 1313 | } else { |
1314 | res = -ETIMEDOUT; | 1314 | if (res == 0) |
1315 | } else | 1315 | res = -ETIMEDOUT; |
1316 | { /* leave "res" unchanged */ } | 1316 | else |
1317 | sock->state = SS_DISCONNECTING; | 1317 | ; /* leave "res" unchanged */ |
1318 | } | 1318 | sock->state = SS_DISCONNECTING; |
1319 | 1319 | } | |
1320 | mutex_unlock(&tsock->lock); | 1320 | |
1321 | return res; | 1321 | mutex_unlock(&tsock->lock); |
1322 | return res; | ||
1322 | } | 1323 | } |
1323 | 1324 | ||
1324 | /** | 1325 | /** |