• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* AF_RXRPC local endpoint management
2  *
3  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells (dhowells@redhat.com)
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version
9  * 2 of the License, or (at your option) any later version.
10  */
11 
12 #include <linux/module.h>
13 #include <linux/net.h>
14 #include <linux/skbuff.h>
15 #include <linux/slab.h>
16 #include <linux/udp.h>
17 #include <linux/ip.h>
18 #include <net/sock.h>
19 #include <net/af_rxrpc.h>
20 #include <generated/utsrelease.h>
21 #include "ar-internal.h"
22 
23 static const char rxrpc_version_string[65] = "linux-" UTS_RELEASE " AF_RXRPC";
24 
25 static LIST_HEAD(rxrpc_locals);
26 DEFINE_RWLOCK(rxrpc_local_lock);
27 static DECLARE_RWSEM(rxrpc_local_sem);
28 static DECLARE_WAIT_QUEUE_HEAD(rxrpc_local_wq);
29 
30 static void rxrpc_destroy_local(struct work_struct *work);
31 static void rxrpc_process_local_events(struct work_struct *work);
32 
33 /*
34  * allocate a new local
35  */
36 static
rxrpc_alloc_local(struct sockaddr_rxrpc * srx)37 struct rxrpc_local *rxrpc_alloc_local(struct sockaddr_rxrpc *srx)
38 {
39 	struct rxrpc_local *local;
40 
41 	local = kzalloc(sizeof(struct rxrpc_local), GFP_KERNEL);
42 	if (local) {
43 		INIT_WORK(&local->destroyer, &rxrpc_destroy_local);
44 		INIT_WORK(&local->acceptor, &rxrpc_accept_incoming_calls);
45 		INIT_WORK(&local->rejecter, &rxrpc_reject_packets);
46 		INIT_WORK(&local->event_processor, &rxrpc_process_local_events);
47 		INIT_LIST_HEAD(&local->services);
48 		INIT_LIST_HEAD(&local->link);
49 		init_rwsem(&local->defrag_sem);
50 		skb_queue_head_init(&local->accept_queue);
51 		skb_queue_head_init(&local->reject_queue);
52 		skb_queue_head_init(&local->event_queue);
53 		spin_lock_init(&local->lock);
54 		rwlock_init(&local->services_lock);
55 		atomic_set(&local->usage, 1);
56 		local->debug_id = atomic_inc_return(&rxrpc_debug_id);
57 		memcpy(&local->srx, srx, sizeof(*srx));
58 	}
59 
60 	_leave(" = %p", local);
61 	return local;
62 }
63 
64 /*
65  * create the local socket
66  * - must be called with rxrpc_local_sem writelocked
67  */
rxrpc_create_local(struct rxrpc_local * local)68 static int rxrpc_create_local(struct rxrpc_local *local)
69 {
70 	struct sock *sock;
71 	int ret, opt;
72 
73 	_enter("%p{%d}", local, local->srx.transport_type);
74 
75 	/* create a socket to represent the local endpoint */
76 	ret = sock_create_kern(&init_net, PF_INET, local->srx.transport_type,
77 			       IPPROTO_UDP, &local->socket);
78 	if (ret < 0) {
79 		_leave(" = %d [socket]", ret);
80 		return ret;
81 	}
82 
83 	/* if a local address was supplied then bind it */
84 	if (local->srx.transport_len > sizeof(sa_family_t)) {
85 		_debug("bind");
86 		ret = kernel_bind(local->socket,
87 				  (struct sockaddr *) &local->srx.transport,
88 				  local->srx.transport_len);
89 		if (ret < 0) {
90 			_debug("bind failed");
91 			goto error;
92 		}
93 	}
94 
95 	/* we want to receive ICMP errors */
96 	opt = 1;
97 	ret = kernel_setsockopt(local->socket, SOL_IP, IP_RECVERR,
98 				(char *) &opt, sizeof(opt));
99 	if (ret < 0) {
100 		_debug("setsockopt failed");
101 		goto error;
102 	}
103 
104 	/* we want to set the don't fragment bit */
105 	opt = IP_PMTUDISC_DO;
106 	ret = kernel_setsockopt(local->socket, SOL_IP, IP_MTU_DISCOVER,
107 				(char *) &opt, sizeof(opt));
108 	if (ret < 0) {
109 		_debug("setsockopt failed");
110 		goto error;
111 	}
112 
113 	write_lock_bh(&rxrpc_local_lock);
114 	list_add(&local->link, &rxrpc_locals);
115 	write_unlock_bh(&rxrpc_local_lock);
116 
117 	/* set the socket up */
118 	sock = local->socket->sk;
119 	sock->sk_user_data	= local;
120 	sock->sk_data_ready	= rxrpc_data_ready;
121 	sock->sk_error_report	= rxrpc_UDP_error_report;
122 	_leave(" = 0");
123 	return 0;
124 
125 error:
126 	kernel_sock_shutdown(local->socket, SHUT_RDWR);
127 	local->socket->sk->sk_user_data = NULL;
128 	sock_release(local->socket);
129 	local->socket = NULL;
130 
131 	_leave(" = %d", ret);
132 	return ret;
133 }
134 
135 /*
136  * create a new local endpoint using the specified UDP address
137  */
rxrpc_lookup_local(struct sockaddr_rxrpc * srx)138 struct rxrpc_local *rxrpc_lookup_local(struct sockaddr_rxrpc *srx)
139 {
140 	struct rxrpc_local *local;
141 	int ret;
142 
143 	_enter("{%d,%u,%pI4+%hu}",
144 	       srx->transport_type,
145 	       srx->transport.family,
146 	       &srx->transport.sin.sin_addr,
147 	       ntohs(srx->transport.sin.sin_port));
148 
149 	down_write(&rxrpc_local_sem);
150 
151 	/* see if we have a suitable local local endpoint already */
152 	read_lock_bh(&rxrpc_local_lock);
153 
154 	list_for_each_entry(local, &rxrpc_locals, link) {
155 		_debug("CMP {%d,%u,%pI4+%hu}",
156 		       local->srx.transport_type,
157 		       local->srx.transport.family,
158 		       &local->srx.transport.sin.sin_addr,
159 		       ntohs(local->srx.transport.sin.sin_port));
160 
161 		if (local->srx.transport_type != srx->transport_type ||
162 		    local->srx.transport.family != srx->transport.family)
163 			continue;
164 
165 		switch (srx->transport.family) {
166 		case AF_INET:
167 			if (local->srx.transport.sin.sin_port !=
168 			    srx->transport.sin.sin_port)
169 				continue;
170 			if (memcmp(&local->srx.transport.sin.sin_addr,
171 				   &srx->transport.sin.sin_addr,
172 				   sizeof(struct in_addr)) != 0)
173 				continue;
174 			goto found_local;
175 
176 		default:
177 			BUG();
178 		}
179 	}
180 
181 	read_unlock_bh(&rxrpc_local_lock);
182 
183 	/* we didn't find one, so we need to create one */
184 	local = rxrpc_alloc_local(srx);
185 	if (!local) {
186 		up_write(&rxrpc_local_sem);
187 		return ERR_PTR(-ENOMEM);
188 	}
189 
190 	ret = rxrpc_create_local(local);
191 	if (ret < 0) {
192 		up_write(&rxrpc_local_sem);
193 		kfree(local);
194 		_leave(" = %d", ret);
195 		return ERR_PTR(ret);
196 	}
197 
198 	up_write(&rxrpc_local_sem);
199 
200 	_net("LOCAL new %d {%d,%u,%pI4+%hu}",
201 	     local->debug_id,
202 	     local->srx.transport_type,
203 	     local->srx.transport.family,
204 	     &local->srx.transport.sin.sin_addr,
205 	     ntohs(local->srx.transport.sin.sin_port));
206 
207 	_leave(" = %p [new]", local);
208 	return local;
209 
210 found_local:
211 	rxrpc_get_local(local);
212 	read_unlock_bh(&rxrpc_local_lock);
213 	up_write(&rxrpc_local_sem);
214 
215 	_net("LOCAL old %d {%d,%u,%pI4+%hu}",
216 	     local->debug_id,
217 	     local->srx.transport_type,
218 	     local->srx.transport.family,
219 	     &local->srx.transport.sin.sin_addr,
220 	     ntohs(local->srx.transport.sin.sin_port));
221 
222 	_leave(" = %p [reuse]", local);
223 	return local;
224 }
225 
226 /*
227  * release a local endpoint
228  */
rxrpc_put_local(struct rxrpc_local * local)229 void rxrpc_put_local(struct rxrpc_local *local)
230 {
231 	_enter("%p{u=%d}", local, atomic_read(&local->usage));
232 
233 	ASSERTCMP(atomic_read(&local->usage), >, 0);
234 
235 	/* to prevent a race, the decrement and the dequeue must be effectively
236 	 * atomic */
237 	write_lock_bh(&rxrpc_local_lock);
238 	if (unlikely(atomic_dec_and_test(&local->usage))) {
239 		_debug("destroy local");
240 		rxrpc_queue_work(&local->destroyer);
241 	}
242 	write_unlock_bh(&rxrpc_local_lock);
243 	_leave("");
244 }
245 
246 /*
247  * destroy a local endpoint
248  */
rxrpc_destroy_local(struct work_struct * work)249 static void rxrpc_destroy_local(struct work_struct *work)
250 {
251 	struct rxrpc_local *local =
252 		container_of(work, struct rxrpc_local, destroyer);
253 
254 	_enter("%p{%d}", local, atomic_read(&local->usage));
255 
256 	down_write(&rxrpc_local_sem);
257 
258 	write_lock_bh(&rxrpc_local_lock);
259 	if (atomic_read(&local->usage) > 0) {
260 		write_unlock_bh(&rxrpc_local_lock);
261 		up_read(&rxrpc_local_sem);
262 		_leave(" [resurrected]");
263 		return;
264 	}
265 
266 	list_del(&local->link);
267 	local->socket->sk->sk_user_data = NULL;
268 	write_unlock_bh(&rxrpc_local_lock);
269 
270 	downgrade_write(&rxrpc_local_sem);
271 
272 	ASSERT(list_empty(&local->services));
273 	ASSERT(!work_pending(&local->acceptor));
274 	ASSERT(!work_pending(&local->rejecter));
275 	ASSERT(!work_pending(&local->event_processor));
276 
277 	/* finish cleaning up the local descriptor */
278 	rxrpc_purge_queue(&local->accept_queue);
279 	rxrpc_purge_queue(&local->reject_queue);
280 	rxrpc_purge_queue(&local->event_queue);
281 	kernel_sock_shutdown(local->socket, SHUT_RDWR);
282 	sock_release(local->socket);
283 
284 	up_read(&rxrpc_local_sem);
285 
286 	_net("DESTROY LOCAL %d", local->debug_id);
287 	kfree(local);
288 
289 	if (list_empty(&rxrpc_locals))
290 		wake_up_all(&rxrpc_local_wq);
291 
292 	_leave("");
293 }
294 
295 /*
296  * preemptively destroy all local local endpoint rather than waiting for
297  * them to be destroyed
298  */
rxrpc_destroy_all_locals(void)299 void __exit rxrpc_destroy_all_locals(void)
300 {
301 	DECLARE_WAITQUEUE(myself,current);
302 
303 	_enter("");
304 
305 	/* we simply have to wait for them to go away */
306 	if (!list_empty(&rxrpc_locals)) {
307 		set_current_state(TASK_UNINTERRUPTIBLE);
308 		add_wait_queue(&rxrpc_local_wq, &myself);
309 
310 		while (!list_empty(&rxrpc_locals)) {
311 			schedule();
312 			set_current_state(TASK_UNINTERRUPTIBLE);
313 		}
314 
315 		remove_wait_queue(&rxrpc_local_wq, &myself);
316 		set_current_state(TASK_RUNNING);
317 	}
318 
319 	_leave("");
320 }
321 
322 /*
323  * Reply to a version request
324  */
rxrpc_send_version_request(struct rxrpc_local * local,struct rxrpc_header * hdr,struct sk_buff * skb)325 static void rxrpc_send_version_request(struct rxrpc_local *local,
326 				       struct rxrpc_header *hdr,
327 				       struct sk_buff *skb)
328 {
329 	struct sockaddr_in sin;
330 	struct msghdr msg;
331 	struct kvec iov[2];
332 	size_t len;
333 	int ret;
334 
335 	_enter("");
336 
337 	sin.sin_family = AF_INET;
338 	sin.sin_port = udp_hdr(skb)->source;
339 	sin.sin_addr.s_addr = ip_hdr(skb)->saddr;
340 
341 	msg.msg_name	= &sin;
342 	msg.msg_namelen	= sizeof(sin);
343 	msg.msg_control	= NULL;
344 	msg.msg_controllen = 0;
345 	msg.msg_flags	= 0;
346 
347 	hdr->seq	= 0;
348 	hdr->serial	= 0;
349 	hdr->type	= RXRPC_PACKET_TYPE_VERSION;
350 	hdr->flags	= RXRPC_LAST_PACKET | (~hdr->flags & RXRPC_CLIENT_INITIATED);
351 	hdr->userStatus	= 0;
352 	hdr->_rsvd	= 0;
353 
354 	iov[0].iov_base	= hdr;
355 	iov[0].iov_len	= sizeof(*hdr);
356 	iov[1].iov_base	= (char *)rxrpc_version_string;
357 	iov[1].iov_len	= sizeof(rxrpc_version_string);
358 
359 	len = iov[0].iov_len + iov[1].iov_len;
360 
361 	_proto("Tx VERSION (reply)");
362 
363 	ret = kernel_sendmsg(local->socket, &msg, iov, 2, len);
364 	if (ret < 0)
365 		_debug("sendmsg failed: %d", ret);
366 
367 	_leave("");
368 }
369 
370 /*
371  * Process event packets targetted at a local endpoint.
372  */
rxrpc_process_local_events(struct work_struct * work)373 static void rxrpc_process_local_events(struct work_struct *work)
374 {
375 	struct rxrpc_local *local = container_of(work, struct rxrpc_local, event_processor);
376 	struct sk_buff *skb;
377 	char v;
378 
379 	_enter("");
380 
381 	atomic_inc(&local->usage);
382 
383 	while ((skb = skb_dequeue(&local->event_queue))) {
384 		struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
385 
386 		kdebug("{%d},{%u}", local->debug_id, sp->hdr.type);
387 
388 		switch (sp->hdr.type) {
389 		case RXRPC_PACKET_TYPE_VERSION:
390 			if (skb_copy_bits(skb, 0, &v, 1) < 0)
391 				return;
392 			_proto("Rx VERSION { %02x }", v);
393 			if (v == 0)
394 				rxrpc_send_version_request(local, &sp->hdr, skb);
395 			break;
396 
397 		default:
398 			/* Just ignore anything we don't understand */
399 			break;
400 		}
401 
402 		rxrpc_put_local(local);
403 		rxrpc_free_skb(skb);
404 	}
405 
406 	rxrpc_put_local(local);
407 	_leave("");
408 }
409