XT_MARK_SET=0,
XT_MARK_AND,
XT_MARK_OR,
+ XT_MARK_COPYXID
};
struct xt_mark_target_info_v1 {
--- /dev/null
+#ifndef _XT_SETXID_H_target
+#define _XT_SETXID_H_target
+
+/* Version 1 */
+enum {
+ XT_SET_PACKET_XID=0
+};
+
+struct xt_setxid_target_info_v1 {
+ unsigned long mark;
+ u_int8_t mode;
+};
+
+#endif /*_XT_SETXID_H_target*/
#define ipt_mark_target_info xt_mark_target_info
/* Version 1 */
-#define IPT_MARK_SET XT_MARK_SET
-#define IPT_MARK_AND XT_MARK_AND
-#define IPT_MARK_OR XT_MARK_OR
+#define IPT_MARK_SET XT_MARK_SET
+#define IPT_MARK_AND XT_MARK_AND
+#define IPT_MARK_OR XT_MARK_OR
+#define IPT_MARK_COPYXID XT_MARK_COPYXID
#define ipt_mark_target_info_v1 xt_mark_target_info_v1
--- /dev/null
+#ifndef _IPT_SETXID_H_target
+#define _IPT_SETXID_H_target
+
+/* Backwards compatibility for old userspace */
+
+#include <linux/netfilter/xt_SETXID.h>
+
+/* Version 1 */
+#define IPT_SET_PACKET_XID XT_SET_PACKET_XID
+
+#define ipt_setxid_target_info_v1 xt_setxid_target_info_v1
+
+#endif /*_IPT_SETXID_H_target*/
#define SOL_NETLINK 270
#define SOL_TIPC 271
+#define SO_SETXID SO_PEERCRED
+
/* IPX options */
#define IPX_TYPE 1
}
+#ifdef CONFIG_NETWORK_SECMARK
+#define skb_tag secmark
+#else
+#define skb_tag mark
+#endif
+
#else
#warning duplicate inclusion
#endif
#define vx_capable(b,c) (capable(b) || \
(cap_raised(current->cap_effective,b) && vx_ccaps(c)))
+#define nx_capable(b,c) (capable(b) || \
+ (cap_raised(current->cap_effective,b) && nx_ncaps(c)))
+
#define vx_current_initpid(n) \
(current->vx_info && \
#define NXF_INIT_SET (NXF_STATE_ADMIN)
+/* network caps */
+
+#define NXC_RAW_ICMP 0x00000100
+#define NXC_RAW_SOCKET 0x00000200
+#define NXC_RAW_SEND 0x00000400
+
+
/* address types */
#define NXA_TYPE_IPV4 1
extern struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num,
__be32 raddr, __be32 laddr,
- int dif);
+ int dif, int tag);
extern int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash);
skb->data = data;
skb->tail = data;
skb->end = data + size;
+ skb->skb_tag = nx_current_nid();
/* make sure we initialize shinfo sequentially */
shinfo = skb_shinfo(skb);
atomic_set(&shinfo->dataref, 1);
skb->data = data;
skb->tail = data;
skb->end = data + size;
+ skb->skb_tag = nx_current_nid();
atomic_set(&(skb_shinfo(skb)->dataref), 1);
skb_shinfo(skb)->nr_frags = 0;
C(tail);
C(end);
+ /* Sapan: Cloned skbs aren't owned by anyone. Let the cloner decide who it belongs to. */
+
atomic_inc(&(skb_shinfo(skb)->dataref));
skb->cloned = 1;
new->tc_index = old->tc_index;
#endif
skb_copy_secmark(new, old);
+ new->skb_tag = old->skb_tag;
+
atomic_set(&new->users, 1);
skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size;
skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs;
}
goto set_sndbuf;
+ case SO_SETXID:
+ if (current->xid) {
+ ret = -EPERM;
+ break;
+ }
+ if (val < 0 || val > MAX_S_CONTEXT) {
+ ret = -EINVAL;
+ break;
+ }
+ sk->sk_xid = val;
+ break;
+
case SO_RCVBUF:
/* Don't error on this BSD doesn't and if you think
about it this is right. Otherwise apps have to
char devname[IFNAMSIZ];
/* Sorry... */
- if (!capable(CAP_NET_RAW)) {
+ if (!nx_capable(CAP_NET_RAW, NXC_RAW_SOCKET)) {
ret = -EPERM;
break;
}
len = sizeof(sk->sk_peercred);
if (copy_to_user(optval, &sk->sk_peercred, len))
return -EFAULT;
+
goto lenout;
case SO_PEERNAME:
return -EAGAIN;
}
inet->sport = htons(inet->num);
+ sk->sk_xid = vx_current_xid();
+ sk->sk_nid = nx_current_nid();
}
release_sock(sk);
return 0;
read_lock(&raw_v4_lock);
if ((raw_sk = sk_head(&raw_v4_htable[hash])) != NULL) {
while ((raw_sk = __raw_v4_lookup(raw_sk, protocol, iph->daddr,
- iph->saddr,
- skb->dev->ifindex)) != NULL) {
+ iph->saddr, skb->dev->ifindex,
+ skb->skb_tag)) != NULL) {
raw_err(raw_sk, skb, info);
raw_sk = sk_next(raw_sk);
iph = (struct iphdr *)skb->data;
optptr[2] += 8;
break;
default:
- if (!skb && !capable(CAP_NET_RAW)) {
+ if (!skb && !nx_capable(CAP_NET_RAW, NXC_RAW_SOCKET)) {
pp_ptr = optptr + 3;
goto error;
}
opt->router_alert = optptr - iph;
break;
case IPOPT_CIPSO:
- if ((!skb && !capable(CAP_NET_RAW)) || opt->cipso) {
+ if ((!skb && !nx_capable(CAP_NET_RAW, NXC_RAW_SOCKET)) || opt->cipso) {
pp_ptr = optptr;
goto error;
}
case IPOPT_SEC:
case IPOPT_SID:
default:
- if (!skb && !capable(CAP_NET_RAW)) {
+ if (!skb && !nx_capable(CAP_NET_RAW, NXC_RAW_SOCKET)) {
pp_ptr = optptr;
goto error;
}
else
logflags = NF_LOG_MASK;
+ printk("TAG=%d ", skb->skb_tag);
+
ih = skb_header_pointer(skb, iphoff, sizeof(_iph), &_iph);
if (ih == NULL) {
printk("TRUNCATED");
struct nx_info *nxi,
uint32_t addr,
uint32_t saddr,
- uint32_t baddr)
-{
+ uint32_t baddr,
+ uint32_t tag)
+{
+ vxdprintk(VXD_CBIT(net, 8),
+ "raw_addr_match: %p[#%u] #%d"
+ " %u.%u.%u.%u/%u.%u.%u.%u/%u.%u.%u.%u",
+ nxi, nxi?nxi->nx_id:0, tag,
+ NIPQUAD(addr), NIPQUAD(saddr), NIPQUAD(baddr));
+
+ if (nxi && !((tag == 1) || (nxi->nx_id == tag)))
+ return 0;
if (addr && (saddr == addr || baddr == addr))
return 1;
if (!saddr)
struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num,
__be32 raddr, __be32 laddr,
- int dif)
+ int dif, int tag)
{
struct hlist_node *node;
if (inet->num == num &&
!(inet->daddr && inet->daddr != raddr) &&
raw_addr_match(sk->sk_nx_info, laddr,
- inet->rcv_saddr, inet->rcv_saddr2) &&
+ inet->rcv_saddr, inet->rcv_saddr2, tag) &&
!(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif))
goto found; /* gotcha */
}
goto out;
sk = __raw_v4_lookup(__sk_head(head), iph->protocol,
iph->saddr, iph->daddr,
- skb->dev->ifindex);
+ skb->dev->ifindex, skb->skb_tag);
while (sk) {
delivered = 1;
}
sk = __raw_v4_lookup(sk_next(sk), iph->protocol,
iph->saddr, iph->daddr,
- skb->dev->ifindex);
+ skb->dev->ifindex, skb->skb_tag);
}
out:
read_unlock(&raw_v4_lock);
}
err = -EPERM;
- if (!nx_check(0, VS_ADMIN) && !capable(CAP_NET_RAW)
+ if (!nx_check(0, VS_ADMIN) && !nx_capable(CAP_NET_RAW, NXC_RAW_SOCKET)
&& (!addr_in_nx_info(sk->sk_nx_info, iph->saddr)))
goto error_free;
obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
# targets
+obj-m += xt_SETXID.o
obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o
obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o
obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
+ *
*/
#include <linux/module.h>
+#include <linux/version.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <net/checksum.h>
+#include <net/route.h>
+#include <net/inet_hashtables.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_MARK.h>
MODULE_ALIAS("ipt_MARK");
MODULE_ALIAS("ip6t_MARK");
+static inline u_int16_t
+get_dst_port(struct ip_conntrack_tuple *tuple)
+{
+ switch (tuple->dst.protonum) {
+ case IPPROTO_GRE:
+ /* XXX Truncate 32-bit GRE key to 16 bits */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
+ return tuple->dst.u.gre.key;
+#else
+ return htons(ntohl(tuple->dst.u.gre.key));
+#endif
+ case IPPROTO_ICMP:
+ /* Bind on ICMP echo ID */
+ return tuple->src.u.icmp.id;
+ case IPPROTO_TCP:
+ return tuple->dst.u.tcp.port;
+ case IPPROTO_UDP:
+ return tuple->dst.u.udp.port;
+ default:
+ return tuple->dst.u.all;
+ }
+}
+
+static inline u_int16_t
+get_src_port(struct ip_conntrack_tuple *tuple)
+{
+ switch (tuple->dst.protonum) {
+ case IPPROTO_GRE:
+ /* XXX Truncate 32-bit GRE key to 16 bits */
+ return htons(ntohl(tuple->src.u.gre.key));
+ case IPPROTO_ICMP:
+ /* Bind on ICMP echo ID */
+ return tuple->src.u.icmp.id;
+ case IPPROTO_TCP:
+ return tuple->src.u.tcp.port;
+ case IPPROTO_UDP:
+ return tuple->src.u.udp.port;
+ default:
+ return tuple->src.u.all;
+ }
+}
+
static unsigned int
target_v0(struct sk_buff **pskb,
const struct net_device *in,
const void *targinfo)
{
const struct xt_mark_target_info_v1 *markinfo = targinfo;
- int mark = 0;
+ int mark = -1;
switch (markinfo->mode) {
case XT_MARK_SET:
case XT_MARK_OR:
mark = (*pskb)->mark | markinfo->mark;
break;
+
+ case XT_MARK_COPYXID:
+ {
+ enum ip_conntrack_info ctinfo;
+ struct sock *connection_sk;
+ int dif;
+
+ struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
+ extern struct inet_hashinfo tcp_hashinfo;
+ enum ip_conntrack_dir dir;
+
+ if (!ct)
+ break;
+ dir= CTINFO2DIR(ctinfo);
+ u_int32_t src_ip = ct->tuplehash[dir].tuple.src.ip;
+ u_int16_t src_port = get_src_port(&ct->tuplehash[dir].tuple);
+
+ u_int32_t ip;
+ u_int16_t port;
+
+ dif = ((struct rtable *)(*pskb)->dst)->rt_iif;
+ ip = ct->tuplehash[dir].tuple.dst.ip;
+ port = get_dst_port(&ct->tuplehash[dir].tuple);
+
+ if ((*pskb)->sk)
+ connection_sk = (*pskb)->sk;
+ else {
+ connection_sk = inet_lookup(&tcp_hashinfo, src_ip, src_port, ip, port, dif);
+ }
+
+ if (connection_sk) {
+ /* XXX:
+ connection_sk->sk_peercred.gid = connection_sk->sk_peercred.uid = ct->xid[dir];
+ ct->xid[!dir]=connection_sk->sk_xid;
+ */
+ if (connection_sk->sk_xid != 0)
+ mark = connection_sk->sk_xid;
+ if (connection_sk != (*pskb)->sk)
+ sock_put(connection_sk);
+ }
+ }
+ break;
}
- if((*pskb)->mark != mark)
+ if((*pskb)->mark != mark && mark != -1)
(*pskb)->mark = mark;
return XT_CONTINUE;
if (markinfo->mode != XT_MARK_SET
&& markinfo->mode != XT_MARK_AND
- && markinfo->mode != XT_MARK_OR) {
+ && markinfo->mode != XT_MARK_OR
+ && markinfo->mode != XT_MARK_COPYXID) {
printk(KERN_WARNING "MARK: unknown mode %u\n",
markinfo->mode);
return 0;
--- /dev/null
+/* This is a module which is used for setting the NFMARK field of an skb. */
+
+/* (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <net/checksum.h>
+
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_MARK.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
+MODULE_DESCRIPTION("ip[6]tables MARK modification module");
+MODULE_ALIAS("ipt_MARK");
+MODULE_ALIAS("ip6t_MARK");
+
+static unsigned int
+target_v0(struct sk_buff **pskb,
+ 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_target_info *markinfo = targinfo;
+
+ if((*pskb)->mark != markinfo->mark)
+ (*pskb)->mark = markinfo->mark;
+
+ return XT_CONTINUE;
+}
+
+static unsigned int
+target_v1(struct sk_buff **pskb,
+ 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_target_info_v1 *markinfo = targinfo;
+ int mark = 0;
+
+ switch (markinfo->mode) {
+ case XT_MARK_SET:
+ mark = markinfo->mark;
+ break;
+
+ case XT_MARK_AND:
+ mark = (*pskb)->mark & markinfo->mark;
+ break;
+
+ case XT_MARK_OR:
+ mark = (*pskb)->mark | markinfo->mark;
+ break;
+ }
+
+ if((*pskb)->mark != mark)
+ (*pskb)->mark = mark;
+
+ return XT_CONTINUE;
+}
+
+
+static int
+checkentry_v0(const char *tablename,
+ const void *entry,
+ const struct xt_target *target,
+ void *targinfo,
+ unsigned int hook_mask)
+{
+ struct xt_mark_target_info *markinfo = targinfo;
+
+ if (markinfo->mark > 0xffffffff) {
+ printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
+ return 0;
+ }
+ return 1;
+}
+
+static int
+checkentry_v1(const char *tablename,
+ const void *entry,
+ const struct xt_target *target,
+ void *targinfo,
+ unsigned int hook_mask)
+{
+ struct xt_mark_target_info_v1 *markinfo = targinfo;
+
+ if (markinfo->mode != XT_MARK_SET
+ && markinfo->mode != XT_MARK_AND
+ && markinfo->mode != XT_MARK_OR) {
+ printk(KERN_WARNING "MARK: unknown mode %u\n",
+ markinfo->mode);
+ return 0;
+ }
+ if (markinfo->mark > 0xffffffff) {
+ printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
+ return 0;
+ }
+ return 1;
+}
+
+#ifdef CONFIG_COMPAT
+struct compat_xt_mark_target_info_v1 {
+ compat_ulong_t mark;
+ u_int8_t mode;
+ u_int8_t __pad1;
+ u_int16_t __pad2;
+};
+
+static void compat_from_user_v1(void *dst, void *src)
+{
+ struct compat_xt_mark_target_info_v1 *cm = src;
+ struct xt_mark_target_info_v1 m = {
+ .mark = cm->mark,
+ .mode = cm->mode,
+ };
+ memcpy(dst, &m, sizeof(m));
+}
+
+static int compat_to_user_v1(void __user *dst, void *src)
+{
+ struct xt_mark_target_info_v1 *m = src;
+ struct compat_xt_mark_target_info_v1 cm = {
+ .mark = m->mark,
+ .mode = m->mode,
+ };
+ return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0;
+}
+#endif /* CONFIG_COMPAT */
+
+static struct xt_target xt_mark_target[] = {
+ {
+ .name = "MARK",
+ .family = AF_INET,
+ .revision = 0,
+ .checkentry = checkentry_v0,
+ .target = target_v0,
+ .targetsize = sizeof(struct xt_mark_target_info),
+ .table = "mangle",
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "MARK",
+ .family = AF_INET,
+ .revision = 1,
+ .checkentry = checkentry_v1,
+ .target = target_v1,
+ .targetsize = sizeof(struct xt_mark_target_info_v1),
+#ifdef CONFIG_COMPAT
+ .compatsize = sizeof(struct compat_xt_mark_target_info_v1),
+ .compat_from_user = compat_from_user_v1,
+ .compat_to_user = compat_to_user_v1,
+#endif
+ .table = "mangle",
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "MARK",
+ .family = AF_INET6,
+ .revision = 0,
+ .checkentry = checkentry_v0,
+ .target = target_v0,
+ .targetsize = sizeof(struct xt_mark_target_info),
+ .table = "mangle",
+ .me = THIS_MODULE,
+ },
+};
+
+static int __init xt_mark_init(void)
+{
+ return xt_register_targets(xt_mark_target, ARRAY_SIZE(xt_mark_target));
+}
+
+static void __exit xt_mark_fini(void)
+{
+ xt_unregister_targets(xt_mark_target, ARRAY_SIZE(xt_mark_target));
+}
+
+module_init(xt_mark_init);
+module_exit(xt_mark_fini);
--- /dev/null
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <net/checksum.h>
+#include <linux/vs_network.h>
+
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_SETXID.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("");
+MODULE_DESCRIPTION("");
+MODULE_ALIAS("ipt_SETXID");
+
+static unsigned int
+target_v1(struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ unsigned int hooknum,
+ const struct xt_target *target,
+ const void *targinfo)
+{
+ const struct xt_setxid_target_info_v1 *setxidinfo = targinfo;
+
+ switch (setxidinfo->mode) {
+ case XT_SET_PACKET_XID:
+ (*pskb)->skb_tag = setxidinfo->mark;
+ break;
+ }
+ return XT_CONTINUE;
+}
+
+
+static int
+checkentry_v1(const char *tablename,
+ const void *entry,
+ const struct xt_target *target,
+ void *targinfo,
+ unsigned int hook_mask)
+{
+ struct xt_setxid_target_info_v1 *setxidinfo = targinfo;
+
+ if (setxidinfo->mode != XT_SET_PACKET_XID) {
+ printk(KERN_WARNING "SETXID: unknown mode %u\n",
+ setxidinfo->mode);
+ return 0;
+ }
+
+ return 1;
+}
+
+static struct xt_target xt_setxid_target[] = {
+ {
+ .name = "SETXID",
+ .family = AF_INET,
+ .revision = 1,
+ .checkentry = checkentry_v1,
+ .target = target_v1,
+ .targetsize = sizeof(struct xt_setxid_target_info_v1),
+ .table = "mangle",
+ .me = THIS_MODULE,
+ }
+};
+
+static int __init init(void)
+{
+ int err;
+
+ err = xt_register_targets(xt_setxid_target, ARRAY_SIZE(xt_setxid_target));
+ return err;
+}
+
+static void __exit fini(void)
+{
+ xt_unregister_targets(xt_setxid_target, ARRAY_SIZE(xt_setxid_target));
+}
+
+module_init(init);
+module_exit(fini);
#include <linux/poll.h>
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/vs_network.h>
#ifdef CONFIG_INET
#include <net/inet_common.h>
unsigned int res)
{
struct sk_filter *filter;
+ struct nx_info *nxi = sk->sk_nx_info;
+ int tag = skb->skb_tag;
+
+ vxdprintk(VXD_CBIT(net, 8),
+ "run_filter: %p[#%u] #%d %d",
+ nxi, nxi?nxi->nx_id:0, tag, res);
+
+ if (nxi && !((tag == 1) || (nxi->nx_id == tag)))
+ return 0;
rcu_read_lock_bh();
filter = rcu_dereference(sk->sk_filter);
__be16 proto = (__force __be16)protocol; /* weird, but documented */
int err;
- if (!capable(CAP_NET_RAW))
+ if (!nx_capable(CAP_NET_RAW, NXC_RAW_SEND))
return -EPERM;
if (sock->type != SOCK_DGRAM && sock->type != SOCK_RAW
#ifdef CONFIG_SOCK_PACKET