X-Git-Url: https://nv-tegra.nvidia.com/r/gitweb?p=linux-2.6.git;a=blobdiff_plain;f=net%2Fphonet%2Fsocket.c;h=c75aa5cdead51cebe9292b1e27a25e4da06621c2;hp=99a4945d565dcf89932d4ffc443a86702462a113;hb=52404881984e2d447f920a23e3bb63262dfc77f3;hpb=ba113a94b7503ee23ffe819e7045134b0c1d31de diff --git a/net/phonet/socket.c b/net/phonet/socket.c index 99a4945d565..c75aa5cdead 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c @@ -25,11 +25,13 @@ #include #include +#include #include #include #include #include +#include #include static int pn_socket_release(struct socket *sock) @@ -55,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; @@ -69,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)) @@ -128,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); @@ -166,6 +170,24 @@ static int pn_socket_autobind(struct socket *sock) return 0; /* socket was already bound */ } +static int pn_socket_accept(struct socket *sock, struct socket *newsock, + int flags) +{ + struct sock *sk = sock->sk; + struct sock *newsk; + int err; + + newsk = sk->sk_prot->accept(sk, flags, &err); + if (!newsk) + return err; + + lock_sock(newsk); + sock_graft(newsk, newsock); + newsock->state = SS_CONNECTED; + release_sock(newsk); + return 0; +} + static int pn_socket_getname(struct socket *sock, struct sockaddr *addr, int *sockaddr_len, int peer) { @@ -182,6 +204,35 @@ static int pn_socket_getname(struct socket *sock, struct sockaddr *addr, return 0; } +static unsigned int pn_socket_poll(struct file *file, struct socket *sock, + poll_table *wait) +{ + struct sock *sk = sock->sk; + struct pep_sock *pn = pep_sk(sk); + unsigned int mask = 0; + + poll_wait(file, &sock->wait, wait); + + switch (sk->sk_state) { + case TCP_LISTEN: + return hlist_empty(&pn->ackq) ? 0 : POLLIN; + case TCP_CLOSE: + return POLLERR; + } + + if (!skb_queue_empty(&sk->sk_receive_queue)) + mask |= POLLIN | POLLRDNORM; + 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) + mask |= POLLOUT | POLLWRNORM | POLLWRBAND; + + return mask; +} + static int pn_socket_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { @@ -220,6 +271,30 @@ static int pn_socket_ioctl(struct socket *sock, unsigned int cmd, return sk->sk_prot->ioctl(sk, cmd, arg); } +static int pn_socket_listen(struct socket *sock, int backlog) +{ + struct sock *sk = sock->sk; + int err = 0; + + if (sock->state != SS_UNCONNECTED) + return -EINVAL; + if (pn_socket_autobind(sock)) + return -ENOBUFS; + + lock_sock(sk); + if (sk->sk_state != TCP_CLOSE) { + err = -EINVAL; + goto out; + } + + sk->sk_state = TCP_LISTEN; + sk->sk_ack_backlog = 0; + sk->sk_max_ack_backlog = backlog; +out: + release_sock(sk); + return err; +} + static int pn_socket_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t total_len) { @@ -256,12 +331,39 @@ const struct proto_ops phonet_dgram_ops = { .sendpage = sock_no_sendpage, }; +const struct proto_ops phonet_stream_ops = { + .family = AF_PHONET, + .owner = THIS_MODULE, + .release = pn_socket_release, + .bind = pn_socket_bind, + .connect = sock_no_connect, + .socketpair = sock_no_socketpair, + .accept = pn_socket_accept, + .getname = pn_socket_getname, + .poll = pn_socket_poll, + .ioctl = pn_socket_ioctl, + .listen = pn_socket_listen, + .shutdown = sock_no_shutdown, + .setsockopt = sock_common_setsockopt, + .getsockopt = sock_common_getsockopt, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_sock_common_setsockopt, + .compat_getsockopt = compat_sock_common_getsockopt, +#endif + .sendmsg = pn_socket_sendmsg, + .recvmsg = sock_common_recvmsg, + .mmap = sock_no_mmap, + .sendpage = sock_no_sendpage, +}; +EXPORT_SYMBOL(phonet_stream_ops); + static DEFINE_MUTEX(port_mutex); /* allocate port for a socket */ 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; @@ -273,15 +375,16 @@ int pn_sock_get_port(struct sock *sk, unsigned short sport) if (!sport) { /* search free port */ - int port, pmin = 0x40, pmax = 0x7f; + int port, pmin, pmax; + phonet_get_local_port_range(&pmin, &pmax); for (port = pmin; port <= pmax; port++) { port_cur++; if (port_cur < pmin || port_cur > pmax) 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; @@ -291,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;