--- linux-2.6.25.11/net/ipv4/af_inet.c 2008-04-17 12:05:44.000000000 -0400 +++ linux-2.6.25.11-vs2.3.0.34.14-nobme-noipv6/net/ipv4/af_inet.c 2008-04-19 16:08:42.000000000 -0400 @@ -317,9 +317,12 @@ lookup_protocol: } err = -EPERM; + if ((protocol == IPPROTO_ICMP) && + 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; @@ -433,6 +436,7 @@ int inet_bind(struct socket *sock, struc struct sockaddr_in *addr = (struct sockaddr_in *)uaddr; struct sock *sk = sock->sk; struct inet_sock *inet = inet_sk(sk); + struct nx_v4_sock_addr nsa; unsigned short snum; int chk_addr_ret; int err; @@ -446,7 +450,11 @@ int inet_bind(struct socket *sock, struc if (addr_len < sizeof(struct sockaddr_in)) goto out; - chk_addr_ret = inet_addr_type(&init_net, addr->sin_addr.s_addr); + err = v4_map_sock_addr(inet, addr, &nsa); + if (err) + goto out; + + chk_addr_ret = inet_addr_type(&init_net, nsa.saddr); /* Not specified by any standard per-se, however it breaks too * many applications when removed. It is unfortunate since @@ -458,7 +466,7 @@ int inet_bind(struct socket *sock, struc err = -EADDRNOTAVAIL; if (!sysctl_ip_nonlocal_bind && !inet->freebind && - addr->sin_addr.s_addr != htonl(INADDR_ANY) && + nsa.saddr != htonl(INADDR_ANY) && chk_addr_ret != RTN_LOCAL && chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST) @@ -483,7 +491,7 @@ int inet_bind(struct socket *sock, struc if (sk->sk_state != TCP_CLOSE || inet->num) goto out_release_sock; - inet->rcv_saddr = inet->saddr = addr->sin_addr.s_addr; + v4_set_sock_addr(inet, &nsa); if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST) inet->saddr = 0; /* Use device */ @@ -676,11 +684,13 @@ int inet_getname(struct socket *sock, st peer == 1)) return -ENOTCONN; sin->sin_port = inet->dport; - sin->sin_addr.s_addr = inet->daddr; + sin->sin_addr.s_addr = + nx_map_sock_lback(sk->sk_nx_info, inet->daddr); } else { __be32 addr = inet->rcv_saddr; if (!addr) addr = inet->saddr; + addr = nx_map_sock_lback(sk->sk_nx_info, addr); sin->sin_port = inet->sport; sin->sin_addr.s_addr = addr; } --- linux-2.6.25.11/net/ipv4/devinet.c 2008-04-17 12:05:44.000000000 -0400 +++ linux-2.6.25.11-vs2.3.0.34.14-nobme-noipv6/net/ipv4/devinet.c 2008-04-19 15:14:52.000000000 -0400 @@ -672,6 +672,8 @@ int devinet_ioctl(unsigned int cmd, void *colon = ':'; if ((in_dev = __in_dev_get_rtnl(dev)) != NULL) { + struct nx_info *nxi = current->nx_info; + if (tryaddrmatch) { /* Matthias Andree */ /* compare label and address (4.4BSD style) */ @@ -680,6 +682,8 @@ int devinet_ioctl(unsigned int cmd, void This is checked above. */ for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; ifap = &ifa->ifa_next) { + if (!nx_v4_ifa_visible(nxi, ifa)) + continue; if (!strcmp(ifr.ifr_name, ifa->ifa_label) && sin_orig.sin_addr.s_addr == ifa->ifa_address) { @@ -692,9 +696,12 @@ int devinet_ioctl(unsigned int cmd, void comparing just the label */ if (!ifa) { for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; - ifap = &ifa->ifa_next) + ifap = &ifa->ifa_next) { + if (!nx_v4_ifa_visible(nxi, ifa)) + continue; if (!strcmp(ifr.ifr_name, ifa->ifa_label)) break; + } } } @@ -846,6 +853,8 @@ static int inet_gifconf(struct net_devic goto out; for (; ifa; ifa = ifa->ifa_next) { + if (!nx_v4_ifa_visible(current->nx_info, ifa)) + continue; if (!buf) { done += sizeof(ifr); continue; @@ -1171,6 +1180,7 @@ static int inet_dump_ifaddr(struct sk_bu struct net_device *dev; struct in_device *in_dev; struct in_ifaddr *ifa; + struct sock *sk = skb->sk; int s_ip_idx, s_idx = cb->args[0]; if (net != &init_net) @@ -1188,6 +1198,8 @@ static int inet_dump_ifaddr(struct sk_bu for (ifa = in_dev->ifa_list, ip_idx = 0; ifa; ifa = ifa->ifa_next, ip_idx++) { + if (sk && !nx_v4_ifa_visible(sk->sk_nx_info, ifa)) + continue; if (ip_idx < s_ip_idx) continue; if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid, --- linux-2.6.25.11/net/ipv4/fib_hash.c 2008-04-17 12:05:44.000000000 -0400 +++ linux-2.6.25.11-vs2.3.0.34.14-nobme-noipv6/net/ipv4/fib_hash.c 2008-04-19 15:14:52.000000000 -0400 @@ -1025,7 +1025,7 @@ static int fib_seq_show(struct seq_file prefix = f->fn_key; mask = FZ_MASK(iter->zone); flags = fib_flag_trans(fa->fa_type, mask, fi); - if (fi) + if (fi && nx_dev_visible(current->nx_info, fi->fib_dev)) snprintf(bf, sizeof(bf), "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u", fi->fib_dev ? fi->fib_dev->name : "*", prefix, --- linux-2.6.25.11/net/ipv4/inet_connection_sock.c 2008-04-17 12:05:44.000000000 -0400 +++ linux-2.6.25.11-vs2.3.0.34.14-nobme-noipv6/net/ipv4/inet_connection_sock.c 2008-04-19 15:14:52.000000000 -0400 @@ -47,10 +47,40 @@ void inet_get_local_port_range(int *low, } EXPORT_SYMBOL(inet_get_local_port_range); +int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) +{ + __be32 sk1_rcv_saddr = inet_rcv_saddr(sk1), + sk2_rcv_saddr = inet_rcv_saddr(sk2); + + if (inet_v6_ipv6only(sk2)) + return 0; + + if (sk1_rcv_saddr && + sk2_rcv_saddr && + sk1_rcv_saddr == sk2_rcv_saddr) + return 1; + + if (sk1_rcv_saddr && + !sk2_rcv_saddr && + v4_addr_in_nx_info(sk2->sk_nx_info, sk1_rcv_saddr, NXA_MASK_BIND)) + return 1; + + if (sk2_rcv_saddr && + !sk1_rcv_saddr && + v4_addr_in_nx_info(sk1->sk_nx_info, sk2_rcv_saddr, NXA_MASK_BIND)) + return 1; + + if (!sk1_rcv_saddr && + !sk2_rcv_saddr && + nx_v4_addr_conflict(sk1->sk_nx_info, sk2->sk_nx_info)) + return 1; + + return 0; +} + int inet_csk_bind_conflict(const struct sock *sk, const struct inet_bind_bucket *tb) { - const __be32 sk_rcv_saddr = inet_rcv_saddr(sk); struct sock *sk2; struct hlist_node *node; int reuse = sk->sk_reuse; @@ -63,9 +93,7 @@ int inet_csk_bind_conflict(const struct sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) { if (!reuse || !sk2->sk_reuse || sk2->sk_state == TCP_LISTEN) { - const __be32 sk2_rcv_saddr = inet_rcv_saddr(sk2); - if (!sk2_rcv_saddr || !sk_rcv_saddr || - sk2_rcv_saddr == sk_rcv_saddr) + if (ipv4_rcv_saddr_equal(sk, sk2)) break; } } --- linux-2.6.25.11/net/ipv4/inet_diag.c 2008-04-17 12:05:44.000000000 -0400 +++ linux-2.6.25.11-vs2.3.0.34.14-nobme-noipv6/net/ipv4/inet_diag.c 2008-04-19 16:05:51.000000000 -0400 @@ -122,8 +122,8 @@ static int inet_csk_diag_fill(struct soc r->id.idiag_sport = inet->sport; r->id.idiag_dport = inet->dport; - r->id.idiag_src[0] = inet->rcv_saddr; - r->id.idiag_dst[0] = inet->daddr; + r->id.idiag_src[0] = nx_map_sock_lback(sk->sk_nx_info, inet->rcv_saddr); + r->id.idiag_dst[0] = nx_map_sock_lback(sk->sk_nx_info, inet->daddr); #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) if (r->idiag_family == AF_INET6) { @@ -210,8 +210,8 @@ static int inet_twsk_diag_fill(struct in r->id.idiag_cookie[1] = (u32)(((unsigned long)tw >> 31) >> 1); r->id.idiag_sport = tw->tw_sport; r->id.idiag_dport = tw->tw_dport; - r->id.idiag_src[0] = tw->tw_rcv_saddr; - r->id.idiag_dst[0] = tw->tw_daddr; + r->id.idiag_src[0] = nx_map_sock_lback(tw->tw_nx_info, tw->tw_rcv_saddr); + r->id.idiag_dst[0] = nx_map_sock_lback(tw->tw_nx_info, tw->tw_daddr); r->idiag_state = tw->tw_substate; r->idiag_timer = 3; r->idiag_expires = DIV_ROUND_UP(tmo * 1000, HZ); @@ -268,6 +268,7 @@ static int inet_diag_get_exact(struct sk err = -EINVAL; if (req->idiag_family == AF_INET) { + /* TODO: lback */ sk = inet_lookup(&init_net, hashinfo, req->id.idiag_dst[0], req->id.idiag_dport, req->id.idiag_src[0], req->id.idiag_sport, req->id.idiag_if); @@ -510,6 +511,7 @@ static int inet_csk_diag_dump(struct soc } else #endif { + /* TODO: lback */ entry.saddr = &inet->rcv_saddr; entry.daddr = &inet->daddr; } @@ -546,6 +548,7 @@ static int inet_twsk_diag_dump(struct in } else #endif { + /* TODO: lback */ entry.saddr = &tw->tw_rcv_saddr; entry.daddr = &tw->tw_daddr; } @@ -592,8 +595,8 @@ static int inet_diag_fill_req(struct sk_ r->id.idiag_sport = inet->sport; r->id.idiag_dport = ireq->rmt_port; - r->id.idiag_src[0] = ireq->loc_addr; - r->id.idiag_dst[0] = ireq->rmt_addr; + r->id.idiag_src[0] = nx_map_sock_lback(sk->sk_nx_info, ireq->loc_addr); + r->id.idiag_dst[0] = nx_map_sock_lback(sk->sk_nx_info, ireq->rmt_addr); r->idiag_expires = jiffies_to_msecs(tmo); r->idiag_rqueue = 0; r->idiag_wqueue = 0; @@ -731,6 +734,8 @@ static int inet_diag_dump(struct sk_buff sk_for_each(sk, node, &hashinfo->listening_hash[i]) { struct inet_sock *inet = inet_sk(sk); + if (!nx_check(sk->sk_nid, VS_WATCH_P | VS_IDENT)) + continue; if (num < s_num) { num++; continue; @@ -792,6 +797,8 @@ skip_listen_ht: sk_for_each(sk, node, &head->chain) { struct inet_sock *inet = inet_sk(sk); + if (!nx_check(sk->sk_nid, VS_WATCH_P | VS_IDENT)) + continue; if (num < s_num) goto next_normal; if (!(r->idiag_states & (1 << sk->sk_state))) @@ -816,6 +823,8 @@ next_normal: inet_twsk_for_each(tw, node, &head->twchain) { + if (!nx_check(tw->tw_nid, VS_WATCH_P | VS_IDENT)) + continue; if (num < s_num) goto next_dying; if (r->id.idiag_sport != tw->tw_sport && --- linux-2.6.25.11/net/ipv4/inet_hashtables.c 2008-04-17 12:05:44.000000000 -0400 +++ linux-2.6.25.11-vs2.3.0.34.14-nobme-noipv6/net/ipv4/inet_hashtables.c 2008-04-19 15:14:52.000000000 -0400 @@ -144,11 +144,10 @@ static struct sock *inet_lookup_listener const __be32 rcv_saddr = inet->rcv_saddr; int score = sk->sk_family == PF_INET ? 1 : 0; - if (rcv_saddr) { - if (rcv_saddr != daddr) - continue; + if (v4_inet_addr_match(sk->sk_nx_info, daddr, rcv_saddr)) score += 2; - } + else + continue; if (sk->sk_bound_dev_if) { if (sk->sk_bound_dev_if != dif) continue; @@ -180,7 +179,7 @@ struct sock *__inet_lookup_listener(stru const struct inet_sock *inet = inet_sk((sk = __sk_head(head))); if (inet->num == hnum && !sk->sk_node.next && - (!inet->rcv_saddr || inet->rcv_saddr == daddr) && + v4_inet_addr_match(sk->sk_nx_info, daddr, inet->rcv_saddr) && (sk->sk_family == PF_INET || !ipv6_only_sock(sk)) && !sk->sk_bound_dev_if && sk->sk_net == net) goto sherry_cache; --- linux-2.6.25.11/net/ipv4/raw.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.11-vs2.3.0.34.14-nobme-noipv6/net/ipv4/raw.c 2008-04-29 20:28:52.000000000 -0400 @@ -126,7 +126,7 @@ static struct sock *__raw_v4_lookup(stru if (sk->sk_net == net && inet->num == num && !(inet->daddr && inet->daddr != raddr) && - !(inet->rcv_saddr && inet->rcv_saddr != laddr) && + v4_sock_addr_match(sk->sk_nx_info, inet, laddr) && !(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif)) goto found; /* gotcha */ } @@ -382,6 +382,12 @@ static int raw_send_hdrinc(struct sock * icmp_out_count(((struct icmphdr *) skb_transport_header(skb))->type); + err = -EPERM; + if (!nx_check(0, VS_ADMIN) && !capable(CAP_NET_RAW) && + sk->sk_nx_info && + !v4_addr_in_nx_info(sk->sk_nx_info, iph->saddr, NXA_MASK_BIND)) + goto error_free; + err = NF_HOOK(PF_INET, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev, dst_output); if (err > 0) @@ -393,6 +399,7 @@ out: error_fault: err = -EFAULT; +error_free: kfree_skb(skb); error: IP_INC_STATS(IPSTATS_MIB_OUTDISCARDS); @@ -560,6 +567,13 @@ static int raw_sendmsg(struct kiocb *ioc } security_sk_classify_flow(sk, &fl); + if (sk->sk_nx_info) { + err = ip_v4_find_src(sk->sk_net, + sk->sk_nx_info, &rt, &fl); + + if (err) + goto done; + } err = ip_route_output_flow(&init_net, &rt, &fl, sk, 1); } if (err) @@ -622,17 +636,19 @@ static int raw_bind(struct sock *sk, str { struct inet_sock *inet = inet_sk(sk); struct sockaddr_in *addr = (struct sockaddr_in *) uaddr; + struct nx_v4_sock_addr nsa = { 0 }; int ret = -EINVAL; int chk_addr_ret; if (sk->sk_state != TCP_CLOSE || addr_len < sizeof(struct sockaddr_in)) goto out; - chk_addr_ret = inet_addr_type(sk->sk_net, addr->sin_addr.s_addr); + v4_map_sock_addr(inet, addr, &nsa); + chk_addr_ret = inet_addr_type(sk->sk_net, nsa.saddr); ret = -EADDRNOTAVAIL; - if (addr->sin_addr.s_addr && chk_addr_ret != RTN_LOCAL && + if (nsa.saddr && chk_addr_ret != RTN_LOCAL && chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST) goto out; - inet->rcv_saddr = inet->saddr = addr->sin_addr.s_addr; + v4_set_sock_addr(inet, &nsa); if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST) inet->saddr = 0; /* Use device */ sk_dst_reset(sk); @@ -684,7 +700,8 @@ static int raw_recvmsg(struct kiocb *ioc /* Copy the address. */ if (sin) { sin->sin_family = AF_INET; - sin->sin_addr.s_addr = ip_hdr(skb)->saddr; + sin->sin_addr.s_addr = + nx_map_sock_lback(sk->sk_nx_info, ip_hdr(skb)->saddr); sin->sin_port = 0; memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); } @@ -862,7 +879,8 @@ static struct sock *raw_get_first(struct struct hlist_node *node; sk_for_each(sk, node, &state->h->ht[state->bucket]) - if (sk->sk_net == state->p.net) + if ((sk->sk_net == state->p.net) && + nx_check(sk->sk_nid, VS_WATCH_P | VS_IDENT)) goto found; } sk = NULL; @@ -878,7 +896,8 @@ static struct sock *raw_get_next(struct sk = sk_next(sk); try_again: ; - } while (sk && sk->sk_net != state->p.net); + } while (sk && ((sk->sk_net != state->p.net) || + !nx_check(sk->sk_nid, VS_WATCH_P | VS_IDENT))); if (!sk && ++state->bucket < RAW_HTABLE_SIZE) { sk = sk_head(&state->h->ht[state->bucket]); @@ -937,7 +956,10 @@ static void raw_sock_seq_show(struct seq seq_printf(seq, "%4d: %08X:%04X %08X:%04X" " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %d", - i, src, srcp, dest, destp, sp->sk_state, + i, + nx_map_sock_lback(current_nx_info(), src), srcp, + nx_map_sock_lback(current_nx_info(), dest), destp, + sp->sk_state, atomic_read(&sp->sk_wmem_alloc), atomic_read(&sp->sk_rmem_alloc), 0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp), --- linux-2.6.25.11/net/ipv4/tcp_ipv4.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.11-vs2.3.0.34.14-nobme-noipv6/net/ipv4/tcp_ipv4.c 2008-04-19 15:14:52.000000000 -0400 @@ -1965,6 +1965,12 @@ static void *listening_get_next(struct s req = req->dl_next; while (1) { while (req) { + vxdprintk(VXD_CBIT(net, 6), + "sk,req: %p [#%d] (from %d)", req->sk, + (req->sk)?req->sk->sk_nid:0, nx_current_nid()); + if (req->sk && + !nx_check(req->sk->sk_nid, VS_WATCH_P | VS_IDENT)) + continue; if (req->rsk_ops->family == st->family) { cur = req; goto out; @@ -1989,6 +1995,10 @@ get_req: } get_sk: sk_for_each_from(sk, node) { + vxdprintk(VXD_CBIT(net, 6), "sk: %p [#%d] (from %d)", + sk, sk->sk_nid, nx_current_nid()); + if (!nx_check(sk->sk_nid, VS_WATCH_P | VS_IDENT)) + continue; if (sk->sk_family == st->family) { cur = sk; goto out; @@ -2038,18 +2048,26 @@ static void *established_get_first(struc read_lock_bh(lock); sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) { - if (sk->sk_family != st->family) { + vxdprintk(VXD_CBIT(net, 6), + "sk,egf: %p [#%d] (from %d)", + sk, sk->sk_nid, nx_current_nid()); + if (!nx_check(sk->sk_nid, VS_WATCH_P | VS_IDENT)) + continue; + if (sk->sk_family != st->family) continue; - } rc = sk; goto out; } st->state = TCP_SEQ_STATE_TIME_WAIT; inet_twsk_for_each(tw, node, &tcp_hashinfo.ehash[st->bucket].twchain) { - if (tw->tw_family != st->family) { + vxdprintk(VXD_CBIT(net, 6), + "tw: %p [#%d] (from %d)", + tw, tw->tw_nid, nx_current_nid()); + if (!nx_check(tw->tw_nid, VS_WATCH_P | VS_IDENT)) + continue; + if (tw->tw_family != st->family) continue; - } rc = tw; goto out; } @@ -2073,7 +2091,8 @@ static void *established_get_next(struct tw = cur; tw = tw_next(tw); get_tw: - while (tw && tw->tw_family != st->family) { + while (tw && (tw->tw_family != st->family || + !nx_check(tw->tw_nid, VS_WATCH_P | VS_IDENT))) { tw = tw_next(tw); } if (tw) { @@ -2094,6 +2113,11 @@ get_tw: sk = sk_next(sk); sk_for_each_from(sk, node) { + vxdprintk(VXD_CBIT(net, 6), + "sk,egn: %p [#%d] (from %d)", + sk, sk->sk_nid, nx_current_nid()); + if (!nx_check(sk->sk_nid, VS_WATCH_P | VS_IDENT)) + continue; if (sk->sk_family == st->family) goto found; } @@ -2266,9 +2290,9 @@ static void get_openreq4(struct sock *sk sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X" " %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %p", i, - ireq->loc_addr, + nx_map_sock_lback(current_nx_info(), ireq->loc_addr), ntohs(inet_sk(sk)->sport), - ireq->rmt_addr, + nx_map_sock_lback(current_nx_info(), ireq->rmt_addr), ntohs(ireq->rmt_port), TCP_SYN_RECV, 0, 0, /* could print option size, but that is af dependent. */ @@ -2310,7 +2334,10 @@ static void get_tcp4_sock(struct sock *s sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX " "%08X %5d %8d %lu %d %p %u %u %u %u %d", - i, src, srcp, dest, destp, sk->sk_state, + i, + nx_map_sock_lback(current_nx_info(), src), srcp, + nx_map_sock_lback(current_nx_info(), dest), destp, + sk->sk_state, tp->write_seq - tp->snd_una, sk->sk_state == TCP_LISTEN ? sk->sk_ack_backlog : (tp->rcv_nxt - tp->copied_seq), @@ -2345,7 +2372,10 @@ static void get_timewait4_sock(struct in sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X" " %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p", - i, src, srcp, dest, destp, tw->tw_substate, 0, 0, + i, + nx_map_sock_lback(current_nx_info(), src), srcp, + nx_map_sock_lback(current_nx_info(), dest), destp, + tw->tw_substate, 0, 0, 3, jiffies_to_clock_t(ttd), 0, 0, 0, 0, atomic_read(&tw->tw_refcnt), tw); } --- linux-2.6.25.11/net/ipv4/tcp_minisocks.c 2008-04-17 11:31:40.000000000 -0400 +++ linux-2.6.25.11-vs2.3.0.34.14-nobme-noipv6/net/ipv4/tcp_minisocks.c 2008-04-19 15:14:52.000000000 -0400 @@ -293,6 +293,11 @@ void tcp_time_wait(struct sock *sk, int tcptw->tw_ts_recent = tp->rx_opt.ts_recent; tcptw->tw_ts_recent_stamp = tp->rx_opt.ts_recent_stamp; + tw->tw_xid = sk->sk_xid; + tw->tw_vx_info = NULL; + tw->tw_nid = sk->sk_nid; + tw->tw_nx_info = NULL; + #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) if (tw->tw_family == PF_INET6) { struct ipv6_pinfo *np = inet6_sk(sk); --- linux-2.6.25.11/net/ipv4/udp.c 2008-04-17 12:05:45.000000000 -0400 +++ linux-2.6.25.11-vs2.3.0.34.14-nobme-noipv6/net/ipv4/udp.c 2008-04-21 12:41:01.000000000 -0400 @@ -246,14 +246,7 @@ int udp_get_port(struct sock *sk, unsign return __udp_lib_get_port(sk, snum, udp_hash, scmp); } -int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) -{ - struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2); - - return ( !ipv6_only_sock(sk2) && - (!inet1->rcv_saddr || !inet2->rcv_saddr || - inet1->rcv_saddr == inet2->rcv_saddr )); -} +extern int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2); static inline int udp_v4_get_port(struct sock *sk, unsigned short snum) { @@ -273,16 +266,23 @@ static struct sock *__udp4_lib_lookup(st int badness = -1; read_lock(&udp_hash_lock); + sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) { struct inet_sock *inet = inet_sk(sk); if (sk->sk_net == net && sk->sk_hash == hnum && !ipv6_only_sock(sk)) { int score = (sk->sk_family == PF_INET ? 1 : 0); + if (inet->rcv_saddr) { if (inet->rcv_saddr != daddr) continue; score+=2; + } else { + /* block non nx_info ips */ + if (!v4_addr_in_nx_info(sk->sk_nx_info, + daddr, NXA_MASK_BIND)) + continue; } if (inet->daddr) { if (inet->daddr != saddr) @@ -329,7 +329,7 @@ static inline struct sock *udp_v4_mcast_ if (s->sk_hash != hnum || (inet->daddr && inet->daddr != rmt_addr) || (inet->dport != rmt_port && inet->dport) || - (inet->rcv_saddr && inet->rcv_saddr != loc_addr) || + !v4_sock_addr_match(sk->sk_nx_info, inet, loc_addr) || ipv6_only_sock(s) || (s->sk_bound_dev_if && s->sk_bound_dev_if != dif)) continue; @@ -662,7 +662,15 @@ int udp_sendmsg(struct kiocb *iocb, stru .uli_u = { .ports = { .sport = inet->sport, .dport = dport } } }; + struct nx_info *nxi = sk->sk_nx_info; + struct net *net = sk->sk_net; + security_sk_classify_flow(sk, &fl); + + err = ip_v4_find_src(net, nxi, &rt, &fl); + if (err) + goto out; + err = ip_route_output_flow(&init_net, &rt, &fl, sk, 1); if (err) { if (err == -ENETUNREACH) @@ -905,7 +913,8 @@ try_again: { sin->sin_family = AF_INET; sin->sin_port = udp_hdr(skb)->source; - sin->sin_addr.s_addr = ip_hdr(skb)->saddr; + sin->sin_addr.s_addr = nx_map_sock_lback( + skb->sk->sk_nx_info, ip_hdr(skb)->saddr); memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); } if (inet->cmsg_flags) @@ -1516,7 +1525,8 @@ static struct sock *udp_get_first(struct for (state->bucket = 0; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) { struct hlist_node *node; sk_for_each(sk, node, state->hashtable + state->bucket) { - if (sk->sk_family == state->family) + if (sk->sk_family == state->family && + nx_check(sk->sk_nid, VS_WATCH_P | VS_IDENT)) goto found; } } @@ -1533,7 +1543,8 @@ static struct sock *udp_get_next(struct sk = sk_next(sk); try_again: ; - } while (sk && sk->sk_family != state->family); + } while (sk && (sk->sk_family != state->family || + !nx_check(sk->sk_nid, VS_WATCH_P | VS_IDENT))); if (!sk && ++state->bucket < UDP_HTABLE_SIZE) { sk = sk_head(state->hashtable + state->bucket); @@ -1648,7 +1659,10 @@ static void udp4_format_sock(struct sock sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X" " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p", - bucket, src, srcp, dest, destp, sp->sk_state, + bucket, + nx_map_sock_lback(current_nx_info(), src), srcp, + nx_map_sock_lback(current_nx_info(), dest), destp, + sp->sk_state, atomic_read(&sp->sk_wmem_alloc), atomic_read(&sp->sk_rmem_alloc), 0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp),