diff -ruP linux-2.6.15.1.orig/include/net/udp.h linux-2.6.15.1/include/net/udp.h --- linux-2.6.15.1.orig/include/net/udp.h 2006-01-15 07:16:02.000000000 +0100 +++ linux-2.6.15.1/include/net/udp.h 2006-01-30 00:32:02.000000000 +0100 @@ -74,6 +74,8 @@ extern unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait); +extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif); + DECLARE_SNMP_STAT(struct udp_mib, udp_statistics); #define UDP_INC_STATS(field) SNMP_INC_STATS(udp_statistics, field) #define UDP_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_statistics, field) diff -ruP linux-2.6.15.1.orig/net/ipv4/netfilter/ipt_owner.c linux-2.6.15.1/net/ipv4/netfilter/ipt_owner.c --- linux-2.6.15.1.orig/net/ipv4/netfilter/ipt_owner.c 2006-01-15 07:16:02.000000000 +0100 +++ linux-2.6.15.1/net/ipv4/netfilter/ipt_owner.c 2006-01-30 07:21:01.000000000 +0100 @@ -12,7 +12,14 @@ #include #include #include +#include +#include +#include #include +#include +#include +#include #include #include @@ -30,23 +37,48 @@ int *hotdrop) { const struct ipt_owner_info *info = matchinfo; + struct iphdr *iph = skb->nh.iph; + struct sock *sk = NULL; + int ret = 0; + + if (out) { + sk = skb->sk; + } else { + if (iph->protocol == IPPROTO_TCP) { + struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl); + sk = inet_lookup(&tcp_hashinfo, iph->saddr, tcph->source, iph->daddr, tcph->dest, skb->dev->ifindex); + + if (sk && sk->sk_state == TCP_TIME_WAIT) { + inet_twsk_put((struct inet_timewait_sock *)sk); + return ret; + } + } else if (iph->protocol == IPPROTO_UDP) { + struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl); + sk = udp_v4_lookup(iph->saddr, udph->source, iph->daddr, udph->dest, skb->dev->ifindex); + } + } - if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file) - return 0; + if (!sk || !sk->sk_socket || !sk->sk_socket->file) + goto out; if(info->match & IPT_OWNER_UID) { - if ((skb->sk->sk_socket->file->f_uid != info->uid) ^ + if ((sk->sk_socket->file->f_uid != info->uid) ^ !!(info->invert & IPT_OWNER_UID)) - return 0; + goto out; } if(info->match & IPT_OWNER_GID) { - if ((skb->sk->sk_socket->file->f_gid != info->gid) ^ + if ((sk->sk_socket->file->f_gid != info->gid) ^ !!(info->invert & IPT_OWNER_GID)) - return 0; + goto out; } - return 1; + ret = 1; + +out: + if (in && sk) + sock_put(sk); + return ret; } static int @@ -58,11 +90,19 @@ { const struct ipt_owner_info *info = matchinfo; - if (hook_mask - & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) { - printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n"); - return 0; - } + if (hook_mask + & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING) | + (1 << NF_IP_LOCAL_IN))) { + printk("ipt_owner: only valid for LOCAL_IN, LOCAL_OUT " + "or POST_ROUTING.\n"); + return 0; + } + + if ((hook_mask & (1 << NF_IP_LOCAL_IN)) + && ip->proto != IPPROTO_TCP && ip->proto != IPPROTO_UDP) { + printk("ipt_owner: only TCP or UDP can be used in LOCAL_IN\n"); + return 0; + } if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) { printk("Matchsize %u != %Zu\n", matchsize, diff -ruP linux-2.6.15.1.orig/net/ipv4/udp.c linux-2.6.15.1/net/ipv4/udp.c --- linux-2.6.15.1.orig/net/ipv4/udp.c 2006-01-15 07:16:02.000000000 +0100 +++ linux-2.6.15.1/net/ipv4/udp.c 2006-01-30 00:31:44.000000000 +0100 @@ -265,7 +265,7 @@ return result; } -static __inline__ struct sock *udp_v4_lookup(u32 saddr, u16 sport, +extern __inline__ struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif) { struct sock *sk; @@ -1566,6 +1566,7 @@ EXPORT_SYMBOL(udp_prot); EXPORT_SYMBOL(udp_sendmsg); EXPORT_SYMBOL(udp_poll); +EXPORT_SYMBOL(udp_v4_lookup); #ifdef CONFIG_PROC_FS EXPORT_SYMBOL(udp_proc_register);