From: Bryam Vargas <redacted>
Move the switch on the frame type out of afiucv_hs_rcv() into
afiucv_hs_dispatch(), and the state changes a SYN|ACK, a SYN|FIN and a
FIN make into afiucv_hs_synack(), afiucv_hs_synfin() and
afiucv_hs_fin(). The three are still called under the bh_lock_sock() of
their callbacks, which now test sk where they tested iucv_sk(sk), a
cast of it. They are defined ahead of iucv_proto: the next patch
reaches them from proto->release_cb. afiucv_hs_synfin() and
afiucv_hs_fin() are the same for now and stay two: a later patch sets
RCV_SHUTDOWN in the second only.
No functional change. The next patch runs the dispatch from a second
place and the three state changes from the task that owns the socket.
Cc: <redacted> # 6.18.x, needed by the next patch
Signed-off-by: Bryam Vargas <redacted>
---
New in v3: v2 moved this code and changed it in one diff. Here it only
moves, so that 5/7 shows what changes.
checkpatch asks for a Fixes: tag because of the stable line. There is
none to give: the patch fixes nothing and is marked for stable only so
that 5/7 applies there.
The kernel with 1/7 to 4/7 gives the result of the one with 1/7 to 3/7
in every test: the 53 default ones and the 28 opt-in ones (window,
strays, connect(), leaks).
---
net/iucv/af_iucv.c | 151 ++++++++++++++++++++++++++++++++++-------------------
1 file changed, 97 insertions(+), 54 deletions(-)
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index 639725917f3f..1677cc65ad06 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -39,6 +39,44 @@
static char iucv_userid[80];
+/**
+ * afiucv_hs_synack() - connect a socket, on the SYN|ACK to its SYN
+ * @sk: the socket, in IUCV_BOUND
+ * @window: the window in the SYN|ACK: the frames the peer takes from us
+ *
+ * Context: Softirq, under bh_lock_sock().
+ */
+static void afiucv_hs_synack(struct sock *sk, u16 window)
+{
+ iucv_sk(sk)->msglimit_peer = window;
+ sk->sk_state = IUCV_CONNECTED;
+ sk->sk_state_change(sk);
+}
+
+/**
+ * afiucv_hs_synfin() - refuse a socket, on the SYN|FIN to its SYN
+ * @sk: the socket, in IUCV_BOUND
+ *
+ * Context: As afiucv_hs_synack().
+ */
+static void afiucv_hs_synfin(struct sock *sk)
+{
+ sk->sk_state = IUCV_DISCONN;
+ sk->sk_state_change(sk);
+}
+
+/**
+ * afiucv_hs_fin() - disconnect a socket, on the FIN of its peer
+ * @sk: the socket, in IUCV_CONNECTED
+ *
+ * Context: As afiucv_hs_synack().
+ */
+static void afiucv_hs_fin(struct sock *sk)
+{
+ sk->sk_state = IUCV_DISCONN;
+ sk->sk_state_change(sk);
+}
+
static struct proto iucv_proto = {
.name = "AF_IUCV",
.owner = THIS_MODULE,@@ -2032,17 +2070,13 @@ static int afiucv_hs_callback_syn(struct sock *sk, struct sk_buff *skb)
*/
static int afiucv_hs_callback_synack(struct sock *sk, struct sk_buff *skb)
{
- struct iucv_sock *iucv = iucv_sk(sk);
-
- if (!iucv || sk->sk_state != IUCV_BOUND) {
+ if (!sk || sk->sk_state != IUCV_BOUND) {
kfree_skb(skb);
return NET_RX_SUCCESS;
}
bh_lock_sock(sk);
- iucv->msglimit_peer = iucv_trans_hdr(skb)->window;
- sk->sk_state = IUCV_CONNECTED;
- sk->sk_state_change(sk);
+ afiucv_hs_synack(sk, iucv_trans_hdr(skb)->window);
bh_unlock_sock(sk);
consume_skb(skb);
return NET_RX_SUCCESS;@@ -2053,16 +2087,13 @@ static int afiucv_hs_callback_synack(struct sock *sk, struct sk_buff *skb)
*/
static int afiucv_hs_callback_synfin(struct sock *sk, struct sk_buff *skb)
{
- struct iucv_sock *iucv = iucv_sk(sk);
-
- if (!iucv || sk->sk_state != IUCV_BOUND) {
+ if (!sk || sk->sk_state != IUCV_BOUND) {
kfree_skb(skb);
return NET_RX_SUCCESS;
}
bh_lock_sock(sk);
- sk->sk_state = IUCV_DISCONN;
- sk->sk_state_change(sk);
+ afiucv_hs_synfin(sk);
bh_unlock_sock(sk);
consume_skb(skb);
return NET_RX_SUCCESS;@@ -2073,19 +2104,15 @@ static int afiucv_hs_callback_synfin(struct sock *sk, struct sk_buff *skb)
*/
static int afiucv_hs_callback_fin(struct sock *sk, struct sk_buff *skb)
{
- struct iucv_sock *iucv = iucv_sk(sk);
-
/* other end of connection closed */
- if (!iucv) {
+ if (!sk) {
kfree_skb(skb);
return NET_RX_SUCCESS;
}
bh_lock_sock(sk);
- if (sk->sk_state == IUCV_CONNECTED) {
- sk->sk_state = IUCV_DISCONN;
- sk->sk_state_change(sk);
- }
+ if (sk->sk_state == IUCV_CONNECTED)
+ afiucv_hs_fin(sk);
bh_unlock_sock(sk);
consume_skb(skb);
return NET_RX_SUCCESS;@@ -2153,6 +2180,57 @@ static int afiucv_hs_callback_rx(struct sock *sk, struct sk_buff *skb)
return NET_RX_SUCCESS;
}
+/**
+ * afiucv_hs_dispatch() - run the callback of a frame
+ * @sk: the socket the frame is for, or NULL if there is none
+ * @skb: the frame
+ *
+ * Context: Softirq.
+ * Return: NET_RX_SUCCESS.
+ */
+static int afiucv_hs_dispatch(struct sock *sk, struct sk_buff *skb)
+{
+ struct af_iucv_trans_hdr *trans_hdr = iucv_trans_hdr(skb);
+ int err = NET_RX_SUCCESS;
+
+ switch (trans_hdr->flags) {
+ case AF_IUCV_FLAG_SYN:
+ /* connect request */
+ err = afiucv_hs_callback_syn(sk, skb);
+ break;
+ case (AF_IUCV_FLAG_SYN | AF_IUCV_FLAG_ACK):
+ /* connect request confirmed */
+ err = afiucv_hs_callback_synack(sk, skb);
+ break;
+ case (AF_IUCV_FLAG_SYN | AF_IUCV_FLAG_FIN):
+ /* connect request refused */
+ err = afiucv_hs_callback_synfin(sk, skb);
+ break;
+ case (AF_IUCV_FLAG_FIN):
+ /* close request */
+ err = afiucv_hs_callback_fin(sk, skb);
+ break;
+ case (AF_IUCV_FLAG_WIN):
+ err = afiucv_hs_callback_win(sk, skb);
+ if (skb->len == sizeof(struct af_iucv_trans_hdr)) {
+ consume_skb(skb);
+ break;
+ }
+ fallthrough; /* and receive non-zero length data */
+ case (AF_IUCV_FLAG_SHT):
+ /* shutdown request */
+ fallthrough; /* and receive zero length data */
+ case 0:
+ /* plain data frame */
+ IUCV_SKB_CB(skb)->class = trans_hdr->iucv_hdr.class;
+ err = afiucv_hs_callback_rx(sk, skb);
+ break;
+ default:
+ kfree_skb(skb);
+ }
+ return err;
+}
+
/*
* afiucv_hs_rcv() - base function for arriving data through HiperSockets
* transport@@ -2233,42 +2311,7 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev,
data -> send FIN
SYN|ACK, SYN|FIN, FIN -> no action? */
- switch (trans_hdr->flags) {
- case AF_IUCV_FLAG_SYN:
- /* connect request */
- err = afiucv_hs_callback_syn(sk, skb);
- break;
- case (AF_IUCV_FLAG_SYN | AF_IUCV_FLAG_ACK):
- /* connect request confirmed */
- err = afiucv_hs_callback_synack(sk, skb);
- break;
- case (AF_IUCV_FLAG_SYN | AF_IUCV_FLAG_FIN):
- /* connect request refused */
- err = afiucv_hs_callback_synfin(sk, skb);
- break;
- case (AF_IUCV_FLAG_FIN):
- /* close request */
- err = afiucv_hs_callback_fin(sk, skb);
- break;
- case (AF_IUCV_FLAG_WIN):
- err = afiucv_hs_callback_win(sk, skb);
- if (skb->len == sizeof(struct af_iucv_trans_hdr)) {
- consume_skb(skb);
- break;
- }
- fallthrough; /* and receive non-zero length data */
- case (AF_IUCV_FLAG_SHT):
- /* shutdown request */
- fallthrough; /* and receive zero length data */
- case 0:
- /* plain data frame */
- IUCV_SKB_CB(skb)->class = trans_hdr->iucv_hdr.class;
- err = afiucv_hs_callback_rx(sk, skb);
- break;
- default:
- kfree_skb(skb);
- }
-
+ err = afiucv_hs_dispatch(sk, skb);
if (sk)
sock_put(sk);
return err;
--
2.56.0