1/* Library which manipulates firewall rules. Version 0.1. */ 2 3/* Architecture of firewall rules is as follows: 4 * 5 * Chains go INPUT, FORWARD, OUTPUT then user chains. 6 * Each user chain starts with an ERROR node. 7 * Every chain ends with an unconditional jump: a RETURN for user chains, 8 * and a POLICY for built-ins. 9 */ 10 11/* (C)1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See 12 COPYING for details). */ 13 14#include <assert.h> 15#include <string.h> 16#include <errno.h> 17#include <stdlib.h> 18#include <stdio.h> 19#include <unistd.h> 20 21#ifdef DEBUG_CONNTRACK 22#define inline 23#endif 24 25#if !defined(__GLIBC__) || (__GLIBC__ < 2) 26typedef unsigned int socklen_t; 27#endif 28 29#include "libiptc/libiptc.h" 30 31#define IP_VERSION 4 32#define IP_OFFSET 0x1FFF 33 34#define HOOK_PRE_ROUTING NF_IP_PRE_ROUTING 35#define HOOK_LOCAL_IN NF_IP_LOCAL_IN 36#define HOOK_FORWARD NF_IP_FORWARD 37#define HOOK_LOCAL_OUT NF_IP_LOCAL_OUT 38#define HOOK_POST_ROUTING NF_IP_POST_ROUTING 39#ifdef NF_IP_DROPPING 40#define HOOK_DROPPING NF_IP_DROPPING 41#endif 42 43#define STRUCT_ENTRY_TARGET struct ipt_entry_target 44#define STRUCT_ENTRY struct ipt_entry 45#define STRUCT_ENTRY_MATCH struct ipt_entry_match 46#define STRUCT_GETINFO struct ipt_getinfo 47#define STRUCT_GET_ENTRIES struct ipt_get_entries 48#define STRUCT_COUNTERS struct ipt_counters 49#define STRUCT_COUNTERS_INFO struct ipt_counters_info 50#define STRUCT_STANDARD_TARGET struct ipt_standard_target 51#define STRUCT_REPLACE struct ipt_replace 52 53#define STRUCT_TC_HANDLE struct iptc_handle 54#define TC_HANDLE_T iptc_handle_t 55 56#define ENTRY_ITERATE IPT_ENTRY_ITERATE 57#define TABLE_MAXNAMELEN IPT_TABLE_MAXNAMELEN 58#define FUNCTION_MAXNAMELEN IPT_FUNCTION_MAXNAMELEN 59 60#define GET_TARGET ipt_get_target 61 62#define ERROR_TARGET IPT_ERROR_TARGET 63#define NUMHOOKS NF_IP_NUMHOOKS 64 65#define IPT_CHAINLABEL ipt_chainlabel 66 67#define TC_DUMP_ENTRIES dump_entries 68#define TC_IS_CHAIN iptc_is_chain 69#define TC_FIRST_CHAIN iptc_first_chain 70#define TC_NEXT_CHAIN iptc_next_chain 71#define TC_FIRST_RULE iptc_first_rule 72#define TC_NEXT_RULE iptc_next_rule 73#define TC_GET_TARGET iptc_get_target 74#define TC_BUILTIN iptc_builtin 75#define TC_GET_POLICY iptc_get_policy 76#define TC_INSERT_ENTRY iptc_insert_entry 77#define TC_REPLACE_ENTRY iptc_replace_entry 78#define TC_APPEND_ENTRY iptc_append_entry 79#define TC_DELETE_ENTRY iptc_delete_entry 80#define TC_DELETE_NUM_ENTRY iptc_delete_num_entry 81#define TC_CHECK_PACKET iptc_check_packet 82#define TC_FLUSH_ENTRIES iptc_flush_entries 83#define TC_ZERO_ENTRIES iptc_zero_entries 84#define TC_READ_COUNTER iptc_read_counter 85#define TC_ZERO_COUNTER iptc_zero_counter 86#define TC_SET_COUNTER iptc_set_counter 87#define TC_CREATE_CHAIN iptc_create_chain 88#define TC_GET_REFERENCES iptc_get_references 89#define TC_DELETE_CHAIN iptc_delete_chain 90#define TC_RENAME_CHAIN iptc_rename_chain 91#define TC_SET_POLICY iptc_set_policy 92#define TC_GET_RAW_SOCKET iptc_get_raw_socket 93#define TC_INIT iptc_init 94#define TC_FREE iptc_free 95#define TC_COMMIT iptc_commit 96#define TC_STRERROR iptc_strerror 97#define TC_NUM_RULES iptc_num_rules 98#define TC_GET_RULE iptc_get_rule 99 100#define TC_AF AF_INET 101#define TC_IPPROTO IPPROTO_IP 102 103#define SO_SET_REPLACE IPT_SO_SET_REPLACE 104#define SO_SET_ADD_COUNTERS IPT_SO_SET_ADD_COUNTERS 105#define SO_GET_INFO IPT_SO_GET_INFO 106#define SO_GET_ENTRIES IPT_SO_GET_ENTRIES 107#define SO_GET_VERSION IPT_SO_GET_VERSION 108 109#define STANDARD_TARGET IPT_STANDARD_TARGET 110#define LABEL_RETURN IPTC_LABEL_RETURN 111#define LABEL_ACCEPT IPTC_LABEL_ACCEPT 112#define LABEL_DROP IPTC_LABEL_DROP 113#define LABEL_QUEUE IPTC_LABEL_QUEUE 114 115#define ALIGN IPT_ALIGN 116#define RETURN IPT_RETURN 117 118#include "libiptc.c" 119 120#define IP_PARTS_NATIVE(n) \ 121(unsigned int)((n)>>24)&0xFF, \ 122(unsigned int)((n)>>16)&0xFF, \ 123(unsigned int)((n)>>8)&0xFF, \ 124(unsigned int)((n)&0xFF) 125 126#define IP_PARTS(n) IP_PARTS_NATIVE(ntohl(n)) 127 128int 129dump_entry(STRUCT_ENTRY *e, const TC_HANDLE_T handle) 130{ 131 size_t i; 132 STRUCT_ENTRY_TARGET *t; 133 134 printf("Entry %u (%lu):\n", iptcb_entry2index(handle, e), 135 iptcb_entry2offset(handle, e)); 136 printf("SRC IP: %u.%u.%u.%u/%u.%u.%u.%u\n", 137 IP_PARTS(e->ip.src.s_addr),IP_PARTS(e->ip.smsk.s_addr)); 138 printf("DST IP: %u.%u.%u.%u/%u.%u.%u.%u\n", 139 IP_PARTS(e->ip.dst.s_addr),IP_PARTS(e->ip.dmsk.s_addr)); 140 printf("Interface: `%s'/", e->ip.iniface); 141 for (i = 0; i < IFNAMSIZ; i++) 142 printf("%c", e->ip.iniface_mask[i] ? 'X' : '.'); 143 printf("to `%s'/", e->ip.outiface); 144 for (i = 0; i < IFNAMSIZ; i++) 145 printf("%c", e->ip.outiface_mask[i] ? 'X' : '.'); 146 printf("\nProtocol: %u\n", e->ip.proto); 147 printf("Flags: %02X\n", e->ip.flags); 148 printf("Invflags: %02X\n", e->ip.invflags); 149 printf("Counters: %llu packets, %llu bytes\n", 150 (unsigned long long)e->counters.pcnt, (unsigned long long)e->counters.bcnt); 151 printf("Cache: %08X ", e->nfcache); 152 if (e->nfcache & NFC_ALTERED) printf("ALTERED "); 153 if (e->nfcache & NFC_UNKNOWN) printf("UNKNOWN "); 154 printf("\n"); 155 156 IPT_MATCH_ITERATE(e, print_match); 157 158 t = GET_TARGET(e); 159 printf("Target name: `%s' [%u]\n", t->u.user.name, t->u.target_size); 160 if (strcmp(t->u.user.name, STANDARD_TARGET) == 0) { 161 int pos = *(int *)t->data; 162 if (pos < 0) 163 printf("verdict=%s\n", 164 pos == -NF_ACCEPT-1 ? "NF_ACCEPT" 165 : pos == -NF_DROP-1 ? "NF_DROP" 166 : pos == -NF_QUEUE-1 ? "NF_QUEUE" 167 : pos == RETURN ? "RETURN" 168 : "UNKNOWN"); 169 else 170 printf("verdict=%u\n", pos); 171 } else if (strcmp(t->u.user.name, IPT_ERROR_TARGET) == 0) 172 printf("error=`%s'\n", t->data); 173 174 printf("\n"); 175 return 0; 176} 177 178static unsigned char * 179is_same(const STRUCT_ENTRY *a, const STRUCT_ENTRY *b, unsigned char *matchmask) 180{ 181 unsigned int i; 182 unsigned char *mptr; 183 184 /* Always compare head structures: ignore mask here. */ 185 if (a->ip.src.s_addr != b->ip.src.s_addr 186 || a->ip.dst.s_addr != b->ip.dst.s_addr 187 || a->ip.smsk.s_addr != b->ip.smsk.s_addr 188 || a->ip.dmsk.s_addr != b->ip.dmsk.s_addr 189 || a->ip.proto != b->ip.proto 190 || a->ip.flags != b->ip.flags 191 || a->ip.invflags != b->ip.invflags) 192 return NULL; 193 194 for (i = 0; i < IFNAMSIZ; i++) { 195 if (a->ip.iniface_mask[i] != b->ip.iniface_mask[i]) 196 return NULL; 197 if ((a->ip.iniface[i] & a->ip.iniface_mask[i]) 198 != (b->ip.iniface[i] & b->ip.iniface_mask[i])) 199 return NULL; 200 if (a->ip.outiface_mask[i] != b->ip.outiface_mask[i]) 201 return NULL; 202 if ((a->ip.outiface[i] & a->ip.outiface_mask[i]) 203 != (b->ip.outiface[i] & b->ip.outiface_mask[i])) 204 return NULL; 205 } 206 207 if (a->nfcache != b->nfcache 208 || a->target_offset != b->target_offset 209 || a->next_offset != b->next_offset) 210 return NULL; 211 212 mptr = matchmask + sizeof(STRUCT_ENTRY); 213 if (IPT_MATCH_ITERATE(a, match_different, a->elems, b->elems, &mptr)) 214 return NULL; 215 mptr += IPT_ALIGN(sizeof(struct ipt_entry_target)); 216 217 return mptr; 218} 219