[NETNS]: Udp sockets per-net lookup.
Add the net parameter to udp_get_port family of calls and udp_lookup one and use it to filter sockets. Signed-off-by: Pavel Emelyanov <xemul@openvz.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
d86e0dac2c
commit
fa4d3c6210
@ -130,14 +130,14 @@ EXPORT_SYMBOL(sysctl_udp_wmem_min);
|
|||||||
atomic_t udp_memory_allocated;
|
atomic_t udp_memory_allocated;
|
||||||
EXPORT_SYMBOL(udp_memory_allocated);
|
EXPORT_SYMBOL(udp_memory_allocated);
|
||||||
|
|
||||||
static inline int __udp_lib_lport_inuse(__u16 num,
|
static inline int __udp_lib_lport_inuse(struct net *net, __u16 num,
|
||||||
const struct hlist_head udptable[])
|
const struct hlist_head udptable[])
|
||||||
{
|
{
|
||||||
struct sock *sk;
|
struct sock *sk;
|
||||||
struct hlist_node *node;
|
struct hlist_node *node;
|
||||||
|
|
||||||
sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)])
|
sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)])
|
||||||
if (sk->sk_hash == num)
|
if (sk->sk_net == net && sk->sk_hash == num)
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -159,6 +159,7 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
|
|||||||
struct hlist_head *head;
|
struct hlist_head *head;
|
||||||
struct sock *sk2;
|
struct sock *sk2;
|
||||||
int error = 1;
|
int error = 1;
|
||||||
|
struct net *net = sk->sk_net;
|
||||||
|
|
||||||
write_lock_bh(&udp_hash_lock);
|
write_lock_bh(&udp_hash_lock);
|
||||||
|
|
||||||
@ -198,7 +199,7 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
|
|||||||
/* 2nd pass: find hole in shortest hash chain */
|
/* 2nd pass: find hole in shortest hash chain */
|
||||||
rover = best;
|
rover = best;
|
||||||
for (i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++) {
|
for (i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++) {
|
||||||
if (! __udp_lib_lport_inuse(rover, udptable))
|
if (! __udp_lib_lport_inuse(net, rover, udptable))
|
||||||
goto gotit;
|
goto gotit;
|
||||||
rover += UDP_HTABLE_SIZE;
|
rover += UDP_HTABLE_SIZE;
|
||||||
if (rover > high)
|
if (rover > high)
|
||||||
@ -218,6 +219,7 @@ gotit:
|
|||||||
sk_for_each(sk2, node, head)
|
sk_for_each(sk2, node, head)
|
||||||
if (sk2->sk_hash == snum &&
|
if (sk2->sk_hash == snum &&
|
||||||
sk2 != sk &&
|
sk2 != sk &&
|
||||||
|
sk2->sk_net == net &&
|
||||||
(!sk2->sk_reuse || !sk->sk_reuse) &&
|
(!sk2->sk_reuse || !sk->sk_reuse) &&
|
||||||
(!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if
|
(!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if
|
||||||
|| sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
|
|| sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
|
||||||
@ -261,9 +263,9 @@ static inline int udp_v4_get_port(struct sock *sk, unsigned short snum)
|
|||||||
/* UDP is nearly always wildcards out the wazoo, it makes no sense to try
|
/* UDP is nearly always wildcards out the wazoo, it makes no sense to try
|
||||||
* harder than this. -DaveM
|
* harder than this. -DaveM
|
||||||
*/
|
*/
|
||||||
static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport,
|
static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,
|
||||||
__be32 daddr, __be16 dport,
|
__be16 sport, __be32 daddr, __be16 dport,
|
||||||
int dif, struct hlist_head udptable[])
|
int dif, struct hlist_head udptable[])
|
||||||
{
|
{
|
||||||
struct sock *sk, *result = NULL;
|
struct sock *sk, *result = NULL;
|
||||||
struct hlist_node *node;
|
struct hlist_node *node;
|
||||||
@ -274,7 +276,8 @@ static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport,
|
|||||||
sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) {
|
sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) {
|
||||||
struct inet_sock *inet = inet_sk(sk);
|
struct inet_sock *inet = inet_sk(sk);
|
||||||
|
|
||||||
if (sk->sk_hash == hnum && !ipv6_only_sock(sk)) {
|
if (sk->sk_net == net && sk->sk_hash == hnum &&
|
||||||
|
!ipv6_only_sock(sk)) {
|
||||||
int score = (sk->sk_family == PF_INET ? 1 : 0);
|
int score = (sk->sk_family == PF_INET ? 1 : 0);
|
||||||
if (inet->rcv_saddr) {
|
if (inet->rcv_saddr) {
|
||||||
if (inet->rcv_saddr != daddr)
|
if (inet->rcv_saddr != daddr)
|
||||||
@ -361,8 +364,8 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct hlist_head udptable[])
|
|||||||
int harderr;
|
int harderr;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
sk = __udp4_lib_lookup(iph->daddr, uh->dest, iph->saddr, uh->source,
|
sk = __udp4_lib_lookup(skb->dev->nd_net, iph->daddr, uh->dest,
|
||||||
skb->dev->ifindex, udptable );
|
iph->saddr, uh->source, skb->dev->ifindex, udptable);
|
||||||
if (sk == NULL) {
|
if (sk == NULL) {
|
||||||
ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
|
ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
|
||||||
return; /* No socket for error */
|
return; /* No socket for error */
|
||||||
@ -1185,8 +1188,8 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
|
|||||||
if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
|
if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
|
||||||
return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable);
|
return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable);
|
||||||
|
|
||||||
sk = __udp4_lib_lookup(saddr, uh->source, daddr, uh->dest,
|
sk = __udp4_lib_lookup(skb->dev->nd_net, saddr, uh->source, daddr,
|
||||||
inet_iif(skb), udptable);
|
uh->dest, inet_iif(skb), udptable);
|
||||||
|
|
||||||
if (sk != NULL) {
|
if (sk != NULL) {
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
@ -56,7 +56,8 @@ static inline int udp_v6_get_port(struct sock *sk, unsigned short snum)
|
|||||||
return udp_get_port(sk, snum, ipv6_rcv_saddr_equal);
|
return udp_get_port(sk, snum, ipv6_rcv_saddr_equal);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport,
|
static struct sock *__udp6_lib_lookup(struct net *net,
|
||||||
|
struct in6_addr *saddr, __be16 sport,
|
||||||
struct in6_addr *daddr, __be16 dport,
|
struct in6_addr *daddr, __be16 dport,
|
||||||
int dif, struct hlist_head udptable[])
|
int dif, struct hlist_head udptable[])
|
||||||
{
|
{
|
||||||
@ -69,7 +70,8 @@ static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport,
|
|||||||
sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) {
|
sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) {
|
||||||
struct inet_sock *inet = inet_sk(sk);
|
struct inet_sock *inet = inet_sk(sk);
|
||||||
|
|
||||||
if (sk->sk_hash == hnum && sk->sk_family == PF_INET6) {
|
if (sk->sk_net == net && sk->sk_hash == hnum &&
|
||||||
|
sk->sk_family == PF_INET6) {
|
||||||
struct ipv6_pinfo *np = inet6_sk(sk);
|
struct ipv6_pinfo *np = inet6_sk(sk);
|
||||||
int score = 0;
|
int score = 0;
|
||||||
if (inet->dport) {
|
if (inet->dport) {
|
||||||
@ -233,7 +235,7 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
|||||||
struct sock *sk;
|
struct sock *sk;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
sk = __udp6_lib_lookup(daddr, uh->dest,
|
sk = __udp6_lib_lookup(skb->dev->nd_net, daddr, uh->dest,
|
||||||
saddr, uh->source, inet6_iif(skb), udptable);
|
saddr, uh->source, inet6_iif(skb), udptable);
|
||||||
if (sk == NULL)
|
if (sk == NULL)
|
||||||
return;
|
return;
|
||||||
@ -478,7 +480,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
|
|||||||
* check socket cache ... must talk to Alan about his plans
|
* check socket cache ... must talk to Alan about his plans
|
||||||
* for sock caches... i'll skip this for now.
|
* for sock caches... i'll skip this for now.
|
||||||
*/
|
*/
|
||||||
sk = __udp6_lib_lookup(saddr, uh->source,
|
sk = __udp6_lib_lookup(skb->dev->nd_net, saddr, uh->source,
|
||||||
daddr, uh->dest, inet6_iif(skb), udptable);
|
daddr, uh->dest, inet6_iif(skb), udptable);
|
||||||
|
|
||||||
if (sk == NULL) {
|
if (sk == NULL) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user