]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/iucv/af_iucv.c
Merge branch 'i2c-next' of git://aeryn.fluff.org.uk/bjdooks/linux
[linux-2.6-omap-h63xx.git] / net / iucv / af_iucv.c
index 29f7baa251107b03751619f1aae1318d170fe2d1..eb8a2a0b6eb71fc10671097563e71c3b7ae97ed9 100644 (file)
@@ -8,6 +8,9 @@
  *  Author(s): Jennifer Hunt <jenhunt@us.ibm.com>
  */
 
+#define KMSG_COMPONENT "af_iucv"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/list.h>
@@ -491,7 +494,21 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr,
        if (err) {
                iucv_path_free(iucv->path);
                iucv->path = NULL;
-               err = -ECONNREFUSED;
+               switch (err) {
+               case 0x0b:      /* Target communicator is not logged on */
+                       err = -ENETUNREACH;
+                       break;
+               case 0x0d:      /* Max connections for this guest exceeded */
+               case 0x0e:      /* Max connections for target guest exceeded */
+                       err = -EAGAIN;
+                       break;
+               case 0x0f:      /* Missing IUCV authorization */
+                       err = -EACCES;
+                       break;
+               default:
+                       err = -ECONNREFUSED;
+                       break;
+               }
                goto done;
        }
 
@@ -504,6 +521,13 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr,
                release_sock(sk);
                return -ECONNREFUSED;
        }
+
+       if (err) {
+               iucv_path_sever(iucv->path, NULL);
+               iucv_path_free(iucv->path);
+               iucv->path = NULL;
+       }
+
 done:
        release_sock(sk);
        return err;
@@ -616,6 +640,8 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
        struct iucv_sock *iucv = iucv_sk(sk);
        struct sk_buff *skb;
        struct iucv_message txmsg;
+       char user_id[9];
+       char appl_id[9];
        int err;
 
        err = sock_error(sk);
@@ -651,8 +677,15 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
                err = iucv_message_send(iucv->path, &txmsg, 0, 0,
                                        (void *) skb->data, skb->len);
                if (err) {
-                       if (err == 3)
-                               printk(KERN_ERR "AF_IUCV msg limit exceeded\n");
+                       if (err == 3) {
+                               user_id[8] = 0;
+                               memcpy(user_id, iucv->dst_user_id, 8);
+                               appl_id[8] = 0;
+                               memcpy(appl_id, iucv->dst_name, 8);
+                               pr_err("Application %s on z/VM guest %s"
+                                      " exceeds message limit\n",
+                                      user_id, appl_id);
+                       }
                        skb_unlink(skb, &iucv->send_skb_q);
                        err = -EPIPE;
                        goto fail;
@@ -1009,12 +1042,14 @@ static int iucv_callback_connreq(struct iucv_path *path,
        ASCEBC(user_data, sizeof(user_data));
        if (sk->sk_state != IUCV_LISTEN) {
                err = iucv_path_sever(path, user_data);
+               iucv_path_free(path);
                goto fail;
        }
 
        /* Check for backlog size */
        if (sk_acceptq_is_full(sk)) {
                err = iucv_path_sever(path, user_data);
+               iucv_path_free(path);
                goto fail;
        }
 
@@ -1022,6 +1057,7 @@ static int iucv_callback_connreq(struct iucv_path *path,
        nsk = iucv_sock_alloc(NULL, SOCK_STREAM, GFP_ATOMIC);
        if (!nsk) {
                err = iucv_path_sever(path, user_data);
+               iucv_path_free(path);
                goto fail;
        }
 
@@ -1045,6 +1081,8 @@ static int iucv_callback_connreq(struct iucv_path *path,
        err = iucv_path_accept(path, &af_iucv_handler, nuser_data, nsk);
        if (err) {
                err = iucv_path_sever(path, user_data);
+               iucv_path_free(path);
+               iucv_sock_kill(nsk);
                goto fail;
        }
 
@@ -1190,7 +1228,8 @@ static int __init afiucv_init(void)
        int err;
 
        if (!MACHINE_IS_VM) {
-               printk(KERN_ERR "AF_IUCV connection needs VM as base\n");
+               pr_err("The af_iucv module cannot be loaded"
+                      " without z/VM\n");
                err = -EPROTONOSUPPORT;
                goto out;
        }