diff --git a/[refs] b/[refs] index cab9fd77cd16..70ba77179031 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 7cbca67c073263c179f605bdbbdc565ab29d801d +refs/heads/master: 835d3ac5e8cbe1fec2c02c7fc662586b30b1f5a8 diff --git a/trunk/drivers/net/wireless/libertas/cmd.c b/trunk/drivers/net/wireless/libertas/cmd.c index 445c6dc09786..84dde09bfbc3 100644 --- a/trunk/drivers/net/wireless/libertas/cmd.c +++ b/trunk/drivers/net/wireless/libertas/cmd.c @@ -1200,24 +1200,6 @@ static void lbs_submit_command(struct lbs_private *priv, lbs_deb_leave(LBS_DEB_HOST); } -static int lbs_cmd_mac_control(struct lbs_private *priv, - struct cmd_ds_command *cmd) -{ - struct cmd_ds_mac_control *mac = &cmd->params.macctrl; - - lbs_deb_enter(LBS_DEB_CMD); - - cmd->command = cpu_to_le16(CMD_MAC_CONTROL); - cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_control) + S_DS_GEN); - mac->action = cpu_to_le16(priv->currentpacketfilter); - - lbs_deb_cmd("MAC_CONTROL: action 0x%04x, size %d\n", - le16_to_cpu(mac->action), le16_to_cpu(cmd->size)); - - lbs_deb_leave(LBS_DEB_CMD); - return 0; -} - /** * This function inserts command node to cmdfreeq * after cleans it. Requires priv->driver_lock held. @@ -1307,12 +1289,15 @@ int lbs_set_radio_control(struct lbs_private *priv) int lbs_set_mac_packet_filter(struct lbs_private *priv) { int ret = 0; + struct cmd_ds_mac_control cmd; lbs_deb_enter(LBS_DEB_CMD); - /* Send MAC control command to station */ - ret = lbs_prepare_and_send_command(priv, - CMD_MAC_CONTROL, 0, 0, 0, NULL); + cmd.hdr.size = cpu_to_le16(sizeof(cmd)); + cmd.action = cpu_to_le16(priv->currentpacketfilter); + cmd.reserved = 0; + + ret = lbs_cmd_with_response(priv, CMD_MAC_CONTROL, &cmd); lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; @@ -1382,10 +1367,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, ret = lbs_cmd_802_11_ps_mode(priv, cmdptr, cmd_action); break; - case CMD_MAC_CONTROL: - ret = lbs_cmd_mac_control(priv, cmdptr); - break; - case CMD_802_11_ASSOCIATE: case CMD_802_11_REASSOCIATE: ret = lbs_cmd_80211_associate(priv, cmdptr, pdata_buf); diff --git a/trunk/drivers/net/wireless/libertas/cmdresp.c b/trunk/drivers/net/wireless/libertas/cmdresp.c index 63aa884b18f2..5534a7b859da 100644 --- a/trunk/drivers/net/wireless/libertas/cmdresp.c +++ b/trunk/drivers/net/wireless/libertas/cmdresp.c @@ -394,7 +394,6 @@ static inline int handle_cmd_response(struct lbs_private *priv, break; case CMD_RET(CMD_MAC_MULTICAST_ADR): - case CMD_RET(CMD_MAC_CONTROL): case CMD_RET(CMD_802_11_RESET): case CMD_RET(CMD_802_11_AUTHENTICATE): case CMD_RET(CMD_802_11_BEACON_STOP): diff --git a/trunk/drivers/net/wireless/libertas/hostcmd.h b/trunk/drivers/net/wireless/libertas/hostcmd.h index 56bc1aa2bb00..b5361b3393d9 100644 --- a/trunk/drivers/net/wireless/libertas/hostcmd.h +++ b/trunk/drivers/net/wireless/libertas/hostcmd.h @@ -211,8 +211,9 @@ struct cmd_ds_802_11_get_log { }; struct cmd_ds_mac_control { + struct cmd_header hdr; __le16 action; - __le16 reserved; + u16 reserved; }; struct cmd_ds_mac_multicast_adr { @@ -695,7 +696,6 @@ struct cmd_ds_command { /* command Body */ union { struct cmd_ds_802_11_ps_mode psmode; - struct cmd_ds_mac_control macctrl; struct cmd_ds_802_11_associate associate; struct cmd_ds_802_11_deauthenticate deauth; struct cmd_ds_802_11_ad_hoc_start ads; diff --git a/trunk/include/linux/in6.h b/trunk/include/linux/in6.h index f674000c6c99..2a61c82af115 100644 --- a/trunk/include/linux/in6.h +++ b/trunk/include/linux/in6.h @@ -249,15 +249,4 @@ struct in6_flowlabel_req * IP6T_SO_GET_REVISION_TARGET 69 */ -/* RFC5014: Source address selection */ -#define IPV6_ADDR_PREFERENCES 72 - -#define IPV6_PREFER_SRC_TMP 0x0001 -#define IPV6_PREFER_SRC_PUBLIC 0x0002 -#define IPV6_PREFER_SRC_PUBTMP_DEFAULT 0x0100 -#define IPV6_PREFER_SRC_COA 0x0004 -#define IPV6_PREFER_SRC_HOME 0x0400 -#define IPV6_PREFER_SRC_CGA 0x0008 -#define IPV6_PREFER_SRC_NONCGA 0x0800 - #endif diff --git a/trunk/include/linux/ipv6.h b/trunk/include/linux/ipv6.h index c9ba0da16ce9..4aaefc349a4b 100644 --- a/trunk/include/linux/ipv6.h +++ b/trunk/include/linux/ipv6.h @@ -274,29 +274,8 @@ struct ipv6_pinfo { __be32 flow_label; __u32 frag_size; - - /* - * Packed in 16bits. - * Omit one shift by by putting the signed field at MSB. - */ -#if defined(__BIG_ENDIAN_BITFIELD) - __s16 hop_limit:9; - __u16 __unused_1:7; -#else - __u16 __unused_1:7; - __s16 hop_limit:9; -#endif - -#if defined(__BIG_ENDIAN_BITFIELD) - /* Packed in 16bits. */ - __s16 mcast_hops:9; - __u16 __unused_2:6, - mc_loop:1; -#else - __u16 mc_loop:1, - __unused_2:6; - __s16 mcast_hops:9; -#endif + __s16 hop_limit; + __s16 mcast_hops; int mcast_oif; /* pktoption flags */ @@ -319,14 +298,11 @@ struct ipv6_pinfo { } rxopt; /* sockopt flags */ - __u8 recverr:1, + __u8 mc_loop:1, + recverr:1, sndflow:1, pmtudisc:2, - ipv6only:1, - srcprefs:3; /* 001: prefer temporary address - * 010: prefer public address - * 100: prefer care-of address - */ + ipv6only:1; __u8 tclass; __u32 dst_cookie; @@ -339,8 +315,9 @@ struct ipv6_pinfo { struct sk_buff *pktoptions; struct { struct ipv6_txoptions *opt; - u8 hop_limit; - u8 tclass; + struct rt6_info *rt; + int hop_limit; + int tclass; } cork; }; diff --git a/trunk/include/net/addrconf.h b/trunk/include/net/addrconf.h index c9276c72764d..232da20e7171 100644 --- a/trunk/include/net/addrconf.h +++ b/trunk/include/net/addrconf.h @@ -78,7 +78,6 @@ extern struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, extern int ipv6_dev_get_saddr(struct net_device *dev, struct in6_addr *daddr, - unsigned int srcprefs, struct in6_addr *saddr); extern int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, @@ -124,6 +123,8 @@ extern int ipv6_is_mld(struct sk_buff *skb, int nexthdr); extern void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len); +extern int ipv6_get_hoplimit(struct net_device *dev); + /* * anycast prototypes (anycast.c) */ diff --git a/trunk/include/net/inet_sock.h b/trunk/include/net/inet_sock.h index a42cd63d241a..b6db16d2766a 100644 --- a/trunk/include/net/inet_sock.h +++ b/trunk/include/net/inet_sock.h @@ -136,7 +136,7 @@ struct inet_sock { unsigned int flags; unsigned int fragsize; struct ip_options *opt; - struct dst_entry *dst; + struct rtable *rt; int length; /* Total length of all frames */ __be32 addr; struct flowi fl; diff --git a/trunk/include/net/ip.h b/trunk/include/net/ip.h index 6d7bcd5e62d4..9f50d4f1f157 100644 --- a/trunk/include/net/ip.h +++ b/trunk/include/net/ip.h @@ -347,11 +347,10 @@ extern int ip_forward(struct sk_buff *skb); extern void ip_options_build(struct sk_buff *skb, struct ip_options *opt, __be32 daddr, struct rtable *rt, int is_frag); extern int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb); extern void ip_options_fragment(struct sk_buff *skb); -extern int ip_options_compile(struct net *net, - struct ip_options *opt, struct sk_buff *skb); -extern int ip_options_get(struct net *net, struct ip_options **optp, +extern int ip_options_compile(struct ip_options *opt, struct sk_buff *skb); +extern int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen); -extern int ip_options_get_from_user(struct net *net, struct ip_options **optp, +extern int ip_options_get_from_user(struct ip_options **optp, unsigned char __user *data, int optlen); extern void ip_options_undo(struct ip_options * opt); extern void ip_forward_options(struct sk_buff *skb); @@ -362,8 +361,7 @@ extern int ip_options_rcv_srr(struct sk_buff *skb); */ extern void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb); -extern int ip_cmsg_send(struct net *net, - struct msghdr *msg, struct ipcm_cookie *ipc); +extern int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc); extern int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen); extern int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen); extern int compat_ip_setsockopt(struct sock *sk, int level, diff --git a/trunk/include/net/ip6_route.h b/trunk/include/net/ip6_route.h index 3ae6799c2b14..0e2895c8b270 100644 --- a/trunk/include/net/ip6_route.h +++ b/trunk/include/net/ip6_route.h @@ -30,12 +30,9 @@ struct route_info { #include #include -#define RT6_LOOKUP_F_IFACE 0x00000001 -#define RT6_LOOKUP_F_REACHABLE 0x00000002 -#define RT6_LOOKUP_F_HAS_SADDR 0x00000004 -#define RT6_LOOKUP_F_SRCPREF_TMP 0x00000008 -#define RT6_LOOKUP_F_SRCPREF_PUBLIC 0x00000010 -#define RT6_LOOKUP_F_SRCPREF_COA 0x00000020 +#define RT6_LOOKUP_F_IFACE 0x1 +#define RT6_LOOKUP_F_REACHABLE 0x2 +#define RT6_LOOKUP_F_HAS_SADDR 0x4 extern struct rt6_info *ip6_null_entry; @@ -91,8 +88,6 @@ extern struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, const struct in6_addr *addr, int anycast); -extern int ip6_dst_hoplimit(struct dst_entry *dst); - /* * support functions for ND * diff --git a/trunk/include/net/protocol.h b/trunk/include/net/protocol.h index 8d024d7cb741..ad8c584233a6 100644 --- a/trunk/include/net/protocol.h +++ b/trunk/include/net/protocol.h @@ -39,8 +39,7 @@ struct net_protocol { int (*gso_send_check)(struct sk_buff *skb); struct sk_buff *(*gso_segment)(struct sk_buff *skb, int features); - unsigned int no_policy:1, - netns_ok:1; + int no_policy; }; #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) diff --git a/trunk/include/net/xfrm.h b/trunk/include/net/xfrm.h index bed7d43932f6..c435620dbb37 100644 --- a/trunk/include/net/xfrm.h +++ b/trunk/include/net/xfrm.h @@ -1045,23 +1045,6 @@ xfrm_address_t *xfrm_flowi_saddr(struct flowi *fl, unsigned short family) return NULL; } -static __inline__ -void xfrm_flowi_addr_get(struct flowi *fl, - xfrm_address_t *saddr, xfrm_address_t *daddr, - unsigned short family) -{ - switch(family) { - case AF_INET: - memcpy(&saddr->a4, &fl->fl4_src, sizeof(saddr->a4)); - memcpy(&daddr->a4, &fl->fl4_dst, sizeof(daddr->a4)); - break; - case AF_INET6: - ipv6_addr_copy((struct in6_addr *)&saddr->a6, &fl->fl6_src); - ipv6_addr_copy((struct in6_addr *)&daddr->a6, &fl->fl6_dst); - break; - } -} - static __inline__ int __xfrm4_state_addr_check(struct xfrm_state *x, xfrm_address_t *daddr, xfrm_address_t *saddr) diff --git a/trunk/net/core/dev.c b/trunk/net/core/dev.c index aebd08606040..f973e38b81af 100644 --- a/trunk/net/core/dev.c +++ b/trunk/net/core/dev.c @@ -2615,7 +2615,7 @@ static int ptype_seq_show(struct seq_file *seq, void *v) if (v == SEQ_START_TOKEN) seq_puts(seq, "Type Device Function\n"); - else if (pt->dev == NULL || pt->dev->nd_net == seq_file_net(seq)) { + else { if (pt->type == htons(ETH_P_ALL)) seq_puts(seq, "ALL "); else @@ -2639,8 +2639,7 @@ static const struct seq_operations ptype_seq_ops = { static int ptype_seq_open(struct inode *inode, struct file *file) { - return seq_open_net(inode, file, &ptype_seq_ops, - sizeof(struct seq_net_private)); + return seq_open(file, &ptype_seq_ops); } static const struct file_operations ptype_seq_fops = { @@ -2648,7 +2647,7 @@ static const struct file_operations ptype_seq_fops = { .open = ptype_seq_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release_net, + .release = seq_release, }; diff --git a/trunk/net/ipv4/af_inet.c b/trunk/net/ipv4/af_inet.c index 06cfb0bed631..44f5ce1fbfa4 100644 --- a/trunk/net/ipv4/af_inet.c +++ b/trunk/net/ipv4/af_inet.c @@ -243,23 +243,6 @@ void build_ehash_secret(void) } EXPORT_SYMBOL(build_ehash_secret); -static inline int inet_netns_ok(struct net *net, int protocol) -{ - int hash; - struct net_protocol *ipprot; - - if (net == &init_net) - return 1; - - hash = protocol & (MAX_INET_PROTOS - 1); - ipprot = rcu_dereference(inet_protos[hash]); - - if (ipprot == NULL) - /* raw IP is OK */ - return 1; - return ipprot->netns_ok; -} - /* * Create an inet socket. */ @@ -276,6 +259,9 @@ static int inet_create(struct net *net, struct socket *sock, int protocol) int try_loading_module = 0; int err; + if (net != &init_net) + return -EAFNOSUPPORT; + if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM && !inet_ehash_secret) @@ -334,10 +320,6 @@ static int inet_create(struct net *net, struct socket *sock, int protocol) if (answer->capability > 0 && !capable(answer->capability)) goto out_rcu_unlock; - err = -EAFNOSUPPORT; - if (!inet_netns_ok(net, protocol)) - goto out_rcu_unlock; - sock->ops = answer->ops; answer_prot = answer->prot; answer_no_check = answer->no_check; @@ -464,7 +446,7 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if (addr_len < sizeof(struct sockaddr_in)) goto out; - chk_addr_ret = inet_addr_type(sk->sk_net, addr->sin_addr.s_addr); + chk_addr_ret = inet_addr_type(&init_net, addr->sin_addr.s_addr); /* Not specified by any standard per-se, however it breaks too * many applications when removed. It is unfortunate since @@ -1132,7 +1114,7 @@ int inet_sk_rebuild_header(struct sock *sk) }; security_sk_classify_flow(sk, &fl); - err = ip_route_output_flow(sk->sk_net, &rt, &fl, sk, 0); + err = ip_route_output_flow(&init_net, &rt, &fl, sk, 0); } if (!err) sk_setup_caps(sk, &rt->u.dst); @@ -1302,20 +1284,17 @@ static struct net_protocol tcp_protocol = { .gso_send_check = tcp_v4_gso_send_check, .gso_segment = tcp_tso_segment, .no_policy = 1, - .netns_ok = 1, }; static struct net_protocol udp_protocol = { .handler = udp_rcv, .err_handler = udp_err, .no_policy = 1, - .netns_ok = 1, }; static struct net_protocol icmp_protocol = { .handler = icmp_rcv, .no_policy = 1, - .netns_ok = 1, }; static int __init init_ipv4_mibs(void) diff --git a/trunk/net/ipv4/arp.c b/trunk/net/ipv4/arp.c index 832473e30b36..efe01df8fc0e 100644 --- a/trunk/net/ipv4/arp.c +++ b/trunk/net/ipv4/arp.c @@ -242,7 +242,7 @@ static int arp_constructor(struct neighbour *neigh) return -EINVAL; } - neigh->type = inet_addr_type(dev->nd_net, addr); + neigh->type = inet_addr_type(&init_net, addr); parms = in_dev->arp_parms; __neigh_parms_put(neigh->parms); @@ -341,14 +341,14 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb) switch (IN_DEV_ARP_ANNOUNCE(in_dev)) { default: case 0: /* By default announce any local IP */ - if (skb && inet_addr_type(dev->nd_net, ip_hdr(skb)->saddr) == RTN_LOCAL) + if (skb && inet_addr_type(&init_net, ip_hdr(skb)->saddr) == RTN_LOCAL) saddr = ip_hdr(skb)->saddr; break; case 1: /* Restrict announcements of saddr in same subnet */ if (!skb) break; saddr = ip_hdr(skb)->saddr; - if (inet_addr_type(dev->nd_net, saddr) == RTN_LOCAL) { + if (inet_addr_type(&init_net, saddr) == RTN_LOCAL) { /* saddr should be known to target */ if (inet_addr_onlink(in_dev, target, saddr)) break; @@ -424,7 +424,7 @@ static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev) int flag = 0; /*unsigned long now; */ - if (ip_route_output_key(dev->nd_net, &rt, &fl) < 0) + if (ip_route_output_key(&init_net, &rt, &fl) < 0) return 1; if (rt->u.dst.dev != dev) { NET_INC_STATS_BH(LINUX_MIB_ARPFILTER); @@ -477,7 +477,7 @@ int arp_find(unsigned char *haddr, struct sk_buff *skb) paddr = skb->rtable->rt_gateway; - if (arp_set_predefined(inet_addr_type(dev->nd_net, paddr), haddr, paddr, dev)) + if (arp_set_predefined(inet_addr_type(&init_net, paddr), haddr, paddr, dev)) return 0; n = __neigh_lookup(&arp_tbl, &paddr, dev, 1); @@ -709,7 +709,6 @@ static int arp_process(struct sk_buff *skb) u16 dev_type = dev->type; int addr_type; struct neighbour *n; - struct net *net = dev->nd_net; /* arp_rcv below verifies the ARP header and verifies the device * is ARP'able. @@ -805,7 +804,7 @@ static int arp_process(struct sk_buff *skb) /* Special case: IPv4 duplicate address detection packet (RFC2131) */ if (sip == 0) { if (arp->ar_op == htons(ARPOP_REQUEST) && - inet_addr_type(net, tip) == RTN_LOCAL && + inet_addr_type(&init_net, tip) == RTN_LOCAL && !arp_ignore(in_dev, sip, tip)) arp_send(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha, dev->dev_addr, sha); @@ -835,7 +834,7 @@ static int arp_process(struct sk_buff *skb) goto out; } else if (IN_DEV_FORWARD(in_dev)) { if (addr_type == RTN_UNICAST && rt->u.dst.dev != dev && - (arp_fwd_proxy(in_dev, rt) || pneigh_lookup(&arp_tbl, net, &tip, dev, 0))) { + (arp_fwd_proxy(in_dev, rt) || pneigh_lookup(&arp_tbl, &init_net, &tip, dev, 0))) { n = neigh_event_ns(&arp_tbl, sha, &sip, dev); if (n) neigh_release(n); @@ -865,7 +864,7 @@ static int arp_process(struct sk_buff *skb) */ if (n == NULL && arp->ar_op == htons(ARPOP_REPLY) && - inet_addr_type(net, sip) == RTN_UNICAST) + inet_addr_type(&init_net, sip) == RTN_UNICAST) n = __neigh_lookup(&arp_tbl, &sip, dev, 1); } @@ -912,6 +911,9 @@ static int arp_rcv(struct sk_buff *skb, struct net_device *dev, { struct arphdr *arp; + if (dev->nd_net != &init_net) + goto freeskb; + /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ if (!pskb_may_pull(skb, arp_hdr_len(dev))) goto freeskb; @@ -1196,6 +1198,9 @@ static int arp_netdev_event(struct notifier_block *this, unsigned long event, vo { struct net_device *dev = ptr; + if (dev->nd_net != &init_net) + return NOTIFY_DONE; + switch (event) { case NETDEV_CHANGEADDR: neigh_changeaddr(&arp_tbl, dev); @@ -1377,29 +1382,13 @@ static const struct file_operations arp_seq_fops = { .release = seq_release_net, }; - -static int __net_init arp_net_init(struct net *net) +static int __init arp_proc_init(void) { - if (!proc_net_fops_create(net, "arp", S_IRUGO, &arp_seq_fops)) + if (!proc_net_fops_create(&init_net, "arp", S_IRUGO, &arp_seq_fops)) return -ENOMEM; return 0; } -static void __net_exit arp_net_exit(struct net *net) -{ - proc_net_remove(net, "arp"); -} - -static struct pernet_operations arp_net_ops = { - .init = arp_net_init, - .exit = arp_net_exit, -}; - -static int __init arp_proc_init(void) -{ - return register_pernet_subsys(&arp_net_ops); -} - #else /* CONFIG_PROC_FS */ static int __init arp_proc_init(void) diff --git a/trunk/net/ipv4/inet_connection_sock.c b/trunk/net/ipv4/inet_connection_sock.c index d13c5f12bb32..f9c5c4def1ba 100644 --- a/trunk/net/ipv4/inet_connection_sock.c +++ b/trunk/net/ipv4/inet_connection_sock.c @@ -333,7 +333,7 @@ struct dst_entry* inet_csk_route_req(struct sock *sk, .dport = ireq->rmt_port } } }; security_req_classify_flow(req, &fl); - if (ip_route_output_flow(sk->sk_net, &rt, &fl, sk, 0)) { + if (ip_route_output_flow(&init_net, &rt, &fl, sk, 0)) { IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); return NULL; } diff --git a/trunk/net/ipv4/ip_fragment.c b/trunk/net/ipv4/ip_fragment.c index 8b448c4b9080..3b2e5adca838 100644 --- a/trunk/net/ipv4/ip_fragment.c +++ b/trunk/net/ipv4/ip_fragment.c @@ -204,11 +204,8 @@ static void ip_expire(unsigned long arg) if ((qp->q.last_in&FIRST_IN) && qp->q.fragments != NULL) { struct sk_buff *head = qp->q.fragments; - struct net *net; - - net = container_of(qp->q.net, struct net, ipv4.frags); /* Send an ICMP "Fragment Reassembly Timeout" message. */ - if ((head->dev = dev_get_by_index(net, qp->iif)) != NULL) { + if ((head->dev = dev_get_by_index(&init_net, qp->iif)) != NULL) { icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); dev_put(head->dev); } diff --git a/trunk/net/ipv4/ip_input.c b/trunk/net/ipv4/ip_input.c index 2aeea5d15425..e3a0c78fa7bf 100644 --- a/trunk/net/ipv4/ip_input.c +++ b/trunk/net/ipv4/ip_input.c @@ -160,7 +160,6 @@ int ip_call_ra_chain(struct sk_buff *skb) struct ip_ra_chain *ra; u8 protocol = ip_hdr(skb)->protocol; struct sock *last = NULL; - struct net_device *dev = skb->dev; read_lock(&ip_ra_lock); for (ra = ip_ra_chain; ra; ra = ra->next) { @@ -171,8 +170,7 @@ int ip_call_ra_chain(struct sk_buff *skb) */ if (sk && inet_sk(sk)->num == protocol && (!sk->sk_bound_dev_if || - sk->sk_bound_dev_if == dev->ifindex) && - sk->sk_net == dev->nd_net) { + sk->sk_bound_dev_if == skb->dev->ifindex)) { if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { if (ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN)) { read_unlock(&ip_ra_lock); @@ -199,8 +197,6 @@ int ip_call_ra_chain(struct sk_buff *skb) static int ip_local_deliver_finish(struct sk_buff *skb) { - struct net *net = skb->dev->nd_net; - __skb_pull(skb, ip_hdrlen(skb)); /* Point into the IP datagram, just past the header. */ @@ -216,8 +212,7 @@ static int ip_local_deliver_finish(struct sk_buff *skb) raw = raw_local_deliver(skb, protocol); hash = protocol & (MAX_INET_PROTOS - 1); - ipprot = rcu_dereference(inet_protos[hash]); - if (ipprot != NULL && (net == &init_net || ipprot->netns_ok)) { + if ((ipprot = rcu_dereference(inet_protos[hash])) != NULL) { int ret; if (!ipprot->no_policy) { @@ -291,7 +286,7 @@ static inline int ip_rcv_options(struct sk_buff *skb) opt = &(IPCB(skb)->opt); opt->optlen = iph->ihl*4 - sizeof(struct iphdr); - if (ip_options_compile(dev->nd_net, opt, skb)) { + if (ip_options_compile(opt, skb)) { IP_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); goto drop; } @@ -378,6 +373,9 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct iphdr *iph; u32 len; + if (dev->nd_net != &init_net) + goto drop; + /* When the interface is in promisc. mode, drop all the crap * that it receives, do not try to analyse it. */ diff --git a/trunk/net/ipv4/ip_options.c b/trunk/net/ipv4/ip_options.c index 87cc1222c600..aeed4e5858ec 100644 --- a/trunk/net/ipv4/ip_options.c +++ b/trunk/net/ipv4/ip_options.c @@ -145,7 +145,7 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb) __be32 addr; memcpy(&addr, sptr+soffset-1, 4); - if (inet_addr_type(skb->dst->dev->nd_net, addr) != RTN_LOCAL) { + if (inet_addr_type(&init_net, addr) != RTN_LOCAL) { dopt->ts_needtime = 1; soffset += 8; } @@ -248,8 +248,7 @@ void ip_options_fragment(struct sk_buff * skb) * If opt == NULL, then skb->data should point to IP header. */ -int ip_options_compile(struct net *net, - struct ip_options * opt, struct sk_buff * skb) +int ip_options_compile(struct ip_options * opt, struct sk_buff * skb) { int l; unsigned char * iph; @@ -390,7 +389,7 @@ int ip_options_compile(struct net *net, { __be32 addr; memcpy(&addr, &optptr[optptr[2]-1], 4); - if (inet_addr_type(net, addr) == RTN_UNICAST) + if (inet_addr_type(&init_net, addr) == RTN_UNICAST) break; if (skb) timeptr = (__be32*)&optptr[optptr[2]+3]; @@ -507,13 +506,13 @@ static struct ip_options *ip_options_get_alloc(const int optlen) GFP_KERNEL); } -static int ip_options_get_finish(struct net *net, struct ip_options **optp, +static int ip_options_get_finish(struct ip_options **optp, struct ip_options *opt, int optlen) { while (optlen & 3) opt->__data[optlen++] = IPOPT_END; opt->optlen = optlen; - if (optlen && ip_options_compile(net, opt, NULL)) { + if (optlen && ip_options_compile(opt, NULL)) { kfree(opt); return -EINVAL; } @@ -522,8 +521,7 @@ static int ip_options_get_finish(struct net *net, struct ip_options **optp, return 0; } -int ip_options_get_from_user(struct net *net, struct ip_options **optp, - unsigned char __user *data, int optlen) +int ip_options_get_from_user(struct ip_options **optp, unsigned char __user *data, int optlen) { struct ip_options *opt = ip_options_get_alloc(optlen); @@ -533,11 +531,10 @@ int ip_options_get_from_user(struct net *net, struct ip_options **optp, kfree(opt); return -EFAULT; } - return ip_options_get_finish(net, optp, opt, optlen); + return ip_options_get_finish(optp, opt, optlen); } -int ip_options_get(struct net *net, struct ip_options **optp, - unsigned char *data, int optlen) +int ip_options_get(struct ip_options **optp, unsigned char *data, int optlen) { struct ip_options *opt = ip_options_get_alloc(optlen); @@ -545,7 +542,7 @@ int ip_options_get(struct net *net, struct ip_options **optp, return -ENOMEM; if (optlen) memcpy(opt->__data, data, optlen); - return ip_options_get_finish(net, optp, opt, optlen); + return ip_options_get_finish(optp, opt, optlen); } void ip_forward_options(struct sk_buff *skb) diff --git a/trunk/net/ipv4/ip_output.c b/trunk/net/ipv4/ip_output.c index 913266cd9902..dc494ea594a7 100644 --- a/trunk/net/ipv4/ip_output.c +++ b/trunk/net/ipv4/ip_output.c @@ -351,7 +351,7 @@ int ip_queue_xmit(struct sk_buff *skb, int ipfragok) * itself out. */ security_sk_classify_flow(sk, &fl); - if (ip_route_output_flow(sk->sk_net, &rt, &fl, sk, 0)) + if (ip_route_output_flow(&init_net, &rt, &fl, sk, 0)) goto no_route; } sk_setup_caps(sk, &rt->u.dst); @@ -825,7 +825,7 @@ int ip_append_data(struct sock *sk, inet->cork.fragsize = mtu = inet->pmtudisc == IP_PMTUDISC_PROBE ? rt->u.dst.dev->mtu : dst_mtu(rt->u.dst.path); - inet->cork.dst = &rt->u.dst; + inet->cork.rt = rt; inet->cork.length = 0; sk->sk_sndmsg_page = NULL; sk->sk_sndmsg_off = 0; @@ -834,7 +834,7 @@ int ip_append_data(struct sock *sk, transhdrlen += exthdrlen; } } else { - rt = (struct rtable *)inet->cork.dst; + rt = inet->cork.rt; if (inet->cork.flags & IPCORK_OPT) opt = inet->cork.opt; @@ -1083,7 +1083,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, if (skb_queue_empty(&sk->sk_write_queue)) return -EINVAL; - rt = (struct rtable *)inet->cork.dst; + rt = inet->cork.rt; if (inet->cork.flags & IPCORK_OPT) opt = inet->cork.opt; @@ -1208,8 +1208,10 @@ static void ip_cork_release(struct inet_sock *inet) inet->cork.flags &= ~IPCORK_OPT; kfree(inet->cork.opt); inet->cork.opt = NULL; - dst_release(inet->cork.dst); - inet->cork.dst = NULL; + if (inet->cork.rt) { + ip_rt_put(inet->cork.rt); + inet->cork.rt = NULL; + } } /* @@ -1222,7 +1224,7 @@ int ip_push_pending_frames(struct sock *sk) struct sk_buff **tail_skb; struct inet_sock *inet = inet_sk(sk); struct ip_options *opt = NULL; - struct rtable *rt = (struct rtable *)inet->cork.dst; + struct rtable *rt = inet->cork.rt; struct iphdr *iph; __be16 df = 0; __u8 ttl; diff --git a/trunk/net/ipv4/ip_sockglue.c b/trunk/net/ipv4/ip_sockglue.c index b854431047a4..bb3cbe5ec36d 100644 --- a/trunk/net/ipv4/ip_sockglue.c +++ b/trunk/net/ipv4/ip_sockglue.c @@ -163,7 +163,7 @@ void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb) ip_cmsg_recv_security(msg, skb); } -int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc) +int ip_cmsg_send(struct msghdr *msg, struct ipcm_cookie *ipc) { int err; struct cmsghdr *cmsg; @@ -176,7 +176,7 @@ int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc) switch (cmsg->cmsg_type) { case IP_RETOPTS: err = cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)); - err = ip_options_get(net, &ipc->opt, CMSG_DATA(cmsg), err < 40 ? err : 40); + err = ip_options_get(&ipc->opt, CMSG_DATA(cmsg), err < 40 ? err : 40); if (err) return err; break; @@ -449,8 +449,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, struct ip_options * opt = NULL; if (optlen > 40 || optlen < 0) goto e_inval; - err = ip_options_get_from_user(sk->sk_net, &opt, - optval, optlen); + err = ip_options_get_from_user(&opt, optval, optlen); if (err) break; if (inet->is_icsk) { @@ -590,13 +589,13 @@ static int do_ip_setsockopt(struct sock *sk, int level, err = 0; break; } - dev = ip_dev_find(sk->sk_net, mreq.imr_address.s_addr); + dev = ip_dev_find(&init_net, mreq.imr_address.s_addr); if (dev) { mreq.imr_ifindex = dev->ifindex; dev_put(dev); } } else - dev = __dev_get_by_index(sk->sk_net, mreq.imr_ifindex); + dev = __dev_get_by_index(&init_net, mreq.imr_ifindex); err = -EADDRNOTAVAIL; diff --git a/trunk/net/ipv4/raw.c b/trunk/net/ipv4/raw.c index 3f68a937b602..b433b485a883 100644 --- a/trunk/net/ipv4/raw.c +++ b/trunk/net/ipv4/raw.c @@ -499,7 +499,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, ipc.oif = sk->sk_bound_dev_if; if (msg->msg_controllen) { - err = ip_cmsg_send(sk->sk_net, msg, &ipc); + err = ip_cmsg_send(msg, &ipc); if (err) goto out; if (ipc.opt) @@ -553,7 +553,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, } security_sk_classify_flow(sk, &fl); - err = ip_route_output_flow(sk->sk_net, &rt, &fl, sk, 1); + err = ip_route_output_flow(&init_net, &rt, &fl, sk, 1); } if (err) goto done; diff --git a/trunk/net/ipv4/tcp_ipv4.c b/trunk/net/ipv4/tcp_ipv4.c index 649d00a50cb1..1a47719a55ad 100644 --- a/trunk/net/ipv4/tcp_ipv4.c +++ b/trunk/net/ipv4/tcp_ipv4.c @@ -2425,29 +2425,14 @@ static struct tcp_seq_afinfo tcp4_seq_afinfo = { .seq_fops = &tcp4_seq_fops, }; -static int tcp4_proc_init_net(struct net *net) -{ - return tcp_proc_register(net, &tcp4_seq_afinfo); -} - -static void tcp4_proc_exit_net(struct net *net) -{ - tcp_proc_unregister(net, &tcp4_seq_afinfo); -} - -static struct pernet_operations tcp4_net_ops = { - .init = tcp4_proc_init_net, - .exit = tcp4_proc_exit_net, -}; - int __init tcp4_proc_init(void) { - return register_pernet_subsys(&tcp4_net_ops); + return tcp_proc_register(&init_net, &tcp4_seq_afinfo); } void tcp4_proc_exit(void) { - unregister_pernet_subsys(&tcp4_net_ops); + tcp_proc_unregister(&init_net, &tcp4_seq_afinfo); } #endif /* CONFIG_PROC_FS */ diff --git a/trunk/net/ipv4/udp.c b/trunk/net/ipv4/udp.c index b37581dfd029..8c1f5eaafcd2 100644 --- a/trunk/net/ipv4/udp.c +++ b/trunk/net/ipv4/udp.c @@ -607,7 +607,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, ipc.oif = sk->sk_bound_dev_if; if (msg->msg_controllen) { - err = ip_cmsg_send(sk->sk_net, msg, &ipc); + err = ip_cmsg_send(msg, &ipc); if (err) return err; if (ipc.opt) @@ -656,7 +656,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, { .sport = inet->sport, .dport = dport } } }; security_sk_classify_flow(sk, &fl); - err = ip_route_output_flow(sk->sk_net, &rt, &fl, sk, 1); + err = ip_route_output_flow(&init_net, &rt, &fl, sk, 1); if (err) { if (err == -ENETUNREACH) IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); @@ -1701,29 +1701,14 @@ static struct udp_seq_afinfo udp4_seq_afinfo = { .seq_fops = &udp4_seq_fops, }; -static int udp4_proc_init_net(struct net *net) -{ - return udp_proc_register(net, &udp4_seq_afinfo); -} - -static void udp4_proc_exit_net(struct net *net) -{ - udp_proc_unregister(net, &udp4_seq_afinfo); -} - -static struct pernet_operations udp4_net_ops = { - .init = udp4_proc_init_net, - .exit = udp4_proc_exit_net, -}; - int __init udp4_proc_init(void) { - return register_pernet_subsys(&udp4_net_ops); + return udp_proc_register(&init_net, &udp4_seq_afinfo); } void udp4_proc_exit(void) { - unregister_pernet_subsys(&udp4_net_ops); + udp_proc_unregister(&init_net, &udp4_seq_afinfo); } #endif /* CONFIG_PROC_FS */ diff --git a/trunk/net/ipv4/udplite.c b/trunk/net/ipv4/udplite.c index 53f3ed496328..8d42e344b043 100644 --- a/trunk/net/ipv4/udplite.c +++ b/trunk/net/ipv4/udplite.c @@ -31,7 +31,6 @@ static struct net_protocol udplite_protocol = { .handler = udplite_rcv, .err_handler = udplite_err, .no_policy = 1, - .netns_ok = 1, }; DEFINE_PROTO_INUSE(udplite) @@ -83,31 +82,6 @@ static struct udp_seq_afinfo udplite4_seq_afinfo = { .seq_show = udp4_seq_show, .seq_fops = &udplite4_seq_fops, }; - -static int udplite4_proc_init_net(struct net *net) -{ - return udp_proc_register(net, &udplite4_seq_afinfo); -} - -static void udplite4_proc_exit_net(struct net *net) -{ - udp_proc_unregister(net, &udplite4_seq_afinfo); -} - -static struct pernet_operations udplite4_net_ops = { - .init = udplite4_proc_init_net, - .exit = udplite4_proc_exit_net, -}; - -static __init int udplite4_proc_init(void) -{ - return register_pernet_subsys(&udplite4_net_ops); -} -#else -static inline int udplite4_proc_init(void) -{ - return 0; -} #endif void __init udplite4_register(void) @@ -120,8 +94,10 @@ void __init udplite4_register(void) inet_register_protosw(&udplite4_protosw); - if (udplite4_proc_init()) +#ifdef CONFIG_PROC_FS + if (udp_proc_register(&init_net, &udplite4_seq_afinfo)) printk(KERN_ERR "%s: Cannot register /proc!\n", __func__); +#endif return; out_unregister_proto: diff --git a/trunk/net/ipv6/addrconf.c b/trunk/net/ipv6/addrconf.c index 89954885dee1..4b86d388bf63 100644 --- a/trunk/net/ipv6/addrconf.c +++ b/trunk/net/ipv6/addrconf.c @@ -877,40 +877,20 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i /* * Choose an appropriate source address (RFC3484) */ -enum { - IPV6_SADDR_RULE_INIT = 0, - IPV6_SADDR_RULE_LOCAL, - IPV6_SADDR_RULE_SCOPE, - IPV6_SADDR_RULE_PREFERRED, -#ifdef CONFIG_IPV6_MIP6 - IPV6_SADDR_RULE_HOA, -#endif - IPV6_SADDR_RULE_OIF, - IPV6_SADDR_RULE_LABEL, -#ifdef CONFIG_IPV6_PRIVACY - IPV6_SADDR_RULE_PRIVACY, -#endif - IPV6_SADDR_RULE_ORCHID, - IPV6_SADDR_RULE_PREFIX, - IPV6_SADDR_RULE_MAX -}; - struct ipv6_saddr_score { - int rule; - int addr_type; - struct inet6_ifaddr *ifa; - DECLARE_BITMAP(scorebits, IPV6_SADDR_RULE_MAX); - int scopedist; - int matchlen; + int addr_type; + unsigned int attrs; + int matchlen; + int scope; + unsigned int rule; }; -struct ipv6_saddr_dst { - struct in6_addr *addr; - int ifindex; - int scope; - int label; - unsigned int prefs; -}; +#define IPV6_SADDR_SCORE_LOCAL 0x0001 +#define IPV6_SADDR_SCORE_PREFERRED 0x0004 +#define IPV6_SADDR_SCORE_HOA 0x0008 +#define IPV6_SADDR_SCORE_OIF 0x0010 +#define IPV6_SADDR_SCORE_LABEL 0x0020 +#define IPV6_SADDR_SCORE_PRIVACY 0x0040 static inline int ipv6_saddr_preferred(int type) { @@ -920,152 +900,28 @@ static inline int ipv6_saddr_preferred(int type) return 0; } -static int ipv6_get_saddr_eval(struct ipv6_saddr_score *score, - struct ipv6_saddr_dst *dst, - int i) -{ - int ret; - - if (i <= score->rule) { - switch (i) { - case IPV6_SADDR_RULE_SCOPE: - ret = score->scopedist; - break; - case IPV6_SADDR_RULE_PREFIX: - ret = score->matchlen; - break; - default: - ret = !!test_bit(i, score->scorebits); - } - goto out; - } - - switch (i) { - case IPV6_SADDR_RULE_INIT: - /* Rule 0: remember if hiscore is not ready yet */ - ret = !!score->ifa; - break; - case IPV6_SADDR_RULE_LOCAL: - /* Rule 1: Prefer same address */ - ret = ipv6_addr_equal(&score->ifa->addr, dst->addr); - break; - case IPV6_SADDR_RULE_SCOPE: - /* Rule 2: Prefer appropriate scope - * - * ret - * ^ - * -1 | d 15 - * ---+--+-+---> scope - * | - * | d is scope of the destination. - * B-d | \ - * | \ <- smaller scope is better if - * B-15 | \ if scope is enough for destinaion. - * | ret = B - scope (-1 <= scope >= d <= 15). - * d-C-1 | / - * |/ <- greater is better - * -C / if scope is not enough for destination. - * /| ret = scope - C (-1 <= d < scope <= 15). - * - * d - C - 1 < B -15 (for all -1 <= d <= 15). - * C > d + 14 - B >= 15 + 14 - B = 29 - B. - * Assume B = 0 and we get C > 29. - */ - ret = __ipv6_addr_src_scope(score->addr_type); - if (ret >= dst->scope) - ret = -ret; - else - ret -= 128; /* 30 is enough */ - score->scopedist = ret; - break; - case IPV6_SADDR_RULE_PREFERRED: - /* Rule 3: Avoid deprecated and optimistic addresses */ - ret = ipv6_saddr_preferred(score->addr_type) || - !(score->ifa->flags & (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)); - break; -#ifdef CONFIG_IPV6_MIP6 - case IPV6_SADDR_RULE_HOA: - { - /* Rule 4: Prefer home address */ - int prefhome = !(dst->prefs & IPV6_PREFER_SRC_COA); - ret = !(score->ifa->flags & IFA_F_HOMEADDRESS) ^ prefhome; - break; - } -#endif - case IPV6_SADDR_RULE_OIF: - /* Rule 5: Prefer outgoing interface */ - ret = (!dst->ifindex || - dst->ifindex == score->ifa->idev->dev->ifindex); - break; - case IPV6_SADDR_RULE_LABEL: - /* Rule 6: Prefer matching label */ - ret = ipv6_addr_label(&score->ifa->addr, score->addr_type, - score->ifa->idev->dev->ifindex) == dst->label; - break; -#ifdef CONFIG_IPV6_PRIVACY - case IPV6_SADDR_RULE_PRIVACY: - { - /* Rule 7: Prefer public address - * Note: prefer temprary address if use_tempaddr >= 2 - */ - int preftmp = dst->prefs & (IPV6_PREFER_SRC_PUBLIC|IPV6_PREFER_SRC_TMP) ? - !!(dst->prefs & IPV6_PREFER_SRC_TMP) : - score->ifa->idev->cnf.use_tempaddr >= 2; - ret = (!(score->ifa->flags & IFA_F_TEMPORARY)) ^ preftmp; - break; - } -#endif - case IPV6_SADDR_RULE_ORCHID: - /* Rule 8-: Prefer ORCHID vs ORCHID or - * non-ORCHID vs non-ORCHID - */ - ret = !(ipv6_addr_orchid(&score->ifa->addr) ^ - ipv6_addr_orchid(dst->addr)); - break; - case IPV6_SADDR_RULE_PREFIX: - /* Rule 8: Use longest matching prefix */ - score->matchlen = ret = ipv6_addr_diff(&score->ifa->addr, - dst->addr); - break; - default: - ret = 0; - } - - if (ret) - __set_bit(i, score->scorebits); - score->rule = i; -out: - return ret; -} - -int ipv6_dev_get_saddr(struct net_device *dst_dev, - struct in6_addr *daddr, unsigned int prefs, - struct in6_addr *saddr) +int ipv6_dev_get_saddr(struct net_device *daddr_dev, + struct in6_addr *daddr, struct in6_addr *saddr) { - struct ipv6_saddr_score scores[2], - *score = &scores[0], *hiscore = &scores[1]; - struct net *net = dst_dev->nd_net; - struct ipv6_saddr_dst dst; + struct ipv6_saddr_score hiscore; + struct inet6_ifaddr *ifa_result = NULL; + struct net *net = daddr_dev->nd_net; + int daddr_type = __ipv6_addr_type(daddr); + int daddr_scope = __ipv6_addr_src_scope(daddr_type); + int daddr_ifindex = daddr_dev ? daddr_dev->ifindex : 0; + u32 daddr_label = ipv6_addr_label(daddr, daddr_type, daddr_ifindex); struct net_device *dev; - int dst_type; - - dst_type = __ipv6_addr_type(daddr); - dst.addr = daddr; - dst.ifindex = dst_dev ? dst_dev->ifindex : 0; - dst.scope = __ipv6_addr_src_scope(dst_type); - dst.label = ipv6_addr_label(daddr, dst_type, dst.ifindex); - dst.prefs = prefs; - hiscore->rule = -1; - hiscore->ifa = NULL; + memset(&hiscore, 0, sizeof(hiscore)); read_lock(&dev_base_lock); rcu_read_lock(); for_each_netdev(net, dev) { struct inet6_dev *idev; + struct inet6_ifaddr *ifa; - /* Candidate Source Address (section 4) + /* Rule 0: Candidate Source Address (section 4) * - multicast and link-local destination address, * the set of candidate source address MUST only * include addresses assigned to interfaces @@ -1077,9 +933,9 @@ int ipv6_dev_get_saddr(struct net_device *dst_dev, * belonging to the same site as the outgoing * interface.) */ - if (((dst_type & IPV6_ADDR_MULTICAST) || - dst.scope <= IPV6_ADDR_SCOPE_LINKLOCAL) && - dst.ifindex && dev->ifindex != dst.ifindex) + if ((daddr_type & IPV6_ADDR_MULTICAST || + daddr_scope <= IPV6_ADDR_SCOPE_LINKLOCAL) && + daddr_dev && dev != daddr_dev) continue; idev = __in6_dev_get(dev); @@ -1087,10 +943,12 @@ int ipv6_dev_get_saddr(struct net_device *dst_dev, continue; read_lock_bh(&idev->lock); - for (score->ifa = idev->addr_list; score->ifa; score->ifa = score->ifa->if_next) { - int i; + for (ifa = idev->addr_list; ifa; ifa = ifa->if_next) { + struct ipv6_saddr_score score; - /* + score.addr_type = __ipv6_addr_type(&ifa->addr); + + /* Rule 0: * - Tentative Address (RFC2462 section 5.4) * - A tentative address is not considered * "assigned to an interface" in the traditional @@ -1100,14 +958,11 @@ int ipv6_dev_get_saddr(struct net_device *dst_dev, * addresses, and the unspecified address MUST * NOT be included in a candidate set. */ - if ((score->ifa->flags & IFA_F_TENTATIVE) && - (!(score->ifa->flags & IFA_F_OPTIMISTIC))) + if ((ifa->flags & IFA_F_TENTATIVE) && + (!(ifa->flags & IFA_F_OPTIMISTIC))) continue; - - score->addr_type = __ipv6_addr_type(&score->ifa->addr); - - if (unlikely(score->addr_type == IPV6_ADDR_ANY || - score->addr_type & IPV6_ADDR_MULTICAST)) { + if (unlikely(score.addr_type == IPV6_ADDR_ANY || + score.addr_type & IPV6_ADDR_MULTICAST)) { LIMIT_NETDEBUG(KERN_DEBUG "ADDRCONF: unspecified / multicast address " "assigned as unicast address on %s", @@ -1115,59 +970,201 @@ int ipv6_dev_get_saddr(struct net_device *dst_dev, continue; } - score->rule = -1; - bitmap_zero(score->scorebits, IPV6_SADDR_RULE_MAX); - - for (i = 0; i < IPV6_SADDR_RULE_MAX; i++) { - int minihiscore, miniscore; - - minihiscore = ipv6_get_saddr_eval(hiscore, &dst, i); - miniscore = ipv6_get_saddr_eval(score, &dst, i); - - if (minihiscore > miniscore) { - if (i == IPV6_SADDR_RULE_SCOPE && - score->scopedist > 0) { - /* - * special case: - * each remaining entry - * has too small (not enough) - * scope, because ifa entries - * are sorted by their scope - * values. - */ - goto try_nextdev; - } - break; - } else if (minihiscore < miniscore) { - struct ipv6_saddr_score *tmp; + score.attrs = 0; + score.matchlen = 0; + score.scope = 0; + score.rule = 0; - if (hiscore->ifa) - in6_ifa_put(hiscore->ifa); + if (ifa_result == NULL) { + /* record it if the first available entry */ + goto record_it; + } - in6_ifa_hold(score->ifa); + /* Rule 1: Prefer same address */ + if (hiscore.rule < 1) { + if (ipv6_addr_equal(&ifa_result->addr, daddr)) + hiscore.attrs |= IPV6_SADDR_SCORE_LOCAL; + hiscore.rule++; + } + if (ipv6_addr_equal(&ifa->addr, daddr)) { + score.attrs |= IPV6_SADDR_SCORE_LOCAL; + if (!(hiscore.attrs & IPV6_SADDR_SCORE_LOCAL)) { + score.rule = 1; + goto record_it; + } + } else { + if (hiscore.attrs & IPV6_SADDR_SCORE_LOCAL) + continue; + } - tmp = hiscore; - hiscore = score; - score = tmp; + /* Rule 2: Prefer appropriate scope */ + if (hiscore.rule < 2) { + hiscore.scope = __ipv6_addr_src_scope(hiscore.addr_type); + hiscore.rule++; + } + score.scope = __ipv6_addr_src_scope(score.addr_type); + if (hiscore.scope < score.scope) { + if (hiscore.scope < daddr_scope) { + score.rule = 2; + goto record_it; + } else + continue; + } else if (score.scope < hiscore.scope) { + if (score.scope < daddr_scope) + break; /* addresses sorted by scope */ + else { + score.rule = 2; + goto record_it; + } + } - /* restore our iterator */ - score->ifa = hiscore->ifa; + /* Rule 3: Avoid deprecated and optimistic addresses */ + if (hiscore.rule < 3) { + if (ipv6_saddr_preferred(hiscore.addr_type) || + (((ifa_result->flags & + (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0))) + hiscore.attrs |= IPV6_SADDR_SCORE_PREFERRED; + hiscore.rule++; + } + if (ipv6_saddr_preferred(score.addr_type) || + (((ifa->flags & + (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0))) { + score.attrs |= IPV6_SADDR_SCORE_PREFERRED; + if (!(hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED)) { + score.rule = 3; + goto record_it; + } + } else { + if (hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED) + continue; + } - break; + /* Rule 4: Prefer home address */ +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) + if (hiscore.rule < 4) { + if (ifa_result->flags & IFA_F_HOMEADDRESS) + hiscore.attrs |= IPV6_SADDR_SCORE_HOA; + hiscore.rule++; + } + if (ifa->flags & IFA_F_HOMEADDRESS) { + score.attrs |= IPV6_SADDR_SCORE_HOA; + if (!(ifa_result->flags & IFA_F_HOMEADDRESS)) { + score.rule = 4; + goto record_it; + } + } else { + if (hiscore.attrs & IPV6_SADDR_SCORE_HOA) + continue; + } +#else + if (hiscore.rule < 4) + hiscore.rule++; +#endif + + /* Rule 5: Prefer outgoing interface */ + if (hiscore.rule < 5) { + if (daddr_dev == NULL || + daddr_dev == ifa_result->idev->dev) + hiscore.attrs |= IPV6_SADDR_SCORE_OIF; + hiscore.rule++; + } + if (daddr_dev == NULL || + daddr_dev == ifa->idev->dev) { + score.attrs |= IPV6_SADDR_SCORE_OIF; + if (!(hiscore.attrs & IPV6_SADDR_SCORE_OIF)) { + score.rule = 5; + goto record_it; } + } else { + if (hiscore.attrs & IPV6_SADDR_SCORE_OIF) + continue; } + + /* Rule 6: Prefer matching label */ + if (hiscore.rule < 6) { + if (ipv6_addr_label(&ifa_result->addr, + hiscore.addr_type, + ifa_result->idev->dev->ifindex) == daddr_label) + hiscore.attrs |= IPV6_SADDR_SCORE_LABEL; + hiscore.rule++; + } + if (ipv6_addr_label(&ifa->addr, + score.addr_type, + ifa->idev->dev->ifindex) == daddr_label) { + score.attrs |= IPV6_SADDR_SCORE_LABEL; + if (!(hiscore.attrs & IPV6_SADDR_SCORE_LABEL)) { + score.rule = 6; + goto record_it; + } + } else { + if (hiscore.attrs & IPV6_SADDR_SCORE_LABEL) + continue; + } + +#ifdef CONFIG_IPV6_PRIVACY + /* Rule 7: Prefer public address + * Note: prefer temprary address if use_tempaddr >= 2 + */ + if (hiscore.rule < 7) { + if ((!(ifa_result->flags & IFA_F_TEMPORARY)) ^ + (ifa_result->idev->cnf.use_tempaddr >= 2)) + hiscore.attrs |= IPV6_SADDR_SCORE_PRIVACY; + hiscore.rule++; + } + if ((!(ifa->flags & IFA_F_TEMPORARY)) ^ + (ifa->idev->cnf.use_tempaddr >= 2)) { + score.attrs |= IPV6_SADDR_SCORE_PRIVACY; + if (!(hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY)) { + score.rule = 7; + goto record_it; + } + } else { + if (hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY) + continue; + } +#else + if (hiscore.rule < 7) + hiscore.rule++; +#endif + + /* Skip rule 8 for orchid -> non-orchid address pairs. */ + if (ipv6_addr_orchid(&ifa->addr) && !ipv6_addr_orchid(daddr)) + continue; + + /* Rule 8: Use longest matching prefix */ + if (hiscore.rule < 8) { + hiscore.matchlen = ipv6_addr_diff(&ifa_result->addr, daddr); + hiscore.rule++; + } + score.matchlen = ipv6_addr_diff(&ifa->addr, daddr); + if (score.matchlen > hiscore.matchlen) { + score.rule = 8; + goto record_it; + } +#if 0 + else if (score.matchlen < hiscore.matchlen) + continue; +#endif + + /* Final Rule: choose first available one */ + continue; +record_it: + if (ifa_result) + in6_ifa_put(ifa_result); + in6_ifa_hold(ifa); + ifa_result = ifa; + hiscore = score; } -try_nextdev: read_unlock_bh(&idev->lock); } rcu_read_unlock(); read_unlock(&dev_base_lock); - if (!hiscore->ifa) + if (!ifa_result) return -EADDRNOTAVAIL; - ipv6_addr_copy(saddr, &hiscore->ifa->addr); - in6_ifa_put(hiscore->ifa); + ipv6_addr_copy(saddr, &ifa_result->addr); + in6_ifa_put(ifa_result); return 0; } diff --git a/trunk/net/ipv6/fib6_rules.c b/trunk/net/ipv6/fib6_rules.c index e7a7fe26cebf..55137408f054 100644 --- a/trunk/net/ipv6/fib6_rules.c +++ b/trunk/net/ipv6/fib6_rules.c @@ -84,18 +84,8 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, if ((rule->flags & FIB_RULE_FIND_SADDR) && r->src.plen && !(flags & RT6_LOOKUP_F_HAS_SADDR)) { struct in6_addr saddr; - unsigned int srcprefs = 0; - - if (flags & RT6_LOOKUP_F_SRCPREF_TMP) - srcprefs |= IPV6_PREFER_SRC_TMP; - if (flags & RT6_LOOKUP_F_SRCPREF_PUBLIC) - srcprefs |= IPV6_PREFER_SRC_PUBLIC; - if (flags & RT6_LOOKUP_F_SRCPREF_COA) - srcprefs |= IPV6_PREFER_SRC_COA; - if (ipv6_dev_get_saddr(ip6_dst_idev(&rt->u.dst)->dev, - &flp->fl6_dst, srcprefs, - &saddr)) + &flp->fl6_dst, &saddr)) goto again; if (!ipv6_prefix_equal(&saddr, &r->src.addr, r->src.plen)) diff --git a/trunk/net/ipv6/icmp.c b/trunk/net/ipv6/icmp.c index 86332417b402..6b5391ab8346 100644 --- a/trunk/net/ipv6/icmp.c +++ b/trunk/net/ipv6/icmp.c @@ -464,7 +464,9 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, else hlimit = np->hop_limit; if (hlimit < 0) - hlimit = ip6_dst_hoplimit(dst); + hlimit = dst_metric(dst, RTAX_HOPLIMIT); + if (hlimit < 0) + hlimit = ipv6_get_hoplimit(dst->dev); tclass = np->tclass; if (tclass < 0) @@ -558,7 +560,9 @@ static void icmpv6_echo_reply(struct sk_buff *skb) else hlimit = np->hop_limit; if (hlimit < 0) - hlimit = ip6_dst_hoplimit(dst); + hlimit = dst_metric(dst, RTAX_HOPLIMIT); + if (hlimit < 0) + hlimit = ipv6_get_hoplimit(dst->dev); tclass = np->tclass; if (tclass < 0) diff --git a/trunk/net/ipv6/ip6_output.c b/trunk/net/ipv6/ip6_output.c index d34aa61353bb..98762fde2b65 100644 --- a/trunk/net/ipv6/ip6_output.c +++ b/trunk/net/ipv6/ip6_output.c @@ -237,7 +237,9 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, if (np) hlimit = np->hop_limit; if (hlimit < 0) - hlimit = ip6_dst_hoplimit(dst); + hlimit = dst_metric(dst, RTAX_HOPLIMIT); + if (hlimit < 0) + hlimit = ipv6_get_hoplimit(dst->dev); tclass = -1; if (np) @@ -920,9 +922,7 @@ static int ip6_dst_lookup_tail(struct sock *sk, if (ipv6_addr_any(&fl->fl6_src)) { err = ipv6_dev_get_saddr(ip6_dst_idev(*dst)->dev, - &fl->fl6_dst, - sk ? inet6_sk(sk)->srcprefs : 0, - &fl->fl6_src); + &fl->fl6_dst, &fl->fl6_src); if (err) goto out_err_release; } @@ -1115,7 +1115,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, /* need source address above miyazawa*/ } dst_hold(&rt->u.dst); - inet->cork.dst = &rt->u.dst; + np->cork.rt = rt; inet->cork.fl = *fl; np->cork.hop_limit = hlimit; np->cork.tclass = tclass; @@ -1136,7 +1136,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, length += exthdrlen; transhdrlen += exthdrlen; } else { - rt = (struct rt6_info *)inet->cork.dst; + rt = np->cork.rt; fl = &inet->cork.fl; if (inet->cork.flags & IPCORK_OPT) opt = np->cork.opt; @@ -1381,9 +1381,9 @@ static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np) inet->cork.flags &= ~IPCORK_OPT; kfree(np->cork.opt); np->cork.opt = NULL; - if (inet->cork.dst) { - dst_release(inet->cork.dst); - inet->cork.dst = NULL; + if (np->cork.rt) { + dst_release(&np->cork.rt->u.dst); + np->cork.rt = NULL; inet->cork.flags &= ~IPCORK_ALLFRAG; } memset(&inet->cork.fl, 0, sizeof(inet->cork.fl)); @@ -1398,7 +1398,7 @@ int ip6_push_pending_frames(struct sock *sk) struct ipv6_pinfo *np = inet6_sk(sk); struct ipv6hdr *hdr; struct ipv6_txoptions *opt = np->cork.opt; - struct rt6_info *rt = (struct rt6_info *)inet->cork.dst; + struct rt6_info *rt = np->cork.rt; struct flowi *fl = &inet->cork.fl; unsigned char proto = fl->proto; int err = 0; diff --git a/trunk/net/ipv6/ipv6_sockglue.c b/trunk/net/ipv6/ipv6_sockglue.c index dc6695cc5767..c11c76cab371 100644 --- a/trunk/net/ipv6/ipv6_sockglue.c +++ b/trunk/net/ipv6/ipv6_sockglue.c @@ -617,67 +617,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, retv = xfrm_user_policy(sk, optname, optval, optlen); break; - case IPV6_ADDR_PREFERENCES: - { - unsigned int pref = 0; - unsigned int prefmask = ~0; - - retv = -EINVAL; - - /* check PUBLIC/TMP/PUBTMP_DEFAULT conflicts */ - switch (val & (IPV6_PREFER_SRC_PUBLIC| - IPV6_PREFER_SRC_TMP| - IPV6_PREFER_SRC_PUBTMP_DEFAULT)) { - case IPV6_PREFER_SRC_PUBLIC: - pref |= IPV6_PREFER_SRC_PUBLIC; - break; - case IPV6_PREFER_SRC_TMP: - pref |= IPV6_PREFER_SRC_TMP; - break; - case IPV6_PREFER_SRC_PUBTMP_DEFAULT: - break; - case 0: - goto pref_skip_pubtmp; - default: - goto e_inval; - } - - prefmask &= ~(IPV6_PREFER_SRC_PUBLIC| - IPV6_PREFER_SRC_TMP); -pref_skip_pubtmp: - - /* check HOME/COA conflicts */ - switch (val & (IPV6_PREFER_SRC_HOME|IPV6_PREFER_SRC_COA)) { - case IPV6_PREFER_SRC_HOME: - break; - case IPV6_PREFER_SRC_COA: - pref |= IPV6_PREFER_SRC_COA; - case 0: - goto pref_skip_coa; - default: - goto e_inval; - } - - prefmask &= ~IPV6_PREFER_SRC_COA; -pref_skip_coa: - - /* check CGA/NONCGA conflicts */ - switch (val & (IPV6_PREFER_SRC_CGA|IPV6_PREFER_SRC_NONCGA)) { - case IPV6_PREFER_SRC_CGA: - case IPV6_PREFER_SRC_NONCGA: - case 0: - break; - default: - goto e_inval; - } - - np->srcprefs = (np->srcprefs & prefmask) | pref; - retv = 0; - - break; - } } - release_sock(sk); return retv; @@ -964,7 +904,9 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, dst = sk_dst_get(sk); if (dst) { if (val < 0) - val = ip6_dst_hoplimit(dst); + val = dst_metric(dst, RTAX_HOPLIMIT); + if (val < 0) + val = ipv6_get_hoplimit(dst->dev); dst_release(dst); } if (val < 0) @@ -992,24 +934,6 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, val = np->sndflow; break; - case IPV6_ADDR_PREFERENCES: - val = 0; - - if (np->srcprefs & IPV6_PREFER_SRC_TMP) - val |= IPV6_PREFER_SRC_TMP; - else if (np->srcprefs & IPV6_PREFER_SRC_PUBLIC) - val |= IPV6_PREFER_SRC_PUBLIC; - else { - /* XXX: should we return system default? */ - val |= IPV6_PREFER_SRC_PUBTMP_DEFAULT; - } - - if (np->srcprefs & IPV6_PREFER_SRC_COA) - val |= IPV6_PREFER_SRC_COA; - else - val |= IPV6_PREFER_SRC_HOME; - break; - default: return -ENOPROTOOPT; } diff --git a/trunk/net/ipv6/ndisc.c b/trunk/net/ipv6/ndisc.c index 3f68a6eae7b2..e7d8e74704c1 100644 --- a/trunk/net/ipv6/ndisc.c +++ b/trunk/net/ipv6/ndisc.c @@ -546,9 +546,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, override = 0; in6_ifa_put(ifp); } else { - if (ipv6_dev_get_saddr(dev, daddr, - inet6_sk(dev->nd_net->ipv6.ndisc_sk)->srcprefs, - &tmpaddr)) + if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr)) return; src_addr = &tmpaddr; } diff --git a/trunk/net/ipv6/raw.c b/trunk/net/ipv6/raw.c index 548d0763f4d3..a9e4235157a2 100644 --- a/trunk/net/ipv6/raw.c +++ b/trunk/net/ipv6/raw.c @@ -885,7 +885,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, else hlimit = np->hop_limit; if (hlimit < 0) - hlimit = ip6_dst_hoplimit(dst); + hlimit = dst_metric(dst, RTAX_HOPLIMIT); + if (hlimit < 0) + hlimit = ipv6_get_hoplimit(dst->dev); } if (tclass < 0) { diff --git a/trunk/net/ipv6/route.c b/trunk/net/ipv6/route.c index 06faa46920e1..a4b5aee0f68a 100644 --- a/trunk/net/ipv6/route.c +++ b/trunk/net/ipv6/route.c @@ -782,15 +782,6 @@ struct dst_entry * ip6_route_output(struct net *net, struct sock *sk, if (!ipv6_addr_any(&fl->fl6_src)) flags |= RT6_LOOKUP_F_HAS_SADDR; - else if (sk) { - unsigned int prefs = inet6_sk(sk)->srcprefs; - if (prefs & IPV6_PREFER_SRC_TMP) - flags |= RT6_LOOKUP_F_SRCPREF_TMP; - if (prefs & IPV6_PREFER_SRC_PUBLIC) - flags |= RT6_LOOKUP_F_SRCPREF_PUBLIC; - if (prefs & IPV6_PREFER_SRC_COA) - flags |= RT6_LOOKUP_F_SRCPREF_COA; - } return fib6_rule_lookup(net, fl, flags, ip6_pol_route_output); } @@ -1043,17 +1034,15 @@ static int ipv6_get_mtu(struct net_device *dev) return mtu; } -int ip6_dst_hoplimit(struct dst_entry *dst) +int ipv6_get_hoplimit(struct net_device *dev) { - int hoplimit = dst_metric(dst, RTAX_HOPLIMIT); - if (hoplimit < 0) { - struct net_device *dev = dst->dev; - struct inet6_dev *idev = in6_dev_get(dev); - if (idev) { - hoplimit = idev->cnf.hop_limit; - in6_dev_put(idev); - } else - hoplimit = ipv6_devconf.hop_limit; + int hoplimit = ipv6_devconf.hop_limit; + struct inet6_dev *idev; + + idev = in6_dev_get(dev); + if (idev) { + hoplimit = idev->cnf.hop_limit; + in6_dev_put(idev); } return hoplimit; } @@ -2171,7 +2160,7 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, else if (dst) { struct in6_addr saddr_buf; if (ipv6_dev_get_saddr(ip6_dst_idev(&rt->u.dst)->dev, - dst, 0, &saddr_buf) == 0) + dst, &saddr_buf) == 0) NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); } diff --git a/trunk/net/ipv6/udp.c b/trunk/net/ipv6/udp.c index 593d3efadaf9..5f5d1218c34e 100644 --- a/trunk/net/ipv6/udp.c +++ b/trunk/net/ipv6/udp.c @@ -792,7 +792,9 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, else hlimit = np->hop_limit; if (hlimit < 0) - hlimit = ip6_dst_hoplimit(dst); + hlimit = dst_metric(dst, RTAX_HOPLIMIT); + if (hlimit < 0) + hlimit = ipv6_get_hoplimit(dst->dev); } if (tclass < 0) { diff --git a/trunk/net/ipv6/udplite.c b/trunk/net/ipv6/udplite.c index 706c5c375a01..93e52e0d57f2 100644 --- a/trunk/net/ipv6/udplite.c +++ b/trunk/net/ipv6/udplite.c @@ -109,28 +109,13 @@ static struct udp_seq_afinfo udplite6_seq_afinfo = { .seq_fops = &udplite6_seq_fops, }; -static int udplite6_proc_init_net(struct net *net) -{ - return udp_proc_register(net, &udplite6_seq_afinfo); -} - -static void udplite6_proc_exit_net(struct net *net) -{ - udp_proc_unregister(net, &udplite6_seq_afinfo); -} - -static struct pernet_operations udplite6_net_ops = { - .init = udplite6_proc_init_net, - .exit = udplite6_proc_exit_net, -}; - int __init udplite6_proc_init(void) { - return register_pernet_subsys(&udplite6_net_ops); + return udp_proc_register(&init_net, &udplite6_seq_afinfo); } void udplite6_proc_exit(void) { - unregister_pernet_subsys(&udplite6_net_ops); + udp_proc_unregister(&init_net, &udplite6_seq_afinfo); } #endif diff --git a/trunk/net/ipv6/xfrm6_input.c b/trunk/net/ipv6/xfrm6_input.c index a71c7ddcb41e..a4714d76ae6b 100644 --- a/trunk/net/ipv6/xfrm6_input.c +++ b/trunk/net/ipv6/xfrm6_input.c @@ -59,6 +59,9 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto) { struct xfrm_state *x = NULL; + int wildcard = 0; + xfrm_address_t *xany; + int nh = 0; int i = 0; /* Allocate new secpath or COW existing one. */ @@ -80,9 +83,10 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, goto drop; } + xany = (xfrm_address_t *)&in6addr_any; + for (i = 0; i < 3; i++) { xfrm_address_t *dst, *src; - switch (i) { case 0: dst = daddr; @@ -90,13 +94,16 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, break; case 1: /* lookup state with wild-card source address */ + wildcard = 1; dst = daddr; - src = (xfrm_address_t *)&in6addr_any; + src = xany; break; + case 2: default: /* lookup state with wild-card addresses */ - dst = (xfrm_address_t *)&in6addr_any; - src = (xfrm_address_t *)&in6addr_any; + wildcard = 1; /* XXX */ + dst = xany; + src = xany; break; } @@ -106,19 +113,39 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, spin_lock(&x->lock); - if ((!i || (x->props.flags & XFRM_STATE_WILDRECV)) && - likely(x->km.state == XFRM_STATE_VALID) && - !xfrm_state_check_expire(x)) { - spin_unlock(&x->lock); - if (x->type->input(x, skb) > 0) { - /* found a valid state */ - break; + if (wildcard) { + if ((x->props.flags & XFRM_STATE_WILDRECV) == 0) { + spin_unlock(&x->lock); + xfrm_state_put(x); + x = NULL; + continue; } - } else + } + + if (unlikely(x->km.state != XFRM_STATE_VALID)) { + spin_unlock(&x->lock); + xfrm_state_put(x); + x = NULL; + continue; + } + if (xfrm_state_check_expire(x)) { spin_unlock(&x->lock); + xfrm_state_put(x); + x = NULL; + continue; + } + + spin_unlock(&x->lock); + + nh = x->type->input(x, skb); + if (nh <= 0) { + xfrm_state_put(x); + x = NULL; + continue; + } - xfrm_state_put(x); - x = NULL; + /* Found a state */ + break; } if (!x) { diff --git a/trunk/net/ipv6/xfrm6_policy.c b/trunk/net/ipv6/xfrm6_policy.c index d92d1fceb8cf..e96dafdc7032 100644 --- a/trunk/net/ipv6/xfrm6_policy.c +++ b/trunk/net/ipv6/xfrm6_policy.c @@ -58,7 +58,7 @@ static int xfrm6_get_saddr(xfrm_address_t *saddr, xfrm_address_t *daddr) return -EHOSTUNREACH; ipv6_dev_get_saddr(ip6_dst_idev(dst)->dev, - (struct in6_addr *)&daddr->a6, 0, + (struct in6_addr *)&daddr->a6, (struct in6_addr *)&saddr->a6); dst_release(dst); return 0; diff --git a/trunk/net/ipv6/xfrm6_state.c b/trunk/net/ipv6/xfrm6_state.c index 5a46bb99c3af..dc817e035e23 100644 --- a/trunk/net/ipv6/xfrm6_state.c +++ b/trunk/net/ipv6/xfrm6_state.c @@ -49,102 +49,125 @@ __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl, x->props.family = AF_INET6; } -/* distribution counting sort function for xfrm_state and xfrm_tmpl */ static int -__xfrm6_sort(void **dst, void **src, int n, int (*cmp)(void *p), int maxclass) +__xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n) { int i; - int class[XFRM_MAX_DEPTH]; - int count[maxclass]; - - memset(count, 0, sizeof(count)); + int j = 0; + /* Rule 1: select IPsec transport except AH */ for (i = 0; i < n; i++) { - int c; - class[i] = c = cmp(src[i]); - count[c]++; + if (src[i]->props.mode == XFRM_MODE_TRANSPORT && + src[i]->id.proto != IPPROTO_AH) { + dst[j++] = src[i]; + src[i] = NULL; + } } + if (j == n) + goto end; - for (i = 2; i < maxclass; i++) - count[i] += count[i - 1]; + /* Rule 2: select MIPv6 RO or inbound trigger */ +#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) + for (i = 0; i < n; i++) { + if (src[i] && + (src[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION || + src[i]->props.mode == XFRM_MODE_IN_TRIGGER)) { + dst[j++] = src[i]; + src[i] = NULL; + } + } + if (j == n) + goto end; +#endif + /* Rule 3: select IPsec transport AH */ for (i = 0; i < n; i++) { - dst[count[class[i] - 1]++] = src[i]; - src[i] = 0; + if (src[i] && + src[i]->props.mode == XFRM_MODE_TRANSPORT && + src[i]->id.proto == IPPROTO_AH) { + dst[j++] = src[i]; + src[i] = NULL; + } } + if (j == n) + goto end; - return 0; -} + /* 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_BEET)) { + dst[j++] = src[i]; + src[i] = NULL; + } + } + if (likely(j == n)) + goto end; -/* - * Rule for xfrm_state: - * - * rule 1: select IPsec transport except AH - * rule 2: select MIPv6 RO or inbound trigger - * rule 3: select IPsec transport AH - * rule 4: select IPsec tunnel - * rule 5: others - */ -static int __xfrm6_state_sort_cmp(void *p) -{ - struct xfrm_state *v = p; - - switch (v->props.mode) { - case XFRM_MODE_TRANSPORT: - if (v->id.proto != IPPROTO_AH) - return 1; - else - return 3; -#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) - case XFRM_MODE_ROUTEOPTIMIZATION: - case XFRM_MODE_IN_TRIGGER: - return 2; -#endif - case XFRM_MODE_TUNNEL: - case XFRM_MODE_BEET: - return 4; + /* Final rule */ + for (i = 0; i < n; i++) { + if (src[i]) { + dst[j++] = src[i]; + src[i] = NULL; + } } - return 5; + + end: + return 0; } static int -__xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n) +__xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n) { - return __xfrm6_sort((void **)dst, (void **)src, n, - __xfrm6_state_sort_cmp, 6); -} + int i; + int j = 0; -/* - * Rule for xfrm_tmpl: - * - * rule 1: select IPsec transport - * rule 2: select MIPv6 RO or inbound trigger - * rule 3: select IPsec tunnel - * rule 4: others - */ -static int __xfrm6_tmpl_sort_cmp(void *p) -{ - struct xfrm_tmpl *v = p; - switch (v->mode) { - case XFRM_MODE_TRANSPORT: - return 1; + /* Rule 1: select IPsec transport */ + for (i = 0; i < n; i++) { + if (src[i]->mode == XFRM_MODE_TRANSPORT) { + dst[j++] = src[i]; + src[i] = NULL; + } + } + if (j == n) + goto end; + + /* Rule 2: select MIPv6 RO or inbound trigger */ #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) - case XFRM_MODE_ROUTEOPTIMIZATION: - case XFRM_MODE_IN_TRIGGER: - return 2; + for (i = 0; i < n; i++) { + if (src[i] && + (src[i]->mode == XFRM_MODE_ROUTEOPTIMIZATION || + src[i]->mode == XFRM_MODE_IN_TRIGGER)) { + dst[j++] = src[i]; + src[i] = NULL; + } + } + if (j == n) + goto end; #endif - case XFRM_MODE_TUNNEL: - case XFRM_MODE_BEET: - return 3; + + /* 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_BEET)) { + dst[j++] = src[i]; + src[i] = NULL; + } } - return 4; -} + if (likely(j == n)) + goto end; -static int -__xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n) -{ - return __xfrm6_sort((void **)dst, (void **)src, n, - __xfrm6_tmpl_sort_cmp, 5); + /* Final rule */ + for (i = 0; i < n; i++) { + if (src[i]) { + dst[j++] = src[i]; + src[i] = NULL; + } + } + + end: + return 0; } int xfrm6_extract_header(struct sk_buff *skb) diff --git a/trunk/net/ipv6/xfrm6_tunnel.c b/trunk/net/ipv6/xfrm6_tunnel.c index c2b278138604..639fe8a6ff1e 100644 --- a/trunk/net/ipv6/xfrm6_tunnel.c +++ b/trunk/net/ipv6/xfrm6_tunnel.c @@ -140,26 +140,12 @@ __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr) EXPORT_SYMBOL(xfrm6_tunnel_spi_lookup); -static int __xfrm6_tunnel_spi_check(u32 spi) -{ - struct xfrm6_tunnel_spi *x6spi; - int index = xfrm6_tunnel_spi_hash_byspi(spi); - struct hlist_node *pos; - - hlist_for_each_entry(x6spi, pos, - &xfrm6_tunnel_spi_byspi[index], - list_byspi) { - if (x6spi->spi == spi) - return -1; - } - return index; -} - static u32 __xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr) { u32 spi; struct xfrm6_tunnel_spi *x6spi; - int index; + struct hlist_node *pos; + unsigned index; if (xfrm6_tunnel_spi < XFRM6_TUNNEL_SPI_MIN || xfrm6_tunnel_spi >= XFRM6_TUNNEL_SPI_MAX) @@ -168,19 +154,32 @@ static u32 __xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr) xfrm6_tunnel_spi++; for (spi = xfrm6_tunnel_spi; spi <= XFRM6_TUNNEL_SPI_MAX; spi++) { - index = __xfrm6_tunnel_spi_check(spi); - if (index >= 0) - goto alloc_spi; + index = xfrm6_tunnel_spi_hash_byspi(spi); + hlist_for_each_entry(x6spi, pos, + &xfrm6_tunnel_spi_byspi[index], + list_byspi) { + if (x6spi->spi == spi) + goto try_next_1; + } + xfrm6_tunnel_spi = spi; + goto alloc_spi; +try_next_1:; } for (spi = XFRM6_TUNNEL_SPI_MIN; spi < xfrm6_tunnel_spi; spi++) { - index = __xfrm6_tunnel_spi_check(spi); - if (index >= 0) - goto alloc_spi; + index = xfrm6_tunnel_spi_hash_byspi(spi); + hlist_for_each_entry(x6spi, pos, + &xfrm6_tunnel_spi_byspi[index], + list_byspi) { + if (x6spi->spi == spi) + goto try_next_2; + } + xfrm6_tunnel_spi = spi; + goto alloc_spi; +try_next_2:; } spi = 0; goto out; alloc_spi: - xfrm6_tunnel_spi = spi; x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, GFP_ATOMIC); if (!x6spi) goto out; diff --git a/trunk/net/netfilter/core.c b/trunk/net/netfilter/core.c index ec05684c56d7..c4065b8f9a95 100644 --- a/trunk/net/netfilter/core.c +++ b/trunk/net/netfilter/core.c @@ -165,14 +165,6 @@ int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb, unsigned int verdict; int ret = 0; -#ifdef CONFIG_NET_NS - struct net *net; - - net = indev == NULL ? outdev->nd_net : indev->nd_net; - if (net != &init_net) - return 1; -#endif - /* We may already have this, but read-locks nest anyway */ rcu_read_lock(); diff --git a/trunk/net/sctp/ipv6.c b/trunk/net/sctp/ipv6.c index dc71d0d83753..46c5b3c5cb99 100644 --- a/trunk/net/sctp/ipv6.c +++ b/trunk/net/sctp/ipv6.c @@ -316,9 +316,7 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc, if (!asoc) { ipv6_dev_get_saddr(dst ? ip6_dst_idev(dst)->dev : NULL, - &daddr->v6.sin6_addr, - inet6_sk(asoc->base.sk)->srcprefs, - &saddr->v6.sin6_addr); + &daddr->v6.sin6_addr, &saddr->v6.sin6_addr); SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: " NIP6_FMT "\n", NIP6(saddr->v6.sin6_addr)); return; diff --git a/trunk/net/xfrm/xfrm_policy.c b/trunk/net/xfrm/xfrm_policy.c index 8e588f20c60c..bae94a8031a2 100644 --- a/trunk/net/xfrm/xfrm_policy.c +++ b/trunk/net/xfrm/xfrm_policy.c @@ -97,52 +97,25 @@ int xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl, return 0; } -static inline struct dst_entry *__xfrm_dst_lookup(int tos, - xfrm_address_t *saddr, - xfrm_address_t *daddr, - int family) -{ - struct xfrm_policy_afinfo *afinfo; - struct dst_entry *dst; - - afinfo = xfrm_policy_get_afinfo(family); - if (unlikely(afinfo == NULL)) - return ERR_PTR(-EAFNOSUPPORT); - - dst = afinfo->dst_lookup(tos, saddr, daddr); - - xfrm_policy_put_afinfo(afinfo); - - return dst; -} - static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x, int tos, - xfrm_address_t *prev_saddr, - xfrm_address_t *prev_daddr, int family) { xfrm_address_t *saddr = &x->props.saddr; xfrm_address_t *daddr = &x->id.daddr; + struct xfrm_policy_afinfo *afinfo; struct dst_entry *dst; - if (x->type->flags & XFRM_TYPE_LOCAL_COADDR) { + if (x->type->flags & XFRM_TYPE_LOCAL_COADDR) saddr = x->coaddr; - daddr = prev_daddr; - } - if (x->type->flags & XFRM_TYPE_REMOTE_COADDR) { - saddr = prev_saddr; + if (x->type->flags & XFRM_TYPE_REMOTE_COADDR) daddr = x->coaddr; - } - - dst = __xfrm_dst_lookup(tos, saddr, daddr, family); - if (!IS_ERR(dst)) { - if (prev_saddr != saddr) - memcpy(prev_saddr, saddr, sizeof(*prev_saddr)); - if (prev_daddr != daddr) - memcpy(prev_daddr, daddr, sizeof(*prev_daddr)); - } + afinfo = xfrm_policy_get_afinfo(family); + if (unlikely(afinfo == NULL)) + return ERR_PTR(-EAFNOSUPPORT); + dst = afinfo->dst_lookup(tos, saddr, daddr); + xfrm_policy_put_afinfo(afinfo); return dst; } @@ -1381,9 +1354,6 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, int trailer_len = 0; int tos; int family = policy->selector.family; - xfrm_address_t saddr, daddr; - - xfrm_flowi_addr_get(fl, &saddr, &daddr, family); tos = xfrm_get_tos(fl, family); err = tos; @@ -1414,8 +1384,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) { family = xfrm[i]->props.family; - dst = xfrm_dst_lookup(xfrm[i], tos, &saddr, &daddr, - family); + dst = xfrm_dst_lookup(xfrm[i], tos, family); err = PTR_ERR(dst); if (IS_ERR(dst)) goto put_states;