libiptc.c revision c8264991454b5e77279830736f80ea3153b6f814
10f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson/* Library which manipulates firewall rules. Version 0.1. */ 2e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 3e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Architecture of firewall rules is as follows: 4e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * 5e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * Chains go INPUT, FORWARD, OUTPUT then user chains. 6e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * Each user chain starts with an ERROR node. 7e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * Every chain ends with an unconditional jump: a RETURN for user chains, 8e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * and a POLICY for built-ins. 9e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher */ 10e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 113ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte/* (C)1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See 123ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte COPYING for details). */ 13aae69bed019826ddec93f761514652a93d871e49Harald Welte 143ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte#include <assert.h> 15fbc85236a6140918ab1d0fb0e07e2d72da46ce45Harald Welte#include <string.h> 163ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte#include <errno.h> 17fbc85236a6140918ab1d0fb0e07e2d72da46ce45Harald Welte#include <stdlib.h> 180113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte#include <stdio.h> 19fbc85236a6140918ab1d0fb0e07e2d72da46ce45Harald Welte#include <limits.h> 20fbc85236a6140918ab1d0fb0e07e2d72da46ce45Harald Welte 21aae69bed019826ddec93f761514652a93d871e49Harald Welte#if !defined(__GLIBC__) || (__GLIBC__ < 2) 22aae69bed019826ddec93f761514652a93d871e49Harald Weltetypedef unsigned int socklen_t; 23aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 24aae69bed019826ddec93f761514652a93d871e49Harald Welte 25aae69bed019826ddec93f761514652a93d871e49Harald Welte#include <libiptc/libiptc.h> 263ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte#include <linux/netfilter_ipv4/ipt_limit.h> 2715920d160760535e51a57b3834eba45257cfa6d8Harald Welte 2815920d160760535e51a57b3834eba45257cfa6d8Harald Welte#define IP_VERSION 4 298b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt#define IP_OFFSET 0x1FFF 307cd002826d0f329620cb738bc4dc4760ef5e084aStephane Ouellette 31aae69bed019826ddec93f761514652a93d871e49Harald Welte#ifndef IPT_LIB_DIR 32aae69bed019826ddec93f761514652a93d871e49Harald Welte#define IPT_LIB_DIR "/usr/local/lib/iptables" 33aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 34aae69bed019826ddec93f761514652a93d871e49Harald Welte 35aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int sockfd = -1; 36aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void *iptc_fn = NULL; 37aae69bed019826ddec93f761514652a93d871e49Harald Welte 38aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic const char *hooknames[] 39aae69bed019826ddec93f761514652a93d871e49Harald Welte= { [NF_IP_PRE_ROUTING] "PREROUTING", 40aae69bed019826ddec93f761514652a93d871e49Harald Welte [NF_IP_LOCAL_IN] "INPUT", 41aae69bed019826ddec93f761514652a93d871e49Harald Welte [NF_IP_FORWARD] "FORWARD", 42aae69bed019826ddec93f761514652a93d871e49Harald Welte [NF_IP_LOCAL_OUT] "OUTPUT", 43aae69bed019826ddec93f761514652a93d871e49Harald Welte [NF_IP_POST_ROUTING] "POSTROUTING" 4401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer}; 4501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 4601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouerstruct counter_map 4701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer{ 4801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer enum { 4901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer COUNTER_MAP_NOMAP, 50e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher COUNTER_MAP_NORMAL_MAP, 51e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher COUNTER_MAP_ZEROED 520b63936140032deac44072951451bdf47b54296aPatrick McHardy } maptype; 530b63936140032deac44072951451bdf47b54296aPatrick McHardy unsigned int mappos; 540b63936140032deac44072951451bdf47b54296aPatrick McHardy}; 550b63936140032deac44072951451bdf47b54296aPatrick McHardy 560b63936140032deac44072951451bdf47b54296aPatrick McHardy/* Convenience structures */ 570b63936140032deac44072951451bdf47b54296aPatrick McHardystruct ipt_error_target 5810758b743d6aa076ebe2c3e8f855e73826841e71Rusty Russell{ 590b63936140032deac44072951451bdf47b54296aPatrick McHardy struct ipt_entry_target t; 6010758b743d6aa076ebe2c3e8f855e73826841e71Rusty Russell char error[IPT_TABLE_MAXNAMELEN]; 61e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 62e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 63aae69bed019826ddec93f761514652a93d871e49Harald Weltestruct iptc_handle 64aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 65aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Have changes been made? */ 66aae69bed019826ddec93f761514652a93d871e49Harald Welte int changed; 67aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Size in here reflects original state. */ 68aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_getinfo info; 69aae69bed019826ddec93f761514652a93d871e49Harald Welte 70aae69bed019826ddec93f761514652a93d871e49Harald Welte struct counter_map *counter_map; 71aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Array of hook names */ 72aae69bed019826ddec93f761514652a93d871e49Harald Welte const char **hooknames; 73e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 74e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* This was taking us ~50 seconds to list 300 rules. */ 75e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Cached: last find_label result */ 76e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher char cache_label_name[IPT_TABLE_MAXNAMELEN]; 77e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int cache_label_return; 781cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte unsigned int cache_label_offset; 791cef74d943055668b5e356eebea877fdaa1ce3e0Harald Welte 80e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Number in here reflects current state. */ 81e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int new_number; 82e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct ipt_get_entries entries; 83e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher}; 84aae69bed019826ddec93f761514652a93d871e49Harald Welte 85aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic void 86aae69bed019826ddec93f761514652a93d871e49Harald Welteset_changed(iptc_handle_t h) 87aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 88aae69bed019826ddec93f761514652a93d871e49Harald Welte h->cache_label_name[0] = '\0'; 89aae69bed019826ddec93f761514652a93d871e49Harald Welte h->changed = 1; 90aae69bed019826ddec93f761514652a93d871e49Harald Welte} 91aae69bed019826ddec93f761514652a93d871e49Harald Welte 92e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic void do_check(iptc_handle_t h, unsigned int line); 93aae69bed019826ddec93f761514652a93d871e49Harald Welte#define CHECK(h) do_check((h), __LINE__) 94aae69bed019826ddec93f761514652a93d871e49Harald Welte 95aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline int 96aae69bed019826ddec93f761514652a93d871e49Harald Welteget_number(const struct ipt_entry *i, 97aae69bed019826ddec93f761514652a93d871e49Harald Welte const struct ipt_entry *seek, 98aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int *pos) 99aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 100aae69bed019826ddec93f761514652a93d871e49Harald Welte if (i == seek) 101aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 102aae69bed019826ddec93f761514652a93d871e49Harald Welte (*pos)++; 103aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 104aae69bed019826ddec93f761514652a93d871e49Harald Welte} 105e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 106e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic unsigned int 107aae69bed019826ddec93f761514652a93d871e49Harald Welteentry2index(const iptc_handle_t h, const struct ipt_entry *seek) 10830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 109aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int pos = 0; 11079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell 111aae69bed019826ddec93f761514652a93d871e49Harald Welte if (IPT_ENTRY_ITERATE(h->entries.entries, h->entries.size, 112aae69bed019826ddec93f761514652a93d871e49Harald Welte get_number, seek, &pos) == 0) { 113aae69bed019826ddec93f761514652a93d871e49Harald Welte fprintf(stderr, "ERROR: offset %i not an entry!\n", 114aae69bed019826ddec93f761514652a93d871e49Harald Welte (unsigned char *)seek - h->entries.entries); 115aae69bed019826ddec93f761514652a93d871e49Harald Welte abort(); 116aae69bed019826ddec93f761514652a93d871e49Harald Welte } 117aae69bed019826ddec93f761514652a93d871e49Harald Welte return pos; 118aae69bed019826ddec93f761514652a93d871e49Harald Welte} 119aae69bed019826ddec93f761514652a93d871e49Harald Welte 120aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline int 121aae69bed019826ddec93f761514652a93d871e49Harald Welteget_entry_n(struct ipt_entry *i, 122aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int number, 123aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int *pos, 124aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_entry **pe) 12530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 12630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (*pos == number) { 12779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell *pe = i; 128e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 1; 129175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt } 130aae69bed019826ddec93f761514652a93d871e49Harald Welte (*pos)++; 131aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 132aae69bed019826ddec93f761514652a93d871e49Harald Welte} 133aae69bed019826ddec93f761514652a93d871e49Harald Welte 134aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic struct ipt_entry * 135aae69bed019826ddec93f761514652a93d871e49Harald Welteindex2entry(iptc_handle_t h, unsigned int index) 136aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 13748bde40e73b45ad134d32cde88b779fe509faf64Jesper Dangaard Brouer unsigned int pos = 0; 13848bde40e73b45ad134d32cde88b779fe509faf64Jesper Dangaard Brouer struct ipt_entry *ret = NULL; 13901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 14001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer IPT_ENTRY_ITERATE(h->entries.entries, h->entries.size, 14101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer get_entry_n, index, &pos, &ret); 1424bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 1434bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer return ret; 1444bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer} 1454bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 1464bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouerstatic inline struct ipt_entry * 14779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellget_entry(iptc_handle_t h, unsigned int offset) 148aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 149aae69bed019826ddec93f761514652a93d871e49Harald Welte return (struct ipt_entry *)(h->entries.entries + offset); 150e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1514bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 1524bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouerstatic inline unsigned long 1534bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouerentry2offset(const iptc_handle_t h, const struct ipt_entry *e) 1544bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer{ 1554bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer return (unsigned char *)e - h->entries.entries; 156aae69bed019826ddec93f761514652a93d871e49Harald Welte} 157aae69bed019826ddec93f761514652a93d871e49Harald Welte 158aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic unsigned long 159aae69bed019826ddec93f761514652a93d871e49Harald Welteindex2offset(iptc_handle_t h, unsigned int index) 160aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 161aae69bed019826ddec93f761514652a93d871e49Harald Welte return entry2offset(h, index2entry(h, index)); 162aae69bed019826ddec93f761514652a93d871e49Harald Welte} 163aae69bed019826ddec93f761514652a93d871e49Harald Welte 164aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic const char * 165aae69bed019826ddec93f761514652a93d871e49Harald Welteget_errorlabel(iptc_handle_t h, unsigned int offset) 166aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 167e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct ipt_entry *e; 168aae69bed019826ddec93f761514652a93d871e49Harald Welte 169aae69bed019826ddec93f761514652a93d871e49Harald Welte e = get_entry(h, offset); 17030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (strcmp(ipt_get_target(e)->u.name, IPT_ERROR_TARGET) != 0) { 171aae69bed019826ddec93f761514652a93d871e49Harald Welte fprintf(stderr, "ERROR: offset %u not an error node!\n", 172aae69bed019826ddec93f761514652a93d871e49Harald Welte offset); 173aae69bed019826ddec93f761514652a93d871e49Harald Welte abort(); 174aae69bed019826ddec93f761514652a93d871e49Harald Welte } 175aae69bed019826ddec93f761514652a93d871e49Harald Welte 176aae69bed019826ddec93f761514652a93d871e49Harald Welte return (const char *)ipt_get_target(e)->data; 177aae69bed019826ddec93f761514652a93d871e49Harald Welte} 17830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 179aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Allocate handle of given size */ 180aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic iptc_handle_t 181175f64177743e5a417e98d483ef995bf7151f3bcRusty Russellalloc_handle(const char *tablename, unsigned int size, unsigned int num_rules) 182aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 183aae69bed019826ddec93f761514652a93d871e49Harald Welte size_t len; 184e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher iptc_handle_t h; 185aae69bed019826ddec93f761514652a93d871e49Harald Welte 186910939897ea0cb9be2729a98c60a92e807aad5c3Jesper Dangaard Brouer len = sizeof(struct iptc_handle) 187fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt + size 188175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell + num_rules * sizeof(struct counter_map); 189175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell 190175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell if ((h = malloc(len)) == NULL) { 191175f64177743e5a417e98d483ef995bf7151f3bcRusty Russell errno = ENOMEM; 192380ba5f3074a16fbaa8869d9594962d58b5f8608Harald Welte return NULL; 193fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt } 194849779c4adf8dd65c83fffb65e6b7898df2a55c6Rusty Russell 19530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell h->changed = 0; 19630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell h->cache_label_name[0] = '\0'; 19730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell h->counter_map = (void *)h 198e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher + sizeof(struct iptc_handle) 199aae69bed019826ddec93f761514652a93d871e49Harald Welte + size; 200aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(h->info.name, tablename); 201aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(h->entries.name, tablename); 202aae69bed019826ddec93f761514652a93d871e49Harald Welte 203aae69bed019826ddec93f761514652a93d871e49Harald Welte return h; 204e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 205aae69bed019826ddec93f761514652a93d871e49Harald Welte 20679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russelliptc_handle_t 207e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucheriptc_init(const char *tablename) 208e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 209e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher iptc_handle_t h; 210e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct ipt_getinfo info; 211e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 212e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher int tmp; 213e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher socklen_t s; 214e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 215aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = iptc_init; 216aae69bed019826ddec93f761514652a93d871e49Harald Welte 217aae69bed019826ddec93f761514652a93d871e49Harald Welte sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); 218aae69bed019826ddec93f761514652a93d871e49Harald Welte if (sockfd < 0) 219aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 220aae69bed019826ddec93f761514652a93d871e49Harald Welte 221aae69bed019826ddec93f761514652a93d871e49Harald Welte s = sizeof(info); 222aae69bed019826ddec93f761514652a93d871e49Harald Welte if (strlen(tablename) >= IPT_TABLE_MAXNAMELEN) { 223aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = EINVAL; 224aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 225aae69bed019826ddec93f761514652a93d871e49Harald Welte } 226aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(info.name, tablename); 227aae69bed019826ddec93f761514652a93d871e49Harald Welte if (getsockopt(sockfd, IPPROTO_IP, IPT_SO_GET_INFO, &info, &s) < 0) 228aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 229aae69bed019826ddec93f761514652a93d871e49Harald Welte 230fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt if ((h = alloc_handle(info.name, info.size, info.num_entries)) 231aae69bed019826ddec93f761514652a93d871e49Harald Welte == NULL) 232aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 233aae69bed019826ddec93f761514652a93d871e49Harald Welte 234aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Too hard --RR */ 235e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#if 0 236fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt sprintf(pathname, "%s/%s", IPT_LIB_DIR, info.name); 237e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher dynlib = dlopen(pathname, RTLD_NOW); 238e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!dynlib) { 239e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 240aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 241aae69bed019826ddec93f761514652a93d871e49Harald Welte } 242a28d495285ad7dd9f286d63958cf20d74eec6bcbMartin Josefsson h->hooknames = dlsym(dynlib, "hooknames"); 243aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!h->hooknames) { 244e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = ENOENT; 245e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return NULL; 246e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 247e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#else 248e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher h->hooknames = hooknames; 249aae69bed019826ddec93f761514652a93d871e49Harald Welte#endif 250fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt 251e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Initialize current state */ 252aae69bed019826ddec93f761514652a93d871e49Harald Welte h->info = info; 253aae69bed019826ddec93f761514652a93d871e49Harald Welte h->new_number = h->info.num_entries; 254aae69bed019826ddec93f761514652a93d871e49Harald Welte for (i = 0; i < h->info.num_entries; i++) 255aae69bed019826ddec93f761514652a93d871e49Harald Welte h->counter_map[i] 256aae69bed019826ddec93f761514652a93d871e49Harald Welte = ((struct counter_map){COUNTER_MAP_NORMAL_MAP, i}); 257fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt 258aae69bed019826ddec93f761514652a93d871e49Harald Welte h->entries.size = h->info.size; 259aae69bed019826ddec93f761514652a93d871e49Harald Welte 260aae69bed019826ddec93f761514652a93d871e49Harald Welte tmp = sizeof(struct ipt_get_entries) + h->info.size; 261aae69bed019826ddec93f761514652a93d871e49Harald Welte 262aae69bed019826ddec93f761514652a93d871e49Harald Welte if (getsockopt(sockfd, IPPROTO_IP, IPT_SO_GET_ENTRIES, &h->entries, 263fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt &tmp) < 0) { 264aae69bed019826ddec93f761514652a93d871e49Harald Welte free(h); 265aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 266aae69bed019826ddec93f761514652a93d871e49Harald Welte } 267aae69bed019826ddec93f761514652a93d871e49Harald Welte 268aae69bed019826ddec93f761514652a93d871e49Harald Welte CHECK(h); 269aae69bed019826ddec93f761514652a93d871e49Harald Welte return h; 270fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt} 271aae69bed019826ddec93f761514652a93d871e49Harald Welte 272aae69bed019826ddec93f761514652a93d871e49Harald Welte#define IP_PARTS_NATIVE(n) \ 273aae69bed019826ddec93f761514652a93d871e49Harald Welte(unsigned int)((n)>>24)&0xFF, \ 274aae69bed019826ddec93f761514652a93d871e49Harald Welte(unsigned int)((n)>>16)&0xFF, \ 275aae69bed019826ddec93f761514652a93d871e49Harald Welte(unsigned int)((n)>>8)&0xFF, \ 276aae69bed019826ddec93f761514652a93d871e49Harald Welte(unsigned int)((n)&0xFF) 277aae69bed019826ddec93f761514652a93d871e49Harald Welte 278aae69bed019826ddec93f761514652a93d871e49Harald Welte#define IP_PARTS(n) IP_PARTS_NATIVE(ntohl(n)) 279aae69bed019826ddec93f761514652a93d871e49Harald Welte 280aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline int 281aae69bed019826ddec93f761514652a93d871e49Harald Welteprint_match(const struct ipt_entry_match *m) 282aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 283aae69bed019826ddec93f761514652a93d871e49Harald Welte printf("Match name: `%s'\n", m->u.name); 28401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return 0; 28501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer} 28601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 28701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouerint 28801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouerdump_entry(struct ipt_entry *e, const iptc_handle_t handle) 28901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer{ 29001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer size_t i; 29101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer struct ipt_entry_target *t; 29201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 29301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer printf("Entry %u (%lu):\n", entry2index(handle, e), 29401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer entry2offset(handle, e)); 29501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer printf("SRC IP: %u.%u.%u.%u/%u.%u.%u.%u\n", 29601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer IP_PARTS(e->ip.src.s_addr),IP_PARTS(e->ip.smsk.s_addr)); 29701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer printf("DST IP: %u.%u.%u.%u/%u.%u.%u.%u\n", 29801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer IP_PARTS(e->ip.dst.s_addr),IP_PARTS(e->ip.dmsk.s_addr)); 29901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer printf("Interface: `%s'/", e->ip.iniface); 30001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer for (i = 0; i < IFNAMSIZ; i++) 30101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer printf("%c", e->ip.iniface_mask[i] ? 'X' : '.'); 30201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer printf("to `%s'/", e->ip.outiface); 30301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer for (i = 0; i < IFNAMSIZ; i++) 30401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer printf("%c", e->ip.outiface_mask[i] ? 'X' : '.'); 30501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer printf("\nProtocol: %u\n", e->ip.proto); 30601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer printf("Flags: %02X\n", e->ip.flags); 30701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer printf("Invflags: %02X\n", e->ip.invflags); 30801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer printf("Counters: %llu packets, %llu bytes\n", 30901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer e->counters.pcnt, e->counters.bcnt); 31001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer printf("Cache: %08X ", e->nfcache); 31101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (e->nfcache & NFC_ALTERED) printf("ALTERED "); 31201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (e->nfcache & NFC_UNKNOWN) printf("UNKNOWN "); 31301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (e->nfcache & NFC_IP_SRC) printf("IP_SRC "); 31401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (e->nfcache & NFC_IP_DST) printf("IP_DST "); 31501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (e->nfcache & NFC_IP_IF_IN) printf("IP_IF_IN "); 31601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (e->nfcache & NFC_IP_IF_OUT) printf("IP_IF_OUT "); 31701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (e->nfcache & NFC_IP_TOS) printf("IP_TOS "); 31801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (e->nfcache & NFC_IP_PROTO) printf("IP_PROTO "); 31901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (e->nfcache & NFC_IP_OPTIONS) printf("IP_OPTIONS "); 32001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (e->nfcache & NFC_IP_TCPFLAGS) printf("IP_TCPFLAGS "); 32101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (e->nfcache & NFC_IP_SRC_PT) printf("IP_SRC_PT "); 32201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (e->nfcache & NFC_IP_DST_PT) printf("IP_DST_PT "); 3234bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer if (e->nfcache & NFC_IP_PROTO_UNKNOWN) printf("IP_PROTO_UNKNOWN "); 3244bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer printf("\n"); 3254bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 3264bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer IPT_MATCH_ITERATE(e, print_match); 3274bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 32801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer t = ipt_get_target(e); 32901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer printf("Target name: `%s' [%u]\n", t->u.name, t->target_size); 3304bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer if (strcmp(t->u.name, IPT_STANDARD_TARGET) == 0) { 331fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt int pos = *(int *)t->data; 3324bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer if (pos < 0) 33301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer printf("verdict=%s\n", 33401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer pos == -NF_ACCEPT-1 ? "NF_ACCEPT" 33501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer : pos == -NF_DROP-1 ? "NF_DROP" 33601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer : pos == -NF_QUEUE-1 ? "NF_QUEUE" 33701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer : pos == IPT_RETURN ? "RETURN" 33801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer : "UNKNOWN"); 33901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer else 34001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer printf("verdict=%u\n", pos); 34101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } else if (strcmp(t->u.name, IPT_ERROR_TARGET) == 0) 34201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer printf("error=`%s'\n", t->data); 34301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 34401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer printf("\n"); 34501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return 0; 34601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer} 34701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 34801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouervoid 34901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouerdump_entries(const iptc_handle_t handle) 3504bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer{ 3514bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer CHECK(handle); 35201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 35301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer printf("libiptc v%s. %u entries, %u bytes.\n", 35401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer NETFILTER_VERSION, 35501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer handle->new_number, handle->entries.size); 35601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer printf("Table `%s'\n", handle->info.name); 35701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer printf("Hooks: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n", 35801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer handle->info.hook_entry[NF_IP_PRE_ROUTING], 35901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer handle->info.hook_entry[NF_IP_LOCAL_IN], 3604bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer handle->info.hook_entry[NF_IP_FORWARD], 3614bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer handle->info.hook_entry[NF_IP_LOCAL_OUT], 3624bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer handle->info.hook_entry[NF_IP_POST_ROUTING]); 3634bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer printf("Underflows: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n", 3644bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer handle->info.underflow[NF_IP_PRE_ROUTING], 3654bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer handle->info.underflow[NF_IP_LOCAL_IN], 3664bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer handle->info.underflow[NF_IP_FORWARD], 3674bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer handle->info.underflow[NF_IP_LOCAL_OUT], 3684bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer handle->info.underflow[NF_IP_POST_ROUTING]); 3694bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 3704bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer IPT_ENTRY_ITERATE(handle->entries.entries, handle->entries.size, 3714bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer dump_entry, handle); 3724bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer} 3734bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 3744bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouerstatic inline int 3754bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouerfind_user_label(struct ipt_entry *e, unsigned int *off, const char *name) 3764bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer{ 3774bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer /* Increment first: they want offset of entry AFTER label */ 3784bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer (*off) += e->next_offset; 3794bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 3804bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer if (strcmp(ipt_get_target(e)->u.name, IPT_ERROR_TARGET) == 0 3814bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer && strcmp(ipt_get_target(e)->data, name) == 0) 3824bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer return 1; 38301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 384dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt return 0; 38501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer} 38601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 38701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer/* Returns offset of label. */ 38801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouerstatic int 38901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouerfind_label(unsigned int *off, 39001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer const char *name, 39101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer const iptc_handle_t handle) 39201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer{ 39301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int i; 39401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 39501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Cached? */ 39601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (handle->cache_label_name[0] 39701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer && strcmp(name, handle->cache_label_name) == 0) { 39801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer *off = handle->cache_label_offset; 39901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return handle->cache_label_return; 40001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 40101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 40201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Builtin chain name? */ 40301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer i = iptc_builtin(name, handle); 40401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (i != 0) { 40501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer *off = handle->info.hook_entry[i-1]; 40601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return 1; 40701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 40801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 4094bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer /* User chain name? */ 4104bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer *off = 0; 4114bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer if (IPT_ENTRY_ITERATE(handle->entries.entries, handle->entries.size, 4124bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer find_user_label, off, name) != 0) { 4134bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer /* last error node doesn't count */ 4144bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer if (*off != handle->entries.size) { 4154bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer strcpy(handle->cache_label_name, name); 4164bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer handle->cache_label_offset = *off; 4174bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer handle->cache_label_return = 1; 41801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return 1; 41901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 42001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 42101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 42201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer strcpy(handle->cache_label_name, name); 42301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer handle->cache_label_return = 0; 42401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return 0; 42501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer} 42601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 42701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer/* Does this chain exist? */ 42801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouerint iptc_is_chain(const char *chain, const iptc_handle_t handle) 42901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer{ 43001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int dummy; 4314bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 4324bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer /* avoid infinite recursion */ 4334bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer#if 0 434fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt CHECK(handle); 4354bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer#endif 4364bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 4374bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer return find_label(&dummy, chain, handle); 4384bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer} 4394bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 4404bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer/* Returns the position of the final (ie. unconditional) element. */ 4414bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouerstatic unsigned int 4424bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouerget_chain_end(const iptc_handle_t handle, unsigned int start) 443fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt{ 4444bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer unsigned int last_off, off; 4454bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer struct ipt_entry *e; 4464bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 4474bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer last_off = start; 4484bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer e = get_entry(handle, start); 4494bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 4504bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer /* Terminate when we meet a error label or a hook entry. */ 4514bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer for (off = start + e->next_offset; 4524bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer off < handle->entries.size; 4534bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer last_off = off, off += e->next_offset) { 4544bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer struct ipt_entry_target *t; 4554bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer unsigned int i; 4564bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 4574bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer e = get_entry(handle, off); 4584bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 45901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* We hit an entry point. */ 46001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer for (i = 0; i < NF_IP_NUMHOOKS; i++) { 46101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if ((handle->info.valid_hooks & (1 << i)) 46201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer && off == handle->info.hook_entry[i]) 463fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt return last_off; 46401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 46501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 46601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* We hit a user chain label */ 46701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer t = ipt_get_target(e); 46801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (strcmp(t->u.name, IPT_ERROR_TARGET) == 0) 46901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return last_off; 47001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 47101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* SHOULD NEVER HAPPEN */ 47201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer fprintf(stderr, "ERROR: Off end (%u) of chain from %u!\n", 47301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer handle->entries.size, off); 47401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer abort(); 47501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer} 47601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 47701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer/* Iterator functions to run through the chains; prev = NULL means 47801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer first chain. Returns NULL at end. */ 47901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouerconst char * 48001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Broueriptc_next_chain(const char *prev, iptc_handle_t *handle) 48101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer{ 48201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int pos; 48301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int i; 48401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer struct ipt_entry *e; 48501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 48601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer CHECK(*handle); 48701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (!prev) 48801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer pos = 0; 48901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer else { 49001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (!find_label(&pos, prev, *handle)) { 491fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt errno = ENOENT; 49201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return NULL; 49301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 49401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer pos = get_chain_end(*handle, pos); 49501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Next entry. */ 49601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer e = get_entry(*handle, pos); 49701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer pos += e->next_offset; 49801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 49901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer e = get_entry(*handle, pos); 50001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 50101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Return names of entry points if it is one. */ 50201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer for (i = 0; i < NF_IP_NUMHOOKS; i++) { 50301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (((*handle)->info.valid_hooks & (1 << i)) 50401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer && pos == (*handle)->info.hook_entry[i]) 50501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return (*handle)->hooknames[i]; 50601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 50701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* If this is the last element, iteration finished */ 50801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (pos + e->next_offset == (*handle)->entries.size) 50901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return NULL; 51001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 51101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (strcmp(ipt_get_target(e)->u.name, IPT_ERROR_TARGET) != 0) { 51201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* SHOULD NEVER HAPPEN */ 51301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer fprintf(stderr, "ERROR: position %u/%u not an error label\n", 51401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer pos, (*handle)->entries.size); 51501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer abort(); 516fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt } 51701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 51801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return (const char *)ipt_get_target(e)->data; 51901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer} 52001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 52101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer/* How many rules in this chain? */ 52201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouerunsigned int 52301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Broueriptc_num_rules(const char *chain, iptc_handle_t *handle) 524fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt{ 52501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int off = 0; 52601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer struct ipt_entry *start, *end; 52701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 52801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer CHECK(*handle); 52901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (!find_label(&off, chain, *handle)) { 53001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer errno = ENOENT; 53101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return (unsigned int)-1; 53201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 53301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 53401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer start = get_entry(*handle, off); 53501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer end = get_entry(*handle, get_chain_end(*handle, off)); 53601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 53701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return entry2index(*handle, end) - entry2index(*handle, start); 53801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer} 539fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt 54001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer/* Get n'th rule in this chain. */ 54101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouerconst struct ipt_entry *iptc_get_rule(const char *chain, 54201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int n, 54301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer iptc_handle_t *handle) 54401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer{ 54501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int pos = 0, chainindex; 54601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 54701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer CHECK(*handle); 54801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (!find_label(&pos, chain, *handle)) { 54901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer errno = ENOENT; 55001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return NULL; 55101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 55201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 55301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer chainindex = entry2index(*handle, get_entry(*handle, pos)); 55401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 55501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return index2entry(*handle, chainindex + n); 55601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer} 55701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 55801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouerstatic const char *target_name(iptc_handle_t handle, struct ipt_entry *e) 55901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer{ 56001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer int spos; 56101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int labelidx; 56201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer struct ipt_entry *jumpto; 56301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 56401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (strcmp(ipt_get_target(e)->u.name, IPT_STANDARD_TARGET) != 0) 56501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return ipt_get_target(e)->u.name; 56601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 56701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Standard target: evaluate */ 56801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer spos = *(int *)ipt_get_target(e)->data; 56901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (spos < 0) { 57001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (spos == IPT_RETURN) 57101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return IPTC_LABEL_RETURN; 57201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer else if (spos == -NF_ACCEPT-1) 57301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return IPTC_LABEL_ACCEPT; 57401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer else if (spos == -NF_DROP-1) 57501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return IPTC_LABEL_DROP; 57601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer else if (spos == -NF_QUEUE-1) 57701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return IPTC_LABEL_QUEUE; 57801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 57901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer fprintf(stderr, "ERROR: off %lu/%u not a valid target (%i)\n", 58001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer entry2offset(handle, e), handle->entries.size, 581fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt spos); 58201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer abort(); 58301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 58401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 58501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer jumpto = get_entry(handle, spos); 58601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 58701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Fall through rule */ 58801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (jumpto == (void *)e + e->next_offset) 58901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return ""; 59001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 59101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Must point to head of a chain: ie. after error rule */ 59201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer labelidx = entry2index(handle, jumpto) - 1; 59301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return get_errorlabel(handle, index2offset(handle, labelidx)); 59401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer} 59501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 59601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer/* Returns a pointer to the target name of this position. */ 59701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouerconst char *iptc_get_target(const char *chain, 59801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int n, 59901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer iptc_handle_t *handle) 60001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer{ 60101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int pos = 0, chainindex; 60201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer struct ipt_entry *e; 603fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt 60401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer CHECK(*handle); 60501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (!find_label(&pos, chain, *handle)) { 60601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer errno = ENOENT; 607dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt return NULL; 60801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 609dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt 61001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer chainindex = entry2index(*handle, get_entry(*handle, pos)); 61101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer e = index2entry(*handle, chainindex + n); 61201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 61301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return target_name(*handle, e); 61401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer} 61501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 61601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer/* Is this a built-in chain? Actually returns hook + 1. */ 61701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouerint 61801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Broueriptc_builtin(const char *chain, const iptc_handle_t handle) 61901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer{ 62001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int i; 62101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 62201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer for (i = 0; i < NF_IP_NUMHOOKS; i++) { 62301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if ((handle->info.valid_hooks & (1 << i)) 62401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer && handle->hooknames[i] 625dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt && strcmp(handle->hooknames[i], chain) == 0) 626dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt return i+1; 62701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 62801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return 0; 62901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer} 63001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 63101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer/* Get the policy of a given built-in chain */ 632dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardtconst char * 633dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardtiptc_get_policy(const char *chain, 63401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer struct ipt_counters *counters, 63501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer iptc_handle_t *handle) 63601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer{ 63701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int start; 63801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer struct ipt_entry *e; 63901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer int hook; 64001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 64101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer CHECK(*handle); 642aae69bed019826ddec93f761514652a93d871e49Harald Welte hook = iptc_builtin(chain, *handle); 643aae69bed019826ddec93f761514652a93d871e49Harald Welte if (hook != 0) 644aae69bed019826ddec93f761514652a93d871e49Harald Welte start = (*handle)->info.hook_entry[hook-1]; 645aae69bed019826ddec93f761514652a93d871e49Harald Welte else 646910939897ea0cb9be2729a98c60a92e807aad5c3Jesper Dangaard Brouer return NULL; 647aae69bed019826ddec93f761514652a93d871e49Harald Welte 648aae69bed019826ddec93f761514652a93d871e49Harald Welte e = get_entry(*handle, get_chain_end(*handle, start)); 649aae69bed019826ddec93f761514652a93d871e49Harald Welte *counters = e->counters; 650aae69bed019826ddec93f761514652a93d871e49Harald Welte 651aae69bed019826ddec93f761514652a93d871e49Harald Welte return target_name(*handle, e); 652aae69bed019826ddec93f761514652a93d871e49Harald Welte} 653aae69bed019826ddec93f761514652a93d871e49Harald Welte 654aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int 655aae69bed019826ddec93f761514652a93d871e49Harald Weltecorrect_verdict(struct ipt_entry *e, 656aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned char *base, 657aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int offset, int delta_offset) 658aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 659aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_standard_target *t = (void *)ipt_get_target(e); 660aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int curr = (unsigned char *)e - base; 661aae69bed019826ddec93f761514652a93d871e49Harald Welte 662aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Trap: insert of fall-through rule. Don't change fall-through 663aae69bed019826ddec93f761514652a93d871e49Harald Welte verdict to jump-over-next-rule. */ 664aae69bed019826ddec93f761514652a93d871e49Harald Welte if (strcmp(t->target.u.name, IPT_STANDARD_TARGET) == 0 665aae69bed019826ddec93f761514652a93d871e49Harald Welte && t->verdict > (int)offset 666a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson && !(curr == offset && 667a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson t->verdict == curr + e->next_offset)) { 668a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson t->verdict += delta_offset; 669a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson } 670a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson 671a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson return 0; 672a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson} 673a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson 674a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson/* Adjusts standard verdict jump positions after an insertion/deletion. */ 675a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefssonstatic int 676a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefssonset_verdict(unsigned int offset, int delta_offset, iptc_handle_t *handle) 677a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson{ 678a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson IPT_ENTRY_ITERATE((*handle)->entries.entries, 679a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson (*handle)->entries.size, 680a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson correct_verdict, (*handle)->entries.entries, 681aae69bed019826ddec93f761514652a93d871e49Harald Welte offset, delta_offset); 682aae69bed019826ddec93f761514652a93d871e49Harald Welte 683fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt set_changed(*handle); 684aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 685aae69bed019826ddec93f761514652a93d871e49Harald Welte} 6864bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 6874bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer/* If prepend is set, then we are prepending to a chain: if the 688aae69bed019826ddec93f761514652a93d871e49Harald Welte * insertion position is an entry point, keep the entry point. */ 689aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int 690aae69bed019826ddec93f761514652a93d871e49Harald Welteinsert_rules(unsigned int num_rules, unsigned int rules_size, 691aae69bed019826ddec93f761514652a93d871e49Harald Welte const struct ipt_entry *insert, 6924bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer unsigned int offset, unsigned int num_rules_offset, 6934bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer int prepend, 6944bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer iptc_handle_t *handle) 6954bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer{ 6964bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer iptc_handle_t newh; 6974bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer struct ipt_getinfo newinfo; 6984bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer unsigned int i; 6994bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 7004bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer if (offset >= (*handle)->entries.size) { 7014bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer errno = EINVAL; 702aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 7034bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer } 7044bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 7054bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer newinfo = (*handle)->info; 706aae69bed019826ddec93f761514652a93d871e49Harald Welte 7074bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer /* Fix up entry points. */ 708aae69bed019826ddec93f761514652a93d871e49Harald Welte for (i = 0; i < NF_IP_NUMHOOKS; i++) { 709aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Entry points to START of chain, so keep same if 710aae69bed019826ddec93f761514652a93d871e49Harald Welte inserting on at that point. */ 711aae69bed019826ddec93f761514652a93d871e49Harald Welte if ((*handle)->info.hook_entry[i] > offset) 71201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer newinfo.hook_entry[i] += rules_size; 713aae69bed019826ddec93f761514652a93d871e49Harald Welte 714aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Underflow always points to END of chain (policy), 715fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt so if something is inserted at same point, it 716aae69bed019826ddec93f761514652a93d871e49Harald Welte should be advanced. */ 717aae69bed019826ddec93f761514652a93d871e49Harald Welte if ((*handle)->info.underflow[i] >= offset) 71801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer newinfo.underflow[i] += rules_size; 71901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 72001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 721aae69bed019826ddec93f761514652a93d871e49Harald Welte newh = alloc_handle((*handle)->info.name, 722aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->info.size + rules_size, 723aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->info.num_entries + num_rules); 724aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!newh) 72501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return 0; 726aae69bed019826ddec93f761514652a93d871e49Harald Welte newh->info = newinfo; 727aae69bed019826ddec93f761514652a93d871e49Harald Welte 72801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Copy pre... */ 72901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer memcpy(newh->entries.entries, (*handle)->entries.entries, offset); 730aae69bed019826ddec93f761514652a93d871e49Harald Welte /* ... Insert new ... */ 731aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(newh->entries.entries + offset, insert, rules_size); 732aae69bed019826ddec93f761514652a93d871e49Harald Welte /* ... copy post */ 733aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(newh->entries.entries + offset + rules_size, 73401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer (*handle)->entries.entries + offset, 73501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer (*handle)->entries.size - offset); 73601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 73701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Move counter map. */ 73801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Copy pre... */ 73901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer memcpy(newh->counter_map, (*handle)->counter_map, 74001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer sizeof(struct counter_map) * num_rules_offset); 74101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* ... copy post */ 74201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer memcpy(newh->counter_map + num_rules_offset + num_rules, 74301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer (*handle)->counter_map + num_rules_offset, 74401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer sizeof(struct counter_map) * ((*handle)->new_number 74501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer - num_rules_offset)); 74601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Set intermediates to no counter copy */ 74701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer for (i = 0; i < num_rules; i++) 74801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer newh->counter_map[num_rules_offset+i] 74901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer = ((struct counter_map){ COUNTER_MAP_NOMAP, 0 }); 75001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 75101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer newh->new_number = (*handle)->new_number + num_rules; 75201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer newh->entries.size = (*handle)->entries.size + rules_size; 75301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer newh->hooknames = (*handle)->hooknames; 75401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 75501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer free(*handle); 75601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer *handle = newh; 75701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 75801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return set_verdict(offset, rules_size, handle); 75901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer} 76001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 76101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouerstatic int 76201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouerdelete_rules(unsigned int num_rules, unsigned int rules_size, 76301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int offset, unsigned int num_rules_offset, 76401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer iptc_handle_t *handle) 76501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer{ 76601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer unsigned int i; 76701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 76801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (offset + rules_size > (*handle)->entries.size) { 76901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer errno = EINVAL; 77001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return 0; 77101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 77201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 77301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Fix up entry points. */ 77401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer for (i = 0; i < NF_IP_NUMHOOKS; i++) { 77501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* In practice, we never delete up to a hook entry, 77601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer since the built-in chains are always first, 77701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer so these two are never equal */ 77801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if ((*handle)->info.hook_entry[i] >= offset + rules_size) 77901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer (*handle)->info.hook_entry[i] -= rules_size; 78001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer else if ((*handle)->info.hook_entry[i] > offset) { 78101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer fprintf(stderr, "ERROR: Deleting entry %u %u %u\n", 78201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer i, (*handle)->info.hook_entry[i], offset); 78301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer abort(); 78401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } 78501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 78601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Underflow points to policy (terminal) rule in 787aae69bed019826ddec93f761514652a93d871e49Harald Welte built-in, so sequality is valid here (when deleting 788aae69bed019826ddec93f761514652a93d871e49Harald Welte the last rule). */ 789aae69bed019826ddec93f761514652a93d871e49Harald Welte if ((*handle)->info.underflow[i] >= offset + rules_size) 790aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->info.underflow[i] -= rules_size; 791aae69bed019826ddec93f761514652a93d871e49Harald Welte else if ((*handle)->info.underflow[i] > offset) { 792aae69bed019826ddec93f761514652a93d871e49Harald Welte fprintf(stderr, "ERROR: Deleting uflow %u %u %u\n", 793aae69bed019826ddec93f761514652a93d871e49Harald Welte i, (*handle)->info.underflow[i], offset); 794aae69bed019826ddec93f761514652a93d871e49Harald Welte abort(); 795aae69bed019826ddec93f761514652a93d871e49Harald Welte } 796aae69bed019826ddec93f761514652a93d871e49Harald Welte } 797aae69bed019826ddec93f761514652a93d871e49Harald Welte 798aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Move the rules down. */ 799aae69bed019826ddec93f761514652a93d871e49Harald Welte memmove((*handle)->entries.entries + offset, 800aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->entries.entries + offset + rules_size, 801aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->entries.size - (offset + rules_size)); 802aae69bed019826ddec93f761514652a93d871e49Harald Welte 803aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Move the counter map down. */ 804aae69bed019826ddec93f761514652a93d871e49Harald Welte memmove(&(*handle)->counter_map[num_rules_offset], 805aae69bed019826ddec93f761514652a93d871e49Harald Welte &(*handle)->counter_map[num_rules_offset + num_rules], 806aae69bed019826ddec93f761514652a93d871e49Harald Welte sizeof(struct counter_map) 807aae69bed019826ddec93f761514652a93d871e49Harald Welte * ((*handle)->new_number - (num_rules + num_rules_offset))); 808aae69bed019826ddec93f761514652a93d871e49Harald Welte 809aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Fix numbers */ 810aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->new_number -= num_rules; 811aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->entries.size -= rules_size; 812fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt 813aae69bed019826ddec93f761514652a93d871e49Harald Welte return set_verdict(offset, -(int)rules_size, handle); 814aae69bed019826ddec93f761514652a93d871e49Harald Welte} 815aae69bed019826ddec93f761514652a93d871e49Harald Welte 816aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int 817aae69bed019826ddec93f761514652a93d871e49Harald Weltestandard_map(struct ipt_entry *e, int verdict) 818aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 819aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_standard_target *t; 820aae69bed019826ddec93f761514652a93d871e49Harald Welte 821aae69bed019826ddec93f761514652a93d871e49Harald Welte t = (struct ipt_standard_target *)ipt_get_target(e); 822aae69bed019826ddec93f761514652a93d871e49Harald Welte 823aae69bed019826ddec93f761514652a93d871e49Harald Welte if (t->target.target_size != IPT_ALIGN(sizeof(struct ipt_standard_target))) { 824aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = EINVAL; 825aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 826aae69bed019826ddec93f761514652a93d871e49Harald Welte } 827aae69bed019826ddec93f761514652a93d871e49Harald Welte /* memset for memcmp convenience on delete/replace */ 828aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(t->target.u.name, 0, IPT_FUNCTION_MAXNAMELEN); 829aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(t->target.u.name, IPT_STANDARD_TARGET); 830aae69bed019826ddec93f761514652a93d871e49Harald Welte t->verdict = verdict; 831aae69bed019826ddec93f761514652a93d871e49Harald Welte 832aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 833aae69bed019826ddec93f761514652a93d871e49Harald Welte} 834aae69bed019826ddec93f761514652a93d871e49Harald Welte 835aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic int 8368d1b38a064d146c77eb8fc951717663e1a713cfcMartin Josefssonmap_target(const iptc_handle_t handle, 837aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_entry *e, 838e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int offset, 839e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct ipt_entry_target *old) 840e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 841e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct ipt_entry_target *t = ipt_get_target(e); 842e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 843ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte /* Save old target (except data, which we don't change, except for 844fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt standard case, where we don't care). */ 845ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte *old = *t; 846ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte 84701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Maybe it's empty (=> fall through) */ 84801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (strcmp(t->u.name, "") == 0) 84901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return standard_map(e, offset + e->next_offset); 85001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Maybe it's a standard target name... */ 85101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer else if (strcmp(t->u.name, IPTC_LABEL_ACCEPT) == 0) 85201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return standard_map(e, -NF_ACCEPT - 1); 85301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer else if (strcmp(t->u.name, IPTC_LABEL_DROP) == 0) 85401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return standard_map(e, -NF_DROP - 1); 85501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer else if (strcmp(t->u.name, IPTC_LABEL_QUEUE) == 0) 85601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return standard_map(e, -NF_QUEUE - 1); 85701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer else if (strcmp(t->u.name, IPTC_LABEL_RETURN) == 0) 85801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return standard_map(e, IPT_RETURN); 85901444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer else if (iptc_builtin(t->u.name, handle)) { 86001444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* Can't jump to builtins. */ 86101444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer errno = EINVAL; 86201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return 0; 86301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer } else { 864ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte /* Maybe it's an existing chain name. */ 8659d3ed77341361674994f584ff69a61f31a342739Olaf Rempel unsigned int exists; 8669d3ed77341361674994f584ff69a61f31a342739Olaf Rempel 86701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer if (find_label(&exists, t->u.name, handle)) 868feca0578a5d035122b4b7cdb8d44d6cca819f35cRobert de Barth return standard_map(e, exists); 8699d3ed77341361674994f584ff69a61f31a342739Olaf Rempel } 8709d3ed77341361674994f584ff69a61f31a342739Olaf Rempel 8719d3ed77341361674994f584ff69a61f31a342739Olaf Rempel /* Must be a module? If not, kernel will reject... */ 87201444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer /* memset to all 0 for your memcmp convenience. */ 87301444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer memset(t->u.name + strlen(t->u.name), 87401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer 0, 87501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer IPT_FUNCTION_MAXNAMELEN - strlen(t->u.name)); 87601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer return 1; 87701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer} 878ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte 879ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Weltestatic void 880ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welteunmap_target(struct ipt_entry *e, struct ipt_entry_target *old) 881ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte{ 882ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte struct ipt_entry_target *t = ipt_get_target(e); 883ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte 884ec30b6c4d3ebb09d2c05e44f3904428893ef13bdHarald Welte /* Save old target (except data, which we don't change, except for 885aae69bed019826ddec93f761514652a93d871e49Harald Welte standard case, where we don't care). */ 886aae69bed019826ddec93f761514652a93d871e49Harald Welte *t = *old; 887fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt} 888aae69bed019826ddec93f761514652a93d871e49Harald Welte 889e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Insert the entry `fw' in chain `chain' into position `rulenum'. */ 8901336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouerint 8911336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Broueriptc_insert_entry(const ipt_chainlabel chain, 8921336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer const struct ipt_entry *e, 893aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int rulenum, 894e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher iptc_handle_t *handle) 895aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 896aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int chainoff, chainindex, offset; 897e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct ipt_entry_target old; 8981336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer int ret; 8991336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer 9001336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer CHECK(*handle); 9011336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer iptc_fn = iptc_insert_entry; 9021336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer if (!find_label(&chainoff, chain, *handle)) { 9031336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer errno = ENOENT; 9041336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer return 0; 9051336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer } 9061336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer 9074bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer chainindex = entry2index(*handle, get_entry(*handle, chainoff)); 908526d3e138635e33773d1ca16477052a04f53f5bdJesper Dangaard Brouer 909526d3e138635e33773d1ca16477052a04f53f5bdJesper Dangaard Brouer if (index2entry(*handle, chainindex + rulenum) 9101336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer > get_entry(*handle, get_chain_end(*handle, chainoff))) { 9114bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer errno = E2BIG; 9121336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer return 0; 9134bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer } 9144bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer offset = index2offset(*handle, chainindex + rulenum); 9154bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 9164bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer /* Mapping target actually alters entry, but that's 9174bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer transparent to the caller. */ 9184bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer if (!map_target(*handle, (struct ipt_entry *)e, offset, &old)) 9194bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer return 0; 9204bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer 9214bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer ret = insert_rules(1, e->next_offset, e, offset, 9224bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer chainindex + rulenum, rulenum == 0, handle); 9231336451ead58d608618ff5b0a251d132b73f9866Jesper Dangaard Brouer unmap_target((struct ipt_entry *)e, &old); 924d8cb787ab44e9d2de4fd3b04fcaa370c9918fc5dJesper Dangaard Brouer CHECK(*handle); 925aae69bed019826ddec93f761514652a93d871e49Harald Welte return ret; 926e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 927e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 928aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Atomically replace rule `rulenum' in `chain' with `fw'. */ 929aae69bed019826ddec93f761514652a93d871e49Harald Welteint 930fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardtiptc_replace_entry(const ipt_chainlabel chain, 931aae69bed019826ddec93f761514652a93d871e49Harald Welte const struct ipt_entry *e, 932aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int rulenum, 933e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher iptc_handle_t *handle) 934aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 935aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int chainoff, chainindex, offset; 936aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_entry_target old; 937aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret; 938aae69bed019826ddec93f761514652a93d871e49Harald Welte 939aae69bed019826ddec93f761514652a93d871e49Harald Welte CHECK(*handle); 940aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = iptc_replace_entry; 941aae69bed019826ddec93f761514652a93d871e49Harald Welte 942aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!find_label(&chainoff, chain, *handle)) { 943aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 944aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 945aae69bed019826ddec93f761514652a93d871e49Harald Welte } 946aae69bed019826ddec93f761514652a93d871e49Harald Welte 947aae69bed019826ddec93f761514652a93d871e49Harald Welte chainindex = entry2index(*handle, get_entry(*handle, chainoff)); 948aae69bed019826ddec93f761514652a93d871e49Harald Welte 949aae69bed019826ddec93f761514652a93d871e49Harald Welte if (index2entry(*handle, chainindex + rulenum) 950aae69bed019826ddec93f761514652a93d871e49Harald Welte >= get_entry(*handle, get_chain_end(*handle, chainoff))) { 951aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = E2BIG; 952aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 953aae69bed019826ddec93f761514652a93d871e49Harald Welte } 954aae69bed019826ddec93f761514652a93d871e49Harald Welte 955aae69bed019826ddec93f761514652a93d871e49Harald Welte offset = index2offset(*handle, chainindex + rulenum); 956aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Replace = delete and insert. */ 957aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!delete_rules(1, get_entry(*handle, offset)->next_offset, 958aae69bed019826ddec93f761514652a93d871e49Harald Welte offset, chainindex + rulenum, handle)) 959aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 960aae69bed019826ddec93f761514652a93d871e49Harald Welte 961aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!map_target(*handle, (struct ipt_entry *)e, offset, &old)) 96248bde40e73b45ad134d32cde88b779fe509faf64Jesper Dangaard Brouer return 0; 963aae69bed019826ddec93f761514652a93d871e49Harald Welte CHECK(*handle); 964aae69bed019826ddec93f761514652a93d871e49Harald Welte 965aae69bed019826ddec93f761514652a93d871e49Harald Welte ret = insert_rules(1, e->next_offset, e, offset, 966aae69bed019826ddec93f761514652a93d871e49Harald Welte chainindex + rulenum, 1, handle); 967aae69bed019826ddec93f761514652a93d871e49Harald Welte unmap_target((struct ipt_entry *)e, &old); 968aae69bed019826ddec93f761514652a93d871e49Harald Welte CHECK(*handle); 969aae69bed019826ddec93f761514652a93d871e49Harald Welte return ret; 970aae69bed019826ddec93f761514652a93d871e49Harald Welte} 971aae69bed019826ddec93f761514652a93d871e49Harald Welte 972aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Append entry `fw' to chain `chain'. Equivalent to insert with 973aae69bed019826ddec93f761514652a93d871e49Harald Welte rulenum = length of chain. */ 974aae69bed019826ddec93f761514652a93d871e49Harald Welteint 975aae69bed019826ddec93f761514652a93d871e49Harald Welteiptc_append_entry(const ipt_chainlabel chain, 976aae69bed019826ddec93f761514652a93d871e49Harald Welte const struct ipt_entry *e, 977aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_handle_t *handle) 978aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 979aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int startoff, endoff; 980aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_entry_target old; 981aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret; 982aae69bed019826ddec93f761514652a93d871e49Harald Welte 983aae69bed019826ddec93f761514652a93d871e49Harald Welte CHECK(*handle); 984aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = iptc_append_entry; 985aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!find_label(&startoff, chain, *handle)) { 986aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 987aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 988aae69bed019826ddec93f761514652a93d871e49Harald Welte } 989aae69bed019826ddec93f761514652a93d871e49Harald Welte 990aae69bed019826ddec93f761514652a93d871e49Harald Welte endoff = get_chain_end(*handle, startoff); 991aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!map_target(*handle, (struct ipt_entry *)e, endoff, &old)) 992aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 993aae69bed019826ddec93f761514652a93d871e49Harald Welte 994aae69bed019826ddec93f761514652a93d871e49Harald Welte ret = insert_rules(1, e->next_offset, e, endoff, 995aae69bed019826ddec93f761514652a93d871e49Harald Welte entry2index(*handle, get_entry(*handle, endoff)), 996aae69bed019826ddec93f761514652a93d871e49Harald Welte 0, handle); 997aae69bed019826ddec93f761514652a93d871e49Harald Welte unmap_target((struct ipt_entry *)e, &old); 998aae69bed019826ddec93f761514652a93d871e49Harald Welte CHECK(*handle); 999aae69bed019826ddec93f761514652a93d871e49Harald Welte return ret; 1000aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1001aae69bed019826ddec93f761514652a93d871e49Harald Welte 1002aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline int 1003aae69bed019826ddec93f761514652a93d871e49Harald Weltematch_different(const struct ipt_entry_match *a, 1004aae69bed019826ddec93f761514652a93d871e49Harald Welte const unsigned char *a_elems, 1005aae69bed019826ddec93f761514652a93d871e49Harald Welte const unsigned char *b_elems, 1006aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned char **maskptr) 1007aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1008aae69bed019826ddec93f761514652a93d871e49Harald Welte const struct ipt_entry_match *b; 1009aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int i; 1010aae69bed019826ddec93f761514652a93d871e49Harald Welte 1011aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Offset of b is the same as a. */ 1012aae69bed019826ddec93f761514652a93d871e49Harald Welte b = (void *)b_elems + ((unsigned char *)a-a_elems); 1013aae69bed019826ddec93f761514652a93d871e49Harald Welte 1014aae69bed019826ddec93f761514652a93d871e49Harald Welte if (a->match_size != b->match_size) 1015aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1016aae69bed019826ddec93f761514652a93d871e49Harald Welte 1017aae69bed019826ddec93f761514652a93d871e49Harald Welte if (strcmp(a->u.name, b->u.name) != 0) 1018aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1019aae69bed019826ddec93f761514652a93d871e49Harald Welte 1020aae69bed019826ddec93f761514652a93d871e49Harald Welte *maskptr += sizeof(*a); 1021aae69bed019826ddec93f761514652a93d871e49Harald Welte 1022aae69bed019826ddec93f761514652a93d871e49Harald Welte for (i = 0; i < a->match_size - sizeof(*a); i++) 1023aae69bed019826ddec93f761514652a93d871e49Harald Welte if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0) 1024aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 102552c380208a87191a8c25608d2c501c0dc32aa9adMartin Josefsson *maskptr += i; 102652c380208a87191a8c25608d2c501c0dc32aa9adMartin Josefsson return 0; 102752c380208a87191a8c25608d2c501c0dc32aa9adMartin Josefsson} 1028aae69bed019826ddec93f761514652a93d871e49Harald Welte 1029aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline int 1030aae69bed019826ddec93f761514652a93d871e49Harald Weltetarget_different(const unsigned char *a_targdata, 10318d1b38a064d146c77eb8fc951717663e1a713cfcMartin Josefsson const unsigned char *b_targdata, 1032aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int tdatasize, 1033aae69bed019826ddec93f761514652a93d871e49Harald Welte const unsigned char *mask) 1034aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1035aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int i; 1036e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher for (i = 0; i < tdatasize; i++) 1037e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (((a_targdata[i] ^ b_targdata[i]) & mask[i]) != 0) 1038aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1039aae69bed019826ddec93f761514652a93d871e49Harald Welte 1040fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt return 0; 1041e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1042aae69bed019826ddec93f761514652a93d871e49Harald Welte 1043aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline int 1044aae69bed019826ddec93f761514652a93d871e49Harald Welteis_same(const struct ipt_entry *a, const struct ipt_entry *b, 1045aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned char *matchmask) 10464bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer{ 10474bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer unsigned int i; 10484bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer struct ipt_entry_target *ta, *tb; 10494bae3f1001028ee283a5e1fcea4a561b0068f95dJesper Dangaard Brouer unsigned char *mptr; 1050aae69bed019826ddec93f761514652a93d871e49Harald Welte 1051aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Always compare head structures: ignore mask here. */ 1052aae69bed019826ddec93f761514652a93d871e49Harald Welte if (a->ip.src.s_addr != b->ip.src.s_addr 1053aae69bed019826ddec93f761514652a93d871e49Harald Welte || a->ip.dst.s_addr != b->ip.dst.s_addr 105401444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer || a->ip.smsk.s_addr != b->ip.smsk.s_addr 105501444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer || a->ip.smsk.s_addr != b->ip.smsk.s_addr 105601444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer || a->ip.proto != b->ip.proto 105701444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer || a->ip.flags != b->ip.flags 105801444da4cb70417d2dc2643e2d48c70de7ff8e96Jesper Dangaard Brouer || a->ip.invflags != b->ip.invflags) 1059aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1060aae69bed019826ddec93f761514652a93d871e49Harald Welte 1061aae69bed019826ddec93f761514652a93d871e49Harald Welte for (i = 0; i < IFNAMSIZ; i++) { 1062aae69bed019826ddec93f761514652a93d871e49Harald Welte if (a->ip.iniface_mask[i] != b->ip.iniface_mask[i]) 1063dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt return 0; 1064aae69bed019826ddec93f761514652a93d871e49Harald Welte if ((a->ip.iniface[i] & a->ip.iniface_mask[i]) 1065aae69bed019826ddec93f761514652a93d871e49Harald Welte != (b->ip.iniface[i] & b->ip.iniface_mask[i])) 1066aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1067aae69bed019826ddec93f761514652a93d871e49Harald Welte if (a->ip.outiface_mask[i] != b->ip.outiface_mask[i]) 1068aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1069aae69bed019826ddec93f761514652a93d871e49Harald Welte if ((a->ip.outiface[i] & a->ip.outiface_mask[i]) 1070dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt != (b->ip.outiface[i] & b->ip.outiface_mask[i])) 1071dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt return 0; 1072aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1073dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt 1074dbb77543ad6afe29e9a1881b2d4fc212de621a55Jan Engelhardt if (a->nfcache != b->nfcache 1075aae69bed019826ddec93f761514652a93d871e49Harald Welte || a->target_offset != b->target_offset 1076aae69bed019826ddec93f761514652a93d871e49Harald Welte || a->next_offset != b->next_offset) 1077aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1078aae69bed019826ddec93f761514652a93d871e49Harald Welte 10790113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte mptr = matchmask + sizeof(struct ipt_entry); 10809e03380e9f78ae347ae4f3f041c4eca50348f2e8Harald Welte if (IPT_MATCH_ITERATE(a, match_different, a->elems, b->elems, &mptr)) 1081aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1082aae69bed019826ddec93f761514652a93d871e49Harald Welte 1083aae69bed019826ddec93f761514652a93d871e49Harald Welte ta = ipt_get_target((struct ipt_entry *)a); 1084aae69bed019826ddec93f761514652a93d871e49Harald Welte tb = ipt_get_target((struct ipt_entry *)b); 1085aae69bed019826ddec93f761514652a93d871e49Harald Welte if (ta->target_size != tb->target_size) 1086aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1087aae69bed019826ddec93f761514652a93d871e49Harald Welte if (strcmp(ta->u.name, tb->u.name) != 0) 1088aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1089aae69bed019826ddec93f761514652a93d871e49Harald Welte 1090aae69bed019826ddec93f761514652a93d871e49Harald Welte mptr += sizeof(*ta); 1091aae69bed019826ddec93f761514652a93d871e49Harald Welte if (target_different(ta->data, tb->data, 1092aae69bed019826ddec93f761514652a93d871e49Harald Welte ta->target_size - sizeof(*ta), mptr)) 1093aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1094aae69bed019826ddec93f761514652a93d871e49Harald Welte 1095aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1096aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1097aae69bed019826ddec93f761514652a93d871e49Harald Welte 1098aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Delete the first rule in `chain' which matches `fw'. */ 1099aae69bed019826ddec93f761514652a93d871e49Harald Welteint 1100aae69bed019826ddec93f761514652a93d871e49Harald Welteiptc_delete_entry(const ipt_chainlabel chain, 1101aae69bed019826ddec93f761514652a93d871e49Harald Welte const struct ipt_entry *origfw, 1102aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned char *matchmask, 1103aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_handle_t *handle) 1104aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1105aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int offset, lastoff; 1106aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_entry *e, *fw; 1107aae69bed019826ddec93f761514652a93d871e49Harald Welte 1108aae69bed019826ddec93f761514652a93d871e49Harald Welte CHECK(*handle); 1109aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = iptc_delete_entry; 1110aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!find_label(&offset, chain, *handle)) { 1111fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt errno = ENOENT; 11120113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 1113aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1114aae69bed019826ddec93f761514652a93d871e49Harald Welte 1115aae69bed019826ddec93f761514652a93d871e49Harald Welte fw = malloc(origfw->next_offset); 1116aae69bed019826ddec93f761514652a93d871e49Harald Welte if (fw == NULL) { 1117aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOMEM; 1118aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1119aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1120aae69bed019826ddec93f761514652a93d871e49Harald Welte lastoff = get_chain_end(*handle, offset); 1121aae69bed019826ddec93f761514652a93d871e49Harald Welte 1122aae69bed019826ddec93f761514652a93d871e49Harald Welte for (; offset < lastoff; offset += e->next_offset) { 1123aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_entry_target discard; 1124aae69bed019826ddec93f761514652a93d871e49Harald Welte 1125aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(fw, origfw, origfw->next_offset); 1126aae69bed019826ddec93f761514652a93d871e49Harald Welte 1127aae69bed019826ddec93f761514652a93d871e49Harald Welte /* FIXME: handle this in is_same --RR */ 1128aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!map_target(*handle, fw, offset, &discard)) { 1129aae69bed019826ddec93f761514652a93d871e49Harald Welte free(fw); 1130aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1131aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1132aae69bed019826ddec93f761514652a93d871e49Harald Welte e = get_entry(*handle, offset); 1133e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1134e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher#if 0 1135aae69bed019826ddec93f761514652a93d871e49Harald Welte printf("Deleting:\n"); 1136fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt dump_entry(newe); 11373ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte#endif 1138aae69bed019826ddec93f761514652a93d871e49Harald Welte if (is_same(e, fw, matchmask)) { 1139aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret; 1140aae69bed019826ddec93f761514652a93d871e49Harald Welte ret = delete_rules(1, e->next_offset, 1141aae69bed019826ddec93f761514652a93d871e49Harald Welte offset, entry2index(*handle, e), 1142aae69bed019826ddec93f761514652a93d871e49Harald Welte handle); 1143aae69bed019826ddec93f761514652a93d871e49Harald Welte free(fw); 1144aae69bed019826ddec93f761514652a93d871e49Harald Welte CHECK(*handle); 1145aae69bed019826ddec93f761514652a93d871e49Harald Welte return ret; 1146aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1147aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1148aae69bed019826ddec93f761514652a93d871e49Harald Welte 1149aae69bed019826ddec93f761514652a93d871e49Harald Welte free(fw); 1150aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 1151aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1152aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1153aae69bed019826ddec93f761514652a93d871e49Harald Welte 1154aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Delete the rule in position `rulenum' in `chain'. */ 1155aae69bed019826ddec93f761514652a93d871e49Harald Welteint 1156aae69bed019826ddec93f761514652a93d871e49Harald Welteiptc_delete_num_entry(const ipt_chainlabel chain, 1157aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int rulenum, 1158aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_handle_t *handle) 1159aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1160aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int chainstart; 1161aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int index; 1162aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret; 1163aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_entry *e; 1164aae69bed019826ddec93f761514652a93d871e49Harald Welte 1165aae69bed019826ddec93f761514652a93d871e49Harald Welte CHECK(*handle); 1166aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = iptc_delete_num_entry; 1167aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!find_label(&chainstart, chain, *handle)) { 1168aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 1169aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1170aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1171aae69bed019826ddec93f761514652a93d871e49Harald Welte 1172aae69bed019826ddec93f761514652a93d871e49Harald Welte index = entry2index(*handle, get_entry(*handle, chainstart)) 1173aae69bed019826ddec93f761514652a93d871e49Harald Welte + rulenum; 1174aae69bed019826ddec93f761514652a93d871e49Harald Welte 1175aae69bed019826ddec93f761514652a93d871e49Harald Welte if (index 1176aae69bed019826ddec93f761514652a93d871e49Harald Welte >= entry2index(*handle, 1177aae69bed019826ddec93f761514652a93d871e49Harald Welte get_entry(*handle, 1178aae69bed019826ddec93f761514652a93d871e49Harald Welte get_chain_end(*handle, chainstart)))) { 1179aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = E2BIG; 1180aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 11813ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte } 11823ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte 1183aae69bed019826ddec93f761514652a93d871e49Harald Welte e = index2entry(*handle, index); 1184fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt if (e == NULL) { 1185efa8fc2123a2a9fc229ab471edd2b2688ce1da3aHarald Welte errno = EINVAL; 11863ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte return 0; 1187aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1188aae69bed019826ddec93f761514652a93d871e49Harald Welte 1189aae69bed019826ddec93f761514652a93d871e49Harald Welte ret = delete_rules(1, e->next_offset, entry2offset(*handle, e), 1190aae69bed019826ddec93f761514652a93d871e49Harald Welte index, handle); 1191aae69bed019826ddec93f761514652a93d871e49Harald Welte CHECK(*handle); 1192aae69bed019826ddec93f761514652a93d871e49Harald Welte return ret; 1193aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1194aae69bed019826ddec93f761514652a93d871e49Harald Welte 1195aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Check the packet `fw' on chain `chain'. Returns the verdict, or 1196aae69bed019826ddec93f761514652a93d871e49Harald Welte NULL and sets errno. */ 1197aae69bed019826ddec93f761514652a93d871e49Harald Welteconst char * 1198aae69bed019826ddec93f761514652a93d871e49Harald Welteiptc_check_packet(const ipt_chainlabel chain, 1199aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_entry *entry, 1200aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_handle_t *handle) 1201aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1202aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOSYS; 1203aae69bed019826ddec93f761514652a93d871e49Harald Welte return NULL; 1204aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1205aae69bed019826ddec93f761514652a93d871e49Harald Welte 1206aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Flushes the entries in the given chain (ie. empties chain). */ 1207aae69bed019826ddec93f761514652a93d871e49Harald Welteint 1208aae69bed019826ddec93f761514652a93d871e49Harald Welteiptc_flush_entries(const ipt_chainlabel chain, iptc_handle_t *handle) 1209aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1210aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int startoff, endoff, startindex, endindex; 1211aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret; 1212aae69bed019826ddec93f761514652a93d871e49Harald Welte 1213aae69bed019826ddec93f761514652a93d871e49Harald Welte CHECK(*handle); 1214aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_fn = iptc_flush_entries; 1215aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!find_label(&startoff, chain, *handle)) { 12163ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte errno = ENOENT; 12173ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte return 0; 1218aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1219fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt endoff = get_chain_end(*handle, startoff); 1220aae69bed019826ddec93f761514652a93d871e49Harald Welte startindex = entry2index(*handle, get_entry(*handle, startoff)); 1221aae69bed019826ddec93f761514652a93d871e49Harald Welte endindex = entry2index(*handle, get_entry(*handle, endoff)); 1222aae69bed019826ddec93f761514652a93d871e49Harald Welte 1223aae69bed019826ddec93f761514652a93d871e49Harald Welte ret = delete_rules(endindex - startindex, 12243ea8f40262386e6b1445a617841f28702fe74d9dHarald Welte endoff - startoff, startoff, startindex, 1225aae69bed019826ddec93f761514652a93d871e49Harald Welte handle); 1226aae69bed019826ddec93f761514652a93d871e49Harald Welte CHECK(*handle); 1227aae69bed019826ddec93f761514652a93d871e49Harald Welte return ret; 1228aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1229aae69bed019826ddec93f761514652a93d871e49Harald Welte 1230aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Zeroes the counters in a chain. */ 1231aae69bed019826ddec93f761514652a93d871e49Harald Welteint 1232aae69bed019826ddec93f761514652a93d871e49Harald Welteiptc_zero_entries(const ipt_chainlabel chain, iptc_handle_t *handle) 1233aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1234aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int i, end; 1235aae69bed019826ddec93f761514652a93d871e49Harald Welte 1236aae69bed019826ddec93f761514652a93d871e49Harald Welte CHECK(*handle); 1237aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!find_label(&i, chain, *handle)) { 1238aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 1239aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1240aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1241aae69bed019826ddec93f761514652a93d871e49Harald Welte end = get_chain_end(*handle, i); 1242fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt 12430113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte i = entry2index(*handle, get_entry(*handle, i)); 1244aae69bed019826ddec93f761514652a93d871e49Harald Welte end = entry2index(*handle, get_entry(*handle, end)); 1245aae69bed019826ddec93f761514652a93d871e49Harald Welte 12460113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte for (; i <= end; i++) { 1247aae69bed019826ddec93f761514652a93d871e49Harald Welte if ((*handle)->counter_map[i].maptype ==COUNTER_MAP_NORMAL_MAP) 1248aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->counter_map[i].maptype = COUNTER_MAP_ZEROED; 1249aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1250aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 1251aae69bed019826ddec93f761514652a93d871e49Harald Welte 12520113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte CHECK(*handle); 12530113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 1; 1254aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1255aae69bed019826ddec93f761514652a93d871e49Harald Welte 1256aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Creates a new chain. */ 1257aae69bed019826ddec93f761514652a93d871e49Harald Welte/* To create a chain, create two rules: error node and unconditional 1258aae69bed019826ddec93f761514652a93d871e49Harald Welte * return. */ 1259aae69bed019826ddec93f761514652a93d871e49Harald Welteint 1260aae69bed019826ddec93f761514652a93d871e49Harald Welteiptc_create_chain(const ipt_chainlabel chain, iptc_handle_t *handle) 1261aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1262aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int pos; 1263aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret; 12640113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte struct { 1265e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct ipt_entry head; 1266aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_error_target name; 1267aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_entry ret; 1268aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_standard_target target; 1269aae69bed019826ddec93f761514652a93d871e49Harald Welte } newc; 1270e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1271fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt CHECK(*handle); 12720113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte iptc_fn = iptc_create_chain; 1273e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1274e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* find_label doesn't cover built-in targets: DROP, ACCEPT, 1275fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt QUEUE, RETURN. */ 1276e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (find_label(&pos, chain, *handle) 1277aae69bed019826ddec93f761514652a93d871e49Harald Welte || strcmp(chain, IPTC_LABEL_DROP) == 0 1278e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher || strcmp(chain, IPTC_LABEL_ACCEPT) == 0 1279aae69bed019826ddec93f761514652a93d871e49Harald Welte || strcmp(chain, IPTC_LABEL_QUEUE) == 0 1280aae69bed019826ddec93f761514652a93d871e49Harald Welte || strcmp(chain, IPTC_LABEL_RETURN) == 0) { 1281e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EEXIST; 1282e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1283e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1284aae69bed019826ddec93f761514652a93d871e49Harald Welte 1285aae69bed019826ddec93f761514652a93d871e49Harald Welte if (strlen(chain)+1 > sizeof(ipt_chainlabel)) { 1286e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher errno = EINVAL; 1287aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 12880371c0c5eb17c81e8dd44c4aa31b58318e9b7b72Harald Welte } 1289aae69bed019826ddec93f761514652a93d871e49Harald Welte 1290aae69bed019826ddec93f761514652a93d871e49Harald Welte memset(&newc, 0, sizeof(newc)); 1291aae69bed019826ddec93f761514652a93d871e49Harald Welte newc.head.target_offset = sizeof(struct ipt_entry); 1292aae69bed019826ddec93f761514652a93d871e49Harald Welte newc.head.next_offset 12930371c0c5eb17c81e8dd44c4aa31b58318e9b7b72Harald Welte = sizeof(struct ipt_entry) + sizeof(struct ipt_error_target); 1294e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(newc.name.t.u.name, IPT_ERROR_TARGET); 1295e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newc.name.t.target_size = sizeof(struct ipt_error_target); 1296aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(newc.name.error, chain); 1297aae69bed019826ddec93f761514652a93d871e49Harald Welte 1298aae69bed019826ddec93f761514652a93d871e49Harald Welte newc.ret.target_offset = sizeof(struct ipt_entry); 1299aae69bed019826ddec93f761514652a93d871e49Harald Welte newc.ret.next_offset 1300aae69bed019826ddec93f761514652a93d871e49Harald Welte = sizeof(struct ipt_entry)+sizeof(struct ipt_standard_target); 1301e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(newc.target.target.u.name, IPT_STANDARD_TARGET); 1302e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newc.target.target.target_size = sizeof(struct ipt_standard_target); 1303aae69bed019826ddec93f761514652a93d871e49Harald Welte newc.target.verdict = IPT_RETURN; 1304fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt 130579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell /* Add just before terminal entry */ 1306e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher ret = insert_rules(2, sizeof(newc), &newc.head, 1307fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt index2offset(*handle, (*handle)->new_number - 1), 130879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell (*handle)->new_number - 1, 1309efa8fc2123a2a9fc229ab471edd2b2688ce1da3aHarald Welte 0, handle); 1310e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher CHECK(*handle); 1311175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt return ret; 1312e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 131379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell 1314e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherstatic int 1315841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefssoncount_ref(struct ipt_entry *e, unsigned int offset, unsigned int *ref) 1316841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson{ 1317841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson struct ipt_standard_target *t; 1318841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 1319175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt if (strcmp(ipt_get_target(e)->u.name, IPT_STANDARD_TARGET) == 0) { 1320175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt t = (struct ipt_standard_target *)ipt_get_target(e); 1321175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt 1322175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt if (t->verdict == offset) 1323175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt (*ref)++; 13242f93205b375ee9f5a383f8041749a9b989012dd0Patrick McHardy } 1325e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1326841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson return 0; 1327e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1328664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates 1329175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt/* Get the number of references to this chain. */ 1330e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucherint 1331664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Patesiptc_get_references(unsigned int *ref, const ipt_chainlabel chain, 1332e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher iptc_handle_t *handle) 1333aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1334aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int offset; 1335aae69bed019826ddec93f761514652a93d871e49Harald Welte 13360113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte CHECK(*handle); 1337841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson if (!find_label(&offset, chain, *handle)) { 1338175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt errno = ENOENT; 1339e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1340841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson } 1341e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1342e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher *ref = 0; 1343175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt IPT_ENTRY_ITERATE((*handle)->entries.entries, 1344e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher (*handle)->entries.size, 13450113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte count_ref, offset, ref); 1346aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1347e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 134879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell 1349e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Deletes a chain. */ 1350175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardtint 1351aae69bed019826ddec93f761514652a93d871e49Harald Welteiptc_delete_chain(const ipt_chainlabel chain, iptc_handle_t *handle) 1352aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1353aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int chainoff, labelidx, labeloff; 1354aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int references; 1355aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_entry *e; 1356aae69bed019826ddec93f761514652a93d871e49Harald Welte int ret; 1357aae69bed019826ddec93f761514652a93d871e49Harald Welte 1358aae69bed019826ddec93f761514652a93d871e49Harald Welte CHECK(*handle); 1359aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!iptc_get_references(&references, chain, handle)) 1360aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1361aae69bed019826ddec93f761514652a93d871e49Harald Welte 1362e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher iptc_fn = iptc_delete_chain; 1363aae69bed019826ddec93f761514652a93d871e49Harald Welte 1364aae69bed019826ddec93f761514652a93d871e49Harald Welte if (iptc_builtin(chain, *handle)) { 1365aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = EINVAL; 1366aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 13677e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell } 1368e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1369e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (references > 0) { 1370aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = EMLINK; 13711c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt return 0; 13722f93205b375ee9f5a383f8041749a9b989012dd0Patrick McHardy } 13732f93205b375ee9f5a383f8041749a9b989012dd0Patrick McHardy 13742f93205b375ee9f5a383f8041749a9b989012dd0Patrick McHardy if (!find_label(&chainoff, chain, *handle)) { 1375aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 1376e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 1377e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1378841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson 13791c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt e = get_entry(*handle, chainoff); 1380841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson if (get_chain_end(*handle, chainoff) != chainoff) { 1381aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOTEMPTY; 1382aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1383664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates } 1384175f451104532f3054b1824695d16a4ee1d8ea34Jan Engelhardt 1385aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Need label index: preceeds chain start */ 13861c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt labelidx = entry2index(*handle, e) - 1; 1387aae69bed019826ddec93f761514652a93d871e49Harald Welte labeloff = index2offset(*handle, labelidx); 1388aae69bed019826ddec93f761514652a93d871e49Harald Welte 1389aae69bed019826ddec93f761514652a93d871e49Harald Welte ret = delete_rules(2, 1390aae69bed019826ddec93f761514652a93d871e49Harald Welte get_entry(*handle, labeloff)->next_offset 1391aae69bed019826ddec93f761514652a93d871e49Harald Welte + e->next_offset, 1392aae69bed019826ddec93f761514652a93d871e49Harald Welte labeloff, labelidx, handle); 1393aae69bed019826ddec93f761514652a93d871e49Harald Welte CHECK(*handle); 1394aae69bed019826ddec93f761514652a93d871e49Harald Welte return ret; 1395aae69bed019826ddec93f761514652a93d871e49Harald Welte} 13961c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt 1397aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Renames a chain. */ 13981c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardtint iptc_rename_chain(const ipt_chainlabel oldname, 13991c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt const ipt_chainlabel newname, 1400841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson iptc_handle_t *handle) 1401841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson{ 1402e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int chainoff, labeloff, labelidx; 140379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell struct ipt_error_target *t; 1404e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1405228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell CHECK(*handle); 1406e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher iptc_fn = iptc_rename_chain; 1407e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1408e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* find_label doesn't cover built-in targets: DROP, ACCEPT 1409fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt RETURN. */ 141079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (find_label(&chainoff, newname, *handle) 1411e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher || strcmp(newname, IPTC_LABEL_DROP) == 0 1412fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt || strcmp(newname, IPTC_LABEL_ACCEPT) == 0 1413e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher || strcmp(newname, IPTC_LABEL_RETURN) == 0) { 1414664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates errno = EEXIST; 1415e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return 0; 141697fb2f1579f0794377db1dca7c5bb07fade1a0dcPatrick McHardy } 1417e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell 14188b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt if (!find_label(&chainoff, oldname, *handle) 1419e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher || iptc_builtin(oldname, *handle)) { 1420d73af64b9d28a5b0309104232c848e8ca8ab6956Jan Engelhardt errno = ENOENT; 142167088e73ce7707229c56987868f112051defca5aRusty Russell return 0; 142267088e73ce7707229c56987868f112051defca5aRusty Russell } 142367088e73ce7707229c56987868f112051defca5aRusty Russell 142467088e73ce7707229c56987868f112051defca5aRusty Russell if (strlen(newname)+1 > sizeof(ipt_chainlabel)) { 142567088e73ce7707229c56987868f112051defca5aRusty Russell errno = EINVAL; 1426d73af64b9d28a5b0309104232c848e8ca8ab6956Jan Engelhardt return 0; 142767088e73ce7707229c56987868f112051defca5aRusty Russell } 142867088e73ce7707229c56987868f112051defca5aRusty Russell 142967088e73ce7707229c56987868f112051defca5aRusty Russell /* Need label index: preceeds chain start */ 143067088e73ce7707229c56987868f112051defca5aRusty Russell labelidx = entry2index(*handle, get_entry(*handle, chainoff)) - 1; 143167088e73ce7707229c56987868f112051defca5aRusty Russell labeloff = index2offset(*handle, labelidx); 1432e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1433aae69bed019826ddec93f761514652a93d871e49Harald Welte t = (struct ipt_error_target *) 143479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell ipt_get_target(get_entry(*handle, labeloff)); 14350113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1436e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher memset(t->error, 0, sizeof(t->error)); 1437e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(t->error, newname); 1438fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt set_changed(*handle); 1439e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1440664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates CHECK(*handle); 1441aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1442e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1443e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1444fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt/* Sets the policy on a built-in chain. */ 1445aae69bed019826ddec93f761514652a93d871e49Harald Welteint 1446aae69bed019826ddec93f761514652a93d871e49Harald Welteiptc_set_policy(const ipt_chainlabel chain, 1447aae69bed019826ddec93f761514652a93d871e49Harald Welte const ipt_chainlabel policy, 1448aae69bed019826ddec93f761514652a93d871e49Harald Welte iptc_handle_t *handle) 1449aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1450aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int hook; 1451aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int policyoff; 1452aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_entry *e; 1453aae69bed019826ddec93f761514652a93d871e49Harald Welte struct ipt_standard_target *t; 1454e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 145530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell CHECK(*handle); 1456e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher iptc_fn = iptc_set_policy; 14571c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt /* Figure out which chain. */ 1458e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher hook = iptc_builtin(chain, *handle); 14591c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (hook == 0) { 1460aae69bed019826ddec93f761514652a93d871e49Harald Welte errno = ENOENT; 1461aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1462aae69bed019826ddec93f761514652a93d871e49Harald Welte } else 1463aae69bed019826ddec93f761514652a93d871e49Harald Welte hook--; 1464aae69bed019826ddec93f761514652a93d871e49Harald Welte 14651c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt policyoff = get_chain_end(*handle, (*handle)->info.hook_entry[hook]); 1466aae69bed019826ddec93f761514652a93d871e49Harald Welte if (policyoff != (*handle)->info.underflow[hook]) { 14670113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte printf("ERROR: Policy for `%s' offset %u != underflow %u\n", 1468aae69bed019826ddec93f761514652a93d871e49Harald Welte chain, policyoff, (*handle)->info.underflow[hook]); 14690113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 14701c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt } 14711c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt 147230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell e = get_entry(*handle, policyoff); 1473aae69bed019826ddec93f761514652a93d871e49Harald Welte t = (struct ipt_standard_target *)ipt_get_target(e); 1474aae69bed019826ddec93f761514652a93d871e49Harald Welte 147530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell if (strcmp(policy, IPTC_LABEL_ACCEPT) == 0) 147630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell t->verdict = -NF_ACCEPT - 1; 147730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell else if (strcmp(policy, IPTC_LABEL_DROP) == 0) 147830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell t->verdict = -NF_DROP - 1; 14791c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt else { 148030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell errno = EINVAL; 14811c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt return 0; 1482aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1483aae69bed019826ddec93f761514652a93d871e49Harald Welte (*handle)->counter_map[entry2index(*handle, e)] 148430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell = ((struct counter_map){ COUNTER_MAP_NOMAP, 0 }); 1485aae69bed019826ddec93f761514652a93d871e49Harald Welte set_changed(*handle); 1486aae69bed019826ddec93f761514652a93d871e49Harald Welte 148730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell CHECK(*handle); 1488aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 148930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 14901c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt 1491aae69bed019826ddec93f761514652a93d871e49Harald Welte/* Without this, on gcc 2.7.2.3, we get: 1492aae69bed019826ddec93f761514652a93d871e49Harald Welte libiptc.c: In function `iptc_commit': 1493aae69bed019826ddec93f761514652a93d871e49Harald Welte libiptc.c:833: fixed or forbidden register was spilled. 149430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell This may be due to a compiler bug or to impossible asm 149530fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell statements or clauses. 149630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell*/ 149779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic void 14981c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardtsubtract_counters(struct ipt_counters *answer, 149930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell const struct ipt_counters *a, 1500aae69bed019826ddec93f761514652a93d871e49Harald Welte const struct ipt_counters *b) 1501aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1502aae69bed019826ddec93f761514652a93d871e49Harald Welte answer->pcnt = a->pcnt - b->pcnt; 1503aae69bed019826ddec93f761514652a93d871e49Harald Welte answer->bcnt = a->bcnt - b->bcnt; 150430fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell} 1505aae69bed019826ddec93f761514652a93d871e49Harald Welte 1506aae69bed019826ddec93f761514652a93d871e49Harald Welteint 15071c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardtiptc_commit(iptc_handle_t *handle) 150830fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell{ 150930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* Replace, then map back the counters. */ 151030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell struct ipt_replace *repl; 1511e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct ipt_counters_info *newcounters; 1512e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher unsigned int i; 151330fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell size_t counterlen 1514aae69bed019826ddec93f761514652a93d871e49Harald Welte = sizeof(struct ipt_counters_info) 1515aae69bed019826ddec93f761514652a93d871e49Harald Welte + sizeof(struct ipt_counters) * (*handle)->new_number; 151630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell 1517aae69bed019826ddec93f761514652a93d871e49Harald Welte CHECK(*handle); 1518aae69bed019826ddec93f761514652a93d871e49Harald Welte#if 0 1519aae69bed019826ddec93f761514652a93d871e49Harald Welte dump_entries(*handle); 15201c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt#endif 1521aae69bed019826ddec93f761514652a93d871e49Harald Welte 152230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell /* Don't commit if nothing changed. */ 1523aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!(*handle)->changed) 1524e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher goto finished; 1525e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 152630fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell repl = malloc(sizeof(*repl) + (*handle)->entries.size); 152779dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell if (!repl) { 15281c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt errno = ENOMEM; 152930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell return 0; 1530aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1531aae69bed019826ddec93f761514652a93d871e49Harald Welte 1532664c0a30b7963040da2e7a7e86dc56a0f1a829b5Derrik Pates /* These are the old counters we will get from kernel */ 15331c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt repl->counters = malloc(sizeof(struct ipt_counters) 1534aae69bed019826ddec93f761514652a93d871e49Harald Welte * (*handle)->info.num_entries); 15351c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt if (!repl->counters) { 1536aae69bed019826ddec93f761514652a93d871e49Harald Welte free(repl); 153730fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell errno = ENOMEM; 1538aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1539aae69bed019826ddec93f761514652a93d871e49Harald Welte } 15401c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt 1541aae69bed019826ddec93f761514652a93d871e49Harald Welte /* These are the counters we're going to put back, later. */ 154230fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell newcounters = malloc(counterlen); 1543aae69bed019826ddec93f761514652a93d871e49Harald Welte if (!newcounters) { 1544aae69bed019826ddec93f761514652a93d871e49Harald Welte free(repl->counters); 1545aae69bed019826ddec93f761514652a93d871e49Harald Welte free(repl); 15461c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt errno = ENOMEM; 1547aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 15481c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt } 15491c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt 1550aae69bed019826ddec93f761514652a93d871e49Harald Welte strcpy(repl->name, (*handle)->info.name); 1551aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->num_entries = (*handle)->new_number; 1552aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->size = (*handle)->entries.size; 1553aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(repl->hook_entry, (*handle)->info.hook_entry, 15541c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt sizeof(repl->hook_entry)); 1555aae69bed019826ddec93f761514652a93d871e49Harald Welte memcpy(repl->underflow, (*handle)->info.underflow, 1556aae69bed019826ddec93f761514652a93d871e49Harald Welte sizeof(repl->underflow)); 1557aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->num_counters = (*handle)->info.num_entries; 1558aae69bed019826ddec93f761514652a93d871e49Harald Welte repl->valid_hooks = (*handle)->info.valid_hooks; 155930fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell memcpy(repl->entries, (*handle)->entries.entries, 156030fd6e5d45e6013f4df10a226787c7a9f49369c1Rusty Russell (*handle)->entries.size); 1561e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 156233690a1aec0b6309ff90066ca56285b6e43013f2Jan Engelhardt if (setsockopt(sockfd, IPPROTO_IP, IPT_SO_SET_REPLACE, repl, 15631c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt sizeof(*repl) + (*handle)->entries.size) < 0) { 1564e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher free(repl->counters); 1565aae69bed019826ddec93f761514652a93d871e49Harald Welte free(repl); 1566aae69bed019826ddec93f761514652a93d871e49Harald Welte free(newcounters); 15671c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt return 0; 1568aae69bed019826ddec93f761514652a93d871e49Harald Welte } 15691c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt 1570aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Put counters back. */ 1571e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher strcpy(newcounters->name, (*handle)->info.name); 1572e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newcounters->num_counters = (*handle)->new_number; 1573e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher for (i = 0; i < (*handle)->new_number; i++) { 1574aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int mappos = (*handle)->counter_map[i].mappos; 1575aae69bed019826ddec93f761514652a93d871e49Harald Welte switch ((*handle)->counter_map[i].maptype) { 1576e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher case COUNTER_MAP_NOMAP: 1577e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher newcounters->counters[i] 157833690a1aec0b6309ff90066ca56285b6e43013f2Jan Engelhardt = ((struct ipt_counters){ 0, 0 }); 15791c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt break; 1580e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1581aae69bed019826ddec93f761514652a93d871e49Harald Welte case COUNTER_MAP_NORMAL_MAP: 1582aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Original read: X. 1583aae69bed019826ddec93f761514652a93d871e49Harald Welte * Atomic read on replacement: X + Y. 1584aae69bed019826ddec93f761514652a93d871e49Harald Welte * Currently in kernel: Z. 1585e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * Want in kernel: X + Y + Z. 15861c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt * => Add in X + Y 1587aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in replacement read. 15881c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt */ 1589aae69bed019826ddec93f761514652a93d871e49Harald Welte newcounters->counters[i] = repl->counters[mappos]; 1590e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher break; 1591e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1592e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher case COUNTER_MAP_ZEROED: 1593e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Original read: X. 1594aae69bed019826ddec93f761514652a93d871e49Harald Welte * Atomic read on replacement: X + Y. 1595aae69bed019826ddec93f761514652a93d871e49Harald Welte * Currently in kernel: Z. 1596aae69bed019826ddec93f761514652a93d871e49Harald Welte * Want in kernel: Y + Z. 1597aae69bed019826ddec93f761514652a93d871e49Harald Welte * => Add in Y. 1598e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher * => Add in (replacement read - original read). 1599e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher */ 1600aae69bed019826ddec93f761514652a93d871e49Harald Welte subtract_counters(&newcounters->counters[i], 160133690a1aec0b6309ff90066ca56285b6e43013f2Jan Engelhardt &repl->counters[mappos], 1602e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher &index2entry(*handle, i)->counters); 1603aae69bed019826ddec93f761514652a93d871e49Harald Welte break; 1604aae69bed019826ddec93f761514652a93d871e49Harald Welte } 160579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell } 1606aae69bed019826ddec93f761514652a93d871e49Harald Welte 1607aae69bed019826ddec93f761514652a93d871e49Harald Welte if (setsockopt(sockfd, IPPROTO_IP, IPT_SO_SET_ADD_COUNTERS, 160879dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell newcounters, counterlen) < 0) { 1609aae69bed019826ddec93f761514652a93d871e49Harald Welte free(repl->counters); 1610aae69bed019826ddec93f761514652a93d871e49Harald Welte free(repl); 1611aae69bed019826ddec93f761514652a93d871e49Harald Welte free(newcounters); 1612aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1613aae69bed019826ddec93f761514652a93d871e49Harald Welte } 1614aae69bed019826ddec93f761514652a93d871e49Harald Welte 1615aae69bed019826ddec93f761514652a93d871e49Harald Welte free(repl->counters); 1616aae69bed019826ddec93f761514652a93d871e49Harald Welte free(repl); 1617aae69bed019826ddec93f761514652a93d871e49Harald Welte free(newcounters); 1618aae69bed019826ddec93f761514652a93d871e49Harald Welte 1619aae69bed019826ddec93f761514652a93d871e49Harald Welte finished: 1620aae69bed019826ddec93f761514652a93d871e49Harald Welte free(*handle); 1621e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher *handle = NULL; 1622aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1623aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1624e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1625e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Get raw socket. */ 1626aae69bed019826ddec93f761514652a93d871e49Harald Welteint 1627aae69bed019826ddec93f761514652a93d871e49Harald Welteiptc_get_raw_socket() 16281c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt{ 1629e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher return sockfd; 1630aae69bed019826ddec93f761514652a93d871e49Harald Welte} 1631e45c71321e77735a1d66b180f8a29bea33aeb1b0Rusty Russell 1632e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher/* Translates errno numbers into more human-readable form than strerror. */ 1633aae69bed019826ddec93f761514652a93d871e49Harald Welteconst char * 16340113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welteiptc_strerror(int err) 1635aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 1636aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int i; 1637aae69bed019826ddec93f761514652a93d871e49Harald Welte struct table_struct { 1638aae69bed019826ddec93f761514652a93d871e49Harald Welte void *fn; 1639aae69bed019826ddec93f761514652a93d871e49Harald Welte int err; 1640aae69bed019826ddec93f761514652a93d871e49Harald Welte const char *message; 1641aae69bed019826ddec93f761514652a93d871e49Harald Welte } table [] = 1642aae69bed019826ddec93f761514652a93d871e49Harald Welte { { NULL, 0, "Incompatible with this kernel" }, 1643aae69bed019826ddec93f761514652a93d871e49Harald Welte { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" }, 1644aae69bed019826ddec93f761514652a93d871e49Harald Welte { NULL, ENOSYS, "Will be implemented real soon. I promise." }, 1645aae69bed019826ddec93f761514652a93d871e49Harald Welte { NULL, ENOMEM, "Memory allocation problem" }, 1646aae69bed019826ddec93f761514652a93d871e49Harald Welte { iptc_init, EPERM, "Permission denied (you must be root)" }, 1647aae69bed019826ddec93f761514652a93d871e49Harald Welte { iptc_init, EINVAL, "Module is wrong version" }, 1648aae69bed019826ddec93f761514652a93d871e49Harald Welte { iptc_delete_chain, ENOTEMPTY, "Chain is not empty" }, 1649aae69bed019826ddec93f761514652a93d871e49Harald Welte { iptc_delete_chain, EINVAL, "Can't delete built-in chain" }, 1650aae69bed019826ddec93f761514652a93d871e49Harald Welte { iptc_delete_chain, EMLINK, 1651aae69bed019826ddec93f761514652a93d871e49Harald Welte "Can't delete chain with references left" }, 16520113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte { iptc_create_chain, EEXIST, "Chain already exists" }, 1653aae69bed019826ddec93f761514652a93d871e49Harald Welte { iptc_insert_entry, E2BIG, "Index of insertion too big" }, 1654aae69bed019826ddec93f761514652a93d871e49Harald Welte { iptc_replace_entry, E2BIG, "Index of replacement too big" }, 1655aae69bed019826ddec93f761514652a93d871e49Harald Welte { iptc_delete_num_entry, E2BIG, "Index of deletion too big" }, 1656aae69bed019826ddec93f761514652a93d871e49Harald Welte { iptc_insert_entry, ELOOP, "Loop found in table" }, 1657fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt { iptc_insert_entry, EINVAL, "Target problem" }, 1658aae69bed019826ddec93f761514652a93d871e49Harald Welte /* EINVAL for CHECK probably means bad interface. */ 1659aae69bed019826ddec93f761514652a93d871e49Harald Welte { iptc_check_packet, EINVAL, 1660aae69bed019826ddec93f761514652a93d871e49Harald Welte "Bad arguments (does that interface exist?)" }, 1661aae69bed019826ddec93f761514652a93d871e49Harald Welte /* ENOENT for DELETE probably means no matching rule */ 16620113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte { iptc_delete_entry, ENOENT, 1663aae69bed019826ddec93f761514652a93d871e49Harald Welte "Bad rule (does a matching rule exist in that chain?)" }, 1664aae69bed019826ddec93f761514652a93d871e49Harald Welte { iptc_set_policy, ENOENT, 1665aae69bed019826ddec93f761514652a93d871e49Harald Welte "Bad built-in chain name" }, 1666b0f3d2d7261be3fe256a66abcc237241fea43a02Martin Josefsson { iptc_set_policy, EINVAL, 16670113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte "Bad policy name" }, 16680113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte { NULL, ENOENT, "No extended target/match by that name" } 1669aae69bed019826ddec93f761514652a93d871e49Harald Welte }; 16700113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 16710113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) { 1672aae69bed019826ddec93f761514652a93d871e49Harald Welte if ((!table[i].fn || table[i].fn == iptc_fn) 1673aae69bed019826ddec93f761514652a93d871e49Harald Welte && table[i].err == err) 1674aae69bed019826ddec93f761514652a93d871e49Harald Welte return table[i].message; 1675aae69bed019826ddec93f761514652a93d871e49Harald Welte } 16761c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt 16770113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return strerror(err); 1678aae69bed019826ddec93f761514652a93d871e49Harald Welte} 16790113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1680aae69bed019826ddec93f761514652a93d871e49Harald Welte/***************************** DEBUGGING ********************************/ 1681fbc85236a6140918ab1d0fb0e07e2d72da46ce45Harald Weltestatic inline int 1682aae69bed019826ddec93f761514652a93d871e49Harald Welteunconditional(const struct ipt_ip *ip) 16830113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte{ 16841c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt unsigned int i; 1685aae69bed019826ddec93f761514652a93d871e49Harald Welte 1686aae69bed019826ddec93f761514652a93d871e49Harald Welte for (i = 0; i < sizeof(*ip)/sizeof(u_int32_t); i++) 1687aae69bed019826ddec93f761514652a93d871e49Harald Welte if (((u_int32_t *)ip)[i]) 16880113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 16890113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1690aae69bed019826ddec93f761514652a93d871e49Harald Welte return 1; 1691aae69bed019826ddec93f761514652a93d871e49Harald Welte} 16920113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1693aae69bed019826ddec93f761514652a93d871e49Harald Weltestatic inline int 16940113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Weltecheck_match(const struct ipt_entry_match *m, unsigned int *off) 1695aae69bed019826ddec93f761514652a93d871e49Harald Welte{ 16960113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte assert(m->match_size >= sizeof(struct ipt_entry_match)); 1697e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1698e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher (*off) += m->match_size; 1699aae69bed019826ddec93f761514652a93d871e49Harald Welte return 0; 1700e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 1701aae69bed019826ddec93f761514652a93d871e49Harald Welte 170279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic inline int 1703e6869a8f59d779ff4d5a0984c86d80db7078496Marc Bouchercheck_entry(const struct ipt_entry *e, unsigned int *i, unsigned int *off, 170479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell unsigned int user_offset, int *was_return, 1705e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher iptc_handle_t h) 170667088e73ce7707229c56987868f112051defca5aRusty Russell{ 17078c700900e2a0cf87d7917cb62578583a60ad1210Philip Blundell unsigned int toff; 1708e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct ipt_standard_target *t; 1709e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1710e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher assert(e->target_offset >= sizeof(struct ipt_entry)); 1711e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher assert(e->next_offset >= e->target_offset 171279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell + sizeof(struct ipt_entry_target)); 171379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell toff = sizeof(struct ipt_entry); 1714e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher IPT_MATCH_ITERATE(e, check_match, &toff); 1715e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1716aae69bed019826ddec93f761514652a93d871e49Harald Welte assert(toff == e->target_offset); 1717aae69bed019826ddec93f761514652a93d871e49Harald Welte 1718e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher t = (struct ipt_standard_target *) 1719e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher ipt_get_target((struct ipt_entry *)e); 17207e53bf9c2a697abdb6f1385557338423a86612a3Rusty Russell assert(t->target.target_size == e->next_offset - e->target_offset); 1721e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher assert(!iptc_is_chain(t->target.u.name, h)); 1722fd1873110f8e57be578df17fc9d03536b10f4f73Jan Engelhardt 1723aae69bed019826ddec93f761514652a93d871e49Harald Welte if (strcmp(t->target.u.name, IPT_STANDARD_TARGET) == 0) { 1724e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher assert(t->target.target_size 1725aae69bed019826ddec93f761514652a93d871e49Harald Welte == IPT_ALIGN(sizeof(struct ipt_standard_target))); 17260113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte 1727e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher assert(t->verdict == -NF_DROP-1 1728e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher || t->verdict == -NF_ACCEPT-1 1729aae69bed019826ddec93f761514652a93d871e49Harald Welte || t->verdict == IPT_RETURN 1730aae69bed019826ddec93f761514652a93d871e49Harald Welte || t->verdict < (int)h->entries.size); 1731aae69bed019826ddec93f761514652a93d871e49Harald Welte 1732aae69bed019826ddec93f761514652a93d871e49Harald Welte if (t->verdict >= 0) { 1733e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct ipt_entry *te = get_entry(h, t->verdict); 173479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell int idx; 1735aae69bed019826ddec93f761514652a93d871e49Harald Welte 173679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell idx = entry2index(h, te); 1737aae69bed019826ddec93f761514652a93d871e49Harald Welte assert(strcmp(ipt_get_target(te)->u.name, 173867088e73ce7707229c56987868f112051defca5aRusty Russell IPT_ERROR_TARGET) 1739aae69bed019826ddec93f761514652a93d871e49Harald Welte != 0); 174079dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell assert(te != e); 1741aae69bed019826ddec93f761514652a93d871e49Harald Welte 174279dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell /* Prior node must be error node, or this node. */ 1743e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher assert(t->verdict == entry2offset(h, e)+e->next_offset 1744e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher || strcmp(ipt_get_target(index2entry(h, idx-1)) 1745e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher ->u.name, IPT_ERROR_TARGET) 1746e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher == 0); 1747e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1748aae69bed019826ddec93f761514652a93d871e49Harald Welte 1749aae69bed019826ddec93f761514652a93d871e49Harald Welte if (t->verdict == IPT_RETURN 1750aae69bed019826ddec93f761514652a93d871e49Harald Welte && unconditional(&e->ip) 1751aae69bed019826ddec93f761514652a93d871e49Harald Welte && e->target_offset == sizeof(*e)) 1752aae69bed019826ddec93f761514652a93d871e49Harald Welte *was_return = 1; 1753aae69bed019826ddec93f761514652a93d871e49Harald Welte else 1754aae69bed019826ddec93f761514652a93d871e49Harald Welte *was_return = 0; 1755aae69bed019826ddec93f761514652a93d871e49Harald Welte } else if (strcmp(t->target.u.name, IPT_ERROR_TARGET) == 0) { 1756aae69bed019826ddec93f761514652a93d871e49Harald Welte assert(t->target.target_size 1757aae69bed019826ddec93f761514652a93d871e49Harald Welte == IPT_ALIGN(sizeof(struct ipt_error_target))); 1758aae69bed019826ddec93f761514652a93d871e49Harald Welte 1759aae69bed019826ddec93f761514652a93d871e49Harald Welte /* If this is in user area, previous must have been return */ 1760e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (*off > user_offset) 1761e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher assert(*was_return); 1762e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 17633aef54dce4f9bbe0b466478fd33a1d3131efbbb8Rusty Russell *was_return = 0; 1764228e98dd6303af11925235af4cf3c3ec450f3f41Rusty Russell } 1765e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher else *was_return = 0; 17663aef54dce4f9bbe0b466478fd33a1d3131efbbb8Rusty Russell 1767733e54b8250576d6a1e0ab5621ef5b144abdf018Rusty Russell if (*off == user_offset) 1768aae69bed019826ddec93f761514652a93d871e49Harald Welte assert(strcmp(t->target.u.name, IPT_ERROR_TARGET) == 0); 1769aae69bed019826ddec93f761514652a93d871e49Harald Welte 1770e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher (*off) += e->next_offset; 1771e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher (*i)++; 17720113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte return 0; 1773e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher} 177479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell 177579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell/* Do every conceivable sanity check on the handle */ 177679dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russellstatic void 17771c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardtdo_check(iptc_handle_t h, unsigned int line) 1778e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher{ 1779aae69bed019826ddec93f761514652a93d871e49Harald Welte unsigned int i, n; 1780eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson unsigned int user_offset; /* Offset of first user chain */ 1781eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson int was_return; 1782e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 178379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell assert(h->changed == 0 || h->changed == 1); 1784aae69bed019826ddec93f761514652a93d871e49Harald Welte if (strcmp(h->info.name, "filter") == 0) { 17851c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt assert(h->info.valid_hooks 1786e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher == (1 << NF_IP_LOCAL_IN 1787e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher | 1 << NF_IP_FORWARD 1788e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher | 1 << NF_IP_LOCAL_OUT)); 1789e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1790eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson /* Hooks should be first three */ 1791eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson assert(h->info.hook_entry[NF_IP_LOCAL_IN] == 0); 1792eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson 1793e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher n = get_chain_end(h, 0); 1794e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher n += get_entry(h, n)->next_offset; 1795e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher assert(h->info.hook_entry[NF_IP_FORWARD] == n); 1796e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1797631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson n = get_chain_end(h, n); 1798631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson n += get_entry(h, n)->next_offset; 1799631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson assert(h->info.hook_entry[NF_IP_LOCAL_OUT] == n); 1800631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson 1801eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson user_offset = h->info.hook_entry[NF_IP_LOCAL_OUT]; 1802a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson } else if (strcmp(h->info.name, "nat") == 0) { 1803631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson assert(h->info.valid_hooks 1804a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson == (1 << NF_IP_PRE_ROUTING 1805a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson | 1 << NF_IP_POST_ROUTING 1806a5616dcfafd33fa46a03a8c270e5e09b2fba7cb1Martin Josefsson | 1 << NF_IP_LOCAL_OUT)); 1807631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson 1808631f3619b7fb597f5e1c8f61c7178d64be7c144fMartin Josefsson assert(h->info.hook_entry[NF_IP_PRE_ROUTING] == 0); 1809eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson 1810aae69bed019826ddec93f761514652a93d871e49Harald Welte n = get_chain_end(h, 0); 1811aae69bed019826ddec93f761514652a93d871e49Harald Welte n += get_entry(h, n)->next_offset; 1812aae69bed019826ddec93f761514652a93d871e49Harald Welte assert(h->info.hook_entry[NF_IP_POST_ROUTING] == n); 1813aae69bed019826ddec93f761514652a93d871e49Harald Welte 1814aae69bed019826ddec93f761514652a93d871e49Harald Welte n = get_chain_end(h, n); 1815aae69bed019826ddec93f761514652a93d871e49Harald Welte n += get_entry(h, n)->next_offset; 1816aae69bed019826ddec93f761514652a93d871e49Harald Welte assert(h->info.hook_entry[NF_IP_LOCAL_OUT] == n); 1817aae69bed019826ddec93f761514652a93d871e49Harald Welte 18181c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt user_offset = h->info.hook_entry[NF_IP_LOCAL_OUT]; 1819aae69bed019826ddec93f761514652a93d871e49Harald Welte } else if (strcmp(h->info.name, "mangle") == 0) { 18200113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte assert(h->info.valid_hooks 1821aae69bed019826ddec93f761514652a93d871e49Harald Welte == (1 << NF_IP_PRE_ROUTING 1822aae69bed019826ddec93f761514652a93d871e49Harald Welte | 1 << NF_IP_LOCAL_OUT)); 1823eb066cc4fb75a616400eaf38dfa31c052c76cf5cMartin Josefsson 1824aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Hooks should be first three */ 1825aae69bed019826ddec93f761514652a93d871e49Harald Welte assert(h->info.hook_entry[NF_IP_PRE_ROUTING] == 0); 18261c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt 1827e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher n = get_chain_end(h, 0); 1828aae69bed019826ddec93f761514652a93d871e49Harald Welte n += get_entry(h, n)->next_offset; 1829e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher assert(h->info.hook_entry[NF_IP_LOCAL_OUT] == n); 1830e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1831e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher user_offset = h->info.hook_entry[NF_IP_LOCAL_OUT]; 1832e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } else 183379dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell abort(); 183479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell 183579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell /* User chain == end of last builtin + policy entry */ 18361c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt user_offset = get_chain_end(h, user_offset); 1837e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher user_offset += get_entry(h, user_offset)->next_offset; 1838aae69bed019826ddec93f761514652a93d871e49Harald Welte 1839aae69bed019826ddec93f761514652a93d871e49Harald Welte /* Overflows should be end of entry chains, and unconditional 1840e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher policy nodes. */ 184179dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell for (i = 0; i < NF_IP_NUMHOOKS; i++) { 1842e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher struct ipt_entry *e; 18431c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt struct ipt_standard_target *t; 1844e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1845e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher if (!(h->info.valid_hooks & (1 << i))) 1846e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher continue; 1847e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher assert(h->info.underflow[i] 18480f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson == get_chain_end(h, h->info.hook_entry[i])); 1849e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1850e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher e = get_entry(h, get_chain_end(h, h->info.hook_entry[i])); 1851e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher assert(unconditional(&e->ip)); 1852e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher assert(e->target_offset == sizeof(*e)); 18530f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson assert(e->next_offset == sizeof(*e) + sizeof(*t)); 18540f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson t = (struct ipt_standard_target *)ipt_get_target(e); 18550f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson 18560f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson assert(strcmp(t->target.u.name, IPT_STANDARD_TARGET) == 0); 18570f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson assert(t->verdict == -NF_DROP-1 || t->verdict == -NF_ACCEPT-1); 18580f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson 18590f9b8b158bb71b96c6b2908f5bf7bb9670ff4eb0Martin Josefsson /* Hooks and underflows must be valid entries */ 1860aae69bed019826ddec93f761514652a93d871e49Harald Welte entry2index(h, get_entry(h, h->info.hook_entry[i])); 1861aae69bed019826ddec93f761514652a93d871e49Harald Welte entry2index(h, get_entry(h, h->info.underflow[i])); 1862e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher } 1863aae69bed019826ddec93f761514652a93d871e49Harald Welte 1864aae69bed019826ddec93f761514652a93d871e49Harald Welte assert(h->info.size 1865aae69bed019826ddec93f761514652a93d871e49Harald Welte >= h->info.num_entries * (sizeof(struct ipt_entry) 1866aae69bed019826ddec93f761514652a93d871e49Harald Welte +sizeof(struct ipt_standard_target))); 1867e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 18681c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt assert(h->entries.size 1869aae69bed019826ddec93f761514652a93d871e49Harald Welte >= (h->new_number 18700113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte * (sizeof(struct ipt_entry) 1871aae69bed019826ddec93f761514652a93d871e49Harald Welte + sizeof(struct ipt_standard_target)))); 1872aae69bed019826ddec93f761514652a93d871e49Harald Welte assert(strcmp(h->info.name, h->entries.name) == 0); 1873aae69bed019826ddec93f761514652a93d871e49Harald Welte 1874aae69bed019826ddec93f761514652a93d871e49Harald Welte i = 0; n = 0; 18750113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte was_return = 0; 18761c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt /* Check all the entries. */ 1877aae69bed019826ddec93f761514652a93d871e49Harald Welte IPT_ENTRY_ITERATE(h->entries.entries, h->entries.size, 1878aae69bed019826ddec93f761514652a93d871e49Harald Welte check_entry, &i, &n, user_offset, &was_return, h); 1879e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1880e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher assert(i == h->new_number); 18810113fe75ff05e09e6f3d251534d9ae32e9aa717cHarald Welte assert(n == h->entries.size); 1882e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher 1883e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher /* Final entry must be error node */ 188479dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell assert(strcmp(ipt_get_target(index2entry(h, h->new_number-1))->u.name, 188579dee0702b18c8ea1d1f7a2b1f6b29349466986bRusty Russell IPT_ERROR_TARGET) == 0); 18861c9015b2cb483678f153121255e10ec0bbfde3e6Jan Engelhardt} 1887e6869a8f59d779ff4d5a0984c86d80db7078496Marc Boucher