⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ulpevent.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
/* SCTP kernel reference Implementation * (C) Copyright IBM Corp. 2001, 2004 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 La Monte H.P. Yarroll * * These functions manipulate an sctp event.   The struct ulpevent is used * to carry notifications and data to the ULP (sockets). * The SCTP reference implementation is free software; * you can redistribute it and/or modify it under the terms of * the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * The SCTP reference implementation is distributed in the hope that it * will be useful, but WITHOUT ANY WARRANTY; without even the implied *                 ************************ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU CC; see the file COPYING.  If not, write to * the Free Software Foundation, 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * Please send any bug reports or fixes you make to the * email address(es): *    lksctp developers <lksctp-developers@lists.sourceforge.net> * * Or submit a bug report through the following website: *    http://www.sf.net/projects/lksctp * * Written or modified by: *    Jon Grimm             <jgrimm@us.ibm.com> *    La Monte H.P. Yarroll <piggy@acm.org> *    Ardelle Fan	    <ardelle.fan@intel.com> *    Sridhar Samudrala     <sri@us.ibm.com> * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. */#include <linux/types.h>#include <linux/skbuff.h>#include <net/sctp/structs.h>#include <net/sctp/sctp.h>#include <net/sctp/sm.h>static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event,				       struct sctp_association *asoc);static void sctp_ulpevent_release_data(struct sctp_ulpevent *event);/* Stub skb destructor.  */static void sctp_stub_rfree(struct sk_buff *skb){/* WARNING:  This function is just a warning not to use the * skb destructor.  If the skb is shared, we may get the destructor * callback on some processor that does not own the sock_lock.  This * was occuring with PACKET socket applications that were monitoring * our skbs.   We can't take the sock_lock, because we can't risk * recursing if we do really own the sock lock.  Instead, do all * of our rwnd manipulation while we own the sock_lock outright. */}/* Create a new sctp_ulpevent.  */struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags, int gfp){	struct sctp_ulpevent *event;	struct sk_buff *skb;	skb = alloc_skb(size, gfp);	if (!skb)		goto fail;	event = sctp_skb2event(skb);	sctp_ulpevent_init(event, msg_flags);	return event;fail:	return NULL;}/* Initialize an ULP event from an given skb.  */void sctp_ulpevent_init(struct sctp_ulpevent *event, int msg_flags){	memset(event, 0, sizeof(struct sctp_ulpevent));	event->msg_flags = msg_flags;}/* Is this a MSG_NOTIFICATION?  */int sctp_ulpevent_is_notification(const struct sctp_ulpevent *event){	return MSG_NOTIFICATION == (event->msg_flags & MSG_NOTIFICATION);}/* Hold the association in case the msg_name needs read out of * the association. */static inline void sctp_ulpevent_set_owner(struct sctp_ulpevent *event,					   const struct sctp_association *asoc){	struct sk_buff *skb;	/* Cast away the const, as we are just wanting to	 * bump the reference count.	 */	sctp_association_hold((struct sctp_association *)asoc);	skb = sctp_event2skb(event);	skb->sk = asoc->base.sk;	event->asoc = (struct sctp_association *)asoc;	skb->destructor = sctp_stub_rfree;}/* A simple destructor to give up the reference to the association. */static inline void sctp_ulpevent_release_owner(struct sctp_ulpevent *event){	sctp_association_put(event->asoc);}/* Create and initialize an SCTP_ASSOC_CHANGE event. * * 5.3.1.1 SCTP_ASSOC_CHANGE * * Communication notifications inform the ULP that an SCTP association * has either begun or ended. The identifier for a new association is * provided by this notification. * * Note: There is no field checking here.  If a field is unused it will be * zero'd out. */struct sctp_ulpevent  *sctp_ulpevent_make_assoc_change(	const struct sctp_association *asoc,	__u16 flags, __u16 state, __u16 error, __u16 outbound,	__u16 inbound, int gfp){	struct sctp_ulpevent *event;	struct sctp_assoc_change *sac;	struct sk_buff *skb;	event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change),				  MSG_NOTIFICATION, gfp);	if (!event)		goto fail;	skb = sctp_event2skb(event);	sac = (struct sctp_assoc_change *)		skb_put(skb, sizeof(struct sctp_assoc_change));	/* Socket Extensions for SCTP	 * 5.3.1.1 SCTP_ASSOC_CHANGE	 *	 * sac_type:	 * It should be SCTP_ASSOC_CHANGE.	 */	sac->sac_type = SCTP_ASSOC_CHANGE;	/* Socket Extensions for SCTP	 * 5.3.1.1 SCTP_ASSOC_CHANGE	 *	 * sac_state: 32 bits (signed integer)	 * This field holds one of a number of values that communicate the	 * event that happened to the association.	 */	sac->sac_state = state;	/* Socket Extensions for SCTP	 * 5.3.1.1 SCTP_ASSOC_CHANGE	 *	 * sac_flags: 16 bits (unsigned integer)	 * Currently unused.	 */	sac->sac_flags = 0;	/* Socket Extensions for SCTP	 * 5.3.1.1 SCTP_ASSOC_CHANGE	 *	 * sac_length: sizeof (__u32)	 * This field is the total length of the notification data, including	 * the notification header.	 */	sac->sac_length = sizeof(struct sctp_assoc_change);	/* Socket Extensions for SCTP	 * 5.3.1.1 SCTP_ASSOC_CHANGE	 *	 * sac_error:  32 bits (signed integer)	 *	 * If the state was reached due to a error condition (e.g.	 * COMMUNICATION_LOST) any relevant error information is available in	 * this field. This corresponds to the protocol error codes defined in	 * [SCTP].	 */	sac->sac_error = error;	/* Socket Extensions for SCTP	 * 5.3.1.1 SCTP_ASSOC_CHANGE	 *	 * sac_outbound_streams:  16 bits (unsigned integer)	 * sac_inbound_streams:  16 bits (unsigned integer)	 *	 * The maximum number of streams allowed in each direction are	 * available in sac_outbound_streams and sac_inbound streams.	 */	sac->sac_outbound_streams = outbound;	sac->sac_inbound_streams = inbound;	/* Socket Extensions for SCTP	 * 5.3.1.1 SCTP_ASSOC_CHANGE	 *	 * sac_assoc_id: sizeof (sctp_assoc_t)	 *	 * The association id field, holds the identifier for the association.	 * All notifications for a given association have the same association	 * identifier.  For TCP style socket, this field is ignored.	 */	sctp_ulpevent_set_owner(event, asoc);	sac->sac_assoc_id = sctp_assoc2id(asoc);	return event;fail:	return NULL;}/* Create and initialize an SCTP_PEER_ADDR_CHANGE event. * * Socket Extensions for SCTP - draft-01 * 5.3.1.2 SCTP_PEER_ADDR_CHANGE * * When a destination address on a multi-homed peer encounters a change * an interface details event is sent. */struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change(	const struct sctp_association *asoc,	const struct sockaddr_storage *aaddr,	int flags, int state, int error, int gfp){	struct sctp_ulpevent *event;	struct sctp_paddr_change  *spc;	struct sk_buff *skb;	event = sctp_ulpevent_new(sizeof(struct sctp_paddr_change),				  MSG_NOTIFICATION, gfp);	if (!event)		goto fail;	skb = sctp_event2skb(event);	spc = (struct sctp_paddr_change *)		skb_put(skb, sizeof(struct sctp_paddr_change));	/* Sockets API Extensions for SCTP	 * Section 5.3.1.2 SCTP_PEER_ADDR_CHANGE	 *	 * spc_type:	 *	 *    It should be SCTP_PEER_ADDR_CHANGE.	 */	spc->spc_type = SCTP_PEER_ADDR_CHANGE;	/* Sockets API Extensions for SCTP	 * Section 5.3.1.2 SCTP_PEER_ADDR_CHANGE	 *	 * spc_length: sizeof (__u32)	 *	 * This field is the total length of the notification data, including	 * the notification header.	 */	spc->spc_length = sizeof(struct sctp_paddr_change);	/* Sockets API Extensions for SCTP	 * Section 5.3.1.2 SCTP_PEER_ADDR_CHANGE	 *	 * spc_flags: 16 bits (unsigned integer)	 * Currently unused.	 */	spc->spc_flags = 0;	/* Sockets API Extensions for SCTP	 * Section 5.3.1.2 SCTP_PEER_ADDR_CHANGE	 *	 * spc_state:  32 bits (signed integer)	 *	 * This field holds one of a number of values that communicate the	 * event that happened to the address.	 */	spc->spc_state = state;	/* Sockets API Extensions for SCTP	 * Section 5.3.1.2 SCTP_PEER_ADDR_CHANGE	 *	 * spc_error:  32 bits (signed integer)	 *	 * If the state was reached due to any error condition (e.g.	 * ADDRESS_UNREACHABLE) any relevant error information is available in	 * this field.	 */	spc->spc_error = error;	/* Socket Extensions for SCTP	 * 5.3.1.1 SCTP_ASSOC_CHANGE	 *	 * spc_assoc_id: sizeof (sctp_assoc_t)	 *	 * The association id field, holds the identifier for the association.	 * All notifications for a given association have the same association	 * identifier.  For TCP style socket, this field is ignored.	 */	sctp_ulpevent_set_owner(event, asoc);	spc->spc_assoc_id = sctp_assoc2id(asoc);	/* Sockets API Extensions for SCTP	 * Section 5.3.1.2 SCTP_PEER_ADDR_CHANGE	 *	 * spc_aaddr: sizeof (struct sockaddr_storage)	 *	 * The affected address field, holds the remote peer's address that is	 * encountering the change of state.	 */	memcpy(&spc->spc_aaddr, aaddr, sizeof(struct sockaddr_storage));	/* Map ipv4 address into v4-mapped-on-v6 address.  */	sctp_get_pf_specific(asoc->base.sk->sk_family)->addr_v4map(					sctp_sk(asoc->base.sk),					(union sctp_addr *)&spc->spc_aaddr);	return event;fail:	return NULL;}/* Create and initialize an SCTP_REMOTE_ERROR notification. * * Note: This assumes that the chunk->skb->data already points to the * operation error payload. * * Socket Extensions for SCTP - draft-01 * 5.3.1.3 SCTP_REMOTE_ERROR * * A remote peer may send an Operational Error message to its peer. * This message indicates a variety of error conditions on an * association. The entire error TLV as it appears on the wire is * included in a SCTP_REMOTE_ERROR event.  Please refer to the SCTP * specification [SCTP] and any extensions for a list of possible * error formats. */struct sctp_ulpevent *sctp_ulpevent_make_remote_error(	const struct sctp_association *asoc, struct sctp_chunk *chunk,	__u16 flags, int gfp){	struct sctp_ulpevent *event;	struct sctp_remote_error *sre;	struct sk_buff *skb;	sctp_errhdr_t *ch;	__u16 cause;	int elen;	ch = (sctp_errhdr_t *)(chunk->skb->data);	cause = ch->cause;	elen = WORD_ROUND(ntohs(ch->length)) - sizeof(sctp_errhdr_t);	/* Pull off the ERROR header.  */	skb_pull(chunk->skb, sizeof(sctp_errhdr_t));	/* Copy the skb to a new skb with room for us to prepend	 * notification with.	 */	skb = skb_copy_expand(chunk->skb, sizeof(struct sctp_remote_error),			      0, gfp);	/* Pull off the rest of the cause TLV from the chunk.  */	skb_pull(chunk->skb, elen);	if (!skb)		goto fail;	/* Embed the event fields inside the cloned skb.  */	event = sctp_skb2event(skb);	sctp_ulpevent_init(event, MSG_NOTIFICATION);	sre = (struct sctp_remote_error *)		skb_push(skb, sizeof(struct sctp_remote_error));	/* Trim the buffer to the right length.  */	skb_trim(skb, sizeof(struct sctp_remote_error) + elen);	/* Socket Extensions for SCTP	 * 5.3.1.3 SCTP_REMOTE_ERROR	 *	 * sre_type:	 *   It should be SCTP_REMOTE_ERROR.	 */	sre->sre_type = SCTP_REMOTE_ERROR;	/*	 * Socket Extensions for SCTP	 * 5.3.1.3 SCTP_REMOTE_ERROR	 *	 * sre_flags: 16 bits (unsigned integer)	 *   Currently unused.	 */	sre->sre_flags = 0;	/* Socket Extensions for SCTP	 * 5.3.1.3 SCTP_REMOTE_ERROR	 *	 * sre_length: sizeof (__u32)	 *	 * This field is the total length of the notification data,	 * including the notification header.	 */	sre->sre_length = skb->len;	/* Socket Extensions for SCTP	 * 5.3.1.3 SCTP_REMOTE_ERROR	 *	 * sre_error: 16 bits (unsigned integer)	 * This value represents one of the Operational Error causes defined in	 * the SCTP specification, in network byte order.	 */	sre->sre_error = cause;	/* Socket Extensions for SCTP	 * 5.3.1.3 SCTP_REMOTE_ERROR	 *	 * sre_assoc_id: sizeof (sctp_assoc_t)	 *	 * The association id field, holds the identifier for the association.	 * All notifications for a given association have the same association	 * identifier.  For TCP style socket, this field is ignored.	 */	sctp_ulpevent_set_owner(event, asoc);	sre->sre_assoc_id = sctp_assoc2id(asoc);	return event;fail:	return NULL;}/* Create and initialize a SCTP_SEND_FAILED notification. * * Socket Extensions for SCTP - draft-01 * 5.3.1.4 SCTP_SEND_FAILED */struct sctp_ulpevent *sctp_ulpevent_make_send_failed(	const struct sctp_association *asoc, struct sctp_chunk *chunk,	__u16 flags, __u32 error, int gfp){	struct sctp_ulpevent *event;	struct sctp_send_failed *ssf;	struct sk_buff *skb;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -