xref: /linux/net/phonet/socket.c (revision 367b8112fe2ea5c39a7bb4d263dcdd9b612fae18)
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 	if (!skb_queue_empty(&pn->ctrlreq_queue))
224 		mask |= POLLPRI;
225 	if (!mask && sk->sk_state == TCP_CLOSE_WAIT)
226 		return POLLHUP;
227 
228 	if (sk->sk_state == TCP_ESTABLISHED && pn->tx_credits)
229 		mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
230 
231 	return mask;
232 }
233 
234 static int pn_socket_ioctl(struct socket *sock, unsigned int cmd,
235 				unsigned long arg)
236 {
237 	struct sock *sk = sock->sk;
238 	struct pn_sock *pn = pn_sk(sk);
239 
240 	if (cmd == SIOCPNGETOBJECT) {
241 		struct net_device *dev;
242 		u16 handle;
243 		u8 saddr;
244 
245 		if (get_user(handle, (__u16 __user *)arg))
246 			return -EFAULT;
247 
248 		lock_sock(sk);
249 		if (sk->sk_bound_dev_if)
250 			dev = dev_get_by_index(sock_net(sk),
251 						sk->sk_bound_dev_if);
252 		else
253 			dev = phonet_device_get(sock_net(sk));
254 		if (dev && (dev->flags & IFF_UP))
255 			saddr = phonet_address_get(dev, pn_addr(handle));
256 		else
257 			saddr = PN_NO_ADDR;
258 		release_sock(sk);
259 
260 		if (dev)
261 			dev_put(dev);
262 		if (saddr == PN_NO_ADDR)
263 			return -EHOSTUNREACH;
264 
265 		handle = pn_object(saddr, pn_port(pn->sobject));
266 		return put_user(handle, (__u16 __user *)arg);
267 	}
268 
269 	return sk->sk_prot->ioctl(sk, cmd, arg);
270 }
271 
272 static int pn_socket_listen(struct socket *sock, int backlog)
273 {
274 	struct sock *sk = sock->sk;
275 	int err = 0;
276 
277 	if (sock->state != SS_UNCONNECTED)
278 		return -EINVAL;
279 	if (pn_socket_autobind(sock))
280 		return -ENOBUFS;
281 
282 	lock_sock(sk);
283 	if (sk->sk_state != TCP_CLOSE) {
284 		err = -EINVAL;
285 		goto out;
286 	}
287 
288 	sk->sk_state = TCP_LISTEN;
289 	sk->sk_ack_backlog = 0;
290 	sk->sk_max_ack_backlog = backlog;
291 out:
292 	release_sock(sk);
293 	return err;
294 }
295 
296 static int pn_socket_sendmsg(struct kiocb *iocb, struct socket *sock,
297 				struct msghdr *m, size_t total_len)
298 {
299 	struct sock *sk = sock->sk;
300 
301 	if (pn_socket_autobind(sock))
302 		return -EAGAIN;
303 
304 	return sk->sk_prot->sendmsg(iocb, sk, m, total_len);
305 }
306 
307 const struct proto_ops phonet_dgram_ops = {
308 	.family		= AF_PHONET,
309 	.owner		= THIS_MODULE,
310 	.release	= pn_socket_release,
311 	.bind		= pn_socket_bind,
312 	.connect	= sock_no_connect,
313 	.socketpair	= sock_no_socketpair,
314 	.accept		= sock_no_accept,
315 	.getname	= pn_socket_getname,
316 	.poll		= datagram_poll,
317 	.ioctl		= pn_socket_ioctl,
318 	.listen		= sock_no_listen,
319 	.shutdown	= sock_no_shutdown,
320 	.setsockopt	= sock_no_setsockopt,
321 	.getsockopt	= sock_no_getsockopt,
322 #ifdef CONFIG_COMPAT
323 	.compat_setsockopt = sock_no_setsockopt,
324 	.compat_getsockopt = sock_no_getsockopt,
325 #endif
326 	.sendmsg	= pn_socket_sendmsg,
327 	.recvmsg	= sock_common_recvmsg,
328 	.mmap		= sock_no_mmap,
329 	.sendpage	= sock_no_sendpage,
330 };
331 
332 const struct proto_ops phonet_stream_ops = {
333 	.family		= AF_PHONET,
334 	.owner		= THIS_MODULE,
335 	.release	= pn_socket_release,
336 	.bind		= pn_socket_bind,
337 	.connect	= sock_no_connect,
338 	.socketpair	= sock_no_socketpair,
339 	.accept		= pn_socket_accept,
340 	.getname	= pn_socket_getname,
341 	.poll		= pn_socket_poll,
342 	.ioctl		= pn_socket_ioctl,
343 	.listen		= pn_socket_listen,
344 	.shutdown	= sock_no_shutdown,
345 	.setsockopt	= sock_common_setsockopt,
346 	.getsockopt	= sock_common_getsockopt,
347 #ifdef CONFIG_COMPAT
348 	.compat_setsockopt = compat_sock_common_setsockopt,
349 	.compat_getsockopt = compat_sock_common_getsockopt,
350 #endif
351 	.sendmsg	= pn_socket_sendmsg,
352 	.recvmsg	= sock_common_recvmsg,
353 	.mmap		= sock_no_mmap,
354 	.sendpage	= sock_no_sendpage,
355 };
356 EXPORT_SYMBOL(phonet_stream_ops);
357 
358 static DEFINE_MUTEX(port_mutex);
359 
360 /* allocate port for a socket */
361 int pn_sock_get_port(struct sock *sk, unsigned short sport)
362 {
363 	static int port_cur;
364 	struct pn_sock *pn = pn_sk(sk);
365 	struct sockaddr_pn try_sa;
366 	struct sock *tmpsk;
367 
368 	memset(&try_sa, 0, sizeof(struct sockaddr_pn));
369 	try_sa.spn_family = AF_PHONET;
370 
371 	mutex_lock(&port_mutex);
372 
373 	if (!sport) {
374 		/* search free port */
375 		int port, pmin, pmax;
376 
377 		phonet_get_local_port_range(&pmin, &pmax);
378 		for (port = pmin; port <= pmax; port++) {
379 			port_cur++;
380 			if (port_cur < pmin || port_cur > pmax)
381 				port_cur = pmin;
382 
383 			pn_sockaddr_set_port(&try_sa, port_cur);
384 			tmpsk = pn_find_sock_by_sa(&try_sa);
385 			if (tmpsk == NULL) {
386 				sport = port_cur;
387 				goto found;
388 			} else
389 				sock_put(tmpsk);
390 		}
391 	} else {
392 		/* try to find specific port */
393 		pn_sockaddr_set_port(&try_sa, sport);
394 		tmpsk = pn_find_sock_by_sa(&try_sa);
395 		if (tmpsk == NULL)
396 			/* No sock there! We can use that port... */
397 			goto found;
398 		else
399 			sock_put(tmpsk);
400 	}
401 	mutex_unlock(&port_mutex);
402 
403 	/* the port must be in use already */
404 	return -EADDRINUSE;
405 
406 found:
407 	mutex_unlock(&port_mutex);
408 	pn->sobject = pn_object(pn_addr(pn->sobject), sport);
409 	return 0;
410 }
411 EXPORT_SYMBOL(pn_sock_get_port);
412