1/* 2 * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation (or any later at your option). 7 * 8 * This code has been sponsored by Vyatta Inc. <http://www.vyatta.com> 9 */ 10 11#include "helper.h" 12 13#include <stdio.h> 14#include <string.h> 15#include <limits.h> 16#include <errno.h> 17#include <sys/types.h> 18#include <sys/stat.h> 19#include <unistd.h> 20#include <dlfcn.h> 21 22int 23cthelper_expect_init(struct nf_expect *exp, struct nf_conntrack *master, 24 uint32_t class, 25 union nfct_attr_grp_addr *saddr, 26 union nfct_attr_grp_addr *daddr, 27 uint8_t l4proto, uint16_t *sport, uint16_t *dport, 28 uint32_t flags) 29{ 30 struct nf_conntrack *expected, *mask; 31 32 expected = nfct_new(); 33 if (!expected) 34 return -1; 35 36 mask = nfct_new(); 37 if (!mask) 38 return -1; 39 40 if (saddr) { 41 switch(nfct_get_attr_u8(master, ATTR_L3PROTO)) { 42 int i; 43 uint32_t addr[4] = {}; 44 45 case AF_INET: 46 nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET); 47 nfct_set_attr_u32(expected, ATTR_IPV4_SRC, saddr->ip); 48 49 nfct_set_attr_u8(mask, ATTR_L3PROTO, AF_INET); 50 nfct_set_attr_u32(mask, ATTR_IPV4_SRC, 0xffffffff); 51 break; 52 case AF_INET6: 53 nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET6); 54 nfct_set_attr(expected, ATTR_IPV6_SRC, saddr->ip6); 55 56 for (i=0; i<4; i++) 57 memset(addr, 0xffffffff, sizeof(uint32_t)); 58 59 nfct_set_attr_u8(mask, ATTR_L3PROTO, AF_INET6); 60 nfct_set_attr(mask, ATTR_IPV6_SRC, addr); 61 break; 62 default: 63 break; 64 } 65 } else { 66 switch(nfct_get_attr_u8(master, ATTR_L3PROTO)) { 67 int i; 68 uint32_t addr[4] = {}; 69 70 case AF_INET: 71 nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET); 72 nfct_set_attr_u32(expected, ATTR_IPV4_SRC, 0x00000000); 73 74 nfct_set_attr_u8(mask, ATTR_L3PROTO, AF_INET); 75 nfct_set_attr_u32(mask, ATTR_IPV4_SRC, 0x00000000); 76 break; 77 case AF_INET6: 78 for (i=0; i<4; i++) 79 memset(addr, 0x00000000, sizeof(uint32_t)); 80 81 nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET6); 82 nfct_set_attr(expected, ATTR_IPV6_SRC, addr); 83 84 nfct_set_attr_u8(mask, ATTR_L3PROTO, AF_INET6); 85 nfct_set_attr(mask, ATTR_IPV6_SRC, addr); 86 break; 87 default: 88 break; 89 } 90 } 91 92 if (sport) { 93 switch(l4proto) { 94 case IPPROTO_TCP: 95 case IPPROTO_UDP: 96 nfct_set_attr_u8(expected, ATTR_L4PROTO, l4proto); 97 nfct_set_attr_u16(expected, ATTR_PORT_SRC, *sport); 98 nfct_set_attr_u8(mask, ATTR_L4PROTO, l4proto); 99 nfct_set_attr_u16(mask, ATTR_PORT_SRC, 0xffff); 100 break; 101 default: 102 break; 103 } 104 } else { 105 switch(l4proto) { 106 case IPPROTO_TCP: 107 case IPPROTO_UDP: 108 nfct_set_attr_u8(expected, ATTR_L4PROTO, l4proto); 109 nfct_set_attr_u16(expected, ATTR_PORT_SRC, 0x0000); 110 nfct_set_attr_u8(mask, ATTR_L4PROTO, l4proto); 111 nfct_set_attr_u16(mask, ATTR_PORT_SRC, 0x0000); 112 break; 113 default: 114 break; 115 } 116 } 117 118 switch(nfct_get_attr_u8(master, ATTR_L3PROTO)) { 119 uint32_t addr[4] = {}; 120 int i; 121 122 case AF_INET: 123 nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET); 124 nfct_set_attr_u32(expected, ATTR_IPV4_DST, daddr->ip); 125 nfct_set_attr_u32(mask, ATTR_IPV4_DST, 0xffffffff); 126 break; 127 case AF_INET6: 128 nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET6); 129 nfct_set_attr(expected, ATTR_IPV6_DST, daddr->ip6); 130 131 for (i=0; i<4; i++) 132 memset(addr, 0xffffffff, sizeof(uint32_t)); 133 134 nfct_set_attr(mask, ATTR_IPV6_DST, addr); 135 break; 136 default: 137 break; 138 } 139 140 switch(l4proto) { 141 case IPPROTO_TCP: 142 case IPPROTO_UDP: 143 nfct_set_attr_u8(expected, ATTR_L4PROTO, l4proto); 144 nfct_set_attr_u16(expected, ATTR_PORT_DST, *dport); 145 nfct_set_attr_u8(mask, ATTR_L4PROTO, l4proto); 146 nfct_set_attr_u16(mask, ATTR_PORT_DST, 0xffff); 147 break; 148 default: 149 break; 150 } 151 152 nfexp_set_attr(exp, ATTR_EXP_MASTER, master); 153 nfexp_set_attr(exp, ATTR_EXP_EXPECTED, expected); 154 nfexp_set_attr(exp, ATTR_EXP_MASK, mask); 155 nfexp_set_attr_u32(exp, ATTR_EXP_FLAGS, flags); 156 157 nfct_destroy(expected); 158 nfct_destroy(mask); 159 160 return 0; 161} 162 163static int cthelper_expect_cmd(struct nf_expect *exp, int cmd) 164{ 165 int ret; 166 struct nfct_handle *h; 167 168 h = nfct_open(EXPECT, 0); 169 if (!h) 170 return -1; 171 172 ret = nfexp_query(h, cmd, exp); 173 174 nfct_close(h); 175 return ret; 176} 177 178int cthelper_add_expect(struct nf_expect *exp) 179{ 180 return cthelper_expect_cmd(exp, NFCT_Q_CREATE_UPDATE); 181} 182 183int cthelper_del_expect(struct nf_expect *exp) 184{ 185 return cthelper_expect_cmd(exp, NFCT_Q_DESTROY); 186} 187 188void 189cthelper_get_addr_src(struct nf_conntrack *ct, int dir, 190 union nfct_attr_grp_addr *addr) 191{ 192 switch (dir) { 193 case MYCT_DIR_ORIG: 194 nfct_get_attr_grp(ct, ATTR_GRP_ORIG_ADDR_SRC, addr); 195 break; 196 case MYCT_DIR_REPL: 197 nfct_get_attr_grp(ct, ATTR_GRP_REPL_ADDR_SRC, addr); 198 break; 199 } 200} 201 202void 203cthelper_get_addr_dst(struct nf_conntrack *ct, int dir, 204 union nfct_attr_grp_addr *addr) 205{ 206 switch (dir) { 207 case MYCT_DIR_ORIG: 208 nfct_get_attr_grp(ct, ATTR_GRP_ORIG_ADDR_DST, addr); 209 break; 210 case MYCT_DIR_REPL: 211 nfct_get_attr_grp(ct, ATTR_GRP_REPL_ADDR_DST, addr); 212 break; 213 } 214} 215