]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - net/phonet/socket.c
cea1136cbe4679beb7a0f8898e1499b5cda929ca
[linux-2.6-omap-h63xx.git] / net / phonet / socket.c
1 /*
2  * File: socket.c
3  *
4  * Phonet sockets
5  *
6  * Copyright (C) 2008 Nokia Corporation.
7  *
8  * Contact: Remi Denis-Courmont <remi.denis-courmont@nokia.com>
9  * Original author: Sakari Ailus <sakari.ailus@nokia.com>
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * version 2 as published by the Free Software Foundation.
14  *
15  * This program is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23  * 02110-1301 USA
24  */
25
26 #include <linux/kernel.h>
27 #include <linux/net.h>
28 #include <linux/poll.h>
29 #include <net/sock.h>
30 #include <net/tcp_states.h>
31
32 #include <linux/phonet.h>
33 #include <net/phonet/phonet.h>
34 #include <net/phonet/pep.h>
35 #include <net/phonet/pn_dev.h>
36
37 static int pn_socket_release(struct socket *sock)
38 {
39         struct sock *sk = sock->sk;
40
41         if (sk) {
42                 sock->sk = NULL;
43                 sk->sk_prot->close(sk, 0);
44         }
45         return 0;
46 }
47
48 static struct  {
49         struct hlist_head hlist;
50         spinlock_t lock;
51 } pnsocks = {
52         .hlist = HLIST_HEAD_INIT,
53         .lock = __SPIN_LOCK_UNLOCKED(pnsocks.lock),
54 };
55
56 /*
57  * Find address based on socket address, match only certain fields.
58  * Also grab sock if it was found. Remember to sock_put it later.
59  */
60 struct sock *pn_find_sock_by_sa(const struct sockaddr_pn *spn)
61 {
62         struct hlist_node *node;
63         struct sock *sknode;
64         struct sock *rval = NULL;
65         u16 obj = pn_sockaddr_get_object(spn);
66         u8 res = spn->spn_resource;
67
68         spin_lock_bh(&pnsocks.lock);
69
70         sk_for_each(sknode, node, &pnsocks.hlist) {
71                 struct pn_sock *pn = pn_sk(sknode);
72                 BUG_ON(!pn->sobject); /* unbound socket */
73
74                 if (pn_port(obj)) {
75                         /* Look up socket by port */
76                         if (pn_port(pn->sobject) != pn_port(obj))
77                                 continue;
78                 } else {
79                         /* If port is zero, look up by resource */
80                         if (pn->resource != res)
81                                 continue;
82                 }
83                 if (pn_addr(pn->sobject)
84                  && pn_addr(pn->sobject) != pn_addr(obj))
85                         continue;
86
87                 rval = sknode;
88                 sock_hold(sknode);
89                 break;
90         }
91
92         spin_unlock_bh(&pnsocks.lock);
93
94         return rval;
95
96 }
97
98 void pn_sock_hash(struct sock *sk)
99 {
100         spin_lock_bh(&pnsocks.lock);
101         sk_add_node(sk, &pnsocks.hlist);
102         spin_unlock_bh(&pnsocks.lock);
103 }
104 EXPORT_SYMBOL(pn_sock_hash);
105
106 void pn_sock_unhash(struct sock *sk)
107 {
108         spin_lock_bh(&pnsocks.lock);
109         sk_del_node_init(sk);
110         spin_unlock_bh(&pnsocks.lock);
111 }
112 EXPORT_SYMBOL(pn_sock_unhash);
113
114 static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len)
115 {
116         struct sock *sk = sock->sk;
117         struct pn_sock *pn = pn_sk(sk);
118         struct sockaddr_pn *spn = (struct sockaddr_pn *)addr;
119         int err;
120         u16 handle;
121         u8 saddr;
122
123         if (sk->sk_prot->bind)
124                 return sk->sk_prot->bind(sk, addr, len);
125
126         if (len < sizeof(struct sockaddr_pn))
127                 return -EINVAL;
128         if (spn->spn_family != AF_PHONET)
129                 return -EAFNOSUPPORT;
130
131         handle = pn_sockaddr_get_object((struct sockaddr_pn *)addr);
132         saddr = pn_addr(handle);
133         if (saddr && phonet_address_lookup(saddr))
134                 return -EADDRNOTAVAIL;
135
136         lock_sock(sk);
137         if (sk->sk_state != TCP_CLOSE || pn_port(pn->sobject)) {
138                 err = -EINVAL; /* attempt to rebind */
139                 goto out;
140         }
141         err = sk->sk_prot->get_port(sk, pn_port(handle));
142         if (err)
143                 goto out;
144
145         /* get_port() sets the port, bind() sets the address if applicable */
146         pn->sobject = pn_object(saddr, pn_port(pn->sobject));
147         pn->resource = spn->spn_resource;
148
149         /* Enable RX on the socket */
150         sk->sk_prot->hash(sk);
151 out:
152         release_sock(sk);
153         return err;
154 }
155
156 static int pn_socket_autobind(struct socket *sock)
157 {
158         struct sockaddr_pn sa;
159         int err;
160
161         memset(&sa, 0, sizeof(sa));
162         sa.spn_family = AF_PHONET;
163         err = pn_socket_bind(sock, (struct sockaddr *)&sa,
164                                 sizeof(struct sockaddr_pn));
165         if (err != -EINVAL)
166                 return err;
167         BUG_ON(!pn_port(pn_sk(sock->sk)->sobject));
168         return 0; /* socket was already bound */
169 }
170
171 static int pn_socket_accept(struct socket *sock, struct socket *newsock,
172                                 int flags)
173 {
174         struct sock *sk = sock->sk;
175         struct sock *newsk;
176         int err;
177
178         newsk = sk->sk_prot->accept(sk, flags, &err);
179         if (!newsk)
180                 return err;
181
182         lock_sock(newsk);
183         sock_graft(newsk, newsock);
184         newsock->state = SS_CONNECTED;
185         release_sock(newsk);
186         return 0;
187 }
188
189 static int pn_socket_getname(struct socket *sock, struct sockaddr *addr,
190                                 int *sockaddr_len, int peer)
191 {
192         struct sock *sk = sock->sk;
193         struct pn_sock *pn = pn_sk(sk);
194
195         memset(addr, 0, sizeof(struct sockaddr_pn));
196         addr->sa_family = AF_PHONET;
197         if (!peer) /* Race with bind() here is userland's problem. */
198                 pn_sockaddr_set_object((struct sockaddr_pn *)addr,
199                                         pn->sobject);
200
201         *sockaddr_len = sizeof(struct sockaddr_pn);
202         return 0;
203 }
204
205 static unsigned int pn_socket_poll(struct file *file, struct socket *sock,
206                                         poll_table *wait)
207 {
208         struct sock *sk = sock->sk;
209         struct pep_sock *pn = pep_sk(sk);
210         unsigned int mask = 0;
211
212         poll_wait(file, &sock->wait, wait);
213
214         switch (sk->sk_state) {
215         case TCP_LISTEN:
216                 return hlist_empty(&pn->ackq) ? 0 : POLLIN;
217         case TCP_CLOSE:
218                 return POLLERR;
219         }
220
221         if (!skb_queue_empty(&sk->sk_receive_queue))
222                 mask |= POLLIN | POLLRDNORM;
223         else if (sk->sk_state == TCP_CLOSE_WAIT)
224                 return POLLHUP;
225
226         if (sk->sk_state == TCP_ESTABLISHED && pn->tx_credits)
227                 mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
228
229         return mask;
230 }
231
232 static int pn_socket_ioctl(struct socket *sock, unsigned int cmd,
233                                 unsigned long arg)
234 {
235         struct sock *sk = sock->sk;
236         struct pn_sock *pn = pn_sk(sk);
237
238         if (cmd == SIOCPNGETOBJECT) {
239                 struct net_device *dev;
240                 u16 handle;
241                 u8 saddr;
242
243                 if (get_user(handle, (__u16 __user *)arg))
244                         return -EFAULT;
245
246                 lock_sock(sk);
247                 if (sk->sk_bound_dev_if)
248                         dev = dev_get_by_index(sock_net(sk),
249                                                 sk->sk_bound_dev_if);
250                 else
251                         dev = phonet_device_get(sock_net(sk));
252                 if (dev && (dev->flags & IFF_UP))
253                         saddr = phonet_address_get(dev, pn_addr(handle));
254                 else
255                         saddr = PN_NO_ADDR;
256                 release_sock(sk);
257
258                 if (dev)
259                         dev_put(dev);
260                 if (saddr == PN_NO_ADDR)
261                         return -EHOSTUNREACH;
262
263                 handle = pn_object(saddr, pn_port(pn->sobject));
264                 return put_user(handle, (__u16 __user *)arg);
265         }
266
267         return sk->sk_prot->ioctl(sk, cmd, arg);
268 }
269
270 static int pn_socket_listen(struct socket *sock, int backlog)
271 {
272         struct sock *sk = sock->sk;
273         int err = 0;
274
275         if (sock->state != SS_UNCONNECTED)
276                 return -EINVAL;
277         if (pn_socket_autobind(sock))
278                 return -ENOBUFS;
279
280         lock_sock(sk);
281         if (sk->sk_state != TCP_CLOSE) {
282                 err = -EINVAL;
283                 goto out;
284         }
285
286         sk->sk_state = TCP_LISTEN;
287         sk->sk_ack_backlog = 0;
288         sk->sk_max_ack_backlog = backlog;
289 out:
290         release_sock(sk);
291         return err;
292 }
293
294 static int pn_socket_sendmsg(struct kiocb *iocb, struct socket *sock,
295                                 struct msghdr *m, size_t total_len)
296 {
297         struct sock *sk = sock->sk;
298
299         if (pn_socket_autobind(sock))
300                 return -EAGAIN;
301
302         return sk->sk_prot->sendmsg(iocb, sk, m, total_len);
303 }
304
305 const struct proto_ops phonet_dgram_ops = {
306         .family         = AF_PHONET,
307         .owner          = THIS_MODULE,
308         .release        = pn_socket_release,
309         .bind           = pn_socket_bind,
310         .connect        = sock_no_connect,
311         .socketpair     = sock_no_socketpair,
312         .accept         = sock_no_accept,
313         .getname        = pn_socket_getname,
314         .poll           = datagram_poll,
315         .ioctl          = pn_socket_ioctl,
316         .listen         = sock_no_listen,
317         .shutdown       = sock_no_shutdown,
318         .setsockopt     = sock_no_setsockopt,
319         .getsockopt     = sock_no_getsockopt,
320 #ifdef CONFIG_COMPAT
321         .compat_setsockopt = sock_no_setsockopt,
322         .compat_getsockopt = sock_no_getsockopt,
323 #endif
324         .sendmsg        = pn_socket_sendmsg,
325         .recvmsg        = sock_common_recvmsg,
326         .mmap           = sock_no_mmap,
327         .sendpage       = sock_no_sendpage,
328 };
329
330 const struct proto_ops phonet_stream_ops = {
331         .family         = AF_PHONET,
332         .owner          = THIS_MODULE,
333         .release        = pn_socket_release,
334         .bind           = pn_socket_bind,
335         .connect        = sock_no_connect,
336         .socketpair     = sock_no_socketpair,
337         .accept         = pn_socket_accept,
338         .getname        = pn_socket_getname,
339         .poll           = pn_socket_poll,
340         .ioctl          = pn_socket_ioctl,
341         .listen         = pn_socket_listen,
342         .shutdown       = sock_no_shutdown,
343         .setsockopt     = sock_no_setsockopt,
344         .getsockopt     = sock_no_getsockopt,
345 #ifdef CONFIG_COMPAT
346         .compat_setsockopt = sock_no_setsockopt,
347         .compat_getsockopt = compat_sock_no_getsockopt,
348 #endif
349         .sendmsg        = pn_socket_sendmsg,
350         .recvmsg        = sock_common_recvmsg,
351         .mmap           = sock_no_mmap,
352         .sendpage       = sock_no_sendpage,
353 };
354 EXPORT_SYMBOL(phonet_stream_ops);
355
356 static DEFINE_MUTEX(port_mutex);
357
358 /* allocate port for a socket */
359 int pn_sock_get_port(struct sock *sk, unsigned short sport)
360 {
361         static int port_cur;
362         struct pn_sock *pn = pn_sk(sk);
363         struct sockaddr_pn try_sa;
364         struct sock *tmpsk;
365
366         memset(&try_sa, 0, sizeof(struct sockaddr_pn));
367         try_sa.spn_family = AF_PHONET;
368
369         mutex_lock(&port_mutex);
370
371         if (!sport) {
372                 /* search free port */
373                 int port, pmin, pmax;
374
375                 phonet_get_local_port_range(&pmin, &pmax);
376                 for (port = pmin; port <= pmax; port++) {
377                         port_cur++;
378                         if (port_cur < pmin || port_cur > pmax)
379                                 port_cur = pmin;
380
381                         pn_sockaddr_set_port(&try_sa, port_cur);
382                         tmpsk = pn_find_sock_by_sa(&try_sa);
383                         if (tmpsk == NULL) {
384                                 sport = port_cur;
385                                 goto found;
386                         } else
387                                 sock_put(tmpsk);
388                 }
389         } else {
390                 /* try to find specific port */
391                 pn_sockaddr_set_port(&try_sa, sport);
392                 tmpsk = pn_find_sock_by_sa(&try_sa);
393                 if (tmpsk == NULL)
394                         /* No sock there! We can use that port... */
395                         goto found;
396                 else
397                         sock_put(tmpsk);
398         }
399         mutex_unlock(&port_mutex);
400
401         /* the port must be in use already */
402         return -EADDRINUSE;
403
404 found:
405         mutex_unlock(&port_mutex);
406         pn->sobject = pn_object(pn_addr(pn->sobject), sport);
407         return 0;
408 }
409 EXPORT_SYMBOL(pn_sock_get_port);