-+ struct sock *sk, *result = NULL;
-+ struct hlist_node *node;
-+ unsigned short hnum = ntohs(dport);
-+ 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_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)
-+ continue;
-+ score+=2;
++ struct sock *sk, *result = NULL;
++ struct hlist_node *node;
++ unsigned short hnum = ntohs(dport);
++ int badness = -1;
++
++ read_lock(&udp_hash_lock);
++ sk_for_each(sk, node, &udptable[udp_hashfn(net, hnum)]) {
++ struct inet_sock *inet = inet_sk(sk);
++
++ if (net_eq(sock_net(sk), 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)
++ continue;
++ score+=2;
++ }
++ if (inet->dport) {
++ if (inet->dport != sport)
++ continue;
++ score+=2;
++ }
++ if (sk->sk_bound_dev_if) {
++ if (sk->sk_bound_dev_if != dif)
++ continue;
++ score+=2;
++ }
++ if (score == 9) {
++ result = sk;
++ break;
++ } else if (score > badness) {
++ result = sk;
++ badness = score;
++ }
++ }
++ }
++
++ if (result)
++ sock_hold(result);
++ read_unlock(&udp_hash_lock);
++ return result;
++}
++
++int onceonly = 1;
++
+ static unsigned int
+ mark_tg(struct sk_buff *skb, const struct net_device *in,
+ const struct net_device *out, unsigned int hooknum,
+ const struct xt_target *target, const void *targinfo)
+ {
+ const struct xt_mark_tginfo2 *info = targinfo;
++ long mark = -1;
++ enum ip_conntrack_info ctinfo;
++ struct sock *connection_sk;
++ int dif;
++ struct nf_conn *ct;
++ extern struct inet_hashinfo tcp_hashinfo;
++ enum ip_conntrack_dir dir;
++ int *curtag;
++ u_int32_t src_ip;
++ u_int32_t dst_ip;
++ u_int16_t proto, src_port;
++ u_int32_t ip;
++ u_int16_t port;
++
++
++ if (info->mark == ~0U) {
++ // As of 2.6.27.39, Dec 8 2009,
++ // NetNS + VNET = Trouble
++ // Let's handle this as a special case
++ struct net *net = dev_net(skb->dev);
++ if (!net_eq(net, &init_net)) {
++ WARN_ON(onceonly);
++ onceonly = 0;
++ return XT_CONTINUE;
++ }
++
++ /* copy-xid */
++ dif = ((struct rtable *)(skb->dst))->rt_iif;
++
++ ct = nf_ct_get(skb, &ctinfo);
++ if (!ct)
++ goto out_mark_finish;
++
++ dir = CTINFO2DIR(ctinfo);
++ src_ip = ct->tuplehash[dir].tuple.src.u3.ip;
++ dst_ip = ct->tuplehash[dir].tuple.dst.u3.ip;
++ src_port = get_src_port(&ct->tuplehash[dir].tuple);
++ proto = ct->tuplehash[dir].tuple.dst.protonum;
++
++ ip = ct->tuplehash[dir].tuple.dst.u3.ip;
++ port = get_dst_port(&ct->tuplehash[dir].tuple);
++
++ if (proto == 1) {
++ if (skb->mark > 0)
++ /* The packet is marked, it's going out */
++ ct->xid[0] = skb->mark;
++
++ if (ct->xid[0] > 0)
++ mark = ct->xid[0];
++ }
++ else if (proto == 17) {
++ struct sock *sk;
++ if (!skb->mark) {
++ sk = __udp4_lib_lookup(net,src_ip, src_port,
++ ip, port, dif, udp_hash);
++
++ if (sk && hooknum == NF_INET_LOCAL_IN)
++ mark = sk->sk_nid;
++
++ if (sk)
++ sock_put(sk);