📄 socket.c
字号:
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 + -