phonet: phonet_device_get() fix
[safe/jmp/linux-2.6] / net / phonet / socket.c
index cea1136..aa1617a 100644 (file)
@@ -57,7 +57,7 @@ static struct  {
  * Find address based on socket address, match only certain fields.
  * Also grab sock if it was found. Remember to sock_put it later.
  */
-struct sock *pn_find_sock_by_sa(const struct sockaddr_pn *spn)
+struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn)
 {
        struct hlist_node *node;
        struct sock *sknode;
@@ -71,6 +71,8 @@ struct sock *pn_find_sock_by_sa(const struct sockaddr_pn *spn)
                struct pn_sock *pn = pn_sk(sknode);
                BUG_ON(!pn->sobject); /* unbound socket */
 
+               if (!net_eq(sock_net(sknode), net))
+                       continue;
                if (pn_port(obj)) {
                        /* Look up socket by port */
                        if (pn_port(pn->sobject) != pn_port(obj))
@@ -130,7 +132,7 @@ static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len)
 
        handle = pn_sockaddr_get_object((struct sockaddr_pn *)addr);
        saddr = pn_addr(handle);
-       if (saddr && phonet_address_lookup(saddr))
+       if (saddr && phonet_address_lookup(sock_net(sk), saddr))
                return -EADDRNOTAVAIL;
 
        lock_sock(sk);
@@ -220,10 +222,12 @@ static unsigned int pn_socket_poll(struct file *file, struct socket *sock,
 
        if (!skb_queue_empty(&sk->sk_receive_queue))
                mask |= POLLIN | POLLRDNORM;
-       else if (sk->sk_state == TCP_CLOSE_WAIT)
+       if (!skb_queue_empty(&pn->ctrlreq_queue))
+               mask |= POLLPRI;
+       if (!mask && sk->sk_state == TCP_CLOSE_WAIT)
                return POLLHUP;
 
-       if (sk->sk_state == TCP_ESTABLISHED && pn->tx_credits)
+       if (sk->sk_state == TCP_ESTABLISHED && atomic_read(&pn->tx_credits))
                mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
 
        return mask;
@@ -340,11 +344,11 @@ const struct proto_ops phonet_stream_ops = {
        .ioctl          = pn_socket_ioctl,
        .listen         = pn_socket_listen,
        .shutdown       = sock_no_shutdown,
-       .setsockopt     = sock_no_setsockopt,
-       .getsockopt     = sock_no_getsockopt,
+       .setsockopt     = sock_common_setsockopt,
+       .getsockopt     = sock_common_getsockopt,
 #ifdef CONFIG_COMPAT
-       .compat_setsockopt = sock_no_setsockopt,
-       .compat_getsockopt = compat_sock_no_getsockopt,
+       .compat_setsockopt = compat_sock_common_setsockopt,
+       .compat_getsockopt = compat_sock_common_getsockopt,
 #endif
        .sendmsg        = pn_socket_sendmsg,
        .recvmsg        = sock_common_recvmsg,
@@ -359,6 +363,7 @@ static DEFINE_MUTEX(port_mutex);
 int pn_sock_get_port(struct sock *sk, unsigned short sport)
 {
        static int port_cur;
+       struct net *net = sock_net(sk);
        struct pn_sock *pn = pn_sk(sk);
        struct sockaddr_pn try_sa;
        struct sock *tmpsk;
@@ -379,7 +384,7 @@ int pn_sock_get_port(struct sock *sk, unsigned short sport)
                                port_cur = pmin;
 
                        pn_sockaddr_set_port(&try_sa, port_cur);
-                       tmpsk = pn_find_sock_by_sa(&try_sa);
+                       tmpsk = pn_find_sock_by_sa(net, &try_sa);
                        if (tmpsk == NULL) {
                                sport = port_cur;
                                goto found;
@@ -389,7 +394,7 @@ int pn_sock_get_port(struct sock *sk, unsigned short sport)
        } else {
                /* try to find specific port */
                pn_sockaddr_set_port(&try_sa, sport);
-               tmpsk = pn_find_sock_by_sa(&try_sa);
+               tmpsk = pn_find_sock_by_sa(net, &try_sa);
                if (tmpsk == NULL)
                        /* No sock there! We can use that port... */
                        goto found;
@@ -407,3 +412,99 @@ found:
        return 0;
 }
 EXPORT_SYMBOL(pn_sock_get_port);
+
+static struct sock *pn_sock_get_idx(struct seq_file *seq, loff_t pos)
+{
+       struct net *net = seq_file_net(seq);
+       struct hlist_node *node;
+       struct sock *sknode;
+
+       sk_for_each(sknode, node, &pnsocks.hlist) {
+               if (!net_eq(net, sock_net(sknode)))
+                       continue;
+               if (!pos)
+                       return sknode;
+               pos--;
+       }
+       return NULL;
+}
+
+static struct sock *pn_sock_get_next(struct seq_file *seq, struct sock *sk)
+{
+       struct net *net = seq_file_net(seq);
+
+       do
+               sk = sk_next(sk);
+       while (sk && !net_eq(net, sock_net(sk)));
+
+       return sk;
+}
+
+static void *pn_sock_seq_start(struct seq_file *seq, loff_t *pos)
+       __acquires(pnsocks.lock)
+{
+       spin_lock_bh(&pnsocks.lock);
+       return *pos ? pn_sock_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
+}
+
+static void *pn_sock_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+       struct sock *sk;
+
+       if (v == SEQ_START_TOKEN)
+               sk = pn_sock_get_idx(seq, 0);
+       else
+               sk = pn_sock_get_next(seq, v);
+       (*pos)++;
+       return sk;
+}
+
+static void pn_sock_seq_stop(struct seq_file *seq, void *v)
+       __releases(pnsocks.lock)
+{
+       spin_unlock_bh(&pnsocks.lock);
+}
+
+static int pn_sock_seq_show(struct seq_file *seq, void *v)
+{
+       int len;
+
+       if (v == SEQ_START_TOKEN)
+               seq_printf(seq, "%s%n", "pt  loc  rem rs st tx_queue rx_queue "
+                       "  uid inode ref pointer drops", &len);
+       else {
+               struct sock *sk = v;
+               struct pn_sock *pn = pn_sk(sk);
+
+               seq_printf(seq, "%2d %04X:%04X:%02X %02X %08X:%08X %5d %lu "
+                       "%d %p %d%n",
+                       sk->sk_protocol, pn->sobject, 0, pn->resource,
+                       sk->sk_state,
+                       sk_wmem_alloc_get(sk), sk_rmem_alloc_get(sk),
+                       sock_i_uid(sk), sock_i_ino(sk),
+                       atomic_read(&sk->sk_refcnt), sk,
+                       atomic_read(&sk->sk_drops), &len);
+       }
+       seq_printf(seq, "%*s\n", 127 - len, "");
+       return 0;
+}
+
+static const struct seq_operations pn_sock_seq_ops = {
+       .start = pn_sock_seq_start,
+       .next = pn_sock_seq_next,
+       .stop = pn_sock_seq_stop,
+       .show = pn_sock_seq_show,
+};
+
+static int pn_sock_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &pn_sock_seq_ops);
+}
+
+const struct file_operations pn_sock_seq_fops = {
+       .owner = THIS_MODULE,
+       .open = pn_sock_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = seq_release,
+};