Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 290823
b: refs/heads/master
c: 9fbd87d
h: refs/heads/master
i:
  290821: fbab97f
  290819: d2707cf
  290815: ef80cab
v: v3
  • Loading branch information
Ursula Braun authored and David S. Miller committed Mar 8, 2012
1 parent cfcdab5 commit 411747e
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 45 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c75a312d8b2c97943014261d71c6ef2622b6d0d9
refs/heads/master: 9fbd87d413921f36d2f55cee1d082323e6eb1d5f
106 changes: 62 additions & 44 deletions trunk/net/iucv/af_iucv.c
Original file line number Diff line number Diff line change
Expand Up @@ -453,14 +453,28 @@ static void iucv_sever_path(struct sock *sk, int with_user_data)
}
}

/* Send FIN through an IUCV socket for HIPER transport */
static int iucv_send_ctrl(struct sock *sk, u8 flags)
{
int err = 0;
int blen;
struct sk_buff *skb;

blen = sizeof(struct af_iucv_trans_hdr) + ETH_HLEN;
skb = sock_alloc_send_skb(sk, blen, 1, &err);
if (skb) {
skb_reserve(skb, blen);
err = afiucv_hs_send(NULL, sk, skb, flags);
}
return err;
}

/* Close an IUCV socket */
static void iucv_sock_close(struct sock *sk)
{
struct iucv_sock *iucv = iucv_sk(sk);
unsigned long timeo;
int err = 0;
int blen;
struct sk_buff *skb;

lock_sock(sk);

Expand All @@ -471,14 +485,7 @@ static void iucv_sock_close(struct sock *sk)

case IUCV_CONNECTED:
if (iucv->transport == AF_IUCV_TRANS_HIPER) {
/* send fin */
blen = sizeof(struct af_iucv_trans_hdr) + ETH_HLEN;
skb = sock_alloc_send_skb(sk, blen, 1, &err);
if (skb) {
skb_reserve(skb, blen);
err = afiucv_hs_send(NULL, sk, skb,
AF_IUCV_FLAG_FIN);
}
err = iucv_send_ctrl(sk, AF_IUCV_FLAG_FIN);
sk->sk_state = IUCV_DISCONN;
sk->sk_state_change(sk);
}
Expand Down Expand Up @@ -782,26 +789,6 @@ static int iucv_sock_autobind(struct sock *sk)
return err;
}

static int afiucv_hs_connect(struct socket *sock)
{
struct sock *sk = sock->sk;
struct sk_buff *skb;
int blen = sizeof(struct af_iucv_trans_hdr) + ETH_HLEN;
int err = 0;

/* send syn */
skb = sock_alloc_send_skb(sk, blen, 1, &err);
if (!skb) {
err = -ENOMEM;
goto done;
}
skb->dev = NULL;
skb_reserve(skb, blen);
err = afiucv_hs_send(NULL, sk, skb, AF_IUCV_FLAG_SYN);
done:
return err;
}

static int afiucv_path_connect(struct socket *sock, struct sockaddr *addr)
{
struct sockaddr_iucv *sa = (struct sockaddr_iucv *) addr;
Expand Down Expand Up @@ -882,7 +869,7 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr,
memcpy(iucv->dst_name, sa->siucv_name, 8);

if (iucv->transport == AF_IUCV_TRANS_HIPER)
err = afiucv_hs_connect(sock);
err = iucv_send_ctrl(sock->sk, AF_IUCV_FLAG_SYN);
else
err = afiucv_path_connect(sock, addr);
if (err)
Expand Down Expand Up @@ -1332,8 +1319,7 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
struct sock *sk = sock->sk;
struct iucv_sock *iucv = iucv_sk(sk);
unsigned int copied, rlen;
struct sk_buff *skb, *rskb, *cskb, *sskb;
int blen;
struct sk_buff *skb, *rskb, *cskb;
int err = 0;

if ((sk->sk_state == IUCV_DISCONN) &&
Expand Down Expand Up @@ -1422,15 +1408,7 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
iucv_process_message_q(sk);
if (atomic_read(&iucv->msg_recv) >=
iucv->msglimit / 2) {
/* send WIN to peer */
blen = sizeof(struct af_iucv_trans_hdr) +
ETH_HLEN;
sskb = sock_alloc_send_skb(sk, blen, 1, &err);
if (sskb) {
skb_reserve(sskb, blen);
err = afiucv_hs_send(NULL, sk, sskb,
AF_IUCV_FLAG_WIN);
}
err = iucv_send_ctrl(sk, AF_IUCV_FLAG_WIN);
if (err) {
sk->sk_state = IUCV_DISCONN;
sk->sk_state_change(sk);
Expand Down Expand Up @@ -2289,6 +2267,44 @@ static void afiucv_hs_callback_txnotify(struct sk_buff *skb,
}

}

/*
* afiucv_netdev_event: handle netdev notifier chain events
*/
static int afiucv_netdev_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
struct net_device *event_dev = (struct net_device *)ptr;
struct hlist_node *node;
struct sock *sk;
struct iucv_sock *iucv;

switch (event) {
case NETDEV_REBOOT:
case NETDEV_GOING_DOWN:
sk_for_each(sk, node, &iucv_sk_list.head) {
iucv = iucv_sk(sk);
if ((iucv->hs_dev == event_dev) &&
(sk->sk_state == IUCV_CONNECTED)) {
if (event == NETDEV_GOING_DOWN)
iucv_send_ctrl(sk, AF_IUCV_FLAG_FIN);
sk->sk_state = IUCV_DISCONN;
sk->sk_state_change(sk);
}
}
break;
case NETDEV_DOWN:
case NETDEV_UNREGISTER:
default:
break;
}
return NOTIFY_DONE;
}

static struct notifier_block afiucv_netdev_notifier = {
.notifier_call = afiucv_netdev_event,
};

static const struct proto_ops iucv_sock_ops = {
.family = PF_IUCV,
.owner = THIS_MODULE,
Expand Down Expand Up @@ -2388,7 +2404,8 @@ static int __init afiucv_init(void)
err = afiucv_iucv_init();
if (err)
goto out_sock;
}
} else
register_netdevice_notifier(&afiucv_netdev_notifier);
dev_add_pack(&iucv_packet_type);
return 0;

Expand All @@ -2409,7 +2426,8 @@ static void __exit afiucv_exit(void)
driver_unregister(&af_iucv_driver);
pr_iucv->iucv_unregister(&af_iucv_handler, 0);
symbol_put(iucv_if);
}
} else
unregister_netdevice_notifier(&afiucv_netdev_notifier);
dev_remove_pack(&iucv_packet_type);
sock_unregister(PF_IUCV);
proto_unregister(&iucv_proto);
Expand Down

0 comments on commit 411747e

Please sign in to comment.