Commit b4f94e3f authored by David S. Miller's avatar David S. Miller

Merge ssh://nuts.ninka.net//home/davem/src/BK/net-2.5

into kernel.bkbits.net:/home/davem/net-2.5
parents 52a150d8 545ac82c
This diff is collapsed.
......@@ -41,6 +41,16 @@
* - 2002/02/18 Erik Habbinga <erik_habbinga @ hp dot com> :
* - ifr2.ifr_flags was not initialized in the hwaddr_notset case,
* SIOCGIFFLAGS now called before hwaddr_notset test
*
* - 2002/10/31 Tony Cureington <tony.cureington * hp_com> :
* - If the master does not have a hardware address when the first slave
* is enslaved, the master is assigned the hardware address of that
* slave - there is a comment in bonding.c stating "ifenslave takes
* care of this now." This corrects the problem of slaves having
* different hardware addresses in active-backup mode when
* multiple interfaces are specified on a single ifenslave command
* (ifenslave bond0 eth0 eth1).
*
*/
static char *version =
......@@ -131,6 +141,7 @@ main(int argc, char **argv)
sa_family_t master_family;
char **spp, *master_ifname, *slave_ifname;
int hwaddr_notset;
int master_up;
while ((c = getopt_long(argc, argv, "acdfrvV?h", longopts, 0)) != EOF)
switch (c) {
......@@ -300,10 +311,86 @@ main(int argc, char **argv)
return 1;
}
if (hwaddr_notset) { /* we do nothing */
if (hwaddr_notset) {
/* assign the slave hw address to the
* master since it currently does not
* have one; otherwise, slaves may
* have different hw addresses in
* active-backup mode as seen when enslaving
* using "ifenslave bond0 eth0 eth1" because
* hwaddr_notset is set outside this loop.
* TODO: put this and the "else" portion in
* a function.
*/
goterr = 0;
master_up = 0;
if (if_flags.ifr_flags & IFF_UP) {
if_flags.ifr_flags &= ~IFF_UP;
if (ioctl(skfd, SIOCSIFFLAGS,
&if_flags) < 0) {
goterr = 1;
fprintf(stderr,
"Shutting down "
"interface %s failed: "
"%s\n",
master_ifname,
strerror(errno));
} else {
/* we took the master down,
* so we must bring it up
*/
master_up = 1;
}
}
}
else { /* we'll assign master's hwaddr to this slave */
if (!goterr) {
/* get the slaves MAC address */
strncpy(if_hwaddr.ifr_name,
slave_ifname, IFNAMSIZ);
if (ioctl(skfd, SIOCGIFHWADDR,
&if_hwaddr) < 0) {
fprintf(stderr,
"Could not get MAC "
"address of %s: %s\n",
slave_ifname,
strerror(errno));
strncpy(if_hwaddr.ifr_name,
master_ifname,
IFNAMSIZ);
goterr=1;
}
}
if (!goterr) {
strncpy(if_hwaddr.ifr_name,
master_ifname, IFNAMSIZ);
if (ioctl(skfd, SIOCSIFHWADDR,
&if_hwaddr) < 0) {
fprintf(stderr,
"Could not set MAC "
"address of %s: %s\n",
master_ifname,
strerror(errno));
goterr=1;
} else {
hwaddr_notset = 0;
}
}
if (master_up) {
if_flags.ifr_flags |= IFF_UP;
if (ioctl(skfd, SIOCSIFFLAGS,
&if_flags) < 0) {
fprintf(stderr,
"Bringing up interface "
"%s failed: %s\n",
master_ifname,
strerror(errno));
}
}
} else {
/* we'll assign master's hwaddr to this slave */
if (ifr2.ifr_flags & IFF_UP) {
ifr2.ifr_flags &= ~IFF_UP;
if (ioctl(skfd, SIOCSIFFLAGS, &ifr2) < 0) {
......
......@@ -1521,6 +1521,12 @@ M: Kai.Makisara@metla.fi
L: linux-scsi@vger.kernel.org
S: Maintained
SCTP PROTOCOL
P: Jon Grimm
M: jgrimm2@us.ibm.com
L: lksctp-developers@lists.sourceforge.net
S: Supported
SCx200 CPU SUPPORT
P: Christer Weinigel
M: christer@weinigel.se
......
......@@ -2028,9 +2028,11 @@ config PPPOE
help
Support for PPP over Ethernet.
This driver requires a specially patched pppd daemon. The patch to
pppd, along with binaries of a patched pppd package can be found at:
<http://www.shoshin.uwaterloo.ca/~mostrows/>.
This driver requires the latest version of pppd from the CVS
repository at cvs.samba.org. Alternatively, see the
RoaringPenguin package (http://www.roaringpenguin.com/pppoe)
which contains instruction on how to use this driver (under
the heading "Kernel mode PPPoE").
config PPPOATM
tristate "PPP over ATM"
......
This diff is collapsed.
......@@ -5,15 +5,15 @@
* PPPoE --- PPP over Ethernet (RFC 2516)
*
*
* Version: 0.6.11
* Version: 0.7.0
*
* 220102 : Fix module use count on failure in pppoe_create, pppox_sk -acme
* 030700 : Fixed connect logic to allow for disconnect.
* 030700 : Fixed connect logic to allow for disconnect.
* 270700 : Fixed potential SMP problems; we must protect against
* simultaneous invocation of ppp_input
* and ppp_unregister_channel.
* 040800 : Respect reference count mechanisms on net-devices.
* 200800 : fix kfree(skb) in pppoe_rcv (acme)
* 200800 : fix kfree(skb) in pppoe_rcv (acme)
* Module reference count is decremented in the right spot now,
* guards against sock_put not actually freeing the sk
* in pppoe_release.
......@@ -30,13 +30,14 @@
* the original skb that was passed in on success, never on
* failure. Delete the copy of the skb on failure to avoid
* a memory leak.
* 081001 : Misc. cleanup (licence string, non-blocking, prevent
* reference of device on close).
* 121301 : New ppp channels interface; cannot unregister a channel
* from interrupts. Thus, we mark the socket as a ZOMBIE
* and do the unregistration later.
* 081001 : Misc. cleanup (licence string, non-blocking, prevent
* reference of device on close).
* 121301 : New ppp channels interface; cannot unregister a channel
* from interrupts. Thus, we mark the socket as a ZOMBIE
* and do the unregistration later.
* 081002 : seq_file support for proc stuff -acme
*
* 111602 : Merge all 2.4 fixes into 2.5/2.6 tree. Label 2.5/2.6
* as version 0.7. Spacing cleanup.
* Author: Michal Ostrowski <mostrows@speakeasy.net>
* Contributors:
* Arnaldo Carvalho de Melo <acme@conectiva.com.br>
......@@ -381,8 +382,8 @@ int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb)
*
***********************************************************************/
static int pppoe_rcv(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt)
struct net_device *dev,
struct packet_type *pt)
{
struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw;
......@@ -398,7 +399,7 @@ static int pppoe_rcv(struct sk_buff *skb,
}
sk = po->sk;
bh_lock_sock(sk);
bh_lock_sock(sk);
/* Socket state is unknown, must put skb into backlog. */
if (sock_owned_by_user(sk) != 0) {
......@@ -443,8 +444,10 @@ static int pppoe_disc_rcv(struct sk_buff *skb,
* what kind of SKB it is during backlog rcv.
*/
if (sock_owned_by_user(sk) == 0) {
/* We're no longer connect at the PPPOE layer,
* and must wait for ppp channel to disconnect us.
*/
sk->state = PPPOX_ZOMBIE;
pppox_unbind_sock(sk);
}
bh_unlock_sock(sk);
......@@ -583,8 +586,7 @@ int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
if ((sk->state & PPPOX_CONNECTED) && sp->sa_addr.pppoe.sid)
goto end;
/* Check for already disconnected sockets,
on attempts to disconnect */
/* Check for already disconnected sockets, on attempts to disconnect */
error = -EALREADY;
if((sk->state & PPPOX_DEAD) && !sp->sa_addr.pppoe.sid )
goto end;
......@@ -596,7 +598,8 @@ int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
/* Delete the old binding */
delete_item(po->pppoe_pa.sid,po->pppoe_pa.remote);
dev_put(po->pppoe_dev);
if(po->pppoe_dev)
dev_put(po->pppoe_dev);
memset(po, 0, sizeof(struct pppox_opt));
po->sk = sk;
......@@ -994,7 +997,7 @@ static int pppoe_seq_show(struct seq_file *seq, void *v)
po->pppoe_pa.remote[2], po->pppoe_pa.remote[3],
po->pppoe_pa.remote[4], po->pppoe_pa.remote[5], dev_name);
out:
return 0;
return 0;
}
static __inline__ struct pppox_opt *pppoe_get_idx(loff_t pos)
......@@ -1064,10 +1067,10 @@ static int pppoe_seq_open(struct inode *inode, struct file *file)
}
static struct file_operations pppoe_seq_fops = {
.open = pppoe_seq_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
.open = pppoe_seq_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
#endif /* CONFIG_PROC_FS */
......
......@@ -5,9 +5,9 @@
* PPPoE --- PPP over Ethernet (RFC 2516)
*
*
* Version: 0.5.1
* Version: 0.5.2
*
* Author: Michal Ostrowski <mostrows@styx.uwaterloo.ca>
* Author: Michal Ostrowski <mostrows@speakeasy.net>
*
* 051000 : Initialization cleanup
*
......@@ -56,8 +56,8 @@ int register_pppox_proto(int proto_num, struct pppox_proto *pp)
void unregister_pppox_proto(int proto_num)
{
if (proto_num >= 0 && proto_num <= PX_MAX_PROTO) {
proto[proto_num] = NULL;
MOD_DEC_USE_COUNT;
proto[proto_num] = NULL;
MOD_DEC_USE_COUNT;
}
}
......@@ -65,9 +65,9 @@ void pppox_unbind_sock(struct sock *sk)
{
/* Clear connection to ppp device, if attached. */
if (sk->state & PPPOX_BOUND) {
if (sk->state & (PPPOX_BOUND|PPPOX_ZOMBIE)) {
ppp_unregister_channel(&pppox_sk(sk)->chan);
sk->state &= ~PPPOX_BOUND;
sk->state = PPPOX_DEAD;
}
}
......@@ -75,7 +75,7 @@ EXPORT_SYMBOL(register_pppox_proto);
EXPORT_SYMBOL(unregister_pppox_proto);
EXPORT_SYMBOL(pppox_unbind_sock);
static int pppox_ioctl(struct socket* sock, unsigned int cmd,
static int pppox_ioctl(struct socket* sock, unsigned int cmd,
unsigned long arg)
{
struct sock *sk = sock->sk;
......@@ -117,10 +117,10 @@ static int pppox_create(struct socket *sock, int protocol)
int err = 0;
if (protocol < 0 || protocol > PX_MAX_PROTO)
return -EPROTOTYPE;
return -EPROTOTYPE;
if (proto[protocol] == NULL)
return -EPROTONOSUPPORT;
return -EPROTONOSUPPORT;
err = (*proto[protocol]->create)(sock);
......
......@@ -37,9 +37,10 @@
#define BOND_CHECK_MII_STATUS (SIOCGMIIPHY)
#define BOND_MODE_ROUNDROBIN 0
#define BOND_MODE_ACTIVEBACKUP 1
#define BOND_MODE_XOR 2
#define BOND_MODE_ROUNDROBIN 0
#define BOND_MODE_ACTIVEBACKUP 1
#define BOND_MODE_XOR 2
#define BOND_MODE_BROADCAST 3
/* each slave's link has 4 states */
#define BOND_LINK_UP 0 /* link is up and running */
......@@ -74,6 +75,7 @@ typedef struct slave {
struct slave *prev;
struct net_device *dev;
short delay;
unsigned long jiffies;
char link; /* one of BOND_LINK_XXXX */
char state; /* one of BOND_STATE_XXXX */
unsigned short original_flags;
......@@ -93,6 +95,8 @@ typedef struct bonding {
slave_t *next;
slave_t *prev;
slave_t *current_slave;
slave_t *primary_slave;
slave_t *current_arp_slave;
__s32 slave_cnt;
rwlock_t lock;
rwlock_t ptrlock;
......
......@@ -544,7 +544,8 @@ enum {
NET_SCTP_PATH_MAX_RETRANS = 8,
NET_SCTP_MAX_INIT_RETRANSMITS = 9,
NET_SCTP_HB_INTERVAL = 10,
NET_SCTP_MAX_BURST = 11,
NET_SCTP_PRESERVE_ENABLE = 11,
NET_SCTP_MAX_BURST = 12,
};
/* CTL_PROC names: */
......
......@@ -10,6 +10,7 @@
#include <linux/config.h>
#include <linux/rtnetlink.h>
#include <linux/rcupdate.h>
#include <net/neighbour.h>
#include <asm/processor.h>
......@@ -71,6 +72,7 @@ struct dst_entry
#endif
struct dst_ops *ops;
struct rcu_head rcu_head;
char info[0];
};
......
......@@ -123,8 +123,8 @@ extern sctp_protocol_t sctp_proto;
extern struct sock *sctp_get_ctl_sock(void);
extern int sctp_copy_local_addr_list(sctp_protocol_t *, sctp_bind_addr_t *,
sctp_scope_t, int priority, int flags);
extern sctp_pf_t *sctp_get_pf_specific(int family);
extern void sctp_set_pf_specific(int family, sctp_pf_t *);
extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family);
extern int sctp_register_pf(struct sctp_pf *, sa_family_t);
/*
* sctp_socket.c
......
......@@ -140,6 +140,8 @@ sctp_state_fn_t sctp_sf_do_5_2_2_dupinit;
sctp_state_fn_t sctp_sf_do_5_2_4_dupcook;
sctp_state_fn_t sctp_sf_unk_chunk;
sctp_state_fn_t sctp_sf_do_8_5_1_E_sa;
sctp_state_fn_t sctp_sf_cookie_echoed_err;
sctp_state_fn_t sctp_sf_do_5_2_6_stale;
/* Prototypes for primitive event state functions. */
sctp_state_fn_t sctp_sf_do_prm_asoc;
......@@ -175,7 +177,6 @@ sctp_state_fn_t sctp_sf_autoclose_timer_expire;
*/
/* Prototypes for chunk state functions. Not in use. */
sctp_state_fn_t sctp_sf_do_5_2_6_stale;
sctp_state_fn_t sctp_sf_do_9_2_reshutack;
sctp_state_fn_t sctp_sf_do_9_2_reshut;
sctp_state_fn_t sctp_sf_do_9_2_shutack;
......@@ -211,7 +212,7 @@ void sctp_populate_tie_tags(__u8 *cookie, __u32 curTag, __u32 hisTag);
/* Prototypes for chunk-building functions. */
sctp_chunk_t *sctp_make_init(const sctp_association_t *,
const sctp_bind_addr_t *,
int priority);
int priority, int vparam_len);
sctp_chunk_t *sctp_make_init_ack(const sctp_association_t *,
const sctp_chunk_t *,
const int priority,
......@@ -322,9 +323,15 @@ sctp_pack_cookie(const sctp_endpoint_t *, const sctp_association_t *,
const __u8 *, int addrs_len);
sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *,
const sctp_association_t *,
sctp_chunk_t *, int priority, int *err);
sctp_chunk_t *, int priority, int *err,
sctp_chunk_t **err_chk_p);
int sctp_addip_addr_config(sctp_association_t *, sctp_param_t,
struct sockaddr_storage*, int);
void sctp_send_stale_cookie_err(const sctp_endpoint_t *ep,
const sctp_association_t *asoc,
const sctp_chunk_t *chunk,
sctp_cmd_seq_t *commands,
sctp_chunk_t *err_chunk);
/* 3rd level prototypes */
__u32 sctp_generate_tag(const sctp_endpoint_t *);
......
......@@ -42,6 +42,7 @@
* Sridhar Samudrala <sri@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com>
* Dajiang Zhang <dajiang.zhang@nokia.com>
* Ardelle Fan <ardelle.fan@intel.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
......@@ -182,6 +183,9 @@ struct SCTP_protocol {
/* Valid.Cookie.Life - 60 seconds */
int valid_cookie_life;
/* Whether Cookie Preservative is enabled(1) or not(0) */
int cookie_preserve_enable;
/* Association.Max.Retrans - 10 attempts
* Path.Max.Retrans - 5 attempts (per destination address)
......@@ -234,7 +238,7 @@ struct SCTP_protocol {
* Pointers to address related SCTP functions.
* (i.e. things that depend on the address family.)
*/
typedef struct sctp_func {
struct sctp_af {
int (*queue_xmit) (struct sk_buff *skb);
int (*setsockopt) (struct sock *sk,
int level,
......@@ -259,27 +263,34 @@ typedef struct sctp_func {
void (*from_skb) (union sctp_addr *,
struct sk_buff *skb,
int saddr);
void (*from_sk) (union sctp_addr *,
struct sock *sk);
void (*to_sk) (union sctp_addr *,
struct sock *sk);
int (*addr_valid) (union sctp_addr *);
sctp_scope_t (*scope) (union sctp_addr *);
void (*inaddr_any) (union sctp_addr *, unsigned short);
int (*is_any) (const union sctp_addr *);
int (*available) (const union sctp_addr *);
__u16 net_header_len;
int sockaddr_len;
sa_family_t sa_family;
struct list_head list;
} sctp_func_t;
};
sctp_func_t *sctp_get_af_specific(sa_family_t);
struct sctp_af *sctp_get_af_specific(sa_family_t);
int sctp_register_af(struct sctp_af *);
/* Protocol family functions. */
typedef struct sctp_pf {
void (*event_msgname)(sctp_ulpevent_t *, char *, int *);
void (*skb_msgname)(struct sk_buff *, char *, int *);
int (*af_supported)(sa_family_t);
void (*skb_msgname) (struct sk_buff *, char *, int *);
int (*af_supported) (sa_family_t);
int (*cmp_addr) (const union sctp_addr *,
const union sctp_addr *,
struct sctp_opt *);
struct sctp_func *af;
int (*bind_verify) (struct sctp_opt *, union sctp_addr *);
struct sctp_af *af;
} sctp_pf_t;
/* SCTP Socket type: UDP or TCP style. */
......@@ -623,7 +634,7 @@ struct SCTP_transport {
union sctp_addr ipaddr;
/* These are the functions we call to handle LLP stuff. */
sctp_func_t *af_specific;
struct sctp_af *af_specific;
/* Which association do we belong to? */
sctp_association_t *asoc;
......@@ -1271,7 +1282,6 @@ struct SCTP_association {
/* The cookie life I award for any cookie. */
struct timeval cookie_life;
__u32 cookie_preserve;
/* Overall : The overall association error count.
* Error Count : [Clear this any time I get something.]
......@@ -1350,6 +1360,9 @@ struct SCTP_association {
*/
__u32 rwnd;
/* This is the last advertised value of rwnd over a SACK chunk. */
__u32 a_rwnd;
/* Number of bytes by which the rwnd has slopped. The rwnd is allowed
* to slop over a maximum of the association's frag_point.
*/
......
......@@ -574,7 +574,15 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
/* Release those devices we held, or Alexey will kill me. */
if (info->indev) dev_put(info->indev);
if (info->outdev) dev_put(info->outdev);
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
if (skb->nf_bridge) {
if (skb->nf_bridge->physindev)
dev_put(skb->nf_bridge->physindev);
if (skb->nf_bridge->physoutdev)
dev_put(skb->nf_bridge->physoutdev);
}
#endif
kfree(info);
return;
}
......
......@@ -207,13 +207,13 @@ static struct pktgen_info pginfos[MAX_PKTGEN];
/** Convert to miliseconds */
inline __u64 tv_to_ms(const struct timeval* tv) {
static inline __u64 tv_to_ms(const struct timeval* tv) {
__u64 ms = tv->tv_usec / 1000;
ms += (__u64)tv->tv_sec * (__u64)1000;
return ms;
}
inline __u64 getCurMs(void) {
static inline __u64 getCurMs(void) {
struct timeval tv;
do_gettimeofday(&tv);
return tv_to_ms(&tv);
......@@ -1277,7 +1277,7 @@ static int proc_write(struct file *file, const char *user_buffer,
}
int create_proc_dir(void)
static int create_proc_dir(void)
{
int len;
/* does proc_dir already exists */
......@@ -1295,7 +1295,7 @@ int create_proc_dir(void)
return 1;
}
int remove_proc_dir(void)
static int remove_proc_dir(void)
{
remove_proc_entry(PG_PROC_DIR, proc_net);
return 1;
......
This diff is collapsed.
......@@ -2236,6 +2236,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
goto get_req;
}
read_unlock_bh(&tp->syn_wait_lock);
sk = sk->next;
}
if (++st->bucket < TCP_LHTABLE_SIZE) {
sk = tcp_listening_hash[st->bucket];
......
......@@ -871,6 +871,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
}
if (!ndisc_parse_options(opt, optlen, &ndopts)) {
in6_dev_put(in6_dev);
if (net_ratelimit())
ND_PRINTK2(KERN_WARNING
"ICMP6 RA: invalid ND option, ignored.\n");
......
/*
* net/key/pfkeyv2.c An implemenation of PF_KEYv2 sockets.
* net/key/af_key.c An implementation of PF_KEYv2 sockets.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......
......@@ -128,8 +128,9 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc,
asoc->state_timestamp = jiffies;
/* Set things that have constant value. */
asoc->cookie_life.tv_sec = SCTP_DEFAULT_COOKIE_LIFE_SEC;
asoc->cookie_life.tv_usec = SCTP_DEFAULT_COOKIE_LIFE_USEC;
asoc->cookie_life.tv_sec = sctp_proto.valid_cookie_life / HZ;
asoc->cookie_life.tv_usec = (sctp_proto.valid_cookie_life % HZ) *
1000000L / HZ;
asoc->pmtu = 0;
asoc->frag_point = 0;
......@@ -185,6 +186,8 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc,
else
asoc->rwnd = sk->rcvbuf;
asoc->a_rwnd = 0;
asoc->rwnd_over = 0;
/* Use my own max window until I learn something better. */
......@@ -642,7 +645,7 @@ __u16 __sctp_association_get_next_ssn(sctp_association_t *asoc, __u16 sid)
int sctp_cmp_addr_exact(const union sctp_addr *ss1,
const union sctp_addr *ss2)
{
struct sctp_func *af;
struct sctp_af *af;
af = sctp_get_af_specific(ss1->sa.sa_family);
if (!af)
......
......@@ -327,7 +327,7 @@ static int sctp_copy_one_addr(sctp_bind_addr_t *dest, union sctp_addr *addr,
/* Is this a wildcard address? */
int sctp_is_any(const union sctp_addr *addr)
{
struct sctp_func *af = sctp_get_af_specific(addr->sa.sa_family);
struct sctp_af *af = sctp_get_af_specific(addr->sa.sa_family);
if (!af)
return 0;
return af->is_any(addr);
......@@ -362,7 +362,7 @@ int sctp_in_scope(const union sctp_addr *addr, sctp_scope_t scope)
/* What is the scope of 'addr'? */
sctp_scope_t sctp_scope(const union sctp_addr *addr)
{
struct sctp_func *af;
struct sctp_af *af;
af = sctp_get_af_specific(addr->sa.sa_family);
if (!af)
......
......@@ -42,6 +42,7 @@
* Hui Huang <hui.huang@nokia.com>
* Daisy Chang <daisyc@us.ibm.com>
* Sridhar Samudrala <sri@us.ibm.com>
* Ardelle Fan <ardelle.fan@intel.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
......@@ -96,7 +97,7 @@ int sctp_rcv(struct sk_buff *skb)
struct sctphdr *sh;
union sctp_addr src;
union sctp_addr dest;
struct sctp_func *af;
struct sctp_af *af;
int ret = 0;
if (skb->pkt_type!=PACKET_HOST)
......@@ -279,6 +280,7 @@ int sctp_rcv_ootb(struct sk_buff *skb)
{
sctp_chunkhdr_t *ch;
__u8 *ch_end;
sctp_errhdr_t *err;
ch = (sctp_chunkhdr_t *) skb->data;
......@@ -308,8 +310,9 @@ int sctp_rcv_ootb(struct sk_buff *skb)
goto discard;
if (ch->type == SCTP_CID_ERROR) {
/* FIXME - Need to check the "Stale cookie" ERROR. */
goto discard;
err = (sctp_errhdr_t *)(ch + sizeof(sctp_chunkhdr_t));
if (SCTP_ERROR_STALE_COOKIE == err->cause)
goto discard;
}
ch = (sctp_chunkhdr_t *) ch_end;
......
......@@ -76,8 +76,19 @@
#include <asm/uaccess.h>
/* FIXME: Cleanup so we don't need TEST_FRAME here. */
#ifndef TEST_FRAME
extern struct notifier_block sctp_inetaddr_notifier;
/* FIXME: This macro needs to be moved to a common header file. */
#define NIP6(addr) \
ntohs((addr)->s6_addr16[0]), \
ntohs((addr)->s6_addr16[1]), \
ntohs((addr)->s6_addr16[2]), \
ntohs((addr)->s6_addr16[3]), \
ntohs((addr)->s6_addr16[4]), \
ntohs((addr)->s6_addr16[5]), \
ntohs((addr)->s6_addr16[6]), \
ntohs((addr)->s6_addr16[7])
/* FIXME: Comments. */
static inline void sctp_v6_err(struct sk_buff *skb,
struct inet6_skb_parm *opt,
......@@ -92,13 +103,38 @@ static inline int sctp_v6_xmit(struct sk_buff *skb)
struct sock *sk = skb->sk;
struct ipv6_pinfo *np = inet6_sk(sk);
struct flowi fl;
struct dst_entry *dst;
struct dst_entry *dst = skb->dst;
struct rt6_info *rt6 = (struct rt6_info *)dst;
struct in6_addr saddr;
int err = 0;
int err;
fl.proto = sk->protocol;
fl.fl6_dst = &np->daddr;
fl.fl6_src = NULL;
fl.fl6_dst = &rt6->rt6i_dst.addr;
/* FIXME: Currently, ip6_route_output() doesn't fill in the source
* address in the returned route entry. So we call ipv6_get_saddr()
* to get an appropriate source address. It is possible that this address
* may not be part of the bind address list of the association.
* Once ip6_route_ouput() is fixed so that it returns a route entry
* with an appropriate source address, the following if condition can
* be removed. With ip6_route_output() returning a source address filled
* route entry, sctp_transport_route() can do real source address
* selection for v6.
*/
if (ipv6_addr_any(&rt6->rt6i_src.addr)) {
err = ipv6_get_saddr(dst, fl.fl6_dst, &saddr);
if (err) {
printk(KERN_ERR "%s: No saddr available for "
"DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
__FUNCTION__, NIP6(fl.fl6_src));
return err;
}
fl.fl6_src = &saddr;
} else {
fl.fl6_src = &rt6->rt6i_src.addr;
}
fl.fl6_flowlabel = np->flow_label;
IP6_ECN_flow_xmit(sk, fl.fl6_flowlabel);
......@@ -111,63 +147,8 @@ static inline int sctp_v6_xmit(struct sk_buff *skb)
fl.nl_u.ip6_u.daddr = rt0->addr;
}
dst = __sk_dst_check(sk, np->dst_cookie);
if (dst == NULL) {
dst = ip6_route_output(sk, &fl);
if (dst->error) {
sk->err_soft = -dst->error;
dst_release(dst);
return -sk->err_soft;
}
ip6_dst_store(sk, dst, NULL);
}
skb->dst = dst_clone(dst);
/* FIXME: This is all temporary until real source address
* selection is done.
*/
if (ipv6_addr_any(&np->saddr)) {
err = ipv6_get_saddr(dst, fl.fl6_dst, &saddr);
if (err)
printk(KERN_ERR "sctp_v6_xmit: no saddr available\n");
/* FIXME: This is a workaround until we get
* real source address selection done. This is here
* to disallow loopback when the scoping rules have
* not bound loopback to the endpoint.
*/
if (sctp_ipv6_addr_type(&saddr) & IPV6_ADDR_LOOPBACK) {
if (!(sctp_ipv6_addr_type(&np->daddr) &
IPV6_ADDR_LOOPBACK)) {
ipv6_addr_copy(&saddr, &np->daddr);
}
}
fl.fl6_src = &saddr;
} else {
fl.fl6_src = &np->saddr;
}
/* Restore final destination back after routing done */
fl.nl_u.ip6_u.daddr = &np->daddr;
return ip6_xmit(sk, skb, &fl, np->opt);
}
#endif /* TEST_FRAME */
/* FIXME: This macro needs to be moved to a common header file. */
#define NIP6(addr) \
ntohs((addr)->s6_addr16[0]), \
ntohs((addr)->s6_addr16[1]), \
ntohs((addr)->s6_addr16[2]), \
ntohs((addr)->s6_addr16[3]), \
ntohs((addr)->s6_addr16[4]), \
ntohs((addr)->s6_addr16[5]), \
ntohs((addr)->s6_addr16[6]), \
ntohs((addr)->s6_addr16[7])
/* Returns the dst cache entry for the given source and destination ip
* addresses.
......@@ -176,7 +157,7 @@ struct dst_entry *sctp_v6_get_dst(union sctp_addr *daddr,
union sctp_addr *saddr)
{
struct dst_entry *dst;
struct flowi fl = {
struct flowi fl = {
.nl_u = { .ip6_u = { .daddr = &daddr->v6.sin6_addr, } } };
......@@ -261,6 +242,20 @@ static void sctp_v6_from_skb(union sctp_addr *addr,struct sk_buff *skb,
ipv6_addr_copy(&addr->v6.sin6_addr, from);
}
/* Initialize an sctp_addr from a socket. */
static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk)
{
addr->v6.sin6_family = AF_INET6;
addr->v6.sin6_port = inet_sk(sk)->num;
addr->v6.sin6_addr = inet6_sk(sk)->rcv_saddr;
}
/* Initialize sk->rcv_saddr from sctp_addr. */
static void sctp_v6_to_sk(union sctp_addr *addr, struct sock *sk)
{
inet6_sk(sk)->rcv_saddr = addr->v6.sin6_addr;
}
/* Initialize a sctp_addr from a dst_entry. */
static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst)
{
......@@ -270,15 +265,15 @@ static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst)
}
/* Compare addresses exactly. Well.. almost exactly; ignore scope_id
* for now. FIXME.
* for now. FIXME: v4-mapped-v6.
*/
static int sctp_v6_cmp_addr(const union sctp_addr *addr1,
static int sctp_v6_cmp_addr(const union sctp_addr *addr1,
const union sctp_addr *addr2)
{
int match;
if (addr1->sa.sa_family != addr2->sa.sa_family)
return 0;
match = !ipv6_addr_cmp((struct in6_addr *)&addr1->v6.sin6_addr,
match = !ipv6_addr_cmp((struct in6_addr *)&addr1->v6.sin6_addr,
(struct in6_addr *)&addr2->v6.sin6_addr);
return match;
......@@ -300,6 +295,22 @@ static int sctp_v6_is_any(const union sctp_addr *addr)
return IPV6_ADDR_ANY == type;
}
/* Should this be available for binding? */
static int sctp_v6_available(const union sctp_addr *addr)
{
int type;
struct in6_addr *in6 = (struct in6_addr *)&addr->v6.sin6_addr;
type = ipv6_addr_type(in6);
if (IPV6_ADDR_ANY == type)
return 1;
if (!(type & IPV6_ADDR_UNICAST))
return 0;
return ipv6_chk_addr(in6, NULL);
}
/* This function checks if the address is a valid address to be used for
* SCTP.
*
......@@ -309,7 +320,7 @@ static int sctp_v6_is_any(const union sctp_addr *addr)
*/
static int sctp_v6_addr_valid(union sctp_addr *addr)
{
int ret = sctp_ipv6_addr_type(&addr->v6.sin6_addr);
int ret = ipv6_addr_type(&addr->v6.sin6_addr);
/* FIXME: v4-mapped-v6 address support. */
......@@ -442,14 +453,14 @@ static int sctp_inet6_af_supported(sa_family_t family)
/* Address matching with wildcards allowed. This extra level
* of indirection lets us choose whether a PF_INET6 should
* disallow any v4 addresses if we so choose.
* disallow any v4 addresses if we so choose.
*/
static int sctp_inet6_cmp_addr(const union sctp_addr *addr1,
static int sctp_inet6_cmp_addr(const union sctp_addr *addr1,
const union sctp_addr *addr2,
struct sctp_opt *opt)
{
struct sctp_func *af1, *af2;
struct sctp_af *af1, *af2;
af1 = sctp_get_af_specific(addr1->sa.sa_family);
af2 = sctp_get_af_specific(addr2->sa.sa_family);
......@@ -461,11 +472,25 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1,
if (addr1->sa.sa_family != addr2->sa.sa_family)
return 0;
return af1->cmp_addr(addr1, addr2);
}
/* Verify that the provided sockaddr looks bindable. Common verification,
* has already been taken care of.
*/
static int sctp_inet6_bind_verify(struct sctp_opt *opt, union sctp_addr *addr)
{
struct sctp_af *af;
/* ASSERT: address family has already been verified. */
if (addr->sa.sa_family != AF_INET6) {
af = sctp_get_af_specific(addr->sa.sa_family);
} else
af = opt->pf->af;
return af->available(addr);
}
static struct proto_ops inet6_seqpacket_ops = {
.family = PF_INET6,
......@@ -501,29 +526,33 @@ static struct inet6_protocol sctpv6_protocol = {
.err_handler = sctp_v6_err,
};
static sctp_func_t sctp_ipv6_specific = {
static struct sctp_af sctp_ipv6_specific = {
.queue_xmit = sctp_v6_xmit,
.setsockopt = ipv6_setsockopt,
.setsockopt = ipv6_setsockopt,
.getsockopt = ipv6_getsockopt,
.get_dst = sctp_v6_get_dst,
.copy_addrlist = sctp_v6_copy_addrlist,
.from_skb = sctp_v6_from_skb,
.from_sk = sctp_v6_from_sk,
.to_sk = sctp_v6_to_sk,
.dst_saddr = sctp_v6_dst_saddr,
.cmp_addr = sctp_v6_cmp_addr,
.scope = sctp_v6_scope,
.addr_valid = sctp_v6_addr_valid,
.inaddr_any = sctp_v6_inaddr_any,
.is_any = sctp_v6_is_any,
.available = sctp_v6_available,
.net_header_len = sizeof(struct ipv6hdr),
.sockaddr_len = sizeof(struct sockaddr_in6),
.sa_family = AF_INET6,
};
static sctp_pf_t sctp_pf_inet6_specific = {
static struct sctp_pf sctp_pf_inet6_specific = {
.event_msgname = sctp_inet6_event_msgname,
.skb_msgname = sctp_inet6_skb_msgname,
.af_supported = sctp_inet6_af_supported,
.cmp_addr = sctp_inet6_cmp_addr,
.bind_verify = sctp_inet6_bind_verify,
.af = &sctp_ipv6_specific,
};
......@@ -538,11 +567,13 @@ int sctp_v6_init(void)
inet6_register_protosw(&sctpv6_protosw);
/* Register the SCTP specfic PF_INET6 functions. */
sctp_set_pf_specific(PF_INET6, &sctp_pf_inet6_specific);
sctp_register_pf(&sctp_pf_inet6_specific, PF_INET6);
/* Register the SCTP specfic AF_INET6 functions. */
sctp_register_af(&sctp_ipv6_specific);
/* Fill in address family info. */
INIT_LIST_HEAD(&sctp_ipv6_specific.list);
list_add_tail(&sctp_ipv6_specific.list, &sctp_proto.address_families);
/* Register notifier for inet6 address additions/deletions. */
register_inet6addr_notifier(&sctp_inetaddr_notifier);
return 0;
}
......@@ -553,4 +584,5 @@ void sctp_v6_exit(void)
list_del(&sctp_ipv6_specific.list);
inet6_del_protocol(&sctpv6_protocol, IPPROTO_SCTP);
inet6_unregister_protosw(&sctpv6_protosw);
unregister_inet6addr_notifier(&sctp_inetaddr_notifier);
}
......@@ -40,6 +40,7 @@
* Jon Grimm <jgrimm@us.ibm.com>
* Sridhar Samudrala <sri@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com>
* Ardelle Fan <ardelle.fan@intel.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
......@@ -67,8 +68,10 @@ struct sctp_mib sctp_statistics[NR_CPUS * 2];
*/
static struct socket *sctp_ctl_socket;
static sctp_pf_t *sctp_pf_inet6_specific;
static sctp_pf_t *sctp_pf_inet_specific;
static struct sctp_pf *sctp_pf_inet6_specific;
static struct sctp_pf *sctp_pf_inet_specific;
static struct sctp_af *sctp_af_v4_specific;
static struct sctp_af *sctp_af_v6_specific;
extern struct net_proto_family inet_family_ops;
......@@ -140,12 +143,12 @@ static void __sctp_get_local_addr_list(sctp_protocol_t *proto)
{
struct net_device *dev;
struct list_head *pos;
struct sctp_func *af;
struct sctp_af *af;
read_lock(&dev_base_lock);
for (dev = dev_base; dev; dev = dev->next) {
list_for_each(pos, &proto->address_families) {
af = list_entry(pos, sctp_func_t, list);
af = list_entry(pos, struct sctp_af, list);
af->copy_addrlist(&proto->local_addr_list, dev);
}
}
......@@ -251,7 +254,6 @@ struct dst_entry *sctp_v4_get_dst(union sctp_addr *daddr,
return &rt->u.dst;
}
/* Initialize a sctp_addr from in incoming skb. */
static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb,
int is_saddr)
......@@ -274,6 +276,21 @@ static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb,
memcpy(&addr->v4.sin_addr.s_addr, from, sizeof(struct in_addr));
}
/* Initialize an sctp_addr from a socket. */
static void sctp_v4_from_sk(union sctp_addr *addr, struct sock *sk)
{
addr->v4.sin_family = AF_INET;
addr->v4.sin_port = inet_sk(sk)->num;
addr->v4.sin_addr.s_addr = inet_sk(sk)->rcv_saddr;
}
/* Initialize sk->rcv_saddr from sctp_addr. */
static void sctp_v4_to_sk(union sctp_addr *addr, struct sock *sk)
{
inet_sk(sk)->rcv_saddr = addr->v4.sin_addr.s_addr;
}
/* Initialize a sctp_addr from a dst_entry. */
static void sctp_v4_dst_saddr(union sctp_addr *saddr, struct dst_entry *dst)
{
......@@ -311,7 +328,7 @@ static int sctp_v4_is_any(const union sctp_addr *addr)
}
/* This function checks if the address is a valid address to be used for
* SCTP.
* SCTP binding.
*
* Output:
* Return 0 - If the address is a non-unicast or an illegal address.
......@@ -326,6 +343,18 @@ static int sctp_v4_addr_valid(union sctp_addr *addr)
return 1;
}
/* Should this be available for binding? */
static int sctp_v4_available(const union sctp_addr *addr)
{
int ret = inet_addr_type(addr->v4.sin_addr.s_addr);
/* FIXME: ip_nonlocal_bind sysctl support. */
if (addr->v4.sin_addr.s_addr != INADDR_ANY && ret != RTN_LOCAL)
return 0;
return 1;
}
/* Checking the loopback, private and other address scopes as defined in
* RFC 1918. The IPv4 scoping is based on the draft for SCTP IPv4
* scoping <draft-stewart-tsvwg-sctp-ipv4-00.txt>.
......@@ -365,11 +394,11 @@ static sctp_scope_t sctp_v4_scope(union sctp_addr *addr)
return retval;
}
/* Event handler for inet device events.
/* Event handler for inet address addition/deletion events.
* Basically, whenever there is an event, we re-build our local address list.
*/
static int sctp_netdev_event(struct notifier_block *this, unsigned long event,
void *ptr)
static int sctp_inetaddr_event(struct notifier_block *this, unsigned long event,
void *ptr)
{
long flags __attribute__ ((unused));
......@@ -405,29 +434,42 @@ int sctp_ctl_sock_init(void)
return 0;
}
/* Register address family specific functions. */
int sctp_register_af(struct sctp_af *af)
{
switch (af->sa_family) {
case AF_INET:
if (sctp_af_v4_specific)
return 0;
sctp_af_v4_specific = af;
break;
case AF_INET6:
if (sctp_af_v6_specific)
return 0;
sctp_af_v6_specific = af;
break;
default:
return 0;
}
INIT_LIST_HEAD(&af->list);
list_add_tail(&af->list, &sctp_proto.address_families);
return 1;
}
/* Get the table of functions for manipulating a particular address
* family.
*/
sctp_func_t *sctp_get_af_specific(sa_family_t family)
struct sctp_af *sctp_get_af_specific(sa_family_t family)
{
struct list_head *pos;
sctp_protocol_t *proto = sctp_get_protocol();
struct sctp_func *retval, *af;
retval = NULL;
/* Cycle through all AF specific functions looking for a
* match.
*/
list_for_each(pos, &proto->address_families) {
af = list_entry(pos, sctp_func_t, list);
if (family == af->sa_family) {
retval = af;
break;
}
switch (family) {
case AF_INET:
return sctp_af_v4_specific;
case AF_INET6:
return sctp_af_v6_specific;
default:
return NULL;
}
return retval;
}
/* Common code to initialize a AF_INET msg_name. */
......@@ -495,21 +537,28 @@ static int sctp_inet_cmp_addr(const union sctp_addr *addr1,
return 0;
}
/* Verify that provided sockaddr looks bindable. Common verification has
* already been taken care of.
*/
static int sctp_inet_bind_verify(struct sctp_opt *opt, union sctp_addr *addr)
{
return sctp_v4_available(addr);
}
struct sctp_func sctp_ipv4_specific;
struct sctp_af sctp_ipv4_specific;
static sctp_pf_t sctp_pf_inet = {
static struct sctp_pf sctp_pf_inet = {
.event_msgname = sctp_inet_event_msgname,
.skb_msgname = sctp_inet_skb_msgname,
.af_supported = sctp_inet_af_supported,
.cmp_addr = sctp_inet_cmp_addr,
.bind_verify = sctp_inet_bind_verify,
.af = &sctp_ipv4_specific,
};
/* Registration for netdev events. */
struct notifier_block sctp_netdev_notifier = {
.notifier_call = sctp_netdev_event,
/* Notifier for inetaddr addition/deletion events. */
struct notifier_block sctp_inetaddr_notifier = {
.notifier_call = sctp_inetaddr_event,
};
/* Socket operations. */
......@@ -551,25 +600,28 @@ static struct inet_protocol sctp_protocol = {
};
/* IPv4 address related functions. */
struct sctp_func sctp_ipv4_specific = {
struct sctp_af sctp_ipv4_specific = {
.queue_xmit = ip_queue_xmit,
.setsockopt = ip_setsockopt,
.getsockopt = ip_getsockopt,
.get_dst = sctp_v4_get_dst,
.copy_addrlist = sctp_v4_copy_addrlist,
.from_skb = sctp_v4_from_skb,
.from_sk = sctp_v4_from_sk,
.to_sk = sctp_v4_to_sk,
.dst_saddr = sctp_v4_dst_saddr,
.cmp_addr = sctp_v4_cmp_addr,
.addr_valid = sctp_v4_addr_valid,
.inaddr_any = sctp_v4_inaddr_any,
.is_any = sctp_v4_is_any,
.available = sctp_v4_available,
.scope = sctp_v4_scope,
.net_header_len = sizeof(struct iphdr),
.sockaddr_len = sizeof(struct sockaddr_in),
.sa_family = AF_INET,
};
sctp_pf_t *sctp_get_pf_specific(int family) {
struct sctp_pf *sctp_get_pf_specific(sa_family_t family) {
switch (family) {
case PF_INET:
......@@ -581,20 +633,24 @@ sctp_pf_t *sctp_get_pf_specific(int family) {
}
}
/* Set the PF specific function table. */
void sctp_set_pf_specific(int family, sctp_pf_t *pf)
/* Register the PF specific function table. */
int sctp_register_pf(struct sctp_pf *pf, sa_family_t family)
{
switch (family) {
case PF_INET:
if (sctp_pf_inet_specific)
return 0;
sctp_pf_inet_specific = pf;
break;
case PF_INET6:
if (sctp_pf_inet6_specific)
return 0;
sctp_pf_inet6_specific = pf;
break;
default:
BUG();
break;
return 0;
}
return 1;
}
/* Initialize the universe into something sensible. */
......@@ -617,7 +673,7 @@ int sctp_init(void)
sctp_dbg_objcnt_init();
/* Initialize the SCTP specific PF functions. */
sctp_set_pf_specific(PF_INET, &sctp_pf_inet);
sctp_register_pf(&sctp_pf_inet, PF_INET);
/*
* 14. Suggested SCTP Protocol Parameter Values
*/
......@@ -636,6 +692,9 @@ int sctp_init(void)
/* Valid.Cookie.Life - 60 seconds */
sctp_proto.valid_cookie_life = 60 * HZ;
/* Whether Cookie Preservative is enabled(1) or not(0) */
sctp_proto.cookie_preserve_enable = 1;
/* Max.Burst - 4 */
sctp_proto.max_burst = SCTP_MAX_BURST;
......@@ -709,8 +768,7 @@ int sctp_init(void)
sctp_sysctl_register();
INIT_LIST_HEAD(&sctp_proto.address_families);
INIT_LIST_HEAD(&sctp_ipv4_specific.list);
list_add_tail(&sctp_ipv4_specific.list, &sctp_proto.address_families);
sctp_register_af(&sctp_ipv4_specific);
status = sctp_v6_init();
if (status)
......@@ -727,7 +785,9 @@ int sctp_init(void)
INIT_LIST_HEAD(&sctp_proto.local_addr_list);
sctp_proto.local_addr_lock = SPIN_LOCK_UNLOCKED;
register_inetaddr_notifier(&sctp_netdev_notifier);
/* Register notifier for inet address additions/deletions. */
register_inetaddr_notifier(&sctp_inetaddr_notifier);
sctp_get_local_addr_list(&sctp_proto);
return 0;
......@@ -757,8 +817,10 @@ void sctp_exit(void)
* up all the remaining associations and all that memory.
*/
/* Unregister notifier for inet address additions/deletions. */
unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
/* Free the local address list. */
unregister_inetaddr_notifier(&sctp_netdev_notifier);
sctp_free_local_addr_list(&sctp_proto);
/* Free the control endpoint. */
......
......@@ -77,13 +77,18 @@ static const sctp_supported_addrs_param_t sat_param = {
{
SCTP_PARAM_SUPPORTED_ADDRESS_TYPES,
__constant_htons(SCTP_SAT_LEN),
},
{ /* types[] */
SCTP_PARAM_IPV4_ADDRESS,
SCTP_V6(SCTP_PARAM_IPV6_ADDRESS,)
}
};
/* gcc 3.2 doesn't allow initialization of zero-length arrays. So the above
* structure is split and the address types array is initialized using a
* fixed length array.
*/
static const __u16 sat_addr_types[2] = {
SCTP_PARAM_IPV4_ADDRESS,
SCTP_V6(SCTP_PARAM_IPV6_ADDRESS,)
};
/* RFC 2960 3.3.2 Initiation (INIT) (1)
*
* Note 2: The ECN capable field is reserved for future use of
......@@ -163,7 +168,7 @@ void sctp_init_cause(sctp_chunk_t *chunk, __u16 cause_code,
*/
sctp_chunk_t *sctp_make_init(const sctp_association_t *asoc,
const sctp_bind_addr_t *bp,
int priority)
int priority, int vparam_len)
{
sctp_inithdr_t init;
union sctp_params addrs;
......@@ -192,6 +197,7 @@ sctp_chunk_t *sctp_make_init(const sctp_association_t *asoc,
chunksize = sizeof(init) + addrs_len + SCTP_SAT_LEN;
chunksize += sizeof(ecap_param);
chunksize += vparam_len;
/* RFC 2960 3.3.2 Initiation (INIT) (1)
*
......@@ -213,7 +219,10 @@ sctp_chunk_t *sctp_make_init(const sctp_association_t *asoc,
sctp_addto_chunk(retval, sizeof(init), &init);
retval->param_hdr.v =
sctp_addto_chunk(retval, addrs_len, addrs.v);
sctp_addto_chunk(retval, SCTP_SAT_LEN, &sat_param);
sctp_addto_chunk(retval, sizeof(sctp_paramhdr_t), &sat_param);
sctp_addto_chunk(retval, sizeof(sat_addr_types), sat_addr_types);
sctp_addto_chunk(retval, sizeof(ecap_param), &ecap_param);
nodata:
......@@ -1337,7 +1346,7 @@ sctp_cookie_param_t *sctp_pack_cookie(const sctp_endpoint_t *ep,
sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep,
const sctp_association_t *asoc,
sctp_chunk_t *chunk, int priority,
int *error)
int *error, sctp_chunk_t **err_chk_p)
{
sctp_association_t *retval = NULL;
sctp_signed_cookie_t *cookie;
......@@ -1394,7 +1403,29 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep,
* for init collision case of lost COOKIE ACK.
*/
if (!asoc && tv_lt(bear_cookie->expiration, chunk->skb->stamp)) {
*error = -SCTP_IERROR_STALE_COOKIE;
/*
* Section 3.3.10.3 Stale Cookie Error (3)
*
* Cause of error
* ---------------
* Stale Cookie Error: Indicates the receipt of a valid State
* Cookie that has expired.
*/
*err_chk_p = sctp_make_op_error_space(asoc, chunk,
ntohs(chunk->chunk_hdr->length));
if (*err_chk_p) {
suseconds_t usecs = (chunk->skb->stamp.tv_sec -
bear_cookie->expiration.tv_sec) * 1000000L +
chunk->skb->stamp.tv_usec -
bear_cookie->expiration.tv_usec;
usecs = htonl(usecs);
sctp_init_cause(*err_chk_p, SCTP_ERROR_STALE_COOKIE,
&usecs, sizeof(usecs));
*error = -SCTP_IERROR_STALE_COOKIE;
} else
*error = -SCTP_IERROR_NOMEM;
goto fail;
}
......@@ -1751,6 +1782,7 @@ int sctp_process_param(sctp_association_t *asoc, union sctp_params param,
__u16 sat;
int retval = 1;
sctp_scope_t scope;
time_t stale;
/* We maintain all INIT parameters in network byte order all the
* time. This allows us to not worry about whether the parameters
......@@ -1770,8 +1802,16 @@ int sctp_process_param(sctp_association_t *asoc, union sctp_params param,
break;
case SCTP_PARAM_COOKIE_PRESERVATIVE:
asoc->cookie_preserve =
ntohl(param.life->lifespan_increment);
if (!sctp_proto.cookie_preserve_enable)
break;
stale = ntohl(param.life->lifespan_increment);
/* Suggested Cookie Life span increment's unit is msec,
* (1/1000sec).
*/
asoc->cookie_life.tv_sec += stale / 1000;
asoc->cookie_life.tv_usec += (stale % 1000) * 1000;
break;
case SCTP_PARAM_HOST_NAME_ADDRESS:
......
......@@ -68,7 +68,8 @@ static void sctp_do_8_2_transport_strike(sctp_association_t *asoc,
sctp_transport_t *transport);
static void sctp_cmd_init_failed(sctp_cmd_seq_t *, sctp_association_t *asoc);
static void sctp_cmd_assoc_failed(sctp_cmd_seq_t *, sctp_association_t *asoc,
sctp_event_t event_type, sctp_chunk_t *chunk);
sctp_event_t event_type, sctp_subtype_t stype,
sctp_chunk_t *chunk);
static int sctp_cmd_process_init(sctp_cmd_seq_t *, sctp_association_t *asoc,
sctp_chunk_t *chunk,
sctp_init_chunk_t *peer_init,
......@@ -517,7 +518,7 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
case SCTP_CMD_ASSOC_FAILED:
sctp_cmd_assoc_failed(commands, asoc, event_type,
chunk);
subtype, chunk);
break;
case SCTP_CMD_COUNTER_INC:
......@@ -736,6 +737,9 @@ int sctp_gen_sack(sctp_association_t *asoc, int force, sctp_cmd_seq_t *commands)
if (!sack)
goto nomem;
/* Update the last advertised rwnd value. */
asoc->a_rwnd = asoc->rwnd;
asoc->peer.sack_needed = 0;
asoc->peer.next_dup_tsn = 0;
......@@ -1046,18 +1050,27 @@ static void sctp_cmd_init_failed(sctp_cmd_seq_t *commands,
static void sctp_cmd_assoc_failed(sctp_cmd_seq_t *commands,
sctp_association_t *asoc,
sctp_event_t event_type,
sctp_subtype_t subtype,
sctp_chunk_t *chunk)
{
sctp_ulpevent_t *event;
__u16 error = 0;
if (event_type == SCTP_EVENT_T_PRIMITIVE)
error = SCTP_ERROR_USER_ABORT;
if (chunk && (SCTP_CID_ABORT == chunk->chunk_hdr->type) &&
(ntohs(chunk->chunk_hdr->length) >= (sizeof(struct sctp_chunkhdr) +
sizeof(struct sctp_errhdr)))) {
error = ((sctp_errhdr_t *)chunk->skb->data)->cause;
switch(event_type) {
case SCTP_EVENT_T_PRIMITIVE:
if (SCTP_PRIMITIVE_ABORT == subtype.primitive)
error = SCTP_ERROR_USER_ABORT;
break;
case SCTP_EVENT_T_CHUNK:
if (chunk && (SCTP_CID_ABORT == chunk->chunk_hdr->type) &&
(ntohs(chunk->chunk_hdr->length) >=
(sizeof(struct sctp_chunkhdr) +
sizeof(struct sctp_errhdr)))) {
error = ((sctp_errhdr_t *)chunk->skb->data)->cause;
}
break;
default:
break;
}
event = sctp_ulpevent_make_assoc_change(asoc,
......
This diff is collapsed.
......@@ -295,7 +295,7 @@ sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
/* SCTP_STATE_COOKIE_WAIT */ \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{.fn = sctp_sf_not_impl, .name = "sctp_sf_not_impl"}, \
{.fn = sctp_sf_cookie_echoed_err, .name = "sctp_sf_cookie_echoed_err"}, \
/* SCTP_STATE_ESTABLISHED */ \
{.fn = sctp_sf_operr_notify, .name = "sctp_sf_operr_notify"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
......
This diff is collapsed.
/* SCTP kernel reference Implementation
* Copyright (c) 2002 International Business Machines Corp.
* Copyright (c) 2002 Intel Corp.
*
* This file is part of the SCTP kernel reference Implementation
*
......@@ -32,6 +33,7 @@
* Written or modified by:
* Mingqin Liu <liuming@us.ibm.com>
* Jon Grimm <jgrimm@us.ibm.com>
* Ardelle Fan <ardelle.fan@intel.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
......@@ -70,6 +72,9 @@ static ctl_table sctp_table[] = {
{ NET_SCTP_HB_INTERVAL, "hb_interval",
&sctp_proto.hb_interval, sizeof(int), 0644, NULL,
&proc_dointvec_jiffies, &sysctl_jiffies },
{ NET_SCTP_PRESERVE_ENABLE, "cookie_preserve_enable",
&sctp_proto.cookie_preserve_enable, sizeof(int), 0644, NULL,
&proc_dointvec_jiffies, &sysctl_jiffies },
{ NET_SCTP_RTO_ALPHA, "rto_alpha_exp_divisor",
&sctp_proto.rto_alpha, sizeof(int), 0644, NULL,
&proc_dointvec },
......
......@@ -207,7 +207,7 @@ void sctp_transport_route(sctp_transport_t *transport, union sctp_addr *saddr,
struct sctp_opt *opt)
{
sctp_association_t *asoc = transport->asoc;
struct sctp_func *af = transport->af_specific;
struct sctp_af *af = transport->af_specific;
union sctp_addr *daddr = &transport->ipaddr;
sctp_bind_addr_t *bp;
rwlock_t *addr_lock;
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment