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

📄 socket.c

📁 一种在UDP协议中实现了拥赛控制和重传机制的协议
💻 C
📖 第 1 页 / 共 5 页
字号:
			trans->hb_allowed = 0;	}	/* spp_pathmaxrxt contains the maximum number of retransmissions	 * before this address shall be considered unreachable.	 */	if (params.spp_pathmaxrxt)		trans->max_retrans = params.spp_pathmaxrxt;	return 0;}/* 7.1.3 Initialization Parameters (SCTP_INITMSG) * * Applications can specify protocol parameters for the default association * initialization.  The option name argument to setsockopt() and getsockopt() * is SCTP_INITMSG. * * Setting initialization parameters is effective only on an unconnected * socket (for UDP-style sockets only future associations are effected * by the change).  With TCP-style sockets, this option is inherited by * sockets derived from a listener socket. */static int sctp_setsockopt_initmsg(struct sock *sk, char __user *optval, int optlen){	struct sctp_initmsg sinit;	struct sctp_sock *sp = sctp_sk(sk);	if (optlen != sizeof(struct sctp_initmsg))		return -EINVAL;	if (copy_from_user(&sinit, optval, optlen))		return -EFAULT;	if (sinit.sinit_num_ostreams)		sp->initmsg.sinit_num_ostreams = sinit.sinit_num_ostreams;		if (sinit.sinit_max_instreams)		sp->initmsg.sinit_max_instreams = sinit.sinit_max_instreams;		if (sinit.sinit_max_attempts)		sp->initmsg.sinit_max_attempts = sinit.sinit_max_attempts;		if (sinit.sinit_max_init_timeo)		sp->initmsg.sinit_max_init_timeo = sinit.sinit_max_init_timeo;		return 0;}/* * 7.1.14 Set default send parameters (SCTP_DEFAULT_SEND_PARAM) * *   Applications that wish to use the sendto() system call may wish to *   specify a default set of parameters that would normally be supplied *   through the inclusion of ancillary data.  This socket option allows *   such an application to set the default sctp_sndrcvinfo structure. *   The application that wishes to use this socket option simply passes *   in to this call the sctp_sndrcvinfo structure defined in Section *   5.2.2) The input parameters accepted by this call include *   sinfo_stream, sinfo_flags, sinfo_ppid, sinfo_context, *   sinfo_timetolive.  The user must provide the sinfo_assoc_id field in *   to this call if the caller is using the UDP model. */static int sctp_setsockopt_default_send_param(struct sock *sk,						char __user *optval, int optlen){	struct sctp_sndrcvinfo info;	struct sctp_association *asoc;	struct sctp_sock *sp = sctp_sk(sk);	if (optlen != sizeof(struct sctp_sndrcvinfo))		return -EINVAL;	if (copy_from_user(&info, optval, optlen))		return -EFAULT;	asoc = sctp_id2assoc(sk, info.sinfo_assoc_id);	if (!asoc && info.sinfo_assoc_id && sctp_style(sk, UDP))		return -EINVAL;	if (asoc) {		asoc->default_stream = info.sinfo_stream;		asoc->default_flags = info.sinfo_flags;		asoc->default_ppid = info.sinfo_ppid;		asoc->default_context = info.sinfo_context;		asoc->default_timetolive = info.sinfo_timetolive;	} else {		sp->default_stream = info.sinfo_stream;		sp->default_flags = info.sinfo_flags;		sp->default_ppid = info.sinfo_ppid;		sp->default_context = info.sinfo_context;		sp->default_timetolive = info.sinfo_timetolive;	}	return 0;}/* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR) * * Requests that the local SCTP stack use the enclosed peer address as * the association primary.  The enclosed address must be one of the * association peer's addresses. */static int sctp_setsockopt_primary_addr(struct sock *sk, char __user *optval,					int optlen){	struct sctp_prim prim;	struct sctp_transport *trans;	if (optlen != sizeof(struct sctp_prim))		return -EINVAL;	if (copy_from_user(&prim, optval, sizeof(struct sctp_prim)))		return -EFAULT;	trans = sctp_addr_id2transport(sk, &prim.ssp_addr, prim.ssp_assoc_id);	if (!trans)		return -EINVAL;	sctp_assoc_set_primary(trans->asoc, trans);	return 0;}/* * 7.1.5 SCTP_NODELAY * * Turn on/off any Nagle-like algorithm.  This means that packets are * generally sent as soon as possible and no unnecessary delays are * introduced, at the cost of more packets in the network.  Expects an *  integer boolean flag. */static int sctp_setsockopt_nodelay(struct sock *sk, char __user *optval,					int optlen){	int val;	if (optlen < sizeof(int))		return -EINVAL;	if (get_user(val, (int __user *)optval))		return -EFAULT;	sctp_sk(sk)->nodelay = (val == 0) ? 0 : 1;	return 0;}/* * * 7.1.1 SCTP_RTOINFO * * The protocol parameters used to initialize and bound retransmission * timeout (RTO) are tunable. sctp_rtoinfo structure is used to access * and modify these parameters. * All parameters are time values, in milliseconds.  A value of 0, when * modifying the parameters, indicates that the current value should not * be changed. * */static int sctp_setsockopt_rtoinfo(struct sock *sk, char __user *optval, int optlen) {	struct sctp_rtoinfo rtoinfo;	struct sctp_association *asoc;	if (optlen != sizeof (struct sctp_rtoinfo))		return -EINVAL;	if (copy_from_user(&rtoinfo, optval, optlen))		return -EFAULT;	asoc = sctp_id2assoc(sk, rtoinfo.srto_assoc_id);	/* Set the values to the specific association */	if (!asoc && rtoinfo.srto_assoc_id && sctp_style(sk, UDP))		return -EINVAL;	if (asoc) {		if (rtoinfo.srto_initial != 0)			asoc->rto_initial = 				msecs_to_jiffies(rtoinfo.srto_initial);		if (rtoinfo.srto_max != 0)			asoc->rto_max = msecs_to_jiffies(rtoinfo.srto_max);		if (rtoinfo.srto_min != 0)			asoc->rto_min = msecs_to_jiffies(rtoinfo.srto_min);	} else {		/* If there is no association or the association-id = 0		 * set the values to the endpoint.		 */		struct sctp_sock *sp = sctp_sk(sk);		if (rtoinfo.srto_initial != 0)			sp->rtoinfo.srto_initial = rtoinfo.srto_initial;		if (rtoinfo.srto_max != 0)			sp->rtoinfo.srto_max = rtoinfo.srto_max;		if (rtoinfo.srto_min != 0)			sp->rtoinfo.srto_min = rtoinfo.srto_min;	}	return 0;}/* * * 7.1.2 SCTP_ASSOCINFO * * This option is used to tune the the maximum retransmission attempts * of the association. * Returns an error if the new association retransmission value is * greater than the sum of the retransmission value  of the peer. * See [SCTP] for more information. * */static int sctp_setsockopt_associnfo(struct sock *sk, char __user *optval, int optlen){	struct sctp_assocparams assocparams;	struct sctp_association *asoc;	if (optlen != sizeof(struct sctp_assocparams))		return -EINVAL;	if (copy_from_user(&assocparams, optval, optlen))		return -EFAULT;	asoc = sctp_id2assoc(sk, assocparams.sasoc_assoc_id);	if (!asoc && assocparams.sasoc_assoc_id && sctp_style(sk, UDP))		return -EINVAL;	/* Set the values to the specific association */	if (asoc) {		if (assocparams.sasoc_asocmaxrxt != 0)			asoc->max_retrans = assocparams.sasoc_asocmaxrxt;		if (assocparams.sasoc_cookie_life != 0) {			asoc->cookie_life.tv_sec =					assocparams.sasoc_cookie_life / 1000;			asoc->cookie_life.tv_usec =					(assocparams.sasoc_cookie_life % 1000)					* 1000;		}	} else {		/* Set the values to the endpoint */		struct sctp_sock *sp = sctp_sk(sk);		if (assocparams.sasoc_asocmaxrxt != 0)			sp->assocparams.sasoc_asocmaxrxt =						assocparams.sasoc_asocmaxrxt;		if (assocparams.sasoc_cookie_life != 0)			sp->assocparams.sasoc_cookie_life =						assocparams.sasoc_cookie_life;	}	return 0;}/* * 7.1.16 Set/clear IPv4 mapped addresses (SCTP_I_WANT_MAPPED_V4_ADDR) * * This socket option is a boolean flag which turns on or off mapped V4 * addresses.  If this option is turned on and the socket is type * PF_INET6, then IPv4 addresses will be mapped to V6 representation. * If this option is turned off, then no mapping will be done of V4 * addresses and a user will receive both PF_INET6 and PF_INET type * addresses on the socket. */static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, int optlen){	int val;	struct sctp_sock *sp = sctp_sk(sk);	if (optlen < sizeof(int))		return -EINVAL;	if (get_user(val, (int __user *)optval))		return -EFAULT;	if (val)		sp->v4mapped = 1;	else		sp->v4mapped = 0;	return 0;}/* * 7.1.17 Set the maximum fragrmentation size (SCTP_MAXSEG) * * This socket option specifies the maximum size to put in any outgoing * SCTP chunk.  If a message is larger than this size it will be * fragmented by SCTP into the specified size.  Note that the underlying * SCTP implementation may fragment into smaller sized chunks when the * PMTU of the underlying association is smaller than the value set by * the user. */static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optlen){	struct sctp_association *asoc;	struct list_head *pos;	struct sctp_sock *sp = sctp_sk(sk);	int val;	if (optlen < sizeof(int))		return -EINVAL;	if (get_user(val, (int __user *)optval))		return -EFAULT;	if ((val < 8) || (val > SCTP_MAX_CHUNK_LEN))		return -EINVAL;	sp->user_frag = val;	if (val) {		/* Update the frag_point of the existing associations. */		list_for_each(pos, &(sp->ep->asocs)) {			asoc = list_entry(pos, struct sctp_association, asocs);			asoc->frag_point = sctp_frag_point(sp, asoc->pmtu); 		}	}	return 0;}/* *  7.1.9 Set Peer Primary Address (SCTP_SET_PEER_PRIMARY_ADDR) * *   Requests that the peer mark the enclosed address as the association *   primary. The enclosed address must be one of the association's *   locally bound addresses. The following structure is used to make a *   set primary request: */static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optval,					     int optlen){	struct sctp_sock	*sp;	struct sctp_endpoint	*ep;	struct sctp_association	*asoc = NULL;	struct sctp_setpeerprim	prim;	struct sctp_chunk	*chunk;	int 			err;	sp = sctp_sk(sk);	ep = sp->ep;	if (!sctp_addip_enable)		return -EPERM;	if (optlen != sizeof(struct sctp_setpeerprim))		return -EINVAL;	if (copy_from_user(&prim, optval, optlen))		return -EFAULT;	asoc = sctp_id2assoc(sk, prim.sspp_assoc_id);	if (!asoc) 		return -EINVAL;	if (!asoc->peer.asconf_capable)		return -EPERM;	if (asoc->peer.addip_disabled_mask & SCTP_PARAM_SET_PRIMARY)		return -EPERM;	if (!sctp_state(asoc, ESTABLISHED))		return -ENOTCONN;	if (!sctp_assoc_lookup_laddr(asoc, (union sctp_addr *)&prim.sspp_addr))		return -EADDRNOTAVAIL;	/* Create an ASCONF chunk with SET_PRIMARY parameter	*/	chunk = sctp_make_asconf_set_prim(asoc,					  (union sctp_addr *)&prim.sspp_addr);	if (!chunk)		return -ENOMEM;	err = sctp_send_asconf(asoc, chunk);	SCTP_DEBUG_PRINTK("We set peer primary addr primitively.\n");	return err;}static int sctp_setsockopt_adaption_layer(struct sock *sk, char __user *optval,					  int optlen){	__u32 val;	if (optlen < sizeof(__u32))		return -EINVAL;	if (copy_from_user(&val, optval, sizeof(__u32)))		return -EFAULT;	sctp_sk(sk)->adaption_ind = val;	return 0;}/* API 6.2 setsockopt(), getsockopt() * * Applications use setsockopt() and getsockopt() to set or retrieve * socket options.  Socket options are used to change the default * behavior of sockets calls.  They are described in Section 7. * * The syntax is: * *   ret = getsockopt(int sd, int level, int optname, void __user *optval, *                    int __user *optlen); *   ret = setsockopt(int sd, int level, int optname, const void __user *optval, *                    int optlen); * *   sd      - the socket descript. *   level   - set to IPPROTO_SCTP for all SCTP options. *   optname - the option name. *   optval  - the buffer to store the value of the option. *   optlen  - the size of the buffer. */SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,				char __user *optval, int optlen){	int retval = 0;	SCTP_DEBUG_PRINTK("sctp_setsockopt(sk: %p... optname: %d)\n",			  sk, optname);	/* I can hardly begin to describe how wrong this is.  This is	 * so broken as to be worse than useless.  The API draft	 * REALLY is NOT helpful here...  I am not convinced that the	 * semantics of setsockopt() with a level OTHER THAN SOL_SCTP	 * are at all well-founded.	 */	if (level != SOL_SCTP) {		struct sctp_af *af = sctp_sk(sk)->pf->af;		retval = af->setsockopt(sk, level, optname, optval, optlen);		goto out_nounlock;	}	sctp_lock_sock(sk);	switch (optname) {	case SCTP_SOCKOPT_BINDX_ADD:		/* 'optlen' is the size of the addresses buffer. */		retval = sctp_setsockopt_bindx(sk, (struct sockaddr __user *)optval,					       optlen, SCTP_BINDX_ADD_ADDR);		break;	case SCTP_SOCKOPT_BINDX_REM:		/* 'optlen' is the size of the addresses buffer. */		retval = sctp_setsockopt_bindx(sk, (struct sockaddr __user *)optval,					       optlen, SCTP_BINDX_REM_ADDR);		break;	case SCTP_DISABLE_FRAGMENTS:		retval = sctp_setsockopt_disable_fragments(sk, optval, optlen);		br

⌨️ 快捷键说明

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