Commit 180fb54b authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/davem/net-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 8f493285 0b7f6302
/* SCTP kernel reference Implementation Copyright (C) 1999-2001
* Cisco, Motorola, and IBM
*
*
* This file is part of the SCTP kernel reference Implementation
*
*
* These are the definitions needed for the command object.
*
* The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of
*
* The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* the SCTP reference implementation is distributed in the hope that it
*
* the SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Boston, MA 02111-1307, USA.
*
* Please send any bug reports or fixes you make to one of the
* following email addresses:
*
*
* La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us>
* 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.
*/
......@@ -69,11 +69,11 @@ typedef enum {
SCTP_CMD_INIT_FAILED, /* High level, do init failure work. */
SCTP_CMD_REPORT_DUP, /* Report a duplicate TSN. */
SCTP_CMD_REPORT_BIGGAP, /* Narc on a TSN (it was too high). */
SCTP_CMD_SET_BIND_ADDR, /* Set the association bind_addr. */
SCTP_CMD_STRIKE, /* Mark a strike against a transport. */
SCTP_CMD_TRANSMIT, /* Transmit the outqueue. */
SCTP_CMD_HB_TIMERS_START, /* Start the heartbeat timers. */
SCTP_CMD_HB_TIMERS_UPDATE, /* Update the heartbeat timers. */
SCTP_CMD_HB_TIMERS_START, /* Start the heartbeat timers. */
SCTP_CMD_HB_TIMER_UPDATE, /* Update a heartbeat timers. */
SCTP_CMD_HB_TIMERS_STOP, /* Stop the heartbeat timers. */
SCTP_CMD_TRANSPORT_RESET, /* Reset the status of a transport. */
SCTP_CMD_TRANSPORT_ON, /* Mark the transport as active. */
SCTP_CMD_REPORT_ERROR, /* Pass this error back out of the sm. */
......@@ -112,7 +112,7 @@ typedef union {
void *ptr;
sctp_chunk_t *chunk;
sctp_association_t *asoc;
sctp_transport_t *transport;
struct sctp_transport *transport;
sctp_bind_addr_t *bp;
sctp_init_chunk_t *init;
sctp_ulpevent_t *ulpevent;
......@@ -160,7 +160,7 @@ SCTP_ARG_CONSTRUCTOR(TO, sctp_event_timeout_t, to)
SCTP_ARG_CONSTRUCTOR(PTR, void *, ptr)
SCTP_ARG_CONSTRUCTOR(CHUNK, sctp_chunk_t *, chunk)
SCTP_ARG_CONSTRUCTOR(ASOC, sctp_association_t *, asoc)
SCTP_ARG_CONSTRUCTOR(TRANSPORT, sctp_transport_t *, transport)
SCTP_ARG_CONSTRUCTOR(TRANSPORT, struct sctp_transport *, transport)
SCTP_ARG_CONSTRUCTOR(BA, sctp_bind_addr_t *, bp)
SCTP_ARG_CONSTRUCTOR(PEER_INIT, sctp_init_chunk_t *, init)
SCTP_ARG_CONSTRUCTOR(ULPEVENT, sctp_ulpevent_t *, ulpevent)
......
......@@ -3,33 +3,33 @@
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001-2002 International Business Machines Corp.
*
*
* This file is part of the SCTP kernel reference Implementation
*
*
* This file is part of the implementation of the add-IP extension,
* based on <draft-ietf-tsvwg-addip-sctp-02.txt> June 29, 2001,
* for the SCTP kernel reference Implementation.
*
* The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of
*
* The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* the SCTP reference implementation is distributed in the hope that it
*
* the SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* ************************
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Boston, MA 02111-1307, USA.
*
* Please send any bug reports or fixes you make to one of the following email
* addresses:
*
*
* La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us>
* Randall Stewart <randall@stewart.chicago.il.us>
......@@ -38,14 +38,14 @@
* Xingang Guo <xingang.guo@intel.com>
* Sridhar Samudrala <samudrala@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com>
*
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
*
*
* There are still LOTS of bugs in this code... I always run on the motto
* "it is a wonder any code ever works :)"
*
*
*
*
*/
#ifndef __sctp_constants_h__
......@@ -56,17 +56,10 @@
#include <linux/ipv6.h> /* For ipv6hdr. */
#include <net/sctp/user.h>
/* What a hack! Jiminy Cricket! */
enum { SCTP_MAX_STREAM = 10 };
/* Define the amount of space to reserve for SCTP, IP, LL.
* There is a little bit of waste that we are always allocating
* for ipv6 headers, but this seems worth the simplicity.
*/
#define SCTP_IP_OVERHEAD ((sizeof(struct sctphdr)\
+ sizeof(struct ipv6hdr)\
+ MAX_HEADER))
/* Value used for stream negotiation. */
enum { SCTP_MAX_STREAM = 0xffff };
enum { SCTP_DEFAULT_OUTSTREAMS = 10 };
enum { SCTP_DEFAULT_INSTREAMS = SCTP_MAX_STREAM };
/* Define the amount of space to reserve for SCTP, IP, LL.
* There is a little bit of waste that we are always allocating
......@@ -105,57 +98,37 @@ typedef enum {
*/
typedef enum {
SCTP_EVENT_TIMEOUT_NONE = 0,
SCTP_EVENT_TIMEOUT_T1_COOKIE,
SCTP_EVENT_TIMEOUT_T1_INIT,
SCTP_EVENT_TIMEOUT_T2_SHUTDOWN,
SCTP_EVENT_TIMEOUT_T3_RTX,
SCTP_EVENT_TIMEOUT_T4_RTO,
SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD,
SCTP_EVENT_TIMEOUT_HEARTBEAT,
SCTP_EVENT_TIMEOUT_SACK,
SCTP_EVENT_TIMEOUT_AUTOCLOSE,
SCTP_EVENT_TIMEOUT_PMTU_RAISE,
} sctp_event_timeout_t;
#define SCTP_EVENT_TIMEOUT_MAX SCTP_EVENT_TIMEOUT_PMTU_RAISE
#define SCTP_EVENT_TIMEOUT_MAX SCTP_EVENT_TIMEOUT_AUTOCLOSE
#define SCTP_NUM_TIMEOUT_TYPES (SCTP_EVENT_TIMEOUT_MAX + 1)
typedef enum {
SCTP_EVENT_NO_PENDING_TSN = 0,
SCTP_EVENT_ICMP_UNREACHFRAG,
} sctp_event_other_t;
#define SCTP_EVENT_OTHER_MAX SCTP_EVENT_ICMP_UNREACHFRAG
#define SCTP_EVENT_OTHER_MAX SCTP_EVENT_NO_PENDING_TSN
#define SCTP_NUM_OTHER_TYPES (SCTP_EVENT_OTHER_MAX + 1)
/* These are primitive requests from the ULP. */
typedef enum {
SCTP_PRIMITIVE_INITIALIZE = 0,
SCTP_PRIMITIVE_ASSOCIATE,
SCTP_PRIMITIVE_ASSOCIATE = 0,
SCTP_PRIMITIVE_SHUTDOWN,
SCTP_PRIMITIVE_ABORT,
SCTP_PRIMITIVE_SEND,
SCTP_PRIMITIVE_SETPRIMARY,
SCTP_PRIMITIVE_RECEIVE,
SCTP_PRIMITIVE_STATUS,
SCTP_PRIMITIVE_CHANGEHEARTBEAT,
SCTP_PRIMITIVE_REQUESTHEARTBEAT,
SCTP_PRIMITIVE_GETSRTTREPORT,
SCTP_PRIMITIVE_SETFAILURETHRESHOLD,
SCTP_PRIMITIVE_SETPROTOPARAMETERS,
SCTP_PRIMITIVE_RECEIVE_UNSENT,
SCTP_PRIMITIVE_RECEIVE_UNACKED,
SCTP_PRIMITIVE_DESTROY,
} sctp_event_primitive_t;
#define SCTP_EVENT_PRIMITIVE_MAX SCTP_PRIMITIVE_DESTROY
#define SCTP_EVENT_PRIMITIVE_MAX SCTP_PRIMITIVE_REQUESTHEARTBEAT
#define SCTP_NUM_PRIMITIVE_TYPES (SCTP_EVENT_PRIMITIVE_MAX + 1)
/* We define here a utility type for manipulating subtypes.
......@@ -268,8 +241,13 @@ extern const char *sctp_state_tbl[], *sctp_evttype_tbl[], *sctp_status_tbl[];
#define SCTP_ADDR_REACHABLE 2
#define SCTP_ADDR_NOT_REACHABLE 1
/* Maximum chunk length considering padding requirements. */
enum { SCTP_MAX_CHUNK_LEN = ((1<<16) - sizeof(__u32)) };
/* Encourage Cookie-Echo bundling by pre-fragmenting chunks a little
* harder (until reaching ESTABLISHED state).
*/
enum { SCTP_ARBITRARY_COOKIE_ECHO_LEN = 200 };
/* Guess at how big to make the TSN mapping array.
* We guarantee that we can handle at least this big a gap between the
......@@ -289,7 +267,8 @@ extern const char *sctp_state_tbl[], *sctp_evttype_tbl[], *sctp_status_tbl[];
* is enough room for 131 duplicate reports. Round down to the
* nearest power of 2.
*/
#define SCTP_MAX_DUP_TSNS 128
enum { SCTP_MIN_PMTU = 576 };
enum { SCTP_MAX_DUP_TSNS = 128 };
typedef enum {
SCTP_COUNTER_INIT_ERROR,
......@@ -298,7 +277,6 @@ typedef enum {
/* How many counters does an association need? */
#define SCTP_NUMBER_COUNTERS 5
/* Here we define the default timers. */
/* cookie timer def = ? seconds */
......@@ -317,10 +295,6 @@ typedef enum {
#define SCTP_DEFAULT_TIMEOUT_SACK ((200 * HZ) / 1000)
#define SCTP_DEFAULT_TIMEOUT_SACK_MAX ((500 * HZ) / 1000) /* 500 ms */
/* How long do we wait before attempting to raise the PMTU? */
#define SCTP_DEFAULT_TIMEOUT_PMTU_RAISE (10 * 60 * HZ) /* 10 Minutes */
#define SCTP_DEFAULT_TIMEOUT_PMTU_RAISE_MIN (10 * 60 * HZ) /* 10 Minutes */
/* RTO.Initial - 3 seconds
* RTO.Min - 1 second
* RTO.Max - 60 seconds
......@@ -439,6 +413,13 @@ typedef enum {
#define SCTP_ADDR6_PEERSUPP 0x00000004 /* IPv6 address is supported by
peer */
/* Reasons to retransmit. */
typedef enum {
SCTP_RETRANSMIT_T3_RTX,
SCTP_RETRANSMIT_FAST_RTX,
SCTP_RETRANSMIT_PMTU_DISCOVERY,
} sctp_retransmit_reason_t;
/* Reasons to lower cwnd. */
typedef enum {
SCTP_LOWER_CWND_T3_RTX,
......@@ -448,4 +429,3 @@ typedef enum {
} sctp_lower_cwnd_t;
#endif /* __sctp_constants_h__ */
/* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001-2002 International Business Machines, Corp.
* Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001-2003 International Business Machines, Corp.
* Copyright (c) 2001-2003 Intel Corp.
*
* This file is part of the SCTP kernel reference Implementation
*
......@@ -36,7 +36,9 @@
* La Monte H.P. Yarroll <piggy@acm.org>
* Xingang Guo <xingang.guo@intel.com>
* Jon Grimm <jgrimm@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.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.
......@@ -147,7 +149,9 @@ extern int sctp_primitive_REQUESTHEARTBEAT(sctp_association_t *, void *arg);
/*
* sctp_crc32c.c
*/
extern __u32 count_crc(__u8 *ptr, __u16 count);
extern __u32 sctp_start_cksum(__u8 *ptr, __u16 count);
extern __u32 sctp_update_cksum(__u8 *ptr, __u16 count, __u32 cksum);
extern __u32 sctp_end_cksum(__u32 cksum);
/*
* sctp_input.c
......@@ -162,6 +166,9 @@ extern void sctp_hash_endpoint(sctp_endpoint_t *);
extern void __sctp_hash_endpoint(sctp_endpoint_t *);
extern void sctp_unhash_endpoint(sctp_endpoint_t *);
extern void __sctp_unhash_endpoint(sctp_endpoint_t *);
extern sctp_association_t *__sctp_lookup_association(const union sctp_addr *,
const union sctp_addr *,
struct sctp_transport **);
/*
* sctp_hashdriver.c
......@@ -266,6 +273,7 @@ extern atomic_t sctp_dbg_objcnt_transport;
extern atomic_t sctp_dbg_objcnt_chunk;
extern atomic_t sctp_dbg_objcnt_bind_addr;
extern atomic_t sctp_dbg_objcnt_addr;
extern atomic_t sctp_dbg_objcnt_ssnmap;
/* Macros to atomically increment/decrement objcnt counters. */
#define SCTP_DBG_OBJCNT_INC(name) \
......@@ -418,6 +426,23 @@ static inline size_t get_user_iov_size(struct iovec *iov, int iovlen)
return retval;
}
/* Generate a random jitter in the range of -50% ~ +50% of input RTO. */
static inline __s32 sctp_jitter(__u32 rto)
{
static __u32 sctp_rand;
__s32 ret;
sctp_rand += jiffies;
sctp_rand ^= (sctp_rand << 12);
sctp_rand ^= (sctp_rand >> 20);
/* Choose random number from 0 to rto, then move to -50% ~ +50%
* of rto.
*/
ret = sctp_rand % rto - (rto >> 1);
return ret;
}
/* Walk through a list of TLV parameters. Don't trust the
* individual parameter lengths and instead depend on
* the chunk length to indicate when to stop. Make sure
......
......@@ -256,7 +256,7 @@ sctp_chunk_t *sctp_make_abort_user(const sctp_association_t *,
const sctp_chunk_t *,
const struct msghdr *);
sctp_chunk_t *sctp_make_heartbeat(const sctp_association_t *,
const sctp_transport_t *,
const struct sctp_transport *,
const void *payload,
const size_t paylen);
sctp_chunk_t *sctp_make_heartbeat_ack(const sctp_association_t *,
......@@ -269,6 +269,11 @@ sctp_chunk_t *sctp_make_op_error(const sctp_association_t *,
const void *payload,
size_t paylen);
void sctp_chunk_assign_tsn(sctp_chunk_t *);
void sctp_chunk_assign_ssn(sctp_chunk_t *);
int sctp_datachunks_from_user(sctp_association_t *,
const struct sctp_sndrcvinfo *,
struct msghdr *, int len,
struct sk_buff_head *);
/* Prototypes for statetable processing. */
......
This diff is collapsed.
/* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 International Business Machines, Corp.
* Copyright (c) 2001-2003 International Business Machines, Corp.
* Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll
*
* These are the definitions needed for the sctp_ulpqueue type. The
* sctp_ulpqueue is the interface between the Upper Layer Protocol, or ULP,
*
* These are the definitions needed for the sctp_ulpq type. The
* sctp_ulpq is the interface between the Upper Layer Protocol, or ULP,
* and the core SCTP state machine. This is the component which handles
* reassembly and ordering.
*
* The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of
* reassembly and ordering.
*
* The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* the SCTP reference implementation is distributed in the hope that it
*
* the SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Please send any bug reports or fixes you make to one of the
* following email addresses:
*
* Jon Grimm <jgrimm@us.ibm.com>
* La Monte H.P. Yarroll <piggy@acm.org>
*
* Boston, MA 02111-1307, USA.
*
* Please send any bug reports or fixes you make to the
* email addresses:
* lksctp developers <lksctp-developers@lists.sourceforge.net>
*
* Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp
*
* Written or modified by:
* Jon Grimm <jgrimm@us.ibm.com>
* La Monte H.P. Yarroll <piggy@acm.org>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
*/
......@@ -42,46 +47,26 @@
#define __sctp_ulpqueue_h__
/* A structure to carry information to the ULP (e.g. Sockets API) */
typedef struct sctp_ulpqueue {
struct sctp_ulpq {
int malloced;
spinlock_t lock;
sctp_association_t *asoc;
struct sk_buff_head reasm;
struct sk_buff_head lobby;
__u16 ssn[0];
} sctp_ulpqueue_t;
/* This macro assists in creation of external storage for variable length
* internal buffers.
*/
#define sctp_ulpqueue_storage_size(inbound) (sizeof(__u16) * (inbound))
sctp_ulpqueue_t *sctp_ulpqueue_new(sctp_association_t *asoc,
__u16 inbound,
int priority);
sctp_ulpqueue_t *sctp_ulpqueue_init(sctp_ulpqueue_t *ulpq,
sctp_association_t *asoc,
__u16 inbound);
void sctp_ulpqueue_free(sctp_ulpqueue_t *);
};
/* Prototypes. */
struct sctp_ulpq *sctp_ulpq_new(sctp_association_t *asoc, int priority);
struct sctp_ulpq *sctp_ulpq_init(struct sctp_ulpq *, sctp_association_t *);
void sctp_ulpq_free(struct sctp_ulpq *);
/* Add a new DATA chunk for processing. */
int sctp_ulpqueue_tail_data(sctp_ulpqueue_t *,
sctp_chunk_t *chunk,
int priority);
int sctp_ulpq_tail_data(struct sctp_ulpq *, sctp_chunk_t *chunk, int priority);
/* Add a new event for propogation to the ULP. */
int sctp_ulpqueue_tail_event(sctp_ulpqueue_t *,
sctp_ulpevent_t *event);
int sctp_ulpq_tail_event(struct sctp_ulpq *, struct sctp_ulpevent *ev);
/* Is the ulpqueue empty. */
int sctp_ulpqueue_is_empty(sctp_ulpqueue_t *);
int sctp_ulpqueue_is_data_empty(sctp_ulpqueue_t *);
int sctp_ulpqueue_is_empty(struct sctp_ulpq *);
#endif /* __sctp_ulpqueue_h__ */
......@@ -90,4 +75,4 @@ int sctp_ulpqueue_is_data_empty(sctp_ulpqueue_t *);
......@@ -100,6 +100,14 @@ enum sctp_optname {
#define SCTP_SOCKOPT_BINDX_REM SCTP_SOCKOPT_BINDX_REM
SCTP_SOCKOPT_PEELOFF, /* peel off association. */
#define SCTP_SOCKOPT_PEELOFF SCTP_SOCKOPT_PEELOFF
SCTP_GET_PEER_ADDRS_NUM, /* Get number of peer addresss. */
#define SCTP_GET_PEER_ADDRS_NUM SCTP_GET_PEER_ADDRS_NUM
SCTP_GET_PEER_ADDRS, /* Get all peer addresss. */
#define SCTP_GET_PEER_ADDRS SCTP_GET_PEER_ADDRS
SCTP_GET_LOCAL_ADDRS_NUM, /* Get number of local addresss. */
#define SCTP_GET_LOCAL_ADDRS_NUM SCTP_GET_LOCAL_ADDRS_NUM
SCTP_GET_LOCAL_ADDRS, /* Get all local addresss. */
#define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS
};
......@@ -576,6 +584,15 @@ struct sctp_setstrm_timeout {
__u16 ssto_streamid_end;
};
/*
* 8.3 8.5 get all peer/local addresses on a socket
* This parameter struct is for getsockopt
*/
struct sctp_getaddrs {
sctp_assoc_t assoc_id;
int addr_num;
struct sockaddr_storage *addrs;
};
/* These are bit fields for msghdr->msg_flags. See section 5.1. */
/* On user space Linux, these live in <bits/socket.h> as an enum. */
......
......@@ -8,6 +8,7 @@
#include <linux/netdevice.h>
#include <linux/crypto.h>
#include <linux/pfkeyv2.h>
#include <linux/in6.h>
#include <net/dst.h>
#include <net/route.h>
......@@ -424,4 +425,23 @@ extern struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id);
extern struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name);
extern struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name);
static inline int
xfrm6_selector_match(struct xfrm_selector *sel, struct flowi *fl)
{
return !memcmp(fl->fl6_dst, sel->daddr.a6, sizeof(struct in6_addr)) &&
!((fl->uli_u.ports.dport^sel->dport)&sel->dport_mask) &&
!((fl->uli_u.ports.sport^sel->sport)&sel->sport_mask) &&
(fl->proto == sel->proto || !sel->proto) &&
(fl->oif == sel->ifindex || !sel->ifindex) &&
!memcmp(fl->fl6_src, sel->saddr.a6, sizeof(struct in6_addr));
}
extern int xfrm6_register_type(struct xfrm_type *type);
extern int xfrm6_unregister_type(struct xfrm_type *type);
extern struct xfrm_type *xfrm6_get_type(u8 proto);
extern struct xfrm_state *xfrm6_state_lookup(struct in6_addr *daddr, u32 spi, u8 proto);
struct xfrm_state * xfrm6_find_acq(u8 mode, u16 reqid, u8 proto, struct in6_addr *daddr, struct in6_addr *saddr, int create);
void xfrm6_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
#endif /* _NET_XFRM_H */
......@@ -33,73 +33,168 @@ static ctl_table *ax25_table;
static int ax25_table_size;
static ctl_table ax25_dir_table[] = {
{NET_AX25, "ax25", NULL, 0, 0555, NULL},
{0}
{
.ctl_name = NET_AX25,
.procname = "ax25",
.maxlen = 0,
.mode = 0555,
},
{ .ctl_name = 0 }
};
static ctl_table ax25_root_table[] = {
{CTL_NET, "net", NULL, 0, 0555, ax25_dir_table},
{0}
{
.ctl_name = CTL_NET,
.procname = "net",
.maxlen = 0,
.mode = 0555,
.child = ax25_dir_table
},
{ .ctl_name = 0 }
};
static const ctl_table ax25_param_table[] = {
{NET_AX25_IP_DEFAULT_MODE, "ip_default_mode",
NULL, sizeof(int), 0644, NULL,
&proc_dointvec_minmax, &sysctl_intvec, NULL,
&min_ipdefmode, &max_ipdefmode},
{NET_AX25_DEFAULT_MODE, "ax25_default_mode",
NULL, sizeof(int), 0644, NULL,
&proc_dointvec_minmax, &sysctl_intvec, NULL,
&min_axdefmode, &max_axdefmode},
{NET_AX25_BACKOFF_TYPE, "backoff_type",
NULL, sizeof(int), 0644, NULL,
&proc_dointvec_minmax, &sysctl_intvec, NULL,
&min_backoff, &max_backoff},
{NET_AX25_CONNECT_MODE, "connect_mode",
NULL, sizeof(int), 0644, NULL,
&proc_dointvec_minmax, &sysctl_intvec, NULL,
&min_conmode, &max_conmode},
{NET_AX25_STANDARD_WINDOW, "standard_window_size",
NULL, sizeof(int), 0644, NULL,
&proc_dointvec_minmax, &sysctl_intvec, NULL,
&min_window, &max_window},
{NET_AX25_EXTENDED_WINDOW, "extended_window_size",
NULL, sizeof(int), 0644, NULL,
&proc_dointvec_minmax, &sysctl_intvec, NULL,
&min_ewindow, &max_ewindow},
{NET_AX25_T1_TIMEOUT, "t1_timeout",
NULL, sizeof(int), 0644, NULL,
&proc_dointvec_minmax, &sysctl_intvec, NULL,
&min_t1, &max_t1},
{NET_AX25_T2_TIMEOUT, "t2_timeout",
NULL, sizeof(int), 0644, NULL,
&proc_dointvec_minmax, &sysctl_intvec, NULL,
&min_t2, &max_t2},
{NET_AX25_T3_TIMEOUT, "t3_timeout",
NULL, sizeof(int), 0644, NULL,
&proc_dointvec_minmax, &sysctl_intvec, NULL,
&min_t3, &max_t3},
{NET_AX25_IDLE_TIMEOUT, "idle_timeout",
NULL, sizeof(int), 0644, NULL,
&proc_dointvec_minmax, &sysctl_intvec, NULL,
&min_idle, &max_idle},
{NET_AX25_N2, "maximum_retry_count",
NULL, sizeof(int), 0644, NULL,
&proc_dointvec_minmax, &sysctl_intvec, NULL,
&min_n2, &max_n2},
{NET_AX25_PACLEN, "maximum_packet_length",
NULL, sizeof(int), 0644, NULL,
&proc_dointvec_minmax, &sysctl_intvec, NULL,
&min_paclen, &max_paclen},
{NET_AX25_PROTOCOL, "protocol",
NULL, sizeof(int), 0644, NULL,
&proc_dointvec_minmax, &sysctl_intvec, NULL,
&min_proto, &max_proto},
{NET_AX25_DAMA_SLAVE_TIMEOUT, "dama_slave_timeout",
NULL, sizeof(int), 0644, NULL,
&proc_dointvec_minmax, &sysctl_intvec, NULL,
&min_ds_timeout, &max_ds_timeout},
{0} /* that's all, folks! */
{
.ctl_name = NET_AX25_IP_DEFAULT_MODE,
.procname = "ip_default_mode",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_ipdefmode,
.extra2 = &max_ipdefmode
},
{
.ctl_name = NET_AX25_DEFAULT_MODE,
.procname = "ax25_default_mode",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_axdefmode,
.extra2 = &max_axdefmode
},
{
.ctl_name = NET_AX25_BACKOFF_TYPE,
.procname = "backoff_type",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_backoff,
.extra2 = &max_backoff
},
{
.ctl_name = NET_AX25_CONNECT_MODE,
.procname = "connect_mode",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_conmode,
.extra2 = &max_conmode
},
{
.ctl_name = NET_AX25_STANDARD_WINDOW,
.procname = "standard_window_size",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_window,
.extra2 = &max_window
},
{
.ctl_name = NET_AX25_EXTENDED_WINDOW,
.procname = "extended_window_size",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_ewindow,
.extra2 = &max_ewindow
},
{
.ctl_name = NET_AX25_T1_TIMEOUT,
.procname = "t1_timeout",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_t1,
.extra2 = &max_t1
},
{
.ctl_name = NET_AX25_T2_TIMEOUT,
.procname = "t2_timeout",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_t2,
.extra2 = &max_t2
},
{
.ctl_name = NET_AX25_T3_TIMEOUT,
.procname = "t3_timeout",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_t3,
.extra2 = &max_t3
},
{
.ctl_name = NET_AX25_IDLE_TIMEOUT,
.procname = "idle_timeout",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_idle,
.extra2 = &max_idle
},
{
.ctl_name = NET_AX25_N2,
.procname = "maximum_retry_count",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_n2,
.extra2 = &max_n2
},
{
.ctl_name = NET_AX25_PACLEN,
.procname = "maximum_packet_length",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_paclen,
.extra2 = &max_paclen
},
{
.ctl_name = NET_AX25_PROTOCOL,
.procname = "protocol",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_proto,
.extra2 = &max_proto
},
{
.ctl_name = NET_AX25_DAMA_SLAVE_TIMEOUT,
.procname = "dama_slave_timeout",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_ds_timeout,
.extra2 = &max_ds_timeout
},
{ .ctl_name = 0 } /* that's all, folks! */
};
void ax25_register_sysctl(void)
......
......@@ -36,59 +36,139 @@ extern char sysctl_divert_version[];
ctl_table core_table[] = {
#ifdef CONFIG_NET
{NET_CORE_WMEM_MAX, "wmem_max",
&sysctl_wmem_max, sizeof(int), 0644, NULL,
&proc_dointvec},
{NET_CORE_RMEM_MAX, "rmem_max",
&sysctl_rmem_max, sizeof(int), 0644, NULL,
&proc_dointvec},
{NET_CORE_WMEM_DEFAULT, "wmem_default",
&sysctl_wmem_default, sizeof(int), 0644, NULL,
&proc_dointvec},
{NET_CORE_RMEM_DEFAULT, "rmem_default",
&sysctl_rmem_default, sizeof(int), 0644, NULL,
&proc_dointvec},
{NET_CORE_DEV_WEIGHT, "dev_weight",
&weight_p, sizeof(int), 0644, NULL,
&proc_dointvec},
{NET_CORE_MAX_BACKLOG, "netdev_max_backlog",
&netdev_max_backlog, sizeof(int), 0644, NULL,
&proc_dointvec},
{NET_CORE_NO_CONG_THRESH, "no_cong_thresh",
&no_cong, sizeof(int), 0644, NULL,
&proc_dointvec},
{NET_CORE_NO_CONG, "no_cong",
&no_cong, sizeof(int), 0644, NULL,
&proc_dointvec},
{NET_CORE_LO_CONG, "lo_cong",
&lo_cong, sizeof(int), 0644, NULL,
&proc_dointvec},
{NET_CORE_MOD_CONG, "mod_cong",
&mod_cong, sizeof(int), 0644, NULL,
&proc_dointvec},
{
.ctl_name = NET_CORE_WMEM_MAX,
.procname = "wmem_max",
.data = &sysctl_wmem_max,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
},
{
.ctl_name = NET_CORE_RMEM_MAX,
.procname = "rmem_max",
.data = &sysctl_rmem_max,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
},
{
.ctl_name = NET_CORE_WMEM_DEFAULT,
.procname = "wmem_default",
.data = &sysctl_wmem_default,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
},
{
.ctl_name = NET_CORE_RMEM_DEFAULT,
.procname = "rmem_default",
.data = &sysctl_rmem_default,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
},
{
.ctl_name = NET_CORE_DEV_WEIGHT,
.procname = "dev_weight",
.data = &weight_p,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
},
{
.ctl_name = NET_CORE_MAX_BACKLOG,
.procname = "netdev_max_backlog",
.data = &netdev_max_backlog,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
},
{
.ctl_name = NET_CORE_NO_CONG_THRESH,
.procname = "no_cong_thresh",
.data = &no_cong,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
},
{
.ctl_name = NET_CORE_NO_CONG,
.procname = "no_cong",
.data = &no_cong,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
},
{
.ctl_name = NET_CORE_LO_CONG,
.procname = "lo_cong",
.data = &lo_cong,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
},
{
.ctl_name = NET_CORE_MOD_CONG,
.procname = "mod_cong",
.data = &mod_cong,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
},
#ifdef CONFIG_NET_FASTROUTE
{NET_CORE_FASTROUTE, "netdev_fastroute",
&netdev_fastroute, sizeof(int), 0644, NULL,
&proc_dointvec},
{
.ctl_name = NET_CORE_FASTROUTE,
.procname = "netdev_fastroute",
.data = &netdev_fastroute,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
},
#endif
{NET_CORE_MSG_COST, "message_cost",
&net_msg_cost, sizeof(int), 0644, NULL,
&proc_dointvec_jiffies},
{NET_CORE_MSG_BURST, "message_burst",
&net_msg_burst, sizeof(int), 0644, NULL,
&proc_dointvec_jiffies},
{NET_CORE_OPTMEM_MAX, "optmem_max",
&sysctl_optmem_max, sizeof(int), 0644, NULL,
&proc_dointvec},
{NET_CORE_HOT_LIST_LENGTH, "hot_list_length",
&sysctl_hot_list_len, sizeof(int), 0644, NULL,
&proc_dointvec},
{
.ctl_name = NET_CORE_MSG_COST,
.procname = "message_cost",
.data = &net_msg_cost,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies
},
{
.ctl_name = NET_CORE_MSG_BURST,
.procname = "message_burst",
.data = &net_msg_burst,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_jiffies
},
{
.ctl_name = NET_CORE_OPTMEM_MAX,
.procname = "optmem_max",
.data = &sysctl_optmem_max,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
},
{
.ctl_name = NET_CORE_HOT_LIST_LENGTH,
.procname = "hot_list_length",
.data = &sysctl_hot_list_len,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
},
#ifdef CONFIG_NET_DIVERT
{NET_CORE_DIVERT_VERSION, "divert_version",
(void *)sysctl_divert_version, 32, 0444, NULL,
&proc_dostring},
{
.ctl_name = NET_CORE_DIVERT_VERSION,
.procname = "divert_version",
.data = (void *)sysctl_divert_version,
.maxlen = 32,
.mode = 0444,
.proc_handler = &proc_dostring
},
#endif /* CONFIG_NET_DIVERT */
#endif /* CONFIG_NET */
{ 0 }
{ .ctl_name = 0 }
};
#endif
......@@ -1361,19 +1361,37 @@ static struct nf_sockopt_ops so_getorigdst
static struct ctl_table_header *ip_conntrack_sysctl_header;
static ctl_table ip_conntrack_table[] = {
{ NET_IP_CONNTRACK_MAX, NET_IP_CONNTRACK_MAX_NAME, &ip_conntrack_max,
sizeof(ip_conntrack_max), 0644, NULL, proc_dointvec },
{ 0 }
{
.ctl_name = NET_IP_CONNTRACK_MAX,
.procname = NET_IP_CONNTRACK_MAX_NAME,
.data = &ip_conntrack_max,
.maxlen = sizeof(ip_conntrack_max),
.mode = 0644,
.proc_handler = proc_dointvec
},
{ .ctl_name = 0 }
};
static ctl_table ip_conntrack_dir_table[] = {
{NET_IPV4, "ipv4", NULL, 0, 0555, ip_conntrack_table, 0, 0, 0, 0, 0},
{ 0 }
{
.ctl_name = NET_IPV4,
.procname = "ipv4",
.maxlen = 0,
.mode = 0555,
.child = ip_conntrack_table
},
{ .ctl_name = 0 }
};
static ctl_table ip_conntrack_root_table[] = {
{CTL_NET, "net", NULL, 0, 0555, ip_conntrack_dir_table, 0, 0, 0, 0, 0},
{ 0 }
{
.ctl_name = CTL_NET,
.procname = "net",
.maxlen = 0,
.mode = 0555,
.child = ip_conntrack_dir_table
},
{ .ctl_name = 0 }
};
#endif /*CONFIG_SYSCTL*/
......
......@@ -586,19 +586,37 @@ static int sysctl_maxlen = IPQ_QMAX_DEFAULT;
static struct ctl_table_header *ipq_sysctl_header;
static ctl_table ipq_table[] = {
{ NET_IPQ_QMAX, NET_IPQ_QMAX_NAME, &sysctl_maxlen,
sizeof(sysctl_maxlen), 0644, NULL, proc_dointvec },
{ 0 }
{
.ctl_name = NET_IPQ_QMAX,
.procname = NET_IPQ_QMAX_NAME,
.data = &sysctl_maxlen,
.maxlen = sizeof(sysctl_maxlen),
.mode = 0644,
.proc_handler = proc_dointvec
},
{ .ctl_name = 0 }
};
static ctl_table ipq_dir_table[] = {
{NET_IPV4, "ipv4", NULL, 0, 0555, ipq_table, 0, 0, 0, 0, 0},
{ 0 }
{
.ctl_name = NET_IPV4,
.procname = "ipv4",
.maxlen = 0,
.mode = 0555,
.child = ipq_table
},
{ .ctl_name = 0 }
};
static ctl_table ipq_root_table[] = {
{CTL_NET, "net", NULL, 0, 0555, ipq_dir_table, 0, 0, 0, 0, 0},
{ 0 }
{
.ctl_name = CTL_NET,
.procname = "net",
.maxlen = 0,
.mode = 0555,
.child = ipq_dir_table
},
{ .ctl_name = 0 }
};
static int
......
This diff is collapsed.
#include <net/xfrm.h>
#include <linux/pfkeyv2.h>
#include <linux/ipsec.h>
#include <net/ipv6.h>
/* Each xfrm_state may be linked to two tables:
......@@ -219,7 +220,8 @@ xfrm_state_find(u32 daddr, u32 saddr, struct flowi *fl, struct xfrm_tmpl *tmpl,
spin_lock_bh(&xfrm_state_lock);
list_for_each_entry(x, xfrm_state_bydst+h, bydst) {
if (daddr == x->id.daddr.xfrm4_addr &&
if (x->props.family == AF_INET &&
daddr == x->id.daddr.xfrm4_addr &&
x->props.reqid == tmpl->reqid &&
(saddr == x->props.saddr.xfrm4_addr || !saddr || !x->props.saddr.xfrm4_addr) &&
tmpl->mode == x->props.mode &&
......@@ -282,6 +284,7 @@ xfrm_state_find(u32 daddr, u32 saddr, struct flowi *fl, struct xfrm_tmpl *tmpl,
x->id = tmpl->id;
if (x->id.daddr.xfrm4_addr == 0)
x->id.daddr.xfrm4_addr = daddr;
x->props.family = AF_INET;
x->props.saddr = tmpl->saddr;
if (x->props.saddr.xfrm4_addr == 0)
x->props.saddr.xfrm4_addr = saddr;
......@@ -317,7 +320,12 @@ xfrm_state_find(u32 daddr, u32 saddr, struct flowi *fl, struct xfrm_tmpl *tmpl,
void xfrm_state_insert(struct xfrm_state *x)
{
unsigned h = ntohl(x->id.daddr.xfrm4_addr);
unsigned h = 0;
if (x->props.family == AF_INET)
h = ntohl(x->id.daddr.xfrm4_addr);
else if (x->props.family == AF_INET6)
h = ntohl(x->id.daddr.a6[2]^x->id.daddr.a6[3]);
h = (h ^ (h>>16)) % XFRM_DST_HSIZE;
......@@ -325,7 +333,10 @@ void xfrm_state_insert(struct xfrm_state *x)
list_add(&x->bydst, xfrm_state_bydst+h);
atomic_inc(&x->refcnt);
h = ntohl(x->id.daddr.xfrm4_addr^x->id.spi^x->id.proto);
if (x->props.family == AF_INET)
h = ntohl(x->id.daddr.xfrm4_addr^x->id.spi^x->id.proto);
else
h = ntohl(x->id.daddr.a6[2]^x->id.daddr.a6[3]^x->id.spi^x->id.proto);
h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE;
list_add(&x->byspi, xfrm_state_byspi+h);
atomic_inc(&x->refcnt);
......@@ -382,7 +393,8 @@ xfrm_state_lookup(u32 daddr, u32 spi, u8 proto)
spin_lock_bh(&xfrm_state_lock);
list_for_each_entry(x, xfrm_state_byspi+h, byspi) {
if (spi == x->id.spi &&
if (x->props.family == AF_INET &&
spi == x->id.spi &&
daddr == x->id.daddr.xfrm4_addr &&
proto == x->id.proto) {
atomic_inc(&x->refcnt);
......@@ -405,7 +417,8 @@ xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr, int create)
spin_lock_bh(&xfrm_state_lock);
list_for_each_entry(x, xfrm_state_bydst+h, bydst) {
if (daddr == x->id.daddr.xfrm4_addr &&
if (x->props.family == AF_INET &&
daddr == x->id.daddr.xfrm4_addr &&
mode == x->props.mode &&
proto == x->id.proto &&
saddr == x->props.saddr.xfrm4_addr &&
......@@ -432,6 +445,7 @@ xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr, int create)
x0->km.state = XFRM_STATE_ACQ;
x0->id.daddr.xfrm4_addr = daddr;
x0->id.proto = proto;
x0->props.family = AF_INET;
x0->props.mode = mode;
x0->props.reqid = reqid;
x0->lft.hard_add_expires_seconds = ACQ_EXPIRES;
......@@ -591,8 +605,14 @@ int xfrm_check_selectors(struct xfrm_state **x, int n, struct flowi *fl)
int i;
for (i=0; i<n; i++) {
if (!xfrm4_selector_match(&x[i]->sel, fl))
if (x[i]->props.family == AF_INET &&
!xfrm4_selector_match(&x[i]->sel, fl))
return -EINVAL;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
if (x[i]->props.family == AF_INET6 &&
!xfrm6_selector_match(&x[i]->sel, fl))
return -EINVAL;
#endif
}
return 0;
}
......@@ -701,3 +721,119 @@ void __init xfrm_state_init(void)
INIT_LIST_HEAD(&xfrm_state_byspi[i]);
}
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
struct xfrm_state *
xfrm6_state_lookup(struct in6_addr *daddr, u32 spi, u8 proto)
{
unsigned h = ntohl(daddr->s6_addr32[2]^daddr->s6_addr32[3]^spi^proto);
struct xfrm_state *x;
h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE;
spin_lock_bh(&xfrm_state_lock);
list_for_each_entry(x, xfrm_state_byspi+h, byspi) {
if (x->props.family == AF_INET6 &&
spi == x->id.spi &&
!ipv6_addr_cmp(daddr, (struct in6_addr *)x->id.daddr.a6) &&
proto == x->id.proto) {
atomic_inc(&x->refcnt);
spin_unlock_bh(&xfrm_state_lock);
return x;
}
}
spin_unlock_bh(&xfrm_state_lock);
return NULL;
}
struct xfrm_state *
xfrm6_find_acq(u8 mode, u16 reqid, u8 proto, struct in6_addr *daddr, struct in6_addr *saddr, int create)
{
struct xfrm_state *x, *x0;
unsigned h = ntohl(daddr->s6_addr32[2]^daddr->s6_addr32[3]);
h = (h ^ (h>>16)) % XFRM_DST_HSIZE;
x0 = NULL;
spin_lock_bh(&xfrm_state_lock);
list_for_each_entry(x, xfrm_state_bydst+h, bydst) {
if (x->props.family == AF_INET6 &&
!memcmp(daddr, x->id.daddr.a6, sizeof(struct in6_addr)) &&
mode == x->props.mode &&
proto == x->id.proto &&
!memcmp(saddr, x->props.saddr.a6, sizeof(struct in6_addr)) &&
reqid == x->props.reqid &&
x->km.state == XFRM_STATE_ACQ) {
if (!x0)
x0 = x;
if (x->id.spi)
continue;
x0 = x;
break;
}
}
if (x0) {
atomic_inc(&x0->refcnt);
} else if (create && (x0 = xfrm_state_alloc()) != NULL) {
memcpy(x0->sel.daddr.a6, daddr, sizeof(struct in6_addr));
memcpy(x0->sel.saddr.a6, saddr, sizeof(struct in6_addr));
x0->sel.prefixlen_d = 128;
x0->sel.prefixlen_s = 128;
memcpy(x0->props.saddr.a6, saddr, sizeof(struct in6_addr));
x0->km.state = XFRM_STATE_ACQ;
memcpy(x0->id.daddr.a6, daddr, sizeof(struct in6_addr));
x0->id.proto = proto;
x0->props.family = AF_INET6;
x0->props.mode = mode;
x0->props.reqid = reqid;
x0->lft.hard_add_expires_seconds = ACQ_EXPIRES;
atomic_inc(&x0->refcnt);
mod_timer(&x0->timer, jiffies + ACQ_EXPIRES*HZ);
atomic_inc(&x0->refcnt);
list_add_tail(&x0->bydst, xfrm_state_bydst+h);
wake_up(&km_waitq);
}
spin_unlock_bh(&xfrm_state_lock);
return x0;
}
void
xfrm6_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi)
{
u32 h;
struct xfrm_state *x0;
if (x->id.spi)
return;
if (minspi == maxspi) {
x0 = xfrm6_state_lookup((struct in6_addr*)x->id.daddr.a6, minspi, x->id.proto);
if (x0) {
xfrm_state_put(x0);
return;
}
x->id.spi = minspi;
} else {
u32 spi = 0;
minspi = ntohl(minspi);
maxspi = ntohl(maxspi);
for (h=0; h<maxspi-minspi+1; h++) {
spi = minspi + net_random()%(maxspi-minspi+1);
x0 = xfrm6_state_lookup((struct in6_addr*)x->id.daddr.a6, htonl(spi), x->id.proto);
if (x0 == NULL)
break;
xfrm_state_put(x0);
}
x->id.spi = htonl(spi);
}
if (x->id.spi) {
spin_lock_bh(&xfrm_state_lock);
h = ntohl(x->id.daddr.a6[2]^x->id.daddr.a6[3]^x->id.spi^x->id.proto);
h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE;
list_add(&x->byspi, xfrm_state_byspi+h);
atomic_inc(&x->refcnt);
spin_unlock_bh(&xfrm_state_lock);
wake_up(&km_waitq);
}
}
#endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */
......@@ -11,3 +11,5 @@ ipv6-objs := af_inet6.o ip6_output.o ip6_input.o addrconf.o sit.o \
ip6_flowlabel.o ipv6_syms.o
obj-$(CONFIG_NETFILTER) += netfilter/
obj-y += xfrm_policy.o
......@@ -4,6 +4,7 @@
#include <net/ipv6.h>
#include <net/addrconf.h>
#include <net/ip6_route.h>
#include <net/xfrm.h>
EXPORT_SYMBOL(ipv6_addr_type);
EXPORT_SYMBOL(icmpv6_send);
......@@ -25,3 +26,6 @@ EXPORT_SYMBOL(inet6_getname);
EXPORT_SYMBOL(inet6_ioctl);
EXPORT_SYMBOL(ipv6_get_saddr);
EXPORT_SYMBOL(ipv6_chk_addr);
EXPORT_SYMBOL(xfrm6_register_type);
EXPORT_SYMBOL(xfrm6_unregister_type);
EXPORT_SYMBOL(xfrm6_get_type);
......@@ -628,19 +628,37 @@ static int sysctl_maxlen = IPQ_QMAX_DEFAULT;
static struct ctl_table_header *ipq_sysctl_header;
static ctl_table ipq_table[] = {
{ NET_IPQ_QMAX, NET_IPQ_QMAX_NAME, &sysctl_maxlen,
sizeof(sysctl_maxlen), 0644, NULL, proc_dointvec },
{ 0 }
{
.ctl_name = NET_IPQ_QMAX,
.procname = NET_IPQ_QMAX_NAME,
.data = &sysctl_maxlen,
.maxlen = sizeof(sysctl_maxlen),
.mode = 0644,
.proc_handler = proc_dointvec
},
{ .ctl_name = 0 }
};
static ctl_table ipq_dir_table[] = {
{NET_IPV6, "ipv6", NULL, 0, 0555, ipq_table, 0, 0, 0, 0, 0},
{ 0 }
{
.ctl_name = NET_IPV6,
.procname = "ipv6",
.maxlen = 0,
.mode = 0555,
.child = ipq_table
},
{ .ctl_name = 0 }
};
static ctl_table ipq_root_table[] = {
{CTL_NET, "net", NULL, 0, 0555, ipq_dir_table, 0, 0, 0, 0, 0},
{ 0 }
{
.ctl_name = CTL_NET,
.procname = "net",
.maxlen = 0,
.mode = 0555,
.child = ipq_dir_table
},
{ .ctl_name = 0 }
};
static int
......
......@@ -20,24 +20,54 @@ extern ctl_table ipv6_icmp_table[];
#ifdef CONFIG_SYSCTL
ctl_table ipv6_table[] = {
{NET_IPV6_ROUTE, "route", NULL, 0, 0555, ipv6_route_table},
{NET_IPV6_ICMP, "icmp", NULL, 0, 0500, ipv6_icmp_table},
{NET_IPV6_BINDV6ONLY, "bindv6only",
&sysctl_ipv6_bindv6only, sizeof(int), 0644, NULL, &proc_dointvec},
{0}
{
.ctl_name = NET_IPV6_ROUTE,
.procname = "route",
.maxlen = 0,
.mode = 0555,
.child = ipv6_route_table
},
{
.ctl_name = NET_IPV6_ICMP,
.procname = "icmp",
.maxlen = 0,
.mode = 0500,
.child = ipv6_icmp_table
},
{
.ctl_name = NET_IPV6_BINDV6ONLY,
.procname = "bindv6only",
.data = &sysctl_ipv6_bindv6only,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
},
{ .ctl_name = 0 }
};
#ifdef MODULE
static struct ctl_table_header *ipv6_sysctl_header;
static ctl_table ipv6_net_table[] = {
{NET_IPV6, "ipv6", NULL, 0, 0555, ipv6_table},
{0}
{
.ctl_name = NET_IPV6,
.procname = "ipv6",
.maxlen = 0,
.mode = 0555,
.child = ipv6_table
},
{ .ctl_name = 0 }
};
static ctl_table ipv6_root_table[] = {
{CTL_NET, "net", NULL, 0, 0555, ipv6_net_table},
{0}
{
.ctl_name = CTL_NET,
.procname = "net",
.maxlen = 0,
.mode = 0555,
.child = ipv6_net_table
},
{ .ctl_name = 0 }
};
void ipv6_sysctl_register(void)
......
#include <net/xfrm.h>
#include <net/ip.h>
static struct xfrm_type *xfrm6_type_map[256];
static rwlock_t xfrm6_type_lock = RW_LOCK_UNLOCKED;
int xfrm6_register_type(struct xfrm_type *type)
{
int err = 0;
write_lock(&xfrm6_type_lock);
if (xfrm6_type_map[type->proto] == NULL)
xfrm6_type_map[type->proto] = type;
else
err = -EEXIST;
write_unlock(&xfrm6_type_lock);
return err;
}
int xfrm6_unregister_type(struct xfrm_type *type)
{
int err = 0;
write_lock(&xfrm6_type_lock);
if (xfrm6_type_map[type->proto] != type)
err = -ENOENT;
else
xfrm6_type_map[type->proto] = NULL;
write_unlock(&xfrm6_type_lock);
return err;
}
struct xfrm_type *xfrm6_get_type(u8 proto)
{
struct xfrm_type *type;
read_lock(&xfrm6_type_lock);
type = xfrm6_type_map[proto];
if (type && !try_module_get(type->owner))
type = NULL;
read_unlock(&xfrm6_type_lock);
return type;
}
......@@ -99,60 +99,175 @@ static int do_devname(ctl_table *table, int write, struct file *filp,
/* One file */
static ctl_table irda_table[] = {
{ DISCOVERY, "discovery", &sysctl_discovery,
sizeof(int), 0644, NULL, &proc_dointvec },
{ DEVNAME, "devname", sysctl_devname,
65, 0644, NULL, &do_devname, &sysctl_string},
{
.ctl_name = DISCOVERY,
.procname = "discovery",
.data = &sysctl_discovery,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
},
{
.ctl_name = DEVNAME,
.procname = "devname",
.data = sysctl_devname,
.maxlen = 65,
.mode = 0644,
.proc_handler = &do_devname,
.strategy = &sysctl_string
},
#ifdef CONFIG_IRDA_DEBUG
{ DEBUG, "debug", &irda_debug,
sizeof(int), 0644, NULL, &proc_dointvec },
{
.ctl_name = DEBUG,
.procname = "debug",
.data = &irda_debug,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
},
#endif
#ifdef CONFIG_IRDA_FAST_RR
{ FAST_POLL, "fast_poll_increase", &sysctl_fast_poll_increase,
sizeof(int), 0644, NULL, &proc_dointvec },
{
.ctl_name = FAST_POLL,
.procname = "fast_poll_increase",
.data = &sysctl_fast_poll_increase,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
},
#endif
{ DISCOVERY_SLOTS, "discovery_slots", &sysctl_discovery_slots,
sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
NULL, &min_discovery_slots, &max_discovery_slots },
{ DISCOVERY_TIMEOUT, "discovery_timeout", &sysctl_discovery_timeout,
sizeof(int), 0644, NULL, &proc_dointvec },
{ SLOT_TIMEOUT, "slot_timeout", &sysctl_slot_timeout,
sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
NULL, &min_slot_timeout, &max_slot_timeout },
{ MAX_BAUD_RATE, "max_baud_rate", &sysctl_max_baud_rate,
sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
NULL, &min_max_baud_rate, &max_max_baud_rate },
{ MIN_TX_TURN_TIME, "min_tx_turn_time", &sysctl_min_tx_turn_time,
sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
NULL, &min_min_tx_turn_time, &max_min_tx_turn_time },
{ MAX_TX_DATA_SIZE, "max_tx_data_size", &sysctl_max_tx_data_size,
sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
NULL, &min_max_tx_data_size, &max_max_tx_data_size },
{ MAX_TX_WINDOW, "max_tx_window", &sysctl_max_tx_window,
sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
NULL, &min_max_tx_window, &max_max_tx_window },
{ MAX_NOREPLY_TIME, "max_noreply_time", &sysctl_max_noreply_time,
sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
NULL, &min_max_noreply_time, &max_max_noreply_time },
{ WARN_NOREPLY_TIME, "warn_noreply_time", &sysctl_warn_noreply_time,
sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
NULL, &min_warn_noreply_time, &max_warn_noreply_time },
{ LAP_KEEPALIVE_TIME, "lap_keepalive_time", &sysctl_lap_keepalive_time,
sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
NULL, &min_lap_keepalive_time, &max_lap_keepalive_time },
{ 0 }
{
.ctl_name = DISCOVERY_SLOTS,
.procname = "discovery_slots",
.data = &sysctl_discovery_slots,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_discovery_slots,
.extra2 = &max_discovery_slots
},
{
.ctl_name = DISCOVERY_TIMEOUT,
.procname = "discovery_timeout",
.data = &sysctl_discovery_timeout,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
},
{
.ctl_name = SLOT_TIMEOUT,
.procname = "slot_timeout",
.data = &sysctl_slot_timeout,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_slot_timeout,
.extra2 = &max_slot_timeout
},
{
.ctl_name = MAX_BAUD_RATE,
.procname = "max_baud_rate",
.data = &sysctl_max_baud_rate,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_max_baud_rate,
.extra2 = &max_max_baud_rate
},
{
.ctl_name = MIN_TX_TURN_TIME,
.procname = "min_tx_turn_time",
.data = &sysctl_min_tx_turn_time,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_min_tx_turn_time,
.extra2 = &max_min_tx_turn_time
},
{
.ctl_name = MAX_TX_DATA_SIZE,
.procname = "max_tx_data_size",
.data = &sysctl_max_tx_data_size,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_max_tx_data_size,
.extra2 = &max_max_tx_data_size
},
{
.ctl_name = MAX_TX_WINDOW,
.procname = "max_tx_window",
.data = &sysctl_max_tx_window,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_max_tx_window,
.extra2 = &max_max_tx_window
},
{
.ctl_name = MAX_NOREPLY_TIME,
.procname = "max_noreply_time",
.data = &sysctl_max_noreply_time,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_max_noreply_time,
.extra2 = &max_max_noreply_time
},
{
.ctl_name = WARN_NOREPLY_TIME,
.procname = "warn_noreply_time",
.data = &sysctl_warn_noreply_time,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_warn_noreply_time,
.extra2 = &max_warn_noreply_time
},
{
.ctl_name = LAP_KEEPALIVE_TIME,
.procname = "lap_keepalive_time",
.data = &sysctl_lap_keepalive_time,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec_minmax,
.strategy = &sysctl_intvec,
.extra1 = &min_lap_keepalive_time,
.extra2 = &max_lap_keepalive_time
},
{ .ctl_name = 0 }
};
/* One directory */
static ctl_table irda_net_table[] = {
{ NET_IRDA, "irda", NULL, 0, 0555, irda_table },
{ 0 }
{
.ctl_name = NET_IRDA,
.procname = "irda",
.maxlen = 0,
.mode = 0555,
.child = irda_table
},
{ .ctl_name = 0 }
};
/* The parent directory */
static ctl_table irda_root_table[] = {
{ CTL_NET, "net", NULL, 0, 0555, irda_net_table },
{ 0 }
{
.ctl_name = CTL_NET,
.procname = "net",
.maxlen = 0,
.mode = 0555,
.child = irda_net_table
},
{ .ctl_name = 0 }
};
static struct ctl_table_header *irda_table_header;
......
This diff is collapsed.
......@@ -324,6 +324,11 @@ EXPORT_SYMBOL(xfrm_policy_walk);
EXPORT_SYMBOL(xfrm_policy_flush);
EXPORT_SYMBOL(xfrm_policy_byid);
EXPORT_SYMBOL(xfrm_policy_list);
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
EXPORT_SYMBOL(xfrm6_state_lookup);
EXPORT_SYMBOL(xfrm6_find_acq);
EXPORT_SYMBOL(xfrm6_alloc_spi);
#endif
EXPORT_SYMBOL_GPL(xfrm_probe_algs);
EXPORT_SYMBOL_GPL(xfrm_count_auth_supported);
......
......@@ -6,7 +6,7 @@ menu "SCTP Configuration (EXPERIMENTAL)"
depends on INET && EXPERIMENTAL
config IPV6_SCTP__
bool
tristate
default y if IPV6=n
default IPV6 if IPV6
......
......@@ -10,7 +10,7 @@ sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \
inqueue.o outqueue.o ulpqueue.o command.o \
tsnmap.o bind_addr.o socket.o primitive.o \
output.o input.o hashdriver.o sla1.o \
debug.o
debug.o ssnmap.o
ifeq ($(CONFIG_SCTP_ADLER32), y)
sctp-y += adler32.o
......
/* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2003 International Business Machines, Corp.
*
* This file is part of the SCTP kernel reference Implementation
*
......@@ -36,6 +37,7 @@
* Randall Stewart <rstewar1@email.mot.com>
* Ken Morneau <kmorneau@cisco.com>
* Qiaobing Xie <qxie1@email.mot.com>
* Sridhar Samudrala <sri@us.ibm.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
......@@ -122,7 +124,7 @@ unsigned long update_adler32(unsigned long adler,
return (s2 << 16) + s1;
}
__u32 count_crc(__u8 *ptr, __u16 count)
__u32 sctp_start_cksum(__u8 *ptr, __u16 count)
{
/*
* Update a running Adler-32 checksum with the bytes
......@@ -146,3 +148,15 @@ __u32 count_crc(__u8 *ptr, __u16 count)
return adler;
}
__u32 sctp_update_cksum(__u8 *ptr, __u16 count, __u32 adler)
{
adler = update_adler32(adler, ptr, count);
return adler;
}
__u32 sctp_end_cksum(__u32 adler)
{
return adler;
}
This diff is collapsed.
......@@ -47,8 +47,8 @@ sctp_cmd_seq_t *sctp_new_cmd_seq(int priority)
{
sctp_cmd_seq_t *retval = t_new(sctp_cmd_seq_t, priority);
/* XXX Check for NULL? -DaveM */
sctp_init_cmd_seq(retval);
if (retval)
sctp_init_cmd_seq(retval);
return retval;
}
......
/* SCTP kernel reference Implementation
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 International Business Machines, Corp.
* Copyright (c) 2001-2003 International Business Machines, Corp.
*
* This file is part of the SCTP kernel reference Implementation
*
......@@ -33,6 +33,7 @@
* Written or modified by:
* Dinakaran Joseph
* Jon Grimm <jgrimm@us.ibm.com>
* Sridhar Samudrala <sri@us.ibm.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
......@@ -135,11 +136,10 @@ __u32 crc_c[256] = {
0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351,
};
__u32 count_crc(__u8 *buffer, __u16 length)
__u32 sctp_start_cksum(__u8 *buffer, __u16 length)
{
__u32 crc32 = ~(__u32) 0;
__u32 i, result;
__u8 byte0, byte1, byte2, byte3;
__u32 i;
/* Optimize this routine to be SCTP specific, knowing how
* to skip the checksum field of the SCTP header.
......@@ -157,6 +157,24 @@ __u32 count_crc(__u8 *buffer, __u16 length)
for (i = sizeof(struct sctphdr); i < length ; i++)
CRC32C(crc32, buffer[i]);
return crc32;
}
__u32 sctp_update_cksum(__u8 *buffer, __u16 length, __u32 crc32)
{
__u32 i;
for (i = 0; i < length ; i++)
CRC32C(crc32, buffer[i]);
return crc32;
}
__u32 sctp_end_cksum(__u32 crc32)
{
__u32 result;
__u8 byte0, byte1, byte2, byte3;
result = ~crc32;
/* result now holds the negated polynomial remainder;
......@@ -183,5 +201,3 @@ __u32 count_crc(__u8 *buffer, __u16 length)
byte3);
return crc32;
}
......@@ -148,22 +148,11 @@ const char *sctp_status_tbl[] = {
/* Printable forms of primitives */
static const char *sctp_primitive_tbl[SCTP_NUM_PRIMITIVE_TYPES] = {
"PRIMITIVE_INITIALIZE",
"PRIMITIVE_ASSOCIATE",
"PRIMITIVE_SHUTDOWN",
"PRIMITIVE_ABORT",
"PRIMITIVE_SEND",
"PRIMITIVE_SETPRIMARY",
"PRIMITIVE_RECEIVE",
"PRIMITIVE_STATUS",
"PRIMITIVE_CHANGEHEARTBEAT",
"PRIMITIVE_REQUESTHEARTBEAT",
"PRIMITIVE_GETSRTTREPORT",
"PRIMITIVE_SETFAILURETHRESHOLD",
"PRIMITIVE_SETPROTOPARAMETERS",
"PRIMITIVE_RECEIVE_UNSENT",
"PRIMITIVE_RECEIVE_UNACKED",
"PRIMITIVE_DESTROY"
};
/* Lookup primitive debug name. */
......@@ -178,7 +167,6 @@ const char *sctp_pname(const sctp_subtype_t id)
static const char *sctp_other_tbl[] = {
"NO_PENDING_TSN",
"ICMP_UNREACHFRAG"
};
/* Lookup "other" debug name. */
......@@ -197,12 +185,10 @@ static const char *sctp_timer_tbl[] = {
"TIMEOUT_T1_INIT",
"TIMEOUT_T2_SHUTDOWN",
"TIMEOUT_T3_RTX",
"TIMEOUT_T4_RTO",
"TIMEOUT_T5_SHUTDOWN_GUARD",
"TIMEOUT_HEARTBEAT",
"TIMEOUT_SACK",
"TIMEOUT_AUTOCLOSE",
"TIMEOUT_PMTU_RAISE",
};
/* Lookup timer debug name. */
......
......@@ -137,7 +137,6 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep, sctp_protocol_t *proto,
ep->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] =
sp->rtoinfo.srto_initial;
ep->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0;
ep->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = 0;
/* sctpimpguide-05 Section 2.12.2
* If the 'T5-shutdown-guard' timer is used, it SHOULD be set to the
......@@ -152,8 +151,6 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep, sctp_protocol_t *proto,
SCTP_DEFAULT_TIMEOUT_SACK;
ep->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
sp->autoclose * HZ;
ep->timeouts[SCTP_EVENT_TIMEOUT_PMTU_RAISE] =
SCTP_DEFAULT_TIMEOUT_PMTU_RAISE;
/* Set up the default send/receive buffer space. */
......@@ -264,7 +261,7 @@ sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *ep,
sctp_association_t *__sctp_endpoint_lookup_assoc(
const sctp_endpoint_t *endpoint,
const union sctp_addr *paddr,
sctp_transport_t **transport)
struct sctp_transport **transport)
{
int rport;
sctp_association_t *asoc;
......@@ -289,9 +286,10 @@ sctp_association_t *__sctp_endpoint_lookup_assoc(
}
/* Lookup association on an endpoint based on a peer address. BH-safe. */
sctp_association_t *sctp_endpoint_lookup_assoc(const sctp_endpoint_t *ep,
const union sctp_addr *paddr,
sctp_transport_t **transport)
sctp_association_t *sctp_endpoint_lookup_assoc(
const sctp_endpoint_t *ep,
const union sctp_addr *paddr,
struct sctp_transport **transport)
{
sctp_association_t *asoc;
......@@ -333,7 +331,7 @@ static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep)
{
sctp_association_t *asoc;
struct sock *sk;
sctp_transport_t *transport;
struct sctp_transport *transport;
sctp_chunk_t *chunk;
sctp_inqueue_t *inqueue;
sctp_subtype_t subtype;
......
/* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 International Business Machines, Corp.
* Copyright (c) 2001-2003 International Business Machines, Corp.
* Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll
......@@ -53,6 +53,9 @@
#include <linux/socket.h>
#include <linux/ip.h>
#include <linux/time.h> /* For struct timeval */
#include <net/ip.h>
#include <net/icmp.h>
#include <net/snmp.h>
#include <net/sock.h>
#include <net/xfrm.h>
#include <net/sctp/sctp.h>
......@@ -63,7 +66,7 @@ static int sctp_rcv_ootb(struct sk_buff *);
sctp_association_t *__sctp_rcv_lookup(struct sk_buff *skb,
const union sctp_addr *laddr,
const union sctp_addr *paddr,
sctp_transport_t **transportp);
struct sctp_transport **transportp);
sctp_endpoint_t *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr);
......@@ -72,10 +75,19 @@ static inline int sctp_rcv_checksum(struct sk_buff *skb)
{
struct sctphdr *sh;
__u32 cmp, val;
struct sk_buff *list = skb_shinfo(skb)->frag_list;
sh = (struct sctphdr *) skb->h.raw;
cmp = ntohl(sh->checksum);
val = count_crc((__u8 *)sh, skb->len);
val = sctp_start_cksum((__u8 *)sh, skb_headlen(skb));
for (; list; list = list->next)
val = sctp_update_cksum((__u8 *)list->data, skb_headlen(list),
val);
val = sctp_end_cksum(val);
if (val != cmp) {
/* CRC failure, dump it. */
return -1;
......@@ -92,7 +104,7 @@ int sctp_rcv(struct sk_buff *skb)
sctp_association_t *asoc;
sctp_endpoint_t *ep = NULL;
sctp_endpoint_common_t *rcvr;
sctp_transport_t *transport = NULL;
struct sctp_transport *transport = NULL;
sctp_chunk_t *chunk;
struct sctphdr *sh;
union sctp_addr src;
......@@ -248,6 +260,27 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
return 0;
}
/* Handle icmp frag needed error. */
static inline void sctp_icmp_frag_needed(struct sock *sk,
sctp_association_t *asoc,
struct sctp_transport *transport,
__u32 pmtu)
{
if (unlikely(pmtu < SCTP_DEFAULT_MINSEGMENT)) {
printk(KERN_WARNING "%s: Reported pmtu %d too low, "
"using default minimum of %d\n", __FUNCTION__, pmtu,
SCTP_DEFAULT_MINSEGMENT);
pmtu = SCTP_DEFAULT_MINSEGMENT;
}
if (!sock_owned_by_user(sk) && transport && (transport->pmtu != pmtu)) {
transport->pmtu = pmtu;
sctp_assoc_sync_pmtu(asoc);
sctp_retransmit(&asoc->outqueue, transport,
SCTP_RETRANSMIT_PMTU_DISCOVERY );
}
}
/*
* This routine is called by the ICMP module when it gets some
* sort of error condition. If err < 0 then the socket should
......@@ -263,9 +296,109 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
* is probably better.
*
*/
void sctp_v4_err(struct sk_buff *skb, u32 info)
void sctp_v4_err(struct sk_buff *skb, __u32 info)
{
/* This should probably involve a call to SCTPhandleICMP(). */
struct iphdr *iph = (struct iphdr *)skb->data;
struct sctphdr *sh = (struct sctphdr *)(skb->data + (iph->ihl <<2));
int type = skb->h.icmph->type;
int code = skb->h.icmph->code;
union sctp_addr saddr, daddr;
struct inet_opt *inet;
struct sock *sk = NULL;
sctp_endpoint_t *ep = NULL;
sctp_association_t *asoc = NULL;
struct sctp_transport *transport;
int err;
if (skb->len < ((iph->ihl << 2) + 8)) {
ICMP_INC_STATS_BH(IcmpInErrors);
return;
}
saddr.v4.sin_family = AF_INET;
saddr.v4.sin_port = ntohs(sh->source);
memcpy(&saddr.v4.sin_addr.s_addr, &iph->saddr, sizeof(struct in_addr));
daddr.v4.sin_family = AF_INET;
daddr.v4.sin_port = ntohs(sh->dest);
memcpy(&daddr.v4.sin_addr.s_addr, &iph->daddr, sizeof(struct in_addr));
/* Look for an association that matches the incoming ICMP error
* packet.
*/
asoc = __sctp_lookup_association(&saddr, &daddr, &transport);
if (!asoc) {
/* If there is no matching association, see if it matches any
* endpoint. This may happen for an ICMP error generated in
* response to an INIT_ACK.
*/
ep = __sctp_rcv_lookup_endpoint(&daddr);
if (!ep) {
ICMP_INC_STATS_BH(IcmpInErrors);
return;
}
}
if (asoc) {
if (ntohl(sh->vtag) != asoc->c.peer_vtag) {
ICMP_INC_STATS_BH(IcmpInErrors);
goto out;
}
sk = asoc->base.sk;
} else
sk = ep->base.sk;
sctp_bh_lock_sock(sk);
/* If too many ICMPs get dropped on busy
* servers this needs to be solved differently.
*/
if (sock_owned_by_user(sk))
NET_INC_STATS_BH(LockDroppedIcmps);
switch (type) {
case ICMP_PARAMETERPROB:
err = EPROTO;
break;
case ICMP_DEST_UNREACH:
if (code > NR_ICMP_UNREACH)
goto out_unlock;
/* PMTU discovery (RFC1191) */
if (ICMP_FRAG_NEEDED == code) {
sctp_icmp_frag_needed(sk, asoc, transport, info);
goto out_unlock;
}
err = icmp_err_convert[code].errno;
break;
case ICMP_TIME_EXCEEDED:
/* Ignore any time exceeded errors due to fragment reassembly
* timeouts.
*/
if (ICMP_EXC_FRAGTIME == code)
goto out_unlock;
err = EHOSTUNREACH;
break;
default:
goto out_unlock;
}
inet = inet_sk(sk);
if (!sock_owned_by_user(sk) && inet->recverr) {
sk->err = err;
sk->error_report(sk);
} else { /* Only an error on timeout */
sk->err_soft = err;
}
out_unlock:
sctp_bh_unlock_sock(sk);
out:
sock_put(sk);
if (asoc)
sctp_association_put(asoc);
if (ep)
sctp_endpoint_put(ep);
}
/*
......@@ -303,17 +436,17 @@ int sctp_rcv_ootb(struct sk_buff *skb)
* chunk, the receiver should silently discard the packet
* and take no further action.
*/
if (ch->type == SCTP_CID_SHUTDOWN_COMPLETE)
if (SCTP_CID_SHUTDOWN_COMPLETE == ch->type)
goto discard;
/* RFC 8.4, 7) If the packet contains a "Stale cookie" ERROR
* or a COOKIE ACK the SCTP Packet should be silently
* discarded.
*/
if (ch->type == SCTP_CID_COOKIE_ACK)
if (SCTP_CID_COOKIE_ACK == ch->type)
goto discard;
if (ch->type == SCTP_CID_ERROR) {
if (SCTP_CID_ERROR == ch->type) {
err = (sctp_errhdr_t *)(ch + sizeof(sctp_chunkhdr_t));
if (SCTP_ERROR_STALE_COOKIE == err->cause)
goto discard;
......@@ -485,12 +618,12 @@ void __sctp_unhash_established(sctp_association_t *asoc)
/* Look up an association. */
sctp_association_t *__sctp_lookup_association(const union sctp_addr *laddr,
const union sctp_addr *paddr,
sctp_transport_t **transportp)
struct sctp_transport **transportp)
{
sctp_hashbucket_t *head;
sctp_endpoint_common_t *epb;
sctp_association_t *asoc;
sctp_transport_t *transport;
struct sctp_transport *transport;
int hash;
/* Optimize here for direct hit, only listening connections can
......@@ -521,7 +654,7 @@ sctp_association_t *__sctp_lookup_association(const union sctp_addr *laddr,
/* Look up an association. BH-safe. */
sctp_association_t *sctp_lookup_association(const union sctp_addr *laddr,
const union sctp_addr *paddr,
sctp_transport_t **transportp)
struct sctp_transport **transportp)
{
sctp_association_t *asoc;
......@@ -537,7 +670,7 @@ int sctp_has_association(const union sctp_addr *laddr,
const union sctp_addr *paddr)
{
sctp_association_t *asoc;
sctp_transport_t *transport;
struct sctp_transport *transport;
if ((asoc = sctp_lookup_association(laddr, paddr, &transport))) {
sock_put(asoc->base.sk);
......@@ -567,7 +700,7 @@ int sctp_has_association(const union sctp_addr *laddr,
*
*/
static sctp_association_t *__sctp_rcv_init_lookup(struct sk_buff *skb,
const union sctp_addr *laddr, sctp_transport_t **transportp)
const union sctp_addr *laddr, struct sctp_transport **transportp)
{
sctp_association_t *asoc;
union sctp_addr addr;
......@@ -627,7 +760,7 @@ static sctp_association_t *__sctp_rcv_init_lookup(struct sk_buff *skb,
sctp_association_t *__sctp_rcv_lookup(struct sk_buff *skb,
const union sctp_addr *paddr,
const union sctp_addr *laddr,
sctp_transport_t **transportp)
struct sctp_transport **transportp)
{
sctp_association_t *asoc;
......
......@@ -98,43 +98,22 @@ static inline void sctp_v6_err(struct sk_buff *skb,
}
/* Based on tcp_v6_xmit() in tcp_ipv6.c. */
static inline int sctp_v6_xmit(struct sk_buff *skb)
static inline int sctp_v6_xmit(struct sk_buff *skb,
struct sctp_transport *transport, int ipfragok)
{
struct sock *sk = skb->sk;
struct ipv6_pinfo *np = inet6_sk(sk);
struct flowi fl;
struct dst_entry *dst = skb->dst;
struct rt6_info *rt6 = (struct rt6_info *)dst;
struct in6_addr saddr;
int err;
fl.proto = sk->protocol;
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.
/* Fill in the dest address from the route entry passed with the skb
* and the source address from the transport.
*/
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_dst = &rt6->rt6i_dst.addr;
fl.fl6_src = &transport->saddr.v6.sin6_addr;
fl.fl6_flowlabel = np->flow_label;
IP6_ECN_flow_xmit(sk, fl.fl6_flowlabel);
......@@ -147,20 +126,26 @@ static inline int sctp_v6_xmit(struct sk_buff *skb)
fl.nl_u.ip6_u.daddr = rt0->addr;
}
SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, "
"src:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x "
"dst:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
__FUNCTION__, skb, skb->len, NIP6(fl.fl6_src),
NIP6(fl.fl6_dst));
return ip6_xmit(sk, skb, &fl, np->opt);
}
/* Returns the dst cache entry for the given source and destination ip
* addresses.
*/
struct dst_entry *sctp_v6_get_dst(union sctp_addr *daddr,
struct dst_entry *sctp_v6_get_dst(sctp_association_t *asoc,
union sctp_addr *daddr,
union sctp_addr *saddr)
{
struct dst_entry *dst;
struct flowi fl = {
.nl_u = { .ip6_u = { .daddr = &daddr->v6.sin6_addr, } } };
SCTP_DEBUG_PRINTK("%s: DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ",
__FUNCTION__, NIP6(fl.fl6_dst));
......@@ -181,12 +166,96 @@ struct dst_entry *sctp_v6_get_dst(union sctp_addr *daddr,
NIP6(&rt->rt6i_dst.addr), NIP6(&rt->rt6i_src.addr));
} else {
SCTP_DEBUG_PRINTK("NO ROUTE\n");
return NULL;
}
return dst;
}
/* Returns the number of consecutive initial bits that match in the 2 ipv6
* addresses.
*/
static inline int sctp_v6_addr_match_len(union sctp_addr *s1,
union sctp_addr *s2)
{
struct in6_addr *a1 = &s1->v6.sin6_addr;
struct in6_addr *a2 = &s2->v6.sin6_addr;
int i, j;
for (i = 0; i < 4 ; i++) {
__u32 a1xora2;
a1xora2 = a1->s6_addr32[i] ^ a2->s6_addr32[i];
if ((j = fls(ntohl(a1xora2))))
return (i * 32 + 32 - j);
}
return (i*32);
}
/* Fills in the source address(saddr) based on the destination address(daddr)
* and asoc's bind address list.
*/
void sctp_v6_get_saddr(sctp_association_t *asoc, struct dst_entry *dst,
union sctp_addr *daddr, union sctp_addr *saddr)
{
sctp_bind_addr_t *bp;
rwlock_t *addr_lock;
struct sockaddr_storage_list *laddr;
struct list_head *pos;
sctp_scope_t scope;
union sctp_addr *baddr = NULL;
__u8 matchlen = 0;
__u8 bmatchlen;
SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p "
"daddr:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ",
__FUNCTION__, asoc, dst, NIP6(&daddr->v6.sin6_addr));
if (!asoc) {
ipv6_get_saddr(dst, &daddr->v6.sin6_addr, &saddr->v6.sin6_addr);
SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: "
"%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
NIP6(&saddr->v6.sin6_addr));
return;
}
scope = sctp_scope(daddr);
bp = &asoc->base.bind_addr;
addr_lock = &asoc->base.addr_lock;
/* Go through the bind address list and find the best source address
* that matches the scope of the destination address.
*/
sctp_read_lock(addr_lock);
list_for_each(pos, &bp->address_list) {
laddr = list_entry(pos, struct sockaddr_storage_list, list);
if ((laddr->a.sa.sa_family == AF_INET6) &&
(scope <= sctp_scope(&laddr->a))) {
bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a);
if (!baddr || (matchlen < bmatchlen)) {
baddr = &laddr->a;
matchlen = bmatchlen;
}
}
}
if (baddr) {
memcpy(saddr, baddr, sizeof(union sctp_addr));
SCTP_DEBUG_PRINTK("saddr: "
"%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
NIP6(&saddr->v6.sin6_addr));
} else {
printk(KERN_ERR "%s: asoc:%p Could not find a valid source "
"address for the "
"dest:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
__FUNCTION__, asoc, NIP6(&daddr->v6.sin6_addr));
}
sctp_read_unlock(addr_lock);
}
/* Make a copy of all potential local addresses. */
static void sctp_v6_copy_addrlist(struct list_head *addrlist,
struct net_device *dev)
......@@ -257,10 +326,12 @@ static void sctp_v6_to_sk(union sctp_addr *addr, struct sock *sk)
}
/* 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,
unsigned short port)
{
struct rt6_info *rt = (struct rt6_info *)dst;
addr->sa.sa_family = AF_INET6;
addr->v6.sin6_port = port;
ipv6_addr_copy(&addr->v6.sin6_addr, &rt->rt6i_src.addr);
}
......@@ -527,10 +598,11 @@ static struct inet6_protocol sctpv6_protocol = {
};
static struct sctp_af sctp_ipv6_specific = {
.queue_xmit = sctp_v6_xmit,
.setsockopt = ipv6_setsockopt,
.sctp_xmit = sctp_v6_xmit,
.setsockopt = ipv6_setsockopt,
.getsockopt = ipv6_getsockopt,
.get_dst = sctp_v6_get_dst,
.get_saddr = sctp_v6_get_saddr,
.copy_addrlist = sctp_v6_copy_addrlist,
.from_skb = sctp_v6_from_skb,
.from_sk = sctp_v6_from_sk,
......@@ -572,7 +644,7 @@ int sctp_v6_init(void)
/* Register the SCTP specfic AF_INET6 functions. */
sctp_register_af(&sctp_ipv6_specific);
/* Register notifier for inet6 address additions/deletions. */
/* Register notifier for inet6 address additions/deletions. */
register_inet6addr_notifier(&sctp_inetaddr_notifier);
return 0;
......
......@@ -54,6 +54,7 @@ SCTP_DBG_OBJCNT(assoc);
SCTP_DBG_OBJCNT(bind_addr);
SCTP_DBG_OBJCNT(chunk);
SCTP_DBG_OBJCNT(addr);
SCTP_DBG_OBJCNT(ssnmap);
/* An array to make it easy to pretty print the debug information
* to the proc fs.
......@@ -66,6 +67,7 @@ sctp_dbg_objcnt_entry_t sctp_dbg_objcnt[] = {
SCTP_DBG_OBJCNT_ENTRY(chunk),
SCTP_DBG_OBJCNT_ENTRY(bind_addr),
SCTP_DBG_OBJCNT_ENTRY(addr),
SCTP_DBG_OBJCNT_ENTRY(ssnmap),
};
/* Callback from procfs to read out objcount information.
......
/* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 International Business Machines, Corp.
* Copyright (c) 2001-2003 International Business Machines, Corp.
*
* This file is part of the SCTP kernel reference Implementation
*
......@@ -62,7 +62,6 @@
#include <net/sctp/sm.h>
/* Forward declarations for private helpers. */
__u32 count_crc(__u8 *ptr, __u16 count);
static void sctp_packet_reset(sctp_packet_t *packet);
static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet,
sctp_chunk_t *chunk);
......@@ -81,6 +80,7 @@ sctp_packet_t *sctp_packet_config(sctp_packet_t *packet,
packet->ecn_capable = ecn_capable;
packet->get_prepend_chunk = prepend_handler;
packet->has_cookie_echo = 0;
packet->ipfragok = 0;
/* We might need to call the prepend_handler right away. */
if (packet_empty)
......@@ -90,7 +90,7 @@ sctp_packet_t *sctp_packet_config(sctp_packet_t *packet,
/* Initialize the packet structure. */
sctp_packet_t *sctp_packet_init(sctp_packet_t *packet,
sctp_transport_t *transport,
struct sctp_transport *transport,
__u16 sport,
__u16 dport)
{
......@@ -102,6 +102,7 @@ sctp_packet_t *sctp_packet_init(sctp_packet_t *packet,
packet->ecn_capable = 0;
packet->get_prepend_chunk = NULL;
packet->has_cookie_echo = 0;
packet->ipfragok = 0;
packet->malloced = 0;
sctp_packet_reset(packet);
return packet;
......@@ -193,6 +194,7 @@ sctp_xmit_t sctp_packet_append_chunk(sctp_packet_t *packet, sctp_chunk_t *chunk)
* transmit and rely on IP
* fragmentation.
*/
packet->ipfragok = 1;
goto append;
}
} else { /* !packet_empty */
......@@ -228,13 +230,13 @@ sctp_xmit_t sctp_packet_append_chunk(sctp_packet_t *packet, sctp_chunk_t *chunk)
}
/* All packets are sent to the network through this function from
* sctp_push_outqueue().
* sctp_outq_tail().
*
* The return value is a normal kernel error return value.
*/
int sctp_packet_transmit(sctp_packet_t *packet)
{
sctp_transport_t *transport = packet->transport;
struct sctp_transport *transport = packet->transport;
sctp_association_t *asoc = transport->asoc;
struct sctphdr *sh;
__u32 crc32;
......@@ -358,22 +360,14 @@ int sctp_packet_transmit(sctp_packet_t *packet)
* Note: Adler-32 is no longer applicable, as has been replaced
* by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>.
*/
crc32 = count_crc((__u8 *)sh, nskb->len);
crc32 = sctp_start_cksum((__u8 *)sh, nskb->len);
crc32 = sctp_end_cksum(crc32);
/* 3) Put the resultant value into the checksum field in the
* common header, and leave the rest of the bits unchanged.
*/
sh->checksum = htonl(crc32);
/* FIXME: Delete the rest of this switch statement once phase 2
* of address selection (ipv6 support) drops in.
*/
switch (transport->ipaddr.sa.sa_family) {
case AF_INET6:
SCTP_V6(inet6_sk(sk)->daddr = transport->ipaddr.v6.sin6_addr;)
break;
};
/* IP layer ECN support
* From RFC 2481
* "The ECN-Capable Transport (ECT) bit would be set by the
......@@ -423,8 +417,10 @@ int sctp_packet_transmit(sctp_packet_t *packet)
}
dst = transport->dst;
if (!dst || dst->obsolete) {
/* The 'obsolete' field of dst is set to 2 when a dst is freed. */
if (!dst || (dst->obsolete > 1)) {
sctp_transport_route(transport, NULL, sctp_sk(sk));
sctp_assoc_sync_pmtu(asoc);
}
nskb->dst = dst_clone(transport->dst);
......@@ -433,14 +429,22 @@ int sctp_packet_transmit(sctp_packet_t *packet)
SCTP_DEBUG_PRINTK("***sctp_transmit_packet*** skb length %d\n",
nskb->len);
(*transport->af_specific->queue_xmit)(nskb);
(*transport->af_specific->sctp_xmit)(nskb, transport, packet->ipfragok);
out:
packet->size = SCTP_IP_OVERHEAD;
return err;
no_route:
kfree_skb(nskb);
IP_INC_STATS_BH(IpOutNoRoutes);
err = -EHOSTUNREACH;
/* FIXME: Returning the 'err' will effect all the associations
* associated with a socket, although only one of the paths of the
* association is unreachable.
* The real failure of a transport or association can be passed on
* to the user via notifications. So setting this error may not be
* required.
*/
/* err = -EHOSTUNREACH; */
goto out;
}
......@@ -473,7 +477,7 @@ static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet,
{
sctp_xmit_t retval = SCTP_XMIT_OK;
size_t datasize, rwnd, inflight;
sctp_transport_t *transport = packet->transport;
struct sctp_transport *transport = packet->transport;
__u32 max_burst_bytes;
/* RFC 2960 6.1 Transmission of DATA Chunks
......
This diff is collapsed.
......@@ -203,23 +203,3 @@ DECLARE_PRIMITIVE(SEND);
*/
DECLARE_PRIMITIVE(REQUESTHEARTBEAT);
/* COMMENT BUG. Find out where this is mentioned in the spec. */
int sctp_other_icmp_unreachfrag(sctp_association_t *asoc, void *arg)
{
int error = 0;
sctp_event_t event_type;
sctp_subtype_t subtype;
sctp_state_t state;
sctp_endpoint_t *ep;
event_type = SCTP_EVENT_T_OTHER;
subtype = SCTP_ST_OTHER(SCTP_EVENT_ICMP_UNREACHFRAG);
state = asoc ? asoc->state : SCTP_STATE_CLOSED;
ep = asoc ? asoc->ep : NULL;
error = sctp_do_sm(event_type, subtype, state, ep,
asoc, arg, GFP_ATOMIC);
return error;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -116,23 +116,51 @@ proc_dodebug(ctl_table *table, int write, struct file *file,
return 0;
}
#define DIRENTRY(nam1, nam2, child) \
{CTL_##nam1, #nam2, NULL, 0, 0555, child }
#define DBGENTRY(nam1, nam2) \
{CTL_##nam1##DEBUG, #nam2 "_debug", &nam2##_debug, sizeof(int),\
0644, NULL, &proc_dodebug}
static ctl_table debug_table[] = {
DBGENTRY(RPC, rpc),
DBGENTRY(NFS, nfs),
DBGENTRY(NFSD, nfsd),
DBGENTRY(NLM, nlm),
{0}
static ctl_table debug_table[] = {
{
.ctl_name = CTL_RPCDEBUG,
.procname = "rpc_debug",
.data = &rpc_debug,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dodebug
},
{
.ctl_name = CTL_NFSDEBUG,
.procname = "nfs_debug",
.data = &nfs_debug,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dodebug
},
{
.ctl_name = CTL_NFSDDEBUG,
.procname = "nfsd_debug",
.data = &nfsd_debug,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dodebug
},
{
.ctl_name = CTL_NLMDEBUG,
.procname = "nlm_debug",
.data = &nlm_debug,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dodebug
},
{ .ctl_name = 0 }
};
static ctl_table sunrpc_table[] = {
DIRENTRY(SUNRPC, sunrpc, debug_table),
{0}
static ctl_table sunrpc_table[] = {
{
.ctl_name = CTL_SUNRPC,
.procname = "sunrpc",
.maxlen = 0,
.mode = 0555,
.child = debug_table
},
{ .ctl_name = 0 }
};
#endif
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