1/* Kernel module to match AH parameters. */ 2#include <linux/module.h> 3#include <linux/skbuff.h> 4 5#include <linux/netfilter_ipv4/ipt_ah.h> 6#include <linux/netfilter_ipv4/ip_tables.h> 7 8EXPORT_NO_SYMBOLS; 9MODULE_LICENSE("GPL"); 10 11#ifdef DEBUG_CONNTRACK 12#define duprintf(format, args...) printk(format , ## args) 13#else 14#define duprintf(format, args...) 15#endif 16 17struct ahhdr { 18 __u32 spi; 19}; 20 21/* Returns 1 if the spi is matched by the range, 0 otherwise */ 22static inline int 23spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert) 24{ 25 int r=0; 26 duprintf("ah spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ', 27 min,spi,max); 28 r=(spi >= min && spi <= max) ^ invert; 29 duprintf(" result %s\n",r? "PASS" : "FAILED"); 30 return r; 31} 32 33static int 34match(const struct sk_buff *skb, 35 const struct net_device *in, 36 const struct net_device *out, 37 const void *matchinfo, 38 int offset, 39 const void *hdr, 40 u_int16_t datalen, 41 int *hotdrop) 42{ 43 const struct ahhdr *ah = hdr; 44 const struct ipt_ah *ahinfo = matchinfo; 45 46 if (offset == 0 && datalen < sizeof(struct ahhdr)) { 47 /* We've been asked to examine this packet, and we 48 can't. Hence, no choice but to drop. */ 49 duprintf("Dropping evil AH tinygram.\n"); 50 *hotdrop = 1; 51 return 0; 52 } 53 54 /* Must not be a fragment. */ 55 return !offset 56 && spi_match(ahinfo->spis[0], ahinfo->spis[1], 57 ntohl(ah->spi), 58 !!(ahinfo->invflags & IPT_AH_INV_SPI)); 59} 60 61/* Called when user tries to insert an entry of this type. */ 62static int 63checkentry(const char *tablename, 64 const struct ipt_ip *ip, 65 void *matchinfo, 66 unsigned int matchinfosize, 67 unsigned int hook_mask) 68{ 69 const struct ipt_ah *ahinfo = matchinfo; 70 71 /* Must specify proto == AH, and no unknown invflags */ 72 if (ip->proto != IPPROTO_AH || (ip->invflags & IPT_INV_PROTO)) { 73 duprintf("ipt_ah: Protocol %u != %u\n", ip->proto, 74 IPPROTO_AH); 75 return 0; 76 } 77 if (matchinfosize != IPT_ALIGN(sizeof(struct ipt_ah))) { 78 duprintf("ipt_ah: matchsize %u != %u\n", 79 matchinfosize, IPT_ALIGN(sizeof(struct ipt_ah))); 80 return 0; 81 } 82 if (ahinfo->invflags & ~IPT_AH_INV_MASK) { 83 duprintf("ipt_ah: unknown flags %X\n", 84 ahinfo->invflags); 85 return 0; 86 } 87 88 return 1; 89} 90 91static struct ipt_match ah_match 92= { { NULL, NULL }, "ah", &match, &checkentry, NULL, THIS_MODULE }; 93 94static int __init init(void) 95{ 96 return ipt_register_match(&ah_match); 97} 98 99static void __exit cleanup(void) 100{ 101 ipt_unregister_match(&ah_match); 102} 103 104module_init(init); 105module_exit(cleanup); 106