/* * API compat layer * written by Jan Engelhardt , 2008 - 2010 * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License, either * version 2 of the License, or any later version. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "compat_skbuff.h" #include "compat_xtnu.h" #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) # define WITH_IPV6 1 #endif static unsigned int xtnu_target_run(struct sk_buff *skb, const struct xt_action_param *par) { struct xtnu_target *nt = xtcompat_nutarget(par->target); return nt->target(&skb, par); } int xtnu_register_target(struct xtnu_target *nt) { struct xt_target *ct; char *tmp; int ret; ct = kzalloc(sizeof(struct xt_target), GFP_KERNEL); if (ct == NULL) return -ENOMEM; tmp = (char *)ct->name; memcpy(tmp, nt->name, sizeof(nt->name)); tmp = (char *)(ct->name + sizeof(ct->name) - sizeof(void *)); *(tmp-1) = '\0'; memcpy(tmp, &nt, sizeof(void *)); ct->revision = nt->revision; ct->family = nt->family; ct->table = (char *)nt->table; ct->hooks = nt->hooks; ct->proto = nt->proto; ct->target = xtnu_target_run; ct->checkentry = nt->checkentry; ct->destroy = nt->destroy; ct->targetsize = nt->targetsize; ct->me = nt->me; nt->__compat_target = ct; ret = xt_register_target(ct); if (ret != 0) kfree(ct); return ret; } EXPORT_SYMBOL_GPL(xtnu_register_target); int xtnu_register_targets(struct xtnu_target *nt, unsigned int num) { unsigned int i; int ret; for (i = 0; i < num; ++i) { ret = xtnu_register_target(&nt[i]); if (ret < 0) { if (i > 0) xtnu_unregister_targets(nt, i); return ret; } } return 0; } EXPORT_SYMBOL_GPL(xtnu_register_targets); void xtnu_unregister_target(struct xtnu_target *nt) { xt_unregister_target(nt->__compat_target); kfree(nt->__compat_target); } EXPORT_SYMBOL_GPL(xtnu_unregister_target); void xtnu_unregister_targets(struct xtnu_target *nt, unsigned int num) { unsigned int i; for (i = 0; i < num; ++i) xtnu_unregister_target(&nt[i]); } EXPORT_SYMBOL_GPL(xtnu_unregister_targets); struct xt_match *xtnu_request_find_match(unsigned int af, const char *name, uint8_t revision) { static const char *const xt_prefix[] = { [AF_UNSPEC] = "x", [AF_INET] = "ip", [AF_INET6] = "ip6", #ifdef AF_ARP [AF_ARP] = "arp", #elif defined(NF_ARP) && NF_ARP != AF_UNSPEC [NF_ARP] = "arp", #endif }; struct xt_match *match; match = try_then_request_module(xt_find_match(af, name, revision), "%st_%s", xt_prefix[af], name); if (IS_ERR(match) || match == NULL) return NULL; return match; } EXPORT_SYMBOL_GPL(xtnu_request_find_match); int xtnu_ip_route_me_harder(struct sk_buff **pskb, unsigned int addr_type) { return ip_route_me_harder(*pskb, addr_type); } EXPORT_SYMBOL_GPL(xtnu_ip_route_me_harder); int xtnu_skb_make_writable(struct sk_buff **pskb, unsigned int len) { return skb_make_writable(*pskb, len); } EXPORT_SYMBOL_GPL(xtnu_skb_make_writable); void *HX_memmem(const void *space, size_t spacesize, const void *point, size_t pointsize) { size_t i; if (pointsize > spacesize) return NULL; for (i = 0; i <= spacesize - pointsize; ++i) if (memcmp(space + i, point, pointsize) == 0) return (void *)space + i; return NULL; } EXPORT_SYMBOL_GPL(HX_memmem); #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) && defined(WITH_IPV6) int xtnu_ipv6_skip_exthdr(const struct sk_buff *skb, int start, uint8_t *nexthdrp, __be16 *fragoffp) { return ipv6_skip_exthdr(skb, start, nexthdrp); } EXPORT_SYMBOL_GPL(xtnu_ipv6_skip_exthdr); #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) && defined(WITH_IPV6) int xtnu_ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, int target, unsigned short *fragoff, int *fragflg) { return ipv6_find_hdr(skb, offset, target, fragoff); } EXPORT_SYMBOL_GPL(xtnu_ipv6_find_hdr); #endif MODULE_LICENSE("GPL");