/* Kernel module to match an IP set. */ #include <linux/module.h> #include <linux/ip.h> #include <linux/skbuff.h> #include <linux/version.h> #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) #include <linux/netfilter_ipv4/ip_tables.h> #define xt_register_match ipt_register_match #define xt_unregister_match ipt_unregister_match #define xt_match ipt_match #else #include <linux/netfilter/x_tables.h> #endif #include <linux/netfilter_ipv4/ip_set.h> #include <linux/netfilter_ipv4/ipt_set.h> #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) #ifndef IPT_ALIGN #define IPT_ALIGN XT_ALIGN #endif #endif static inline int match_set(const struct ipt_set_info *info, const struct sk_buff *skb, int inv) { if (ip_set_testip_kernel(info->index, skb, info->flags)) inv = !inv; return inv; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *matchinfo, int offset, const void *hdr, u_int16_t datalen, int *hotdrop) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *matchinfo, int offset, int *hotdrop) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *matchinfo, int offset, unsigned int protoff, int *hotdrop) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const struct xt_match *match, const void *matchinfo, int offset, unsigned int protoff, int *hotdrop) #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) */ static bool match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const struct xt_match *match, const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop) #endif { const struct ipt_set_info_match *info = matchinfo; return match_set(&info->match_set, skb, info->match_set.flags[0] & IPSET_MATCH_INV); } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) static int checkentry(const char *tablename, const void *inf, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) static int checkentry(const char *tablename, const void *inf, const struct xt_match *match, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) static int checkentry(const char *tablename, const void *inf, const struct xt_match *match, void *matchinfo, unsigned int hook_mask) #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) */ static bool checkentry(const char *tablename, const void *inf, const struct xt_match *match, void *matchinfo, unsigned int hook_mask) #endif { struct ipt_set_info_match *info = matchinfo; ip_set_id_t index; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) if (matchsize != IPT_ALIGN(sizeof(struct ipt_set_info_match))) { ip_set_printk("invalid matchsize %d", matchsize); return 0; } #endif index = ip_set_get_byindex(info->match_set.index); if (index == IP_SET_INVALID_ID) { ip_set_printk("Cannot find set indentified by id %u to match", info->match_set.index); return 0; /* error */ } if (info->match_set.flags[IP_SET_MAX_BINDINGS] != 0) { ip_set_printk("That's nasty!"); return 0; /* error */ } return 1; }
static int ipt_limit_checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { struct ipt_rateinfo *r = matchinfo; if (matchsize != IPT_ALIGN(sizeof(struct ipt_rateinfo))) return 0; /* Check for overflow. */ if (r->burst == 0 || user2credits(r->avg * r->burst) < user2credits(r->avg)) { printk("Overflow in ipt_limit, try lower: %u/%u\n", r->avg, r->burst); return 0; } /* User avg in seconds * IPT_LIMIT_SCALE: convert to jiffies * 128. */ r->prev = jiffies; r->credit = user2credits(r->avg * r->burst); /* Credits full. */ r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */ r->cost = user2credits(r->avg); /* For SMP, we only want to use one set of counters. */ r->master = r; return 1; }
static struct ipt_entry_target * get_dscp_target(unsigned char dscp) { struct ipt_entry_target * target; struct xt_DSCP_info * di; size_t size; size = IPT_ALIGN(sizeof(struct ipt_entry_target)) + IPT_ALIGN(sizeof(struct xt_DSCP_info)); target = calloc(1, size); target->u.target_size = size; strncpy(target->u.user.name, "DSCP", sizeof(target->u.user.name)); /* one ip_nat_range already included in ip_nat_multi_range */ di = (struct xt_DSCP_info *)&target->data[0]; di->dscp=dscp; return target; }
static struct ipt_entry_match * get_udp_match(unsigned short dport) { struct ipt_entry_match *match; struct ipt_udp * udpinfo; size_t size; size = IPT_ALIGN(sizeof(struct ipt_entry_match)) + IPT_ALIGN(sizeof(struct ipt_udp)); match = calloc(1, size); match->u.match_size = size; strncpy(match->u.user.name, "udp", IPT_FUNCTION_MAXNAMELEN); udpinfo = (struct ipt_udp *)match->data; udpinfo->spts[0] = 0; /* all source ports */ udpinfo->spts[1] = 0xFFFF; udpinfo->dpts[0] = dport; /* specified destination port */ udpinfo->dpts[1] = dport; return match; }
/* TODO : add the -m state --state NEW,ESTABLISHED,RELATED * only for the filter rule */ static struct ipt_entry_match * get_tcp_match(unsigned short dport) { struct ipt_entry_match *match; struct ipt_tcp * tcpinfo; size_t size; size = IPT_ALIGN(sizeof(struct ipt_entry_match)) + IPT_ALIGN(sizeof(struct ipt_tcp)); match = calloc(1, size); match->u.match_size = size; strncpy(match->u.user.name, "tcp", sizeof(match->u.user.name)); tcpinfo = (struct ipt_tcp *)match->data; tcpinfo->spts[0] = 0; /* all source ports */ tcpinfo->spts[1] = 0xFFFF; tcpinfo->dpts[0] = dport; /* specified destination port */ tcpinfo->dpts[1] = dport; return match; }
static int check(const char *tablename, const struct ipt_ip *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { if (matchsize != IPT_ALIGN(sizeof(struct ipt_state_info))) return 0; return 1; }
static int checkentry(const char *tablename, const struct ipt_entry *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo; if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ECN_info))) { printk(KERN_WARNING "ECN: targinfosize %u != %Zu\n", targinfosize, IPT_ALIGN(sizeof(struct ipt_ECN_info))); return 0; } if (strcmp(tablename, "mangle") != 0) { printk(KERN_WARNING "ECN: can only be called from \"mangle\" table, not \"%s\"\n", tablename); return 0; } if (einfo->operation & IPT_ECN_OP_MASK) { printk(KERN_WARNING "ECN: unsupported ECN operation %x\n", einfo->operation); return 0; } if (einfo->ip_ect & ~IPT_ECN_IP_MASK) { printk(KERN_WARNING "ECN: new ECT codepoint %x out of mask\n", einfo->ip_ect); return 0; } if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)) && e->ip.proto != IPPROTO_TCP) { printk(KERN_WARNING "ECN: cannot use TCP operations on a " "non-tcp rule\n"); return 0; } return 1; }
static int checkentry(const char *tablename, const struct ipt_entry *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info))) { printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", targinfosize, IPT_ALIGN(sizeof(struct ipt_mark_target_info))); return 0; } if (strcmp(tablename, "mangle") != 0) { printk(KERN_WARNING "MARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename); return 0; } return 1; }
static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { 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 (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) { printk("Matchsize %u != %Zu\n", matchsize, IPT_ALIGN(sizeof(struct ipt_owner_info))); return 0; } return 1; }
static int checkentry(const char *tablename, const struct ipt_entry *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { if (targinfosize != IPT_ALIGN(0)) return 0; return 1; }
static int ipt_led_checkentry(const char *tablename, const struct ipt_entry *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { const struct ipt_led_info *ledinfo = targinfo; if (targinfosize != IPT_ALIGN(sizeof(struct ipt_led_info))) { DEBUGP("LED: targinfosize %u != %u\n", targinfosize, IPT_ALIGN(sizeof(struct ipt_led_info))); return 0; } if (ledinfo->led >= LEDMAN_MAX) { DEBUGP("LED: led %u >= %u\n", ledinfo->led, LEDMAN_MAX); return 0; } return 1; }
/* Kernel module to match an IP set. */ #include <linux/module.h> #include <linux/ip.h> #include <linux/skbuff.h> #include <linux/version.h> #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) #include <linux/netfilter_ipv4/ip_tables.h> #define xt_register_match ipt_register_match #define xt_unregister_match ipt_unregister_match #define xt_match ipt_match #else #include <linux/netfilter/x_tables.h> #endif #include <linux/netfilter_ipv4/ip_set.h> #include <linux/netfilter_ipv4/ipt_set.h> #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) #ifndef IPT_ALIGN #define IPT_ALIGN XT_ALIGN #endif #endif static inline int match_set(const struct ipt_set_info *info, const struct sk_buff *skb, int inv) { if (ip_set_testip_kernel(info->index, skb, info->flags)) inv = !inv; return inv; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *matchinfo, int offset, const void *hdr, u_int16_t datalen, int *hotdrop) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *matchinfo, int offset, int *hotdrop) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *matchinfo, int offset, unsigned int protoff, int *hotdrop) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const struct xt_match *match, const void *matchinfo, int offset, unsigned int protoff, int *hotdrop) #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) */ static bool match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const struct xt_match *match, const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop) #endif { const struct ipt_set_info_match *info = matchinfo; return match_set(&info->match_set, skb, info->match_set.flags[0] & IPSET_MATCH_INV); } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) static int checkentry(const char *tablename, const void *inf, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) static int checkentry(const char *tablename, const void *inf, const struct xt_match *match, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) static int checkentry(const char *tablename, const void *inf, const struct xt_match *match, void *matchinfo, unsigned int hook_mask) #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) */ static bool checkentry(const char *tablename, const void *inf, const struct xt_match *match, void *matchinfo, unsigned int hook_mask) #endif { struct ipt_set_info_match *info = matchinfo; ip_set_id_t index; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) if (matchsize != IPT_ALIGN(sizeof(struct ipt_set_info_match))) { ip_set_printk("invalid matchsize %d", matchsize); return 0; } #endif index = ip_set_get_byindex(info->match_set.index); if (index == IP_SET_INVALID_ID) { ip_set_printk("Cannot find set indentified by id %u to match", info->match_set.index); return 0; /* error */ } if (info->match_set.flags[IP_SET_MAX_BINDINGS] != 0) { ip_set_printk("That's nasty!"); return 0; /* error */ } return 1; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) static void destroy(void *matchinfo, unsigned int matchsize) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) static void destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize) #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) */ static void destroy(const struct xt_match *match, void *matchinfo) #endif { struct ipt_set_info_match *info = matchinfo; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) if (matchsize != IPT_ALIGN(sizeof(struct ipt_set_info_match))) { ip_set_printk("invalid matchsize %d", matchsize); return; } #endif ip_set_put(info->match_set.index); }
static struct ipt_entry_target * get_dnat_target(const char * daddr, unsigned short dport) { struct ipt_entry_target * target; struct ip_nat_multi_range * mr; struct ip_nat_range * range; size_t size; size = IPT_ALIGN(sizeof(struct ipt_entry_target)) + IPT_ALIGN(sizeof(struct ip_nat_multi_range)); target = calloc(1, size); target->u.target_size = size; strncpy(target->u.user.name, "DNAT", IPT_FUNCTION_MAXNAMELEN); /* one ip_nat_range already included in ip_nat_multi_range */ mr = (struct ip_nat_multi_range *)&target->data[0]; mr->rangesize = 1; range = &mr->range[0]; range->min_ip = range->max_ip = inet_addr(daddr); range->flags |= IP_NAT_RANGE_MAP_IPS; range->min.all = range->max.all = htons(dport); range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED; return target; }
static struct ipt_natinfo * append_range(struct ipt_natinfo *info, const struct ip_nat_range *range) { unsigned int size; /* One ip_nat_range already included in ip_nat_multi_range */ size = IPT_ALIGN(sizeof(*info) + info->mr.rangesize * sizeof(*range)); info = realloc(info, size); info->t.u.target_size = size; info->mr.range[info->mr.rangesize] = *range; info->mr.rangesize++; return info; }
static int checkentry(const char *tablename, const struct ipt_entry *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { struct ipt_connmark_target_info *matchinfo = targinfo; if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) { printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n", targinfosize, IPT_ALIGN(sizeof(struct ipt_connmark_target_info))); return 0; } if (matchinfo->mode == IPT_CONNMARK_RESTORE) { if (strcmp(tablename, "mangle") != 0) { printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename); return 0; } } return 1; }
static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { const struct ipt_physdev_info *info = matchinfo; if (matchsize != IPT_ALIGN(sizeof(struct ipt_physdev_info))) return 0; if (!(info->bitmask & IPT_PHYSDEV_OP_MASK) || info->bitmask & ~IPT_PHYSDEV_OP_MASK) return 0; return 1; }
static int check(const char *tablename, const struct ipt_ip *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { struct ipt_helper_info *info = matchinfo; info->name[29] = '\0'; /* verify size */ if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info))) return 0; return 1; }
static struct ipt_natinfo * append_range(struct ipt_natinfo *info, const struct ip_nat_range *range) { unsigned int size; /* One rangesize already in struct ipt_natinfo */ size = IPT_ALIGN(sizeof(*info) + info->mr.rangesize * sizeof(*range)); info = realloc(info, size); if (!info) exit_error(OTHER_PROBLEM, "Out of memory\n"); info->t.u.target_size = size; info->mr.range[info->mr.rangesize] = *range; info->mr.rangesize++; return info; }
static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { struct ipt_mark_info *minfo = (struct ipt_mark_info *) matchinfo; if (matchsize != IPT_ALIGN(sizeof(struct ipt_mark_info))) return 0; if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) { printk(KERN_WARNING "mark: only supports 32bit mark\n"); return 0; } return 1; }
static int checkentry_v1(const char *tablename, const struct ipt_ip *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { const struct ipt_multiport_v1 *multiinfo = matchinfo; /* Must specify supported protocol, no unknown flags or bad count */ return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP || ip->proto == IPPROTO_SCTP) && !(ip->invflags & IPT_INV_PROTO) && matchsize == IPT_ALIGN(sizeof(struct ipt_multiport_v1)) && (multiinfo->flags == IPT_MULTIPORT_SOURCE || multiinfo->flags == IPT_MULTIPORT_DESTINATION || multiinfo->flags == IPT_MULTIPORT_EITHER) && multiinfo->count <= IPT_MULTI_PORTS; }
/* ipt_SET.c - netfilter target to manipulate IP sets */ #include <linux/module.h> #include <linux/ip.h> #include <linux/skbuff.h> #include <linux/version.h> #include <linux/netfilter_ipv4.h> #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) #include <linux/netfilter_ipv4/ip_tables.h> #define xt_register_target ipt_register_target #define xt_unregister_target ipt_unregister_target #define xt_target ipt_target #define XT_CONTINUE IPT_CONTINUE #else #include <linux/netfilter/x_tables.h> #endif #include <linux/netfilter_ipv4/ipt_set.h> static unsigned int #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) target(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in, const struct net_device *out, const void *targinfo, void *userinfo) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) target(struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, unsigned int hooknum, const void *targinfo, void *userinfo) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) target(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, void *userinfo) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) target(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) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) target(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) #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) */ target(struct sk_buff *skb, const struct xt_target_param *par) #endif { #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) const struct ipt_set_info_target *info = targinfo; #else const struct ipt_set_info_target *info = par->targinfo; #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) struct sk_buff *skb = *pskb; #endif if (info->add_set.index != IP_SET_INVALID_ID) ip_set_addip_kernel(info->add_set.index, skb, info->add_set.flags); if (info->del_set.index != IP_SET_INVALID_ID) ip_set_delip_kernel(info->del_set.index, skb, info->del_set.flags); return XT_CONTINUE; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) static int checkentry(const char *tablename, const struct ipt_entry *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) static int checkentry(const char *tablename, const void *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) static int checkentry(const char *tablename, const void *e, const struct xt_target *target, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) static int checkentry(const char *tablename, const void *e, const struct xt_target *target, void *targinfo, unsigned int hook_mask) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) static bool checkentry(const char *tablename, const void *e, const struct xt_target *target, void *targinfo, unsigned int hook_mask) #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) */ static bool checkentry(const struct xt_tgchk_param *par) #endif { #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) const struct ipt_set_info_target *info = targinfo; #else const struct ipt_set_info_target *info = par->targinfo; #endif ip_set_id_t index; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) if (targinfosize != IPT_ALIGN(sizeof(*info))) { DP("bad target info size %u", targinfosize); return 0; } #endif if (info->add_set.index != IP_SET_INVALID_ID) { index = ip_set_get_byindex(info->add_set.index); if (index == IP_SET_INVALID_ID) { ip_set_printk("cannot find add_set index %u as target", info->add_set.index); return 0; /* error */ } } if (info->del_set.index != IP_SET_INVALID_ID) { index = ip_set_get_byindex(info->del_set.index); if (index == IP_SET_INVALID_ID) { ip_set_printk("cannot find del_set index %u as target", info->del_set.index); return 0; /* error */ } } if (info->add_set.flags[IP_SET_MAX_BINDINGS] != 0 || info->del_set.flags[IP_SET_MAX_BINDINGS] != 0) { ip_set_printk("That's nasty!"); return 0; /* error */ } return 1; }
static int check(const char *tablename, const struct ipt_ip *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { if (hook_mask & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_LOCAL_IN))) { printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, " "LOCAL_IN or FORWARD.\n"); return 0; } if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info))) { printk("ipt_realm: invalid matchsize.\n"); return 0; } return 1; }
static int ipt_mac_checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo, unsigned int matchsize, unsigned int hook_mask) { /* FORWARD isn't always valid, but it's nice to be able to do --RR */ if (hook_mask & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD))) { printk("ipt_mac: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n"); return 0; } if (matchsize != IPT_ALIGN(sizeof(struct ipt_mac_info))) return 0; return 1; }
/* ipt_SET.c - netfilter target to manipulate IP sets */ #include <linux/module.h> #include <linux/ip.h> #include <linux/skbuff.h> #include <linux/version.h> #include <linux/netfilter_ipv4.h> #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) #include <linux/netfilter_ipv4/ip_tables.h> #define xt_register_target ipt_register_target #define xt_unregister_target ipt_unregister_target #define xt_target ipt_target #define XT_CONTINUE IPT_CONTINUE #else #include <linux/netfilter/x_tables.h> #endif #include <linux/netfilter_ipv4/ipt_set.h> static unsigned int #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) target(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in, const struct net_device *out, const void *targinfo, void *userinfo) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) target(struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, unsigned int hooknum, const void *targinfo, void *userinfo) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) target(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, void *userinfo) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) target(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) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) target(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) #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) */ target(struct sk_buff *skb, const struct xt_target_param *par) #endif { #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) const struct ipt_set_info_target *info = targinfo; #else const struct ipt_set_info_target *info = par->targinfo; #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) struct sk_buff *skb = *pskb; #endif if (info->add_set.index != IP_SET_INVALID_ID) ip_set_addip_kernel(info->add_set.index, skb, info->add_set.flags); if (info->del_set.index != IP_SET_INVALID_ID) ip_set_delip_kernel(info->del_set.index, skb, info->del_set.flags); return XT_CONTINUE; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) static int checkentry(const char *tablename, const struct ipt_entry *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) static int checkentry(const char *tablename, const void *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) static int checkentry(const char *tablename, const void *e, const struct xt_target *target, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) static int checkentry(const char *tablename, const void *e, const struct xt_target *target, void *targinfo, unsigned int hook_mask) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) static bool checkentry(const char *tablename, const void *e, const struct xt_target *target, void *targinfo, unsigned int hook_mask) #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) */ static bool checkentry(const struct xt_tgchk_param *par) #endif { #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) const struct ipt_set_info_target *info = targinfo; #else const struct ipt_set_info_target *info = par->targinfo; #endif ip_set_id_t index; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) if (targinfosize != IPT_ALIGN(sizeof(*info))) { DP("bad target info size %u", targinfosize); return 0; } #endif if (info->add_set.index != IP_SET_INVALID_ID) { index = ip_set_get_byindex(info->add_set.index); if (index == IP_SET_INVALID_ID) { ip_set_printk("cannot find add_set index %u as target", info->add_set.index); return 0; /* error */ } } if (info->del_set.index != IP_SET_INVALID_ID) { index = ip_set_get_byindex(info->del_set.index); if (index == IP_SET_INVALID_ID) { ip_set_printk("cannot find del_set index %u as target", info->del_set.index); return 0; /* error */ } } if (info->add_set.flags[IP_SET_MAX_BINDINGS] != 0 || info->del_set.flags[IP_SET_MAX_BINDINGS] != 0) { ip_set_printk("That's nasty!"); return 0; /* error */ } return 1; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) static void destroy(void *targetinfo, unsigned int targetsize) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) static void destroy(const struct xt_target *target, void *targetinfo, unsigned int targetsize) #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) static void destroy(const struct xt_target *target, void *targetinfo) #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) */ static void destroy(const struct xt_tgdtor_param *par) #endif { #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) const struct ipt_set_info_target *info = targetinfo; #else const struct ipt_set_info_target *info = par->targinfo; #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) if (targetsize != IPT_ALIGN(sizeof(struct ipt_set_info_target))) { ip_set_printk("invalid targetsize %d", targetsize); return; } #endif if (info->add_set.index != IP_SET_INVALID_ID) ip_set_put_byindex(info->add_set.index); if (info->del_set.index != IP_SET_INVALID_ID) ip_set_put_byindex(info->del_set.index); }
static unsigned char * is_same(const STRUCT_ENTRY *a, const STRUCT_ENTRY *b, unsigned char *matchmask) { unsigned int i; unsigned char *mptr; /* Always compare head structures: ignore mask here. */ if (a->ip.src.s_addr != b->ip.src.s_addr || a->ip.dst.s_addr != b->ip.dst.s_addr || a->ip.smsk.s_addr != b->ip.smsk.s_addr || a->ip.dmsk.s_addr != b->ip.dmsk.s_addr || a->ip.proto != b->ip.proto || a->ip.flags != b->ip.flags || a->ip.invflags != b->ip.invflags) return NULL; for (i = 0; i < IFNAMSIZ; i++) { if (a->ip.iniface_mask[i] != b->ip.iniface_mask[i]) return NULL; if ((a->ip.iniface[i] & a->ip.iniface_mask[i]) != (b->ip.iniface[i] & b->ip.iniface_mask[i])) return NULL; if (a->ip.outiface_mask[i] != b->ip.outiface_mask[i]) return NULL; if ((a->ip.outiface[i] & a->ip.outiface_mask[i]) != (b->ip.outiface[i] & b->ip.outiface_mask[i])) return NULL; } if (a->nfcache != b->nfcache || a->target_offset != b->target_offset || a->next_offset != b->next_offset) return NULL; mptr = matchmask + sizeof(STRUCT_ENTRY); if (IPT_MATCH_ITERATE(a, match_different, a->elems, b->elems, &mptr)) return NULL; mptr += IPT_ALIGN(sizeof(struct ipt_entry_target)); return mptr; }
static int ipt_mirror_checkentry(const char *tablename, const struct ipt_entry *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { /* Only on INPUT, FORWARD or PRE_ROUTING, otherwise loop danger. */ if (hook_mask & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_IN))) { DEBUGP("MIRROR: bad hook\n"); return 0; } if (targinfosize != IPT_ALIGN(0)) { DEBUGP("MIRROR: targinfosize %u != 0\n", targinfosize); return 0; } return 1; }
static int check(const char *tablename, const void *e_void, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { const struct ipt_reject_info *rejinfo = targinfo; const struct ipt_entry *e = e_void; if (targinfosize != IPT_ALIGN(sizeof(struct ipt_reject_info))) { DEBUGP("REJECT: targinfosize %u != 0\n", targinfosize); return 0; } /* Only allow these for packet filtering. */ if (strcmp(tablename, "filter") != 0) { DEBUGP("REJECT: bad table `%s'.\n", tablename); return 0; } if ((hook_mask & ~((1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT))) != 0) { DEBUGP("REJECT: bad hook mask %X\n", hook_mask); return 0; } if (rejinfo->with == IPT_ICMP_ECHOREPLY) { printk("REJECT: ECHOREPLY no longer supported.\n"); return 0; } else if (rejinfo->with == IPT_TCP_RESET) { /* Must specify that it's a TCP packet */ if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) { DEBUGP("REJECT: TCP_RESET invalid for non-tcp\n"); return 0; } } return 1; }
static int ipt_trigger_checkentry(const char *tablename, const struct ipt_entry *e, void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { const struct ipt_trigger_info *triggerinfo = targinfo; if (targinfosize != IPT_ALIGN(sizeof(struct ipt_trigger_info))) { return 0; } if (triggerinfo->timer <= 0 || triggerinfo->timer > 9999 ) { return 0; } if (triggerinfo->process_name[sizeof(triggerinfo->process_name)-1] != '\0') { return 0; } return 1; }
ipt_acct_check_entry (const char *table_name, const struct ipt_entry *entry, void *target_info, unsigned int target_info_size, unsigned int hook_mask) #endif { struct ipt_acct_info *info = (struct ipt_acct_info *) target_info; #if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 19) if (target_info_size != IPT_ALIGN (sizeof (struct ipt_acct_info))) { printk ("ipt_ACCT: wrong target_info_size = %u\n", target_info_size); return 0; } #endif if (info->retcode != IPT_CONTINUE && info->retcode != NF_ACCEPT && info->retcode != NF_DROP) { printk ("ipt_ACCT: wrong retcode = %u\n", info->retcode); return 0; } return 1; }
save(const struct ipt_ip *ip, const struct ipt_entry_match *match) { const struct ipt_rand_info *randinfo = (const struct ipt_rand_info *)match->data; div_t result = div((randinfo->average *100), 255); if (result.rem > 127) /* round up... */ ++result.quot; printf("--average %u ", result.quot); } struct iptables_match rand_match = { .next = NULL, .name = "random", .version = IPTABLES_VERSION, .size = IPT_ALIGN(sizeof(struct ipt_rand_info)), .userspacesize = IPT_ALIGN(sizeof(struct ipt_rand_info)), // .help = &help, .init = &init, .parse = &parse, .final_check = &final_check, .print = &print, .save = &save, .extra_opts = opts }; void _init(void) { register_match(&rand_match); }