aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorYing Xue <ying.xue@windriver.com>2012-11-29 18:39:14 -0500
committerPaul Gortmaker <paul.gortmaker@windriver.com>2012-12-07 17:23:20 -0500
commit7e6c131e1568dcc2033736739a9880dce1976886 (patch)
tree218e2e4cdcd69d1e2e58ab707c8cb3561cddc586 /net
parentbc879117d4cf2a6fcf5c5a43f157143bbbe88e84 (diff)
tipc: consolidate connection-oriented message reception in one function
Handling of connection-related message reception is currently scattered around at different places in the code. This makes it harder to verify that things are handled correctly in all possible scenarios. So we consolidate the existing processing of connection-oriented message reception in a single routine. In the process, we convert the chain of if/else into a switch/case for improved readability. A cast on the socket_state in the switch is needed to avoid compile warnings on 32 bit, like "net/tipc/socket.c:1252:2: warning: case value ‘4294967295’ not in enumerated type". This happens because existing tipc code pseudo extends the default linux socket state values with: #define SS_LISTENING -1 /* socket is listening */ #define SS_READY -2 /* socket is connectionless */ It may make sense to add these as _positive_ values to the existing socket state enum list someday, vs. these already existing defines. Signed-off-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> [PG: add cast to fix warning; remove returns from middle of switch] Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/tipc/socket.c75
1 files changed, 51 insertions, 24 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index b630f3839ca3..d16a6de32ea1 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1187,6 +1187,53 @@ static int rx_queue_full(struct tipc_msg *msg, u32 queue_size, u32 base)
1187} 1187}
1188 1188
1189/** 1189/**
1190 * filter_connect - Handle all incoming messages for a connection-based socket
1191 * @tsock: TIPC socket
1192 * @msg: message
1193 *
1194 * Returns TIPC error status code and socket error status code
1195 * once it encounters some errors
1196 */
1197static u32 filter_connect(struct tipc_sock *tsock, struct sk_buff **buf)
1198{
1199 struct socket *sock = tsock->sk.sk_socket;
1200 struct tipc_msg *msg = buf_msg(*buf);
1201 u32 retval = TIPC_ERR_NO_PORT;
1202
1203 if (msg_mcast(msg))
1204 return retval;
1205
1206 switch ((int)sock->state) {
1207 case SS_CONNECTED:
1208 /* Accept only connection-based messages sent by peer */
1209 if (msg_connected(msg) && tipc_port_peer_msg(tsock->p, msg)) {
1210 if (unlikely(msg_errcode(msg))) {
1211 sock->state = SS_DISCONNECTING;
1212 __tipc_disconnect(tsock->p);
1213 }
1214 retval = TIPC_OK;
1215 }
1216 break;
1217 case SS_CONNECTING:
1218 /* Accept only ACK or NACK message */
1219 if (msg_connected(msg) || (msg_errcode(msg)))
1220 retval = TIPC_OK;
1221 break;
1222 case SS_LISTENING:
1223 case SS_UNCONNECTED:
1224 /* Accept only SYN message */
1225 if (!msg_connected(msg) && !(msg_errcode(msg)))
1226 retval = TIPC_OK;
1227 break;
1228 case SS_DISCONNECTING:
1229 break;
1230 default:
1231 pr_err("Unknown socket state %u\n", sock->state);
1232 }
1233 return retval;
1234}
1235
1236/**
1190 * filter_rcv - validate incoming message 1237 * filter_rcv - validate incoming message
1191 * @sk: socket 1238 * @sk: socket
1192 * @buf: message 1239 * @buf: message
@@ -1203,6 +1250,7 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
1203 struct socket *sock = sk->sk_socket; 1250 struct socket *sock = sk->sk_socket;
1204 struct tipc_msg *msg = buf_msg(buf); 1251 struct tipc_msg *msg = buf_msg(buf);
1205 u32 recv_q_len; 1252 u32 recv_q_len;
1253 u32 res = TIPC_OK;
1206 1254
1207 /* Reject message if it is wrong sort of message for socket */ 1255 /* Reject message if it is wrong sort of message for socket */
1208 if (msg_type(msg) > TIPC_DIRECT_MSG) 1256 if (msg_type(msg) > TIPC_DIRECT_MSG)
@@ -1212,24 +1260,9 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
1212 if (msg_connected(msg)) 1260 if (msg_connected(msg))
1213 return TIPC_ERR_NO_PORT; 1261 return TIPC_ERR_NO_PORT;
1214 } else { 1262 } else {
1215 if (msg_mcast(msg)) 1263 res = filter_connect(tipc_sk(sk), &buf);
1216 return TIPC_ERR_NO_PORT; 1264 if (res != TIPC_OK || buf == NULL)
1217 if (sock->state == SS_CONNECTED) { 1265 return res;
1218 if (!msg_connected(msg) ||
1219 !tipc_port_peer_msg(tipc_sk_port(sk), msg))
1220 return TIPC_ERR_NO_PORT;
1221 } else if (sock->state == SS_CONNECTING) {
1222 if (!msg_connected(msg) && (msg_errcode(msg) == 0))
1223 return TIPC_ERR_NO_PORT;
1224 } else if (sock->state == SS_LISTENING) {
1225 if (msg_connected(msg) || msg_errcode(msg))
1226 return TIPC_ERR_NO_PORT;
1227 } else if (sock->state == SS_DISCONNECTING) {
1228 return TIPC_ERR_NO_PORT;
1229 } else /* (sock->state == SS_UNCONNECTED) */ {
1230 if (msg_connected(msg) || msg_errcode(msg))
1231 return TIPC_ERR_NO_PORT;
1232 }
1233 } 1266 }
1234 1267
1235 /* Reject message if there isn't room to queue it */ 1268 /* Reject message if there isn't room to queue it */
@@ -1243,12 +1276,6 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
1243 TIPC_SKB_CB(buf)->handle = 0; 1276 TIPC_SKB_CB(buf)->handle = 0;
1244 __skb_queue_tail(&sk->sk_receive_queue, buf); 1277 __skb_queue_tail(&sk->sk_receive_queue, buf);
1245 1278
1246 /* Initiate connection termination for an incoming 'FIN' */
1247 if (unlikely(msg_errcode(msg) && (sock->state == SS_CONNECTED))) {
1248 sock->state = SS_DISCONNECTING;
1249 __tipc_disconnect(tipc_sk_port(sk));
1250 }
1251
1252 sk->sk_data_ready(sk, 0); 1279 sk->sk_data_ready(sk, 0);
1253 return TIPC_OK; 1280 return TIPC_OK;
1254} 1281}