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