--- linux-2.6.25.10/net/ipv6/addrconf.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/addrconf.c 2008-06-23 16:09:17.000000000 -0400 @@ -87,6 +87,8 @@ #include #include +#include +#include /* Set to 3 to get tracing... */ #define ACONF_DEBUG 2 --- linux-2.6.25.10/net/ipv6/addrconf.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/addrconf.c 2008-06-23 16:09:17.000000000 -0400 @@ -918,7 +920,8 @@ static inline int ipv6_saddr_preferred(i } int ipv6_dev_get_saddr(struct net_device *daddr_dev, - struct in6_addr *daddr, struct in6_addr *saddr) + struct in6_addr *daddr, struct in6_addr *saddr, + struct nx_info *nxi) { struct ipv6_saddr_score hiscore; struct inet6_ifaddr *ifa_result = NULL; --- linux-2.6.25.10/net/ipv6/addrconf.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/addrconf.c 2008-06-23 16:09:17.000000000 -0400 @@ -964,6 +967,10 @@ int ipv6_dev_get_saddr(struct net_device score.addr_type = __ipv6_addr_type(&ifa->addr); + /* Use only addresses assigned to the context */ + if (!v6_ifa_in_nx_info(ifa, nxi)) + continue; + /* Rule 0: * - Tentative Address (RFC2462 section 5.4) * - A tentative address is not considered --- linux-2.6.25.10/net/ipv6/addrconf.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/addrconf.c 2008-06-23 16:09:17.000000000 -0400 @@ -1181,9 +1188,10 @@ record_it: int ipv6_get_saddr(struct dst_entry *dst, - struct in6_addr *daddr, struct in6_addr *saddr) + struct in6_addr *daddr, struct in6_addr *saddr, + struct nx_info *nxi) { - return ipv6_dev_get_saddr(dst ? ip6_dst_idev(dst)->dev : NULL, daddr, saddr); + return ipv6_dev_get_saddr(dst ? ip6_dst_idev(dst)->dev : NULL, daddr, saddr, nxi); } EXPORT_SYMBOL(ipv6_get_saddr); --- linux-2.6.25.10/net/ipv6/addrconf.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/addrconf.c 2008-06-23 16:09:17.000000000 -0400 @@ -1287,6 +1295,8 @@ struct inet6_ifaddr *ipv6_get_ifaddr(str return ifp; } +extern int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2); + int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) { const struct in6_addr *sk_rcv_saddr6 = &inet6_sk(sk)->rcv_saddr; --- linux-2.6.25.10/net/ipv6/addrconf.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/addrconf.c 2008-06-23 16:09:17.000000000 -0400 @@ -1291,7 +1301,6 @@ ***** { const struct in6_addr *sk_rcv_saddr6 = &inet6_sk(sk)->rcv_saddr; const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2); - __be32 sk_rcv_saddr = inet_sk(sk)->rcv_saddr; __be32 sk2_rcv_saddr = inet_rcv_saddr(sk2); int sk_ipv6only = ipv6_only_sock(sk); int sk2_ipv6only = inet_v6_ipv6only(sk2); --- linux-2.6.25.10/net/ipv6/addrconf.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/addrconf.c 2008-06-23 16:09:17.000000000 -0400 @@ -1298,7 +1307,8 @@ ***** int addr_type = ipv6_addr_type(sk_rcv_saddr6); int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED; - if (!sk2_rcv_saddr && !sk_ipv6only) + /* FIXME: needs handling for v4 ANY */ + if (!sk2_rcv_saddr && !sk_ipv6only && !sk2->sk_nx_info) return 1; if (addr_type2 == IPV6_ADDR_ANY && --- linux-2.6.25.10/net/ipv6/addrconf.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/addrconf.c 2008-06-23 16:09:17.000000000 -0400 @@ -1302,7 +1312,8 @@ ***** return 1; if (addr_type2 == IPV6_ADDR_ANY && - !(sk2_ipv6only && addr_type == IPV6_ADDR_MAPPED)) + !(sk2_ipv6only && addr_type == IPV6_ADDR_MAPPED) && + v6_addr_in_nx_info(sk2->sk_nx_info, sk_rcv_saddr6, -1)) return 1; if (addr_type == IPV6_ADDR_ANY && --- linux-2.6.25.10/net/ipv6/addrconf.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/addrconf.c 2008-06-23 16:09:17.000000000 -0400 @@ -1306,7 +1317,13 @@ ***** return 1; if (addr_type == IPV6_ADDR_ANY && - !(sk_ipv6only && addr_type2 == IPV6_ADDR_MAPPED)) + !(sk_ipv6only && addr_type2 == IPV6_ADDR_MAPPED) && + (sk2_rcv_saddr6 && v6_addr_in_nx_info(sk->sk_nx_info, sk2_rcv_saddr6, -1))) + return 1; + + if (addr_type == IPV6_ADDR_ANY && + addr_type2 == IPV6_ADDR_ANY && + nx_v6_addr_conflict(sk->sk_nx_info, sk2->sk_nx_info)) return 1; if (sk2_rcv_saddr6 && --- linux-2.6.25.10/net/ipv6/addrconf.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/addrconf.c 2008-06-23 16:09:17.000000000 -0400 @@ -1310,6 +1327,8 @@ ***** return 1; if (sk2_rcv_saddr6 && + addr_type != IPV6_ADDR_ANY && + addr_type != IPV6_ADDR_ANY && ipv6_addr_equal(sk_rcv_saddr6, sk2_rcv_saddr6)) return 1; --- linux-2.6.25.10/net/ipv6/addrconf.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/addrconf.c 2008-06-23 16:09:17.000000000 -0400 @@ -1315,7 +1334,7 @@ ***** if (addr_type == IPV6_ADDR_MAPPED && !sk2_ipv6only && - (!sk2_rcv_saddr || !sk_rcv_saddr || sk_rcv_saddr == sk2_rcv_saddr)) + ipv4_rcv_saddr_equal(sk, sk2)) return 1; return 0; --- linux-2.6.25.10/net/ipv6/addrconf.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/addrconf.c 2008-06-23 16:09:17.000000000 -0400 @@ -2846,7 +2865,10 @@ static void if6_seq_stop(struct seq_file static int if6_seq_show(struct seq_file *seq, void *v) { struct inet6_ifaddr *ifp = (struct inet6_ifaddr *)v; - seq_printf(seq, + + if (nx_check(0, VS_ADMIN|VS_WATCH) || + v6_addr_in_nx_info(current_nx_info(), &ifp->addr, -1)) + seq_printf(seq, NIP6_SEQFMT " %02x %02x %02x %02x %8s\n", NIP6(ifp->addr), ifp->idev->dev->ifindex, --- linux-2.6.25.10/net/ipv6/addrconf.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/addrconf.c 2008-06-23 16:09:17.000000000 -0400 @@ -3337,6 +3359,11 @@ static int inet6_dump_addr(struct sk_buf struct inet6_ifaddr *ifa; struct ifmcaddr6 *ifmca; struct ifacaddr6 *ifaca; + struct nx_info *nxi = skb->sk ? skb->sk->sk_nx_info : NULL; + + /* disable ipv6 on non v6 guests */ + if (nxi && !nx_info_has_v6(nxi)) + return skb->len; s_idx = cb->args[0]; s_ip_idx = ip_idx = cb->args[1]; --- linux-2.6.25.10/net/ipv6/addrconf.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/addrconf.c 2008-06-23 16:09:17.000000000 -0400 @@ -3358,6 +3385,8 @@ static int inet6_dump_addr(struct sk_buf ifa = ifa->if_next, ip_idx++) { if (ip_idx < s_ip_idx) continue; + if (!v6_addr_in_nx_info(nxi, &ifa->addr, -1)) + continue; err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, --- linux-2.6.25.10/net/ipv6/addrconf.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/addrconf.c 2008-06-23 16:09:17.000000000 -0400 @@ -3371,6 +3400,8 @@ static int inet6_dump_addr(struct sk_buf ifmca = ifmca->next, ip_idx++) { if (ip_idx < s_ip_idx) continue; + if (!v6_addr_in_nx_info(nxi, &ifmca->mca_addr, -1)) + continue; err = inet6_fill_ifmcaddr(skb, ifmca, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, --- linux-2.6.25.10/net/ipv6/addrconf.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/addrconf.c 2008-06-23 16:09:17.000000000 -0400 @@ -3384,6 +3415,8 @@ static int inet6_dump_addr(struct sk_buf ifaca = ifaca->aca_next, ip_idx++) { if (ip_idx < s_ip_idx) continue; + if (!v6_addr_in_nx_info(nxi, &ifaca->aca_addr, -1)) + continue; err = inet6_fill_ifacaddr(skb, ifaca, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, --- linux-2.6.25.10/net/ipv6/addrconf.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/addrconf.c 2008-06-23 16:09:17.000000000 -0400 @@ -3678,6 +3711,11 @@ static int inet6_dump_ifinfo(struct sk_b int s_idx = cb->args[0]; struct net_device *dev; struct inet6_dev *idev; + struct nx_info *nxi = skb->sk ? skb->sk->sk_nx_info : NULL; + + /* FIXME: maybe disable ipv6 on non v6 guests? + if (skb->sk && skb->sk->sk_vx_info) + return skb->len; */ if (net != &init_net) return 0; --- linux-2.6.25.10/net/ipv6/addrconf.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/addrconf.c 2008-06-23 16:09:17.000000000 -0400 @@ -3687,6 +3725,8 @@ static int inet6_dump_ifinfo(struct sk_b for_each_netdev(&init_net, dev) { if (idx < s_idx) goto cont; + if (!v6_dev_in_nx_info(dev, nxi)) + goto cont; if ((idev = in6_dev_get(dev)) == NULL) goto cont; err = inet6_fill_ifinfo(skb, idev, NETLINK_CB(cb->skb).pid, --- linux-2.6.25.10/net/socket.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/socket.c 2008-04-19 15:14:52.000000000 -0400 @@ -1105,6 +1135,13 @@ static int __sock_create(struct net *net if (type < 0 || type >= SOCK_MAX) return -EINVAL; + if (!nx_check(0, VS_ADMIN)) { + if (family == PF_INET && !current_nx_info_has_v4()) + return -EAFNOSUPPORT; + if (family == PF_INET6 && !current_nx_info_has_v6()) + return -EAFNOSUPPORT; + } + /* Compatibility. This uglymoron is moved from INET layer to here to avoid --- linux-2.6.25.10/net/ipv6/af_inet6.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/af_inet6.c 2008-04-19 15:14:52.000000000 -0400 @@ -248,6 +254,7 @@ int inet6_bind(struct socket *sock, stru struct sock *sk = sock->sk; struct inet_sock *inet = inet_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk); + struct nx_v6_sock_addr nsa; __be32 v4addr = 0; unsigned short snum; int addr_type = 0; --- linux-2.6.25.10/net/ipv6/af_inet6.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/af_inet6.c 2008-04-19 15:14:52.000000000 -0400 @@ -307,6 +323,11 @@ int inet6_bind(struct socket *sock, stru } } + if (!v6_addr_in_nx_info(sk->sk_nx_info, &addr->sin6_addr, -1)) { + err = -EADDRNOTAVAIL; + goto out; + } + /* ipv4 addr of the socket is invalid. Only the * unspecified and mapped address have a v4 equivalent. */ --- linux-2.6.25.10/net/ipv6/af_inet6.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/af_inet6.c 2008-04-19 15:14:52.000000000 -0400 @@ -325,6 +346,8 @@ int inet6_bind(struct socket *sock, stru } } + v6_set_sock_addr(inet, &nsa); + inet->rcv_saddr = v4addr; inet->saddr = v4addr; --- linux-2.6.25.10/net/ipv6/af_inet6.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/af_inet6.c 2008-04-19 15:14:52.000000000 -0400 @@ -422,6 +446,7 @@ ***** if (np->sndflow) sin->sin6_flowinfo = np->flow_label; } else { + /* FIXME: remap lback? */ if (ipv6_addr_any(&np->rcv_saddr)) ipv6_addr_copy(&sin->sin6_addr, &np->saddr); else --- linux-2.6.25.10/net/ipv6/inet6_hashtables.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/inet6_hashtables.c 2008-04-19 15:14:52.000000000 -0400 @@ -114,6 +115,9 @@ struct sock *inet6_lookup_listener(struc if (!ipv6_addr_equal(&np->rcv_saddr, daddr)) continue; score++; + } else { + if (!v6_addr_in_nx_info(sk->sk_nx_info, daddr, -1)) + continue; } if (sk->sk_bound_dev_if) { if (sk->sk_bound_dev_if != dif) --- linux-2.6.25.10/net/ipv6/udp.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/udp.c 2008-04-19 15:14:52.000000000 -0400 @@ -83,6 +84,10 @@ static struct sock *__udp6_lib_lookup(st if (!ipv6_addr_equal(&np->rcv_saddr, daddr)) continue; score++; + } else { + /* block non nx_info ips */ + if (!v6_addr_in_nx_info(sk->sk_nx_info, daddr, -1)) + continue; } if (!ipv6_addr_any(&np->daddr)) { if (!ipv6_addr_equal(&np->daddr, saddr)) --- linux-2.6.25.10/net/ipv6/fib6_rules.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/fib6_rules.c 2008-04-19 15:14:52.000000000 -0400 @@ -86,7 +86,7 @@ static int fib6_rule_action(struct fib_r r->src.plen && !(flags & RT6_LOOKUP_F_HAS_SADDR)) { struct in6_addr saddr; if (ipv6_get_saddr(&rt->u.dst, &flp->fl6_dst, - &saddr)) + &saddr, NULL)) goto again; if (!ipv6_prefix_equal(&saddr, &r->src.addr, r->src.plen)) --- linux-2.6.25.10/net/ipv6/xfrm6_policy.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/xfrm6_policy.c 2008-04-19 16:13:21.000000000 -0400 @@ -58,7 +58,7 @@ static int xfrm6_get_saddr(xfrm_address_ return -EHOSTUNREACH; ipv6_get_saddr(dst, (struct in6_addr *)&daddr->a6, - (struct in6_addr *)&saddr->a6); + (struct in6_addr *)&saddr->a6, NULL); dst_release(dst); return 0; } --- linux-2.6.25.10/net/ipv6/route.c 2008-07-11 12:27:04.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/route.c 2008-06-23 15:22:21.000000000 -0400 @@ -2122,7 +2122,7 @@ static int rt6_fill_node(struct sk_buff NLA_PUT_U32(skb, RTA_IIF, iif); else if (dst) { struct in6_addr saddr_buf; - if (ipv6_get_saddr(&rt->u.dst, dst, &saddr_buf) == 0) + if (ipv6_get_saddr(&rt->u.dst, dst, &saddr_buf, (skb->sk ? skb->sk->sk_nx_info : NULL)) == 0) NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); } --- linux-2.6.25.10/net/ipv6/tcp_ipv6.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/tcp_ipv6.c 2008-04-19 15:14:52.000000000 -0400 @@ -154,8 +155,15 @@ static int tcp_v6_connect(struct sock *s * connect() to INADDR_ANY means loopback (BSD'ism). */ - if(ipv6_addr_any(&usin->sin6_addr)) - usin->sin6_addr.s6_addr[15] = 0x1; + if(ipv6_addr_any(&usin->sin6_addr)) { + struct nx_info *nxi = sk->sk_nx_info; + + if (nxi && nx_info_has_v6(nxi)) + /* FIXME: remap lback? */ + usin->sin6_addr = nxi->v6.ip; + else + usin->sin6_addr.s6_addr[15] = 0x1; + } addr_type = ipv6_addr_type(&usin->sin6_addr); --- linux-2.6.25.10/net/ipv6/af_inet6.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/af_inet6.c 2008-04-19 15:14:52.000000000 -0400 @@ -282,6 +294,10 @@ int inet6_bind(struct socket *sock, stru err = -EADDRNOTAVAIL; goto out; } + if (!v4_addr_in_nx_info(sk->sk_nx_info, v4addr, NXA_MASK_BIND)) { + err = -EADDRNOTAVAIL; + goto out; + } } else { if (addr_type != IPV6_ADDR_ANY) { struct net_device *dev = NULL; --- linux-2.6.25.10/net/ipv6/ip6_output.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/ip6_output.c 2008-04-19 15:14:52.000000000 -0400 @@ -920,7 +920,7 @@ static int ip6_dst_lookup_tail(struct so goto out_err_release; if (ipv6_addr_any(&fl->fl6_src)) { - err = ipv6_get_saddr(*dst, &fl->fl6_dst, &fl->fl6_src); + err = ipv6_get_saddr(*dst, &fl->fl6_dst, &fl->fl6_src, sk->sk_nx_info); if (err) goto out_err_release; } --- linux-2.6.25.10/include/linux/vs_inet6.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.25.10-vs2.3.0.34.13.1/include/linux/vs_inet6.h 2008-04-19 15:14:52.000000000 -0400 @@ -0,0 +1,229 @@ +#ifndef _VS_INET6_H +#define _VS_INET6_H + +#include "vserver/base.h" +#include "vserver/network.h" +#include "vserver/debug.h" + +#include + +#define NXAV6(a) NIP6((a)->ip), NIP6((a)->mask), (a)->prefix, (a)->type +#define NXAV6_FMT "[" NIP6_FMT "/" NIP6_FMT "/%d:%04x]" + + +#ifdef CONFIG_IPV6 + +static inline +int v6_addr_match(struct nx_addr_v6 *nxa, + const struct in6_addr *addr, uint16_t mask) +{ + switch (nxa->type & mask) { + case NXA_TYPE_MASK: + return ipv6_masked_addr_cmp(&nxa->ip, &nxa->mask, addr); + case NXA_TYPE_ADDR: + return ipv6_addr_equal(&nxa->ip, addr); + case NXA_TYPE_ANY: + return 1; + default: + return 0; + } +} + +static inline +int v6_addr_in_nx_info(struct nx_info *nxi, + const struct in6_addr *addr, uint16_t mask) +{ + struct nx_addr_v6 *nxa; + + if (!nxi) + return 1; + for (nxa = &nxi->v6; nxa; nxa = nxa->next) + if (v6_addr_match(nxa, addr, mask)) + return 1; + return 0; +} + +static inline +int v6_nx_addr_match(struct nx_addr_v6 *nxa, struct nx_addr_v6 *addr, uint16_t mask) +{ + /* FIXME: needs full range checks */ + return v6_addr_match(nxa, &addr->ip, mask); +} + +static inline +int v6_nx_addr_in_nx_info(struct nx_info *nxi, struct nx_addr_v6 *nxa, uint16_t mask) +{ + struct nx_addr_v6 *ptr; + + for (ptr = &nxi->v6; ptr; ptr = ptr->next) + if (v6_nx_addr_match(ptr, nxa, mask)) + return 1; + return 0; +} + + +/* + * Check if a given address matches for a socket + * + * nxi: the socket's nx_info if any + * addr: to be verified address + */ +static inline +int v6_sock_addr_match ( + struct nx_info *nxi, + struct inet_sock *inet, + struct in6_addr *addr) +{ + struct sock *sk = &inet->sk; + struct in6_addr *saddr = inet6_rcv_saddr(sk); + + if (!ipv6_addr_any(addr) && + ipv6_addr_equal(saddr, addr)) + return 1; + if (ipv6_addr_any(saddr)) + return v6_addr_in_nx_info(nxi, addr, -1); + return 0; +} + +/* + * check if address is covered by socket + * + * sk: the socket to check against + * addr: the address in question (must be != 0) + */ + +static inline +int __v6_addr_match_socket(const struct sock *sk, struct nx_addr_v6 *nxa) +{ + struct nx_info *nxi = sk->sk_nx_info; + struct in6_addr *saddr = inet6_rcv_saddr(sk); + + vxdprintk(VXD_CBIT(net, 5), + "__v6_addr_in_socket(%p," NXAV6_FMT ") %p:" NIP6_FMT " %p;%lx", + sk, NXAV6(nxa), nxi, NIP6(*saddr), sk->sk_socket, + (sk->sk_socket?sk->sk_socket->flags:0)); + + if (!ipv6_addr_any(saddr)) { /* direct address match */ + return v6_addr_match(nxa, saddr, -1); + } else if (nxi) { /* match against nx_info */ + return v6_nx_addr_in_nx_info(nxi, nxa, -1); + } else { /* unrestricted any socket */ + return 1; + } +} + + +/* inet related checks and helpers */ + + +struct in_ifaddr; +struct net_device; +struct sock; + + +#include +#include +#include + + +int dev_in_nx_info(struct net_device *, struct nx_info *); +int v6_dev_in_nx_info(struct net_device *, struct nx_info *); +int nx_v6_addr_conflict(struct nx_info *, struct nx_info *); + + + +static inline +int v6_ifa_in_nx_info(struct inet6_ifaddr *ifa, struct nx_info *nxi) +{ + if (!nxi) + return 1; + if (!ifa) + return 0; + return v6_addr_in_nx_info(nxi, &ifa->addr, -1); +} + +static inline +int nx_v6_ifa_visible(struct nx_info *nxi, struct inet6_ifaddr *ifa) +{ + if (!nx_info_flags(nxi, NXF_HIDE_NETIF, 0)) + return 1; + if (v6_ifa_in_nx_info(ifa, nxi)) + return 1; + return 0; +} + + +struct nx_v6_sock_addr { + struct in6_addr saddr; /* Address used for validation */ + struct in6_addr baddr; /* Address used for socket bind */ +}; + +static inline +int v6_map_sock_addr(struct inet_sock *inet, struct sockaddr_in6 *addr, + struct nx_v6_sock_addr *nsa) +{ + // struct sock *sk = &inet->sk; + // struct nx_info *nxi = sk->sk_nx_info; + struct in6_addr saddr = addr->sin6_addr; + struct in6_addr baddr = saddr; + + nsa->saddr = saddr; + nsa->baddr = baddr; + return 0; +} + +static inline +void v6_set_sock_addr(struct inet_sock *inet, struct nx_v6_sock_addr *nsa) +{ + // struct sock *sk = &inet->sk; + // struct in6_addr *saddr = inet6_rcv_saddr(sk); + + // *saddr = nsa->baddr; + // inet->saddr = nsa->baddr; +} + +static inline +int nx_info_has_v6(struct nx_info *nxi) +{ + if (!nxi) + return 1; + if (NX_IPV6(nxi)) + return 1; + return 0; +} + +#else /* CONFIG_IPV6 */ + +static inline +int nx_v6_dev_visible(struct nx_info *n, struct net_device *d) +{ + return 1; +} + + +static inline +int nx_v6_addr_conflict(struct nx_info *n, uint32_t a, const struct sock *s) +{ + return 1; +} + +static inline +int v6_ifa_in_nx_info(struct in_ifaddr *a, struct nx_info *n) +{ + return 1; +} + +static inline +int nx_info_has_v6(struct nx_info *nxi) +{ + return 0; +} + +#endif /* CONFIG_IPV6 */ + +#define current_nx_info_has_v6() \ + nx_info_has_v6(current_nx_info()) + +#else +#warning duplicate inclusion +#endif --- linux-2.6.25.10/net/sctp/ipv6.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/sctp/ipv6.c 2008-04-19 15:14:52.000000000 -0400 @@ -316,7 +316,7 @@ static void sctp_v6_get_saddr(struct sct __FUNCTION__, asoc, dst, NIP6(daddr->v6.sin6_addr)); if (!asoc) { - ipv6_get_saddr(dst, &daddr->v6.sin6_addr,&saddr->v6.sin6_addr); + ipv6_get_saddr(dst, &daddr->v6.sin6_addr,&saddr->v6.sin6_addr, asoc->base.sk->sk_nx_info); SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: " NIP6_FMT "\n", NIP6(saddr->v6.sin6_addr)); return; --- linux-2.6.25.10/net/ipv6/af_inet6.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/af_inet6.c 2008-04-19 15:14:52.000000000 -0400 @@ -148,9 +151,12 @@ lookup_protocol: } err = -EPERM; + if ((protocol == IPPROTO_ICMPV6) && + nx_capable(answer->capability, NXC_RAW_ICMP)) + goto override; if (answer->capability > 0 && !capable(answer->capability)) goto out_rcu_unlock; - +override: sock->ops = answer->ops; answer_prot = answer->prot; answer_no_check = answer->no_check; --- linux-2.6.25.10/include/net/addrconf.h 2008-04-17 12:05:44.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/include/net/addrconf.h 2008-04-19 15:14:52.000000000 -0400 @@ -75,10 +75,12 @@ extern struct inet6_ifaddr *ipv6_ge extern int ipv6_get_saddr(struct dst_entry *dst, struct in6_addr *daddr, - struct in6_addr *saddr); + struct in6_addr *saddr, + struct nx_info *nxi); extern int ipv6_dev_get_saddr(struct net_device *dev, struct in6_addr *daddr, - struct in6_addr *saddr); + struct in6_addr *saddr, + struct nx_info *nxi); extern int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, unsigned char banned_flags); --- linux-2.6.25.10/net/ipv6/ndisc.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/ndisc.c 2008-04-19 15:14:52.000000000 -0400 @@ -563,7 +563,7 @@ static void ndisc_send_na(struct net_dev override = 0; in6_ifa_put(ifp); } else { - if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr)) + if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr, NULL)) return; src_addr = &tmpaddr; } --- linux-2.6.25.10/net/ipv6/Kconfig 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/Kconfig 2008-04-19 15:14:52.000000000 -0400 @@ -4,8 +4,8 @@ # IPv6 as module will cause a CRASH if you try to unload it config IPV6 - tristate "The IPv6 protocol" - default m + bool "The IPv6 protocol" + default n ---help--- This is complemental support for the IP version 6. You will still be able to do traditional IPv4 networking as well. --- linux-2.6.25.10/net/ipv6/af_inet6.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/af_inet6.c 2008-04-19 15:14:52.000000000 -0400 @@ -259,6 +266,11 @@ int inet6_bind(struct socket *sock, stru if (addr_len < SIN6_LEN_RFC2133) return -EINVAL; + + err = v6_map_sock_addr(inet, addr, &nsa); + if (err) + return err; + addr_type = ipv6_addr_type(&addr->sin6_addr); if ((addr_type & IPV6_ADDR_MULTICAST) && sock->type == SOCK_STREAM) return -EINVAL; --- linux-2.6.25.10/net/ipv6/af_inet6.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.10-vs2.3.0.34.13.1/net/ipv6/af_inet6.c 2008-04-19 15:14:52.000000000 -0400 @@ -419,6 +442,7 @@ int inet6_getname(struct socket *sock, s return -ENOTCONN; sin->sin6_port = inet->dport; ipv6_addr_copy(&sin->sin6_addr, &np->daddr); + /* FIXME: remap lback? */ if (np->sndflow) sin->sin6_flowinfo = np->flow_label; } else {