mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: (51 commits) [IPV6]: Fix again the fl6_sock_lookup() fixed locking [NETFILTER]: nf_conntrack_tcp: fix connection reopening fix [IPV6]: Fix race in ipv6_flowlabel_opt() when inserting two labels [IPV6]: Lost locking in fl6_sock_lookup [IPV6]: Lost locking when inserting a flowlabel in ipv6_fl_list [NETFILTER]: xt_sctp: fix mistake to pass a pointer where array is required [NET]: Fix OOPS due to missing check in dev_parse_header(). [TCP]: Remove lost_retrans zero seqno special cases [NET]: fix carrier-on bug? [NET]: Fix uninitialised variable in ip_frag_reasm() [IPSEC]: Rename mode to outer_mode and add inner_mode [IPSEC]: Disallow combinations of RO and AH/ESP/IPCOMP [IPSEC]: Use the top IPv4 route's peer instead of the bottom [IPSEC]: Store afinfo pointer in xfrm_mode [IPSEC]: Add missing BEET checks [IPSEC]: Move type and mode map into xfrm_state.c [IPSEC]: Fix length check in xfrm_parse_spi [IPSEC]: Move ip_summed zapping out of xfrm6_rcv_spi [IPSEC]: Get nexthdr from caller in xfrm6_rcv_spi [IPSEC]: Move tunnel parsing for IPv4 out of xfrm4_input ...
This commit is contained in:
commit
a57793651f
@ -31,10 +31,8 @@ void slip_init(struct net_device *dev, void *data)
|
||||
slip_proto_init(&spri->slip);
|
||||
|
||||
dev->init = NULL;
|
||||
dev->header_cache_update = NULL;
|
||||
dev->hard_header_cache = NULL;
|
||||
dev->hard_header = NULL;
|
||||
dev->hard_header_len = 0;
|
||||
dev->header_ops = NULL;
|
||||
dev->addr_len = 0;
|
||||
dev->type = ARPHRD_SLIP;
|
||||
dev->tx_queue_len = 256;
|
||||
|
@ -34,9 +34,7 @@ void slirp_init(struct net_device *dev, void *data)
|
||||
|
||||
dev->init = NULL;
|
||||
dev->hard_header_len = 0;
|
||||
dev->header_cache_update = NULL;
|
||||
dev->hard_header_cache = NULL;
|
||||
dev->hard_header = NULL;
|
||||
dev->header_ops = NULL;
|
||||
dev->addr_len = 0;
|
||||
dev->type = ARPHRD_SLIP;
|
||||
dev->tx_queue_len = 256;
|
||||
|
@ -56,8 +56,8 @@
|
||||
|
||||
#define DRV_MODULE_NAME "bnx2"
|
||||
#define PFX DRV_MODULE_NAME ": "
|
||||
#define DRV_MODULE_VERSION "1.6.7"
|
||||
#define DRV_MODULE_RELDATE "October 10, 2007"
|
||||
#define DRV_MODULE_VERSION "1.6.8"
|
||||
#define DRV_MODULE_RELDATE "October 17, 2007"
|
||||
|
||||
#define RUN_AT(x) (jiffies + (x))
|
||||
|
||||
@ -3079,14 +3079,18 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)
|
||||
autoneg = bp->autoneg;
|
||||
advertising = bp->advertising;
|
||||
|
||||
bp->autoneg = AUTONEG_SPEED;
|
||||
bp->advertising = ADVERTISED_10baseT_Half |
|
||||
ADVERTISED_10baseT_Full |
|
||||
ADVERTISED_100baseT_Half |
|
||||
ADVERTISED_100baseT_Full |
|
||||
ADVERTISED_Autoneg;
|
||||
if (bp->phy_port == PORT_TP) {
|
||||
bp->autoneg = AUTONEG_SPEED;
|
||||
bp->advertising = ADVERTISED_10baseT_Half |
|
||||
ADVERTISED_10baseT_Full |
|
||||
ADVERTISED_100baseT_Half |
|
||||
ADVERTISED_100baseT_Full |
|
||||
ADVERTISED_Autoneg;
|
||||
}
|
||||
|
||||
bnx2_setup_copper_phy(bp);
|
||||
spin_lock_bh(&bp->phy_lock);
|
||||
bnx2_setup_phy(bp, bp->phy_port);
|
||||
spin_unlock_bh(&bp->phy_lock);
|
||||
|
||||
bp->autoneg = autoneg;
|
||||
bp->advertising = advertising;
|
||||
@ -3097,10 +3101,16 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)
|
||||
|
||||
/* Enable port mode. */
|
||||
val &= ~BNX2_EMAC_MODE_PORT;
|
||||
val |= BNX2_EMAC_MODE_PORT_MII |
|
||||
BNX2_EMAC_MODE_MPKT_RCVD |
|
||||
val |= BNX2_EMAC_MODE_MPKT_RCVD |
|
||||
BNX2_EMAC_MODE_ACPI_RCVD |
|
||||
BNX2_EMAC_MODE_MPKT;
|
||||
if (bp->phy_port == PORT_TP)
|
||||
val |= BNX2_EMAC_MODE_PORT_MII;
|
||||
else {
|
||||
val |= BNX2_EMAC_MODE_PORT_GMII;
|
||||
if (bp->line_speed == SPEED_2500)
|
||||
val |= BNX2_EMAC_MODE_25G_MODE;
|
||||
}
|
||||
|
||||
REG_WR(bp, BNX2_EMAC_MODE, val);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -22,7 +22,7 @@ config SSB
|
||||
|
||||
config SSB_PCIHOST_POSSIBLE
|
||||
bool
|
||||
depends on SSB && PCI
|
||||
depends on SSB && (PCI = y || PCI = SSB)
|
||||
default y
|
||||
|
||||
config SSB_PCIHOST
|
||||
@ -37,7 +37,7 @@ config SSB_PCIHOST
|
||||
|
||||
config SSB_PCMCIAHOST_POSSIBLE
|
||||
bool
|
||||
depends on SSB && PCMCIA && EXPERIMENTAL
|
||||
depends on SSB && (PCMCIA = y || PCMCIA = SSB) && EXPERIMENTAL
|
||||
default y
|
||||
|
||||
config SSB_PCMCIAHOST
|
||||
|
@ -173,7 +173,7 @@ u32 ssb_cpu_clock(struct ssb_mipscore *mcore)
|
||||
|
||||
void ssb_mipscore_init(struct ssb_mipscore *mcore)
|
||||
{
|
||||
struct ssb_bus *bus = mcore->dev->bus;
|
||||
struct ssb_bus *bus;
|
||||
struct ssb_device *dev;
|
||||
unsigned long hz, ns;
|
||||
unsigned int irq, i;
|
||||
@ -183,6 +183,7 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore)
|
||||
|
||||
ssb_dprintk(KERN_INFO PFX "Initializing MIPS core...\n");
|
||||
|
||||
bus = mcore->dev->bus;
|
||||
hz = ssb_clockspeed(bus);
|
||||
if (!hz)
|
||||
hz = 100000000;
|
||||
|
@ -146,6 +146,7 @@ struct sock;
|
||||
|
||||
extern unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen);
|
||||
extern int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);
|
||||
extern int sk_detach_filter(struct sock *sk);
|
||||
extern int sk_chk_filter(struct sock_filter *filter, int flen);
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
|
@ -827,7 +827,7 @@ static inline int dev_parse_header(const struct sk_buff *skb,
|
||||
{
|
||||
const struct net_device *dev = skb->dev;
|
||||
|
||||
if (!dev->header_ops->parse)
|
||||
if (!dev->header_ops || !dev->header_ops->parse)
|
||||
return 0;
|
||||
return dev->header_ops->parse(skb, haddr);
|
||||
}
|
||||
|
@ -7,9 +7,6 @@
|
||||
|
||||
#define XT_SCTP_VALID_FLAGS 0x07
|
||||
|
||||
#define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0]))
|
||||
|
||||
|
||||
struct xt_sctp_flag_info {
|
||||
u_int8_t chunktype;
|
||||
u_int8_t flag;
|
||||
@ -59,21 +56,21 @@ struct xt_sctp_info {
|
||||
#define SCTP_CHUNKMAP_RESET(chunkmap) \
|
||||
do { \
|
||||
int i; \
|
||||
for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
|
||||
for (i = 0; i < ARRAY_SIZE(chunkmap); i++) \
|
||||
chunkmap[i] = 0; \
|
||||
} while (0)
|
||||
|
||||
#define SCTP_CHUNKMAP_SET_ALL(chunkmap) \
|
||||
do { \
|
||||
int i; \
|
||||
for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
|
||||
for (i = 0; i < ARRAY_SIZE(chunkmap); i++) \
|
||||
chunkmap[i] = ~0; \
|
||||
} while (0)
|
||||
|
||||
#define SCTP_CHUNKMAP_COPY(destmap, srcmap) \
|
||||
do { \
|
||||
int i; \
|
||||
for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
|
||||
for (i = 0; i < ARRAY_SIZE(srcmap); i++) \
|
||||
destmap[i] = srcmap[i]; \
|
||||
} while (0)
|
||||
|
||||
@ -81,7 +78,7 @@ struct xt_sctp_info {
|
||||
({ \
|
||||
int i; \
|
||||
int flag = 1; \
|
||||
for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
|
||||
for (i = 0; i < ARRAY_SIZE(chunkmap); i++) { \
|
||||
if (chunkmap[i]) { \
|
||||
flag = 0; \
|
||||
break; \
|
||||
@ -94,7 +91,7 @@ struct xt_sctp_info {
|
||||
({ \
|
||||
int i; \
|
||||
int flag = 1; \
|
||||
for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
|
||||
for (i = 0; i < ARRAY_SIZE(chunkmap); i++) { \
|
||||
if (chunkmap[i] != ~0) { \
|
||||
flag = 0; \
|
||||
break; \
|
||||
|
@ -39,8 +39,13 @@ struct inet_frags {
|
||||
struct inet_frags_ctl *ctl;
|
||||
|
||||
unsigned int (*hashfn)(struct inet_frag_queue *);
|
||||
void (*constructor)(struct inet_frag_queue *q,
|
||||
void *arg);
|
||||
void (*destructor)(struct inet_frag_queue *);
|
||||
void (*skb_free)(struct sk_buff *);
|
||||
int (*match)(struct inet_frag_queue *q,
|
||||
void *arg);
|
||||
void (*frag_expire)(unsigned long data);
|
||||
};
|
||||
|
||||
void inet_frags_init(struct inet_frags *);
|
||||
@ -50,6 +55,8 @@ void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f);
|
||||
void inet_frag_destroy(struct inet_frag_queue *q,
|
||||
struct inet_frags *f, int *work);
|
||||
int inet_frag_evictor(struct inet_frags *f);
|
||||
struct inet_frag_queue *inet_frag_find(struct inet_frags *f, void *key,
|
||||
unsigned int hash);
|
||||
|
||||
static inline void inet_frag_put(struct inet_frag_queue *q, struct inet_frags *f)
|
||||
{
|
||||
|
@ -377,6 +377,17 @@ static inline int ipv6_prefix_equal(const struct in6_addr *a1,
|
||||
prefixlen);
|
||||
}
|
||||
|
||||
struct inet_frag_queue;
|
||||
|
||||
struct ip6_create_arg {
|
||||
__be32 id;
|
||||
struct in6_addr *src;
|
||||
struct in6_addr *dst;
|
||||
};
|
||||
|
||||
void ip6_frag_init(struct inet_frag_queue *q, void *a);
|
||||
int ip6_frag_match(struct inet_frag_queue *q, void *a);
|
||||
|
||||
static inline int ipv6_addr_any(const struct in6_addr *a)
|
||||
{
|
||||
return ((a->s6_addr32[0] | a->s6_addr32[1] |
|
||||
|
@ -904,16 +904,6 @@ static inline int sk_filter(struct sock *sk, struct sk_buff *skb)
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* sk_filter_rcu_free: Free a socket filter
|
||||
* @rcu: rcu_head that contains the sk_filter to free
|
||||
*/
|
||||
static inline void sk_filter_rcu_free(struct rcu_head *rcu)
|
||||
{
|
||||
struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu);
|
||||
kfree(fp);
|
||||
}
|
||||
|
||||
/**
|
||||
* sk_filter_release: Release a socket filter
|
||||
* @sk: socket
|
||||
@ -922,14 +912,18 @@ static inline void sk_filter_rcu_free(struct rcu_head *rcu)
|
||||
* Remove a filter from a socket and release its resources.
|
||||
*/
|
||||
|
||||
static inline void sk_filter_release(struct sock *sk, struct sk_filter *fp)
|
||||
static inline void sk_filter_release(struct sk_filter *fp)
|
||||
{
|
||||
if (atomic_dec_and_test(&fp->refcnt))
|
||||
kfree(fp);
|
||||
}
|
||||
|
||||
static inline void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp)
|
||||
{
|
||||
unsigned int size = sk_filter_len(fp);
|
||||
|
||||
atomic_sub(size, &sk->sk_omem_alloc);
|
||||
|
||||
if (atomic_dec_and_test(&fp->refcnt))
|
||||
call_rcu_bh(&fp->rcu, sk_filter_rcu_free);
|
||||
sk_filter_release(fp);
|
||||
}
|
||||
|
||||
static inline void sk_filter_charge(struct sock *sk, struct sk_filter *fp)
|
||||
|
@ -186,7 +186,8 @@ struct xfrm_state
|
||||
/* Reference to data common to all the instances of this
|
||||
* transformer. */
|
||||
struct xfrm_type *type;
|
||||
struct xfrm_mode *mode;
|
||||
struct xfrm_mode *inner_mode;
|
||||
struct xfrm_mode *outer_mode;
|
||||
|
||||
/* Security context */
|
||||
struct xfrm_sec_ctx *security;
|
||||
@ -228,8 +229,6 @@ struct xfrm_type;
|
||||
struct xfrm_dst;
|
||||
struct xfrm_policy_afinfo {
|
||||
unsigned short family;
|
||||
struct xfrm_type *type_map[IPPROTO_MAX];
|
||||
struct xfrm_mode *mode_map[XFRM_MODE_MAX];
|
||||
struct dst_ops *dst_ops;
|
||||
void (*garbage_collect)(void);
|
||||
int (*dst_lookup)(struct xfrm_dst **dst, struct flowi *fl);
|
||||
@ -255,7 +254,10 @@ extern void km_state_expired(struct xfrm_state *x, int hard, u32 pid);
|
||||
extern int __xfrm_state_delete(struct xfrm_state *x);
|
||||
|
||||
struct xfrm_state_afinfo {
|
||||
unsigned short family;
|
||||
unsigned int family;
|
||||
struct module *owner;
|
||||
struct xfrm_type *type_map[IPPROTO_MAX];
|
||||
struct xfrm_mode *mode_map[XFRM_MODE_MAX];
|
||||
int (*init_flags)(struct xfrm_state *x);
|
||||
void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl,
|
||||
struct xfrm_tmpl *tmpl,
|
||||
@ -267,8 +269,6 @@ struct xfrm_state_afinfo {
|
||||
|
||||
extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo);
|
||||
extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo);
|
||||
extern struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family);
|
||||
extern void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
|
||||
|
||||
extern void xfrm_state_delete_tunnel(struct xfrm_state *x);
|
||||
|
||||
@ -295,8 +295,6 @@ struct xfrm_type
|
||||
|
||||
extern int xfrm_register_type(struct xfrm_type *type, unsigned short family);
|
||||
extern int xfrm_unregister_type(struct xfrm_type *type, unsigned short family);
|
||||
extern struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family);
|
||||
extern void xfrm_put_type(struct xfrm_type *type);
|
||||
|
||||
struct xfrm_mode {
|
||||
int (*input)(struct xfrm_state *x, struct sk_buff *skb);
|
||||
@ -314,14 +312,19 @@ struct xfrm_mode {
|
||||
*/
|
||||
int (*output)(struct xfrm_state *x,struct sk_buff *skb);
|
||||
|
||||
struct xfrm_state_afinfo *afinfo;
|
||||
struct module *owner;
|
||||
unsigned int encap;
|
||||
int flags;
|
||||
};
|
||||
|
||||
/* Flags for xfrm_mode. */
|
||||
enum {
|
||||
XFRM_MODE_FLAG_TUNNEL = 1,
|
||||
};
|
||||
|
||||
extern int xfrm_register_mode(struct xfrm_mode *mode, int family);
|
||||
extern int xfrm_unregister_mode(struct xfrm_mode *mode, int family);
|
||||
extern struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family);
|
||||
extern void xfrm_put_mode(struct xfrm_mode *mode);
|
||||
|
||||
struct xfrm_tmpl
|
||||
{
|
||||
@ -1046,11 +1049,19 @@ extern void xfrm_replay_notify(struct xfrm_state *x, int event);
|
||||
extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
|
||||
extern int xfrm_init_state(struct xfrm_state *x);
|
||||
extern int xfrm_output(struct sk_buff *skb);
|
||||
extern int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
|
||||
int encap_type);
|
||||
extern int xfrm4_rcv(struct sk_buff *skb);
|
||||
|
||||
static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
|
||||
{
|
||||
return xfrm4_rcv_encap(skb, nexthdr, spi, 0);
|
||||
}
|
||||
|
||||
extern int xfrm4_output(struct sk_buff *skb);
|
||||
extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family);
|
||||
extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
|
||||
extern int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi);
|
||||
extern int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi);
|
||||
extern int xfrm6_rcv(struct sk_buff *skb);
|
||||
extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
|
||||
xfrm_address_t *saddr, u8 proto);
|
||||
|
121
net/atm/br2684.c
121
net/atm/br2684.c
@ -24,16 +24,6 @@ Author: Marcell GAL, 2000, XDSL Ltd, Hungary
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* Define this to use a version of the code which interacts with the higher
|
||||
* layers in a more intellegent way, by always reserving enough space for
|
||||
* our header at the begining of the packet. However, there may still be
|
||||
* some problems with programs like tcpdump. In 2.5 we'll sort out what
|
||||
* we need to do to get this perfect. For now we just will copy the packet
|
||||
* if we need space for the header
|
||||
*/
|
||||
/* #define FASTER_VERSION */
|
||||
|
||||
#ifdef SKB_DEBUG
|
||||
static void skb_debug(const struct sk_buff *skb)
|
||||
{
|
||||
@ -69,9 +59,7 @@ struct br2684_vcc {
|
||||
#ifdef CONFIG_ATM_BR2684_IPFILTER
|
||||
struct br2684_filter filter;
|
||||
#endif /* CONFIG_ATM_BR2684_IPFILTER */
|
||||
#ifndef FASTER_VERSION
|
||||
unsigned copies_needed, copies_failed;
|
||||
#endif /* FASTER_VERSION */
|
||||
};
|
||||
|
||||
struct br2684_dev {
|
||||
@ -147,13 +135,6 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev,
|
||||
struct br2684_vcc *brvcc)
|
||||
{
|
||||
struct atm_vcc *atmvcc;
|
||||
#ifdef FASTER_VERSION
|
||||
if (brvcc->encaps == e_llc)
|
||||
memcpy(skb_push(skb, 8), llc_oui_pid_pad, 8);
|
||||
/* last 2 bytes of llc_oui_pid_pad are managed by header routines;
|
||||
yes, you got it: 8 + 2 = sizeof(llc_oui_pid_pad)
|
||||
*/
|
||||
#else
|
||||
int minheadroom = (brvcc->encaps == e_llc) ? 10 : 2;
|
||||
if (skb_headroom(skb) < minheadroom) {
|
||||
struct sk_buff *skb2 = skb_realloc_headroom(skb, minheadroom);
|
||||
@ -170,7 +151,6 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev,
|
||||
skb_copy_to_linear_data(skb, llc_oui_pid_pad, 10);
|
||||
else
|
||||
memset(skb->data, 0, 2);
|
||||
#endif /* FASTER_VERSION */
|
||||
skb_debug(skb);
|
||||
|
||||
ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc;
|
||||
@ -237,87 +217,6 @@ static struct net_device_stats *br2684_get_stats(struct net_device *dev)
|
||||
return &BRPRIV(dev)->stats;
|
||||
}
|
||||
|
||||
#ifdef FASTER_VERSION
|
||||
/*
|
||||
* These mirror eth_header and eth_header_cache. They are not usually
|
||||
* exported for use in modules, so we grab them from net_device
|
||||
* after ether_setup() is done with it. Bit of a hack.
|
||||
*/
|
||||
static int (*my_eth_header)(struct sk_buff *, struct net_device *,
|
||||
unsigned short, void *, void *, unsigned);
|
||||
static int (*my_eth_header_cache)(struct neighbour *, struct hh_cache *);
|
||||
|
||||
static int
|
||||
br2684_header(struct sk_buff *skb, struct net_device *dev,
|
||||
unsigned short type, void *daddr, void *saddr, unsigned len)
|
||||
{
|
||||
u16 *pad_before_eth;
|
||||
int t = my_eth_header(skb, dev, type, daddr, saddr, len);
|
||||
if (t > 0) {
|
||||
pad_before_eth = (u16 *) skb_push(skb, 2);
|
||||
*pad_before_eth = 0;
|
||||
return dev->hard_header_len; /* or return 16; ? */
|
||||
} else
|
||||
return t;
|
||||
}
|
||||
|
||||
static int
|
||||
br2684_header_cache(struct neighbour *neigh, struct hh_cache *hh)
|
||||
{
|
||||
/* hh_data is 16 bytes long. if encaps is ether-llc we need 24, so
|
||||
xmit will add the additional header part in that case */
|
||||
u16 *pad_before_eth = (u16 *)(hh->hh_data);
|
||||
int t = my_eth_header_cache(neigh, hh);
|
||||
DPRINTK("br2684_header_cache, neigh=%p, hh_cache=%p\n", neigh, hh);
|
||||
if (t < 0)
|
||||
return t;
|
||||
else {
|
||||
*pad_before_eth = 0;
|
||||
hh->hh_len = PADLEN + ETH_HLEN;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is similar to eth_type_trans, which cannot be used because of
|
||||
* our dev->hard_header_len
|
||||
*/
|
||||
static inline __be16 br_type_trans(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct ethhdr *eth;
|
||||
unsigned char *rawp;
|
||||
eth = eth_hdr(skb);
|
||||
|
||||
if (is_multicast_ether_addr(eth->h_dest)) {
|
||||
if (!compare_ether_addr(eth->h_dest, dev->broadcast))
|
||||
skb->pkt_type = PACKET_BROADCAST;
|
||||
else
|
||||
skb->pkt_type = PACKET_MULTICAST;
|
||||
}
|
||||
|
||||
else if (compare_ether_addr(eth->h_dest, dev->dev_addr))
|
||||
skb->pkt_type = PACKET_OTHERHOST;
|
||||
|
||||
if (ntohs(eth->h_proto) >= 1536)
|
||||
return eth->h_proto;
|
||||
|
||||
rawp = skb->data;
|
||||
|
||||
/*
|
||||
* This is a magic hack to spot IPX packets. Older Novell breaks
|
||||
* the protocol design and runs IPX over 802.3 without an 802.2 LLC
|
||||
* layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
|
||||
* won't work for fault tolerant netware but does for the rest.
|
||||
*/
|
||||
if (*(unsigned short *) rawp == 0xFFFF)
|
||||
return htons(ETH_P_802_3);
|
||||
|
||||
/*
|
||||
* Real 802.2 LLC
|
||||
*/
|
||||
return htons(ETH_P_802_2);
|
||||
}
|
||||
#endif /* FASTER_VERSION */
|
||||
|
||||
/*
|
||||
* We remember when the MAC gets set, so we don't override it later with
|
||||
@ -448,17 +347,8 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef FASTER_VERSION
|
||||
/* FIXME: tcpdump shows that pointer to mac header is 2 bytes earlier,
|
||||
than should be. What else should I set? */
|
||||
skb_pull(skb, plen);
|
||||
skb_set_mac_header(skb, -ETH_HLEN);
|
||||
skb->pkt_type = PACKET_HOST;
|
||||
skb->protocol = br_type_trans(skb, net_dev);
|
||||
#else
|
||||
skb_pull(skb, plen - ETH_HLEN);
|
||||
skb->protocol = eth_type_trans(skb, net_dev);
|
||||
#endif /* FASTER_VERSION */
|
||||
#ifdef CONFIG_ATM_BR2684_IPFILTER
|
||||
if (unlikely(packet_fails_filter(skb->protocol, brvcc, skb))) {
|
||||
brdev->stats.rx_dropped++;
|
||||
@ -584,13 +474,6 @@ static void br2684_setup(struct net_device *netdev)
|
||||
ether_setup(netdev);
|
||||
brdev->net_dev = netdev;
|
||||
|
||||
#ifdef FASTER_VERSION
|
||||
my_eth_header = netdev->hard_header;
|
||||
netdev->hard_header = br2684_header;
|
||||
my_eth_header_cache = netdev->hard_header_cache;
|
||||
netdev->hard_header_cache = br2684_header_cache;
|
||||
netdev->hard_header_len = sizeof(llc_oui_pid_pad) + ETH_HLEN; /* 10 + 14 */
|
||||
#endif
|
||||
my_eth_mac_addr = netdev->set_mac_address;
|
||||
netdev->set_mac_address = br2684_mac_addr;
|
||||
netdev->hard_start_xmit = br2684_start_xmit;
|
||||
@ -719,16 +602,12 @@ static int br2684_seq_show(struct seq_file *seq, void *v)
|
||||
|
||||
list_for_each_entry(brvcc, &brdev->brvccs, brvccs) {
|
||||
seq_printf(seq, " vcc %d.%d.%d: encaps=%s"
|
||||
#ifndef FASTER_VERSION
|
||||
", failed copies %u/%u"
|
||||
#endif /* FASTER_VERSION */
|
||||
"\n", brvcc->atmvcc->dev->number,
|
||||
brvcc->atmvcc->vpi, brvcc->atmvcc->vci,
|
||||
(brvcc->encaps == e_llc) ? "LLC" : "VC"
|
||||
#ifndef FASTER_VERSION
|
||||
, brvcc->copies_failed
|
||||
, brvcc->copies_needed
|
||||
#endif /* FASTER_VERSION */
|
||||
);
|
||||
#ifdef CONFIG_ATM_BR2684_IPFILTER
|
||||
#define b1(var, byte) ((u8 *) &brvcc->filter.var)[byte]
|
||||
|
@ -386,6 +386,25 @@ int sk_chk_filter(struct sock_filter *filter, int flen)
|
||||
return (BPF_CLASS(filter[flen - 1].code) == BPF_RET) ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* sk_filter_rcu_release: Release a socket filter by rcu_head
|
||||
* @rcu: rcu_head that contains the sk_filter to free
|
||||
*/
|
||||
static void sk_filter_rcu_release(struct rcu_head *rcu)
|
||||
{
|
||||
struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu);
|
||||
|
||||
sk_filter_release(fp);
|
||||
}
|
||||
|
||||
static void sk_filter_delayed_uncharge(struct sock *sk, struct sk_filter *fp)
|
||||
{
|
||||
unsigned int size = sk_filter_len(fp);
|
||||
|
||||
atomic_sub(size, &sk->sk_omem_alloc);
|
||||
call_rcu_bh(&fp->rcu, sk_filter_rcu_release);
|
||||
}
|
||||
|
||||
/**
|
||||
* sk_attach_filter - attach a socket filter
|
||||
* @fprog: the filter program
|
||||
@ -398,7 +417,7 @@ int sk_chk_filter(struct sock_filter *filter, int flen)
|
||||
*/
|
||||
int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
|
||||
{
|
||||
struct sk_filter *fp;
|
||||
struct sk_filter *fp, *old_fp;
|
||||
unsigned int fsize = sizeof(struct sock_filter) * fprog->len;
|
||||
int err;
|
||||
|
||||
@ -418,19 +437,34 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
|
||||
fp->len = fprog->len;
|
||||
|
||||
err = sk_chk_filter(fp->insns, fp->len);
|
||||
if (!err) {
|
||||
struct sk_filter *old_fp;
|
||||
|
||||
rcu_read_lock_bh();
|
||||
old_fp = rcu_dereference(sk->sk_filter);
|
||||
rcu_assign_pointer(sk->sk_filter, fp);
|
||||
rcu_read_unlock_bh();
|
||||
fp = old_fp;
|
||||
if (err) {
|
||||
sk_filter_uncharge(sk, fp);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (fp)
|
||||
sk_filter_release(sk, fp);
|
||||
return err;
|
||||
rcu_read_lock_bh();
|
||||
old_fp = rcu_dereference(sk->sk_filter);
|
||||
rcu_assign_pointer(sk->sk_filter, fp);
|
||||
rcu_read_unlock_bh();
|
||||
|
||||
sk_filter_delayed_uncharge(sk, old_fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sk_detach_filter(struct sock *sk)
|
||||
{
|
||||
int ret = -ENOENT;
|
||||
struct sk_filter *filter;
|
||||
|
||||
rcu_read_lock_bh();
|
||||
filter = rcu_dereference(sk->sk_filter);
|
||||
if (filter) {
|
||||
rcu_assign_pointer(sk->sk_filter, NULL);
|
||||
sk_filter_delayed_uncharge(sk, filter);
|
||||
ret = 0;
|
||||
}
|
||||
rcu_read_unlock_bh();
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(sk_chk_filter);
|
||||
|
@ -2454,7 +2454,7 @@ static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev)
|
||||
spin_lock(&x->lock);
|
||||
iph = ip_hdr(skb);
|
||||
|
||||
err = x->mode->output(x, skb);
|
||||
err = x->outer_mode->output(x, skb);
|
||||
if (err)
|
||||
goto error;
|
||||
err = x->type->output(x, skb);
|
||||
|
@ -428,7 +428,6 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
|
||||
char __user *optval, int optlen)
|
||||
{
|
||||
struct sock *sk=sock->sk;
|
||||
struct sk_filter *filter;
|
||||
int val;
|
||||
int valbool;
|
||||
struct linger ling;
|
||||
@ -652,16 +651,7 @@ set_rcvbuf:
|
||||
break;
|
||||
|
||||
case SO_DETACH_FILTER:
|
||||
rcu_read_lock_bh();
|
||||
filter = rcu_dereference(sk->sk_filter);
|
||||
if (filter) {
|
||||
rcu_assign_pointer(sk->sk_filter, NULL);
|
||||
sk_filter_release(sk, filter);
|
||||
rcu_read_unlock_bh();
|
||||
break;
|
||||
}
|
||||
rcu_read_unlock_bh();
|
||||
ret = -ENONET;
|
||||
ret = sk_detach_filter(sk);
|
||||
break;
|
||||
|
||||
case SO_PASSSEC:
|
||||
@ -925,7 +915,7 @@ void sk_free(struct sock *sk)
|
||||
|
||||
filter = rcu_dereference(sk->sk_filter);
|
||||
if (filter) {
|
||||
sk_filter_release(sk, filter);
|
||||
sk_filter_uncharge(sk, filter);
|
||||
rcu_assign_pointer(sk->sk_filter, NULL);
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,9 @@
|
||||
#include "ccid.h"
|
||||
#include "dccp.h"
|
||||
|
||||
/* rate-limit for syncs in reply to sequence-invalid packets; RFC 4340, 7.5.4 */
|
||||
int sysctl_dccp_sync_ratelimit __read_mostly = HZ / 8;
|
||||
|
||||
static void dccp_fin(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
sk->sk_shutdown |= RCV_SHUTDOWN;
|
||||
|
@ -18,9 +18,6 @@
|
||||
#error This file should not be compiled without CONFIG_SYSCTL defined
|
||||
#endif
|
||||
|
||||
/* rate-limit for syncs in reply to sequence-invalid packets; RFC 4340, 7.5.4 */
|
||||
int sysctl_dccp_sync_ratelimit __read_mostly = HZ / 8;
|
||||
|
||||
static struct ctl_table dccp_default_table[] = {
|
||||
{
|
||||
.procname = "seq_window",
|
||||
|
@ -586,7 +586,7 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
|
||||
if (stype & IEEE80211_STYPE_QOS_DATA) {
|
||||
const struct ieee80211_hdr_3addrqos *qoshdr =
|
||||
(struct ieee80211_hdr_3addrqos *)skb->data;
|
||||
hdr[12] = qoshdr->qos_ctl & cpu_to_le16(IEEE80211_QCTL_TID);
|
||||
hdr[12] = le16_to_cpu(qoshdr->qos_ctl) & IEEE80211_QCTL_TID;
|
||||
} else
|
||||
hdr[12] = 0; /* priority */
|
||||
|
||||
|
@ -136,7 +136,9 @@ void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f,
|
||||
*work -= f->qsize;
|
||||
atomic_sub(f->qsize, &f->mem);
|
||||
|
||||
f->destructor(q);
|
||||
if (f->destructor)
|
||||
f->destructor(q);
|
||||
kfree(q);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(inet_frag_destroy);
|
||||
@ -172,3 +174,88 @@ int inet_frag_evictor(struct inet_frags *f)
|
||||
return evicted;
|
||||
}
|
||||
EXPORT_SYMBOL(inet_frag_evictor);
|
||||
|
||||
static struct inet_frag_queue *inet_frag_intern(struct inet_frag_queue *qp_in,
|
||||
struct inet_frags *f, unsigned int hash, void *arg)
|
||||
{
|
||||
struct inet_frag_queue *qp;
|
||||
#ifdef CONFIG_SMP
|
||||
struct hlist_node *n;
|
||||
#endif
|
||||
|
||||
write_lock(&f->lock);
|
||||
#ifdef CONFIG_SMP
|
||||
/* With SMP race we have to recheck hash table, because
|
||||
* such entry could be created on other cpu, while we
|
||||
* promoted read lock to write lock.
|
||||
*/
|
||||
hlist_for_each_entry(qp, n, &f->hash[hash], list) {
|
||||
if (f->match(qp, arg)) {
|
||||
atomic_inc(&qp->refcnt);
|
||||
write_unlock(&f->lock);
|
||||
qp_in->last_in |= COMPLETE;
|
||||
inet_frag_put(qp_in, f);
|
||||
return qp;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
qp = qp_in;
|
||||
if (!mod_timer(&qp->timer, jiffies + f->ctl->timeout))
|
||||
atomic_inc(&qp->refcnt);
|
||||
|
||||
atomic_inc(&qp->refcnt);
|
||||
hlist_add_head(&qp->list, &f->hash[hash]);
|
||||
list_add_tail(&qp->lru_list, &f->lru_list);
|
||||
f->nqueues++;
|
||||
write_unlock(&f->lock);
|
||||
return qp;
|
||||
}
|
||||
|
||||
static struct inet_frag_queue *inet_frag_alloc(struct inet_frags *f, void *arg)
|
||||
{
|
||||
struct inet_frag_queue *q;
|
||||
|
||||
q = kzalloc(f->qsize, GFP_ATOMIC);
|
||||
if (q == NULL)
|
||||
return NULL;
|
||||
|
||||
f->constructor(q, arg);
|
||||
atomic_add(f->qsize, &f->mem);
|
||||
setup_timer(&q->timer, f->frag_expire, (unsigned long)q);
|
||||
spin_lock_init(&q->lock);
|
||||
atomic_set(&q->refcnt, 1);
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
static struct inet_frag_queue *inet_frag_create(struct inet_frags *f,
|
||||
void *arg, unsigned int hash)
|
||||
{
|
||||
struct inet_frag_queue *q;
|
||||
|
||||
q = inet_frag_alloc(f, arg);
|
||||
if (q == NULL)
|
||||
return NULL;
|
||||
|
||||
return inet_frag_intern(q, f, hash, arg);
|
||||
}
|
||||
|
||||
struct inet_frag_queue *inet_frag_find(struct inet_frags *f, void *key,
|
||||
unsigned int hash)
|
||||
{
|
||||
struct inet_frag_queue *q;
|
||||
struct hlist_node *n;
|
||||
|
||||
read_lock(&f->lock);
|
||||
hlist_for_each_entry(q, n, &f->hash[hash], list) {
|
||||
if (f->match(q, key)) {
|
||||
atomic_inc(&q->refcnt);
|
||||
read_unlock(&f->lock);
|
||||
return q;
|
||||
}
|
||||
}
|
||||
read_unlock(&f->lock);
|
||||
|
||||
return inet_frag_create(f, key, hash);
|
||||
}
|
||||
EXPORT_SYMBOL(inet_frag_find);
|
||||
|
@ -108,6 +108,11 @@ int ip_frag_mem(void)
|
||||
static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
|
||||
struct net_device *dev);
|
||||
|
||||
struct ip4_create_arg {
|
||||
struct iphdr *iph;
|
||||
u32 user;
|
||||
};
|
||||
|
||||
static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot)
|
||||
{
|
||||
return jhash_3words((__force u32)id << 16 | prot,
|
||||
@ -123,6 +128,19 @@ static unsigned int ip4_hashfn(struct inet_frag_queue *q)
|
||||
return ipqhashfn(ipq->id, ipq->saddr, ipq->daddr, ipq->protocol);
|
||||
}
|
||||
|
||||
static int ip4_frag_match(struct inet_frag_queue *q, void *a)
|
||||
{
|
||||
struct ipq *qp;
|
||||
struct ip4_create_arg *arg = a;
|
||||
|
||||
qp = container_of(q, struct ipq, q);
|
||||
return (qp->id == arg->iph->id &&
|
||||
qp->saddr == arg->iph->saddr &&
|
||||
qp->daddr == arg->iph->daddr &&
|
||||
qp->protocol == arg->iph->protocol &&
|
||||
qp->user == arg->user);
|
||||
}
|
||||
|
||||
/* Memory Tracking Functions. */
|
||||
static __inline__ void frag_kfree_skb(struct sk_buff *skb, int *work)
|
||||
{
|
||||
@ -132,6 +150,20 @@ static __inline__ void frag_kfree_skb(struct sk_buff *skb, int *work)
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
static void ip4_frag_init(struct inet_frag_queue *q, void *a)
|
||||
{
|
||||
struct ipq *qp = container_of(q, struct ipq, q);
|
||||
struct ip4_create_arg *arg = a;
|
||||
|
||||
qp->protocol = arg->iph->protocol;
|
||||
qp->id = arg->iph->id;
|
||||
qp->saddr = arg->iph->saddr;
|
||||
qp->daddr = arg->iph->daddr;
|
||||
qp->user = arg->user;
|
||||
qp->peer = sysctl_ipfrag_max_dist ?
|
||||
inet_getpeer(arg->iph->saddr, 1) : NULL;
|
||||
}
|
||||
|
||||
static __inline__ void ip4_frag_free(struct inet_frag_queue *q)
|
||||
{
|
||||
struct ipq *qp;
|
||||
@ -139,17 +171,6 @@ static __inline__ void ip4_frag_free(struct inet_frag_queue *q)
|
||||
qp = container_of(q, struct ipq, q);
|
||||
if (qp->peer)
|
||||
inet_putpeer(qp->peer);
|
||||
kfree(qp);
|
||||
}
|
||||
|
||||
static __inline__ struct ipq *frag_alloc_queue(void)
|
||||
{
|
||||
struct ipq *qp = kzalloc(sizeof(struct ipq), GFP_ATOMIC);
|
||||
|
||||
if (!qp)
|
||||
return NULL;
|
||||
atomic_add(sizeof(struct ipq), &ip4_frags.mem);
|
||||
return qp;
|
||||
}
|
||||
|
||||
|
||||
@ -185,7 +206,9 @@ static void ip_evictor(void)
|
||||
*/
|
||||
static void ip_expire(unsigned long arg)
|
||||
{
|
||||
struct ipq *qp = (struct ipq *) arg;
|
||||
struct ipq *qp;
|
||||
|
||||
qp = container_of((struct inet_frag_queue *) arg, struct ipq, q);
|
||||
|
||||
spin_lock(&qp->q.lock);
|
||||
|
||||
@ -210,110 +233,28 @@ out:
|
||||
ipq_put(qp);
|
||||
}
|
||||
|
||||
/* Creation primitives. */
|
||||
|
||||
static struct ipq *ip_frag_intern(struct ipq *qp_in)
|
||||
{
|
||||
struct ipq *qp;
|
||||
#ifdef CONFIG_SMP
|
||||
struct hlist_node *n;
|
||||
#endif
|
||||
unsigned int hash;
|
||||
|
||||
write_lock(&ip4_frags.lock);
|
||||
hash = ipqhashfn(qp_in->id, qp_in->saddr, qp_in->daddr,
|
||||
qp_in->protocol);
|
||||
#ifdef CONFIG_SMP
|
||||
/* With SMP race we have to recheck hash table, because
|
||||
* such entry could be created on other cpu, while we
|
||||
* promoted read lock to write lock.
|
||||
*/
|
||||
hlist_for_each_entry(qp, n, &ip4_frags.hash[hash], q.list) {
|
||||
if (qp->id == qp_in->id &&
|
||||
qp->saddr == qp_in->saddr &&
|
||||
qp->daddr == qp_in->daddr &&
|
||||
qp->protocol == qp_in->protocol &&
|
||||
qp->user == qp_in->user) {
|
||||
atomic_inc(&qp->q.refcnt);
|
||||
write_unlock(&ip4_frags.lock);
|
||||
qp_in->q.last_in |= COMPLETE;
|
||||
ipq_put(qp_in);
|
||||
return qp;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
qp = qp_in;
|
||||
|
||||
if (!mod_timer(&qp->q.timer, jiffies + ip4_frags_ctl.timeout))
|
||||
atomic_inc(&qp->q.refcnt);
|
||||
|
||||
atomic_inc(&qp->q.refcnt);
|
||||
hlist_add_head(&qp->q.list, &ip4_frags.hash[hash]);
|
||||
INIT_LIST_HEAD(&qp->q.lru_list);
|
||||
list_add_tail(&qp->q.lru_list, &ip4_frags.lru_list);
|
||||
ip4_frags.nqueues++;
|
||||
write_unlock(&ip4_frags.lock);
|
||||
return qp;
|
||||
}
|
||||
|
||||
/* Add an entry to the 'ipq' queue for a newly received IP datagram. */
|
||||
static struct ipq *ip_frag_create(struct iphdr *iph, u32 user)
|
||||
{
|
||||
struct ipq *qp;
|
||||
|
||||
if ((qp = frag_alloc_queue()) == NULL)
|
||||
goto out_nomem;
|
||||
|
||||
qp->protocol = iph->protocol;
|
||||
qp->id = iph->id;
|
||||
qp->saddr = iph->saddr;
|
||||
qp->daddr = iph->daddr;
|
||||
qp->user = user;
|
||||
qp->peer = sysctl_ipfrag_max_dist ? inet_getpeer(iph->saddr, 1) : NULL;
|
||||
|
||||
/* Initialize a timer for this entry. */
|
||||
init_timer(&qp->q.timer);
|
||||
qp->q.timer.data = (unsigned long) qp; /* pointer to queue */
|
||||
qp->q.timer.function = ip_expire; /* expire function */
|
||||
spin_lock_init(&qp->q.lock);
|
||||
atomic_set(&qp->q.refcnt, 1);
|
||||
|
||||
return ip_frag_intern(qp);
|
||||
|
||||
out_nomem:
|
||||
LIMIT_NETDEBUG(KERN_ERR "ip_frag_create: no memory left !\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Find the correct entry in the "incomplete datagrams" queue for
|
||||
* this IP datagram, and create new one, if nothing is found.
|
||||
*/
|
||||
static inline struct ipq *ip_find(struct iphdr *iph, u32 user)
|
||||
{
|
||||
__be16 id = iph->id;
|
||||
__be32 saddr = iph->saddr;
|
||||
__be32 daddr = iph->daddr;
|
||||
__u8 protocol = iph->protocol;
|
||||
struct inet_frag_queue *q;
|
||||
struct ip4_create_arg arg;
|
||||
unsigned int hash;
|
||||
struct ipq *qp;
|
||||
struct hlist_node *n;
|
||||
|
||||
read_lock(&ip4_frags.lock);
|
||||
hash = ipqhashfn(id, saddr, daddr, protocol);
|
||||
hlist_for_each_entry(qp, n, &ip4_frags.hash[hash], q.list) {
|
||||
if (qp->id == id &&
|
||||
qp->saddr == saddr &&
|
||||
qp->daddr == daddr &&
|
||||
qp->protocol == protocol &&
|
||||
qp->user == user) {
|
||||
atomic_inc(&qp->q.refcnt);
|
||||
read_unlock(&ip4_frags.lock);
|
||||
return qp;
|
||||
}
|
||||
}
|
||||
read_unlock(&ip4_frags.lock);
|
||||
arg.iph = iph;
|
||||
arg.user = user;
|
||||
hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol);
|
||||
|
||||
return ip_frag_create(iph, user);
|
||||
q = inet_frag_find(&ip4_frags, &arg, hash);
|
||||
if (q == NULL)
|
||||
goto out_nomem;
|
||||
|
||||
return container_of(q, struct ipq, q);
|
||||
|
||||
out_nomem:
|
||||
LIMIT_NETDEBUG(KERN_ERR "ip_frag_create: no memory left !\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Is the fragment too far ahead to be part of ipq? */
|
||||
@ -545,7 +486,6 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
|
||||
if (prev) {
|
||||
head = prev->next;
|
||||
fp = skb_clone(head, GFP_ATOMIC);
|
||||
|
||||
if (!fp)
|
||||
goto out_nomem;
|
||||
|
||||
@ -571,7 +511,6 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
|
||||
goto out_oversize;
|
||||
|
||||
/* Head of list must not be cloned. */
|
||||
err = -ENOMEM;
|
||||
if (skb_cloned(head) && pskb_expand_head(head, 0, 0, GFP_ATOMIC))
|
||||
goto out_nomem;
|
||||
|
||||
@ -627,6 +566,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
|
||||
out_nomem:
|
||||
LIMIT_NETDEBUG(KERN_ERR "IP: queue_glue: no memory for gluing "
|
||||
"queue %p\n", qp);
|
||||
err = -ENOMEM;
|
||||
goto out_fail;
|
||||
out_oversize:
|
||||
if (net_ratelimit())
|
||||
@ -671,9 +611,12 @@ void __init ipfrag_init(void)
|
||||
{
|
||||
ip4_frags.ctl = &ip4_frags_ctl;
|
||||
ip4_frags.hashfn = ip4_hashfn;
|
||||
ip4_frags.constructor = ip4_frag_init;
|
||||
ip4_frags.destructor = ip4_frag_free;
|
||||
ip4_frags.skb_free = NULL;
|
||||
ip4_frags.qsize = sizeof(struct ipq);
|
||||
ip4_frags.match = ip4_frag_match;
|
||||
ip4_frags.frag_expire = ip_expire;
|
||||
inet_frags_init(&ip4_frags);
|
||||
}
|
||||
|
||||
|
@ -1121,7 +1121,7 @@ static int tcp_mark_lost_retrans(struct sock *sk, u32 received_upto)
|
||||
struct sk_buff *skb;
|
||||
int flag = 0;
|
||||
int cnt = 0;
|
||||
u32 new_low_seq = 0;
|
||||
u32 new_low_seq = tp->snd_nxt;
|
||||
|
||||
tcp_for_write_queue(skb, sk) {
|
||||
u32 ack_seq = TCP_SKB_CB(skb)->ack_seq;
|
||||
@ -1153,7 +1153,7 @@ static int tcp_mark_lost_retrans(struct sock *sk, u32 received_upto)
|
||||
NET_INC_STATS_BH(LINUX_MIB_TCPLOSTRETRANSMIT);
|
||||
}
|
||||
} else {
|
||||
if (!new_low_seq || before(ack_seq, new_low_seq))
|
||||
if (before(ack_seq, new_low_seq))
|
||||
new_low_seq = ack_seq;
|
||||
cnt += tcp_skb_pcount(skb);
|
||||
}
|
||||
@ -1242,7 +1242,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
|
||||
int num_sacks = (ptr[1] - TCPOLEN_SACK_BASE)>>3;
|
||||
int reord = tp->packets_out;
|
||||
int prior_fackets;
|
||||
u32 highest_sack_end_seq = 0;
|
||||
u32 highest_sack_end_seq = tp->lost_retrans_low;
|
||||
int flag = 0;
|
||||
int found_dup_sack = 0;
|
||||
int cached_fack_count;
|
||||
|
@ -16,19 +16,6 @@
|
||||
#include <net/ip.h>
|
||||
#include <net/xfrm.h>
|
||||
|
||||
static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq)
|
||||
{
|
||||
switch (nexthdr) {
|
||||
case IPPROTO_IPIP:
|
||||
case IPPROTO_IPV6:
|
||||
*spi = ip_hdr(skb)->saddr;
|
||||
*seq = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return xfrm_parse_spi(skb, nexthdr, spi, seq);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NETFILTER
|
||||
static inline int xfrm4_rcv_encap_finish(struct sk_buff *skb)
|
||||
{
|
||||
@ -46,28 +33,29 @@ drop:
|
||||
}
|
||||
#endif
|
||||
|
||||
static int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
|
||||
int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
|
||||
int encap_type)
|
||||
{
|
||||
__be32 spi, seq;
|
||||
int err;
|
||||
__be32 seq;
|
||||
struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
|
||||
struct xfrm_state *x;
|
||||
int xfrm_nr = 0;
|
||||
int decaps = 0;
|
||||
int err = xfrm4_parse_spi(skb, ip_hdr(skb)->protocol, &spi, &seq);
|
||||
unsigned int nhoff = offsetof(struct iphdr, protocol);
|
||||
|
||||
if (err != 0)
|
||||
seq = 0;
|
||||
if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
|
||||
goto drop;
|
||||
|
||||
do {
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
int nexthdr;
|
||||
|
||||
if (xfrm_nr == XFRM_MAX_DEPTH)
|
||||
goto drop;
|
||||
|
||||
x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi,
|
||||
iph->protocol != IPPROTO_IPV6 ? iph->protocol : IPPROTO_IPIP, AF_INET);
|
||||
nexthdr, AF_INET);
|
||||
if (x == NULL)
|
||||
goto drop;
|
||||
|
||||
@ -103,15 +91,15 @@ static int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
|
||||
|
||||
xfrm_vec[xfrm_nr++] = x;
|
||||
|
||||
if (x->mode->input(x, skb))
|
||||
if (x->outer_mode->input(x, skb))
|
||||
goto drop;
|
||||
|
||||
if (x->props.mode == XFRM_MODE_TUNNEL) {
|
||||
if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
|
||||
decaps = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
err = xfrm_parse_spi(skb, ip_hdr(skb)->protocol, &spi, &seq);
|
||||
err = xfrm_parse_spi(skb, nexthdr, &spi, &seq);
|
||||
if (err < 0)
|
||||
goto drop;
|
||||
} while (!err);
|
||||
@ -165,6 +153,7 @@ drop:
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm4_rcv_encap);
|
||||
|
||||
/* If it's a keepalive packet, then just eat it.
|
||||
* If it's an encapsulated packet, then pass it to the
|
||||
@ -252,11 +241,8 @@ int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
|
||||
__skb_pull(skb, len);
|
||||
skb_reset_transport_header(skb);
|
||||
|
||||
/* modify the protocol (it's ESP!) */
|
||||
iph->protocol = IPPROTO_ESP;
|
||||
|
||||
/* process ESP */
|
||||
ret = xfrm4_rcv_encap(skb, encap_type);
|
||||
ret = xfrm4_rcv_encap(skb, IPPROTO_ESP, 0, encap_type);
|
||||
return ret;
|
||||
|
||||
drop:
|
||||
@ -266,7 +252,7 @@ drop:
|
||||
|
||||
int xfrm4_rcv(struct sk_buff *skb)
|
||||
{
|
||||
return xfrm4_rcv_encap(skb, 0);
|
||||
return xfrm4_rcv_spi(skb, ip_hdr(skb)->protocol, 0);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(xfrm4_rcv);
|
||||
|
@ -114,6 +114,7 @@ static struct xfrm_mode xfrm4_beet_mode = {
|
||||
.output = xfrm4_beet_output,
|
||||
.owner = THIS_MODULE,
|
||||
.encap = XFRM_MODE_BEET,
|
||||
.flags = XFRM_MODE_FLAG_TUNNEL,
|
||||
};
|
||||
|
||||
static int __init xfrm4_beet_init(void)
|
||||
|
@ -139,6 +139,7 @@ static struct xfrm_mode xfrm4_tunnel_mode = {
|
||||
.output = xfrm4_tunnel_output,
|
||||
.owner = THIS_MODULE,
|
||||
.encap = XFRM_MODE_TUNNEL,
|
||||
.flags = XFRM_MODE_FLAG_TUNNEL,
|
||||
};
|
||||
|
||||
static int __init xfrm4_tunnel_init(void)
|
||||
|
@ -47,7 +47,7 @@ static inline int xfrm4_output_one(struct sk_buff *skb)
|
||||
struct iphdr *iph;
|
||||
int err;
|
||||
|
||||
if (x->props.mode == XFRM_MODE_TUNNEL) {
|
||||
if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
|
||||
err = xfrm4_tunnel_check_size(skb);
|
||||
if (err)
|
||||
goto error_nolock;
|
||||
|
@ -117,7 +117,7 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
|
||||
header_len += xfrm[i]->props.header_len;
|
||||
trailer_len += xfrm[i]->props.trailer_len;
|
||||
|
||||
if (xfrm[i]->props.mode == XFRM_MODE_TUNNEL) {
|
||||
if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
|
||||
unsigned short encap_family = xfrm[i]->props.family;
|
||||
switch (encap_family) {
|
||||
case AF_INET:
|
||||
@ -151,7 +151,6 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
|
||||
i = 0;
|
||||
for (; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
|
||||
struct xfrm_dst *x = (struct xfrm_dst*)dst_prev;
|
||||
struct xfrm_state_afinfo *afinfo;
|
||||
x->u.rt.fl = *fl;
|
||||
|
||||
dst_prev->xfrm = xfrm[i++];
|
||||
@ -169,27 +168,17 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
|
||||
/* Copy neighbout for reachability confirmation */
|
||||
dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour);
|
||||
dst_prev->input = rt->u.dst.input;
|
||||
/* XXX: When IPv6 module can be unloaded, we should manage reference
|
||||
* to xfrm6_output in afinfo->output. Miyazawa
|
||||
* */
|
||||
afinfo = xfrm_state_get_afinfo(dst_prev->xfrm->props.family);
|
||||
if (!afinfo) {
|
||||
dst = *dst_p;
|
||||
err = -EAFNOSUPPORT;
|
||||
goto error;
|
||||
}
|
||||
dst_prev->output = afinfo->output;
|
||||
xfrm_state_put_afinfo(afinfo);
|
||||
if (dst_prev->xfrm->props.family == AF_INET && rt->peer)
|
||||
atomic_inc(&rt->peer->refcnt);
|
||||
x->u.rt.peer = rt->peer;
|
||||
dst_prev->output = dst_prev->xfrm->outer_mode->afinfo->output;
|
||||
if (rt0->peer)
|
||||
atomic_inc(&rt0->peer->refcnt);
|
||||
x->u.rt.peer = rt0->peer;
|
||||
/* Sheit... I remember I did this right. Apparently,
|
||||
* it was magically lost, so this code needs audit */
|
||||
x->u.rt.rt_flags = rt0->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL);
|
||||
x->u.rt.rt_type = rt->rt_type;
|
||||
x->u.rt.rt_type = rt0->rt_type;
|
||||
x->u.rt.rt_src = rt0->rt_src;
|
||||
x->u.rt.rt_dst = rt0->rt_dst;
|
||||
x->u.rt.rt_gateway = rt->rt_gateway;
|
||||
x->u.rt.rt_gateway = rt0->rt_gateway;
|
||||
x->u.rt.rt_spec_dst = rt0->rt_spec_dst;
|
||||
x->u.rt.idev = rt0->idev;
|
||||
in_dev_hold(rt0->idev);
|
||||
@ -291,7 +280,7 @@ static void xfrm4_dst_destroy(struct dst_entry *dst)
|
||||
|
||||
if (likely(xdst->u.rt.idev))
|
||||
in_dev_put(xdst->u.rt.idev);
|
||||
if (dst->xfrm && dst->xfrm->props.family == AF_INET && likely(xdst->u.rt.peer))
|
||||
if (likely(xdst->u.rt.peer))
|
||||
inet_putpeer(xdst->u.rt.peer);
|
||||
xfrm_dst_destroy(xdst);
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl,
|
||||
|
||||
static struct xfrm_state_afinfo xfrm4_state_afinfo = {
|
||||
.family = AF_INET,
|
||||
.owner = THIS_MODULE,
|
||||
.init_flags = xfrm4_init_flags,
|
||||
.init_tempsel = __xfrm4_init_tempsel,
|
||||
.output = xfrm4_output,
|
||||
|
@ -18,7 +18,7 @@ static int ipip_output(struct xfrm_state *x, struct sk_buff *skb)
|
||||
|
||||
static int ipip_xfrm_rcv(struct xfrm_state *x, struct sk_buff *skb)
|
||||
{
|
||||
return IPPROTO_IP;
|
||||
return ip_hdr(skb)->protocol;
|
||||
}
|
||||
|
||||
static int ipip_init_state(struct xfrm_state *x)
|
||||
@ -48,20 +48,25 @@ static struct xfrm_type ipip_type = {
|
||||
.output = ipip_output
|
||||
};
|
||||
|
||||
static int xfrm_tunnel_rcv(struct sk_buff *skb)
|
||||
{
|
||||
return xfrm4_rcv_spi(skb, IPPROTO_IP, ip_hdr(skb)->saddr);
|
||||
}
|
||||
|
||||
static int xfrm_tunnel_err(struct sk_buff *skb, u32 info)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static struct xfrm_tunnel xfrm_tunnel_handler = {
|
||||
.handler = xfrm4_rcv,
|
||||
.handler = xfrm_tunnel_rcv,
|
||||
.err_handler = xfrm_tunnel_err,
|
||||
.priority = 2,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||
static struct xfrm_tunnel xfrm64_tunnel_handler = {
|
||||
.handler = xfrm4_rcv,
|
||||
.handler = xfrm_tunnel_rcv,
|
||||
.err_handler = xfrm_tunnel_err,
|
||||
.priority = 2,
|
||||
};
|
||||
|
@ -255,11 +255,6 @@ static void addrconf_mod_timer(struct inet6_ifaddr *ifp,
|
||||
|
||||
static int snmp6_alloc_dev(struct inet6_dev *idev)
|
||||
{
|
||||
int err = -ENOMEM;
|
||||
|
||||
if (!idev || !idev->dev)
|
||||
return -EINVAL;
|
||||
|
||||
if (snmp_mib_init((void **)idev->stats.ipv6,
|
||||
sizeof(struct ipstats_mib),
|
||||
__alignof__(struct ipstats_mib)) < 0)
|
||||
@ -280,15 +275,14 @@ err_icmpmsg:
|
||||
err_icmp:
|
||||
snmp_mib_free((void **)idev->stats.ipv6);
|
||||
err_ip:
|
||||
return err;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static int snmp6_free_dev(struct inet6_dev *idev)
|
||||
static void snmp6_free_dev(struct inet6_dev *idev)
|
||||
{
|
||||
snmp_mib_free((void **)idev->stats.icmpv6msg);
|
||||
snmp_mib_free((void **)idev->stats.icmpv6);
|
||||
snmp_mib_free((void **)idev->stats.ipv6);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Nobody refers to this device, we may destroy it. */
|
||||
|
@ -747,6 +747,7 @@ static void cleanup_ipv6_mibs(void)
|
||||
{
|
||||
snmp_mib_free((void **)ipv6_statistics);
|
||||
snmp_mib_free((void **)icmpv6_statistics);
|
||||
snmp_mib_free((void **)icmpv6msg_statistics);
|
||||
snmp_mib_free((void **)udp_stats_in6);
|
||||
snmp_mib_free((void **)udplite_stats_in6);
|
||||
}
|
||||
|
@ -344,6 +344,8 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
|
||||
pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
|
||||
goto out;
|
||||
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
|
||||
hdr_len = skb->data - skb_network_header(skb);
|
||||
ah = (struct ip_auth_hdr *)skb->data;
|
||||
ahp = x->data;
|
||||
@ -475,8 +477,15 @@ static int ah6_init_state(struct xfrm_state *x)
|
||||
|
||||
x->props.header_len = XFRM_ALIGN8(sizeof(struct ip_auth_hdr) +
|
||||
ahp->icv_trunc_len);
|
||||
if (x->props.mode == XFRM_MODE_TUNNEL)
|
||||
switch (x->props.mode) {
|
||||
case XFRM_MODE_BEET:
|
||||
case XFRM_MODE_TRANSPORT:
|
||||
break;
|
||||
case XFRM_MODE_TUNNEL:
|
||||
x->props.header_len += sizeof(struct ipv6hdr);
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
x->data = ahp;
|
||||
|
||||
return 0;
|
||||
|
@ -354,8 +354,15 @@ static int esp6_init_state(struct xfrm_state *x)
|
||||
(x->ealg->alg_key_len + 7) / 8))
|
||||
goto error;
|
||||
x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen;
|
||||
if (x->props.mode == XFRM_MODE_TUNNEL)
|
||||
switch (x->props.mode) {
|
||||
case XFRM_MODE_BEET:
|
||||
case XFRM_MODE_TRANSPORT:
|
||||
break;
|
||||
case XFRM_MODE_TUNNEL:
|
||||
x->props.header_len += sizeof(struct ipv6hdr);
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
x->data = esp;
|
||||
return 0;
|
||||
|
||||
|
@ -154,8 +154,10 @@ static void ip6_fl_gc(unsigned long dummy)
|
||||
write_unlock(&ip6_fl_lock);
|
||||
}
|
||||
|
||||
static int fl_intern(struct ip6_flowlabel *fl, __be32 label)
|
||||
static struct ip6_flowlabel *fl_intern(struct ip6_flowlabel *fl, __be32 label)
|
||||
{
|
||||
struct ip6_flowlabel *lfl;
|
||||
|
||||
fl->label = label & IPV6_FLOWLABEL_MASK;
|
||||
|
||||
write_lock_bh(&ip6_fl_lock);
|
||||
@ -163,12 +165,26 @@ static int fl_intern(struct ip6_flowlabel *fl, __be32 label)
|
||||
for (;;) {
|
||||
fl->label = htonl(net_random())&IPV6_FLOWLABEL_MASK;
|
||||
if (fl->label) {
|
||||
struct ip6_flowlabel *lfl;
|
||||
lfl = __fl_lookup(fl->label);
|
||||
if (lfl == NULL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* we dropper the ip6_fl_lock, so this entry could reappear
|
||||
* and we need to recheck with it.
|
||||
*
|
||||
* OTOH no need to search the active socket first, like it is
|
||||
* done in ipv6_flowlabel_opt - sock is locked, so new entry
|
||||
* with the same label can only appear on another sock
|
||||
*/
|
||||
lfl = __fl_lookup(fl->label);
|
||||
if (lfl != NULL) {
|
||||
atomic_inc(&lfl->users);
|
||||
write_unlock_bh(&ip6_fl_lock);
|
||||
return lfl;
|
||||
}
|
||||
}
|
||||
|
||||
fl->lastuse = jiffies;
|
||||
@ -176,7 +192,7 @@ static int fl_intern(struct ip6_flowlabel *fl, __be32 label)
|
||||
fl_ht[FL_HASH(fl->label)] = fl;
|
||||
atomic_inc(&fl_size);
|
||||
write_unlock_bh(&ip6_fl_lock);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -190,14 +206,17 @@ struct ip6_flowlabel * fl6_sock_lookup(struct sock *sk, __be32 label)
|
||||
|
||||
label &= IPV6_FLOWLABEL_MASK;
|
||||
|
||||
read_lock_bh(&ip6_sk_fl_lock);
|
||||
for (sfl=np->ipv6_fl_list; sfl; sfl = sfl->next) {
|
||||
struct ip6_flowlabel *fl = sfl->fl;
|
||||
if (fl->label == label) {
|
||||
fl->lastuse = jiffies;
|
||||
atomic_inc(&fl->users);
|
||||
read_unlock_bh(&ip6_sk_fl_lock);
|
||||
return fl;
|
||||
}
|
||||
}
|
||||
read_unlock_bh(&ip6_sk_fl_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -409,6 +428,16 @@ static int ipv6_opt_cmp(struct ipv6_txoptions *o1, struct ipv6_txoptions *o2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void fl_link(struct ipv6_pinfo *np, struct ipv6_fl_socklist *sfl,
|
||||
struct ip6_flowlabel *fl)
|
||||
{
|
||||
write_lock_bh(&ip6_sk_fl_lock);
|
||||
sfl->fl = fl;
|
||||
sfl->next = np->ipv6_fl_list;
|
||||
np->ipv6_fl_list = sfl;
|
||||
write_unlock_bh(&ip6_sk_fl_lock);
|
||||
}
|
||||
|
||||
int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
|
||||
{
|
||||
int err;
|
||||
@ -416,7 +445,8 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
|
||||
struct in6_flowlabel_req freq;
|
||||
struct ipv6_fl_socklist *sfl1=NULL;
|
||||
struct ipv6_fl_socklist *sfl, **sflp;
|
||||
struct ip6_flowlabel *fl;
|
||||
struct ip6_flowlabel *fl, *fl1 = NULL;
|
||||
|
||||
|
||||
if (optlen < sizeof(freq))
|
||||
return -EINVAL;
|
||||
@ -472,8 +502,6 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
|
||||
sfl1 = kmalloc(sizeof(*sfl1), GFP_KERNEL);
|
||||
|
||||
if (freq.flr_label) {
|
||||
struct ip6_flowlabel *fl1 = NULL;
|
||||
|
||||
err = -EEXIST;
|
||||
read_lock_bh(&ip6_sk_fl_lock);
|
||||
for (sfl = np->ipv6_fl_list; sfl; sfl = sfl->next) {
|
||||
@ -492,6 +520,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
|
||||
if (fl1 == NULL)
|
||||
fl1 = fl_lookup(freq.flr_label);
|
||||
if (fl1) {
|
||||
recheck:
|
||||
err = -EEXIST;
|
||||
if (freq.flr_flags&IPV6_FL_F_EXCL)
|
||||
goto release;
|
||||
@ -513,11 +542,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
|
||||
fl1->linger = fl->linger;
|
||||
if ((long)(fl->expires - fl1->expires) > 0)
|
||||
fl1->expires = fl->expires;
|
||||
write_lock_bh(&ip6_sk_fl_lock);
|
||||
sfl1->fl = fl1;
|
||||
sfl1->next = np->ipv6_fl_list;
|
||||
np->ipv6_fl_list = sfl1;
|
||||
write_unlock_bh(&ip6_sk_fl_lock);
|
||||
fl_link(np, sfl1, fl1);
|
||||
fl_free(fl);
|
||||
return 0;
|
||||
|
||||
@ -534,9 +559,9 @@ release:
|
||||
if (sfl1 == NULL || (err = mem_check(sk)) != 0)
|
||||
goto done;
|
||||
|
||||
err = fl_intern(fl, freq.flr_label);
|
||||
if (err)
|
||||
goto done;
|
||||
fl1 = fl_intern(fl, freq.flr_label);
|
||||
if (fl1 != NULL)
|
||||
goto recheck;
|
||||
|
||||
if (!freq.flr_label) {
|
||||
if (copy_to_user(&((struct in6_flowlabel_req __user *) optval)->flr_label,
|
||||
@ -545,9 +570,7 @@ release:
|
||||
}
|
||||
}
|
||||
|
||||
sfl1->fl = fl;
|
||||
sfl1->next = np->ipv6_fl_list;
|
||||
np->ipv6_fl_list = sfl1;
|
||||
fl_link(np, sfl1, fl);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
|
@ -411,8 +411,15 @@ static int ipcomp6_init_state(struct xfrm_state *x)
|
||||
goto out;
|
||||
|
||||
x->props.header_len = 0;
|
||||
if (x->props.mode == XFRM_MODE_TUNNEL)
|
||||
switch (x->props.mode) {
|
||||
case XFRM_MODE_BEET:
|
||||
case XFRM_MODE_TRANSPORT:
|
||||
break;
|
||||
case XFRM_MODE_TUNNEL:
|
||||
x->props.header_len += sizeof(struct ipv6hdr);
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
|
||||
mutex_lock(&ipcomp6_resource_mutex);
|
||||
if (!ipcomp6_alloc_scratches())
|
||||
|
@ -130,22 +130,6 @@ static inline void frag_kfree_skb(struct sk_buff *skb, unsigned int *work)
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
static void nf_frag_free(struct inet_frag_queue *q)
|
||||
{
|
||||
kfree(container_of(q, struct nf_ct_frag6_queue, q));
|
||||
}
|
||||
|
||||
static inline struct nf_ct_frag6_queue *frag_alloc_queue(void)
|
||||
{
|
||||
struct nf_ct_frag6_queue *fq;
|
||||
|
||||
fq = kzalloc(sizeof(struct nf_ct_frag6_queue), GFP_ATOMIC);
|
||||
if (fq == NULL)
|
||||
return NULL;
|
||||
atomic_add(sizeof(struct nf_ct_frag6_queue), &nf_frags.mem);
|
||||
return fq;
|
||||
}
|
||||
|
||||
/* Destruction primitives. */
|
||||
|
||||
static __inline__ void fq_put(struct nf_ct_frag6_queue *fq)
|
||||
@ -168,7 +152,10 @@ static void nf_ct_frag6_evictor(void)
|
||||
|
||||
static void nf_ct_frag6_expire(unsigned long data)
|
||||
{
|
||||
struct nf_ct_frag6_queue *fq = (struct nf_ct_frag6_queue *) data;
|
||||
struct nf_ct_frag6_queue *fq;
|
||||
|
||||
fq = container_of((struct inet_frag_queue *)data,
|
||||
struct nf_ct_frag6_queue, q);
|
||||
|
||||
spin_lock(&fq->q.lock);
|
||||
|
||||
@ -184,87 +171,27 @@ out:
|
||||
|
||||
/* Creation primitives. */
|
||||
|
||||
static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash,
|
||||
struct nf_ct_frag6_queue *fq_in)
|
||||
{
|
||||
struct nf_ct_frag6_queue *fq;
|
||||
#ifdef CONFIG_SMP
|
||||
struct hlist_node *n;
|
||||
#endif
|
||||
|
||||
write_lock(&nf_frags.lock);
|
||||
#ifdef CONFIG_SMP
|
||||
hlist_for_each_entry(fq, n, &nf_frags.hash[hash], q.list) {
|
||||
if (fq->id == fq_in->id &&
|
||||
ipv6_addr_equal(&fq_in->saddr, &fq->saddr) &&
|
||||
ipv6_addr_equal(&fq_in->daddr, &fq->daddr)) {
|
||||
atomic_inc(&fq->q.refcnt);
|
||||
write_unlock(&nf_frags.lock);
|
||||
fq_in->q.last_in |= COMPLETE;
|
||||
fq_put(fq_in);
|
||||
return fq;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
fq = fq_in;
|
||||
|
||||
if (!mod_timer(&fq->q.timer, jiffies + nf_frags_ctl.timeout))
|
||||
atomic_inc(&fq->q.refcnt);
|
||||
|
||||
atomic_inc(&fq->q.refcnt);
|
||||
hlist_add_head(&fq->q.list, &nf_frags.hash[hash]);
|
||||
INIT_LIST_HEAD(&fq->q.lru_list);
|
||||
list_add_tail(&fq->q.lru_list, &nf_frags.lru_list);
|
||||
nf_frags.nqueues++;
|
||||
write_unlock(&nf_frags.lock);
|
||||
return fq;
|
||||
}
|
||||
|
||||
|
||||
static struct nf_ct_frag6_queue *
|
||||
nf_ct_frag6_create(unsigned int hash, __be32 id, struct in6_addr *src, struct in6_addr *dst)
|
||||
{
|
||||
struct nf_ct_frag6_queue *fq;
|
||||
|
||||
if ((fq = frag_alloc_queue()) == NULL) {
|
||||
pr_debug("Can't alloc new queue\n");
|
||||
goto oom;
|
||||
}
|
||||
|
||||
fq->id = id;
|
||||
ipv6_addr_copy(&fq->saddr, src);
|
||||
ipv6_addr_copy(&fq->daddr, dst);
|
||||
|
||||
setup_timer(&fq->q.timer, nf_ct_frag6_expire, (unsigned long)fq);
|
||||
spin_lock_init(&fq->q.lock);
|
||||
atomic_set(&fq->q.refcnt, 1);
|
||||
|
||||
return nf_ct_frag6_intern(hash, fq);
|
||||
|
||||
oom:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static __inline__ struct nf_ct_frag6_queue *
|
||||
fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst)
|
||||
{
|
||||
struct nf_ct_frag6_queue *fq;
|
||||
struct hlist_node *n;
|
||||
unsigned int hash = ip6qhashfn(id, src, dst);
|
||||
struct inet_frag_queue *q;
|
||||
struct ip6_create_arg arg;
|
||||
unsigned int hash;
|
||||
|
||||
read_lock(&nf_frags.lock);
|
||||
hlist_for_each_entry(fq, n, &nf_frags.hash[hash], q.list) {
|
||||
if (fq->id == id &&
|
||||
ipv6_addr_equal(src, &fq->saddr) &&
|
||||
ipv6_addr_equal(dst, &fq->daddr)) {
|
||||
atomic_inc(&fq->q.refcnt);
|
||||
read_unlock(&nf_frags.lock);
|
||||
return fq;
|
||||
}
|
||||
}
|
||||
read_unlock(&nf_frags.lock);
|
||||
arg.id = id;
|
||||
arg.src = src;
|
||||
arg.dst = dst;
|
||||
hash = ip6qhashfn(id, src, dst);
|
||||
|
||||
return nf_ct_frag6_create(hash, id, src, dst);
|
||||
q = inet_frag_find(&nf_frags, &arg, hash);
|
||||
if (q == NULL)
|
||||
goto oom;
|
||||
|
||||
return container_of(q, struct nf_ct_frag6_queue, q);
|
||||
|
||||
oom:
|
||||
pr_debug("Can't alloc new queue\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -749,9 +676,12 @@ int nf_ct_frag6_init(void)
|
||||
{
|
||||
nf_frags.ctl = &nf_frags_ctl;
|
||||
nf_frags.hashfn = nf_hashfn;
|
||||
nf_frags.destructor = nf_frag_free;
|
||||
nf_frags.constructor = ip6_frag_init;
|
||||
nf_frags.destructor = NULL;
|
||||
nf_frags.skb_free = nf_skb_free;
|
||||
nf_frags.qsize = sizeof(struct nf_ct_frag6_queue);
|
||||
nf_frags.match = ip6_frag_match;
|
||||
nf_frags.frag_expire = nf_ct_frag6_expire;
|
||||
inet_frags_init(&nf_frags);
|
||||
|
||||
return 0;
|
||||
|
@ -143,6 +143,18 @@ static unsigned int ip6_hashfn(struct inet_frag_queue *q)
|
||||
return ip6qhashfn(fq->id, &fq->saddr, &fq->daddr);
|
||||
}
|
||||
|
||||
int ip6_frag_match(struct inet_frag_queue *q, void *a)
|
||||
{
|
||||
struct frag_queue *fq;
|
||||
struct ip6_create_arg *arg = a;
|
||||
|
||||
fq = container_of(q, struct frag_queue, q);
|
||||
return (fq->id == arg->id &&
|
||||
ipv6_addr_equal(&fq->saddr, arg->src) &&
|
||||
ipv6_addr_equal(&fq->daddr, arg->dst));
|
||||
}
|
||||
EXPORT_SYMBOL(ip6_frag_match);
|
||||
|
||||
/* Memory Tracking Functions. */
|
||||
static inline void frag_kfree_skb(struct sk_buff *skb, int *work)
|
||||
{
|
||||
@ -152,20 +164,16 @@ static inline void frag_kfree_skb(struct sk_buff *skb, int *work)
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
static void ip6_frag_free(struct inet_frag_queue *fq)
|
||||
void ip6_frag_init(struct inet_frag_queue *q, void *a)
|
||||
{
|
||||
kfree(container_of(fq, struct frag_queue, q));
|
||||
}
|
||||
struct frag_queue *fq = container_of(q, struct frag_queue, q);
|
||||
struct ip6_create_arg *arg = a;
|
||||
|
||||
static inline struct frag_queue *frag_alloc_queue(void)
|
||||
{
|
||||
struct frag_queue *fq = kzalloc(sizeof(struct frag_queue), GFP_ATOMIC);
|
||||
|
||||
if(!fq)
|
||||
return NULL;
|
||||
atomic_add(sizeof(struct frag_queue), &ip6_frags.mem);
|
||||
return fq;
|
||||
fq->id = arg->id;
|
||||
ipv6_addr_copy(&fq->saddr, arg->src);
|
||||
ipv6_addr_copy(&fq->daddr, arg->dst);
|
||||
}
|
||||
EXPORT_SYMBOL(ip6_frag_init);
|
||||
|
||||
/* Destruction primitives. */
|
||||
|
||||
@ -193,9 +201,11 @@ static void ip6_evictor(struct inet6_dev *idev)
|
||||
|
||||
static void ip6_frag_expire(unsigned long data)
|
||||
{
|
||||
struct frag_queue *fq = (struct frag_queue *) data;
|
||||
struct frag_queue *fq;
|
||||
struct net_device *dev = NULL;
|
||||
|
||||
fq = container_of((struct inet_frag_queue *)data, struct frag_queue, q);
|
||||
|
||||
spin_lock(&fq->q.lock);
|
||||
|
||||
if (fq->q.last_in & COMPLETE)
|
||||
@ -230,98 +240,30 @@ out:
|
||||
fq_put(fq);
|
||||
}
|
||||
|
||||
/* Creation primitives. */
|
||||
|
||||
|
||||
static struct frag_queue *ip6_frag_intern(struct frag_queue *fq_in)
|
||||
static __inline__ struct frag_queue *
|
||||
fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst,
|
||||
struct inet6_dev *idev)
|
||||
{
|
||||
struct frag_queue *fq;
|
||||
struct inet_frag_queue *q;
|
||||
struct ip6_create_arg arg;
|
||||
unsigned int hash;
|
||||
#ifdef CONFIG_SMP
|
||||
struct hlist_node *n;
|
||||
#endif
|
||||
|
||||
write_lock(&ip6_frags.lock);
|
||||
hash = ip6qhashfn(fq_in->id, &fq_in->saddr, &fq_in->daddr);
|
||||
#ifdef CONFIG_SMP
|
||||
hlist_for_each_entry(fq, n, &ip6_frags.hash[hash], q.list) {
|
||||
if (fq->id == fq_in->id &&
|
||||
ipv6_addr_equal(&fq_in->saddr, &fq->saddr) &&
|
||||
ipv6_addr_equal(&fq_in->daddr, &fq->daddr)) {
|
||||
atomic_inc(&fq->q.refcnt);
|
||||
write_unlock(&ip6_frags.lock);
|
||||
fq_in->q.last_in |= COMPLETE;
|
||||
fq_put(fq_in);
|
||||
return fq;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
fq = fq_in;
|
||||
arg.id = id;
|
||||
arg.src = src;
|
||||
arg.dst = dst;
|
||||
hash = ip6qhashfn(id, src, dst);
|
||||
|
||||
if (!mod_timer(&fq->q.timer, jiffies + ip6_frags_ctl.timeout))
|
||||
atomic_inc(&fq->q.refcnt);
|
||||
|
||||
atomic_inc(&fq->q.refcnt);
|
||||
hlist_add_head(&fq->q.list, &ip6_frags.hash[hash]);
|
||||
INIT_LIST_HEAD(&fq->q.lru_list);
|
||||
list_add_tail(&fq->q.lru_list, &ip6_frags.lru_list);
|
||||
ip6_frags.nqueues++;
|
||||
write_unlock(&ip6_frags.lock);
|
||||
return fq;
|
||||
}
|
||||
|
||||
|
||||
static struct frag_queue *
|
||||
ip6_frag_create(__be32 id, struct in6_addr *src, struct in6_addr *dst,
|
||||
struct inet6_dev *idev)
|
||||
{
|
||||
struct frag_queue *fq;
|
||||
|
||||
if ((fq = frag_alloc_queue()) == NULL)
|
||||
q = inet_frag_find(&ip6_frags, &arg, hash);
|
||||
if (q == NULL)
|
||||
goto oom;
|
||||
|
||||
fq->id = id;
|
||||
ipv6_addr_copy(&fq->saddr, src);
|
||||
ipv6_addr_copy(&fq->daddr, dst);
|
||||
|
||||
init_timer(&fq->q.timer);
|
||||
fq->q.timer.function = ip6_frag_expire;
|
||||
fq->q.timer.data = (long) fq;
|
||||
spin_lock_init(&fq->q.lock);
|
||||
atomic_set(&fq->q.refcnt, 1);
|
||||
|
||||
return ip6_frag_intern(fq);
|
||||
return container_of(q, struct frag_queue, q);
|
||||
|
||||
oom:
|
||||
IP6_INC_STATS_BH(idev, IPSTATS_MIB_REASMFAILS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static __inline__ struct frag_queue *
|
||||
fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst,
|
||||
struct inet6_dev *idev)
|
||||
{
|
||||
struct frag_queue *fq;
|
||||
struct hlist_node *n;
|
||||
unsigned int hash;
|
||||
|
||||
read_lock(&ip6_frags.lock);
|
||||
hash = ip6qhashfn(id, src, dst);
|
||||
hlist_for_each_entry(fq, n, &ip6_frags.hash[hash], q.list) {
|
||||
if (fq->id == id &&
|
||||
ipv6_addr_equal(src, &fq->saddr) &&
|
||||
ipv6_addr_equal(dst, &fq->daddr)) {
|
||||
atomic_inc(&fq->q.refcnt);
|
||||
read_unlock(&ip6_frags.lock);
|
||||
return fq;
|
||||
}
|
||||
}
|
||||
read_unlock(&ip6_frags.lock);
|
||||
|
||||
return ip6_frag_create(id, src, dst, idev);
|
||||
}
|
||||
|
||||
|
||||
static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
|
||||
struct frag_hdr *fhdr, int nhoff)
|
||||
{
|
||||
@ -697,8 +639,11 @@ void __init ipv6_frag_init(void)
|
||||
|
||||
ip6_frags.ctl = &ip6_frags_ctl;
|
||||
ip6_frags.hashfn = ip6_hashfn;
|
||||
ip6_frags.destructor = ip6_frag_free;
|
||||
ip6_frags.constructor = ip6_frag_init;
|
||||
ip6_frags.destructor = NULL;
|
||||
ip6_frags.skb_free = NULL;
|
||||
ip6_frags.qsize = sizeof(struct frag_queue);
|
||||
ip6_frags.match = ip6_frag_match;
|
||||
ip6_frags.frag_expire = ip6_frag_expire;
|
||||
inet_frags_init(&ip6_frags);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include <net/ipv6.h>
|
||||
#include <net/xfrm.h>
|
||||
|
||||
int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi)
|
||||
int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
|
||||
{
|
||||
int err;
|
||||
__be32 seq;
|
||||
@ -24,11 +24,9 @@ int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi)
|
||||
struct xfrm_state *x;
|
||||
int xfrm_nr = 0;
|
||||
int decaps = 0;
|
||||
int nexthdr;
|
||||
unsigned int nhoff;
|
||||
|
||||
nhoff = IP6CB(skb)->nhoff;
|
||||
nexthdr = skb_network_header(skb)[nhoff];
|
||||
|
||||
seq = 0;
|
||||
if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
|
||||
@ -41,7 +39,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi)
|
||||
goto drop;
|
||||
|
||||
x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi,
|
||||
nexthdr != IPPROTO_IPIP ? nexthdr : IPPROTO_IPV6, AF_INET6);
|
||||
nexthdr, AF_INET6);
|
||||
if (x == NULL)
|
||||
goto drop;
|
||||
spin_lock(&x->lock);
|
||||
@ -70,10 +68,10 @@ int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi)
|
||||
|
||||
xfrm_vec[xfrm_nr++] = x;
|
||||
|
||||
if (x->mode->input(x, skb))
|
||||
if (x->outer_mode->input(x, skb))
|
||||
goto drop;
|
||||
|
||||
if (x->props.mode == XFRM_MODE_TUNNEL) { /* XXX */
|
||||
if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
|
||||
decaps = 1;
|
||||
break;
|
||||
}
|
||||
@ -99,7 +97,6 @@ int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi)
|
||||
memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec,
|
||||
xfrm_nr * sizeof(xfrm_vec[0]));
|
||||
skb->sp->len += xfrm_nr;
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
|
||||
nf_reset(skb);
|
||||
|
||||
@ -135,7 +132,8 @@ EXPORT_SYMBOL(xfrm6_rcv_spi);
|
||||
|
||||
int xfrm6_rcv(struct sk_buff *skb)
|
||||
{
|
||||
return xfrm6_rcv_spi(skb, 0);
|
||||
return xfrm6_rcv_spi(skb, skb_network_header(skb)[IP6CB(skb)->nhoff],
|
||||
0);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(xfrm6_rcv);
|
||||
|
@ -79,6 +79,7 @@ static struct xfrm_mode xfrm6_beet_mode = {
|
||||
.output = xfrm6_beet_output,
|
||||
.owner = THIS_MODULE,
|
||||
.encap = XFRM_MODE_BEET,
|
||||
.flags = XFRM_MODE_FLAG_TUNNEL,
|
||||
};
|
||||
|
||||
static int __init xfrm6_beet_init(void)
|
||||
|
@ -58,16 +58,7 @@ static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do nothing about routing optimization header unlike IPsec.
|
||||
*/
|
||||
static int xfrm6_ro_input(struct xfrm_state *x, struct sk_buff *skb)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct xfrm_mode xfrm6_ro_mode = {
|
||||
.input = xfrm6_ro_input,
|
||||
.output = xfrm6_ro_output,
|
||||
.owner = THIS_MODULE,
|
||||
.encap = XFRM_MODE_ROUTEOPTIMIZATION,
|
||||
|
@ -118,6 +118,7 @@ static struct xfrm_mode xfrm6_tunnel_mode = {
|
||||
.output = xfrm6_tunnel_output,
|
||||
.owner = THIS_MODULE,
|
||||
.encap = XFRM_MODE_TUNNEL,
|
||||
.flags = XFRM_MODE_FLAG_TUNNEL,
|
||||
};
|
||||
|
||||
static int __init xfrm6_tunnel_init(void)
|
||||
|
@ -50,7 +50,7 @@ static inline int xfrm6_output_one(struct sk_buff *skb)
|
||||
struct ipv6hdr *iph;
|
||||
int err;
|
||||
|
||||
if (x->props.mode == XFRM_MODE_TUNNEL) {
|
||||
if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
|
||||
err = xfrm6_tunnel_check_size(skb);
|
||||
if (err)
|
||||
goto error_nolock;
|
||||
|
@ -178,8 +178,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
|
||||
__xfrm6_bundle_len_inc(&header_len, &nfheader_len, xfrm[i]);
|
||||
trailer_len += xfrm[i]->props.trailer_len;
|
||||
|
||||
if (xfrm[i]->props.mode == XFRM_MODE_TUNNEL ||
|
||||
xfrm[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION) {
|
||||
if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
|
||||
unsigned short encap_family = xfrm[i]->props.family;
|
||||
switch(encap_family) {
|
||||
case AF_INET:
|
||||
@ -215,7 +214,6 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
|
||||
i = 0;
|
||||
for (; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
|
||||
struct xfrm_dst *x = (struct xfrm_dst*)dst_prev;
|
||||
struct xfrm_state_afinfo *afinfo;
|
||||
|
||||
dst_prev->xfrm = xfrm[i++];
|
||||
dst_prev->dev = rt->u.dst.dev;
|
||||
@ -232,18 +230,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
|
||||
/* Copy neighbour for reachability confirmation */
|
||||
dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour);
|
||||
dst_prev->input = rt->u.dst.input;
|
||||
/* XXX: When IPv4 is implemented as module and can be unloaded,
|
||||
* we should manage reference to xfrm4_output in afinfo->output.
|
||||
* Miyazawa
|
||||
*/
|
||||
afinfo = xfrm_state_get_afinfo(dst_prev->xfrm->props.family);
|
||||
if (!afinfo) {
|
||||
dst = *dst_p;
|
||||
goto error;
|
||||
}
|
||||
|
||||
dst_prev->output = afinfo->output;
|
||||
xfrm_state_put_afinfo(afinfo);
|
||||
dst_prev->output = dst_prev->xfrm->outer_mode->afinfo->output;
|
||||
/* Sheit... I remember I did this right. Apparently,
|
||||
* it was magically lost, so this code needs audit */
|
||||
x->u.rt6.rt6i_flags = rt0->rt6i_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL);
|
||||
|
@ -93,7 +93,8 @@ __xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n)
|
||||
/* Rule 4: select IPsec tunnel */
|
||||
for (i = 0; i < n; i++) {
|
||||
if (src[i] &&
|
||||
src[i]->props.mode == XFRM_MODE_TUNNEL) {
|
||||
(src[i]->props.mode == XFRM_MODE_TUNNEL ||
|
||||
src[i]->props.mode == XFRM_MODE_BEET)) {
|
||||
dst[j++] = src[i];
|
||||
src[i] = NULL;
|
||||
}
|
||||
@ -146,7 +147,8 @@ __xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n)
|
||||
/* Rule 3: select IPsec tunnel */
|
||||
for (i = 0; i < n; i++) {
|
||||
if (src[i] &&
|
||||
src[i]->mode == XFRM_MODE_TUNNEL) {
|
||||
(src[i]->mode == XFRM_MODE_TUNNEL ||
|
||||
src[i]->mode == XFRM_MODE_BEET)) {
|
||||
dst[j++] = src[i];
|
||||
src[i] = NULL;
|
||||
}
|
||||
@ -168,6 +170,7 @@ __xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n)
|
||||
|
||||
static struct xfrm_state_afinfo xfrm6_state_afinfo = {
|
||||
.family = AF_INET6,
|
||||
.owner = THIS_MODULE,
|
||||
.init_tempsel = __xfrm6_init_tempsel,
|
||||
.tmpl_sort = __xfrm6_tmpl_sort,
|
||||
.state_sort = __xfrm6_state_sort,
|
||||
|
@ -248,7 +248,7 @@ static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
|
||||
|
||||
static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
|
||||
{
|
||||
return 0;
|
||||
return skb_network_header(skb)[IP6CB(skb)->nhoff];
|
||||
}
|
||||
|
||||
static int xfrm6_tunnel_rcv(struct sk_buff *skb)
|
||||
@ -257,7 +257,7 @@ static int xfrm6_tunnel_rcv(struct sk_buff *skb)
|
||||
__be32 spi;
|
||||
|
||||
spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr);
|
||||
return xfrm6_rcv_spi(skb, spi) > 0 ? : 0;
|
||||
return xfrm6_rcv_spi(skb, IPPROTO_IPV6, spi) > 0 ? : 0;
|
||||
}
|
||||
|
||||
static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
||||
|
@ -381,18 +381,9 @@ static void ircomm_tty_discovery_indication(discinfo_t *discovery,
|
||||
info.daddr = discovery->daddr;
|
||||
info.saddr = discovery->saddr;
|
||||
|
||||
/* FIXME. We have a locking problem on the hashbin here.
|
||||
* We probably need to use hashbin_find_next(), but we first
|
||||
* need to ensure that "line" is unique. - Jean II */
|
||||
self = (struct ircomm_tty_cb *) hashbin_get_first(ircomm_tty);
|
||||
while (self != NULL) {
|
||||
IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
|
||||
|
||||
ircomm_tty_do_event(self, IRCOMM_TTY_DISCOVERY_INDICATION,
|
||||
NULL, &info);
|
||||
|
||||
self = (struct ircomm_tty_cb *) hashbin_get_next(ircomm_tty);
|
||||
}
|
||||
self = (struct ircomm_tty_cb *) priv;
|
||||
ircomm_tty_do_event(self, IRCOMM_TTY_DISCOVERY_INDICATION,
|
||||
NULL, &info);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -306,9 +306,12 @@ int ieee80211_set_channel(struct ieee80211_local *local, int channel, int freq)
|
||||
((chan->chan == channel) || (chan->freq == freq))) {
|
||||
local->oper_channel = chan;
|
||||
local->oper_hw_mode = mode;
|
||||
set++;
|
||||
set = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (set)
|
||||
break;
|
||||
}
|
||||
|
||||
if (set) {
|
||||
@ -508,10 +511,11 @@ static int ieee80211_ioctl_giwap(struct net_device *dev,
|
||||
|
||||
static int ieee80211_ioctl_siwscan(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_point *data, char *extra)
|
||||
union iwreq_data *wrqu, char *extra)
|
||||
{
|
||||
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
struct iw_scan_req *req = NULL;
|
||||
u8 *ssid = NULL;
|
||||
size_t ssid_len = 0;
|
||||
|
||||
@ -536,6 +540,14 @@ static int ieee80211_ioctl_siwscan(struct net_device *dev,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* if SSID was specified explicitly then use that */
|
||||
if (wrqu->data.length == sizeof(struct iw_scan_req) &&
|
||||
wrqu->data.flags & IW_SCAN_THIS_ESSID) {
|
||||
req = (struct iw_scan_req *)extra;
|
||||
ssid = req->essid;
|
||||
ssid_len = req->essid_len;
|
||||
}
|
||||
|
||||
return ieee80211_sta_req_scan(dev, ssid, ssid_len);
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,6 @@
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
* BSS table: use <BSSID,SSID> as the key to support multi-SSID APs
|
||||
* order BSS list by RSSI(?) ("quality of AP")
|
||||
* scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE,
|
||||
* SSID)
|
||||
@ -61,7 +60,8 @@
|
||||
static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
|
||||
u8 *ssid, size_t ssid_len);
|
||||
static struct ieee80211_sta_bss *
|
||||
ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid);
|
||||
ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel,
|
||||
u8 *ssid, u8 ssid_len);
|
||||
static void ieee80211_rx_bss_put(struct net_device *dev,
|
||||
struct ieee80211_sta_bss *bss);
|
||||
static int ieee80211_sta_find_ibss(struct net_device *dev,
|
||||
@ -427,7 +427,9 @@ static void ieee80211_set_associated(struct net_device *dev,
|
||||
if (sdata->type != IEEE80211_IF_TYPE_STA)
|
||||
return;
|
||||
|
||||
bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
|
||||
bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
|
||||
local->hw.conf.channel,
|
||||
ifsta->ssid, ifsta->ssid_len);
|
||||
if (bss) {
|
||||
if (bss->has_erp_value)
|
||||
ieee80211_handle_erp_ie(dev, bss->erp_value);
|
||||
@ -574,7 +576,8 @@ static void ieee80211_send_assoc(struct net_device *dev,
|
||||
capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME |
|
||||
WLAN_CAPABILITY_SHORT_PREAMBLE;
|
||||
}
|
||||
bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
|
||||
bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel,
|
||||
ifsta->ssid, ifsta->ssid_len);
|
||||
if (bss) {
|
||||
if (bss->capability & WLAN_CAPABILITY_PRIVACY)
|
||||
capab |= WLAN_CAPABILITY_PRIVACY;
|
||||
@ -722,6 +725,7 @@ static void ieee80211_send_disassoc(struct net_device *dev,
|
||||
static int ieee80211_privacy_mismatch(struct net_device *dev,
|
||||
struct ieee80211_if_sta *ifsta)
|
||||
{
|
||||
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||
struct ieee80211_sta_bss *bss;
|
||||
int res = 0;
|
||||
|
||||
@ -729,7 +733,8 @@ static int ieee80211_privacy_mismatch(struct net_device *dev,
|
||||
ifsta->key_management_enabled)
|
||||
return 0;
|
||||
|
||||
bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
|
||||
bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel,
|
||||
ifsta->ssid, ifsta->ssid_len);
|
||||
if (!bss)
|
||||
return 0;
|
||||
|
||||
@ -1203,15 +1208,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
|
||||
capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
|
||||
status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
|
||||
aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
|
||||
if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
|
||||
printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not "
|
||||
"set\n", dev->name, aid);
|
||||
aid &= ~(BIT(15) | BIT(14));
|
||||
|
||||
printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x "
|
||||
"status=%d aid=%d)\n",
|
||||
dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa),
|
||||
capab_info, status_code, aid);
|
||||
capab_info, status_code, aid & ~(BIT(15) | BIT(14)));
|
||||
|
||||
if (status_code != WLAN_STATUS_SUCCESS) {
|
||||
printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
|
||||
@ -1223,6 +1224,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
|
||||
return;
|
||||
}
|
||||
|
||||
if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
|
||||
printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not "
|
||||
"set\n", dev->name, aid);
|
||||
aid &= ~(BIT(15) | BIT(14));
|
||||
|
||||
pos = mgmt->u.assoc_resp.variable;
|
||||
if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems)
|
||||
== ParseFailed) {
|
||||
@ -1241,7 +1247,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
|
||||
* update our stored copy */
|
||||
if (elems.erp_info && elems.erp_info_len >= 1) {
|
||||
struct ieee80211_sta_bss *bss
|
||||
= ieee80211_rx_bss_get(dev, ifsta->bssid);
|
||||
= ieee80211_rx_bss_get(dev, ifsta->bssid,
|
||||
local->hw.conf.channel,
|
||||
ifsta->ssid, ifsta->ssid_len);
|
||||
if (bss) {
|
||||
bss->erp_value = elems.erp_info[0];
|
||||
bss->has_erp_value = 1;
|
||||
@ -1271,7 +1279,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
|
||||
" AP\n", dev->name);
|
||||
return;
|
||||
}
|
||||
bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
|
||||
bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
|
||||
local->hw.conf.channel,
|
||||
ifsta->ssid, ifsta->ssid_len);
|
||||
if (bss) {
|
||||
sta->last_rssi = bss->rssi;
|
||||
sta->last_signal = bss->signal;
|
||||
@ -1347,7 +1357,8 @@ static void __ieee80211_rx_bss_hash_del(struct net_device *dev,
|
||||
|
||||
|
||||
static struct ieee80211_sta_bss *
|
||||
ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid)
|
||||
ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel,
|
||||
u8 *ssid, u8 ssid_len)
|
||||
{
|
||||
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||
struct ieee80211_sta_bss *bss;
|
||||
@ -1358,6 +1369,11 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid)
|
||||
atomic_inc(&bss->users);
|
||||
atomic_inc(&bss->users);
|
||||
memcpy(bss->bssid, bssid, ETH_ALEN);
|
||||
bss->channel = channel;
|
||||
if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) {
|
||||
memcpy(bss->ssid, ssid, ssid_len);
|
||||
bss->ssid_len = ssid_len;
|
||||
}
|
||||
|
||||
spin_lock_bh(&local->sta_bss_lock);
|
||||
/* TODO: order by RSSI? */
|
||||
@ -1369,7 +1385,8 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid)
|
||||
|
||||
|
||||
static struct ieee80211_sta_bss *
|
||||
ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid)
|
||||
ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel,
|
||||
u8 *ssid, u8 ssid_len)
|
||||
{
|
||||
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||
struct ieee80211_sta_bss *bss;
|
||||
@ -1377,7 +1394,10 @@ ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid)
|
||||
spin_lock_bh(&local->sta_bss_lock);
|
||||
bss = local->sta_bss_hash[STA_HASH(bssid)];
|
||||
while (bss) {
|
||||
if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0) {
|
||||
if (!memcmp(bss->bssid, bssid, ETH_ALEN) &&
|
||||
bss->channel == channel &&
|
||||
bss->ssid_len == ssid_len &&
|
||||
(ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) {
|
||||
atomic_inc(&bss->users);
|
||||
break;
|
||||
}
|
||||
@ -1545,9 +1565,11 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
|
||||
else
|
||||
channel = rx_status->channel;
|
||||
|
||||
bss = ieee80211_rx_bss_get(dev, mgmt->bssid);
|
||||
bss = ieee80211_rx_bss_get(dev, mgmt->bssid, channel,
|
||||
elems.ssid, elems.ssid_len);
|
||||
if (!bss) {
|
||||
bss = ieee80211_rx_bss_add(dev, mgmt->bssid);
|
||||
bss = ieee80211_rx_bss_add(dev, mgmt->bssid, channel,
|
||||
elems.ssid, elems.ssid_len);
|
||||
if (!bss)
|
||||
return;
|
||||
} else {
|
||||
@ -1573,10 +1595,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
|
||||
|
||||
bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
|
||||
bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
|
||||
if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) {
|
||||
memcpy(bss->ssid, elems.ssid, elems.ssid_len);
|
||||
bss->ssid_len = elems.ssid_len;
|
||||
}
|
||||
|
||||
bss->supp_rates_len = 0;
|
||||
if (elems.supp_rates) {
|
||||
@ -1647,7 +1665,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
|
||||
|
||||
|
||||
bss->hw_mode = rx_status->phymode;
|
||||
bss->channel = channel;
|
||||
bss->freq = rx_status->freq;
|
||||
if (channel != rx_status->channel &&
|
||||
(bss->hw_mode == MODE_IEEE80211G ||
|
||||
@ -2375,7 +2392,7 @@ static int ieee80211_sta_create_ibss(struct net_device *dev,
|
||||
{
|
||||
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||
struct ieee80211_sta_bss *bss;
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
struct ieee80211_hw_mode *mode;
|
||||
u8 bssid[ETH_ALEN], *pos;
|
||||
int i;
|
||||
@ -2398,18 +2415,17 @@ static int ieee80211_sta_create_ibss(struct net_device *dev,
|
||||
printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n",
|
||||
dev->name, print_mac(mac, bssid));
|
||||
|
||||
bss = ieee80211_rx_bss_add(dev, bssid);
|
||||
bss = ieee80211_rx_bss_add(dev, bssid, local->hw.conf.channel,
|
||||
sdata->u.sta.ssid, sdata->u.sta.ssid_len);
|
||||
if (!bss)
|
||||
return -ENOMEM;
|
||||
|
||||
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
mode = local->oper_hw_mode;
|
||||
|
||||
if (local->hw.conf.beacon_int == 0)
|
||||
local->hw.conf.beacon_int = 100;
|
||||
bss->beacon_int = local->hw.conf.beacon_int;
|
||||
bss->hw_mode = local->hw.conf.phymode;
|
||||
bss->channel = local->hw.conf.channel;
|
||||
bss->freq = local->hw.conf.freq;
|
||||
bss->last_update = jiffies;
|
||||
bss->capability = WLAN_CAPABILITY_IBSS;
|
||||
@ -2469,7 +2485,8 @@ static int ieee80211_sta_find_ibss(struct net_device *dev,
|
||||
"%s\n", print_mac(mac, bssid), print_mac(mac2, ifsta->bssid));
|
||||
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
|
||||
if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 &&
|
||||
(bss = ieee80211_rx_bss_get(dev, bssid))) {
|
||||
(bss = ieee80211_rx_bss_get(dev, bssid, local->hw.conf.channel,
|
||||
ifsta->ssid, ifsta->ssid_len))) {
|
||||
printk(KERN_DEBUG "%s: Selected IBSS BSSID %s"
|
||||
" based on configured SSID\n",
|
||||
dev->name, print_mac(mac, bssid));
|
||||
|
@ -834,10 +834,12 @@ static int tcp_packet(struct nf_conn *conntrack,
|
||||
case TCP_CONNTRACK_SYN_SENT:
|
||||
if (old_state < TCP_CONNTRACK_TIME_WAIT)
|
||||
break;
|
||||
if (conntrack->proto.tcp.seen[!dir].flags &
|
||||
IP_CT_TCP_FLAG_CLOSE_INIT) {
|
||||
/* Attempt to reopen a closed connection.
|
||||
* Delete this connection and look up again. */
|
||||
if ((conntrack->proto.tcp.seen[!dir].flags &
|
||||
IP_CT_TCP_FLAG_CLOSE_INIT)
|
||||
|| (conntrack->proto.tcp.last_dir == dir
|
||||
&& conntrack->proto.tcp.last_index == TCP_RST_SET)) {
|
||||
/* Attempt to reopen a closed/aborted connection.
|
||||
* Delete this connection and look up again. */
|
||||
write_unlock_bh(&tcp_lock);
|
||||
if (del_timer(&conntrack->timeout))
|
||||
conntrack->timeout.function((unsigned long)
|
||||
@ -925,6 +927,7 @@ static int tcp_packet(struct nf_conn *conntrack,
|
||||
in_window:
|
||||
/* From now on we have got in-window packets */
|
||||
conntrack->proto.tcp.last_index = index;
|
||||
conntrack->proto.tcp.last_dir = dir;
|
||||
|
||||
pr_debug("tcp_conntracks: ");
|
||||
NF_CT_DUMP_TUPLE(tuple);
|
||||
|
@ -42,21 +42,21 @@ match_flags(const struct xt_sctp_flag_info *flag_info,
|
||||
static inline bool
|
||||
match_packet(const struct sk_buff *skb,
|
||||
unsigned int offset,
|
||||
const u_int32_t *chunkmap,
|
||||
int chunk_match_type,
|
||||
const struct xt_sctp_flag_info *flag_info,
|
||||
const int flag_count,
|
||||
const struct xt_sctp_info *info,
|
||||
bool *hotdrop)
|
||||
{
|
||||
u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
|
||||
sctp_chunkhdr_t _sch, *sch;
|
||||
int chunk_match_type = info->chunk_match_type;
|
||||
const struct xt_sctp_flag_info *flag_info = info->flag_info;
|
||||
int flag_count = info->flag_count;
|
||||
|
||||
#ifdef DEBUG_SCTP
|
||||
int i = 0;
|
||||
#endif
|
||||
|
||||
if (chunk_match_type == SCTP_CHUNK_MATCH_ALL)
|
||||
SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
|
||||
SCTP_CHUNKMAP_COPY(chunkmapcopy, info->chunkmap);
|
||||
|
||||
do {
|
||||
sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch);
|
||||
@ -73,7 +73,7 @@ match_packet(const struct sk_buff *skb,
|
||||
|
||||
duprintf("skb->len: %d\toffset: %d\n", skb->len, offset);
|
||||
|
||||
if (SCTP_CHUNKMAP_IS_SET(chunkmap, sch->type)) {
|
||||
if (SCTP_CHUNKMAP_IS_SET(info->chunkmap, sch->type)) {
|
||||
switch (chunk_match_type) {
|
||||
case SCTP_CHUNK_MATCH_ANY:
|
||||
if (match_flags(flag_info, flag_count,
|
||||
@ -104,7 +104,7 @@ match_packet(const struct sk_buff *skb,
|
||||
|
||||
switch (chunk_match_type) {
|
||||
case SCTP_CHUNK_MATCH_ALL:
|
||||
return SCTP_CHUNKMAP_IS_CLEAR(chunkmap);
|
||||
return SCTP_CHUNKMAP_IS_CLEAR(info->chunkmap);
|
||||
case SCTP_CHUNK_MATCH_ANY:
|
||||
return false;
|
||||
case SCTP_CHUNK_MATCH_ONLY:
|
||||
@ -148,9 +148,7 @@ match(const struct sk_buff *skb,
|
||||
&& ntohs(sh->dest) <= info->dpts[1],
|
||||
XT_SCTP_DEST_PORTS, info->flags, info->invflags)
|
||||
&& SCCHECK(match_packet(skb, protoff + sizeof (sctp_sctphdr_t),
|
||||
info->chunkmap, info->chunk_match_type,
|
||||
info->flag_info, info->flag_count,
|
||||
hotdrop),
|
||||
info, hotdrop),
|
||||
XT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
|
||||
}
|
||||
|
||||
|
@ -249,10 +249,11 @@ static void dev_watchdog_down(struct net_device *dev)
|
||||
*/
|
||||
void netif_carrier_on(struct net_device *dev)
|
||||
{
|
||||
if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state))
|
||||
if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state)) {
|
||||
linkwatch_fire_event(dev);
|
||||
if (netif_running(dev))
|
||||
__netdev_watchdog_up(dev);
|
||||
if (netif_running(dev))
|
||||
__netdev_watchdog_up(dev);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -49,13 +49,16 @@ EXPORT_SYMBOL(secpath_dup);
|
||||
int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq)
|
||||
{
|
||||
int offset, offset_seq;
|
||||
int hlen;
|
||||
|
||||
switch (nexthdr) {
|
||||
case IPPROTO_AH:
|
||||
hlen = sizeof(struct ip_auth_hdr);
|
||||
offset = offsetof(struct ip_auth_hdr, spi);
|
||||
offset_seq = offsetof(struct ip_auth_hdr, seq_no);
|
||||
break;
|
||||
case IPPROTO_ESP:
|
||||
hlen = sizeof(struct ip_esp_hdr);
|
||||
offset = offsetof(struct ip_esp_hdr, spi);
|
||||
offset_seq = offsetof(struct ip_esp_hdr, seq_no);
|
||||
break;
|
||||
@ -69,7 +72,7 @@ int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!pskb_may_pull(skb, 16))
|
||||
if (!pskb_may_pull(skb, hlen))
|
||||
return -EINVAL;
|
||||
|
||||
*spi = *(__be32*)(skb_transport_header(skb) + offset);
|
||||
|
@ -63,7 +63,7 @@ int xfrm_output(struct sk_buff *skb)
|
||||
xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
|
||||
}
|
||||
|
||||
err = x->mode->output(x, skb);
|
||||
err = x->outer_mode->output(x, skb);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
@ -82,7 +82,7 @@ int xfrm_output(struct sk_buff *skb)
|
||||
}
|
||||
dst = skb->dst;
|
||||
x = dst->xfrm;
|
||||
} while (x && (x->props.mode != XFRM_MODE_TUNNEL));
|
||||
} while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL));
|
||||
|
||||
err = 0;
|
||||
|
||||
|
@ -49,8 +49,6 @@ static DEFINE_SPINLOCK(xfrm_policy_gc_lock);
|
||||
|
||||
static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family);
|
||||
static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo);
|
||||
static struct xfrm_policy_afinfo *xfrm_policy_lock_afinfo(unsigned int family);
|
||||
static void xfrm_policy_unlock_afinfo(struct xfrm_policy_afinfo *afinfo);
|
||||
|
||||
static inline int
|
||||
__xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl)
|
||||
@ -86,72 +84,6 @@ int xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xfrm_register_type(struct xfrm_type *type, unsigned short family)
|
||||
{
|
||||
struct xfrm_policy_afinfo *afinfo = xfrm_policy_lock_afinfo(family);
|
||||
struct xfrm_type **typemap;
|
||||
int err = 0;
|
||||
|
||||
if (unlikely(afinfo == NULL))
|
||||
return -EAFNOSUPPORT;
|
||||
typemap = afinfo->type_map;
|
||||
|
||||
if (likely(typemap[type->proto] == NULL))
|
||||
typemap[type->proto] = type;
|
||||
else
|
||||
err = -EEXIST;
|
||||
xfrm_policy_unlock_afinfo(afinfo);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm_register_type);
|
||||
|
||||
int xfrm_unregister_type(struct xfrm_type *type, unsigned short family)
|
||||
{
|
||||
struct xfrm_policy_afinfo *afinfo = xfrm_policy_lock_afinfo(family);
|
||||
struct xfrm_type **typemap;
|
||||
int err = 0;
|
||||
|
||||
if (unlikely(afinfo == NULL))
|
||||
return -EAFNOSUPPORT;
|
||||
typemap = afinfo->type_map;
|
||||
|
||||
if (unlikely(typemap[type->proto] != type))
|
||||
err = -ENOENT;
|
||||
else
|
||||
typemap[type->proto] = NULL;
|
||||
xfrm_policy_unlock_afinfo(afinfo);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm_unregister_type);
|
||||
|
||||
struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family)
|
||||
{
|
||||
struct xfrm_policy_afinfo *afinfo;
|
||||
struct xfrm_type **typemap;
|
||||
struct xfrm_type *type;
|
||||
int modload_attempted = 0;
|
||||
|
||||
retry:
|
||||
afinfo = xfrm_policy_get_afinfo(family);
|
||||
if (unlikely(afinfo == NULL))
|
||||
return NULL;
|
||||
typemap = afinfo->type_map;
|
||||
|
||||
type = typemap[proto];
|
||||
if (unlikely(type && !try_module_get(type->owner)))
|
||||
type = NULL;
|
||||
if (!type && !modload_attempted) {
|
||||
xfrm_policy_put_afinfo(afinfo);
|
||||
request_module("xfrm-type-%d-%d",
|
||||
(int) family, (int) proto);
|
||||
modload_attempted = 1;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
xfrm_policy_put_afinfo(afinfo);
|
||||
return type;
|
||||
}
|
||||
|
||||
int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl,
|
||||
unsigned short family)
|
||||
{
|
||||
@ -170,94 +102,6 @@ int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl,
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm_dst_lookup);
|
||||
|
||||
void xfrm_put_type(struct xfrm_type *type)
|
||||
{
|
||||
module_put(type->owner);
|
||||
}
|
||||
|
||||
int xfrm_register_mode(struct xfrm_mode *mode, int family)
|
||||
{
|
||||
struct xfrm_policy_afinfo *afinfo;
|
||||
struct xfrm_mode **modemap;
|
||||
int err;
|
||||
|
||||
if (unlikely(mode->encap >= XFRM_MODE_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
afinfo = xfrm_policy_lock_afinfo(family);
|
||||
if (unlikely(afinfo == NULL))
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
err = -EEXIST;
|
||||
modemap = afinfo->mode_map;
|
||||
if (likely(modemap[mode->encap] == NULL)) {
|
||||
modemap[mode->encap] = mode;
|
||||
err = 0;
|
||||
}
|
||||
|
||||
xfrm_policy_unlock_afinfo(afinfo);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm_register_mode);
|
||||
|
||||
int xfrm_unregister_mode(struct xfrm_mode *mode, int family)
|
||||
{
|
||||
struct xfrm_policy_afinfo *afinfo;
|
||||
struct xfrm_mode **modemap;
|
||||
int err;
|
||||
|
||||
if (unlikely(mode->encap >= XFRM_MODE_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
afinfo = xfrm_policy_lock_afinfo(family);
|
||||
if (unlikely(afinfo == NULL))
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
err = -ENOENT;
|
||||
modemap = afinfo->mode_map;
|
||||
if (likely(modemap[mode->encap] == mode)) {
|
||||
modemap[mode->encap] = NULL;
|
||||
err = 0;
|
||||
}
|
||||
|
||||
xfrm_policy_unlock_afinfo(afinfo);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm_unregister_mode);
|
||||
|
||||
struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family)
|
||||
{
|
||||
struct xfrm_policy_afinfo *afinfo;
|
||||
struct xfrm_mode *mode;
|
||||
int modload_attempted = 0;
|
||||
|
||||
if (unlikely(encap >= XFRM_MODE_MAX))
|
||||
return NULL;
|
||||
|
||||
retry:
|
||||
afinfo = xfrm_policy_get_afinfo(family);
|
||||
if (unlikely(afinfo == NULL))
|
||||
return NULL;
|
||||
|
||||
mode = afinfo->mode_map[encap];
|
||||
if (unlikely(mode && !try_module_get(mode->owner)))
|
||||
mode = NULL;
|
||||
if (!mode && !modload_attempted) {
|
||||
xfrm_policy_put_afinfo(afinfo);
|
||||
request_module("xfrm-mode-%d-%d", family, encap);
|
||||
modload_attempted = 1;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
xfrm_policy_put_afinfo(afinfo);
|
||||
return mode;
|
||||
}
|
||||
|
||||
void xfrm_put_mode(struct xfrm_mode *mode)
|
||||
{
|
||||
module_put(mode->owner);
|
||||
}
|
||||
|
||||
static inline unsigned long make_jiffies(long secs)
|
||||
{
|
||||
if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ)
|
||||
@ -2096,7 +1940,8 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
|
||||
if (xdst->genid != dst->xfrm->genid)
|
||||
return 0;
|
||||
|
||||
if (strict && fl && dst->xfrm->props.mode != XFRM_MODE_TUNNEL &&
|
||||
if (strict && fl &&
|
||||
!(dst->xfrm->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) &&
|
||||
!xfrm_state_addr_flow_check(dst->xfrm, fl, family))
|
||||
return 0;
|
||||
|
||||
@ -2213,23 +2058,6 @@ static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo)
|
||||
read_unlock(&xfrm_policy_afinfo_lock);
|
||||
}
|
||||
|
||||
static struct xfrm_policy_afinfo *xfrm_policy_lock_afinfo(unsigned int family)
|
||||
{
|
||||
struct xfrm_policy_afinfo *afinfo;
|
||||
if (unlikely(family >= NPROTO))
|
||||
return NULL;
|
||||
write_lock_bh(&xfrm_policy_afinfo_lock);
|
||||
afinfo = xfrm_policy_afinfo[family];
|
||||
if (unlikely(!afinfo))
|
||||
write_unlock_bh(&xfrm_policy_afinfo_lock);
|
||||
return afinfo;
|
||||
}
|
||||
|
||||
static void xfrm_policy_unlock_afinfo(struct xfrm_policy_afinfo *afinfo)
|
||||
{
|
||||
write_unlock_bh(&xfrm_policy_afinfo_lock);
|
||||
}
|
||||
|
||||
static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
|
||||
{
|
||||
struct net_device *dev = ptr;
|
||||
@ -2464,7 +2292,8 @@ static int xfrm_policy_migrate(struct xfrm_policy *pol,
|
||||
if (!migrate_tmpl_match(mp, &pol->xfrm_vec[i]))
|
||||
continue;
|
||||
n++;
|
||||
if (pol->xfrm_vec[i].mode != XFRM_MODE_TUNNEL)
|
||||
if (pol->xfrm_vec[i].mode != XFRM_MODE_TUNNEL &&
|
||||
pol->xfrm_vec[i].mode != XFRM_MODE_BEET)
|
||||
continue;
|
||||
/* update endpoints */
|
||||
memcpy(&pol->xfrm_vec[i].id.daddr, &mp->new_daddr,
|
||||
|
@ -57,6 +57,9 @@ static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024;
|
||||
static unsigned int xfrm_state_num;
|
||||
static unsigned int xfrm_state_genid;
|
||||
|
||||
static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family);
|
||||
static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
|
||||
|
||||
static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr,
|
||||
xfrm_address_t *saddr,
|
||||
u32 reqid,
|
||||
@ -187,6 +190,184 @@ int __xfrm_state_delete(struct xfrm_state *x);
|
||||
int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol);
|
||||
void km_state_expired(struct xfrm_state *x, int hard, u32 pid);
|
||||
|
||||
static struct xfrm_state_afinfo *xfrm_state_lock_afinfo(unsigned int family)
|
||||
{
|
||||
struct xfrm_state_afinfo *afinfo;
|
||||
if (unlikely(family >= NPROTO))
|
||||
return NULL;
|
||||
write_lock_bh(&xfrm_state_afinfo_lock);
|
||||
afinfo = xfrm_state_afinfo[family];
|
||||
if (unlikely(!afinfo))
|
||||
write_unlock_bh(&xfrm_state_afinfo_lock);
|
||||
return afinfo;
|
||||
}
|
||||
|
||||
static void xfrm_state_unlock_afinfo(struct xfrm_state_afinfo *afinfo)
|
||||
{
|
||||
write_unlock_bh(&xfrm_state_afinfo_lock);
|
||||
}
|
||||
|
||||
int xfrm_register_type(struct xfrm_type *type, unsigned short family)
|
||||
{
|
||||
struct xfrm_state_afinfo *afinfo = xfrm_state_lock_afinfo(family);
|
||||
struct xfrm_type **typemap;
|
||||
int err = 0;
|
||||
|
||||
if (unlikely(afinfo == NULL))
|
||||
return -EAFNOSUPPORT;
|
||||
typemap = afinfo->type_map;
|
||||
|
||||
if (likely(typemap[type->proto] == NULL))
|
||||
typemap[type->proto] = type;
|
||||
else
|
||||
err = -EEXIST;
|
||||
xfrm_state_unlock_afinfo(afinfo);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm_register_type);
|
||||
|
||||
int xfrm_unregister_type(struct xfrm_type *type, unsigned short family)
|
||||
{
|
||||
struct xfrm_state_afinfo *afinfo = xfrm_state_lock_afinfo(family);
|
||||
struct xfrm_type **typemap;
|
||||
int err = 0;
|
||||
|
||||
if (unlikely(afinfo == NULL))
|
||||
return -EAFNOSUPPORT;
|
||||
typemap = afinfo->type_map;
|
||||
|
||||
if (unlikely(typemap[type->proto] != type))
|
||||
err = -ENOENT;
|
||||
else
|
||||
typemap[type->proto] = NULL;
|
||||
xfrm_state_unlock_afinfo(afinfo);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm_unregister_type);
|
||||
|
||||
static struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family)
|
||||
{
|
||||
struct xfrm_state_afinfo *afinfo;
|
||||
struct xfrm_type **typemap;
|
||||
struct xfrm_type *type;
|
||||
int modload_attempted = 0;
|
||||
|
||||
retry:
|
||||
afinfo = xfrm_state_get_afinfo(family);
|
||||
if (unlikely(afinfo == NULL))
|
||||
return NULL;
|
||||
typemap = afinfo->type_map;
|
||||
|
||||
type = typemap[proto];
|
||||
if (unlikely(type && !try_module_get(type->owner)))
|
||||
type = NULL;
|
||||
if (!type && !modload_attempted) {
|
||||
xfrm_state_put_afinfo(afinfo);
|
||||
request_module("xfrm-type-%d-%d", family, proto);
|
||||
modload_attempted = 1;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
xfrm_state_put_afinfo(afinfo);
|
||||
return type;
|
||||
}
|
||||
|
||||
static void xfrm_put_type(struct xfrm_type *type)
|
||||
{
|
||||
module_put(type->owner);
|
||||
}
|
||||
|
||||
int xfrm_register_mode(struct xfrm_mode *mode, int family)
|
||||
{
|
||||
struct xfrm_state_afinfo *afinfo;
|
||||
struct xfrm_mode **modemap;
|
||||
int err;
|
||||
|
||||
if (unlikely(mode->encap >= XFRM_MODE_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
afinfo = xfrm_state_lock_afinfo(family);
|
||||
if (unlikely(afinfo == NULL))
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
err = -EEXIST;
|
||||
modemap = afinfo->mode_map;
|
||||
if (modemap[mode->encap])
|
||||
goto out;
|
||||
|
||||
err = -ENOENT;
|
||||
if (!try_module_get(afinfo->owner))
|
||||
goto out;
|
||||
|
||||
mode->afinfo = afinfo;
|
||||
modemap[mode->encap] = mode;
|
||||
err = 0;
|
||||
|
||||
out:
|
||||
xfrm_state_unlock_afinfo(afinfo);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm_register_mode);
|
||||
|
||||
int xfrm_unregister_mode(struct xfrm_mode *mode, int family)
|
||||
{
|
||||
struct xfrm_state_afinfo *afinfo;
|
||||
struct xfrm_mode **modemap;
|
||||
int err;
|
||||
|
||||
if (unlikely(mode->encap >= XFRM_MODE_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
afinfo = xfrm_state_lock_afinfo(family);
|
||||
if (unlikely(afinfo == NULL))
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
err = -ENOENT;
|
||||
modemap = afinfo->mode_map;
|
||||
if (likely(modemap[mode->encap] == mode)) {
|
||||
modemap[mode->encap] = NULL;
|
||||
module_put(mode->afinfo->owner);
|
||||
err = 0;
|
||||
}
|
||||
|
||||
xfrm_state_unlock_afinfo(afinfo);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm_unregister_mode);
|
||||
|
||||
static struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family)
|
||||
{
|
||||
struct xfrm_state_afinfo *afinfo;
|
||||
struct xfrm_mode *mode;
|
||||
int modload_attempted = 0;
|
||||
|
||||
if (unlikely(encap >= XFRM_MODE_MAX))
|
||||
return NULL;
|
||||
|
||||
retry:
|
||||
afinfo = xfrm_state_get_afinfo(family);
|
||||
if (unlikely(afinfo == NULL))
|
||||
return NULL;
|
||||
|
||||
mode = afinfo->mode_map[encap];
|
||||
if (unlikely(mode && !try_module_get(mode->owner)))
|
||||
mode = NULL;
|
||||
if (!mode && !modload_attempted) {
|
||||
xfrm_state_put_afinfo(afinfo);
|
||||
request_module("xfrm-mode-%d-%d", family, encap);
|
||||
modload_attempted = 1;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
xfrm_state_put_afinfo(afinfo);
|
||||
return mode;
|
||||
}
|
||||
|
||||
static void xfrm_put_mode(struct xfrm_mode *mode)
|
||||
{
|
||||
module_put(mode->owner);
|
||||
}
|
||||
|
||||
static void xfrm_state_gc_destroy(struct xfrm_state *x)
|
||||
{
|
||||
del_timer_sync(&x->timer);
|
||||
@ -196,8 +377,10 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
|
||||
kfree(x->calg);
|
||||
kfree(x->encap);
|
||||
kfree(x->coaddr);
|
||||
if (x->mode)
|
||||
xfrm_put_mode(x->mode);
|
||||
if (x->inner_mode)
|
||||
xfrm_put_mode(x->inner_mode);
|
||||
if (x->outer_mode)
|
||||
xfrm_put_mode(x->outer_mode);
|
||||
if (x->type) {
|
||||
x->type->destructor(x);
|
||||
xfrm_put_type(x->type);
|
||||
@ -1699,7 +1882,7 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo)
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm_state_unregister_afinfo);
|
||||
|
||||
struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family)
|
||||
static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family)
|
||||
{
|
||||
struct xfrm_state_afinfo *afinfo;
|
||||
if (unlikely(family >= NPROTO))
|
||||
@ -1711,14 +1894,11 @@ struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family)
|
||||
return afinfo;
|
||||
}
|
||||
|
||||
void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo)
|
||||
static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo)
|
||||
{
|
||||
read_unlock(&xfrm_state_afinfo_lock);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(xfrm_state_get_afinfo);
|
||||
EXPORT_SYMBOL(xfrm_state_put_afinfo);
|
||||
|
||||
/* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */
|
||||
void xfrm_state_delete_tunnel(struct xfrm_state *x)
|
||||
{
|
||||
@ -1769,6 +1949,14 @@ int xfrm_init_state(struct xfrm_state *x)
|
||||
goto error;
|
||||
|
||||
err = -EPROTONOSUPPORT;
|
||||
x->inner_mode = xfrm_get_mode(x->props.mode, x->sel.family);
|
||||
if (x->inner_mode == NULL)
|
||||
goto error;
|
||||
|
||||
if (!(x->inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) &&
|
||||
family != x->sel.family)
|
||||
goto error;
|
||||
|
||||
x->type = xfrm_get_type(x->id.proto, family);
|
||||
if (x->type == NULL)
|
||||
goto error;
|
||||
@ -1777,8 +1965,8 @@ int xfrm_init_state(struct xfrm_state *x)
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
x->mode = xfrm_get_mode(x->props.mode, family);
|
||||
if (x->mode == NULL)
|
||||
x->outer_mode = xfrm_get_mode(x->props.mode, family);
|
||||
if (x->outer_mode == NULL)
|
||||
goto error;
|
||||
|
||||
x->km.state = XFRM_STATE_VALID;
|
||||
|
Loading…
Reference in New Issue
Block a user