Phonet: allow phonet_device_init() to fail, put it to __init section
[safe/jmp/linux-2.6] / net / phonet / af_phonet.c
index 0a74aea..95bc49d 100644 (file)
 #include <net/phonet/phonet.h>
 #include <net/phonet/pn_dev.h>
 
-static struct net_proto_family phonet_proto_family;
-static struct phonet_protocol *phonet_proto_get(int protocol);
-static inline void phonet_proto_put(struct phonet_protocol *pp);
+/* Transport protocol registration */
+static struct phonet_protocol *proto_tab[PHONET_NPROTO] __read_mostly;
+static DEFINE_SPINLOCK(proto_tab_lock);
+
+static struct phonet_protocol *phonet_proto_get(int protocol)
+{
+       struct phonet_protocol *pp;
+
+       if (protocol >= PHONET_NPROTO)
+               return NULL;
+
+       spin_lock(&proto_tab_lock);
+       pp = proto_tab[protocol];
+       if (pp && !try_module_get(pp->prot->owner))
+               pp = NULL;
+       spin_unlock(&proto_tab_lock);
+
+       return pp;
+}
+
+static inline void phonet_proto_put(struct phonet_protocol *pp)
+{
+       module_put(pp->prot->owner);
+}
 
 /* protocol family functions */
 
@@ -46,9 +67,6 @@ static int pn_socket_create(struct net *net, struct socket *sock, int protocol)
        struct phonet_protocol *pnp;
        int err;
 
-       if (net != &init_net)
-               return -EAFNOSUPPORT;
-
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
@@ -58,17 +76,19 @@ static int pn_socket_create(struct net *net, struct socket *sock, int protocol)
                case SOCK_DGRAM:
                        protocol = PN_PROTO_PHONET;
                        break;
+               case SOCK_SEQPACKET:
+                       protocol = PN_PROTO_PIPE;
+                       break;
                default:
                        return -EPROTONOSUPPORT;
                }
        }
 
        pnp = phonet_proto_get(protocol);
-#ifdef CONFIG_KMOD
        if (pnp == NULL &&
            request_module("net-pf-%d-proto-%d", PF_PHONET, protocol) == 0)
                pnp = phonet_proto_get(protocol);
-#endif
+
        if (pnp == NULL)
                return -EPROTONOSUPPORT;
        if (sock->type != pnp->sock_type) {
@@ -142,8 +162,8 @@ static int pn_send(struct sk_buff *skb, struct net_device *dev,
        struct phonethdr *ph;
        int err;
 
-       if (skb->len + 2 > 0xffff) {
-               /* Phonet length field would overflow */
+       if (skb->len + 2 > 0xffff /* Phonet length field limit */ ||
+           skb->len + sizeof(struct phonethdr) > dev->mtu) {
                err = -EMSGSIZE;
                goto drop;
        }
@@ -255,10 +275,10 @@ static inline int can_respond(struct sk_buff *skb)
                return 0;
 
        ph = pn_hdr(skb);
-       if (phonet_address_get(skb->dev, ph->pn_rdev) != ph->pn_rdev)
-               return 0; /* we are not the destination */
        if (ph->pn_res == PN_PREFIX && !pskb_may_pull(skb, 5))
                return 0;
+       if (ph->pn_res == PN_COMMGR) /* indications */
+               return 0;
 
        ph = pn_hdr(skb); /* re-acquires the pointer */
        pm = pn_msg(skb);
@@ -307,7 +327,8 @@ static int send_reset_indications(struct sk_buff *rskb)
 
        return pn_raw_send(data, sizeof(data), rskb->dev,
                                pn_object(oph->pn_sdev, 0x00),
-                               pn_object(oph->pn_rdev, oph->pn_robj), 0x10);
+                               pn_object(oph->pn_rdev, oph->pn_robj),
+                               PN_COMMGR);
 }
 
 
@@ -321,14 +342,11 @@ static int phonet_rcv(struct sk_buff *skb, struct net_device *dev,
                        struct packet_type *pkttype,
                        struct net_device *orig_dev)
 {
+       struct net *net = dev_net(dev);
        struct phonethdr *ph;
-       struct sock *sk;
        struct sockaddr_pn sa;
        u16 len;
 
-       if (dev_net(dev) != &init_net)
-               goto out;
-
        /* check we have at least a full Phonet header */
        if (!pskb_pull(skb, sizeof(struct phonethdr)))
                goto out;
@@ -344,21 +362,21 @@ static int phonet_rcv(struct sk_buff *skb, struct net_device *dev,
        skb_reset_transport_header(skb);
 
        pn_skb_get_dst_sockaddr(skb, &sa);
-       if (pn_sockaddr_get_addr(&sa) == 0)
-               goto out; /* currently, we cannot be device 0 */
 
-       sk = pn_find_sock_by_sa(&sa);
-       if (sk == NULL) {
+       /* check if we are the destination */
+       if (phonet_address_lookup(net, pn_sockaddr_get_addr(&sa)) == 0) {
+               /* Phonet packet input */
+               struct sock *sk = pn_find_sock_by_sa(net, &sa);
+
+               if (sk)
+                       return sk_receive_skb(sk, skb, 0);
+
                if (can_respond(skb)) {
                        send_obj_unreachable(skb);
                        send_reset_indications(skb);
                }
-               goto out;
        }
 
-       /* Push data to the socket (or other sockets connected to it). */
-       return sk_receive_skb(sk, skb, 0);
-
 out:
        kfree_skb(skb);
        return NET_RX_DROP;
@@ -370,10 +388,6 @@ static struct packet_type phonet_packet_type = {
        .func = phonet_rcv,
 };
 
-/* Transport protocol registration */
-static struct phonet_protocol *proto_tab[PHONET_NPROTO] __read_mostly;
-static DEFINE_SPINLOCK(proto_tab_lock);
-
 int __init_or_module phonet_proto_register(int protocol,
                                                struct phonet_protocol *pp)
 {
@@ -407,42 +421,23 @@ void phonet_proto_unregister(int protocol, struct phonet_protocol *pp)
 }
 EXPORT_SYMBOL(phonet_proto_unregister);
 
-static struct phonet_protocol *phonet_proto_get(int protocol)
-{
-       struct phonet_protocol *pp;
-
-       if (protocol >= PHONET_NPROTO)
-               return NULL;
-
-       spin_lock(&proto_tab_lock);
-       pp = proto_tab[protocol];
-       if (pp && !try_module_get(pp->prot->owner))
-               pp = NULL;
-       spin_unlock(&proto_tab_lock);
-
-       return pp;
-}
-
-static inline void phonet_proto_put(struct phonet_protocol *pp)
-{
-       module_put(pp->prot->owner);
-}
-
 /* Module registration */
 static int __init phonet_init(void)
 {
        int err;
 
+       err = phonet_device_init();
+       if (err)
+               return err;
+
        err = sock_register(&phonet_proto_family);
        if (err) {
                printk(KERN_ALERT
                        "phonet protocol family initialization failed\n");
-               return err;
+               goto err_sock;
        }
 
-       phonet_device_init();
        dev_add_pack(&phonet_packet_type);
-       phonet_netlink_register();
        phonet_sysctl_init();
 
        err = isi_register();
@@ -454,6 +449,7 @@ err:
        phonet_sysctl_exit();
        sock_unregister(PF_PHONET);
        dev_remove_pack(&phonet_packet_type);
+err_sock:
        phonet_device_exit();
        return err;
 }