diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/bridge/br_if.c | 1 | ||||
-rw-r--r-- | net/core/filter.c | 6 | ||||
-rw-r--r-- | net/dccp/proto.c | 1 | ||||
-rw-r--r-- | net/ipv4/devinet.c | 40 | ||||
-rw-r--r-- | net/ipv4/fib_frontend.c | 2 | ||||
-rw-r--r-- | net/ipv4/fib_trie.c | 3 | ||||
-rw-r--r-- | net/ipv4/netfilter/Kconfig | 10 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_netlink.c | 25 | ||||
-rw-r--r-- | net/ipv6/addrconf.c | 12 | ||||
-rw-r--r-- | net/ipv6/datagram.c | 2 | ||||
-rw-r--r-- | net/ipv6/exthdrs.c | 22 | ||||
-rw-r--r-- | net/ipv6/ip6_flowlabel.c | 16 | ||||
-rw-r--r-- | net/ipv6/raw.c | 4 | ||||
-rw-r--r-- | net/ipv6/udp.c | 4 | ||||
-rw-r--r-- | net/netlink/af_netlink.c | 2 | ||||
-rw-r--r-- | net/sched/sch_netem.c | 2 | ||||
-rw-r--r-- | net/sunrpc/rpc_pipe.c | 26 |
17 files changed, 116 insertions, 62 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index defcf6a..975abe2 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -366,6 +366,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) spin_lock_bh(&br->lock); br_stp_recalculate_bridge_id(br); + br_features_recompute(br); if ((br->dev->flags & IFF_UP) && (dev->flags & IFF_UP) && netif_carrier_ok(dev)) br_stp_enable_port(p); diff --git a/net/core/filter.c b/net/core/filter.c index 079c2ed..2841bfc 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -116,8 +116,6 @@ int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen) A /= X; continue; case BPF_ALU|BPF_DIV|BPF_K: - if (fentry->k == 0) - return 0; A /= fentry->k; continue; case BPF_ALU|BPF_AND|BPF_X: @@ -320,6 +318,10 @@ int sk_chk_filter(struct sock_filter *filter, int flen) } } + /* check for division by zero -Kris Katterjohn 2005-10-30 */ + if (ftest->code == (BPF_ALU|BPF_DIV|BPF_K) && ftest->k == 0) + return -EINVAL; + /* check that memory operations use valid addresses. */ if (ftest->k >= BPF_MEMWORDS) { /* but it might not be a memory operation... */ diff --git a/net/dccp/proto.c b/net/dccp/proto.c index e0ace7c..8a6b2a9 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -46,6 +46,7 @@ atomic_t dccp_orphan_count = ATOMIC_INIT(0); static struct net_protocol dccp_protocol = { .handler = dccp_v4_rcv, .err_handler = dccp_v4_err, + .no_policy = 1, }; const char *dccp_packet_name(const int type) diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 4ec4b2c..04a6fe3 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -234,7 +234,10 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, int destroy) { struct in_ifaddr *promote = NULL; - struct in_ifaddr *ifa1 = *ifap; + struct in_ifaddr *ifa, *ifa1 = *ifap; + struct in_ifaddr *last_prim = in_dev->ifa_list; + struct in_ifaddr *prev_prom = NULL; + int do_promote = IN_DEV_PROMOTE_SECONDARIES(in_dev); ASSERT_RTNL(); @@ -243,18 +246,22 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, **/ if (!(ifa1->ifa_flags & IFA_F_SECONDARY)) { - struct in_ifaddr *ifa; struct in_ifaddr **ifap1 = &ifa1->ifa_next; while ((ifa = *ifap1) != NULL) { + if (!(ifa->ifa_flags & IFA_F_SECONDARY) && + ifa1->ifa_scope <= ifa->ifa_scope) + last_prim = ifa; + if (!(ifa->ifa_flags & IFA_F_SECONDARY) || ifa1->ifa_mask != ifa->ifa_mask || !inet_ifa_match(ifa1->ifa_address, ifa)) { ifap1 = &ifa->ifa_next; + prev_prom = ifa; continue; } - if (!IN_DEV_PROMOTE_SECONDARIES(in_dev)) { + if (!do_promote) { *ifap1 = ifa->ifa_next; rtmsg_ifa(RTM_DELADDR, ifa); @@ -283,18 +290,31 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, */ rtmsg_ifa(RTM_DELADDR, ifa1); notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1); - if (destroy) { - inet_free_ifa(ifa1); - if (!in_dev->ifa_list) - inetdev_destroy(in_dev); - } + if (promote) { + + if (prev_prom) { + prev_prom->ifa_next = promote->ifa_next; + promote->ifa_next = last_prim->ifa_next; + last_prim->ifa_next = promote; + } - if (promote && IN_DEV_PROMOTE_SECONDARIES(in_dev)) { - /* not sure if we should send a delete notify first? */ promote->ifa_flags &= ~IFA_F_SECONDARY; rtmsg_ifa(RTM_NEWADDR, promote); notifier_call_chain(&inetaddr_chain, NETDEV_UP, promote); + for (ifa = promote->ifa_next; ifa; ifa = ifa->ifa_next) { + if (ifa1->ifa_mask != ifa->ifa_mask || + !inet_ifa_match(ifa1->ifa_address, ifa)) + continue; + fib_add_ifaddr(ifa); + } + + } + if (destroy) { + inet_free_ifa(ifa1); + + if (!in_dev->ifa_list) + inetdev_destroy(in_dev); } } diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 2267c1f..882f88f 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -407,7 +407,7 @@ static void fib_magic(int cmd, int type, u32 dst, int dst_len, struct in_ifaddr tb->tb_delete(tb, &req.rtm, &rta, &req.nlh, NULL); } -static void fib_add_ifaddr(struct in_ifaddr *ifa) +void fib_add_ifaddr(struct in_ifaddr *ifa) { struct in_device *in_dev = ifa->ifa_dev; struct net_device *dev = in_dev->dev; diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 66247f3..705e3ce 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -2378,6 +2378,7 @@ static unsigned fib_flag_trans(int type, u32 mask, const struct fib_info *fi) */ static int fib_route_seq_show(struct seq_file *seq, void *v) { + const struct fib_trie_iter *iter = seq->private; struct leaf *l = v; int i; char bf[128]; @@ -2389,6 +2390,8 @@ static int fib_route_seq_show(struct seq_file *seq, void *v) return 0; } + if (iter->trie == trie_local) + return 0; if (IS_TNODE(l)) return 0; diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 9d3c8b5..0bc0052 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -440,7 +440,7 @@ config IP_NF_MATCH_COMMENT config IP_NF_MATCH_CONNMARK tristate 'Connection mark match support' depends on IP_NF_IPTABLES - depends on IP_NF_CONNTRACK_MARK || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) + depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) help This option adds a `connmark' match, which allows you to match the connection mark value previously set for the session by `CONNMARK'. @@ -452,7 +452,7 @@ config IP_NF_MATCH_CONNMARK config IP_NF_MATCH_CONNBYTES tristate 'Connection byte/packet counter match support' depends on IP_NF_IPTABLES - depends on IP_NF_CT_ACCT || (NF_CT_ACCT && NF_CONNTRACK_IPV4) + depends on (IP_NF_CONNTRACK && IP_NF_CT_ACCT) || (NF_CT_ACCT && NF_CONNTRACK_IPV4) help This option adds a `connbytes' match, which allows you to match the number of bytes and/or packets for each direction within a connection. @@ -767,7 +767,7 @@ config IP_NF_TARGET_TTL config IP_NF_TARGET_CONNMARK tristate 'CONNMARK target support' depends on IP_NF_MANGLE - depends on IP_NF_CONNTRACK_MARK || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) + depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) help This option adds a `CONNMARK' target, which allows one to manipulate the connection mark value. Similar to the MARK target, but @@ -779,8 +779,8 @@ config IP_NF_TARGET_CONNMARK config IP_NF_TARGET_CLUSTERIP tristate "CLUSTERIP target support (EXPERIMENTAL)" - depends on IP_NF_IPTABLES && EXPERIMENTAL - depends on IP_NF_CONNTRACK_MARK || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) + depends on IP_NF_MANGLE && EXPERIMENTAL + depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) help The CLUSTERIP target allows you to build load-balancing clusters of network servers without having a dedicated load-balancing diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index de9f446..3fce91b 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -27,6 +27,7 @@ #include <linux/errno.h> #include <linux/netlink.h> #include <linux/spinlock.h> +#include <linux/interrupt.h> #include <linux/notifier.h> #include <linux/netfilter.h> @@ -59,11 +60,13 @@ ctnetlink_dump_tuples_proto(struct sk_buff *skb, NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum); + /* If no protocol helper is found, this function will return the + * generic protocol helper, so proto won't *ever* be NULL */ proto = ip_conntrack_proto_find_get(tuple->dst.protonum); - if (likely(proto && proto->tuple_to_nfattr)) { + if (likely(proto->tuple_to_nfattr)) ret = proto->tuple_to_nfattr(skb, tuple); - ip_conntrack_proto_put(proto); - } + + ip_conntrack_proto_put(proto); return ret; @@ -128,9 +131,11 @@ ctnetlink_dump_protoinfo(struct sk_buff *skb, const struct ip_conntrack *ct) struct nfattr *nest_proto; int ret; - - if (!proto || !proto->to_nfattr) + + if (!proto->to_nfattr) { + ip_conntrack_proto_put(proto); return 0; + } nest_proto = NFA_NEST(skb, CTA_PROTOINFO); @@ -527,10 +532,10 @@ ctnetlink_parse_tuple_proto(struct nfattr *attr, proto = ip_conntrack_proto_find_get(tuple->dst.protonum); - if (likely(proto && proto->nfattr_to_tuple)) { + if (likely(proto->nfattr_to_tuple)) ret = proto->nfattr_to_tuple(tb, tuple); - ip_conntrack_proto_put(proto); - } + + ip_conntrack_proto_put(proto); return ret; } @@ -596,8 +601,6 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr, return -EINVAL; npt = ip_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum); - if (!npt) - return 0; if (!npt->nfattr_to_range) { ip_nat_proto_put(npt); @@ -957,8 +960,6 @@ ctnetlink_change_protoinfo(struct ip_conntrack *ct, struct nfattr *cda[]) nfattr_parse_nested(tb, CTA_PROTOINFO_MAX, attr); proto = ip_conntrack_proto_find_get(npt); - if (!proto) - return -EINVAL; if (proto->from_nfattr) err = proto->from_nfattr(tb, ct); diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 56a09a4..76ff9f4 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -985,6 +985,8 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, } /* Rule 4: Prefer home address -- not implemented yet */ + if (hiscore.rule < 4) + hiscore.rule++; /* Rule 5: Prefer outgoing interface */ if (hiscore.rule < 5) { @@ -2627,7 +2629,7 @@ static void addrconf_verify(unsigned long foo) for (i=0; i < IN6_ADDR_HSIZE; i++) { restart: - write_lock(&addrconf_hash_lock); + read_lock(&addrconf_hash_lock); for (ifp=inet6_addr_lst[i]; ifp; ifp=ifp->lst_next) { unsigned long age; #ifdef CONFIG_IPV6_PRIVACY @@ -2649,7 +2651,7 @@ restart: if (age >= ifp->valid_lft) { spin_unlock(&ifp->lock); in6_ifa_hold(ifp); - write_unlock(&addrconf_hash_lock); + read_unlock(&addrconf_hash_lock); ipv6_del_addr(ifp); goto restart; } else if (age >= ifp->prefered_lft) { @@ -2668,7 +2670,7 @@ restart: if (deprecate) { in6_ifa_hold(ifp); - write_unlock(&addrconf_hash_lock); + read_unlock(&addrconf_hash_lock); ipv6_ifa_notify(0, ifp); in6_ifa_put(ifp); @@ -2686,7 +2688,7 @@ restart: in6_ifa_hold(ifp); in6_ifa_hold(ifpub); spin_unlock(&ifp->lock); - write_unlock(&addrconf_hash_lock); + read_unlock(&addrconf_hash_lock); ipv6_create_tempaddr(ifpub, ifp); in6_ifa_put(ifpub); in6_ifa_put(ifp); @@ -2703,7 +2705,7 @@ restart: spin_unlock(&ifp->lock); } } - write_unlock(&addrconf_hash_lock); + read_unlock(&addrconf_hash_lock); } addr_chk_timer.expires = time_before(next, jiffies + HZ) ? jiffies + HZ : next; diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index cc51840..c4a3a99 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -437,7 +437,7 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) break; case IPPROTO_AH: nexthdr = ptr[0]; - len = (ptr[1] + 1) << 2; + len = (ptr[1] + 2) << 2; break; default: nexthdr = ptr[0]; diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 9225495..be6faf3 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -628,6 +628,7 @@ ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, if (!tot_len) return NULL; + tot_len += sizeof(*opt2); opt2 = sock_kmalloc(sk, tot_len, GFP_ATOMIC); if (!opt2) return ERR_PTR(-ENOBUFS); @@ -668,7 +669,26 @@ ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, return opt2; out: - sock_kfree_s(sk, p, tot_len); + sock_kfree_s(sk, opt2, opt2->tot_len); return ERR_PTR(err); } +struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space, + struct ipv6_txoptions *opt) +{ + /* + * ignore the dest before srcrt unless srcrt is being included. + * --yoshfuji + */ + if (opt && opt->dst0opt && !opt->srcrt) { + if (opt_space != opt) { + memcpy(opt_space, opt, sizeof(*opt_space)); + opt = opt_space; + } + opt->opt_nflen -= ipv6_optlen(opt->dst0opt); + opt->dst0opt = NULL; + } + + return opt; +} + diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index bbbe80c..1cf0276 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c @@ -225,20 +225,16 @@ struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions * opt_space, struct ip6_flowlabel * fl, struct ipv6_txoptions * fopt) { - struct ipv6_txoptions * fl_opt = fl ? fl->opt : NULL; - - if (fopt == NULL || fopt->opt_flen == 0) { - if (!fl_opt || !fl_opt->dst0opt || fl_opt->srcrt) - return fl_opt; - } - + struct ipv6_txoptions * fl_opt = fl->opt; + + if (fopt == NULL || fopt->opt_flen == 0) + return fl_opt; + if (fl_opt != NULL) { opt_space->hopopt = fl_opt->hopopt; - opt_space->dst0opt = fl_opt->srcrt ? fl_opt->dst0opt : NULL; + opt_space->dst0opt = fl_opt->dst0opt; opt_space->srcrt = fl_opt->srcrt; opt_space->opt_nflen = fl_opt->opt_nflen; - if (fl_opt->dst0opt && !fl_opt->srcrt) - opt_space->opt_nflen -= ipv6_optlen(fl_opt->dst0opt); } else { if (fopt->opt_nflen == 0) return fopt; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 8e9628f..a66900c 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -748,7 +748,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, } if (opt == NULL) opt = np->opt; - opt = fl6_merge_options(&opt_space, flowlabel, opt); + if (flowlabel) + opt = fl6_merge_options(&opt_space, flowlabel, opt); + opt = ipv6_fixup_options(&opt_space, opt); fl.proto = proto; rawv6_probe_proto_opt(&fl, msg); diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index e671153..5cc8731 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -771,7 +771,9 @@ do_udp_sendmsg: } if (opt == NULL) opt = np->opt; - opt = fl6_merge_options(&opt_space, flowlabel, opt); + if (flowlabel) + opt = fl6_merge_options(&opt_space, flowlabel, opt); + opt = ipv6_fixup_options(&opt_space, opt); fl->proto = IPPROTO_UDP; ipv6_addr_copy(&fl->fl6_dst, daddr); diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 8c38ee6..96020d7 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -476,7 +476,7 @@ static int netlink_autobind(struct socket *sock) struct hlist_head *head; struct sock *osk; struct hlist_node *node; - s32 pid = current->pid; + s32 pid = current->tgid; int err; static s32 rover = -4097; diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index cdc8d28..82fb07a 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -464,7 +464,7 @@ static int tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch) const struct netem_skb_cb *cb = (const struct netem_skb_cb *)skb->cb; - if (PSCHED_TLESS(cb->time_to_send, ncb->time_to_send)) + if (!PSCHED_TLESS(ncb->time_to_send, cb->time_to_send)) break; } diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 81e00a6..e3b242d 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -39,23 +39,27 @@ static kmem_cache_t *rpc_inode_cachep __read_mostly; #define RPC_UPCALL_TIMEOUT (30*HZ) static void -__rpc_purge_upcall(struct inode *inode, int err) +__rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, int err) { - struct rpc_inode *rpci = RPC_I(inode); struct rpc_pipe_msg *msg; + void (*destroy_msg)(struct rpc_pipe_msg *); - while (!list_empty(&rpci->pipe)) { - msg = list_entry(rpci->pipe.next, struct rpc_pipe_msg, list); + destroy_msg = rpci->ops->destroy_msg; + while (!list_empty(head)) { + msg = list_entry(head->next, struct rpc_pipe_msg, list); list_del_init(&msg->list); msg->errno = err; - rpci->ops->destroy_msg(msg); - } - while (!list_empty(&rpci->in_upcall)) { - msg = list_entry(rpci->pipe.next, struct rpc_pipe_msg, list); - list_del_init(&msg->list); - msg->errno = err; - rpci->ops->destroy_msg(msg); + destroy_msg(msg); } +} + +static void +__rpc_purge_upcall(struct inode *inode, int err) +{ + struct rpc_inode *rpci = RPC_I(inode); + + __rpc_purge_list(rpci, &rpci->pipe, err); + __rpc_purge_list(rpci, &rpci->in_upcall, err); rpci->pipelen = 0; wake_up(&rpci->waitq); } |