File Index
Files and directories
Sign in
FILE

endpointola.c

File preview with syntax highlighting.

linux-6.19.14/net/sctp/endpointola.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/* SCTP kernel implementation
  3 * Copyright (c) 1999-2000 Cisco, Inc.
  4 * Copyright (c) 1999-2001 Motorola, Inc.
  5 * Copyright (c) 2001-2002 International Business Machines, Corp.
  6 * Copyright (c) 2001 Intel Corp.
  7 * Copyright (c) 2001 Nokia, Inc.
  8 * Copyright (c) 2001 La Monte H.P. Yarroll
  9 *
 10 * This file is part of the SCTP kernel implementation
 11 *
 12 * This abstraction represents an SCTP endpoint.
 13 *
 14 * Please send any bug reports or fixes you make to the
 15 * email address(es):
 16 *    lksctp developers <linux-sctp@vger.kernel.org>
 17 *
 18 * Written or modified by:
 19 *    La Monte H.P. Yarroll <piggy@acm.org>
 20 *    Karl Knutson <karl@athena.chicago.il.us>
 21 *    Jon Grimm <jgrimm@austin.ibm.com>
 22 *    Daisy Chang <daisyc@us.ibm.com>
 23 *    Dajiang Zhang <dajiang.zhang@nokia.com>
 24 */
 25
 26#include <linux/types.h>
 27#include <linux/slab.h>
 28#include <linux/in.h>
 29#include <linux/random.h>	/* get_random_bytes() */
 30#include <net/sock.h>
 31#include <net/ipv6.h>
 32#include <net/sctp/sctp.h>
 33#include <net/sctp/sm.h>
 34
 35/* Forward declarations for internal helpers. */
 36static void sctp_endpoint_bh_rcv(struct work_struct *work);
 37
 38static void gen_cookie_auth_key(struct hmac_sha256_key *key)
 39{
 40	u8 raw_key[SCTP_COOKIE_KEY_SIZE];
 41
 42	get_random_bytes(raw_key, sizeof(raw_key));
 43	hmac_sha256_preparekey(key, raw_key, sizeof(raw_key));
 44	memzero_explicit(raw_key, sizeof(raw_key));
 45}
 46
 47/*
 48 * Initialize the base fields of the endpoint structure.
 49 */
 50static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
 51						struct sock *sk,
 52						gfp_t gfp)
 53{
 54	struct net *net = sock_net(sk);
 55	struct sctp_shared_key *null_key;
 56
 57	ep->asconf_enable = net->sctp.addip_enable;
 58	ep->auth_enable = net->sctp.auth_enable;
 59	if (ep->auth_enable) {
 60		if (sctp_auth_init(ep, gfp))
 61			goto nomem;
 62		if (ep->asconf_enable) {
 63			sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF);
 64			sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF_ACK);
 65		}
 66	}
 67
 68	/* Initialize the base structure. */
 69	/* What type of endpoint are we?  */
 70	ep->base.type = SCTP_EP_TYPE_SOCKET;
 71
 72	/* Initialize the basic object fields. */
 73	refcount_set(&ep->base.refcnt, 1);
 74	ep->base.dead = false;
 75
 76	/* Create an input queue.  */
 77	sctp_inq_init(&ep->base.inqueue);
 78
 79	/* Set its top-half handler */
 80	sctp_inq_set_th_handler(&ep->base.inqueue, sctp_endpoint_bh_rcv);
 81
 82	/* Initialize the bind addr area */
 83	sctp_bind_addr_init(&ep->base.bind_addr, 0);
 84
 85	/* Create the lists of associations.  */
 86	INIT_LIST_HEAD(&ep->asocs);
 87
 88	/* Use SCTP specific send buffer space queues.  */
 89	ep->sndbuf_policy = net->sctp.sndbuf_policy;
 90
 91	sk->sk_data_ready = sctp_data_ready;
 92	sk->sk_write_space = sctp_write_space;
 93	sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
 94
 95	/* Get the receive buffer policy for this endpoint */
 96	ep->rcvbuf_policy = net->sctp.rcvbuf_policy;
 97
 98	/* Generate the cookie authentication key. */
 99	gen_cookie_auth_key(&ep->cookie_auth_key);
100
101	/* SCTP-AUTH extensions*/
102	INIT_LIST_HEAD(&ep->endpoint_shared_keys);
103	null_key = sctp_auth_shkey_create(0, gfp);
104	if (!null_key)
105		goto nomem_shkey;
106
107	list_add(&null_key->key_list, &ep->endpoint_shared_keys);
108
109	/* Add the null key to the endpoint shared keys list and
110	 * set the hmcas and chunks pointers.
111	 */
112	ep->prsctp_enable = net->sctp.prsctp_enable;
113	ep->reconf_enable = net->sctp.reconf_enable;
114	ep->ecn_enable = net->sctp.ecn_enable;
115
116	/* Remember who we are attached to.  */
117	ep->base.sk = sk;
118	ep->base.net = sock_net(sk);
119	sock_hold(ep->base.sk);
120
121	return ep;
122
123nomem_shkey:
124	sctp_auth_free(ep);
125nomem:
126	return NULL;
127
128}
129
130/* Create a sctp_endpoint with all that boring stuff initialized.
131 * Returns NULL if there isn't enough memory.
132 */
133struct sctp_endpoint *sctp_endpoint_new(struct sock *sk, gfp_t gfp)
134{
135	struct sctp_endpoint *ep;
136
137	/* Build a local endpoint. */
138	ep = kzalloc(sizeof(*ep), gfp);
139	if (!ep)
140		goto fail;
141
142	if (!sctp_endpoint_init(ep, sk, gfp))
143		goto fail_init;
144
145	SCTP_DBG_OBJCNT_INC(ep);
146	return ep;
147
148fail_init:
149	kfree(ep);
150fail:
151	return NULL;
152}
153
154/* Add an association to an endpoint.  */
155void sctp_endpoint_add_asoc(struct sctp_endpoint *ep,
156			    struct sctp_association *asoc)
157{
158	struct sock *sk = ep->base.sk;
159
160	/* If this is a temporary association, don't bother
161	 * since we'll be removing it shortly and don't
162	 * want anyone to find it anyway.
163	 */
164	if (asoc->temp)
165		return;
166
167	/* Now just add it to our list of asocs */
168	list_add_tail(&asoc->asocs, &ep->asocs);
169
170	/* Increment the backlog value for a TCP-style listening socket. */
171	if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))
172		sk_acceptq_added(sk);
173}
174
175/* Free the endpoint structure.  Delay cleanup until
176 * all users have released their reference count on this structure.
177 */
178void sctp_endpoint_free(struct sctp_endpoint *ep)
179{
180	ep->base.dead = true;
181
182	inet_sk_set_state(ep->base.sk, SCTP_SS_CLOSED);
183
184	/* Unlink this endpoint, so we can't find it again! */
185	sctp_unhash_endpoint(ep);
186
187	sctp_endpoint_put(ep);
188}
189
190/* Final destructor for endpoint.  */
191static void sctp_endpoint_destroy_rcu(struct rcu_head *head)
192{
193	struct sctp_endpoint *ep = container_of(head, struct sctp_endpoint, rcu);
194	struct sock *sk = ep->base.sk;
195
196	sctp_sk(sk)->ep = NULL;
197	sock_put(sk);
198
199	kfree(ep);
200	SCTP_DBG_OBJCNT_DEC(ep);
201}
202
203static void sctp_endpoint_destroy(struct sctp_endpoint *ep)
204{
205	struct sock *sk;
206
207	if (unlikely(!ep->base.dead)) {
208		WARN(1, "Attempt to destroy undead endpoint %p!\n", ep);
209		return;
210	}
211
212	/* SCTP-AUTH: Free up AUTH releated data such as shared keys
213	 * chunks and hmacs arrays that were allocated
214	 */
215	sctp_auth_destroy_keys(&ep->endpoint_shared_keys);
216	sctp_auth_free(ep);
217
218	/* Cleanup. */
219	sctp_inq_free(&ep->base.inqueue);
220	sctp_bind_addr_free(&ep->base.bind_addr);
221
222	memzero_explicit(&ep->cookie_auth_key, sizeof(ep->cookie_auth_key));
223
224	sk = ep->base.sk;
225	/* Remove and free the port */
226	if (sctp_sk(sk)->bind_hash)
227		sctp_put_port(sk);
228
229	call_rcu(&ep->rcu, sctp_endpoint_destroy_rcu);
230}
231
232/* Hold a reference to an endpoint. */
233int sctp_endpoint_hold(struct sctp_endpoint *ep)
234{
235	return refcount_inc_not_zero(&ep->base.refcnt);
236}
237
238/* Release a reference to an endpoint and clean up if there are
239 * no more references.
240 */
241void sctp_endpoint_put(struct sctp_endpoint *ep)
242{
243	if (refcount_dec_and_test(&ep->base.refcnt))
244		sctp_endpoint_destroy(ep);
245}
246
247/* Is this the endpoint we are looking for?  */
248struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep,
249					       struct net *net,
250					       const union sctp_addr *laddr,
251					       int dif, int sdif)
252{
253	int bound_dev_if = READ_ONCE(ep->base.sk->sk_bound_dev_if);
254	struct sctp_endpoint *retval = NULL;
255
256	if (net_eq(ep->base.net, net) &&
257	    sctp_sk_bound_dev_eq(net, bound_dev_if, dif, sdif) &&
258	    (htons(ep->base.bind_addr.port) == laddr->v4.sin_port)) {
259		if (sctp_bind_addr_match(&ep->base.bind_addr, laddr,
260					 sctp_sk(ep->base.sk)))
261			retval = ep;
262	}
263
264	return retval;
265}
266
267/* Find the association that goes with this chunk.
268 * We lookup the transport from hashtable at first, then get association
269 * through t->assoc.
270 */
271struct sctp_association *sctp_endpoint_lookup_assoc(
272	const struct sctp_endpoint *ep,
273	const union sctp_addr *paddr,
274	struct sctp_transport **transport)
275{
276	struct sctp_association *asoc = NULL;
277	struct sctp_transport *t;
278
279	*transport = NULL;
280
281	/* If the local port is not set, there can't be any associations
282	 * on this endpoint.
283	 */
284	if (!ep->base.bind_addr.port)
285		return NULL;
286
287	rcu_read_lock();
288	t = sctp_epaddr_lookup_transport(ep, paddr);
289	if (!t)
290		goto out;
291
292	*transport = t;
293	asoc = t->asoc;
294out:
295	rcu_read_unlock();
296	return asoc;
297}
298
299/* Look for any peeled off association from the endpoint that matches the
300 * given peer address.
301 */
302bool sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep,
303				 const union sctp_addr *paddr)
304{
305	int bound_dev_if = READ_ONCE(ep->base.sk->sk_bound_dev_if);
306	struct sctp_sockaddr_entry *addr;
307	struct net *net = ep->base.net;
308	struct sctp_bind_addr *bp;
309
310	bp = &ep->base.bind_addr;
311	/* This function is called with the socket lock held,
312	 * so the address_list can not change.
313	 */
314	list_for_each_entry(addr, &bp->address_list, list) {
315		if (sctp_has_association(net, &addr->a, paddr,
316					 bound_dev_if, bound_dev_if))
317			return true;
318	}
319
320	return false;
321}
322
323/* Do delayed input processing.  This is scheduled by sctp_rcv().
324 * This may be called on BH or task time.
325 */
326static void sctp_endpoint_bh_rcv(struct work_struct *work)
327{
328	struct sctp_endpoint *ep =
329		container_of(work, struct sctp_endpoint,
330			     base.inqueue.immediate);
331	struct sctp_association *asoc;
332	struct sock *sk;
333	struct net *net;
334	struct sctp_transport *transport;
335	struct sctp_chunk *chunk;
336	struct sctp_inq *inqueue;
337	union sctp_subtype subtype;
338	enum sctp_state state;
339	int error = 0;
340	int first_time = 1;	/* is this the first time through the loop */
341
342	if (ep->base.dead)
343		return;
344
345	asoc = NULL;
346	inqueue = &ep->base.inqueue;
347	sk = ep->base.sk;
348	net = sock_net(sk);
349
350	while (NULL != (chunk = sctp_inq_pop(inqueue))) {
351		subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type);
352
353		/* If the first chunk in the packet is AUTH, do special
354		 * processing specified in Section 6.3 of SCTP-AUTH spec
355		 */
356		if (first_time && (subtype.chunk == SCTP_CID_AUTH)) {
357			struct sctp_chunkhdr *next_hdr;
358
359			next_hdr = sctp_inq_peek(inqueue);
360			if (!next_hdr)
361				goto normal;
362
363			/* If the next chunk is COOKIE-ECHO, skip the AUTH
364			 * chunk while saving a pointer to it so we can do
365			 * Authentication later (during cookie-echo
366			 * processing).
367			 */
368			if (next_hdr->type == SCTP_CID_COOKIE_ECHO) {
369				chunk->auth_chunk = skb_clone(chunk->skb,
370								GFP_ATOMIC);
371				chunk->auth = 1;
372				continue;
373			}
374		}
375normal:
376		/* We might have grown an association since last we
377		 * looked, so try again.
378		 *
379		 * This happens when we've just processed our
380		 * COOKIE-ECHO chunk.
381		 */
382		if (NULL == chunk->asoc) {
383			asoc = sctp_endpoint_lookup_assoc(ep,
384							  sctp_source(chunk),
385							  &transport);
386			chunk->asoc = asoc;
387			chunk->transport = transport;
388		}
389
390		state = asoc ? asoc->state : SCTP_STATE_CLOSED;
391		if (sctp_auth_recv_cid(subtype.chunk, asoc) && !chunk->auth)
392			continue;
393
394		/* Remember where the last DATA chunk came from so we
395		 * know where to send the SACK.
396		 */
397		if (asoc && sctp_chunk_is_data(chunk))
398			asoc->peer.last_data_from = chunk->transport;
399		else {
400			SCTP_INC_STATS(ep->base.net, SCTP_MIB_INCTRLCHUNKS);
401			if (asoc)
402				asoc->stats.ictrlchunks++;
403		}
404
405		if (chunk->transport)
406			chunk->transport->last_time_heard = ktime_get();
407
408		error = sctp_do_sm(net, SCTP_EVENT_T_CHUNK, subtype, state,
409				   ep, asoc, chunk, GFP_ATOMIC);
410
411		if (error && chunk)
412			chunk->pdiscard = 1;
413
414		/* Check to see if the endpoint is freed in response to
415		 * the incoming chunk. If so, get out of the while loop.
416		 */
417		if (!sctp_sk(sk)->ep)
418			break;
419
420		if (first_time)
421			first_time = 0;
422	}
423}
~/ Read-only file preview.