| OpenSS7 SS7 for the Common Man | © Copyright 1997-2007 OpenSS7 Corporation All Rights Reserved. Last modified: Sat, 16 Aug 2008 00:06:24 GMT | ||||||||||||||||
| |||||||||||||||||
| Description: CodeFile /code/strinet/src/drivers/inet.c
#ident "@(#) inet.c,v openss7-0_9_2_F(0.9.2.85) 2007/05/17 22:33:00"
static char const ident[] =
"inet.c,v openss7-0_9_2_F(0.9.2.85) 2007/05/17 22:33:00";
#include <sys/os7/compat.h>
#if defined HAVE_OPENSS7_SCTP
#if !defined CONFIG_SCTP && !defined CONFIG_SCTP_MODULE
#undef HAVE_OPENSS7_SCTP
#endif
#endif
#if !defined HAVE_OPENSS7_SCTP
#undef sctp_addr
#define sctp_addr stupid_sctp_addr_in_the_wrong_place
#endif
#include <linux/bitops.h>
#define t_tst_bit(nr,addr) test_bit(nr,addr)
#define t_set_bit(nr,addr) __set_bit(nr,addr)
#define t_clr_bit(nr,addr) __clear_bit(nr,addr)
#include <linux/net.h>
#include <linux/in.h>
#include <linux/un.h>
#include <linux/ip.h>
#undef ASSERT
#include <net/sock.h>
#include <net/udp.h>
#include <net/tcp.h>
#if defined HAVE_OPENSS7_SCTP
#undef STATIC
#undef INLINE
#include <net/sctp.h>
#endif
#if 0
#undef ensure
#undef assure
#undef assert
#undef printd
#undef swerr
#undef rare
#undef seldom
#undef likely
#define ensure __ensure
#define assure __assure
#define assert __assert
#define printd __printd
#define swerr __swerr
#define rare __rare
#define seldom __seldom
#define _DEBUG
#endif
#ifdef HAVE_OLD_SOCK_STRUCTURE
#define sk_callback_lock callback_lock
#define sk_user_data user_data
#define sk_state_change state_change
#define sk_data_ready data_ready
#define sk_write_space write_space
#define sk_error_report error_report
#define sk_lingertime lingertime
#define sk_state state
#define sk_rcvbuf rcvbuf
#define sk_rcvlowat rcvlowat
#define sk_sndbuf sndbuf
#define sk_reuse reuse
#define sk_localroute localroute
#define sk_no_check no_check
#define sk_debug debug
#define sk_allocation allocation
#define sk_priority priority
#define sk_ack_backlog ack_backlog
#define sk_prot prot
#define sk_receive_queue receive_queue
#define sk_rmem_alloc rmem_alloc
#define sock_tst_dead(_sk) (((struct sock *)_sk)->dead ? 1 : 0)
#define sock_tst_done(_sk) (((struct sock *)_sk)->done ? 1 : 0)
#define sock_tst_urginline(_sk) (((struct sock *)_sk)->urginline ? 1 : 0)
#define sock_tst_keepopen(_sk) (((struct sock *)_sk)->keepopen ? 1 : 0)
#define sock_tst_linger(_sk) (((struct sock *)_sk)->linger ? 1 : 0)
#define sock_tst_destroy(_sk) (((struct sock *)_sk)->destroy ? 1 : 0)
#define sock_tst_broadcast(_sk) (((struct sock *)_sk)->broadcast ? 1 : 0)
#define sock_tst_localroute(_sk) (((struct sock *)_sk)->localroute ? 1 : 0)
#define sock_tst_debug(_sk) (((struct sock *)_sk)->debug ? 1 : 0)
#define sock_set_dead(_sk) (((struct sock *)_sk)->dead = 1)
#define sock_set_done(_sk) (((struct sock *)_sk)->done = 1)
#define sock_set_urginline(_sk) (((struct sock *)_sk)->urginline = 1)
#define sock_set_keepopen(_sk) (((struct sock *)_sk)->keepopen = 1)
#define sock_set_linger(_sk) (((struct sock *)_sk)->linger = 1)
#define sock_set_destroy(_sk) (((struct sock *)_sk)->destroy = 1)
#define sock_set_broadcast(_sk) (((struct sock *)_sk)->broadcast = 1)
#define sock_set_localroute(_sk) (((struct sock *)_sk)->localroute = 1)
#define sock_set_debug(_sk) (((struct sock *)_sk)->debug = 1)
#define sock_clr_dead(_sk) (((struct sock *)_sk)->dead = 0)
#define sock_clr_done(_sk) (((struct sock *)_sk)->done = 0)
#define sock_clr_urginline(_sk) (((struct sock *)_sk)->urginline = 0)
#define sock_clr_keepopen(_sk) (((struct sock *)_sk)->keepopen = 0)
#define sock_clr_linger(_sk) (((struct sock *)_sk)->linger = 0)
#define sock_clr_destroy(_sk) (((struct sock *)_sk)->destroy = 0)
#define sock_clr_broadcast(_sk) (((struct sock *)_sk)->broadcast = 0)
#define sock_clr_localroute(_sk) (((struct sock *)_sk)->localroute = 0)
#define sock_clr_debug(_sk) (((struct sock *)_sk)->debug = 0)
#undef inet_sk
#define inet_sk(_sk) (&(((struct sock *)_sk)->protinfo.af_inet))
#undef inet_csk
#define inet_csk(_sk) (&(((struct sock *)_sk)->protinfo.af_inet))
#undef tcp_sk
#define tcp_sk(_sk) (&(((struct sock *)_sk)->tp_pinfo.af_tcp))
#undef sctp_sk
#define sctp_sk(_sk) (&(((struct sock *)_sk)->tp_pinfo.af_sctp))
#define sock_saddr(_sk) (((struct sock *)_sk)->saddr)
#define sock_sport(_sk) (((struct sock *)_sk)->sport)
#define sock_daddr(_sk) (((struct sock *)_sk)->daddr)
#define sock_dport(_sk) (((struct sock *)_sk)->dport)
#define tcp_user_mss(_tp) ((_tp)->user_mss)
#define sock_syn_retries(_sk) (tcp_sk(_sk)->syn_retries)
#define sock_defer_accept(_sk) (tcp_sk(_sk)->defer_accept)
#define sock_accept_queue_head(_sk) (tcp_sk(_sk)->accept_queue)
#define sock_accept_queue_tail(_sk) (tcp_sk(_sk)->accept_queue_tail)
#define sock_accept_queue_lock(_sk)
#define sock_accept_queue_unlock(_sk)
#else
#ifdef HAVE_TRN_SOCK_STRUCTURE
#define sock_tst_dead(_sk) (sock_flag(_sk, SOCK_DEAD) ? 1 : 0)
#define sock_tst_done(_sk) (sock_flag(_sk, SOCK_DONE) ? 1 : 0)
#define sock_tst_urginline(_sk) (sock_flag(_sk, SOCK_URGINLINE) ? 1 : 0)
#define sock_tst_keepopen(_sk) (sock_flag(_sk, SOCK_KEEPOPEN) ? 1 : 0)
#define sock_tst_linger(_sk) (sock_flag(_sk, SOCK_LINGER) ? 1 : 0)
#define sock_tst_destroy(_sk) (sock_flag(_sk, SOCK_DESTROY) ? 1 : 0)
#define sock_tst_broadcast(_sk) (sock_flag(_sk, SOCK_BROADCAST) ? 1 : 0)
#define sock_tst_localroute(_sk) (((struct sock *)_sk)->sk_localroute ? 1 : 0)
#define sock_tst_debug(_sk) (((struct sock *)_sk)->sk_debug ? 1 : 0)
#define sock_set_dead(_sk) (sock_set_flag(_sk, SOCK_DEAD))
#define sock_set_done(_sk) (sock_set_flag(_sk, SOCK_DONE))
#define sock_set_urginline(_sk) (sock_set_flag(_sk, SOCK_URGINLINE))
#define sock_set_keepopen(_sk) (sock_set_flag(_sk, SOCK_KEEPOPEN))
#define sock_set_linger(_sk) (sock_set_flag(_sk, SOCK_LINGER))
#define sock_set_destroy(_sk) (sock_set_flag(_sk, SOCK_DESTROY))
#define sock_set_broadcast(_sk) (sock_set_flag(_sk, SOCK_BROADCAST))
#define sock_set_localroute(_sk) (((struct sock *)_sk)->sk_localroute = 1)
#define sock_set_debug(_sk) (((struct sock *)_sk)->sk_debug = 1)
#define sock_clr_dead(_sk) (sock_reset_flag(_sk, SOCK_DEAD))
#define sock_clr_done(_sk) (sock_reset_flag(_sk, SOCK_DONE))
#define sock_clr_urginline(_sk) (sock_reset_flag(_sk, SOCK_URGINLINE))
#define sock_clr_keepopen(_sk) (sock_reset_flag(_sk, SOCK_KEEPOPEN))
#define sock_clr_linger(_sk) (sock_reset_flag(_sk, SOCK_LINGER))
#define sock_clr_destroy(_sk) (sock_reset_flag(_sk, SOCK_DESTROY))
#define sock_clr_broadcast(_sk) (sock_reset_flag(_sk, SOCK_BROADCAST))
#define sock_clr_localroute(_sk) (((struct sock *)_sk)->sk_localroute = 0)
#define sock_clr_debug(_sk) (((struct sock *)_sk)->sk_debug = 0)
#define sock_saddr(_sk) (inet_sk(_sk)->saddr)
#define sock_sport(_sk) (inet_sk(_sk)->sport)
#define sock_daddr(_sk) (inet_sk(_sk)->daddr)
#define sock_dport(_sk) (inet_sk(_sk)->dport)
#define tcp_user_mss(_tp) ((_tp)->user_mss)
#define sock_syn_retries(_sk) (tcp_sk(_sk)->syn_retries)
#define sock_defer_accept(_sk) (tcp_sk(_sk)->defer_accept)
#define sock_accept_queue_head(_sk) (tcp_sk(_sk)->accept_queue)
#define sock_accept_queue_tail(_sk) (tcp_sk(_sk)->accept_queue_tail)
#define sock_accept_queue_lock(_sk)
#define sock_accept_queue_unlock(_sk)
#else
#ifdef HAVE_NEW_SOCK_STRUCTURE
#define sock_tst_dead(_sk) (sock_flag(_sk, SOCK_DEAD) ? 1 : 0)
#define sock_tst_done(_sk) (sock_flag(_sk, SOCK_DONE) ? 1 : 0)
#define sock_tst_urginline(_sk) (sock_flag(_sk, SOCK_URGINLINE) ? 1 : 0)
#define sock_tst_keepopen(_sk) (sock_flag(_sk, SOCK_KEEPOPEN) ? 1 : 0)
#define sock_tst_linger(_sk) (sock_flag(_sk, SOCK_LINGER) ? 1 : 0)
#define sock_tst_destroy(_sk) (sock_flag(_sk, SOCK_DESTROY) ? 1 : 0)
#define sock_tst_broadcast(_sk) (sock_flag(_sk, SOCK_BROADCAST) ? 1 : 0)
#ifdef HAVE_KMEMB_STRUCT_SOCK_SK_LOCALROUTE
#define sock_tst_localroute(_sk) (((struct sock *)_sk)->sk_localroute ? 1 : 0)
#else
#define sock_tst_localroute(_sk) (sock_flag(_sk, SOCK_LOCALROUTE) ? 1 : 0)
#endif
#ifdef HAVE_KMEMB_STRUCT_SOCK_SK_DEBUG
#define sock_tst_debug(_sk) (((struct sock *)_sk)->sk_debug ? 1 : 0)
#else
#define sock_tst_debug(_sk) (sock_flag(_sk, SOCK_DBG) ? 1 : 0)
#endif
#define sock_set_dead(_sk) (sock_set_flag(_sk, SOCK_DEAD))
#define sock_set_done(_sk) (sock_set_flag(_sk, SOCK_DONE))
#define sock_set_urginline(_sk) (sock_set_flag(_sk, SOCK_URGINLINE))
#define sock_set_keepopen(_sk) (sock_set_flag(_sk, SOCK_KEEPOPEN))
#define sock_set_linger(_sk) (sock_set_flag(_sk, SOCK_LINGER))
#define sock_set_destroy(_sk) (sock_set_flag(_sk, SOCK_DESTROY))
#define sock_set_broadcast(_sk) (sock_set_flag(_sk, SOCK_BROADCAST))
#ifdef HAVE_KMEMB_STRUCT_SOCK_SK_LOCALROUTE
#define sock_set_localroute(_sk) (((struct sock *)_sk)->sk_localroute = 1)
#else
#define sock_set_localroute(_sk) (sock_set_flag(_sk, SOCK_LOCALROUTE))
#endif
#ifdef HAVE_KMEMB_STRUCT_SOCK_SK_DEBUG
#define sock_set_debug(_sk) (((struct sock *)_sk)->sk_debug = 1)
#else
#define sock_set_debug(_sk) (sock_set_flag(_sk, SOCK_DBG))
#endif
#define sock_clr_dead(_sk) (sock_reset_flag(_sk, SOCK_DEAD))
#define sock_clr_done(_sk) (sock_reset_flag(_sk, SOCK_DONE))
#define sock_clr_urginline(_sk) (sock_reset_flag(_sk, SOCK_URGINLINE))
#define sock_clr_keepopen(_sk) (sock_reset_flag(_sk, SOCK_KEEPOPEN))
#define sock_clr_linger(_sk) (sock_reset_flag(_sk, SOCK_LINGER))
#define sock_clr_destroy(_sk) (sock_reset_flag(_sk, SOCK_DESTROY))
#define sock_clr_broadcast(_sk) (sock_reset_flag(_sk, SOCK_BROADCAST))
#ifdef HAVE_KMEMB_STRUCT_SOCK_SK_LOCALROUTE
#define sock_clr_localroute(_sk) (((struct sock *)_sk)->sk_localroute = 0)
#else
#define sock_clr_localroute(_sk) (sock_reset_flag(_sk, SOCK_LOCALROUTE))
#endif
#ifdef HAVE_KMEMB_STRUCT_SOCK_SK_DEBUG
#define sock_clr_debug(_sk) (((struct sock *)_sk)->sk_debug = 0)
#else
#define sock_clr_debug(_sk) (sock_reset_flag(_sk, SOCK_DBG))
#endif
#define sock_saddr(_sk) (inet_sk(_sk)->saddr)
#define sock_sport(_sk) (inet_sk(_sk)->sport)
#define sock_daddr(_sk) (inet_sk(_sk)->daddr)
#define sock_dport(_sk) (inet_sk(_sk)->dport)
#define inet_opt inet_sock
#define tcp_opt tcp_sock
#define tcp_user_mss(_tp) ((_tp)->rx_opt.user_mss)
#ifndef HAVE_KFUNC_INET_CSK
#define sock_syn_retries(_sk) (tcp_sk(_sk)->syn_retries)
#ifndef HAVE_KINC_NET_REQUEST_SOCK_H
#define sock_defer_accept(_sk) (tcp_sk(_sk)->defer_accept)
#define sock_accept_queue_head(_sk) (tcp_sk(_sk)->accept_queue)
#define sock_accept_queue_tail(_sk) (tcp_sk(_sk)->accept_queue_tail)
#define sock_accept_queue_lock(_sk)
#define sock_accept_queue_unlock(_sk)
#else
#define sock_defer_accept(_sk) (tcp_sk(_sk)->defer_accept)
#define sock_accept_queue_head(_sk) (tcp_sk(_sk)->accept_queue.rskq_accept_head)
#define sock_accept_queue_tail(_sk) (tcp_sk(_sk)->accept_queue.rskq_accept_tail)
#define sock_accept_queue_lock(_sk) write_lock_bh(&tcp_sk(_sk)->accept_queue.syn_wait_lock)
#define sock_accept_queue_unlock(_sk) write_unlock_bh(&tcp_sk(_sk)->accept_queue.syn_wait_lock)
#define open_request request_sock
#define tcp_openreq_fastfree(__req) __reqsk_free(__req)
#endif
#else
#define sock_syn_retries(_sk) (inet_csk(_sk)->icsk_syn_retries)
#define sock_defer_accept(_sk) (inet_csk(_sk)->icsk_accept_queue.rskq_defer_accept)
#define sock_accept_queue_head(_sk) (inet_csk(_sk)->icsk_accept_queue.rskq_accept_head)
#define sock_accept_queue_tail(_sk) (inet_csk(_sk)->icsk_accept_queue.rskq_accept_tail)
#define sock_accept_queue_lock(_sk) write_lock_bh(&inet_csk(_sk)->icsk_accept_queue.syn_wait_lock)
#define sock_accept_queue_unlock(_sk) write_unlock_bh(&inet_csk(_sk)->icsk_accept_queue.syn_wait_lock)
#define open_request request_sock
#define tcp_openreq_fastfree(__req) __reqsk_free(__req)
#endif
#else
#error One of HAVE_OLD_SOCK_STRUCTURE, HAVE_TRN_SOCK_STRUCTURE or HAVE_NEW_SOCK_STRUCTURE must be defined.
#endif
#endif
#endif
#ifndef SK_WMEM_MAX
#define SK_WMEM_MAX 65535
#endif
#ifndef SK_RMEM_MAX
#define SK_RMEM_MAX 65535
#endif
#if !defined HAVE_OPENSS7_SCTP
#undef sctp_addr
#endif
#ifndef tcp_openreq_cachep
#ifdef HAVE_TCP_OPENREQ_CACHEP_ADDR
#include <linux/slab.h>
static kmem_cachep_t *const _tcp_openreq_cachep_location =
(typeof(_tcp_openreq_cachep_location)) (HAVE_TCP_OPENREQ_CACHEP_ADDR);
#define tcp_openreq_cachep (*_tcp_openreq_cachep_location)
#endif
#endif
#ifndef tcp_set_keepalive
#ifdef HAVE_TCP_SET_KEEPALIVE_ADDR
void
tcp_set_keepalive(struct sock *sk, int val)
{
static void (*func) (struct sock *, int) = (typeof(func)) HAVE_TCP_SET_KEEPALIVE_ADDR;
return func(sk, val);
}
#endif
#endif
#ifndef tcp_sync_mss
#ifdef HAVE_TCP_SYNC_MSS_ADDR
int
tcp_sync_mss(struct sock *sk, u32 pmtu)
{
static int (*func) (struct sock *, u32) = (typeof(func)) HAVE_TCP_SYNC_MSS_ADDR;
return func(sk, pmtu);
}
#endif
#endif
#ifndef tcp_write_xmit
#ifdef HAVE_TCP_WRITE_XMIT_ADDR
int
tcp_write_xmit(struct sock *sk, int nonagle)
{
static int (*func) (struct sock *, int) = (typeof(func)) HAVE_TCP_WRITE_XMIT_ADDR;
return func(sk, nonagle);
}
#endif
#endif
#ifndef tcp_cwnd_application_limited
#ifdef HAVE_TCP_CWND_APPLICATION_LIMITED_ADDR
void
tcp_cwnd_application_limited(struct sock *sk)
{
static void (*func) (struct sock *) = (typeof(func)) HAVE_TCP_CWND_APPLICATION_LIMITED_ADDR;
return func(sk);
}
#endif
#endif
__u8 ip_tos2prio[16] = { 0, 1, 0, 0, 2, 2, 2, 2, 6, 6, 6, 6, 4, 4, 4, 4 };
#ifndef sysctl_rmem_default
#ifdef HAVE_SYSCTL_RMEM_DEFAULT_ADDR
static __u32 *const _sysctl_rmem_default_location =
(typeof(_sysctl_rmem_default_location)) (HAVE_SYSCTL_RMEM_DEFAULT_ADDR);
#define sysctl_rmem_default (*_sysctl_rmem_default_location)
#else
#define sysctl_rmem_default SK_RMEM_MAX
#endif
#endif
#ifndef sysctl_wmem_default
#ifdef HAVE_SYSCTL_WMEM_DEFAULT_ADDR
static __u32 *const _sysctl_wmem_default_location =
(typeof(_sysctl_wmem_default_location)) (HAVE_SYSCTL_WMEM_DEFAULT_ADDR);
#define sysctl_wmem_default (*_sysctl_wmem_default_location)
#else
#define sysctl_wmem_default SK_WMEM_MAX
#endif
#endif
#ifndef sysctl_tcp_fin_timeout
#ifdef HAVE_SYSCTL_TCP_FIN_TIMEOUT_ADDR
static __u32 *const _sysctl_tcp_fin_timeout_location =
(typeof(_sysctl_tcp_fin_timeout_location)) (HAVE_SYSCTL_TCP_FIN_TIMEOUT_ADDR);
#define sysctl_tcp_fin_timeout (*_sysctl_tcp_fin_timeout_location)
#else
#define sysctl_tcp_fin_timeout TCP_FIN_TIMEOUT
#endif
#endif
#ifndef tcp_current_mss
#ifdef HAVE_TCP_CURRENT_MSS_ADDR
unsigned int
tcp_current_mss(struct sock *sk, int large)
{
static unsigned int (*func) (struct sock *, int) = (typeof(func)) HAVE_TCP_CURRENT_MSS_ADDR;
return func(sk, large);
}
#endif
#endif
#ifndef sysctl_ip_dynaddr
#ifdef HAVE_SYSCTL_IP_DYNADDR_ADDR
extern int sysctl_ip_dynaddr;
#define sysctl_ip_dynaddr (*((typeof(sysctl_ip_dynaddr) *)HAVE_SYSCTL_IP_DYNADDR_ADDR))
#endif
#endif
#ifndef sysctl_ip_nonlocal_bind
#ifdef HAVE_SYSCTL_IP_NONLOCAL_BIND_ADDR
extern int sysctl_ip_nonlocal_bind;
#define sysctl_ip_nonlocal_bind (*((typeof(sysctl_ip_nonlocal_bind) *)HAVE_SYSCTL_IP_NONLOCAL_BIND_ADDR))
#endif
#endif
#ifndef sysctl_ip_default_ttl
#ifdef HAVE_SYSCTL_IP_DEFAULT_TTL_ADDR
extern int sysctl_ip_default_ttl;
#define sysctl_ip_default_ttl (*((typeof(sysctl_ip_default_ttl) *)HAVE_SYSCTL_IP_DEFAULT_TTL_ADDR))
#endif
#endif
#ifndef tcp_set_skb_tso_segs
#ifdef HAVE_TCP_SET_SKB_TSO_SEGS_ADDR
#ifdef HAVE_KFUNC_TCP_SET_SKB_TSO_SEGS_SOCK
void
tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb)
{
static void (*func) (struct sock *, struct sk_buff *) =
(typeof(func)) HAVE_TCP_SET_SKB_TSO_SEGS_ADDR;
return func(sk, skb);
}
#else
void
tcp_set_skb_tso_segs(struct sk_buff *skb, unsigned int mss_std)
{
static void (*func) (struct sk_buff *, unsigned int) =
(typeof(func)) HAVE_TCP_SET_SKB_TSO_SEGS_ADDR;
return func(skb, mss_std);
}
#endif
#endif
#endif
#ifndef tcp_set_skb_tso_factor
#ifdef HAVE_TCP_SET_SKB_TSO_FACTOR_ADDR
void
tcp_set_skb_tso_factor(struct sk_buff *skb, unsigned int mss_std)
{
static void (*func) (struct sk_buff *, unsigned int) =
(typeof(func)) HAVE_TCP_SET_SKB_TSO_FACTOR_ADDR;
return func(skb, mss_std);
}
#endif
#endif
#if defined HAVE_TIHDR_H
# include <tihdr.h>
#else
# include <sys/tihdr.h>
#endif
#include <sys/xti.h>
#include <sys/xti_inet.h>
#include <sys/xti_sctp.h>
#define T_ALLLEVELS -1
#define LINUX_2_4 1
#define SS__DESCRIP "UNIX SYSTEM V RELEASE 4.2 FAST STREAMS FOR LINUX"
#define SS__EXTRA "Part of the OpenSS7 Stack for Linux Fast-STREAMS."
#define SS__COPYRIGHT "Copyright (c) 1997-2006 OpenSS7 Corporation. All Rights Reserved."
#define SS__REVISION "OpenSS7 inet.c,v openss7-0_9_2_F(0.9.2.85) 2007/05/17 22:33:00"
#define SS__DEVICE "SVR 4.2 STREAMS INET Drivers (NET4)"
#define SS__CONTACT "Brian Bidulock <bidulock@openss7.org>"
#define SS__LICENSE "GPL"
#define SS__BANNER SS__DESCRIP "\n" \
SS__EXTRA "\n" \
SS__REVISION "\n" \
SS__COPYRIGHT "\n" \
SS__DEVICE "\n" \
SS__CONTACT
#define SS__SPLASH SS__DESCRIP "\n" \
SS__REVISION
#ifdef LINUX
MODULE_AUTHOR(SS__CONTACT);
MODULE_DESCRIPTION(SS__DESCRIP);
MODULE_SUPPORTED_DEVICE(SS__DEVICE);
#ifdef MODULE_LICENSE
MODULE_LICENSE(SS__LICENSE);
#endif
#if defined MODULE_ALIAS
MODULE_ALIAS("streams-inet");
#endif
#endif
#ifdef LFS
#define SS__DRV_ID CONFIG_STREAMS_SS__MAJOR
#define SS__DRV_NAME CONFIG_STREAMS_SS__NAME
#define SS__CMAJORS CONFIG_STREAMS_SS__NMAJORS
#define SS__CMAJOR_0 CONFIG_STREAMS_SS__MAJOR
#define SS__UNITS CONFIG_STREAMS_SS__NMINORS
#endif
#define IP_CMINOR 32
#define FIRST_CMINOR 33
#define ICMP_CMINOR 33
#define GGP_CMINOR 34
#define IPIP_CMINOR 35
#define TCP_CMINOR 36
#define EGP_CMINOR 37
#define PUP_CMINOR 38
#define UDP_CMINOR 39
#define IDP_CMINOR 40
#define RAWIP_CMINOR 41
#define TICOTS_ORD_CMINOR 42
#define TICOTS_CMINOR 43
#define TICLTS_CMINOR 44
#if defined HAVE_OPENSS7_SCTP
#define SCTP_CMINOR 45
#define LAST_CMINOR 45
#else
#define LAST_CMINOR 44
#endif
#define FREE_CMINOR 50
#ifdef LINUX
#ifdef MODULE_ALIAS
#ifdef LFS
MODULE_ALIAS("streams-modid-" __stringify(CONFIG_STREAMS_SS__MAJOR));
MODULE_ALIAS("streams-driver-inet");
MODULE_ALIAS("streams-major-" __stringify(CONFIG_STREAMS_SS__MAJOR));
MODULE_ALIAS("/dev/streams/inet");
MODULE_ALIAS("/dev/streams/inet
#endif
#endif
#define DRV_ID SS__DRV_ID
#define DRV_NAME SS__DRV_NAME
#define CMAJORS SS__CMAJORS
#define CMAJOR_0 SS__CMAJOR_0
#define UNITS SS__UNITS
#ifdef MODULE
#define DRV_BANNER SS__BANNER
#else
#define DRV_BANNER SS__SPLASH
#endif
STATIC struct module_info ss_rinfo = {
.mi_idnum = DRV_ID,
.mi_idname = DRV_NAME,
.mi_minpsz = 0,
.mi_maxpsz = (1 << 16),
.mi_hiwat = SHEADHIWAT << 5,
.mi_lowat = 0,
};
STATIC struct module_stat ss_rstat __attribute__ ((__aligned__(SMP_CACHE_BYTES)));
STATIC struct module_stat ss_wstat __attribute__ ((__aligned__(SMP_CACHE_BYTES)));
STATIC streamscall int ss_open(queue_t *, dev_t *, int, int, cred_t *);
STATIC streamscall int ss_close(queue_t *, int, cred_t *);
STATIC streamscall int ss_rput(queue_t *, mblk_t *);
STATIC streamscall int ss_rsrv(queue_t *);
STATIC struct qinit ss_rinit = {
.qi_putp = ss_rput,
.qi_srvp = ss_rsrv,
.qi_qopen = ss_open,
.qi_qclose = ss_close,
.qi_minfo = &ss_rinfo,
.qi_mstat = &ss_rstat,
};
STATIC struct module_info ss_winfo = {
.mi_idnum = DRV_ID,
.mi_idname = DRV_NAME,
.mi_minpsz = 0,
.mi_maxpsz = (1 << 16),
.mi_hiwat = (SHEADHIWAT >> 1),
.mi_lowat = 0,
};
STATIC streamscall int ss_wput(queue_t *, mblk_t *);
STATIC streamscall int ss_wsrv(queue_t *);
STATIC struct qinit ss_winit = {
.qi_putp = ss_wput,
.qi_srvp = ss_wsrv,
.qi_minfo = &ss_winfo,
.qi_mstat = &ss_wstat,
};
MODULE_STATIC struct streamtab ss_info = {
.st_rdinit = &ss_rinit,
.st_wrinit = &ss_winit,
};
#define TSF_UNBND ( 1 << TS_UNBND )
#define TSF_WACK_BREQ ( 1 << TS_WACK_BREQ )
#define TSF_WACK_UREQ ( 1 << TS_WACK_UREQ )
#define TSF_IDLE ( 1 << TS_IDLE )
#ifdef TS_WACK_OPTREQ
#define TSF_WACK_OPTREQ ( 1 << TS_WACK_OPTREQ )
#endif
#define TSF_WACK_CREQ ( 1 << TS_WACK_CREQ )
#define TSF_WCON_CREQ ( 1 << TS_WCON_CREQ )
#define TSF_WRES_CIND ( 1 << TS_WRES_CIND )
#define TSF_WACK_CRES ( 1 << TS_WACK_CRES )
#define TSF_DATA_XFER ( 1 << TS_DATA_XFER )
#define TSF_WIND_ORDREL ( 1 << TS_WIND_ORDREL )
#define TSF_WREQ_ORDREL ( 1 << TS_WREQ_ORDREL )
#define TSF_WACK_DREQ6 ( 1 << TS_WACK_DREQ6 )
#define TSF_WACK_DREQ7 ( 1 << TS_WACK_DREQ7 )
#define TSF_WACK_DREQ9 ( 1 << TS_WACK_DREQ9 )
#define TSF_WACK_DREQ10 ( 1 << TS_WACK_DREQ10 )
#define TSF_WACK_DREQ11 ( 1 << TS_WACK_DREQ11 )
#define TSF_NOSTATES ( 1 << TS_NOSTATES )
#define TSM_WACK_DREQ (TSF_WACK_DREQ6 \
|TSF_WACK_DREQ7 \
|TSF_WACK_DREQ9 \
|TSF_WACK_DREQ10 \
|TSF_WACK_DREQ11)
#define TSM_LISTEN (TSF_IDLE \
|TSF_WRES_CIND)
#define TSM_CONNECTED (TSF_WCON_CREQ\
|TSF_WRES_CIND\
|TSF_DATA_XFER\
|TSF_WIND_ORDREL\
|TSF_WREQ_ORDREL)
#define TSM_DISCONN (TSF_IDLE\
|TSF_UNBND)
#define TSM_INDATA (TSF_DATA_XFER\
|TSF_WIND_ORDREL)
#define TSM_OUTDATA (TSF_DATA_XFER\
|TSF_WREQ_ORDREL)
#ifndef T_PROVIDER
#define T_PROVIDER 0
#define T_USER 1
#endif
#define TCPM_CLOSING (TCPF_CLOSE\
|TCPF_TIME_WAIT\
|TCPF_CLOSE_WAIT)
#define TCPM_CONNIND (TCPF_SYN_RECV\
|TCPF_ESTABLISHED\
|TCPF_LISTEN)
typedef struct ss_options {
#if 0
unsigned char flags[12];
#else
unsigned long flags[3];
#endif
struct {
t_uscalar_t debug[4];
struct t_linger linger;
t_uscalar_t rcvbuf;
t_uscalar_t rcvlowat;
t_uscalar_t sndbuf;
t_uscalar_t sndlowat;
} xti;
struct {
unsigned char options[40];
unsigned char tos;
unsigned char ttl;
unsigned int reuseaddr;
unsigned int dontroute;
unsigned int broadcast;
uint32_t addr;
} ip;
struct {
t_uscalar_t checksum;
} udp;
struct {
t_uscalar_t nodelay;
t_uscalar_t maxseg;
struct t_kpalive keepalive;
t_uscalar_t cork;
t_uscalar_t keepidle;
t_uscalar_t keepitvl;
t_uscalar_t keepcnt;
t_uscalar_t syncnt;
t_uscalar_t linger2;
t_uscalar_t defer_accept;
t_uscalar_t window_clamp;
struct t_tcp_info info;
t_uscalar_t quickack;
} tcp;
#if defined HAVE_OPENSS7_SCTP
struct {
t_uscalar_t nodelay;
t_uscalar_t maxseg;
t_uscalar_t cork;
t_uscalar_t ppi;
t_uscalar_t sid;
t_uscalar_t ssn;
t_uscalar_t tsn;
t_uscalar_t recvopt;
t_uscalar_t cookie_life;
t_uscalar_t sack_delay;
t_uscalar_t path_max_retrans;
t_uscalar_t assoc_max_retrans;
t_uscalar_t max_init_retries;
t_uscalar_t heartbeat_itvl;
t_uscalar_t rto_initial;
t_uscalar_t rto_min;
t_uscalar_t rto_max;
t_uscalar_t ostreams;
t_uscalar_t istreams;
t_uscalar_t cookie_inc;
t_uscalar_t throttle_itvl;
t_uscalar_t mac_type;
t_uscalar_t cksum_type;
struct t_sctp_hb hb;
struct t_sctp_rto rto;
struct {
struct t_sctp_status status;
struct t_sctp_dest_status dest_status;
} status;
t_uscalar_t debug;
#if defined CONFIG_SCTP_ECN
t_uscalar_t ecn;
#endif
#if defined CONFIG_SCTP_ADD_IP || defined CONFIG_SCTP_ADAPTATION_LAYER_INFO
t_uscalar_t ali;
#endif
#if defined CONFIG_SCTP_ADD_IP
t_uscalar_t add;
t_uscalar_t set;
struct sockaddr_in add_ip;
struct sockaddr_in del_ip;
struct sockaddr_in set_ip;
#endif
#if defined CONFIG_SCTP_PARTIAL_RELIABILITY
t_uscalar_t pr;
#endif
#if defined CONFIG_SCTP_LIFETIMES || defined CONFIG_SCTP_PARTIAL_RELIABILITY
t_uscalar_t lifetime;
#endif
t_uscalar_t disposition;
t_uscalar_t max_burst;
} sctp;
#endif
} ss_options_t;
typedef struct ss_profile {
struct {
uint family;
uint type;
uint protocol;
} prot;
struct T_info_ack info;
} ss_profile_t;
typedef struct ss_protocol {
struct ss_protocol *next;
struct ss_protocol **prev;
atomic_t refcnt;
spinlock_t lock;
void (*put) (struct ss_protocol *);
struct ss_protocol *(*get) (struct ss_protocol *);
uint type;
uint id;
uint state;
uint flags;
int ps_family;
int ps_type;
int ps_protocol;
dev_t ps_dev;
int ps_flags;
} ss_protocol_t;
struct ss_protocol *ss_protosw = NULL;
typedef struct inet {
struct inet *next;
struct inet **prev;
size_t refcnt;
spinlock_t lock;
major_t cmajor;
minor_t cminor;
queue_t *rq;
queue_t *wq;
cred_t cred;
spinlock_t qlock;
queue_t *rwait;
queue_t *wwait;
long users;
uint rbid;
uint wbid;
ushort port;
int tcp_state;
ss_profile_t p;
struct {
void (*sk_state_change) (struct sock *);
void (*sk_data_ready) (struct sock *, int);
void (*sk_write_space) (struct sock *);
void (*sk_error_report) (struct sock *);
} cb_save;
struct sockaddr src;
struct sockaddr dst;
ss_options_t options;
unsigned char _pad[40];
bufq_t conq;
uint conind;
struct socket *sock;
} ss_t;
#define PRIV(__q) ((ss_t *)((__q)->q_ptr))
#define SOCK_PRIV(__sk) ((__sk)->sk_user_data)
#define xti_default_debug { 0, }
#define xti_default_linger (struct t_linger){T_YES, 120}
#define xti_default_rcvbuf SK_RMEM_MAX
#define xti_default_rcvlowat 1
#define xti_default_sndbuf SK_WMEM_MAX
#define xti_default_sndlowat 1
#define ip_default_options { 0, }
#define ip_default_tos 0
#define ip_default_ttl 64
#define ip_default_reuseaddr T_NO
#define ip_default_dontroute T_NO
#define ip_default_broadcast T_NO
#define udp_default_checksum T_YES
#define tcp_default_nodelay T_NO
#define tcp_default_maxseg 536
#define tcp_default_keepalive (struct t_kpalive){ T_YES, 1 }
#define sctp_default_nodelay T_NO
#define sctp_default_maxseg 536
#define sctp_default_cork T_NO
#define sctp_default_ppi 0
#define sctp_default_sid 0
#define sctp_default_ssn T_UNSPEC
#define sctp_default_tsn T_UNSPEC
#define sctp_default_recvopt T_YES
#define sctp_default_cookie_life 60
#define sctp_default_sack_delay 200
#define sctp_default_path_max_retrans 5
#define sctp_default_assoc_max_retrans 10
#define sctp_default_max_init_retries 8
#define sctp_default_heartbeat_itvl 30
#define sctp_default_rto_initial 3000
#define sctp_default_rto_min 1000
#define sctp_default_rto_max 60000
#define sctp_default_ostreams 1
#define sctp_default_istreams 33
#define sctp_default_cookie_inc 1000
#define sctp_default_throttle_itvl 50
#ifdef CONFIG_SCTP_HMAC_MD5
#define sctp_default_mac_type T_SCTP_HMAC_MD5
#else
#ifdef CONFIG_SCTP_HMAC_SHA1
#define sctp_default_mac_type T_SCTP_HMAC_SHA1
#else
#define sctp_default_mac_type T_SCTP_HMAC_NONE
#endif
#endif
#if defined CONFIG_SCTP_CRC32C
#define sctp_default_cksum_type T_SCTP_CSUM_CRC32C
#else
#define sctp_default_cksum_type T_SCTP_CSUM_ADLER32
#endif
#define sctp_default_hb (struct t_sctp_hb){ INADDR_ANY, T_YES, sctp_default_heartbeat_itvl }
#define sctp_default_rto (struct t_sctp_rto){ INADDR_ANY, sctp_default_rto_initial, sctp_default_rto_min, sctp_default_rto_max, sctp_default_path_max_retrans }
#define sctp_default_sctp_status (struct t_sctp_status){ 0, }
#define sctp_default_dest_status (struct t_sctp_dest_status){ INADDR_ANY, }
#define sctp_default_status { { 0, }, { INADDR_ANY, } }
#define sctp_default_debug 0
#if defined CONFIG_SCTP_ECN
#define sctp_default_ecn T_YES
#else
#define sctp_default_ecn T_NO
#endif
#define sctp_default_ali 0
#define sctp_default_add T_NO
#define sctp_default_set T_NO
#define sctp_default_add_ip INADDR_ANY
#define sctp_default_del_ip INADDR_ANY
#define sctp_default_set_ip INADDR_ANY
#define sctp_default_pr T_NO
#define sctp_default_lifetime T_UNSPEC
#define sctp_default_disposition T_UNSPEC
#define sctp_default_max_burst 4
enum {
_T_BIT_XTI_DEBUG = 0,
_T_BIT_XTI_LINGER,
_T_BIT_XTI_RCVBUF,
_T_BIT_XTI_RCVLOWAT,
_T_BIT_XTI_SNDBUF,
_T_BIT_XTI_SNDLOWAT,
_T_BIT_IP_OPTIONS,
_T_BIT_IP_TOS,
_T_BIT_IP_TTL,
_T_BIT_IP_REUSEADDR,
_T_BIT_IP_DONTROUTE,
_T_BIT_IP_BROADCAST,
_T_BIT_IP_ADDR,
_T_BIT_IP_RETOPTS,
_T_BIT_TCP_NODELAY,
_T_BIT_TCP_MAXSEG,
_T_BIT_TCP_KEEPALIVE,
_T_BIT_TCP_CORK,
_T_BIT_TCP_KEEPIDLE,
_T_BIT_TCP_KEEPINTVL,
_T_BIT_TCP_KEEPCNT,
_T_BIT_TCP_SYNCNT,
_T_BIT_TCP_LINGER2,
_T_BIT_TCP_DEFER_ACCEPT,
_T_BIT_TCP_WINDOW_CLAMP,
_T_BIT_TCP_INFO,
_T_BIT_TCP_QUICKACK,
_T_BIT_UDP_CHECKSUM,
#if defined HAVE_OPENSS7_SCTP
_T_BIT_SCTP_NODELAY,
_T_BIT_SCTP_MAXSEG,
_T_BIT_SCTP_CORK,
_T_BIT_SCTP_PPI,
_T_BIT_SCTP_SID,
_T_BIT_SCTP_SSN,
_T_BIT_SCTP_TSN,
_T_BIT_SCTP_RECVOPT,
_T_BIT_SCTP_COOKIE_LIFE,
_T_BIT_SCTP_SACK_DELAY,
_T_BIT_SCTP_PATH_MAX_RETRANS,
_T_BIT_SCTP_ASSOC_MAX_RETRANS,
_T_BIT_SCTP_MAX_INIT_RETRIES,
_T_BIT_SCTP_HEARTBEAT_ITVL,
_T_BIT_SCTP_RTO_INITIAL,
_T_BIT_SCTP_RTO_MIN,
_T_BIT_SCTP_RTO_MAX,
_T_BIT_SCTP_OSTREAMS,
_T_BIT_SCTP_ISTREAMS,
_T_BIT_SCTP_COOKIE_INC,
_T_BIT_SCTP_THROTTLE_ITVL,
_T_BIT_SCTP_MAC_TYPE,
_T_BIT_SCTP_CKSUM_TYPE,
_T_BIT_SCTP_HB,
_T_BIT_SCTP_RTO,
_T_BIT_SCTP_STATUS,
_T_BIT_SCTP_DEBUG,
_T_BIT_SCTP_ECN,
_T_BIT_SCTP_ALI,
_T_BIT_SCTP_ADD,
_T_BIT_SCTP_SET,
_T_BIT_SCTP_ADD_IP,
_T_BIT_SCTP_DEL_IP,
_T_BIT_SCTP_SET_IP,
_T_BIT_SCTP_PR,
_T_BIT_SCTP_LIFETIME,
_T_BIT_SCTP_DISPOSITION,
_T_BIT_SCTP_MAX_BURST,
#endif
};
typedef struct ss_event {
struct sock *sk;
int state;
} ss_event_t;
STATIC spinlock_t ss_lock = SPIN_LOCK_UNLOCKED;
STATIC ss_t *ss_opens = NULL;
#if 0
STATIC ss_t *ss_dflt_dest = NULL;
STATIC ss_t *ss_dflt_lstn = NULL;
#endif
STATIC void ss_state_change(struct sock *sk);
STATIC void ss_write_space(struct sock *sk);
STATIC void ss_error_report(struct sock *sk);
STATIC void ss_data_ready(struct sock *sk, int len);
STATIC void
ss_socket_put(struct socket *sock)
{
unsigned long flags;
struct sock *sk;
ensure(sock, return);
if ((sk = sock->sk)) {
write_lock_irqsave(&sk->sk_callback_lock, flags);
{
ss_t *ss;
if ((ss = SOCK_PRIV(sk))) {
SOCK_PRIV(sk) = NULL;
ss->refcnt--;
sk->sk_state_change = ss->cb_save.sk_state_change;
sk->sk_data_ready = ss->cb_save.sk_data_ready;
sk->sk_write_space = ss->cb_save.sk_write_space;
sk->sk_error_report = ss->cb_save.sk_error_report;
} else
assure(ss);
}
write_unlock_irqrestore(&sock->sk->sk_callback_lock, flags);
sock_set_keepopen(sk);
sk->sk_lingertime = 0;
} else
assure(sk);
sock_release(sock);
}
STATIC void
ss_socket_get(struct socket *sock, ss_t *ss)
{
unsigned long flags;
struct sock *sk;
ensure(sock, return);
if ((sk = sock->sk)) {
write_lock_irqsave(&sock->sk->sk_callback_lock, flags);
{
SOCK_PRIV(sk) = ss;
ss->refcnt++;
ss->cb_save.sk_state_change = sk->sk_state_change;
ss->cb_save.sk_data_ready = sk->sk_data_ready;
ss->cb_save.sk_write_space = sk->sk_write_space;
ss->cb_save.sk_error_report = sk->sk_error_report;
sk->sk_state_change = ss_state_change;
sk->sk_data_ready = ss_data_ready;
sk->sk_write_space = ss_write_space;
sk->sk_error_report = ss_error_report;
#ifdef LINUX_2_4
inet_sk(sk)->recverr = 1;
#else
sk->ip_recverr = 1;
#endif
ss->tcp_state = sk->sk_state;
}
write_unlock_irqrestore(&sock->sk->sk_callback_lock, flags);
} else
assure(sk);
}
#if 0
STATIC int
ss_trylockq(queue_t *q)
{
unsigned long flags;
int res;
ss_t *ss = PRIV(q);
spin_lock_irqsave(&ss->qlock, flags);
if (!(res = !ss->users++)) {
if (q == ss->rq)
ss->rwait = q;
if (q == ss->wq)
ss->wwait = q;
--ss->users;
}
spin_unlock_irqrestore(&ss->qlock, flags);
return (res);
}
STATIC void
ss_unlockq(queue_t *q)
{
unsigned long flags;
ss_t *ss = PRIV(q);
spin_lock_irqsave(&ss->qlock, flags);
if (ss->rwait)
qenable(xchg(&ss->rwait, NULL));
if (ss->wwait)
qenable(xchg(&ss->wwait, NULL));
ss->users = 0;
spin_unlock_irqrestore(&ss->qlock, flags);
}
#else
STATIC inline fastcall int
ss_trylockq(queue_t *q)
{
return (!test_and_set_bit(0, &PRIV(q)->users));
}
STATIC inline fastcall void
ss_unlockq(queue_t *q)
{
clear_bit(0, &PRIV(q)->users);
}
#endif
STATIC void streamscall
ss_bufsrv(long data)
{
queue_t *q = (queue_t *) data;
if (q) {
ss_t *ss = PRIV(q);
unsigned long flags;
spin_lock_irqsave(&ss->lock, flags);
if (q == ss->rq) {
if (ss->rbid) {
ss->rbid = 0;
ss->refcnt--;
}
} else if (q == ss->wq) {
if (ss->wbid) {
ss->wbid = 0;
ss->refcnt--;
}
} else
swerr();
spin_unlock_irqrestore(&ss->lock, flags);
qenable(q);
}
}
STATIC void
__ss_unbufcall(queue_t *q)
{
ss_t *ss = PRIV(q);
if (ss->rbid) {
unbufcall(xchg(&ss->rbid, 0));
ss->refcnt--;
}
if (ss->wbid) {
unbufcall(xchg(&ss->wbid, 0));
ss->refcnt--;
}
}
STATIC mblk_t *
ss_allocb(queue_t *q, size_t size, int prior)
{
mblk_t *mp;
if ((mp = allocb(size, prior)))
return (mp);
else {
ss_t *ss = PRIV(q);
unsigned long flags;
spin_lock_irqsave(&ss->lock, flags);
if (q == ss->rq) {
if (!ss->rbid) {
ss->rbid = bufcall(size, prior, &ss_bufsrv, (long) q);
ss->refcnt++;
}
} else if (q == ss->wq) {
if (!ss->wbid) {
ss->wbid = bufcall(size, prior, &ss_bufsrv, (long) q);
ss->refcnt++;
}
} else
swerr();
spin_unlock_irqrestore(&ss->lock, flags);
return (NULL);
}
}
#if 0
STATIC mblk_t *
ss_esballoc(queue_t *q, unsigned char *base, size_t size, int prior, frtn_t *frtn)
{
mblk_t *mp;
if ((mp = esballoc(base, size, prior, frtn)))
return (mp);
else {
ss_t *ss = PRIV(q);
if (q == ss->rq) {
if (!ss->rbid) {
ss->rbid = esbbcall(prior, &ss_bufsrv, (long) q);
ss->refcnt++;
}
return (NULL);
}
if (q == ss->wq) {
if (!ss->wbid) {
ss->wbid = esbbcall(prior, &ss_bufsrv, (long) q);
ss->refcnt++;
}
return (NULL);
}
swerr();
return (NULL);
}
}
#endif
#define T_SPACE(len) \
(sizeof(struct t_opthdr) + T_ALIGN(len))
#define T_LENGTH(len) \
(sizeof(struct t_opthdr) + len)
#define _T_SPACE_SIZEOF(s) \
T_SPACE(sizeof(s))
#define _T_LENGTH_SIZEOF(s) \
T_LENGTH(sizeof(s))
STATIC ss_options_t ss_defaults = {
{0,}
,
{
xti_default_debug,
xti_default_linger,
xti_default_rcvbuf,
xti_default_rcvlowat,
xti_default_sndbuf,
xti_default_sndlowat,
}
,
{
ip_default_options,
ip_default_tos,
ip_default_ttl,
ip_default_reuseaddr,
ip_default_dontroute,
ip_default_broadcast,
}
,
{
udp_default_checksum,
}
,
{
tcp_default_nodelay,
tcp_default_maxseg,
tcp_default_keepalive,
}
#if defined HAVE_OPENSS7_SCTP
,
{
sctp_default_nodelay,
sctp_default_maxseg,
sctp_default_cork,
sctp_default_ppi,
sctp_default_sid,
sctp_default_ssn,
sctp_default_tsn,
sctp_default_recvopt,
sctp_default_cookie_life,
sctp_default_sack_delay,
sctp_default_path_max_retrans,
sctp_default_assoc_max_retrans,
sctp_default_max_init_retries,
sctp_default_heartbeat_itvl,
sctp_default_rto_initial,
sctp_default_rto_min,
sctp_default_rto_max,
sctp_default_ostreams,
sctp_default_istreams,
sctp_default_cookie_inc,
sctp_default_throttle_itvl,
sctp_default_mac_type,
sctp_default_cksum_type,
sctp_default_hb,
sctp_default_rto,
sctp_default_status,
sctp_default_debug,
#if defined CONFIG_SCTP_ECN
sctp_default_ecn,
#endif
#if defined CONFIG_SCTP_ADD_IP || defined CONFIG_SCTP_ADAPTATION_LAYER_INFO
sctp_default_ali,
#endif
#if defined CONFIG_SCTP_ADD_IP
sctp_default_add,
sctp_default_set,
sctp_default_add_ip,
sctp_default_del_ip,
sctp_default_set_ip,
#endif
#if defined CONFIG_SCTP_PARTIAL_RELIABILITY
sctp_default_pr,
#endif
#if defined CONFIG_SCTP_LIFETIMES || defined CONFIG_SCTP_PARTIAL_RELIABILITY
sctp_default_lifetime,
#endif
sctp_default_disposition,
sctp_default_max_burst,
}
#endif
};
#define t_defaults ss_defaults
STATIC int
ss_size_conn_opts(ss_t *ss)
{
int size = 0;
if (t_tst_bit(_T_BIT_XTI_DEBUG, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.xti.debug);
if (t_tst_bit(_T_BIT_XTI_LINGER, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.xti.linger);
if (t_tst_bit(_T_BIT_XTI_RCVBUF, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.xti.rcvbuf);
if (t_tst_bit(_T_BIT_XTI_RCVLOWAT, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.xti.rcvlowat);
if (t_tst_bit(_T_BIT_XTI_SNDBUF, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.xti.sndbuf);
if (t_tst_bit(_T_BIT_XTI_SNDLOWAT, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.xti.sndlowat);
if (ss->p.prot.family == PF_INET) {
{
#if 0
if (t_tst_bit(_T_BIT_IP_OPTIONS, ss->options.flags))
#endif
size += _T_SPACE_SIZEOF(ss->options.ip.options);
#if 0
if (t_tst_bit(_T_BIT_IP_TOS, ss->options.flags))
#endif
size += _T_SPACE_SIZEOF(ss->options.ip.tos);
}
if (t_tst_bit(_T_BIT_IP_TTL, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.ip.ttl);
if (t_tst_bit(_T_BIT_IP_REUSEADDR, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.ip.reuseaddr);
if (t_tst_bit(_T_BIT_IP_DONTROUTE, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.ip.dontroute);
if (t_tst_bit(_T_BIT_IP_BROADCAST, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.ip.broadcast);
if (t_tst_bit(_T_BIT_IP_ADDR, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.ip.addr);
switch (ss->p.prot.protocol) {
case T_INET_TCP:
if (t_tst_bit(_T_BIT_TCP_NODELAY, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.tcp.nodelay);
if (t_tst_bit(_T_BIT_TCP_MAXSEG, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.tcp.maxseg);
if (t_tst_bit(_T_BIT_TCP_KEEPALIVE, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.tcp.keepalive);
if (t_tst_bit(_T_BIT_TCP_CORK, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.tcp.cork);
if (t_tst_bit(_T_BIT_TCP_KEEPIDLE, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.tcp.keepidle);
if (t_tst_bit(_T_BIT_TCP_KEEPINTVL, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.tcp.keepitvl);
if (t_tst_bit(_T_BIT_TCP_KEEPCNT, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.tcp.keepcnt);
if (t_tst_bit(_T_BIT_TCP_SYNCNT, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.tcp.syncnt);
if (t_tst_bit(_T_BIT_TCP_LINGER2, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.tcp.linger2);
if (t_tst_bit(_T_BIT_TCP_DEFER_ACCEPT, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.tcp.defer_accept);
if (t_tst_bit(_T_BIT_TCP_WINDOW_CLAMP, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.tcp.window_clamp);
#if 0
if (t_tst_bit(_T_BIT_TCP_INFO, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.tcp.info);
#endif
if (t_tst_bit(_T_BIT_TCP_QUICKACK, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.tcp.quickack);
break;
#if defined HAVE_OPENSS7_SCTP
case T_INET_SCTP:
if (t_tst_bit(_T_BIT_SCTP_NODELAY, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.sctp.nodelay);
if (t_tst_bit(_T_BIT_SCTP_MAXSEG, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.sctp.maxseg);
if (t_tst_bit(_T_BIT_SCTP_CORK, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.sctp.cork);
if (t_tst_bit(_T_BIT_SCTP_PPI, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.sctp.ppi);
if (t_tst_bit(_T_BIT_SCTP_SID, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.sctp.sid);
if (t_tst_bit(_T_BIT_SCTP_SSN, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.sctp.ssn);
if (t_tst_bit(_T_BIT_SCTP_TSN, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.sctp.tsn);
if (t_tst_bit(_T_BIT_SCTP_RECVOPT, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.sctp.recvopt);
if (t_tst_bit(_T_BIT_SCTP_COOKIE_LIFE, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.sctp.cookie_life);
if (t_tst_bit(_T_BIT_SCTP_SACK_DELAY, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.sctp.sack_delay);
if (t_tst_bit(_T_BIT_SCTP_PATH_MAX_RETRANS, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.sctp.path_max_retrans);
if (t_tst_bit(_T_BIT_SCTP_ASSOC_MAX_RETRANS, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.sctp.assoc_max_retrans);
if (t_tst_bit(_T_BIT_SCTP_MAX_INIT_RETRIES, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.sctp.max_init_retries);
if (t_tst_bit(_T_BIT_SCTP_HEARTBEAT_ITVL, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.sctp.heartbeat_itvl);
if (t_tst_bit(_T_BIT_SCTP_RTO_INITIAL, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.sctp.rto_initial);
if (t_tst_bit(_T_BIT_SCTP_RTO_MIN, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.sctp.rto_min);
if (t_tst_bit(_T_BIT_SCTP_RTO_MAX, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.sctp.rto_max);
{
#if 0
if (t_tst_bit(_T_BIT_SCTP_OSTREAMS, ss->options.flags))
#endif
size += _T_SPACE_SIZEOF(ss->options.sctp.ostreams);
#if 0
if (t_tst_bit(_T_BIT_SCTP_ISTREAMS, ss->options.flags))
#endif
size += _T_SPACE_SIZEOF(ss->options.sctp.istreams);
}
if (t_tst_bit(_T_BIT_SCTP_COOKIE_INC, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.sctp.cookie_inc);
if (t_tst_bit(_T_BIT_SCTP_THROTTLE_ITVL, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.sctp.throttle_itvl);
if (t_tst_bit(_T_BIT_SCTP_MAC_TYPE, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.sctp.mac_type);
if (t_tst_bit(_T_BIT_SCTP_HB, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.sctp.hb);
if (t_tst_bit(_T_BIT_SCTP_RTO, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.sctp.rto);
if (t_tst_bit(_T_BIT_SCTP_STATUS, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.sctp.status);
if (t_tst_bit(_T_BIT_SCTP_DEBUG, ss->options.flags))
size += _T_SPACE_SIZEOF(ss->options.sctp.debug);
break;
#endif
}
}
return (size);
}
STATIC int
t_build_conn_opts(ss_t *ss, unsigned char *op, size_t olen)
{
struct t_opthdr *oh;
struct sock *sk;
if (op == NULL || olen == 0)
return (0);
if (!ss || !ss->sock || !(sk = ss->sock->sk))
goto eproto;
oh = _T_OPT_FIRSTHDR_OFS(op, olen, 0);
if (t_tst_bit(_T_BIT_XTI_DEBUG, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(ss->options.xti.debug);
oh->level = XTI_GENERIC;
oh->name = XTI_DEBUG;
oh->status = T_SUCCESS;
bcopy(ss->options.xti.debug, T_OPT_DATA(oh), sizeof(ss->options.xti.debug));
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_XTI_LINGER, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(ss->options.xti.linger);
oh->level = XTI_GENERIC;
oh->name = XTI_LINGER;
oh->status = T_SUCCESS;
if ((sock_tst_linger(sk) == 1) != (ss->options.xti.linger.l_onoff == T_YES)) {
ss->options.xti.linger.l_onoff = sock_tst_linger(sk) ? T_YES : T_NO;
}
if (ss->options.xti.linger.l_onoff == T_YES) {
if (ss->options.xti.linger.l_linger != sk->sk_lingertime / HZ) {
if (ss->options.xti.linger.l_linger != T_UNSPEC
&& ss->options.xti.linger.l_linger < sk->sk_lingertime / HZ)
oh->status = T_PARTSUCCESS;
ss->options.xti.linger.l_linger = sk->sk_lingertime / HZ;
}
} else
ss->options.xti.linger.l_linger = T_UNSPEC;
*((struct t_linger *) T_OPT_DATA(oh)) = ss->options.xti.linger;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_XTI_RCVBUF, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(ss->options.xti.rcvbuf);
oh->level = XTI_GENERIC;
oh->name = XTI_RCVBUF;
oh->status = T_SUCCESS;
if (ss->options.xti.rcvbuf != sk->sk_rcvbuf / 2) {
if (ss->options.xti.rcvbuf != T_UNSPEC
&& ss->options.xti.rcvbuf < sk->sk_rcvbuf / 2)
oh->status = T_PARTSUCCESS;
ss->options.xti.rcvbuf = sk->sk_rcvbuf / 2;
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.xti.rcvbuf;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_XTI_RCVLOWAT, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(ss->options.xti.rcvlowat);
oh->level = XTI_GENERIC;
oh->name = XTI_RCVLOWAT;
oh->status = T_SUCCESS;
if (ss->options.xti.rcvlowat != sk->sk_rcvlowat) {
if (ss->options.xti.rcvlowat != T_UNSPEC
&& ss->options.xti.rcvlowat < sk->sk_rcvlowat)
oh->status = T_PARTSUCCESS;
ss->options.xti.rcvlowat = sk->sk_rcvlowat;
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.xti.rcvlowat;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_XTI_SNDBUF, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(ss->options.xti.sndbuf);
oh->level = XTI_GENERIC;
oh->name = XTI_SNDBUF;
oh->status = T_SUCCESS;
if (ss->options.xti.sndbuf != sk->sk_sndbuf / 2) {
if (ss->options.xti.sndbuf != T_UNSPEC
&& ss->options.xti.sndbuf < sk->sk_sndbuf / 2)
oh->status = T_PARTSUCCESS;
ss->options.xti.sndbuf = sk->sk_sndbuf / 2;
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.xti.sndbuf;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_XTI_SNDLOWAT, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(ss->options.xti.sndlowat);
oh->level = XTI_GENERIC;
oh->name = XTI_SNDLOWAT;
oh->status = T_SUCCESS;
if (ss->options.xti.sndlowat != 1) {
if (ss->options.xti.sndlowat != T_UNSPEC && ss->options.xti.sndlowat < 1)
oh->status = T_PARTSUCCESS;
ss->options.xti.sndlowat = 1;
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = t_defaults.xti.sndlowat;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (ss->p.prot.family == PF_INET) {
struct inet_opt *np = inet_sk(sk);
#if 0
if (t_tst_bit(_T_BIT_IP_OPTIONS, ss->options.flags))
#endif
{
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(ss->options.ip.options);
oh->level = T_INET_IP;
oh->name = T_IP_OPTIONS;
oh->status = T_SUCCESS;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
#if 0
if (t_tst_bit(_T_BIT_IP_TOS, ss->options.flags))
#endif
{
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(ss->options.ip.tos);
oh->level = T_INET_IP;
oh->name = T_IP_TOS;
oh->status = T_SUCCESS;
if (ss->options.ip.tos != np->tos) {
if (ss->options.ip.tos > np->tos)
oh->status = T_PARTSUCCESS;
ss->options.ip.tos = np->tos;
}
*((unsigned char *) T_OPT_DATA(oh)) = ss->options.ip.tos;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_IP_TTL, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(ss->options.ip.ttl);
oh->level = T_INET_IP;
oh->name = T_IP_TTL;
oh->status = T_SUCCESS;
#ifdef HAVE_STRUCT_SOCK_PROTINFO_AF_INET_TTL
if (ss->options.ip.ttl != np->ttl) {
if (ss->options.ip.ttl > np->ttl)
oh->status = T_PARTSUCCESS;
ss->options.ip.ttl = np->ttl;
}
#else
#ifdef HAVE_STRUCT_SOCK_PROTINFO_AF_INET_UC_TTL
if (ss->options.ip.ttl != np->uc_ttl) {
if (ss->options.ip.ttl > np->uc_ttl)
oh->status = T_PARTSUCCESS;
ss->options.ip.ttl = np->uc_ttl;
}
#endif
#endif
*((unsigned char *) T_OPT_DATA(oh)) = ss->options.ip.ttl;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_IP_REUSEADDR, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(unsigned int);
oh->level = T_INET_IP;
oh->name = T_IP_REUSEADDR;
oh->status = T_SUCCESS;
if ((ss->options.ip.reuseaddr == T_NO) != (sk->sk_reuse == 0)) {
oh->status = T_PARTSUCCESS;
ss->options.ip.reuseaddr = sk->sk_reuse ? T_YES : T_NO;
}
*((unsigned int *) T_OPT_DATA(oh)) = ss->options.ip.reuseaddr;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_IP_DONTROUTE, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(unsigned int);
oh->level = T_INET_IP;
oh->name = T_IP_DONTROUTE;
oh->status = T_SUCCESS;
if ((ss->options.ip.dontroute == T_NO) != (sock_tst_localroute(sk) == 0)) {
oh->status = T_PARTSUCCESS;
ss->options.ip.dontroute = sock_tst_localroute(sk) ? T_YES : T_NO;
}
*((unsigned int *) T_OPT_DATA(oh)) = ss->options.ip.dontroute;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_IP_BROADCAST, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(unsigned int);
oh->level = T_INET_IP;
oh->name = T_IP_BROADCAST;
oh->status = T_SUCCESS;
if ((ss->options.ip.broadcast == T_NO) != (sock_tst_broadcast(sk) == 0)) {
oh->status = T_PARTSUCCESS;
ss->options.ip.broadcast = sock_tst_broadcast(sk) ? T_YES : T_NO;
}
*((unsigned int *) T_OPT_DATA(oh)) = ss->options.ip.broadcast;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_IP_ADDR, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(uint32_t);
oh->level = T_INET_IP;
oh->name = T_IP_ADDR;
oh->status = T_SUCCESS;
*((uint32_t *) T_OPT_DATA(oh)) = ss->options.ip.addr;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
switch (ss->p.prot.protocol) {
case T_INET_TCP:
{
struct tcp_opt *tp = tcp_sk(sk);
if (t_tst_bit(_T_BIT_TCP_NODELAY, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_TCP;
oh->name = T_TCP_NODELAY;
oh->status = T_SUCCESS;
if ((ss->options.tcp.nodelay == T_NO) != (tp->nonagle == 0)) {
oh->status = T_PARTSUCCESS;
ss->options.tcp.nodelay = tp->nonagle ? T_YES : T_NO;
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.tcp.nodelay;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_TCP_MAXSEG, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_TCP;
oh->name = T_TCP_MAXSEG;
oh->status = T_SUCCESS;
if (ss->options.tcp.maxseg != tcp_user_mss(tp)) {
if (ss->options.tcp.maxseg > tcp_user_mss(tp))
oh->status = T_PARTSUCCESS;
ss->options.tcp.maxseg = tcp_user_mss(tp);
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.tcp.maxseg;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_TCP_KEEPALIVE, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(struct t_kpalive);
oh->level = T_INET_TCP;
oh->name = T_TCP_KEEPALIVE;
oh->status = T_SUCCESS;
if ((ss->options.tcp.keepalive.kp_onoff != T_NO) !=
(sock_tst_keepopen(sk) != 0)) {
ss->options.tcp.keepalive.kp_onoff =
sock_tst_keepopen(sk) ? T_YES : T_NO;
}
if (ss->options.tcp.keepalive.kp_onoff == T_YES) {
if (ss->options.tcp.keepalive.kp_timeout !=
tp->keepalive_time / 60 / HZ) {
if (ss->options.tcp.keepalive.kp_timeout != T_UNSPEC
&& ss->options.tcp.keepalive.kp_timeout >
tp->keepalive_time / 60 / HZ)
oh->status = T_PARTSUCCESS;
ss->options.tcp.keepalive.kp_timeout =
tp->keepalive_time / 60 / HZ;
}
} else
ss->options.tcp.keepalive.kp_timeout = T_UNSPEC;
*((struct t_kpalive *) T_OPT_DATA(oh)) = ss->options.tcp.keepalive;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_TCP_CORK, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_TCP;
oh->name = T_TCP_CORK;
oh->status = T_SUCCESS;
if ((ss->options.tcp.cork == T_YES) != (tp->nonagle == 2)) {
oh->status = T_FAILURE;
ss->options.tcp.cork = (tp->nonagle == 2) ? T_YES : T_NO;
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.tcp.cork;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_TCP_KEEPIDLE, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_TCP;
oh->name = T_TCP_KEEPIDLE;
oh->status = T_SUCCESS;
if (ss->options.tcp.keepidle == T_UNSPEC)
ss->options.tcp.keepidle = tp->keepalive_time / HZ;
else if (ss->options.tcp.keepidle != tp->keepalive_time / HZ) {
oh->status = T_PARTSUCCESS;
ss->options.tcp.keepidle = tp->keepalive_time / HZ;
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.tcp.keepidle;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_TCP_KEEPINTVL, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_TCP;
oh->name = T_TCP_KEEPINTVL;
oh->status = T_SUCCESS;
if (ss->options.tcp.keepitvl == T_UNSPEC)
ss->options.tcp.keepitvl = tp->keepalive_intvl / HZ;
else if (ss->options.tcp.keepitvl != tp->keepalive_intvl / HZ) {
oh->status = T_PARTSUCCESS;
ss->options.tcp.keepcnt = tp->keepalive_intvl / HZ;
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.tcp.keepcnt;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_TCP_KEEPCNT, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_TCP;
oh->name = T_TCP_KEEPCNT;
oh->status = T_SUCCESS;
if (ss->options.tcp.keepcnt == T_UNSPEC)
ss->options.tcp.keepcnt = tp->keepalive_probes;
else if (ss->options.tcp.keepcnt != tp->keepalive_probes) {
oh->status = T_FAILURE;
ss->options.tcp.keepcnt = tp->keepalive_probes;
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.tcp.keepcnt;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_TCP_SYNCNT, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_TCP;
oh->name = T_TCP_SYNCNT;
oh->status = T_SUCCESS;
if (ss->options.tcp.syncnt == T_UNSPEC)
ss->options.tcp.syncnt = sock_syn_retries(sk);
else if (ss->options.tcp.syncnt != sock_syn_retries(sk)) {
oh->status = T_FAILURE;
ss->options.tcp.syncnt = sock_syn_retries(sk);
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.tcp.syncnt;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_TCP_LINGER2, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_TCP;
oh->name = T_TCP_LINGER2;
oh->status = T_SUCCESS;
if (ss->options.tcp.linger2 == T_UNSPEC)
ss->options.tcp.linger2 = tp->linger2 / HZ;
else if (ss->options.tcp.linger2 != tp->linger2 / HZ) {
oh->status = T_PARTSUCCESS;
ss->options.tcp.linger2 = tp->linger2 / HZ;
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.tcp.linger2;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_TCP_DEFER_ACCEPT, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_TCP;
oh->name = T_TCP_DEFER_ACCEPT;
oh->status = T_SUCCESS;
if (ss->options.tcp.defer_accept == T_UNSPEC)
ss->options.tcp.defer_accept =
(TCP_TIMEOUT_INIT / HZ) << sock_defer_accept(sk);
else if (ss->options.tcp.defer_accept !=
((TCP_TIMEOUT_INIT / HZ) << sock_defer_accept(sk))) {
oh->status = T_PARTSUCCESS;
ss->options.tcp.defer_accept =
((TCP_TIMEOUT_INIT / HZ) << sock_defer_accept(sk));
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.tcp.defer_accept;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_TCP_WINDOW_CLAMP, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_TCP;
oh->name = T_TCP_WINDOW_CLAMP;
oh->status = T_SUCCESS;
if (ss->options.tcp.window_clamp == T_UNSPEC)
ss->options.tcp.window_clamp = tp->window_clamp;
else if (ss->options.tcp.window_clamp != tp->window_clamp) {
oh->status = T_PARTSUCCESS;
ss->options.tcp.window_clamp = tp->window_clamp;
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.tcp.window_clamp;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_TCP_INFO, ss->options.flags)) {
}
if (t_tst_bit(_T_BIT_TCP_QUICKACK, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_TCP;
oh->name = T_TCP_QUICKACK;
oh->status = T_SUCCESS;
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.tcp.quickack;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
break;
}
#if defined HAVE_OPENSS7_SCTP
case T_INET_SCTP:
{
struct sctp_opt *sp = sctp_sk(sk);
if (t_tst_bit(_T_BIT_SCTP_NODELAY, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_NODELAY;
oh->status = T_SUCCESS;
if ((ss->options.sctp.nodelay != T_NO) != (sp->nonagle != 0)) {
oh->status = T_PARTSUCCESS;
ss->options.sctp.nodelay = sp->nonagle ? T_YES : T_NO;
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.nodelay;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_MAXSEG, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_MAXSEG;
oh->status = T_SUCCESS;
if (ss->options.sctp.maxseg != sp->user_amps) {
if (ss->options.sctp.maxseg > sp->user_amps)
oh->status = T_PARTSUCCESS;
ss->options.sctp.maxseg = sp->user_amps;
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.maxseg;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_CORK, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_CORK;
oh->status = T_SUCCESS;
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.cork;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_PPI, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_PPI;
oh->status = T_SUCCESS;
ss->options.sctp.ppi = sp->ppi;
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.ppi;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_SID, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_SID;
oh->status = T_SUCCESS;
ss->options.sctp.sid = sp->sid;
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.sid;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_SSN, ss->options.flags)) {
}
if (t_tst_bit(_T_BIT_SCTP_TSN, ss->options.flags)) {
}
if (t_tst_bit(_T_BIT_SCTP_RECVOPT, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_RECVOPT;
oh->status = T_SUCCESS;
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.recvopt;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_COOKIE_LIFE, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_COOKIE_LIFE;
oh->status = T_SUCCESS;
if (ss->options.sctp.cookie_life != sp->ck_life / HZ * 1000) {
if (ss->options.sctp.cookie_life < sp->ck_life / HZ * 1000)
oh->status = T_PARTSUCCESS;
ss->options.sctp.cookie_life = sp->ck_life / HZ * 1000;
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.cookie_life;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_SACK_DELAY, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_SACK_DELAY;
oh->status = T_SUCCESS;
if (ss->options.sctp.sack_delay != sp->max_sack / HZ * 1000) {
if (ss->options.sctp.sack_delay < sp->max_sack / HZ * 1000)
oh->status = T_PARTSUCCESS;
ss->options.sctp.sack_delay = sp->max_sack / HZ * 1000;
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.sack_delay;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_PATH_MAX_RETRANS, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_PATH_MAX_RETRANS;
oh->status = T_SUCCESS;
*((t_uscalar_t *) T_OPT_DATA(oh)) =
ss->options.sctp.path_max_retrans;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_ASSOC_MAX_RETRANS, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_ASSOC_MAX_RETRANS;
oh->status = T_SUCCESS;
*((t_uscalar_t *) T_OPT_DATA(oh)) =
ss->options.sctp.assoc_max_retrans;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_MAX_INIT_RETRIES, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_MAX_INIT_RETRIES;
oh->status = T_SUCCESS;
*((t_uscalar_t *) T_OPT_DATA(oh)) =
ss->options.sctp.max_init_retries;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_HEARTBEAT_ITVL, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_HEARTBEAT_ITVL;
oh->status = T_SUCCESS;
if (ss->options.sctp.heartbeat_itvl != sp->hb_itvl / HZ * 1000) {
if (ss->options.sctp.heartbeat_itvl <
sp->hb_itvl / HZ * 1000)
oh->status = T_PARTSUCCESS;
ss->options.sctp.heartbeat_itvl = sp->hb_itvl / HZ * 1000;
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.heartbeat_itvl;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_RTO_INITIAL, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_RTO_INITIAL;
oh->status = T_SUCCESS;
if (ss->options.sctp.rto_initial != sp->rto_ini / HZ * 1000) {
if (ss->options.sctp.rto_initial < sp->rto_ini / HZ * 1000)
oh->status = T_PARTSUCCESS;
ss->options.sctp.rto_initial = sp->rto_ini / HZ * 1000;
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.rto_initial;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_RTO_MIN, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_RTO_MIN;
oh->status = T_SUCCESS;
if (ss->options.sctp.rto_min != sp->rto_min / HZ * 1000) {
if (ss->options.sctp.rto_min < sp->rto_min / HZ * 1000)
oh->status = T_PARTSUCCESS;
ss->options.sctp.rto_min = sp->rto_min / HZ * 1000;
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.rto_min;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_RTO_MAX, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_RTO_MAX;
oh->status = T_SUCCESS;
if (ss->options.sctp.rto_max != sp->rto_max / HZ * 1000) {
if (ss->options.sctp.rto_max < sp->rto_max / HZ * 1000)
oh->status = T_PARTSUCCESS;
ss->options.sctp.rto_max = sp->rto_max / HZ * 1000;
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.rto_max;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
#if 0
if (t_tst_bit(_T_BIT_SCTP_OSTREAMS, ss->options.flags))
#endif
{
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_OSTREAMS;
oh->status = T_SUCCESS;
if (ss->options.sctp.ostreams != sp->req_ostr) {
if (ss->options.sctp.ostreams > sp->req_ostr)
oh->status = T_PARTSUCCESS;
ss->options.sctp.ostreams = sp->req_ostr;
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.ostreams;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
#if 0
if (t_tst_bit(_T_BIT_SCTP_ISTREAMS, ss->options.flags))
#endif
{
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_ISTREAMS;
oh->status = T_SUCCESS;
if (ss->options.sctp.istreams != sp->max_istr) {
if (ss->options.sctp.istreams > sp->max_istr)
oh->status = T_PARTSUCCESS;
ss->options.sctp.istreams = sp->max_istr;
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.istreams;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_COOKIE_INC, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_COOKIE_INC;
oh->status = T_SUCCESS;
if (ss->options.sctp.cookie_inc != sp->ck_inc / HZ * 1000) {
if (ss->options.sctp.cookie_inc < sp->ck_inc / HZ * 1000)
oh->status = T_PARTSUCCESS;
ss->options.sctp.cookie_inc = sp->ck_inc / HZ * 1000;
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.cookie_inc;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_THROTTLE_ITVL, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_THROTTLE_ITVL;
oh->status = T_SUCCESS;
if (ss->options.sctp.throttle_itvl != sp->throttle / HZ * 1000) {
if (ss->options.sctp.throttle_itvl <
sp->throttle / HZ * 1000)
oh->status = T_PARTSUCCESS;
ss->options.sctp.throttle_itvl = sp->throttle / HZ * 1000;
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.throttle_itvl;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_MAC_TYPE, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_MAC_TYPE;
oh->status = T_SUCCESS;
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.mac_type;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_CKSUM_TYPE, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_CKSUM_TYPE;
oh->status = T_SUCCESS;
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.cksum_type;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_HB, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(struct t_sctp_hb);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_HB;
oh->status = T_SUCCESS;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_RTO, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(struct t_sctp_rto);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_RTO;
oh->status = T_SUCCESS;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_STATUS, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len =
T_SPACE(sizeof(struct t_sctp_status) +
sizeof(struct t_sctp_dest_status));
oh->level = T_INET_SCTP;
oh->name = T_SCTP_STATUS;
oh->status = T_SUCCESS;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_DEBUG, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_DEBUG;
oh->status = T_SUCCESS;
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.debug;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
#if defined CONFIG_SCTP_ECN
if (t_tst_bit(_T_BIT_SCTP_ECN, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_ECN;
oh->status = T_SUCCESS;
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.ecn;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
#endif
#if defined CONFIG_SCTP_ADD_IP || defined CONFIG_SCTP_ADAPTATION_LAYER_INFO
if (t_tst_bit(_T_BIT_SCTP_ALI, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_ALI;
oh->status = T_SUCCESS;
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.ali;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
#endif
#if defined CONFIG_SCTP_ADD_IP
if (t_tst_bit(_T_BIT_SCTP_ADD, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_ADD;
oh->status = T_SUCCESS;
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.add;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_SET, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_SET;
oh->status = T_SUCCESS;
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.set;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_ADD_IP, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_ADD_IP;
oh->status = T_SUCCESS;
*((struct sockaddr_in *) T_OPT_DATA(oh)) = ss->options.sctp.add_ip;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_DEL_IP, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_DEL_IP;
oh->status = T_SUCCESS;
*((struct sockaddr_in *) T_OPT_DATA(oh)) = ss->options.sctp.del_ip;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_SET_IP, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_SET_IP;
oh->status = T_SUCCESS;
*((struct sockaddr_in *) T_OPT_DATA(oh)) = ss->options.sctp.set_ip;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
#endif
#if defined CONFIG_SCTP_PARTIAL_RELIABILITY
if (t_tst_bit(_T_BIT_SCTP_PR, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_PR;
oh->status = T_SUCCESS;
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.pr;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
#endif
#if defined CONFIG_SCTP_LIFETIMES || defined CONFIG_SCTP_PARTIAL_RELIABILITY
if (t_tst_bit(_T_BIT_SCTP_LIFETIME, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_LIFETIME;
oh->status = T_SUCCESS;
if (ss->options.sctp.lifetime != sp->life / HZ * 1000) {
if (ss->options.sctp.lifetime < sp->life / HZ * 1000)
oh->status = T_PARTSUCCESS;
ss->options.sctp.lifetime = sp->life / HZ * 1000;
}
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.lifetime;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
#endif
if (t_tst_bit(_T_BIT_SCTP_DISPOSITION, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_DISPOSITION;
oh->status = T_SUCCESS;
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.disposition;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
if (t_tst_bit(_T_BIT_SCTP_MAX_BURST, ss->options.flags)) {
if (oh == NULL)
goto efault;
oh->len = _T_LENGTH_SIZEOF(t_uscalar_t);
oh->level = T_INET_SCTP;
oh->name = T_SCTP_MAX_BURST;
oh->status = T_SUCCESS;
*((t_uscalar_t *) T_OPT_DATA(oh)) = ss->options.sctp.max_burst;
oh = _T_OPT_NEXTHDR_OFS(op, olen, oh, 0);
}
break;
}
#endif
}
}
assure(oh == NULL);
return (olen);
// return ((unsigned char *) oh - op);
eproto:
swerr();
return (-EPROTO);
efault:
swerr();
return (-EFAULT);
}
#ifdef __LP64__
#undef MAX_SCHEDULE_TIMEOUT
#define MAX_SCHEDULE_TIMEOUT INT_MAX
#endif
STATIC int
t_set_options(ss_t *ss)
{
struct sock *sk;
if (!ss || !ss->sock || !(sk = ss->sock->sk))
goto eproto;
if (t_tst_bit(_T_BIT_XTI_DEBUG, ss->options.flags)) {
}
if (t_tst_bit(_T_BIT_XTI_LINGER, ss->options.flags)) {
struct t_linger *valp = &ss->options.xti.linger;
if (valp->l_onoff == T_NO)
valp->l_linger = T_UNSPEC;
else {
if (valp->l_linger == T_UNSPEC)
valp->l_linger = t_defaults.xti.linger.l_linger;
if (valp->l_linger == T_INFINITE)
valp->l_linger = MAX_SCHEDULE_TIMEOUT / HZ;
if (valp->l_linger >= MAX_SCHEDULE_TIMEOUT / HZ)
valp->l_linger = MAX_SCHEDULE_TIMEOUT / HZ;
}
if (valp->l_onoff == T_YES) {
sock_set_linger(sk);
sk->sk_lingertime = valp->l_linger * HZ;
} else {
sock_clr_linger(sk);
sk->sk_lingertime = 0;
}
}
if (t_tst_bit(_T_BIT_XTI_RCVBUF, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.xti.rcvbuf;
if (*valp > sysctl_rmem_max)
*valp = sysctl_rmem_max;
if (*valp < SOCK_MIN_RCVBUF / 2)
*valp = SOCK_MIN_RCVBUF / 2;
sk->sk_rcvbuf = *valp * 2;
}
if (t_tst_bit(_T_BIT_XTI_RCVLOWAT, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.xti.rcvlowat;
if (*valp < 1)
*valp = 1;
if (*valp > INT_MAX)
*valp = INT_MAX;
sk->sk_rcvlowat = *valp;
}
if (t_tst_bit(_T_BIT_XTI_SNDBUF, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.xti.sndbuf;
if (*valp > sysctl_wmem_max)
*valp = sysctl_wmem_max;
if (*valp < SOCK_MIN_SNDBUF / 2)
*valp = SOCK_MIN_SNDBUF / 2;
sk->sk_sndbuf = *valp * 2;
}
if (t_tst_bit(_T_BIT_XTI_SNDLOWAT, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.xti.sndlowat;
if (*valp < 1)
*valp = 1;
if (*valp > 1)
*valp = 1;
}
if (ss->p.prot.family == PF_INET) {
struct inet_opt *np = inet_sk(sk);
if (t_tst_bit(_T_BIT_IP_OPTIONS, ss->options.flags)) {
unsigned char *valp = ss->options.ip.options;
(void) valp;
}
if (t_tst_bit(_T_BIT_IP_TOS, ss->options.flags)) {
unsigned char *valp = &ss->options.ip.tos;
np->tos = *valp;
}
if (t_tst_bit(_T_BIT_IP_TTL, ss->options.flags)) {
unsigned char *valp = &ss->options.ip.ttl;
if (*valp < 1)
*valp = 1;
#ifdef HAVE_STRUCT_SOCK_PROTINFO_AF_INET_TTL
np->ttl = *valp;
#else
#ifdef HAVE_STRUCT_SOCK_PROTINFO_AF_INET_UC_TTL
np->uc_ttl = *valp;
#endif
#endif
}
if (t_tst_bit(_T_BIT_IP_REUSEADDR, ss->options.flags)) {
unsigned int *valp = &ss->options.ip.reuseaddr;
sk->sk_reuse = (*valp == T_YES) ? 1 : 0;
}
if (t_tst_bit(_T_BIT_IP_DONTROUTE, ss->options.flags)) {
unsigned int *valp = &ss->options.ip.dontroute;
if (*valp == T_YES)
sock_set_localroute(sk);
else
sock_clr_localroute(sk);
}
if (t_tst_bit(_T_BIT_IP_BROADCAST, ss->options.flags)) {
unsigned int *valp = &ss->options.ip.broadcast;
if (*valp == T_YES)
sock_set_broadcast(sk);
else
sock_clr_broadcast(sk);
}
if (t_tst_bit(_T_BIT_IP_ADDR, ss->options.flags)) {
uint32_t *valp = &ss->options.ip.addr;
sock_saddr(sk) = *valp;
}
switch (ss->p.prot.protocol) {
case T_INET_UDP:
if (t_tst_bit(_T_BIT_UDP_CHECKSUM, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.udp.checksum;
sk->sk_no_check =
(*valp == T_YES) ? UDP_CSUM_DEFAULT : UDP_CSUM_NOXMIT;
}
break;
case T_INET_TCP:
{
struct tcp_opt *tp = tcp_sk(sk);
if (t_tst_bit(_T_BIT_TCP_NODELAY, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.tcp.nodelay;
tp->nonagle = (*valp == T_YES) ? 1 : 0;
}
if (t_tst_bit(_T_BIT_TCP_MAXSEG, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.tcp.maxseg;
if (*valp < 8)
*valp = 8;
if (*valp > MAX_TCP_WINDOW)
*valp = MAX_TCP_WINDOW;
tcp_user_mss(tp) = *valp;
}
if (t_tst_bit(_T_BIT_TCP_KEEPALIVE, ss->options.flags)) {
struct t_kpalive *valp = &ss->options.tcp.keepalive;
if (valp->kp_onoff == T_NO)
valp->kp_timeout = T_UNSPEC;
else {
if (valp->kp_timeout == T_UNSPEC)
valp->kp_timeout =
t_defaults.tcp.keepalive.kp_timeout;
if (valp->kp_timeout < 1)
valp->kp_timeout = 1;
if (valp->kp_timeout > MAX_SCHEDULE_TIMEOUT / 60 / HZ)
valp->kp_timeout = MAX_SCHEDULE_TIMEOUT / 60 / HZ;
}
if (valp->kp_onoff == T_YES)
tp->keepalive_time = valp->kp_timeout * 60 * HZ;
#if defined HAVE_TCP_SET_KEEPALIVE_ADDR
tcp_set_keepalive(sk, valp->kp_onoff == T_YES ? 1 : 0);
#endif
if (valp->kp_onoff == T_YES)
sock_set_keepopen(sk);
else
sock_clr_keepopen(sk);
}
if (t_tst_bit(_T_BIT_TCP_CORK, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.tcp.cork;
(void) valp;
}
if (t_tst_bit(_T_BIT_TCP_KEEPIDLE, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.tcp.keepidle;
(void) valp;
}
if (t_tst_bit(_T_BIT_TCP_KEEPINTVL, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.tcp.keepitvl;
(void) valp;
}
if (t_tst_bit(_T_BIT_TCP_KEEPCNT, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.tcp.keepcnt;
(void) valp;
}
if (t_tst_bit(_T_BIT_TCP_SYNCNT, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.tcp.syncnt;
(void) valp;
}
if (t_tst_bit(_T_BIT_TCP_LINGER2, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.tcp.linger2;
(void) valp;
}
if (t_tst_bit(_T_BIT_TCP_DEFER_ACCEPT, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.tcp.defer_accept;
(void) valp;
}
if (t_tst_bit(_T_BIT_TCP_WINDOW_CLAMP, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.tcp.window_clamp;
(void) valp;
}
if (t_tst_bit(_T_BIT_TCP_INFO, ss->options.flags)) {
}
if (t_tst_bit(_T_BIT_TCP_QUICKACK, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.tcp.quickack;
(void) valp;
}
break;
}
#if defined HAVE_OPENSS7_SCTP
case T_INET_SCTP:
{
struct sctp_opt *sp = sctp_sk(sk);
if (t_tst_bit(_T_BIT_SCTP_NODELAY, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.nodelay;
(void) *valp;
}
if (t_tst_bit(_T_BIT_SCTP_MAXSEG, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.maxseg;
if (*valp < 1)
*valp = 1;
if (*valp > MAX_TCP_WINDOW)
*valp = MAX_TCP_WINDOW;
sp->user_amps = *valp;
}
if (t_tst_bit(_T_BIT_SCTP_CORK, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.cork;
if (sp->nonagle != 1)
sp->nonagle = (*valp == T_YES) ? 2 : 0;
}
if (t_tst_bit(_T_BIT_SCTP_PPI, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.ppi;
sp->ppi = *valp;
}
if (t_tst_bit(_T_BIT_SCTP_SID, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.sid;
sp->sid = *valp;
}
#if 0
if (t_tst_bit(_T_BIT_SCTP_SSN, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.ssn;
}
if (t_tst_bit(_T_BIT_SCTP_TSN, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.tsn;
}
#endif
if (t_tst_bit(_T_BIT_SCTP_RECVOPT, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.recvopt;
if (*valp == T_YES)
sp->cmsg_flags |=
(SCTP_CMSGF_RECVSID | SCTP_CMSGF_RECVPPI |
SCTP_CMSGF_RECVSSN | SCTP_CMSGF_RECVTSN);
else
sp->cmsg_flags &=
~(SCTP_CMSGF_RECVSID | SCTP_CMSGF_RECVPPI |
SCTP_CMSGF_RECVSSN | SCTP_CMSGF_RECVTSN);
}
if (t_tst_bit(_T_BIT_SCTP_COOKIE_LIFE, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.cookie_life;
if (*valp == T_INFINITE)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
if (*valp / HZ > MAX_SCHEDULE_TIMEOUT / 1000)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
sp->ck_life = *valp / 1000 * HZ;
}
if (t_tst_bit(_T_BIT_SCTP_SACK_DELAY, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.sack_delay;
if (*valp == T_INFINITE)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
if (*valp / HZ > MAX_SCHEDULE_TIMEOUT / 1000)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
sp->max_sack = *valp / 1000 * HZ;
}
if (t_tst_bit(_T_BIT_SCTP_PATH_MAX_RETRANS, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.path_max_retrans;
sp->rtx_path = *valp;
}
if (t_tst_bit(_T_BIT_SCTP_ASSOC_MAX_RETRANS, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.assoc_max_retrans;
sp->max_retrans = *valp;
}
if (t_tst_bit(_T_BIT_SCTP_MAX_INIT_RETRIES, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.max_init_retries;
sp->max_inits = *valp;
}
if (t_tst_bit(_T_BIT_SCTP_HEARTBEAT_ITVL, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.heartbeat_itvl;
if (*valp == T_INFINITE)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
if (*valp / HZ > MAX_SCHEDULE_TIMEOUT / 1000)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
sp->hb_itvl = *valp / 1000 * HZ;
#if defined CONFIG_SCTP_THROTTLE_HEARTBEATS
sp->hb_tint = (*valp >> 1) + 1;
#endif
}
if (t_tst_bit(_T_BIT_SCTP_RTO_INITIAL, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.rto_initial;
if (*valp == T_INFINITE)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
if (*valp > sp->rto_max / HZ * 1000)
*valp = sp->rto_max / HZ * 1000;
if (*valp < sp->rto_min / HZ * 1000)
*valp = sp->rto_min / HZ * 1000;
if (*valp / HZ > MAX_SCHEDULE_TIMEOUT / 1000)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
sp->rto_ini = *valp / 1000 * HZ;
}
if (t_tst_bit(_T_BIT_SCTP_RTO_MIN, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.rto_min;
if (*valp == T_INFINITE)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
if (*valp > sp->rto_max / HZ * 1000)
*valp = sp->rto_max / HZ * 1000;
if (*valp > sp->rto_ini / HZ * 1000)
*valp = sp->rto_ini / HZ * 1000;
if (*valp / HZ > MAX_SCHEDULE_TIMEOUT / 1000)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
sp->rto_min = *valp / 1000 * HZ;
}
if (t_tst_bit(_T_BIT_SCTP_RTO_MAX, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.rto_max;
if (*valp == T_INFINITE)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
if (*valp < sp->rto_min / HZ * 1000)
*valp = sp->rto_min / HZ * 1000;
if (*valp < sp->rto_ini / HZ * 1000)
*valp = sp->rto_ini / HZ * 1000;
if (*valp / HZ > MAX_SCHEDULE_TIMEOUT / 1000)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
sp->rto_max = *valp / 1000 * HZ;
}
if (t_tst_bit(_T_BIT_SCTP_OSTREAMS, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.ostreams;
sp->req_ostr = *valp;
}
if (t_tst_bit(_T_BIT_SCTP_ISTREAMS, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.istreams;
sp->max_istr = *valp;
}
if (t_tst_bit(_T_BIT_SCTP_COOKIE_INC, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.cookie_inc;
if (*valp == T_INFINITE)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
if (*valp / HZ > MAX_SCHEDULE_TIMEOUT / 1000)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
sp->ck_inc = *valp / 1000 * HZ;
}
if (t_tst_bit(_T_BIT_SCTP_THROTTLE_ITVL, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.throttle_itvl;
if (*valp == T_INFINITE)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
if (*valp / HZ > MAX_SCHEDULE_TIMEOUT / 1000)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
sp->throttle = *valp / 1000 * HZ;
}
if (t_tst_bit(_T_BIT_SCTP_MAC_TYPE, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.mac_type;
sp->hmac = *valp;
}
if (t_tst_bit(_T_BIT_SCTP_CKSUM_TYPE, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.cksum_type;
sp->cksum = *valp;
}
if (t_tst_bit(_T_BIT_SCTP_HB, ss->options.flags)) {
struct t_sctp_hb *valp = &ss->options.sctp.hb;
if (valp->hb_itvl == T_UNSPEC)
valp->hb_itvl = t_defaults.sctp.hb.hb_itvl;
if (valp->hb_itvl == T_INFINITE)
valp->hb_itvl = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
if (valp->hb_itvl / HZ > MAX_SCHEDULE_TIMEOUT / 1000)
valp->hb_itvl = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
if (valp->hb_itvl < 1000 / HZ)
valp->hb_itvl = 1000 / HZ;
}
if (t_tst_bit(_T_BIT_SCTP_RTO, ss->options.flags)) {
struct t_sctp_rto *valp = &ss->options.sctp.rto;
if (valp->rto_initial == T_INFINITE)
valp->rto_initial = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
if (valp->rto_initial / HZ > MAX_SCHEDULE_TIMEOUT / 1000)
valp->rto_initial = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
if (valp->rto_min == T_INFINITE)
valp->rto_min = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
if (valp->rto_min / HZ > MAX_SCHEDULE_TIMEOUT / 1000)
valp->rto_min = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
if (valp->rto_max == T_INFINITE)
valp->rto_max = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
if (valp->rto_max / HZ > MAX_SCHEDULE_TIMEOUT / 1000)
valp->rto_max = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
}
if (t_tst_bit(_T_BIT_SCTP_STATUS, ss->options.flags)) {
}
if (t_tst_bit(_T_BIT_SCTP_DEBUG, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.debug;
sp->options = *valp;
}
#if defined CONFIG_SCTP_ECN
if (t_tst_bit(_T_BIT_SCTP_ECN, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.ecn;
if (*valp == T_YES)
sp->l_caps |= SCTP_CAPS_ECN;
else
sp->l_caps &= ~SCTP_CAPS_ECN;
}
#endif
#if defined CONFIG_SCTP_ADD_IP || defined CONFIG_SCTP_ADAPTATION_LAYER_INFO
if (t_tst_bit(_T_BIT_SCTP_ALI, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.ali;
if (*valp)
sp->l_caps |= SCTP_CAPS_ALI;
else
sp->l_caps &= ~SCTP_CAPS_ALI;
}
#endif
#if defined CONFIG_SCTP_ADD_IP
if (t_tst_bit(_T_BIT_SCTP_ADD, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.add;
if (*valp == T_YES)
sp->l_caps |= SCTP_CAPS_ADD_IP;
else
sp->l_caps &= ~SCTP_CAPS_ADD_IP;
}
if (t_tst_bit(_T_BIT_SCTP_SET, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.set;
if (*valp == T_YES)
sp->l_caps |= SCTP_CAPS_SET_IP;
else
sp->l_caps &= ~SCTP_CAPS_SET_IP;
}
#if 0
if (t_tst_bit(_T_BIT_SCTP_ADD_IP, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.add_ip;
sctp_add_ip(sk, valp);
}
if (t_tst_bit(_T_BIT_SCTP_DEL_IP, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.del_ip;
sctp_del_ip(sk, valp);
}
if (t_tst_bit(_T_BIT_SCTP_SET_IP, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.set_ip;
sctp_set_ip(sk, valp);
}
#endif
#endif
#if defined CONFIG_SCTP_PARTIAL_RELIABILITY
if (t_tst_bit(_T_BIT_SCTP_PR, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.pr;
sp->prel = *valp;
}
#endif
#if defined CONFIG_SCTP_LIFETIMES || defined CONFIG_SCTP_PARTIAL_RELIABILITY
if (t_tst_bit(_T_BIT_SCTP_LIFETIME, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.lifetime;
if (*valp == T_INFINITE)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
if (*valp / HZ > MAX_SCHEDULE_TIMEOUT / 1000)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
sp->life = *valp / 1000 * HZ;
}
#endif
if (t_tst_bit(_T_BIT_SCTP_DISPOSITION, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.disposition;
sp->disp = *valp;
}
if (t_tst_bit(_T_BIT_SCTP_MAX_BURST, ss->options.flags)) {
t_uscalar_t *valp = &ss->options.sctp.max_burst;
sp->max_burst = *valp;
}
break;
}
#endif
}
}
return (0);
eproto:
swerr();
return (-EPROTO);
}
STATIC int
t_parse_conn_opts(ss_t *ss, const unsigned char *ip, size_t ilen, int request)
{
const struct t_opthdr *ih;
struct sock *sk;
bzero(ss->options.flags, sizeof(ss->options.flags));
if (ip == NULL || ilen == 0)
return (0);
if (!ss || !ss->sock || !(sk = ss->sock->sk))
goto eproto;
for (ih = _T_OPT_FIRSTHDR_OFS(ip, ilen, 0); ih; ih = _T_OPT_NEXTHDR_OFS(ip, ilen, ih, 0)) {
if (ih->len < sizeof(*ih))
goto einval;
switch (ih->level) {
case XTI_GENERIC:
switch (ih->name) {
case XTI_DEBUG:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (((ih->len - sizeof(*ih)) % sizeof(t_uscalar_t)) != 0)
goto einval;
if (ih->len >= sizeof(*ih) + 4 * sizeof(t_uscalar_t))
ss->options.xti.debug[3] = valp[3];
else
ss->options.xti.debug[3] = 0;
if (ih->len >= sizeof(*ih) + 3 * sizeof(t_uscalar_t))
ss->options.xti.debug[2] = valp[2];
else
ss->options.xti.debug[2] = 0;
if (ih->len >= sizeof(*ih) + 2 * sizeof(t_uscalar_t))
ss->options.xti.debug[1] = valp[1];
else
ss->options.xti.debug[1] = 0;
if (ih->len >= sizeof(*ih) + 1 * sizeof(t_uscalar_t))
ss->options.xti.debug[0] = valp[0];
else
ss->options.xti.debug[1] = 0;
t_set_bit(_T_BIT_XTI_DEBUG, ss->options.flags);
continue;
}
case XTI_LINGER:
{
struct t_linger *valp = (struct t_linger *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
if (valp->l_onoff != T_NO && valp->l_onoff != T_YES)
goto einval;
if (valp->l_linger != T_INFINITE && valp->l_linger != T_UNSPEC
&& valp->l_linger < 0)
goto einval;
ss->options.xti.linger = *valp;
t_set_bit(_T_BIT_XTI_LINGER, ss->options.flags);
if (!request)
continue;
if (valp->l_onoff == T_NO)
valp->l_linger = T_UNSPEC;
else {
if (valp->l_linger == T_UNSPEC)
valp->l_linger = t_defaults.xti.linger.l_linger;
if (valp->l_linger == T_INFINITE)
valp->l_linger = MAX_SCHEDULE_TIMEOUT / HZ;
if (valp->l_linger >= MAX_SCHEDULE_TIMEOUT / HZ)
valp->l_linger = MAX_SCHEDULE_TIMEOUT / HZ;
}
if (valp->l_onoff == T_YES) {
sock_set_linger(sk);
sk->sk_lingertime = valp->l_linger * HZ;
} else {
sock_clr_linger(sk);
sk->sk_lingertime = 0;
}
continue;
}
case XTI_RCVBUF:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
ss->options.xti.rcvbuf = *valp;
t_set_bit(_T_BIT_XTI_RCVBUF, ss->options.flags);
if (!request)
continue;
if (*valp > sysctl_rmem_max)
*valp = sysctl_rmem_max;
if (*valp < SOCK_MIN_RCVBUF / 2)
*valp = SOCK_MIN_RCVBUF / 2;
sk->sk_rcvbuf = *valp * 2;
continue;
}
case XTI_RCVLOWAT:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
ss->options.xti.rcvlowat = *valp;
t_set_bit(_T_BIT_XTI_RCVLOWAT, ss->options.flags);
if (!request)
continue;
if (*valp < 1)
*valp = 1;
if (*valp > INT_MAX)
*valp = INT_MAX;
sk->sk_rcvlowat = *valp;
continue;
}
case XTI_SNDBUF:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
ss->options.xti.sndbuf = *valp;
t_set_bit(_T_BIT_XTI_SNDBUF, ss->options.flags);
if (!request)
continue;
if (*valp > sysctl_wmem_max)
*valp = sysctl_wmem_max;
if (*valp < SOCK_MIN_SNDBUF / 2)
*valp = SOCK_MIN_SNDBUF / 2;
sk->sk_sndbuf = *valp * 2;
continue;
}
case XTI_SNDLOWAT:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
ss->options.xti.sndlowat = *valp;
t_set_bit(_T_BIT_XTI_SNDLOWAT, ss->options.flags);
if (!request)
continue;
if (*valp < 1)
*valp = 1;
if (*valp > 1)
*valp = 1;
continue;
}
}
continue;
case T_INET_IP:
if (ss->p.prot.family == PF_INET) {
struct inet_opt *np = inet_sk(sk);
switch (ih->name) {
case T_IP_OPTIONS:
{
unsigned char *valp = (unsigned char *) T_OPT_DATA(ih);
(void) valp;
t_set_bit(_T_BIT_IP_OPTIONS, ss->options.flags);
continue;
}
case T_IP_TOS:
{
unsigned char *valp = (unsigned char *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
ss->options.ip.tos = *valp;
t_set_bit(_T_BIT_IP_TOS, ss->options.flags);
if (!request)
continue;
np->tos = *valp;
continue;
}
case T_IP_TTL:
{
unsigned char *valp = (unsigned char *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
ss->options.ip.ttl = *valp;
t_set_bit(_T_BIT_IP_TTL, ss->options.flags);
if (!request)
continue;
if (*valp < 1)
*valp = 1;
#ifdef HAVE_STRUCT_SOCK_PROTINFO_AF_INET_TTL
np->ttl = *valp;
#else
#ifdef HAVE_STRUCT_SOCK_PROTINFO_AF_INET_UC_TTL
np->uc_ttl = *valp;
#endif
#endif
continue;
}
case T_IP_REUSEADDR:
{
unsigned int *valp = (unsigned int *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
if (*valp != T_NO && *valp != T_YES)
goto einval;
ss->options.ip.reuseaddr = *valp;
t_set_bit(_T_BIT_IP_REUSEADDR, ss->options.flags);
if (!request)
continue;
sk->sk_reuse = (*valp == T_YES) ? 1 : 0;
continue;
}
case T_IP_DONTROUTE:
{
unsigned int *valp = (unsigned int *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
if (*valp != T_NO && *valp != T_YES)
goto einval;
ss->options.ip.dontroute = *valp;
t_set_bit(_T_BIT_IP_DONTROUTE, ss->options.flags);
if (!request)
continue;
if (*valp == T_YES)
sock_set_localroute(sk);
else
sock_clr_localroute(sk);
continue;
}
case T_IP_BROADCAST:
{
unsigned int *valp = (unsigned int *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
if (*valp != T_NO && *valp != T_YES)
goto einval;
ss->options.ip.broadcast = *valp;
t_set_bit(_T_BIT_IP_BROADCAST, ss->options.flags);
if (!request)
continue;
if (*valp == T_YES)
sock_set_broadcast(sk);
else
sock_clr_broadcast(sk);
continue;
}
case T_IP_ADDR:
{
uint32_t *valp = (unsigned int *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
ss->options.ip.addr = *valp;
t_set_bit(_T_BIT_IP_ADDR, ss->options.flags);
if (!request)
continue;
sock_saddr(sk) = *valp;
continue;
}
}
}
continue;
case T_INET_UDP:
if (ss->p.prot.family == PF_INET && ss->p.prot.protocol == T_INET_UDP) {
switch (ih->name) {
case T_UDP_CHECKSUM:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
if (*valp != T_NO && *valp != T_YES)
goto einval;
ss->options.udp.checksum = *valp;
t_set_bit(_T_BIT_UDP_CHECKSUM, ss->options.flags);
if (!request)
continue;
sk->sk_no_check =
(*valp == T_YES) ? UDP_CSUM_DEFAULT : UDP_CSUM_NOXMIT;
continue;
}
}
}
continue;
case T_INET_TCP:
if (ss->p.prot.family == PF_INET && ss->p.prot.protocol == T_INET_TCP) {
struct tcp_opt *tp = tcp_sk(sk);
switch (ih->name) {
case T_TCP_NODELAY:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
if (*valp != T_NO && *valp != T_YES)
goto einval;
ss->options.tcp.nodelay = *valp;
t_set_bit(_T_BIT_TCP_NODELAY, ss->options.flags);
if (!request)
continue;
tp->nonagle = (*valp == T_YES) ? 1 : 0;
continue;
}
case T_TCP_MAXSEG:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
ss->options.tcp.maxseg = *valp;
t_set_bit(_T_BIT_TCP_MAXSEG, ss->options.flags);
if (!request)
continue;
if (*valp < 8)
*valp = 8;
if (*valp > MAX_TCP_WINDOW)
*valp = MAX_TCP_WINDOW;
tcp_user_mss(tp) = *valp;
continue;
}
case T_TCP_KEEPALIVE:
{
struct t_kpalive *valp =
(struct t_kpalive *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
if (valp->kp_onoff != T_YES && valp->kp_onoff != T_NO)
goto einval;
if (valp->kp_timeout != T_INFINITE
&& valp->kp_timeout != T_UNSPEC && valp->kp_timeout < 0)
goto einval;
ss->options.tcp.keepalive = *valp;
t_set_bit(_T_BIT_TCP_KEEPALIVE, ss->options.flags);
if (!request)
continue;
if (valp->kp_onoff == T_NO)
valp->kp_timeout = T_UNSPEC;
else {
if (valp->kp_timeout == T_UNSPEC)
valp->kp_timeout =
t_defaults.tcp.keepalive.kp_timeout;
if (valp->kp_timeout < 1)
valp->kp_timeout = 1;
if (valp->kp_timeout >
MAX_SCHEDULE_TIMEOUT / 60 / HZ)
valp->kp_timeout =
MAX_SCHEDULE_TIMEOUT / 60 / HZ;
}
if (valp->kp_onoff == T_YES)
tp->keepalive_time = valp->kp_timeout * 60 * HZ;
#if defined HAVE_TCP_SET_KEEPALIVE_ADDR
tcp_set_keepalive(sk, valp->kp_onoff == T_YES ? 1 : 0);
#endif
if (valp->kp_onoff == T_YES)
sock_set_keepopen(sk);
else
sock_clr_keepopen(sk);
continue;
}
case T_TCP_CORK:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len != sizeof(*ih) + sizeof(*valp))
goto einval;
if (*valp != T_YES && *valp != T_NO)
goto einval;
ss->options.tcp.cork = *valp;
t_set_bit(_T_BIT_TCP_CORK, ss->options.flags);
if (!request)
continue;
if (*valp == T_YES && tp->nonagle == 0)
tp->nonagle = 2;
if (*valp == T_NO && tp->nonagle == 2)
tp->nonagle = 0;
continue;
}
case T_TCP_KEEPIDLE:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len != sizeof(*ih) + sizeof(*valp))
goto einval;
ss->options.tcp.keepidle = *valp;
t_set_bit(_T_BIT_TCP_KEEPIDLE, ss->options.flags);
if (!request)
continue;
if (*valp < 1)
*valp = 1;
if (*valp > MAX_TCP_KEEPIDLE)
*valp = MAX_TCP_KEEPIDLE;
tp->keepalive_time = *valp * HZ;
continue;
}
case T_TCP_KEEPINTVL:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len != sizeof(*ih) + sizeof(*valp))
goto einval;
ss->options.tcp.keepitvl = *valp;
t_set_bit(_T_BIT_TCP_KEEPINTVL, ss->options.flags);
if (!request)
continue;
if (*valp < 1)
*valp = 1;
if (*valp > MAX_TCP_KEEPINTVL)
*valp = MAX_TCP_KEEPINTVL;
tp->keepalive_intvl = *valp * HZ;
continue;
}
case T_TCP_KEEPCNT:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len != sizeof(*ih) + sizeof(*valp))
goto einval;
ss->options.tcp.keepcnt = *valp;
t_set_bit(_T_BIT_TCP_KEEPCNT, ss->options.flags);
if (!request)
continue;
if (*valp < 1)
*valp = 1;
if (*valp > MAX_TCP_KEEPCNT)
*valp = MAX_TCP_KEEPCNT;
tp->keepalive_probes = *valp;
continue;
}
case T_TCP_SYNCNT:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len != sizeof(*ih) + sizeof(*valp))
goto einval;
ss->options.tcp.syncnt = *valp;
t_set_bit(_T_BIT_TCP_SYNCNT, ss->options.flags);
if (!request)
continue;
if (*valp < 1)
*valp = 1;
if (*valp > MAX_TCP_SYNCNT)
*valp = MAX_TCP_SYNCNT;
sock_syn_retries(sk) = *valp;
continue;
}
case T_TCP_LINGER2:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len != sizeof(*ih) + sizeof(*valp))
goto einval;
ss->options.tcp.linger2 = *valp;
t_set_bit(_T_BIT_TCP_LINGER2, ss->options.flags);
if (!request)
continue;
if (*valp < 0)
tp->linger2 = -1;
else if (*valp > sysctl_tcp_fin_timeout / HZ)
tp->linger2 = 0;
else
tp->linger2 = *valp * HZ;
continue;
}
case T_TCP_DEFER_ACCEPT:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len != sizeof(*ih) + sizeof(*valp))
goto einval;
ss->options.tcp.defer_accept = *valp;
t_set_bit(_T_BIT_TCP_DEFER_ACCEPT, ss->options.flags);
if (!request)
continue;
if (*valp == 0)
sock_defer_accept(sk) = 0;
else {
for (sock_defer_accept(sk) = 0;
sock_defer_accept(sk) < 32
&& *valp >
((TCP_TIMEOUT_INIT /
HZ) << sock_defer_accept(sk));
sock_defer_accept(sk)++) ;
sock_defer_accept(sk)++;
}
continue;
}
case T_TCP_WINDOW_CLAMP:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len != sizeof(*ih) + sizeof(*valp))
goto einval;
ss->options.tcp.window_clamp = *valp;
t_set_bit(_T_BIT_TCP_WINDOW_CLAMP, ss->options.flags);
if (!request)
continue;
if (*valp < SOCK_MIN_RCVBUF / 2)
*valp = SOCK_MIN_RCVBUF / 2;
tp->window_clamp = *valp;
continue;
}
#if 0
case T_TCP_INFO:
{
}
case T_TCP_QUICKACK:
{
}
#endif
}
}
continue;
#if defined HAVE_OPENSS7_SCTP
case T_INET_SCTP:
if (ss->p.prot.family == PF_INET && ss->p.prot.protocol == T_INET_SCTP) {
struct sctp_opt *sp = sctp_sk(sk);
switch (ih->name) {
case T_SCTP_NODELAY:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
if (*valp != T_NO && *valp != T_YES)
goto einval;
ss->options.sctp.nodelay = *valp;
t_set_bit(_T_BIT_SCTP_NODELAY, ss->options.flags);
if (!request)
continue;
continue;
}
case T_SCTP_MAXSEG:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
ss->options.sctp.maxseg = *valp;
t_set_bit(_T_BIT_SCTP_MAXSEG, ss->options.flags);
if (!request)
continue;
if (*valp < 1)
*valp = 1;
if (*valp > MAX_TCP_WINDOW)
*valp = MAX_TCP_WINDOW;
sp->user_amps = *valp;
continue;
}
case T_SCTP_CORK:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
if (*valp != T_NO && *valp != T_YES)
goto einval;
ss->options.sctp.cork = *valp;
t_set_bit(_T_BIT_SCTP_CORK, ss->options.flags);
if (!request)
continue;
if (sp->nonagle != 1)
sp->nonagle = (*valp == T_YES) ? 2 : 0;
continue;
}
case T_SCTP_PPI:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
ss->options.sctp.ppi = *valp;
t_set_bit(_T_BIT_SCTP_PPI, ss->options.flags);
if (!request)
continue;
sp->ppi = *valp;
continue;
}
case T_SCTP_SID:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
if (*valp > sp->n_ostr)
goto einval;
ss->options.sctp.sid = *valp;
t_set_bit(_T_BIT_SCTP_SID, ss->options.flags);
if (!request)
continue;
sp->sid = *valp;
continue;
}
case T_SCTP_SSN:
{
goto einval;
}
case T_SCTP_TSN:
{
goto einval;
}
case T_SCTP_RECVOPT:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
if (*valp != T_NO && *valp != T_YES)
goto einval;
ss->options.sctp.recvopt = *valp;
t_set_bit(_T_BIT_SCTP_RECVOPT, ss->options.flags);
if (!request)
continue;
if (*valp == T_YES)
sp->cmsg_flags |=
(SCTP_CMSGF_RECVSID | SCTP_CMSGF_RECVPPI |
SCTP_CMSGF_RECVSSN | SCTP_CMSGF_RECVTSN);
else
sp->cmsg_flags &=
~(SCTP_CMSGF_RECVSID | SCTP_CMSGF_RECVPPI |
SCTP_CMSGF_RECVSSN | SCTP_CMSGF_RECVTSN);
continue;
}
case T_SCTP_COOKIE_LIFE:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
ss->options.sctp.cookie_life = *valp;
t_set_bit(_T_BIT_SCTP_COOKIE_LIFE, ss->options.flags);
if (!request)
continue;
if (*valp == T_INFINITE)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
if (*valp / HZ > MAX_SCHEDULE_TIMEOUT / 1000)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
sp->ck_life = *valp / 1000 * HZ;
continue;
}
case T_SCTP_SACK_DELAY:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
ss->options.sctp.sack_delay = *valp;
t_set_bit(_T_BIT_SCTP_SACK_DELAY, ss->options.flags);
if (!request)
continue;
if (*valp == T_INFINITE)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
if (*valp / HZ > MAX_SCHEDULE_TIMEOUT / 1000)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
sp->max_sack = *valp / 1000 * HZ;
continue;
}
case T_SCTP_PATH_MAX_RETRANS:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
ss->options.sctp.path_max_retrans = *valp;
t_set_bit(_T_BIT_SCTP_PATH_MAX_RETRANS, ss->options.flags);
if (!request)
continue;
sp->rtx_path = *valp;
continue;
}
case T_SCTP_ASSOC_MAX_RETRANS:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
ss->options.sctp.assoc_max_retrans = *valp;
t_set_bit(_T_BIT_SCTP_ASSOC_MAX_RETRANS, ss->options.flags);
if (!request)
continue;
sp->max_retrans = *valp;
continue;
}
case T_SCTP_MAX_INIT_RETRIES:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
ss->options.sctp.max_init_retries = *valp;
t_set_bit(_T_BIT_SCTP_MAX_INIT_RETRIES, ss->options.flags);
if (!request)
continue;
sp->max_inits = *valp;
continue;
}
case T_SCTP_HEARTBEAT_ITVL:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
ss->options.sctp.heartbeat_itvl = *valp;
t_set_bit(_T_BIT_SCTP_HEARTBEAT_ITVL, ss->options.flags);
if (!request)
continue;
if (*valp == T_INFINITE)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
if (*valp / HZ > MAX_SCHEDULE_TIMEOUT / 1000)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
sp->hb_itvl = *valp / 1000 * HZ;
#if defined CONFIG_SCTP_THROTTLE_HEARTBEATS
sp->hb_tint = (*valp >> 1) + 1;
#endif
continue;
}
case T_SCTP_RTO_INITIAL:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
ss->options.sctp.rto_initial = *valp;
t_set_bit(_T_BIT_SCTP_RTO_INITIAL, ss->options.flags);
if (!request)
continue;
if (*valp == T_INFINITE)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
if (*valp > sp->rto_max / HZ * 1000)
*valp = sp->rto_max / HZ * 1000;
if (*valp < sp->rto_min / HZ * 1000)
*valp = sp->rto_min / HZ * 1000;
if (*valp / HZ > MAX_SCHEDULE_TIMEOUT / 1000)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
sp->rto_ini = *valp / 1000 * HZ;
continue;
}
case T_SCTP_RTO_MIN:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
ss->options.sctp.rto_min = *valp;
t_set_bit(_T_BIT_SCTP_RTO_MIN, ss->options.flags);
if (!request)
continue;
if (*valp == T_INFINITE)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
if (*valp > sp->rto_max / HZ * 1000)
*valp = sp->rto_max / HZ * 1000;
if (*valp > sp->rto_ini / HZ * 1000)
*valp = sp->rto_ini / HZ * 1000;
if (*valp / HZ > MAX_SCHEDULE_TIMEOUT / 1000)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
sp->rto_min = *valp / 1000 * HZ;
continue;
}
case T_SCTP_RTO_MAX:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
ss->options.sctp.rto_max = *valp;
t_set_bit(_T_BIT_SCTP_RTO_MAX, ss->options.flags);
if (!request)
continue;
if (*valp == T_INFINITE)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
if (*valp < sp->rto_min / HZ * 1000)
*valp = sp->rto_min / HZ * 1000;
if (*valp < sp->rto_ini / HZ * 1000)
*valp = sp->rto_ini / HZ * 1000;
if (*valp / HZ > MAX_SCHEDULE_TIMEOUT / 1000)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
sp->rto_max = *valp / 1000 * HZ;
continue;
}
case T_SCTP_OSTREAMS:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
if (*valp < 1 || *valp > 0x0ffff)
goto einval;
ss->options.sctp.ostreams = *valp;
t_set_bit(_T_BIT_SCTP_OSTREAMS, ss->options.flags);
if (!request)
continue;
sp->req_ostr = *valp;
continue;
}
case T_SCTP_ISTREAMS:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
if (*valp < 1 || *valp > 0x0ffff)
goto einval;
ss->options.sctp.istreams = *valp;
t_set_bit(_T_BIT_SCTP_ISTREAMS, ss->options.flags);
if (!request)
continue;
sp->max_istr = *valp;
continue;
}
case T_SCTP_COOKIE_INC:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
ss->options.sctp.cookie_inc = *valp;
t_set_bit(_T_BIT_SCTP_COOKIE_INC, ss->options.flags);
if (!request)
continue;
if (*valp == T_INFINITE)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
if (*valp / HZ > MAX_SCHEDULE_TIMEOUT / 1000)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
sp->ck_inc = *valp / 1000 * HZ;
continue;
}
case T_SCTP_THROTTLE_ITVL:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
ss->options.sctp.throttle_itvl = *valp;
t_set_bit(_T_BIT_SCTP_THROTTLE_ITVL, ss->options.flags);
if (!request)
continue;
if (*valp == T_INFINITE)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
if (*valp / HZ > MAX_SCHEDULE_TIMEOUT / 1000)
*valp = MAX_SCHEDULE_TIMEOUT / 1000 * HZ;
sp->throttle = *valp / 1000 * HZ;
continue;
}
case T_SCTP_MAC_TYPE:
{
t_uscalar_t *valp = (t_uscalar_t *) T_OPT_DATA(ih);
if (ih->len - sizeof(*ih) != sizeof(*valp))
goto einval;
if (*valp != T_SCTP_HMAC_NO |