net/sctp/bind_addr.c

Source file repositories/reference/linux-study-clean/net/sctp/bind_addr.c

File Facts

System
Linux kernel
Corpus path
net/sctp/bind_addr.c
Extension
.c
Size
14522 bytes
Lines
585
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

list_for_each_entry(addr, &src->address_list, list) {
			error = sctp_copy_one_addr(net, dest, &addr->a,
						   SCTP_SCOPE_LINK, gfp,
						   flags);
			if (error < 0)
				goto out;
		}
	}

	/* If somehow no addresses were found that can be used with this
	 * scope, it's an error.
	 */
	if (list_empty(&dest->address_list))
		error = -ENETUNREACH;

out:
	if (error)
		sctp_bind_addr_clean(dest);

	return error;
}

/* Exactly duplicate the address lists.  This is necessary when doing
 * peer-offs and accepts.  We don't want to put all the current system
 * addresses into the endpoint.  That's useless.  But we do want duplicat
 * the list of bound addresses that the older endpoint used.
 */
int sctp_bind_addr_dup(struct sctp_bind_addr *dest,
			const struct sctp_bind_addr *src,
			gfp_t gfp)
{
	struct sctp_sockaddr_entry *addr;
	int error = 0;

	/* All addresses share the same port.  */
	dest->port = src->port;

	list_for_each_entry(addr, &src->address_list, list) {
		error = sctp_add_bind_addr(dest, &addr->a, sizeof(addr->a),
					   1, gfp);
		if (error < 0)
			break;
	}

	return error;
}

/* Initialize the SCTP_bind_addr structure for either an endpoint or
 * an association.
 */
void sctp_bind_addr_init(struct sctp_bind_addr *bp, __u16 port)
{
	INIT_LIST_HEAD(&bp->address_list);
	bp->port = port;
}

/* Dispose of the address list. */
static void sctp_bind_addr_clean(struct sctp_bind_addr *bp)
{
	struct sctp_sockaddr_entry *addr, *temp;

	/* Empty the bind address list. */
	list_for_each_entry_safe(addr, temp, &bp->address_list, list) {
		list_del_rcu(&addr->list);
		kfree_rcu(addr, rcu);
		SCTP_DBG_OBJCNT_DEC(addr);
	}
}

/* Dispose of an SCTP_bind_addr structure  */
void sctp_bind_addr_free(struct sctp_bind_addr *bp)
{
	/* Empty the bind address list. */
	sctp_bind_addr_clean(bp);
}

/* Add an address to the bind address list in the SCTP_bind_addr structure. */
int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
		       int new_size, __u8 addr_state, gfp_t gfp)
{
	struct sctp_sockaddr_entry *addr;

	/* Add the address to the bind address list.  */
	addr = kzalloc_obj(*addr, gfp);
	if (!addr)
		return -ENOMEM;

	memcpy(&addr->a, new, min_t(size_t, sizeof(*new), new_size));

	/* Fix up the port if it has not yet been set.

Annotation

Implementation Notes