* [PATCH] mac80211: only honor IW_SCAN_THIS_ESSID in STA, IBSS, and AP modes
From: John W. Linville @ 2007-10-17 14:54 UTC (permalink / raw)
To: linux-wireless; +Cc: davem, flamingice, netdev, John W. Linville
In-Reply-To: <20071017145315.GC5744@tuxdriver.com>
The previous IW_SCAN_THIS_ESSID patch left a hole allowing scan
requests on interfaces in inappropriate modes.
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
net/mac80211/ieee80211_ioctl.c | 37 +++++++++++++++++++------------------
1 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c
index 83e4035..e1fafb6 100644
--- a/net/mac80211/ieee80211_ioctl.c
+++ b/net/mac80211/ieee80211_ioctl.c
@@ -521,29 +521,30 @@ static int ieee80211_ioctl_siwscan(struct net_device *dev,
if (!netif_running(dev))
return -ENETDOWN;
+ switch (sdata->type) {
+ case IEEE80211_IF_TYPE_STA:
+ case IEEE80211_IF_TYPE_IBSS:
+ if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) {
+ ssid = sdata->u.sta.ssid;
+ ssid_len = sdata->u.sta.ssid_len;
+ }
+ break;
+ case IEEE80211_IF_TYPE_AP:
+ if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) {
+ ssid = sdata->u.ap.ssid;
+ ssid_len = sdata->u.ap.ssid_len;
+ }
+ break;
+ default:
+ 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;
- } else {
- switch (sdata->type) {
- case IEEE80211_IF_TYPE_STA:
- case IEEE80211_IF_TYPE_IBSS:
- if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) {
- ssid = sdata->u.sta.ssid;
- ssid_len = sdata->u.sta.ssid_len;
- }
- break;
- case IEEE80211_IF_TYPE_AP:
- if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) {
- ssid = sdata->u.ap.ssid;
- ssid_len = sdata->u.ap.ssid_len;
- }
- break;
- default:
- return -EOPNOTSUPP;
- }
}
return ieee80211_sta_req_scan(dev, ssid, ssid_len);
--
1.5.2.4
^ permalink raw reply related
* [PATCH] NET: Fix uninitialised variable in ip_frag_reasm()
From: David Howells @ 2007-10-17 15:02 UTC (permalink / raw)
To: netdev; +Cc: dhowells
Fix uninitialised variable in ip_frag_reasm(). err should be set to -ENOMEM
if the initial call of skb_clone() fails.
Signed-off-by: David Howells <dhowells@redhat.com>
---
net/ipv4/ip_fragment.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 443b3f8..4629dad 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -545,7 +545,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 +570,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 +625,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())
^ permalink raw reply related
* [PATCH 9/11] [IPSEC]: Use the top IPv4 route's peer instead of the bottom
From: Herbert Xu @ 2007-10-17 14:34 UTC (permalink / raw)
To: David S. Miller, YOSHIFUJI Hideaki, Patrick McHardy, netdev
In-Reply-To: <20071017142940.GA23879@gondor.apana.org.au>
[IPSEC]: Use the top IPv4 route's peer instead of the bottom
For IPv4 we were using the bottom route's peer instead of the top one.
This is wrong because the peer is only used by TCP to keep track of
information about the TCP destination address which certainly does not
live in the bottom route.
This patch fixes that which allows us to get rid of the family check
since the bottom route could be IPv6 while the top one must always
be IPv4.
I've also changed the other fields which are IPv4-specific to get the
info from the top route instead of potentially bogus data from the
bottom route.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
net/ipv4/xfrm4_policy.c | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index c65b8e0..1f0ea0e 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -169,16 +169,16 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour);
dst_prev->input = rt->u.dst.input;
dst_prev->output = dst_prev->xfrm->mode->afinfo->output;
- if (dst_prev->xfrm->props.family == AF_INET && rt->peer)
- atomic_inc(&rt->peer->refcnt);
- x->u.rt.peer = rt->peer;
+ 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);
@@ -280,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);
}
^ permalink raw reply related
* [PATCH 11/11] [IPSEC]: Rename mode to outer_mode and add inner_mode
From: Herbert Xu @ 2007-10-17 14:34 UTC (permalink / raw)
To: David S. Miller, YOSHIFUJI Hideaki, Patrick McHardy, netdev
In-Reply-To: <20071017142940.GA23879@gondor.apana.org.au>
[IPSEC]: Rename mode to outer_mode and add inner_mode
This patch adds a new field to xfrm states called inner_mode. The existing
mode object is renamed to outer_mode.
This is the first part of an attempt to fix inter-family transforms. As it
is we always use the outer family when determining which mode to use. As a
result we may end up shoving IPv4 packets into netfilter6 and vice versa.
What we really want is to use the inner family for the first part of outbound
processing and the outer family for the second part. For inbound processing
we'd use the opposite pairing.
I've also added a check to prevent silly combinations such as transport mode
with inter-family transforms.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
include/net/xfrm.h | 3 ++-
net/core/pktgen.c | 2 +-
net/ipv4/xfrm4_input.c | 4 ++--
net/ipv4/xfrm4_policy.c | 2 +-
net/ipv6/xfrm6_input.c | 4 ++--
net/ipv6/xfrm6_policy.c | 2 +-
net/xfrm/xfrm_output.c | 4 ++--
net/xfrm/xfrm_policy.c | 2 +-
net/xfrm/xfrm_state.c | 18 ++++++++++++++----
9 files changed, 26 insertions(+), 15 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index f0f3318..688f6f5 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -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;
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 2100c73..8cae60c 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -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);
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index bc5dc07..5e95c8a 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -91,10 +91,10 @@ int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
xfrm_vec[xfrm_nr++] = x;
- if (x->mode->input(x, skb))
+ if (x->outer_mode->input(x, skb))
goto drop;
- if (x->mode->flags & XFRM_MODE_FLAG_TUNNEL) {
+ if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
decaps = 1;
break;
}
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 1f0ea0e..cc86fb1 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -168,7 +168,7 @@ __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;
- dst_prev->output = dst_prev->xfrm->mode->afinfo->output;
+ dst_prev->output = dst_prev->xfrm->outer_mode->afinfo->output;
if (rt0->peer)
atomic_inc(&rt0->peer->refcnt);
x->u.rt.peer = rt0->peer;
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index c6ee1a3..5157837 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -68,10 +68,10 @@ int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
xfrm_vec[xfrm_nr++] = x;
- if (x->mode->input(x, skb))
+ if (x->outer_mode->input(x, skb))
goto drop;
- if (x->mode->flags & XFRM_MODE_FLAG_TUNNEL) {
+ if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
decaps = 1;
break;
}
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 3242683..82e27b8 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -230,7 +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;
- dst_prev->output = dst_prev->xfrm->mode->afinfo->output;
+ 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);
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 8bf71ba..f4bfd6c 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -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->mode->flags & XFRM_MODE_FLAG_TUNNEL));
+ } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL));
err = 0;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 1d66fb4..b702bd8 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1941,7 +1941,7 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
return 0;
if (strict && fl &&
- !(dst->xfrm->mode->flags & XFRM_MODE_FLAG_TUNNEL) &&
+ !(dst->xfrm->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) &&
!xfrm_state_addr_flow_check(dst->xfrm, fl, family))
return 0;
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 48b4a06..224b44e 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -377,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);
@@ -1947,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;
@@ -1955,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;
^ permalink raw reply related
* [PATCH 8/11] [IPSEC]: Store afinfo pointer in xfrm_mode
From: Herbert Xu @ 2007-10-17 14:34 UTC (permalink / raw)
To: David S. Miller, YOSHIFUJI Hideaki, Patrick McHardy, netdev
In-Reply-To: <20071017142940.GA23879@gondor.apana.org.au>
[IPSEC]: Store afinfo pointer in xfrm_mode
It is convenient to have a pointer from xfrm_state to address-specific
functions such as the output function for a family. Currently the
address-specific policy code calls out to the xfrm state code to get
those pointers when we could get it in an easier way via the state
itself.
This patch adds an xfrm_state_afinfo to xfrm_mode (since they're
address-specific) and changes the policy code to use it. I've also
added an owner field to do reference counting on the module providing
the afinfo even though it isn't strictly necessary today since IPv6
can't be unloaded yet.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
include/net/xfrm.h | 6 +++---
net/ipv4/xfrm4_policy.c | 13 +------------
net/ipv4/xfrm4_state.c | 1 +
net/ipv6/xfrm6_policy.c | 14 +-------------
net/ipv6/xfrm6_state.c | 1 +
net/xfrm/xfrm_state.c | 26 +++++++++++++++++---------
6 files changed, 24 insertions(+), 37 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 2143f29..f0f3318 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -253,7 +253,8 @@ 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);
@@ -267,8 +268,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);
@@ -312,6 +311,7 @@ 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;
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 2373d67..c65b8e0 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -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,17 +168,7 @@ __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);
+ dst_prev->output = dst_prev->xfrm->mode->afinfo->output;
if (dst_prev->xfrm->props.family == AF_INET && rt->peer)
atomic_inc(&rt->peer->refcnt);
x->u.rt.peer = rt->peer;
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index 93e2c06..13d54a1 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -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,
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index dc4bdcb..3242683 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -214,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;
@@ -231,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->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);
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index e644c80..b392bee 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -170,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,
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index dc438f2..48b4a06 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -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,
@@ -289,11 +292,18 @@ int xfrm_register_mode(struct xfrm_mode *mode, int family)
err = -EEXIST;
modemap = afinfo->mode_map;
- if (likely(modemap[mode->encap] == NULL)) {
- modemap[mode->encap] = mode;
- err = 0;
- }
+ 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;
}
@@ -316,6 +326,7 @@ int xfrm_unregister_mode(struct xfrm_mode *mode, int family)
modemap = afinfo->mode_map;
if (likely(modemap[mode->encap] == mode)) {
modemap[mode->encap] = NULL;
+ module_put(mode->afinfo->owner);
err = 0;
}
@@ -1869,7 +1880,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))
@@ -1881,14 +1892,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)
{
^ permalink raw reply related
* [PATCH 10/11] [IPSEC]: Disallow combinations of RO and AH/ESP/IPCOMP
From: Herbert Xu @ 2007-10-17 14:34 UTC (permalink / raw)
To: David S. Miller, YOSHIFUJI Hideaki, Patrick McHardy, netdev
In-Reply-To: <20071017142940.GA23879@gondor.apana.org.au>
[IPSEC]: Disallow combinations of RO and AH/ESP/IPCOMP
Combining RO and AH/ESP/IPCOMP does not make sense. So this patch adds a
check in the state initialisation function to prevent this.
This allows us to safely remove the mode input function of RO since it
can never be called anymore. Indeed, if somehow it does get called we'll
know about it through an OOPS instead of it slipping past silently.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
net/ipv6/ah6.c | 9 ++++++++-
net/ipv6/esp6.c | 9 ++++++++-
net/ipv6/ipcomp6.c | 9 ++++++++-
net/ipv6/xfrm6_mode_ro.c | 9 ---------
4 files changed, 24 insertions(+), 12 deletions(-)
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index a8221d1..67cd066 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -477,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;
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 9eb9285..b071543 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -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;
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 28fc8ed..80ef2a1 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -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())
diff --git a/net/ipv6/xfrm6_mode_ro.c b/net/ipv6/xfrm6_mode_ro.c
index 957ae36..a7bc8c6 100644
--- a/net/ipv6/xfrm6_mode_ro.c
+++ b/net/ipv6/xfrm6_mode_ro.c
@@ -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,
^ permalink raw reply related
* [PATCH 7/11] [IPSEC]: Add missing BEET checks
From: Herbert Xu @ 2007-10-17 14:34 UTC (permalink / raw)
To: David S. Miller, YOSHIFUJI Hideaki, Patrick McHardy, netdev
In-Reply-To: <20071017142940.GA23879@gondor.apana.org.au>
[IPSEC]: Add missing BEET checks
Currently BEET mode does not reinject the packet back into the stack
like tunnel mode does. Since BEET should behave just like tunnel mode
this is incorrect.
This patch fixes this by introducing a flags field to xfrm_mode that
tells the IPsec code whether it should terminate and reinject the packet
back into the stack.
It then sets the flag for BEET and tunnel mode.
I've also added a number of missing BEET checks elsewhere where we check
whether a given mode is a tunnel or not.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
include/net/xfrm.h | 6 ++++++
net/ipv4/xfrm4_input.c | 2 +-
net/ipv4/xfrm4_mode_beet.c | 1 +
net/ipv4/xfrm4_mode_tunnel.c | 1 +
net/ipv4/xfrm4_output.c | 2 +-
net/ipv4/xfrm4_policy.c | 2 +-
net/ipv6/xfrm6_input.c | 2 +-
net/ipv6/xfrm6_mode_beet.c | 1 +
net/ipv6/xfrm6_mode_tunnel.c | 1 +
net/ipv6/xfrm6_output.c | 2 +-
net/ipv6/xfrm6_policy.c | 3 +--
net/ipv6/xfrm6_state.c | 6 ++++--
net/xfrm/xfrm_output.c | 2 +-
net/xfrm/xfrm_policy.c | 6 ++++--
14 files changed, 25 insertions(+), 12 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 7f156a0..2143f29 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -314,6 +314,12 @@ struct xfrm_mode {
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);
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index 5cb0b59..bc5dc07 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -94,7 +94,7 @@ int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
if (x->mode->input(x, skb))
goto drop;
- if (x->props.mode == XFRM_MODE_TUNNEL) {
+ if (x->mode->flags & XFRM_MODE_FLAG_TUNNEL) {
decaps = 1;
break;
}
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
index 73d2338..e42e122 100644
--- a/net/ipv4/xfrm4_mode_beet.c
+++ b/net/ipv4/xfrm4_mode_beet.c
@@ -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)
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index 1ae9d32..e4deecb 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -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)
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index a4edd66..dcbc274 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -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->mode->flags & XFRM_MODE_FLAG_TUNNEL) {
err = xfrm4_tunnel_check_size(skb);
if (err)
goto error_nolock;
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 329825c..2373d67 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -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:
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index b1201c3..c6ee1a3 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -71,7 +71,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
if (x->mode->input(x, skb))
goto drop;
- if (x->props.mode == XFRM_MODE_TUNNEL) { /* XXX */
+ if (x->mode->flags & XFRM_MODE_FLAG_TUNNEL) {
decaps = 1;
break;
}
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
index 13bb1e8..2bfb4f0 100644
--- a/net/ipv6/xfrm6_mode_beet.c
+++ b/net/ipv6/xfrm6_mode_beet.c
@@ -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)
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index ea22838..fd84e22 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -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)
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index a5a32c1..c9f42d1 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -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->mode->flags & XFRM_MODE_FLAG_TUNNEL) {
err = xfrm6_tunnel_check_size(skb);
if (err)
goto error_nolock;
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 15aa4c5..dc4bdcb 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -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:
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index cdadb48..e644c80 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -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;
}
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 0eb3377..8bf71ba 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -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->mode->flags & XFRM_MODE_FLAG_TUNNEL));
err = 0;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index ca24c90..1d66fb4 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1940,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->mode->flags & XFRM_MODE_FLAG_TUNNEL) &&
!xfrm_state_addr_flow_check(dst->xfrm, fl, family))
return 0;
@@ -2291,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,
^ permalink raw reply related
* [PATCH 6/11] [IPSEC]: Move type and mode map into xfrm_state.c
From: Herbert Xu @ 2007-10-17 14:34 UTC (permalink / raw)
To: David S. Miller, YOSHIFUJI Hideaki, Patrick McHardy, netdev
In-Reply-To: <20071017142940.GA23879@gondor.apana.org.au>
[IPSEC]: Move type and mode map into xfrm_state.c
The type and mode maps are only used by SAs, not policies. So it makes
sense to move them from xfrm_policy.c into xfrm_state.c. This alos allows
us to mark xfrm_get_type/xfrm_put_type/xfrm_get_mode/xfrm_put_mode as
static.
The only other change I've made in the move is to get rid of the casts
on the request_module call for types. They're unnecessary because C
will promote them to ints anyway.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
include/net/xfrm.h | 8 --
net/xfrm/xfrm_policy.c | 173 -------------------------------------------------
net/xfrm/xfrm_state.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 172 insertions(+), 179 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index d8974ca..7f156a0 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -228,8 +228,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);
@@ -256,6 +254,8 @@ extern int __xfrm_state_delete(struct xfrm_state *x);
struct xfrm_state_afinfo {
unsigned short family;
+ 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,
@@ -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);
@@ -320,8 +318,6 @@ struct xfrm_mode {
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
{
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index af27c19..ca24c90 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -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)
@@ -2213,23 +2057,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;
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 344f0a6..dc438f2 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -187,6 +187,176 @@ 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 (likely(modemap[mode->encap] == NULL)) {
+ modemap[mode->encap] = mode;
+ err = 0;
+ }
+
+ 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;
+ 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);
^ permalink raw reply related
* [PATCH 5/11] [IPSEC]: Fix length check in xfrm_parse_spi
From: Herbert Xu @ 2007-10-17 14:34 UTC (permalink / raw)
To: David S. Miller, YOSHIFUJI Hideaki, Patrick McHardy, netdev
In-Reply-To: <20071017142940.GA23879@gondor.apana.org.au>
[IPSEC]: Fix length check in xfrm_parse_spi
Currently xfrm_parse_spi requires there to be 16 bytes for AH and ESP.
In contrived cases there may not actually be 16 bytes there since the
respective header sizes are less than that (8 and 12 currently).
This patch changes the test to use the actual header length instead of 16.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
net/xfrm/xfrm_input.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 113f444..cb97fda 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -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);
^ permalink raw reply related
* [PATCH 4/11] [IPSEC]: Move ip_summed zapping out of xfrm6_rcv_spi
From: Herbert Xu @ 2007-10-17 14:34 UTC (permalink / raw)
To: David S. Miller, YOSHIFUJI Hideaki, Patrick McHardy, netdev
In-Reply-To: <20071017142940.GA23879@gondor.apana.org.au>
[IPSEC]: Move ip_summed zapping out of xfrm6_rcv_spi
Not every transform needs to zap ip_summed. For example, a pure tunnel
mode encapsulation does not affect the hardware checksum at all. In fact,
every algorithm (that needs this) other than AH6 already does its own
ip_summed zapping.
This patch moves the zapping into AH6 which is in line with what IPv4 does.
Possible future optimisation: Checksum the data as we copy them in IPComp.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
net/ipv6/ah6.c | 2 ++
net/ipv6/xfrm6_input.c | 1 -
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index f9f6891..a8221d1 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -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;
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index 596a730..b1201c3 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -97,7 +97,6 @@ int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __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);
^ permalink raw reply related
* [PATCH 3/11] [IPSEC]: Get nexthdr from caller in xfrm6_rcv_spi
From: Herbert Xu @ 2007-10-17 14:34 UTC (permalink / raw)
To: David S. Miller, YOSHIFUJI Hideaki, Patrick McHardy, netdev
In-Reply-To: <20071017142940.GA23879@gondor.apana.org.au>
[IPSEC]: Get nexthdr from caller in xfrm6_rcv_spi
Currently xfrm6_rcv_spi gets the nexthdr value itself from the packet.
This means that we need to fix up the value in case we have a 4-on-6
tunnel. Moving this logic into the caller simplifies things and allows
us to merge the code with IPv4.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
include/net/xfrm.h | 2 +-
net/ipv6/xfrm6_input.c | 9 ++++-----
net/ipv6/xfrm6_tunnel.c | 2 +-
3 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 680739f..d8974ca 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1058,7 +1058,7 @@ static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
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);
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index 02f69e5..596a730 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -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);
@@ -135,7 +133,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);
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 6c67ac1..fae90ff 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -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,
^ permalink raw reply related
* [PATCH 2/11] [IPSEC]: Move tunnel parsing for IPv4 out of xfrm4_input
From: Herbert Xu @ 2007-10-17 14:34 UTC (permalink / raw)
To: David S. Miller, YOSHIFUJI Hideaki, Patrick McHardy, netdev
In-Reply-To: <20071017142940.GA23879@gondor.apana.org.au>
[IPSEC]: Move tunnel parsing for IPv4 out of xfrm4_input
This patch moves the tunnel parsing for IPv4 out of xfrm4_input and into
xfrm4_tunnel. This change is in line with what IPv6 does and will allow
us to merge the two input functions.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
include/net/xfrm.h | 8 ++++++++
net/ipv4/xfrm4_input.c | 36 +++++++++++-------------------------
net/ipv4/xfrm4_tunnel.c | 9 +++++++--
3 files changed, 26 insertions(+), 27 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 0e84484..680739f 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1046,7 +1046,15 @@ 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);
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index e9bbfde..5cb0b59 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -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;
@@ -111,7 +99,7 @@ static int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
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);
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index 83e9580..3268451 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -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,
};
^ permalink raw reply related
* [PATCH 1/11] [IPSEC]: Fix pure tunnel modes involving IPv6
From: Herbert Xu @ 2007-10-17 14:34 UTC (permalink / raw)
To: David S. Miller, YOSHIFUJI Hideaki, Patrick McHardy, netdev
In-Reply-To: <20071017142940.GA23879@gondor.apana.org.au>
[IPSEC]: Fix pure tunnel modes involving IPv6
I noticed that my recent patch broke 6-on-4 pure IPsec tunnels (the ones
that are only used for incompressible IPsec packets). Subsequent reviews
show that I broke 6-on-6 pure tunnels more than three years ago and nobody
ever noticed. I suppose every must be testing 6-on-6 IPComp with large
pings which are very compressible :)
This patch fixes both cases.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
net/ipv4/xfrm4_tunnel.c | 2 +-
net/ipv6/xfrm6_tunnel.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index 1312417..83e9580 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -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)
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 3f8a3ab..6c67ac1 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -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)
^ permalink raw reply related
* [0/11] Various xfrm fixes and clean-ups
From: Herbert Xu @ 2007-10-17 14:29 UTC (permalink / raw)
To: David S. Miller, YOSHIFUJI Hideaki, Patrick McHardy, netdev
Hi Dave:
This series of patches completely replaces the ones I posted
yesterday so you can delete the previous batch.
I'm still in the process of fixing up inter-family transforms
so this is mostly the patches I posted yesterday with the
offensive bits removed :)
I hadn't realised how broken inter-family transforms are on
output until I started trying to fix them. As it is, it'll
happily send IPv4 packets into the IPv6 ICMP stack or worse,
IPv6 netfilter and vice versa.
The last patch in the series lays the foundation of my fix
to this. My plan is to divide the work that's currently done
by x->mode->output into two parts so that the first part can
be done by the inner address family, i.e., x->inner_mode while
the rest of it will be done by x->outer_mode->output. A similar
scheme would operate on the inbound direction.
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* [PATCH] Fix memory leak in cleanup_ipv6_mibs()
From: Pavel Emelyanov @ 2007-10-17 14:04 UTC (permalink / raw)
To: David Miller; +Cc: Linux Netdev List, devel
The icmpv6msg mib statistics is not freed.
This is almost not critical for current kernel, since ipv6
module is unloadable, but this can happen on load error and
will happen every time we stop the network namespace (when
we have one, of course).
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
---
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index bc92938..1b1caf3 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -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);
}
^ permalink raw reply related
* Re: BUG: unable to handle kernel NULL pointer dereference at virtual address 000000b0
From: Eric Dumazet @ 2007-10-17 13:54 UTC (permalink / raw)
To: Krzysztof Oledzki; +Cc: netdev
In-Reply-To: <Pine.LNX.4.64.0710171250480.21430@bizon.gios.gov.pl>
Krzysztof Oledzki a écrit :
>
>
> On Wed, 17 Oct 2007, Eric Dumazet wrote:
>
>> Krzysztof Oledzki a écrit :
>>>
>>>
>>> On Wed, 17 Oct 2007, Eric Dumazet wrote:
>>>
>>>> Krzysztof Oledzki a écrit :
>>>>> Hello,
>>>>>
>>>>> Today I found in my logs:
>>>>>
>>>>> BUG: unable to handle kernel NULL pointer dereference at virtual
>>>>> address 000000b0
>>>>> printing eip:
>>>>> 78395f65
>>>>> *pde = 00000000
>>>>> Oops: 0000 [#1]
>>>>> PREEMPT SMP
>>>>> CPU: 0
>>>>> EIP: 0060:[<78395f65>] Not tainted VLI
>>>>> EFLAGS: 00210286 (2.6.22.9 #1)
>>>>> EIP is at __ip_route_output_key+0x412/0x722
>>>>> eax: 80000000 ebx: 00000000 ecx: 5dd2b1c3 edx: 00000000
>>>>> esi: 00000000 edi: d44c7e30 ebp: ec8c4980 esp: d44c7ddc
>>>>> ds: 007b es: 007b fs: 00d8 gs: 0033 ss: 0068
>>>>> Process smtpd (pid: 12479, ti=d44c6000 task=9e759510 task.ti=d44c6000)
>>>>> Stack: d44c7e7c d44c7e7c d44c7eb8 00000000 d44c7e7c 00000000
>>>>> 00000000 00000005
>>>>> 00000000 ffffffff 5dd2b1c3 00000000 00000000 00000000
>>>>> 00000000 00000000
>>>>> 00000000 00000000 00000000 00000000 00000000 00030000
>>>>> 00000000 d44c7e7c
>>>>> Call Trace:
>>>>> [<78396280>] ip_route_output_flow+0xb/0x3e
>>>>> [<783b2b29>] ip4_datagram_connect+0x1c9/0x308
>>>>> [<783ba70a>] inet_dgram_connect+0x45/0x4e
>>>>> [<7837135e>] sys_connect+0x72/0x9c
>>>>> [<78371607>] sock_map_fd+0x41/0x4a
>>>>> [<7840d1b1>] _spin_lock+0x33/0x3e
>>>>> [<7840d623>] _spin_unlock+0x25/0x3b
>>>>> [<78371607>] sock_map_fd+0x41/0x4a
>>>>> [<78372792>] sys_socketcall+0x8f/0x242
>>>>> [<7813e99c>] trace_hardirqs_on+0x122/0x14c
>>>>> [<78103dc6>] sysenter_past_esp+0x8f/0x99
>>>>> [<78103d96>] sysenter_past_esp+0x5f/0x99
>>>>> =======================
>>>>> Code: fa e0 00 00 00 75 07 c6 44 24 56 05 eb 14 81 fa f0 00 00 00
>>>>> 0f 84 e1 02 00 00 84 c0 0f 84 d9 02 00 00 8b 44 24 0c 0d 00 00 00
>>>>> 80 <f6> 86 b0 00 00 00 08 0f 44 44 24 0c 89 44 24 0c b8 01 00 00 00
>>>>> EIP: [<78395f65>] __ip_route_output_key+0x412/0x722 SS:ESP
>>>>> 0068:d44c7ddc
>>>>>
>>>>> Shortly before it there was:
>>>>> Oct 17 07:17:55 cougar postfix/master[3400]: warning: process
>>>>> /usr/lib/postfix/smtpd pid 12479 killed by signal 11
>>>>>
>>>>> Best regards,
>>>>>
>>>>>
>>>>> Krzysztof Olędzki
>>>>
>>>> Hello Krzysztof
>>>>
>>>> Could you give us some details about this ? kernel version at least.
>>>
>>> Yes, I was little to hurry sending this bug report. Anyway, it is
>>> 2.6.22.9 like mentioned in the oops: EFLAGS: 00210286 (2.6.22.9 #1)
>>>
>>>> (you could for example take a look at REPORTING-BUGS, or run
>>>> scripts/ver_linux)
>>>
>>> Linux cougar 2.6.22.9 #1 SMP PREEMPT Wed Oct 3 10:24:19 CEST 2007
>>> i686 Intel(R) Pentium(R) D CPU 3.20GHz GenuineIntel GNU/Linux
>>>
>>> Gnu C 4.1.2
>>> Gnu make 3.81
>>> binutils 2.17
>>> util-linux 2.12r
>>> mount 2.12r
>>> module-init-tools 3.2.2
>>> e2fsprogs 1.40.2
>>> Linux C Library > libc.2.5
>>> Dynamic linker (ldd) 2.5
>>> Procps 3.2.7
>>> Net-tools 1.60
>>> Kbd 1.12
>>> Sh-utils 6.9
>>>
>>
>> Yes indeed, version was on your initial report.
>>
>> It seems this kernel is unusual (VMSPLIT_2G_OPT instead of stdandard
>> VMSPLIT_3G), any chance you provide full .config ?
>
> Attached, both .config and dmesg.
>
Hum, you are using IPT_TPROXY thing, which is not in linux-2.6.22.9
I have no idea how this can taint the kernel, since you provide no information.
Try to reproduce the problem with a genuine kernel.
Thank you
^ permalink raw reply
* Re: Difference between device statistics from ifconfig and ip -s l l
From: Milan Kocian @ 2007-10-17 13:42 UTC (permalink / raw)
To: jamal; +Cc: Patrick McHardy, netdev
In-Reply-To: <1192622498.4460.25.camel@localhost>
On Wed, Oct 17, 2007 at 08:01:38AM -0400, jamal wrote:
> >
> > One probably stupid question: Why is not done similar sum in output of 'ip -s l l' ?
>
> "missed" is not really an error. It just means the driver was
> overwhelmed and didnt even get the chance of seeing it whereas an error
> is something the driver processed and saw a problem with it.
>
Thanks for explanation. But if I understand well, the packet is lost anyway, isn't it ?
And when the packet is lost and I want to see all problems, I have to use detailed
(ip -s -s ) stats because non-detailed (ip -s ) stats may hide problems. True ?
If yes then using non-detailed stats lacks sense.
> > Imagine me :), I do 'ifconfig' and see dropped packets and then I do 'ip -s l l'
> > and see zeros. I stare on it like an idiot. Where is bug ? ifconfig ? ip ?
> > (man page of ip and 'ip -s -s l l' with missed packets stats saved me :).
> >
> > IMHO I think that comparable outputs of both programs should be still the same.
>
> I think ifconfig sums them up so the output formatting looks nice, but
> ip is more accurate. These stats are from standard SNMP mibs (off top of
> my head RFC1213 if it hasnt been obsoleted by something) - look at
> InIFxxxx stats.
>
I will try to look at. Thanks!
> cheers,
> jamal
>
regards,
--
Milan Kocian
^ permalink raw reply
* [PATCH] Consolidate creation of kmem caches with "calculated" names
From: Pavel Emelyanov @ 2007-10-17 13:09 UTC (permalink / raw)
To: David Miller; +Cc: Linux Netdev List, devel
Some places in network (like protocol registration and dccp)
generate the kmem cache name with snprintf() to create caches
for several protocols with similar names.
Make the routine that makes this in one place. Possibly, this
is better to be put in mm/sl[uoa]b.c, but I haven't found
any other places in kernel that require such functionality,
so put this code (temporary?) in net/core/util.c
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
---
diff --git a/include/net/sock.h b/include/net/sock.h
index 453c79d..8040d59 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -601,6 +601,10 @@ struct proto {
extern int proto_register(struct proto *prot, int alloc_slab);
extern void proto_unregister(struct proto *prot);
+struct kmem_cache *kmem_cache_create_va(int size, unsigned long flags,
+ char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
+void kmem_cache_destroy_va(struct kmem_cache *);
+
#ifdef SOCK_REFCNT_DEBUG
static inline void sk_refcnt_debug_inc(struct sock *sk)
{
diff --git a/net/core/sock.c b/net/core/sock.c
index d45ecdc..65f485a 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1777,10 +1777,6 @@ static LIST_HEAD(proto_list);
int proto_register(struct proto *prot, int alloc_slab)
{
- char *request_sock_slab_name = NULL;
- char *timewait_sock_slab_name;
- int rc = -ENOBUFS;
-
if (alloc_slab) {
prot->slab = kmem_cache_create(prot->name, prot->obj_size, 0,
SLAB_HWCACHE_ALIGN, NULL);
@@ -1792,62 +1788,44 @@ int proto_register(struct proto *prot, int alloc_slab)
}
if (prot->rsk_prot != NULL) {
- static const char mask[] = "request_sock_%s";
-
- request_sock_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL);
- if (request_sock_slab_name == NULL)
- goto out_free_sock_slab;
-
- sprintf(request_sock_slab_name, mask, prot->name);
- prot->rsk_prot->slab = kmem_cache_create(request_sock_slab_name,
- prot->rsk_prot->obj_size, 0,
- SLAB_HWCACHE_ALIGN, NULL);
+ prot->rsk_prot->slab = kmem_cache_create_va(
+ prot->rsk_prot->obj_size,
+ SLAB_HWCACHE_ALIGN,
+ "request_sock_%s", prot->name);
if (prot->rsk_prot->slab == NULL) {
printk(KERN_CRIT "%s: Can't create request sock SLAB cache!\n",
prot->name);
- goto out_free_request_sock_slab_name;
+ goto out_rsk;
}
}
if (prot->twsk_prot != NULL) {
- static const char mask[] = "tw_sock_%s";
+ prot->twsk_prot->twsk_slab = kmem_cache_create_va(
+ prot->twsk_prot->twsk_obj_size,
+ SLAB_HWCACHE_ALIGN,
+ "tw_sock_%s", prot->name);
- timewait_sock_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL);
-
- if (timewait_sock_slab_name == NULL)
- goto out_free_request_sock_slab;
-
- sprintf(timewait_sock_slab_name, mask, prot->name);
- prot->twsk_prot->twsk_slab =
- kmem_cache_create(timewait_sock_slab_name,
- prot->twsk_prot->twsk_obj_size,
- 0, SLAB_HWCACHE_ALIGN,
- NULL);
if (prot->twsk_prot->twsk_slab == NULL)
- goto out_free_timewait_sock_slab_name;
+ goto out_twsk;
}
}
write_lock(&proto_list_lock);
list_add(&prot->node, &proto_list);
write_unlock(&proto_list_lock);
- rc = 0;
-out:
- return rc;
-out_free_timewait_sock_slab_name:
- kfree(timewait_sock_slab_name);
-out_free_request_sock_slab:
+ return 0;
+
+out_twsk:
if (prot->rsk_prot && prot->rsk_prot->slab) {
- kmem_cache_destroy(prot->rsk_prot->slab);
+ kmem_cache_destroy_va(prot->rsk_prot->slab);
prot->rsk_prot->slab = NULL;
}
-out_free_request_sock_slab_name:
- kfree(request_sock_slab_name);
-out_free_sock_slab:
+out_rsk:
kmem_cache_destroy(prot->slab);
prot->slab = NULL;
- goto out;
+out:
+ return -ENOBUFS;
}
EXPORT_SYMBOL(proto_register);
diff --git a/net/core/utils.c b/net/core/utils.c
index 0bf17da..eccc71b 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -293,3 +293,41 @@ out:
}
EXPORT_SYMBOL(in6_pton);
+
+struct kmem_cache *kmem_cache_create_va(int size, unsigned long flags,
+ char *fmt, ...)
+{
+ char *name, str[64];
+ struct kmem_cache *c;
+ va_list args;
+
+ va_start(args, fmt);
+ vsnprintf(str, sizeof(str), fmt, args);
+ va_end(args);
+
+ name = kstrdup(str, GFP_KERNEL);
+ if (name == NULL)
+ goto err_name;
+
+ c = kmem_cache_create(name, size, 0, flags, NULL);
+ if (c == NULL)
+ goto err_cache;
+
+ return c;
+
+err_cache:
+ kfree(name);
+err_name:
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(kmem_cache_create_va);
+
+void kmem_cache_destroy_va(struct kmem_cache *c)
+{
+ const char *name;
+
+ name = kmem_cache_name(c);
+ kmem_cache_destroy(c);
+ kfree(name);
+}
+EXPORT_SYMBOL_GPL(kmem_cache_destroy_va);
diff --git a/net/dccp/ccid.c b/net/dccp/ccid.c
index c45088b..9d2cc27 100644
--- a/net/dccp/ccid.c
+++ b/net/dccp/ccid.c
@@ -56,51 +56,21 @@ static inline void ccids_read_unlock(void)
#define ccids_read_unlock() do { } while(0)
#endif
-static struct kmem_cache *ccid_kmem_cache_create(int obj_size, const char *fmt,...)
-{
- struct kmem_cache *slab;
- char slab_name_fmt[32], *slab_name;
- va_list args;
-
- va_start(args, fmt);
- vsnprintf(slab_name_fmt, sizeof(slab_name_fmt), fmt, args);
- va_end(args);
-
- slab_name = kstrdup(slab_name_fmt, GFP_KERNEL);
- if (slab_name == NULL)
- return NULL;
- slab = kmem_cache_create(slab_name, sizeof(struct ccid) + obj_size, 0,
- SLAB_HWCACHE_ALIGN, NULL);
- if (slab == NULL)
- kfree(slab_name);
- return slab;
-}
-
-static void ccid_kmem_cache_destroy(struct kmem_cache *slab)
-{
- if (slab != NULL) {
- const char *name = kmem_cache_name(slab);
-
- kmem_cache_destroy(slab);
- kfree(name);
- }
-}
-
int ccid_register(struct ccid_operations *ccid_ops)
{
int err = -ENOBUFS;
ccid_ops->ccid_hc_rx_slab =
- ccid_kmem_cache_create(ccid_ops->ccid_hc_rx_obj_size,
- "%s_hc_rx_sock",
- ccid_ops->ccid_name);
+ kmem_cache_create_va(ccid_ops->ccid_hc_rx_obj_size,
+ SLAB_HWCACHE_ALIGN,
+ "%s_hc_rx_sock", ccid_ops->ccid_name);
if (ccid_ops->ccid_hc_rx_slab == NULL)
goto out;
ccid_ops->ccid_hc_tx_slab =
- ccid_kmem_cache_create(ccid_ops->ccid_hc_tx_obj_size,
- "%s_hc_tx_sock",
- ccid_ops->ccid_name);
+ kmem_cache_create_va(ccid_ops->ccid_hc_tx_obj_size,
+ SLAB_HWCACHE_ALIGN,
+ "%s_hc_tx_sock", ccid_ops->ccid_name);
if (ccid_ops->ccid_hc_tx_slab == NULL)
goto out_free_rx_slab;
@@ -118,12 +88,13 @@ int ccid_register(struct ccid_operations *ccid_ops)
ccid_ops->ccid_id, ccid_ops->ccid_name);
out:
return err;
+
out_free_tx_slab:
- ccid_kmem_cache_destroy(ccid_ops->ccid_hc_tx_slab);
+ kmem_cache_destroy_va(ccid_ops->ccid_hc_tx_slab);
ccid_ops->ccid_hc_tx_slab = NULL;
goto out;
out_free_rx_slab:
- ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab);
+ kmem_cache_destroy_va(ccid_ops->ccid_hc_rx_slab);
ccid_ops->ccid_hc_rx_slab = NULL;
goto out;
}
@@ -136,9 +107,9 @@ int ccid_unregister(struct ccid_operations *ccid_ops)
ccids[ccid_ops->ccid_id] = NULL;
ccids_write_unlock();
- ccid_kmem_cache_destroy(ccid_ops->ccid_hc_tx_slab);
+ kmem_cache_destroy_va(ccid_ops->ccid_hc_tx_slab);
ccid_ops->ccid_hc_tx_slab = NULL;
- ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab);
+ kmem_cache_destroy_va(ccid_ops->ccid_hc_rx_slab);
ccid_ops->ccid_hc_rx_slab = NULL;
pr_info("CCID: Unregistered CCID %d (%s)\n",
^ permalink raw reply related
* Re: Difference between device statistics from ifconfig and ip -s l l
From: jamal @ 2007-10-17 12:01 UTC (permalink / raw)
To: Milan Kocian; +Cc: Patrick McHardy, netdev
In-Reply-To: <20071017112919.GC16356@wq.cz>
On Wed, 2007-17-10 at 13:29 +0200, Milan Kocian wrote:
> On Wed, Oct 17, 2007 at 12:35:43PM +0200, Patrick McHardy wrote:
> > Milan Kocian wrote:
> >> On Wed, Oct 17, 2007 at 11:36:30AM +0200, Patrick McHardy wrote:
> >>
> >>> ifconfig gets its data from /proc/net/dev, which adds up rx_errors
> >>> and rx_missed.
> >>>
> >> Adds up rx_errors and rx_missed and prints it as dropped ? Ok, ifconfig is
> >> a little old. But why I don't see missed packets from RX errors detailed
> >> stats (ip -s -s l l) in non-detailed stats as errors and see zero ?
> >
> >
> > I meant to write "adds up rx_dropped and rx_missed".
>
> ok.
>
> One probably stupid question: Why is not done similar sum in output of 'ip -s l l' ?
"missed" is not really an error. It just means the driver was
overwhelmed and didnt even get the chance of seeing it whereas an error
is something the driver processed and saw a problem with it.
> Imagine me :), I do 'ifconfig' and see dropped packets and then I do 'ip -s l l'
> and see zeros. I stare on it like an idiot. Where is bug ? ifconfig ? ip ?
> (man page of ip and 'ip -s -s l l' with missed packets stats saved me :).
>
> IMHO I think that comparable outputs of both programs should be still the same.
I think ifconfig sums them up so the output formatting looks nice, but
ip is more accurate. These stats are from standard SNMP mibs (off top of
my head RFC1213 if it hasnt been obsoleted by something) - look at
InIFxxxx stats.
cheers,
jamal
^ permalink raw reply
* Re: BNX2X driver: kernel panic when running netperf
From: Eliezer Tamir @ 2007-10-17 11:46 UTC (permalink / raw)
To: masbock, netdev@vger.kernel.org; +Cc: David Miller
In-Reply-To: <20071016.164938.66177554.davem@davemloft.net>
On Tue, 2007-10-16 at 16:49 -0700, David Miller wrote:
> From: Max Asbock <masbock@us.ibm.com>
> Date: Tue, 16 Oct 2007 16:34:40 -0700
>
> > I tested the bnx2x driver (0001-BNX2X-0.40.10a-net-2.6.24.patch)
> with
> > netdev-2.6.24 git tree and found that I can reproducibly panic the
> > system when running netperf with the TCP_STREAM test.
> > I copied the following information from the panic message:
> > RIP: 0xc02fff32
> > net_rx_action +0x142/0x190
>
> The driver is doing netif_rx_complete() yet returning a value from
> ->poll() which is >= budget, which is illegal.
>
> We had to fix a similar bug in the tg3 and bnx2 drivers, the same
> logic probably just propagated itself into bnx2x.
I think that this will fix the bug.
This is a diff against 0.40.10a.
I hope to get a new version out soon, once we finish working on Dave's
comments.
Eliezer
---
drivers/net/bnx2x.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/bnx2x.c b/drivers/net/bnx2x.c
index f462c74..9220bd3 100644
--- a/drivers/net/bnx2x.c
+++ b/drivers/net/bnx2x.c
@@ -8085,9 +8085,10 @@ #endif
work_done = bnx2x_rx_int(fp, budget);
}
- rmb(); /* TBD check */
+ rmb(); /* bnx2x_has_work() reads the status block */
- if (!bnx2x_has_work(fp)) {
+ /* must not complete if we consumed full budget */
+ if ((work_done < budget) && !bnx2x_has_work(fp)) {
netif_rx_complete(bp->dev, napi);
bnx2x_ack_sb(bp, fp->index, USTORM_ID, fp->fp_u_idx,
--
1.4.2
^ permalink raw reply related
* Re: Difference between device statistics from ifconfig and ip -s l l
From: Milan Kocian @ 2007-10-17 11:29 UTC (permalink / raw)
To: Patrick McHardy; +Cc: netdev
In-Reply-To: <4715E57F.6080905@trash.net>
On Wed, Oct 17, 2007 at 12:35:43PM +0200, Patrick McHardy wrote:
> Milan Kocian wrote:
>> On Wed, Oct 17, 2007 at 11:36:30AM +0200, Patrick McHardy wrote:
>>
>>> ifconfig gets its data from /proc/net/dev, which adds up rx_errors
>>> and rx_missed.
>>>
>> Adds up rx_errors and rx_missed and prints it as dropped ? Ok, ifconfig is
>> a little old. But why I don't see missed packets from RX errors detailed
>> stats (ip -s -s l l) in non-detailed stats as errors and see zero ?
>
>
> I meant to write "adds up rx_dropped and rx_missed".
ok.
One probably stupid question: Why is not done similar sum in output of 'ip -s l l' ?
Imagine me :), I do 'ifconfig' and see dropped packets and then I do 'ip -s l l'
and see zeros. I stare on it like an idiot. Where is bug ? ifconfig ? ip ?
(man page of ip and 'ip -s -s l l' with missed packets stats saved me :).
IMHO I think that comparable outputs of both programs should be still the same.
thanks for reply.
regards,
--
Milan Kocian
^ permalink raw reply
* backlogged...
From: David Miller @ 2007-10-17 11:25 UTC (permalink / raw)
To: netdev
Sorry, I didn't get to process any networking patches today.
I got sidetracked fixing a bug in gcc-4.2.x that miscompiles the
kernel, and then debugging the block layer scatterlist regressions
added yesterday to Linus's tree.
Those are both resolved, so if nothing new explodes I'll try to catch
up a bit tomorrow.
^ permalink raw reply
* Re: BUG: unable to handle kernel NULL pointer dereference at virtual address 000000b0
From: Krzysztof Oledzki @ 2007-10-17 10:53 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev
In-Reply-To: <4715E60E.3020401@cosmosbay.com>
[-- Attachment #1: Type: TEXT/PLAIN, Size: 3483 bytes --]
On Wed, 17 Oct 2007, Eric Dumazet wrote:
> Krzysztof Oledzki a écrit :
>>
>>
>> On Wed, 17 Oct 2007, Eric Dumazet wrote:
>>
>>> Krzysztof Oledzki a écrit :
>>>> Hello,
>>>>
>>>> Today I found in my logs:
>>>>
>>>> BUG: unable to handle kernel NULL pointer dereference at virtual address
>>>> 000000b0
>>>> printing eip:
>>>> 78395f65
>>>> *pde = 00000000
>>>> Oops: 0000 [#1]
>>>> PREEMPT SMP
>>>> CPU: 0
>>>> EIP: 0060:[<78395f65>] Not tainted VLI
>>>> EFLAGS: 00210286 (2.6.22.9 #1)
>>>> EIP is at __ip_route_output_key+0x412/0x722
>>>> eax: 80000000 ebx: 00000000 ecx: 5dd2b1c3 edx: 00000000
>>>> esi: 00000000 edi: d44c7e30 ebp: ec8c4980 esp: d44c7ddc
>>>> ds: 007b es: 007b fs: 00d8 gs: 0033 ss: 0068
>>>> Process smtpd (pid: 12479, ti=d44c6000 task=9e759510 task.ti=d44c6000)
>>>> Stack: d44c7e7c d44c7e7c d44c7eb8 00000000 d44c7e7c 00000000 00000000
>>>> 00000005
>>>> 00000000 ffffffff 5dd2b1c3 00000000 00000000 00000000 00000000
>>>> 00000000
>>>> 00000000 00000000 00000000 00000000 00000000 00030000 00000000
>>>> d44c7e7c
>>>> Call Trace:
>>>> [<78396280>] ip_route_output_flow+0xb/0x3e
>>>> [<783b2b29>] ip4_datagram_connect+0x1c9/0x308
>>>> [<783ba70a>] inet_dgram_connect+0x45/0x4e
>>>> [<7837135e>] sys_connect+0x72/0x9c
>>>> [<78371607>] sock_map_fd+0x41/0x4a
>>>> [<7840d1b1>] _spin_lock+0x33/0x3e
>>>> [<7840d623>] _spin_unlock+0x25/0x3b
>>>> [<78371607>] sock_map_fd+0x41/0x4a
>>>> [<78372792>] sys_socketcall+0x8f/0x242
>>>> [<7813e99c>] trace_hardirqs_on+0x122/0x14c
>>>> [<78103dc6>] sysenter_past_esp+0x8f/0x99
>>>> [<78103d96>] sysenter_past_esp+0x5f/0x99
>>>> =======================
>>>> Code: fa e0 00 00 00 75 07 c6 44 24 56 05 eb 14 81 fa f0 00 00 00 0f 84
>>>> e1 02 00 00 84 c0 0f 84 d9 02 00 00 8b 44 24 0c 0d 00 00 00 80 <f6> 86 b0
>>>> 00 00 00 08 0f 44 44 24 0c 89 44 24 0c b8 01 00 00 00
>>>> EIP: [<78395f65>] __ip_route_output_key+0x412/0x722 SS:ESP 0068:d44c7ddc
>>>>
>>>> Shortly before it there was:
>>>> Oct 17 07:17:55 cougar postfix/master[3400]: warning: process
>>>> /usr/lib/postfix/smtpd pid 12479 killed by signal 11
>>>>
>>>> Best regards,
>>>>
>>>>
>>>> Krzysztof Olędzki
>>>
>>> Hello Krzysztof
>>>
>>> Could you give us some details about this ? kernel version at least.
>>
>> Yes, I was little to hurry sending this bug report. Anyway, it is 2.6.22.9
>> like mentioned in the oops: EFLAGS: 00210286 (2.6.22.9 #1)
>>
>>> (you could for example take a look at REPORTING-BUGS, or run
>>> scripts/ver_linux)
>>
>> Linux cougar 2.6.22.9 #1 SMP PREEMPT Wed Oct 3 10:24:19 CEST 2007 i686
>> Intel(R) Pentium(R) D CPU 3.20GHz GenuineIntel GNU/Linux
>>
>> Gnu C 4.1.2
>> Gnu make 3.81
>> binutils 2.17
>> util-linux 2.12r
>> mount 2.12r
>> module-init-tools 3.2.2
>> e2fsprogs 1.40.2
>> Linux C Library > libc.2.5
>> Dynamic linker (ldd) 2.5
>> Procps 3.2.7
>> Net-tools 1.60
>> Kbd 1.12
>> Sh-utils 6.9
>>
>
> Yes indeed, version was on your initial report.
>
> It seems this kernel is unusual (VMSPLIT_2G_OPT instead of stdandard
> VMSPLIT_3G), any chance you provide full .config ?
Attached, both .config and dmesg.
Thank you.
Best regards,
Krzysztof Olędzki
[-- Attachment #2: Type: APPLICATION/octet-stream, Size: 7500 bytes --]
[-- Attachment #3: Type: APPLICATION/octet-stream, Size: 8674 bytes --]
^ permalink raw reply
* [PATCH] Cleanup snmp6_alloc_dev()
From: Pavel Emelyanov @ 2007-10-17 10:44 UTC (permalink / raw)
To: David Miller; +Cc: Linux Netdev List, devel
This functions is never called with NULL or not setup argument,
so the checks inside are redundant.
Also, the return value is always -ENOMEM, so no need in
additional variable for this.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
---
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 52d10d2..c173549 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -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,7 +275,7 @@ 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)
^ permalink raw reply related
* Re: BUG: unable to handle kernel NULL pointer dereference at virtual address 000000b0
From: Eric Dumazet @ 2007-10-17 10:38 UTC (permalink / raw)
To: Krzysztof Oledzki; +Cc: netdev
In-Reply-To: <Pine.LNX.4.64.0710171018470.21430@bizon.gios.gov.pl>
Krzysztof Oledzki a écrit :
>
>
> On Wed, 17 Oct 2007, Eric Dumazet wrote:
>
>> Krzysztof Oledzki a écrit :
>>> Hello,
>>>
>>> Today I found in my logs:
>>>
>>> BUG: unable to handle kernel NULL pointer dereference at virtual
>>> address 000000b0
>>> printing eip:
>>> 78395f65
>>> *pde = 00000000
>>> Oops: 0000 [#1]
>>> PREEMPT SMP
>>> CPU: 0
>>> EIP: 0060:[<78395f65>] Not tainted VLI
>>> EFLAGS: 00210286 (2.6.22.9 #1)
>>> EIP is at __ip_route_output_key+0x412/0x722
>>> eax: 80000000 ebx: 00000000 ecx: 5dd2b1c3 edx: 00000000
>>> esi: 00000000 edi: d44c7e30 ebp: ec8c4980 esp: d44c7ddc
>>> ds: 007b es: 007b fs: 00d8 gs: 0033 ss: 0068
>>> Process smtpd (pid: 12479, ti=d44c6000 task=9e759510 task.ti=d44c6000)
>>> Stack: d44c7e7c d44c7e7c d44c7eb8 00000000 d44c7e7c 00000000 00000000
>>> 00000005
>>> 00000000 ffffffff 5dd2b1c3 00000000 00000000 00000000 00000000
>>> 00000000
>>> 00000000 00000000 00000000 00000000 00000000 00030000 00000000
>>> d44c7e7c
>>> Call Trace:
>>> [<78396280>] ip_route_output_flow+0xb/0x3e
>>> [<783b2b29>] ip4_datagram_connect+0x1c9/0x308
>>> [<783ba70a>] inet_dgram_connect+0x45/0x4e
>>> [<7837135e>] sys_connect+0x72/0x9c
>>> [<78371607>] sock_map_fd+0x41/0x4a
>>> [<7840d1b1>] _spin_lock+0x33/0x3e
>>> [<7840d623>] _spin_unlock+0x25/0x3b
>>> [<78371607>] sock_map_fd+0x41/0x4a
>>> [<78372792>] sys_socketcall+0x8f/0x242
>>> [<7813e99c>] trace_hardirqs_on+0x122/0x14c
>>> [<78103dc6>] sysenter_past_esp+0x8f/0x99
>>> [<78103d96>] sysenter_past_esp+0x5f/0x99
>>> =======================
>>> Code: fa e0 00 00 00 75 07 c6 44 24 56 05 eb 14 81 fa f0 00 00 00 0f
>>> 84 e1 02 00 00 84 c0 0f 84 d9 02 00 00 8b 44 24 0c 0d 00 00 00 80
>>> <f6> 86 b0 00 00 00 08 0f 44 44 24 0c 89 44 24 0c b8 01 00 00 00
>>> EIP: [<78395f65>] __ip_route_output_key+0x412/0x722 SS:ESP 0068:d44c7ddc
>>>
>>> Shortly before it there was:
>>> Oct 17 07:17:55 cougar postfix/master[3400]: warning: process
>>> /usr/lib/postfix/smtpd pid 12479 killed by signal 11
>>>
>>> Best regards,
>>>
>>>
>>> Krzysztof Olędzki
>>
>> Hello Krzysztof
>>
>> Could you give us some details about this ? kernel version at least.
>
> Yes, I was little to hurry sending this bug report. Anyway, it is
> 2.6.22.9 like mentioned in the oops: EFLAGS: 00210286 (2.6.22.9 #1)
>
>> (you could for example take a look at REPORTING-BUGS, or run
>> scripts/ver_linux)
>
> Linux cougar 2.6.22.9 #1 SMP PREEMPT Wed Oct 3 10:24:19 CEST 2007 i686
> Intel(R) Pentium(R) D CPU 3.20GHz GenuineIntel GNU/Linux
>
> Gnu C 4.1.2
> Gnu make 3.81
> binutils 2.17
> util-linux 2.12r
> mount 2.12r
> module-init-tools 3.2.2
> e2fsprogs 1.40.2
> Linux C Library > libc.2.5
> Dynamic linker (ldd) 2.5
> Procps 3.2.7
> Net-tools 1.60
> Kbd 1.12
> Sh-utils 6.9
>
Yes indeed, version was on your initial report.
It seems this kernel is unusual (VMSPLIT_2G_OPT instead of stdandard
VMSPLIT_3G), any chance you provide full .config ?
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox