diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/cipso_ipv4.c | 5 | ||||
-rw-r--r-- | net/ipv4/fib_frontend.c | 13 | ||||
-rw-r--r-- | net/ipv4/fib_rules.c | 14 | ||||
-rw-r--r-- | net/ipv4/fib_semantics.c | 2 | ||||
-rw-r--r-- | net/ipv4/fib_trie.c | 11 | ||||
-rw-r--r-- | net/ipv4/igmp.c | 2 | ||||
-rw-r--r-- | net/ipv4/netfilter/arp_tables.c | 10 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_standalone.c | 15 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_CLUSTERIP.c | 2 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_ULOG.c | 7 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_standalone.c | 14 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 13 | ||||
-rw-r--r-- | net/ipv4/tcp_cong.c | 23 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 6 | ||||
-rw-r--r-- | net/ipv4/xfrm4_mode_beet.c | 28 |
15 files changed, 102 insertions, 63 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/fib_frontend.c b/net/ipv4/fib_frontend.c index 1fba6439fc5..cac06c43f00 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: @@ -771,6 +776,8 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb ) .nl_u = { .ip4_u = { .daddr = frn->fl_addr, .tos = frn->fl_tos, .scope = frn->fl_scope } } }; + + frn->err = -ENOENT; if (tb) { local_bh_disable(); @@ -782,6 +789,7 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb ) frn->nh_sel = res.nh_sel; frn->type = res.type; frn->scope = res.scope; + fib_res_put(&res); } local_bh_enable(); } @@ -796,6 +804,9 @@ static void nl_fib_input(struct sock *sk, int len) struct fib_table *tb; skb = skb_dequeue(&sk->sk_receive_queue); + if (skb == NULL) + return; + nlh = (struct nlmsghdr *)skb->data; if (skb->len < NLMSG_SPACE(0) || skb->len < nlh->nlmsg_len || nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*frn))) { @@ -808,7 +819,7 @@ static void nl_fib_input(struct sock *sk, int len) nl_fib_lookup(frn, tb); - pid = nlh->nlmsg_pid; /*pid of sending process */ + pid = NETLINK_CB(skb).pid; /* pid of sending process */ NETLINK_CB(skb).pid = 0; /* from kernel */ NETLINK_CB(skb).dst_group = 0; /* unicast */ netlink_unicast(sk, skb, pid, MSG_DONTWAIT); 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/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 5170f5c75f9..57b0221f9e2 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -166,13 +166,9 @@ static inline int arp_packet_match(const struct arphdr *arphdr, return 0; } - for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) { - unsigned long odev; - memcpy(&odev, outdev + i*sizeof(unsigned long), - sizeof(unsigned long)); - ret |= (odev - ^ ((const unsigned long *)arpinfo->outiface)[i]) - & ((const unsigned long *)arpinfo->outiface_mask)[i]; + for (i = 0, ret = 0; i < IFNAMSIZ; i++) { + ret |= (outdev[i] ^ arpinfo->outiface[i]) + & arpinfo->outiface_mask[i]; } if (FWINV(ret != 0, ARPT_INV_VIA_OUT)) { 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/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index a26404dbe21..9acc018766f 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c @@ -61,6 +61,7 @@ #include <linux/netfilter_ipv4/ipt_ULOG.h> #include <net/sock.h> #include <linux/bitops.h> +#include <asm/unaligned.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); @@ -236,9 +237,9 @@ static void ipt_ulog_packet(unsigned int hooknum, /* copy hook, prefix, timestamp, payload, etc. */ pm->data_len = copy_len; - pm->timestamp_sec = skb->tstamp.off_sec; - pm->timestamp_usec = skb->tstamp.off_usec; - pm->mark = skb->mark; + put_unaligned(skb->tstamp.off_sec, &pm->timestamp_sec); + put_unaligned(skb->tstamp.off_usec, &pm->timestamp_usec); + put_unaligned(skb->mark, &pm->mark); pm->hook = hooknum; if (prefix != NULL) strncpy(pm->prefix, prefix, sizeof(pm->prefix)); 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_cong.c b/net/ipv4/tcp_cong.c index 5c8caf4a124..34ae3f13483 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c @@ -77,18 +77,19 @@ void tcp_init_congestion_control(struct sock *sk) struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_congestion_ops *ca; - if (icsk->icsk_ca_ops != &tcp_init_congestion_ops) - return; + /* if no choice made yet assign the current value set as default */ + if (icsk->icsk_ca_ops == &tcp_init_congestion_ops) { + rcu_read_lock(); + list_for_each_entry_rcu(ca, &tcp_cong_list, list) { + if (try_module_get(ca->owner)) { + icsk->icsk_ca_ops = ca; + break; + } - rcu_read_lock(); - list_for_each_entry_rcu(ca, &tcp_cong_list, list) { - if (try_module_get(ca->owner)) { - icsk->icsk_ca_ops = ca; - break; + /* fallback to next available */ } - + rcu_read_unlock(); } - rcu_read_unlock(); if (icsk->icsk_ca_ops->init) icsk->icsk_ca_ops->init(sk); @@ -236,6 +237,7 @@ int tcp_set_congestion_control(struct sock *sk, const char *name) rcu_read_lock(); ca = tcp_ca_find(name); + /* no change asking for existing value */ if (ca == icsk->icsk_ca_ops) goto out; @@ -261,7 +263,8 @@ int tcp_set_congestion_control(struct sock *sk, const char *name) else { tcp_cleanup_congestion_control(sk); icsk->icsk_ca_ops = ca; - if (icsk->icsk_ca_ops->init) + + if (sk->sk_state != TCP_CLOSE && icsk->icsk_ca_ops->init) icsk->icsk_ca_ops->init(sk); } out: 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/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c index 89cf59ea7bb..d419e15d980 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; @@ -53,8 +52,10 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb) ph = (struct ip_beet_phdr *)skb->h.raw; ph->padlen = 4 - (optlen & 4); - ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8; + ph->hdrlen = optlen / 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 + (IPV4_BEET_PHMAXLEN - 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) |