#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
#include <linux/bitops.h>
#include <linux/compiler.h>
+#include <linux/vserver/context.h>
#include <asm/atomic.h>
enum ip_conntrack_info
} nat;
#endif /* CONFIG_IP_NF_NAT_NEEDED */
+ /* VServer context id */
+ xid_t xid;
+
};
/* get master conntrack via master expectation */
#endif
#endif
+ xid_t xid; /* VServer context ID */
/* These elements must be at the end, see alloc_skb() for details. */
#include <linux/route.h>
#include <linux/ip.h>
#include <linux/cache.h>
-#include <linux/vs_base.h>
-#include <linux/vs_context.h>
-#include <linux/vs_network.h>
#ifndef __KERNEL__
#warning This file is not supposed to be used outside of kernel.
return ip_tos2prio[IPTOS_TOS(tos)>>1];
}
-#define IPI_LOOPBACK 0x0100007f
-
-static inline int ip_find_src(struct nx_info *nxi, struct rtable **rp, struct flowi *fl)
-{
- int err;
- int i, n = nxi->nbipv4;
- u32 ipv4root = nxi->ipv4[0];
-
- if (ipv4root == 0)
- return 0;
-
- if (fl->fl4_src == 0) {
- if (n > 1) {
- u32 foundsrc;
-
- err = __ip_route_output_key(rp, fl);
- if (err) {
- fl->fl4_src = ipv4root;
- err = __ip_route_output_key(rp, fl);
- }
- if (err)
- return err;
-
- foundsrc = (*rp)->rt_src;
- ip_rt_put(*rp);
-
- for (i=0; i<n; i++){
- u32 mask = nxi->mask[i];
- u32 ipv4 = nxi->ipv4[i];
- u32 net4 = ipv4 & mask;
-
- if (foundsrc == ipv4) {
- fl->fl4_src = ipv4;
- break;
- }
- if (!fl->fl4_src && (foundsrc & mask) == net4)
- fl->fl4_src = ipv4;
- }
- }
- if (fl->fl4_src == 0)
- fl->fl4_src = (fl->fl4_dst == IPI_LOOPBACK)
- ? IPI_LOOPBACK : ipv4root;
- } else {
- for (i=0; i<n; i++) {
- if (nxi->ipv4[i] == fl->fl4_src)
- break;
- }
- if (i == n)
- return -EPERM;
- }
- return 0;
-}
-
static inline int ip_route_connect(struct rtable **rp, u32 dst,
u32 src, u32 tos, int oif, u8 protocol,
u16 sport, u16 dport, struct sock *sk)
.dport = dport } } };
int err;
- struct nx_info *nx_info = current->nx_info;
-
- if (sk)
- nx_info = sk->sk_nx_info;
- vxdprintk("ip_route_connect(%p) %p,%p;%lx\n",
- sk, nx_info, sk->sk_socket,
- (sk->sk_socket?sk->sk_socket->flags:0));
-
- if (nx_info) {
- err = ip_find_src(nx_info, rp, &fl);
- if (err)
- return err;
- if (fl.fl4_dst == IPI_LOOPBACK && !vx_check(0, VX_ADMIN))
- fl.fl4_dst = nx_info->ipv4[0];
- }
- if (!fl.fl4_dst || !fl.fl4_src) {
+ if (!dst || !src) {
err = __ip_route_output_key(rp, &fl);
if (err)
return err;
int err = 0;
int skb_len;
+ /* Silently drop if the context is not entitled to read the
+ * packet.
+ */
+ if (sk->sk_xid && sk->sk_xid != skb->xid)
+ goto out;
+
/* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
number of warnings when compiling with -W --ANK
*/
#include <linux/kallsyms.h>
#include <linux/netpoll.h>
#include <linux/rcupdate.h>
-#include <linux/vserver/network.h>
#ifdef CONFIG_NET_RADIO
#include <linux/wireless.h> /* Note : will define WIRELESS_EXT */
#include <net/iw_handler.h>
total = 0;
for (dev = dev_base; dev; dev = dev->next) {
- if (!dev_in_nx_info(dev, current->nx_info))
- continue;
for (i = 0; i < NPROTO; i++) {
if (gifconf_list[i]) {
int done;
static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev)
{
- struct nx_info *nxi = current->nx_info;
-
- if (!dev_in_nx_info(dev, nxi))
- return;
if (dev->get_stats) {
struct net_device_stats *stats = dev->get_stats(dev);
for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++)
printk(" O=0x%8.8X", *opt++);
+ printk(" MARK=%lu (0x%lu)",
+ (long unsigned int)skb->nfmark,
+ (long unsigned int)skb->nfmark);
printk("\n");
}
}
EXPORT_SYMBOL(nf_unregister_hook);
EXPORT_SYMBOL(nf_unregister_queue_handler);
EXPORT_SYMBOL(nf_unregister_sockopt);
+#ifdef CONFIG_NETFILTER_DEBUG
+EXPORT_SYMBOL(nf_dump_skb);
+#endif
for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
if (idx < s_idx)
continue;
- if (!dev_in_nx_info(dev, current->nx_info))
- continue;
if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, 0) <= 0)
break;
}
struct sk_buff *skb;
int size = NLMSG_GOODSIZE;
- if (!dev_in_nx_info(dev, current->nx_info))
- return;
skb = alloc_skb(size, GFP_KERNEL);
if (!skb)
return;
#endif
#endif
+ C(xid);
C(truesize);
atomic_set(&n->users, 1);
C(head);
#endif
new->tc_index = old->tc_index;
#endif
+ new->xid = old->xid;
atomic_set(&new->users, 1);
}
#ifdef CONFIG_IP_MROUTE
#include <linux/mroute.h>
#endif
+#include <linux/vs_base.h>
+#include <linux/vs_context.h>
+#include <linux/vs_network.h>
DEFINE_SNMP_STAT(struct linux_mib, net_statistics);
unsigned short snum;
int chk_addr_ret;
int err;
- __u32 s_addr; /* Address used for validation */
- __u32 s_addr1;
- __u32 s_addr2 = 0xffffffffl; /* Optional address of the socket */
- struct nx_info *nxi = sk->sk_nx_info;
/* If the socket has its own bind function then use it. (RAW) */
if (sk->sk_prot->bind) {
if (addr_len < sizeof(struct sockaddr_in))
goto out;
- s_addr = s_addr1 = addr->sin_addr.s_addr;
- nxdprintk("inet_bind(%p) %p,%p;%lx\n",
- sk, nx_info, sk->sk_socket,
- (sk->sk_socket?sk->sk_socket->flags:0));
- if (nxi) {
- __u32 v4_bcast = nxi->v4_bcast;
- __u32 ipv4root = nxi->ipv4[0];
- int nbipv4 = nxi->nbipv4;
- if (s_addr == 0) {
- s_addr = ipv4root;
- if (nbipv4 > 1)
- s_addr1 = 0;
- else {
- s_addr1 = ipv4root;
- }
- s_addr2 = v4_bcast;
- } else if (s_addr == 0x0100007f) {
- s_addr = s_addr1 = ipv4root;
- } else if (s_addr != v4_bcast) {
- int i;
- for (i=0; i<nbipv4; i++) {
- if (s_addr == nxi->ipv4[i])
- break;
- }
- if (i == nbipv4) {
- return -EADDRNOTAVAIL;
- }
- }
- }
- chk_addr_ret = inet_addr_type(s_addr);
+ chk_addr_ret = inet_addr_type(addr->sin_addr.s_addr);
/* Not specified by any standard per-se, however it breaks too
* many applications when removed. It is unfortunate since
err = -EADDRNOTAVAIL;
if (!sysctl_ip_nonlocal_bind &&
!inet->freebind &&
- s_addr != INADDR_ANY &&
+ addr->sin_addr.s_addr != INADDR_ANY &&
chk_addr_ret != RTN_LOCAL &&
chk_addr_ret != RTN_MULTICAST &&
chk_addr_ret != RTN_BROADCAST)
if (sk->sk_state != TCP_CLOSE || inet->num)
goto out_release_sock;
- inet->rcv_saddr = inet->saddr = s_addr1;
- inet->rcv_saddr2 = s_addr2;
+ inet->rcv_saddr = inet->saddr = addr->sin_addr.s_addr;
if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
inet->saddr = 0; /* Use device */
return rc;
}
-/*
- Check that a device is not member of the ipv4root assigned to the process
- Return true if this is the case
-
- If the process is not bound to specific IP, then it returns 0 (all
- interface are fine).
-*/
-static inline int devinet_notiproot (struct in_ifaddr *ifa)
-{
- int ret = 0;
- struct nx_info *nxi;
-
- if ((nxi = current->nx_info)) {
- int i;
- int nbip = nxi->nbipv4;
- __u32 addr = ifa->ifa_local;
- ret = 1;
- for (i=0; i<nbip; i++) {
- if(nxi->ipv4[i] == addr) {
- ret = 0;
- break;
- }
- }
- }
- return ret;
-}
-
int devinet_ioctl(unsigned int cmd, void __user *arg)
{
ret = -EADDRNOTAVAIL;
if (!ifa && cmd != SIOCSIFADDR && cmd != SIOCSIFFLAGS)
goto done;
- if (!ifa_in_nx_info(ifa, current->nx_info))
- goto done;
switch(cmd) {
case SIOCGIFADDR: /* Get interface address */
goto out;
for (; ifa; ifa = ifa->ifa_next) {
- if (!ifa_in_nx_info(ifa, current->nx_info))
- continue;
if (!buf) {
done += sizeof(ifr);
continue;
read_lock(&in_dev->lock);
for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;
ifa = ifa->ifa_next, ip_idx++) {
- if (!ifa_in_nx_info(ifa, current->nx_info))
- continue;
if (ip_idx < s_ip_idx)
continue;
if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
return flags;
}
-extern int dev_in_nx_info(struct net_device *, struct nx_info *);
-
/*
* This outputs /proc/net/route.
*
mask = FZ_MASK(iter->zone);
flags = fib_flag_trans(f->fn_type, f->fn_state & FN_S_ZOMBIE,
mask, fi);
- if (fi && dev_in_nx_info(fi->fib_dev, current->nx_info))
+ if (fi)
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,
len += sprintf(buffer + len, "[ASSURED] ");
len += sprintf(buffer + len, "use=%u ",
atomic_read(&conntrack->ct_general.use));
+ len += sprintf(buffer + len, "xid=%d ",
+ conntrack->xid);
len += sprintf(buffer + len, "\n");
return len;
return 0;
}
+#if 0
if (strcmp(tablename, "mangle") != 0) {
printk(KERN_WARNING "MARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
return 0;
}
+#endif
return 1;
}
#include <linux/seq_file.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
+#include <linux/vs_base.h>
struct hlist_head raw_v4_htable[RAWV4_HTABLE_SIZE];
rwlock_t raw_v4_lock = RW_LOCK_UNLOCKED;
write_unlock_bh(&raw_v4_lock);
}
-
-/*
- Check if an address is in the list
-*/
-static inline int raw_addr_in_list (
- u32 rcv_saddr1,
- u32 rcv_saddr2,
- u32 loc_addr,
- struct nx_info *nx_info)
-{
- int ret = 0;
- if (loc_addr != 0 &&
- (rcv_saddr1 == loc_addr || rcv_saddr2 == loc_addr))
- ret = 1;
- else if (rcv_saddr1 == 0) {
- /* Accept any address or only the one in the list */
- if (nx_info == NULL)
- ret = 1;
- else {
- int n = nx_info->nbipv4;
- int i;
- for (i=0; i<n; i++) {
- if (nx_info->ipv4[i] == loc_addr) {
- ret = 1;
- break;
- }
- }
- }
- }
- return ret;
-}
-
struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num,
unsigned long raddr, unsigned long laddr,
int dif)
if (inet->num == num &&
!(inet->daddr && inet->daddr != raddr) &&
- raw_addr_in_list(inet->rcv_saddr, inet->rcv_saddr2,
- laddr, sk->sk_nx_info) &&
+ !(inet->rcv_saddr && inet->rcv_saddr != laddr) &&
!(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif))
goto found; /* gotcha */
}
.proto = inet->hdrincl ? IPPROTO_RAW :
sk->sk_protocol,
};
-
- if (sk->sk_nx_info) {
- err = ip_find_src(sk->sk_nx_info, &rt, &fl);
-
- if (err)
- goto done;
- }
err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT));
}
if (err)
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/vs_base.h>
+
extern int sysctl_ip_dynaddr;
int sysctl_tcp_tw_reuse;
int sysctl_tcp_low_latency;
tcp_sk(sk)->bind_hash = tb;
}
-/*
- Return 1 if addr match the socket IP list
- or the socket is INADDR_ANY
-*/
-static inline int tcp_in_list(struct sock *sk, u32 addr)
-{
- struct nx_info *nxi = sk->sk_nx_info;
-
- vxdprintk("tcp_in_list(%p) %p,%p;%lx\n",
- sk, nxi, sk->sk_socket,
- (sk->sk_socket?sk->sk_socket->flags:0));
-
- if (nxi) {
- int n = nxi->nbipv4;
- int i;
-
- for (i=0; i<n; i++)
- if (nxi->ipv4[i] == addr)
- return 1;
- }
- else if (!tcp_v4_rcv_saddr(sk) || tcp_v4_rcv_saddr(sk) == addr)
- return 1;
- return 0;
-}
-
-/*
- Check if the addresses in sk1 conflict with those in sk2
-*/
-int tcp_ipv4_addr_conflict(struct sock *sk1, struct sock *sk2)
-{
- if (sk1 && sk2)
- nxdprintk("inet_bind(%p,%p) %p,%p;%lx %p,%p;%lx\n",
- sk1, sk2,
- sk1->sk_nx_info, sk1->sk_socket,
- (sk1->sk_socket?sk1->sk_socket->flags:0),
- sk2->sk_nx_info, sk2->sk_socket,
- (sk2->sk_socket?sk2->sk_socket->flags:0));
-
- if (tcp_v4_rcv_saddr(sk1)) {
- /* Bind to one address only */
- return tcp_in_list (sk2, tcp_v4_rcv_saddr(sk1));
- } else if (sk1->sk_nx_info) {
- /* A restricted bind(any) */
- struct nx_info *nxi = sk1->sk_nx_info;
- int n = nxi->nbipv4;
- int i;
-
- for (i=0; i<n; i++)
- if (tcp_in_list (sk2, nxi->ipv4[i]))
- return 1;
- } else /* A bind(any) do not allow other bind on the same port */
- return 1;
- return 0;
-}
-
static inline int tcp_bind_conflict(struct sock *sk, struct tcp_bind_bucket *tb)
{
+ const u32 sk_rcv_saddr = tcp_v4_rcv_saddr(sk);
struct sock *sk2;
struct hlist_node *node;
int reuse = sk->sk_reuse;
sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) {
if (!reuse || !sk2->sk_reuse ||
sk2->sk_state == TCP_LISTEN) {
- if (tcp_ipv4_addr_conflict(sk, sk2))
+ const u32 sk2_rcv_saddr = tcp_v4_rcv_saddr(sk2);
+ if (!sk2_rcv_saddr || !sk_rcv_saddr ||
+ sk2_rcv_saddr == sk_rcv_saddr)
break;
}
}
wake_up(&tcp_lhash_wait);
}
-/*
- Check if an address is in the list
-*/
-static inline int tcp_addr_in_list(
- u32 rcv_saddr,
- u32 daddr,
- struct nx_info *nx_info)
-{
- if (rcv_saddr == daddr)
- return 1;
- else if (rcv_saddr == 0) {
- /* Accept any address or check the list */
- if (!nx_info)
- return 1;
- else {
- int n = nx_info->nbipv4;
- int i;
-
- for (i=0; i<n; i++)
- if (nx_info->ipv4[i] == daddr)
- return 1;
- }
- }
- return 0;
-}
-
-
-
/* Don't inline this cruft. Here are some nice properties to
* exploit here. The BSD API does not allow a listening TCP
* to specify the remote port nor the remote address for the
__u32 rcv_saddr = inet->rcv_saddr;
score = (sk->sk_family == PF_INET ? 1 : 0);
- if (tcp_addr_in_list(rcv_saddr, daddr, sk->sk_nx_info))
+ if (rcv_saddr) {
+ if (rcv_saddr != daddr)
+ continue;
score+=2;
- else
- continue;
+ }
if (sk->sk_bound_dev_if) {
if (sk->sk_bound_dev_if != dif)
continue;
if (!hlist_empty(head)) {
struct inet_opt *inet = inet_sk((sk = __sk_head(head)));
if (inet->num == hnum && !sk->sk_node.next &&
+ (!inet->rcv_saddr || inet->rcv_saddr == daddr) &&
(sk->sk_family == PF_INET || !ipv6_only_sock(sk)) &&
- tcp_addr_in_list(inet->rcv_saddr, daddr, sk->sk_nx_info) &&
!sk->sk_bound_dev_if)
goto sherry_cache;
sk = __tcp_v4_lookup_listener(head, daddr, hnum, dif);
goto no_tcp_socket;
process:
+ /* Silently drop if the context is not entitled to read the
+ * packet.
+ */
+ if (sk->sk_xid && sk->sk_xid != skb->xid)
+ goto discard_it;
+
if (sk->sk_state == TCP_TIME_WAIT)
goto do_time_wait;
#include <linux/sysctl.h>
#include <linux/workqueue.h>
#include <linux/vs_socket.h>
+#include <linux/vs_context.h>
+#include <linux/vs_network.h>
#include <net/tcp.h>
#include <net/inet_common.h>
#include <net/xfrm.h>
#include <net/inet_common.h>
#include <net/checksum.h>
#include <net/xfrm.h>
+#include <linux/vs_base.h>
/*
* Snmp MIB for the UDP layer
/* Shared by v4/v6 udp. */
int udp_port_rover;
-int tcp_ipv4_addr_conflict(struct sock *sk1, struct sock *sk2);
-
static int udp_v4_get_port(struct sock *sk, unsigned short snum)
{
struct hlist_node *node;
(!sk2->sk_bound_dev_if ||
!sk->sk_bound_dev_if ||
sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
- tcp_ipv4_addr_conflict(sk2, sk) &&
+ (!inet2->rcv_saddr ||
+ !inet->rcv_saddr ||
+ inet2->rcv_saddr == inet->rcv_saddr) &&
(!sk2->sk_reuse || !sk->sk_reuse))
goto fail;
}
write_unlock_bh(&udp_hash_lock);
}
-static inline int udp_in_list(struct nx_info *nx_info, u32 addr)
-{
- int n = nx_info->nbipv4;
- int i;
-
- for (i=0; i<n; i++)
- if (nx_info->ipv4[i] == addr)
- return 1;
- return 0;
-}
-
/* UDP is nearly always wildcards out the wazoo, it makes no sense to try
* harder than this. -DaveM
*/
if (inet->rcv_saddr != daddr)
continue;
score+=2;
- } else if (sk->sk_nx_info) {
- if (udp_in_list(sk->sk_nx_info, daddr))
- score+=2;
- else
- continue;
}
if (inet->daddr) {
if (inet->daddr != saddr)
if (inet->num != hnum ||
(inet->daddr && inet->daddr != rmt_addr) ||
(inet->dport != rmt_port && inet->dport) ||
- (inet->rcv_saddr && inet->rcv_saddr != loc_addr &&
- inet->rcv_saddr2 && inet->rcv_saddr2 != loc_addr) ||
+ (inet->rcv_saddr && inet->rcv_saddr != loc_addr) ||
ipv6_only_sock(s) ||
(s->sk_bound_dev_if && s->sk_bound_dev_if != dif))
continue;
.uli_u = { .ports =
{ .sport = inet->sport,
.dport = dport } } };
- struct nx_info *nxi = sk->sk_nx_info;
-
- if (nxi) {
- err = ip_find_src(nxi, &rt, &fl);
- if (err)
- goto out;
- if (daddr == IPI_LOOPBACK && !vx_check(0, VX_ADMIN))
- daddr = fl.fl4_dst = nxi->ipv4[0];
- }
err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT));
if (err)
goto out;
#include <linux/poll.h>
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/vs_base.h>
+#include <linux/vs_context.h>
+#include <linux/vs_network.h>
#ifdef CONFIG_INET
#include <net/inet_common.h>
{
BUG_TRAP(!atomic_read(&sk->sk_rmem_alloc));
BUG_TRAP(!atomic_read(&sk->sk_wmem_alloc));
+ BUG_ON(sk->sk_nx_info);
+ BUG_ON(sk->sk_vx_info);
if (!sock_flag(sk, SOCK_DEAD)) {
printk("Attempt to release alive packet socket: %p\n", sk);
sk = pt->af_packet_priv;
po = pkt_sk(sk);
+ if (sk->sk_xid && sk->sk_xid != skb->xid)
+ goto drop;
+
skb->dev = dev;
if (dev->hard_header) {
}
#endif
+ clr_vx_info(&sk->sk_vx_info);
+ clr_nx_info(&sk->sk_nx_info);
+
/*
* Now the socket is dead. No more input will appear.
*/
sk->sk_destruct = packet_sock_destruct;
atomic_inc(&packet_socks_nr);
+ set_vx_info(&sk->sk_vx_info, current->vx_info);
+ sk->sk_xid = vx_current_xid();
+ set_nx_info(&sk->sk_nx_info, current->nx_info);
+ sk->sk_nid = nx_current_nid();
+
/*
* Attach a protocol block
*/
.mmap = packet_mmap,
.sendpage = sock_no_sendpage,
};
+EXPORT_SYMBOL(packet_ops);
-static struct net_proto_family packet_family_ops = {
+struct net_proto_family packet_family_ops = {
.family = PF_PACKET,
.create = packet_create,
.owner = THIS_MODULE,
};
+EXPORT_SYMBOL(packet_family_ops);
static struct notifier_block packet_netdev_notifier = {
.notifier_call =packet_notifier,