aboutsummaryrefslogtreecommitdiff
path: root/net/ipv4
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/cipso_ipv4.c5
-rw-r--r--net/ipv4/devinet.c4
-rw-r--r--net/ipv4/fib_frontend.c5
-rw-r--r--net/ipv4/fib_rules.c14
-rw-r--r--net/ipv4/fib_semantics.c2
-rw-r--r--net/ipv4/fib_trie.c11
-rw-r--r--net/ipv4/igmp.c2
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c15
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c2
-rw-r--r--net/ipv4/netfilter/nf_nat_standalone.c14
-rw-r--r--net/ipv4/tcp.c13
-rw-r--r--net/ipv4/tcp_output.c6
-rw-r--r--net/ipv4/udp.c1
-rw-r--r--net/ipv4/xfrm4_mode_beet.c26
14 files changed, 78 insertions, 42 deletions
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index c976dd7e975..2ce5b693a8b 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -1933,6 +1933,11 @@ int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
&cipso_ptr[6],
secattr);
break;
+ case CIPSO_V4_TAG_RANGE:
+ ret_val = cipso_v4_parsetag_rng(doi_def,
+ &cipso_ptr[6],
+ secattr);
+ break;
}
skbuff_getattr_return:
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index e10794dc5f6..98a00d0edc7 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -502,8 +502,10 @@ static struct in_ifaddr *rtm_to_ifaddr(struct nlmsghdr *nlh)
goto errout;
ifm = nlmsg_data(nlh);
- if (ifm->ifa_prefixlen > 32 || tb[IFA_LOCAL] == NULL)
+ if (ifm->ifa_prefixlen > 32 || tb[IFA_LOCAL] == NULL) {
+ err = -EINVAL;
goto errout;
+ }
dev = __dev_get_by_index(ifm->ifa_index);
if (dev == NULL) {
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 1fba6439fc5..fc920f63452 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -493,6 +493,11 @@ static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh,
cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid;
cfg->fc_nlinfo.nlh = nlh;
+ if (cfg->fc_type > RTN_MAX) {
+ err = -EINVAL;
+ goto errout;
+ }
+
nlmsg_for_each_attr(attr, nlh, sizeof(struct rtmsg), remaining) {
switch (attr->nla_type) {
case RTA_DST:
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index b837c33e040..c660c074c76 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -171,8 +171,6 @@ static struct fib_table *fib_empty_table(void)
static struct nla_policy fib4_rule_policy[FRA_MAX+1] __read_mostly = {
FRA_GENERIC_POLICY,
- [FRA_SRC] = { .type = NLA_U32 },
- [FRA_DST] = { .type = NLA_U32 },
[FRA_FLOW] = { .type = NLA_U32 },
};
@@ -183,8 +181,7 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
int err = -EINVAL;
struct fib4_rule *rule4 = (struct fib4_rule *) rule;
- if (frh->src_len > 32 || frh->dst_len > 32 ||
- (frh->tos & ~IPTOS_TOS_MASK))
+ if (frh->tos & ~IPTOS_TOS_MASK)
goto errout;
if (rule->table == RT_TABLE_UNSPEC) {
@@ -201,10 +198,10 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
}
}
- if (tb[FRA_SRC])
+ if (frh->src_len)
rule4->src = nla_get_be32(tb[FRA_SRC]);
- if (tb[FRA_DST])
+ if (frh->dst_len)
rule4->dst = nla_get_be32(tb[FRA_DST]);
#ifdef CONFIG_NET_CLS_ROUTE
@@ -242,10 +239,10 @@ static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
return 0;
#endif
- if (tb[FRA_SRC] && (rule4->src != nla_get_be32(tb[FRA_SRC])))
+ if (frh->src_len && (rule4->src != nla_get_be32(tb[FRA_SRC])))
return 0;
- if (tb[FRA_DST] && (rule4->dst != nla_get_be32(tb[FRA_DST])))
+ if (frh->dst_len && (rule4->dst != nla_get_be32(tb[FRA_DST])))
return 0;
return 1;
@@ -309,6 +306,7 @@ static size_t fib4_rule_nlmsg_payload(struct fib_rule *rule)
static struct fib_rules_ops fib4_rules_ops = {
.family = AF_INET,
.rule_size = sizeof(struct fib4_rule),
+ .addr_size = sizeof(u32),
.action = fib4_rule_action,
.match = fib4_rule_match,
.configure = fib4_rule_configure,
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 2f1fdae6efa..3dad12ee76c 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -89,7 +89,7 @@ static const struct
{
int error;
u8 scope;
-} fib_props[RTA_MAX + 1] = {
+} fib_props[RTN_MAX + 1] = {
{
.error = 0,
.scope = RT_SCOPE_NOWHERE,
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 72b3036bbc0..214c34732e8 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1123,6 +1123,9 @@ err:
return fa_head;
}
+/*
+ * Caller must hold RTNL.
+ */
static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg)
{
struct trie *t = (struct trie *) tb->tb_data;
@@ -1527,7 +1530,6 @@ static int trie_leaf_remove(struct trie *t, t_key key)
t->revision++;
t->size--;
- preempt_disable();
tp = NODE_PARENT(n);
tnode_free((struct tnode *) n);
@@ -1537,11 +1539,13 @@ static int trie_leaf_remove(struct trie *t, t_key key)
rcu_assign_pointer(t->trie, trie_rebalance(t, tp));
} else
rcu_assign_pointer(t->trie, NULL);
- preempt_enable();
return 1;
}
+/*
+ * Caller must hold RTNL.
+ */
static int fn_trie_delete(struct fib_table *tb, struct fib_config *cfg)
{
struct trie *t = (struct trie *) tb->tb_data;
@@ -1720,6 +1724,9 @@ up:
return NULL; /* Ready. Root of trie */
}
+/*
+ * Caller must hold RTNL.
+ */
static int fn_trie_flush(struct fib_table *tb)
{
struct trie *t = (struct trie *) tb->tb_data;
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 1c6a084b5fb..8cedb2a2c9d 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -1255,9 +1255,9 @@ out:
*/
void ip_mc_rejoin_group(struct ip_mc_list *im)
{
+#ifdef CONFIG_IP_MULTICAST
struct in_device *in_dev = im->interface;
-#ifdef CONFIG_IP_MULTICAST
if (im->multiaddr == IGMP_ALL_HOSTS)
return;
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index adf25f9f70e..6bcfdf6dfcc 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -253,14 +253,17 @@ ip_nat_local_fn(unsigned int hooknum,
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
if (ct->tuplehash[dir].tuple.dst.ip !=
- ct->tuplehash[!dir].tuple.src.ip
-#ifdef CONFIG_XFRM
- || ct->tuplehash[dir].tuple.dst.u.all !=
- ct->tuplehash[!dir].tuple.src.u.all
-#endif
- )
+ ct->tuplehash[!dir].tuple.src.ip) {
if (ip_route_me_harder(pskb, RTN_UNSPEC))
ret = NF_DROP;
+ }
+#ifdef CONFIG_XFRM
+ else if (ct->tuplehash[dir].tuple.dst.u.all !=
+ ct->tuplehash[!dir].tuple.src.u.all)
+ if (ip_xfrm_me_harder(pskb))
+ ret = NF_DROP;
+#endif
+
}
return ret;
}
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index e965b333c99..42b08029e86 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -411,12 +411,10 @@ checkentry(const char *tablename,
"has invalid config pointer!\n");
return 0;
}
- clusterip_config_entry_get(cipinfo->config);
} else {
/* Case B: This is a new rule referring to an existing
* clusterip config. */
cipinfo->config = config;
- clusterip_config_entry_get(cipinfo->config);
}
} else {
/* Case C: This is a completely new clusterip config */
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c
index e4d3ef17d45..15aa3db8cb3 100644
--- a/net/ipv4/netfilter/nf_nat_standalone.c
+++ b/net/ipv4/netfilter/nf_nat_standalone.c
@@ -245,14 +245,16 @@ nf_nat_local_fn(unsigned int hooknum,
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
if (ct->tuplehash[dir].tuple.dst.u3.ip !=
- ct->tuplehash[!dir].tuple.src.u3.ip
-#ifdef CONFIG_XFRM
- || ct->tuplehash[dir].tuple.dst.u.all !=
- ct->tuplehash[!dir].tuple.src.u.all
-#endif
- )
+ ct->tuplehash[!dir].tuple.src.u3.ip) {
if (ip_route_me_harder(pskb, RTN_UNSPEC))
ret = NF_DROP;
+ }
+#ifdef CONFIG_XFRM
+ else if (ct->tuplehash[dir].tuple.dst.u.all !=
+ ct->tuplehash[!dir].tuple.src.u.all)
+ if (ip_xfrm_me_harder(pskb))
+ ret = NF_DROP;
+#endif
}
return ret;
}
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 74c4d103ebc..3834b10b511 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2458,11 +2458,18 @@ void __init tcp_init(void)
sysctl_max_syn_backlog = 128;
}
- /* Allow no more than 3/4 kernel memory (usually less) allocated to TCP */
- sysctl_tcp_mem[0] = (1536 / sizeof (struct inet_bind_hashbucket)) << order;
- sysctl_tcp_mem[1] = sysctl_tcp_mem[0] * 4 / 3;
+ /* Set the pressure threshold to be a fraction of global memory that
+ * is up to 1/2 at 256 MB, decreasing toward zero with the amount of
+ * memory, with a floor of 128 pages.
+ */
+ limit = min(nr_all_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT);
+ limit = (limit * (nr_all_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11);
+ limit = max(limit, 128UL);
+ sysctl_tcp_mem[0] = limit / 4 * 3;
+ sysctl_tcp_mem[1] = limit;
sysctl_tcp_mem[2] = sysctl_tcp_mem[0] * 2;
+ /* Set per-socket limits to no more than 1/128 the pressure threshold */
limit = ((unsigned long)sysctl_tcp_mem[1]) << (PAGE_SHIFT - 7);
max_share = min(4UL*1024*1024, limit);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index dc151139b5a..3c24881f2a6 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -943,7 +943,8 @@ static void tcp_cwnd_validate(struct sock *sk, struct tcp_sock *tp)
if (tp->packets_out > tp->snd_cwnd_used)
tp->snd_cwnd_used = tp->packets_out;
- if ((s32)(tcp_time_stamp - tp->snd_cwnd_stamp) >= inet_csk(sk)->icsk_rto)
+ if (sysctl_tcp_slow_start_after_idle &&
+ (s32)(tcp_time_stamp - tp->snd_cwnd_stamp) >= inet_csk(sk)->icsk_rto)
tcp_cwnd_application_limited(sk);
}
}
@@ -1607,6 +1608,9 @@ u32 __tcp_select_window(struct sock *sk)
*/
if (window <= free_space - mss || window > free_space)
window = (free_space/mss)*mss;
+ else if (mss == full_space &&
+ free_space > window + full_space/2)
+ window = free_space;
}
return window;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index ce6c4603431..fc620a7c1db 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1215,6 +1215,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
if (ulen < sizeof(*uh) || pskb_trim_rcsum(skb, ulen))
goto short_packet;
+ uh = skb->h.uh;
udp4_csum_init(skb, uh);
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
index 89cf59ea7bb..f68dfd8a0f5 100644
--- a/net/ipv4/xfrm4_mode_beet.c
+++ b/net/ipv4/xfrm4_mode_beet.c
@@ -42,10 +42,9 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
skb->nh.raw = skb_push(skb, x->props.header_len + hdrlen);
top_iph = skb->nh.iph;
- hdrlen = iph->ihl * 4 - optlen;
- skb->h.raw += hdrlen;
+ skb->h.raw += sizeof(*iph) - hdrlen;
- memmove(top_iph, iph, hdrlen);
+ memmove(top_iph, iph, sizeof(*iph));
if (unlikely(optlen)) {
struct ip_beet_phdr *ph;
@@ -55,6 +54,8 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
ph->padlen = 4 - (optlen & 4);
ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8;
ph->nexthdr = top_iph->protocol;
+ if (ph->padlen)
+ memset(ph + 1, IPOPT_NOP, ph->padlen);
top_iph->protocol = IPPROTO_BEETPH;
top_iph->ihl = sizeof(struct iphdr) / 4;
@@ -77,29 +78,32 @@ static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb)
protocol = iph->protocol;
if (unlikely(iph->protocol == IPPROTO_BEETPH)) {
- struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(iph + 1);
+ struct ip_beet_phdr *ph;
if (!pskb_may_pull(skb, sizeof(*ph)))
goto out;
+ ph = (struct ip_beet_phdr *)(skb->h.ipiph + 1);
- phlen = ph->hdrlen * 8;
- optlen = phlen - ph->padlen - sizeof(*ph);
+ phlen = sizeof(*ph) + ph->padlen;
+ optlen = ph->hdrlen * 8 - phlen;
if (optlen < 0 || optlen & 3 || optlen > 250)
goto out;
- if (!pskb_may_pull(skb, phlen))
+ if (!pskb_may_pull(skb, phlen + optlen))
goto out;
+ skb->len -= phlen + optlen;
ph_nexthdr = ph->nexthdr;
}
- skb_push(skb, sizeof(*iph) - phlen + optlen);
- memmove(skb->data, skb->nh.raw, sizeof(*iph));
- skb->nh.raw = skb->data;
+ skb->nh.raw = skb->data + (phlen - sizeof(*iph));
+ memmove(skb->nh.raw, iph, sizeof(*iph));
+ skb->h.raw = skb->data + (phlen + optlen);
+ skb->data = skb->h.raw;
iph = skb->nh.iph;
iph->ihl = (sizeof(*iph) + optlen) / 4;
- iph->tot_len = htons(skb->len);
+ iph->tot_len = htons(skb->len + iph->ihl * 4);
iph->daddr = x->sel.daddr.a4;
iph->saddr = x->sel.saddr.a4;
if (ph_nexthdr)