nft.c revision 9e62dc8637f210cdeaed784396fecab9b6e5f043
1384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso/* 2384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org> 3384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso * 4384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso * This program is free software; you can redistribute it and/or modify 5384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso * it under the terms of the GNU General Public License as published 6384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso * by the Free Software Foundation; either version 2 of the License, or 7384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso * (at your option) any later version. 8384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso * 9384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso * This code has been sponsored by Sophos Astaro <http://www.sophos.com> 10384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso */ 11384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 12384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#if 0 13384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define DEBUGP(x, args...) fprintf(stdout, x, ## args) 14384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define NLDEBUG 15384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define DEBUG_DEL 16384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#else 17384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define DEBUGP(x, args...) 18384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif 19384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 20384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <unistd.h> 21384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <fcntl.h> 22384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <sys/types.h> 23384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <sys/socket.h> 24384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <stdbool.h> 25384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <errno.h> 26384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <netdb.h> /* getprotobynumber */ 27384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <time.h> 28384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 29384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <xtables.h> 30384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libiptc/libxtc.h> 31384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libiptc/xtcshared.h> 32384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 33384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <stdlib.h> 34384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <string.h> 35384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 36384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <linux/netfilter/x_tables.h> 370391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka#include <linux/netfilter_ipv4/ip_tables.h> 380391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka#include <linux/netfilter_ipv6/ip6_tables.h> 390391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka#include <netinet/ip6.h> 40384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 41384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <linux/netlink.h> 42384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <linux/netfilter/nfnetlink.h> 43384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <linux/netfilter/nf_tables.h> 44384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <linux/netfilter/nf_tables_compat.h> 45384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 46384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libmnl/libmnl.h> 47384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libnftables/table.h> 48384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libnftables/chain.h> 49384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libnftables/rule.h> 50384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <libnftables/expr.h> 51384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 52384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <netinet/in.h> /* inet_ntoa */ 53384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include <arpa/inet.h> 54384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 55384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include "nft.h" 56384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#include "xshared.h" /* proto_to_name */ 57384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 58384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void *nft_fn; 59384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 60384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh, 61384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int (*cb)(const struct nlmsghdr *nlh, void *data), 62384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso void *data) 63384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 64384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int ret; 65384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso char buf[MNL_SOCKET_BUFFER_SIZE]; 66384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 67384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (mnl_socket_sendto(h->nl, nlh, nlh->nlmsg_len) < 0) { 68384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso perror("mnl_socket_send"); 69384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return -1; 70384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 71384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 72384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ret = mnl_socket_recvfrom(h->nl, buf, sizeof(buf)); 73384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso while (ret > 0) { 74384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ret = mnl_cb_run(buf, ret, h->seq, h->portid, cb, data); 75384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (ret <= 0) 76384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 77384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 78384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ret = mnl_socket_recvfrom(h->nl, buf, sizeof(buf)); 79384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 80384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (ret == -1) { 81384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return -1; 82384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 83384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 84384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 0; 85384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 86384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 87384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FILTER 0 88384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define MANGLE 1 89384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define RAW 2 90384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define SECURITY 3 91890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso#define NAT 4 92890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso#define TABLES_MAX 5 93384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 94e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayusostruct builtin_chain { 95e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso const char *name; 96890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso const char *type; 975b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso uint32_t prio; 98e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso uint32_t hook; 99e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso}; 100e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso 101c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusostatic struct builtin_table { 102384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *name; 103e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso struct builtin_chain chains[NF_INET_NUMHOOKS]; 104384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} tables[TABLES_MAX] = { 105384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso [RAW] = { 106384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso .name = "raw", 107e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .chains = { 108e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso { 109e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .name = "PREROUTING", 110890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .type = "filter", 1115b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso .prio = -300, /* NF_IP_PRI_RAW */ 112e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .hook = NF_INET_PRE_ROUTING, 113e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso }, 114e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso { 115e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .name = "OUTPUT", 116890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .type = "filter", 1175b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso .prio = -300, /* NF_IP_PRI_RAW */ 118e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .hook = NF_INET_LOCAL_OUT, 119e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso }, 120e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso }, 121384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso }, 122384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso [MANGLE] = { 123384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso .name = "mangle", 124e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .chains = { 125e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso { 126e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .name = "PREROUTING", 127890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .type = "filter", 1285b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso .prio = -150, /* NF_IP_PRI_MANGLE */ 129e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .hook = NF_INET_PRE_ROUTING, 130e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso }, 131e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso { 132e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .name = "INPUT", 133890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .type = "filter", 1345b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso .prio = -150, /* NF_IP_PRI_MANGLE */ 135e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .hook = NF_INET_LOCAL_IN, 136e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso }, 137e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso { 138e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .name = "FORWARD", 139890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .type = "filter", 1405b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso .prio = -150, /* NF_IP_PRI_MANGLE */ 141e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .hook = NF_INET_FORWARD, 142e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso }, 143e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso { 144e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .name = "OUTPUT", 145890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .type = "route", 1465b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso .prio = -150, /* NF_IP_PRI_MANGLE */ 147e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .hook = NF_INET_LOCAL_OUT, 148e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso }, 149e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso { 150e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .name = "POSTROUTING", 151890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .type = "filter", 1525b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso .prio = -150, /* NF_IP_PRI_MANGLE */ 153e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .hook = NF_INET_POST_ROUTING, 154e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso }, 155e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso }, 156384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso }, 157384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso [FILTER] = { 158384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso .name = "filter", 159e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .chains = { 160e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso { 161e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .name = "INPUT", 162890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .type = "filter", 1635b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso .prio = 0, /* NF_IP_PRI_FILTER */ 164e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .hook = NF_INET_LOCAL_IN, 165e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso }, 166e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso { 167e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .name = "FORWARD", 168890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .type = "filter", 1695b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso .prio = 0, /* NF_IP_PRI_FILTER */ 170e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .hook = NF_INET_FORWARD, 171e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso }, 172e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso { 173e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .name = "OUTPUT", 174890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .type = "filter", 1755b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso .prio = 0, /* NF_IP_PRI_FILTER */ 176e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .hook = NF_INET_LOCAL_OUT, 177e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso }, 178e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso }, 179384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso }, 180384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso [SECURITY] = { 181384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso .name = "security", 182e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .chains = { 183e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso { 184e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .name = "INPUT", 185890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .type = "filter", 1865b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso .prio = 150, /* NF_IP_PRI_SECURITY */ 187e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .hook = NF_INET_LOCAL_IN, 188e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso }, 189e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso { 190e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .name = "FORWARD", 191890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .type = "filter", 1925b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso .prio = 150, /* NF_IP_PRI_SECURITY */ 193e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .hook = NF_INET_FORWARD, 194e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso }, 195e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso { 196e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .name = "OUTPUT", 197890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .type = "filter", 1985b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso .prio = 150, /* NF_IP_PRI_SECURITY */ 199e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso .hook = NF_INET_LOCAL_OUT, 200e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso }, 201384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso }, 202384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso }, 203890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso [NAT] = { 204890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .name = "nat", 205890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .chains = { 206890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso { 207890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .name = "OUTPUT", 208890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .type = "nat", 209890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .prio = -100, /* NF_IP_PRI_NAT_DST */ 210890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .hook = NF_INET_LOCAL_OUT, 211890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso }, 212890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso { 213890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .name = "INPUT", 214890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .type = "nat", 215890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .prio = 100, /* NF_IP_PRI_NAT_SRC */ 216890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .hook = NF_INET_LOCAL_IN, 217890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso }, 218890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso { 219890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .name = "PREROUTING", 220890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .type = "nat", 221890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .prio = -100, /* NF_IP_PRI_NAT_DST */ 222890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .hook = NF_INET_PRE_ROUTING, 223890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso }, 224890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso { 225890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .name = "POSTROUTING", 226890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .type = "nat", 227890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .prio = 100, /* NF_IP_PRI_NAT_SRC */ 228890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso .hook = NF_INET_POST_ROUTING, 229890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso }, 230890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso }, 231890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso }, 232384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}; 233384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2345705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayusostatic int 2355705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayusonft_table_builtin_add(struct nft_handle *h, struct builtin_table *_t, 2365705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso bool dormant) 2375b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso{ 2385b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso char buf[MNL_SOCKET_BUFFER_SIZE]; 2395b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso struct nlmsghdr *nlh; 2405b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso struct nft_table *t; 2415b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso int ret; 2425b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso 2435b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso t = nft_table_alloc(); 2445b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso if (t == NULL) 2455b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso return -1; 2465b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso 2475b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso nft_table_attr_set(t, NFT_TABLE_ATTR_NAME, (char *)_t->name); 2485705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso if (dormant) { 2495705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso nft_table_attr_set_u32(t, NFT_TABLE_ATTR_FLAGS, 2505705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso NFT_TABLE_F_DORMANT); 2515705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso } 2525b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso 2530391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, h->family, 2545b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso NLM_F_ACK|NLM_F_EXCL, h->seq); 2555b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso nft_table_nlmsg_build_payload(nlh, t); 2565b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso nft_table_free(t); 2575b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso 2585b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso ret = mnl_talk(h, nlh, NULL, NULL); 2595b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso if (ret < 0) { 2605b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso if (errno != EEXIST) 2615b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso perror("mnl-talk:nft_table_init_one"); 2625b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso } 2635b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso return ret; 2645b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso} 2655b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso 266c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusostatic struct nft_chain * 267c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusonft_chain_builtin_alloc(struct builtin_table *table, 268c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso struct builtin_chain *chain, int policy) 269384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 270384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_chain *c; 271384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 272384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso c = nft_chain_alloc(); 273384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (c == NULL) 274c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso return NULL; 275384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 276384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table->name); 277384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)chain->name); 278384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_HOOKNUM, chain->hook); 2795b414b85c33912aec912d260502c8b0c0df794a1Pablo Neira Ayuso nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_PRIO, chain->prio); 280384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_POLICY, policy); 281890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso nft_chain_attr_set(c, NFT_CHAIN_ATTR_TYPE, (char *)chain->type); 282384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 283c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso return c; 284c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso} 285c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso 286c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusostatic void 287c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusonft_chain_builtin_add(struct nft_handle *h, struct builtin_table *table, 288c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso struct builtin_chain *chain, int policy) 289c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso{ 290c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso char buf[MNL_SOCKET_BUFFER_SIZE]; 291c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso struct nlmsghdr *nlh; 292c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso struct nft_chain *c; 293c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso 294c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso c = nft_chain_builtin_alloc(table, chain, policy); 295c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso if (c == NULL) 296c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso return; 297c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso 298890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso /* NLM_F_CREATE requests module autoloading */ 2990391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family, 300890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso NLM_F_ACK|NLM_F_EXCL|NLM_F_CREATE, 301890fd9ef76ad0c11695fb0d09a88169e6e46584fPablo Neira Ayuso h->seq); 302384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_nlmsg_build_payload(nlh, c); 303384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_free(c); 304384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 305384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (mnl_talk(h, nlh, NULL, NULL) < 0) { 306384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (errno != EEXIST) 307c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso perror("mnl_talk:nft_chain_builtin_add"); 308c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso } 309c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso} 310c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso 311c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso/* find if built-in table already exists */ 312c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusostatic struct builtin_table *nft_table_builtin_find(const char *table) 313c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso{ 314c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso int i; 315c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso bool found = false; 316c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso 317c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso for (i=0; i<TABLES_MAX; i++) { 318c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso if (strcmp(tables[i].name, table) != 0) 319c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso continue; 320c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso 321c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso found = true; 322c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso break; 323384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 324c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso 325c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso return found ? &tables[i] : NULL; 326384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 327384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 328c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso/* find if built-in chain already exists */ 329c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusostatic struct builtin_chain * 330e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayusonft_chain_builtin_find(struct builtin_table *t, const char *chain) 331384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 332e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso int i; 333c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso bool found = false; 334384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 335e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso for (i=0; i<NF_IP_NUMHOOKS && t->chains[i].name != NULL; i++) { 336e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso if (strcmp(t->chains[i].name, chain) != 0) 337e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso continue; 338384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 339e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso found = true; 340e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso break; 341e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso } 342e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso return found ? &t->chains[i] : NULL; 343e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso} 344e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso 345e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayusostatic void 346e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso__nft_chain_builtin_init(struct nft_handle *h, 347e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso struct builtin_table *table, const char *chain, 348e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso int policy) 349e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso{ 350e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso int i, default_policy; 351e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso 352e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso /* Initialize all built-in chains. Exception, for e one received as 353e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso * parameter, set the default policy as requested. 354e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso */ 355e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso for (i=0; i<NF_IP_NUMHOOKS && table->chains[i].name != NULL; i++) { 356e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso if (chain && strcmp(table->chains[i].name, chain) == 0) 357e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso default_policy = policy; 358e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso else 359e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso default_policy = NF_ACCEPT; 360e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso 361e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso nft_chain_builtin_add(h, table, &table->chains[i], 362e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso default_policy); 363384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 364c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso} 365c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso 366c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusostatic int 367c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusonft_chain_builtin_init(struct nft_handle *h, const char *table, 368c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso const char *chain, int policy) 369c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso{ 370c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso int ret = 0; 371c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso struct builtin_table *t; 372c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso 373c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso t = nft_table_builtin_find(table); 374c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso if (t == NULL) { 375c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso ret = -1; 376c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso goto out; 377c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso } 3785705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso if (nft_table_builtin_add(h, t, false) < 0) { 379e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso /* Built-in table already initialized, skip. */ 380e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso if (errno == EEXIST) 381e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso goto out; 382c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso } 383e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso __nft_chain_builtin_init(h, t, chain, policy); 384c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayusoout: 385c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso return ret; 386384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 387384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 388384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_init(struct nft_handle *h) 389384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 390384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso h->nl = mnl_socket_open(NETLINK_NETFILTER); 391384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (h->nl == NULL) { 392384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso perror("mnl_socket_open"); 393384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return -1; 394384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 395384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 396384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (mnl_socket_bind(h->nl, 0, MNL_SOCKET_AUTOPID) < 0) { 397384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso perror("mnl_socket_bind"); 398384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return -1; 399384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 400384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso h->portid = mnl_socket_get_portid(h->nl); 401384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 402384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 0; 403384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 404384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 405384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusovoid nft_fini(struct nft_handle *h) 406384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 407384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso mnl_socket_close(h->nl); 408384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 409384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 410384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_table_add(struct nft_handle *h, const struct nft_table *t) 411384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 412384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso char buf[MNL_SOCKET_BUFFER_SIZE]; 413384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nlmsghdr *nlh; 414384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 4150391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, h->family, 416384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso NLM_F_ACK|NLM_F_EXCL, h->seq); 417384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_table_nlmsg_build_payload(nlh, t); 418384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 419384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return mnl_talk(h, nlh, NULL, NULL); 420384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 421384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 422384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_add(struct nft_handle *h, const struct nft_chain *c) 423384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 424384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso char buf[MNL_SOCKET_BUFFER_SIZE]; 425384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nlmsghdr *nlh; 426384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 4270391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family, 428384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso NLM_F_ACK|NLM_F_EXCL, h->seq); 429384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_nlmsg_build_payload(nlh, c); 430384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 431384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return mnl_talk(h, nlh, NULL, NULL); 432384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 433384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 4345705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayusoint nft_table_set_dormant(struct nft_handle *h, const char *table) 4355705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso{ 4365705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso int ret = 0, i; 4375705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso struct builtin_table *t; 4385705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso 4395705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso t = nft_table_builtin_find(table); 4405705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso if (t == NULL) { 4415705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso ret = -1; 4425705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso goto out; 4435705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso } 4445705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso /* Add this table as dormant */ 4455705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso if (nft_table_builtin_add(h, t, true) < 0) { 4465705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso /* Built-in table already initialized, skip. */ 4475705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso if (errno == EEXIST) 4485705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso goto out; 4495705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso } 4505705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso for (i=0; t->chains[i].name != NULL && i<NF_INET_NUMHOOKS; i++) 4515705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso __nft_chain_builtin_init(h, t, t->chains[i].name, NF_ACCEPT); 4525705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayusoout: 4535705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso return ret; 4545705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso} 4555705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso 4565705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayusoint nft_table_wake_dormant(struct nft_handle *h, const char *table) 4575705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso{ 4585705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso char buf[MNL_SOCKET_BUFFER_SIZE]; 4595705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso struct nlmsghdr *nlh; 4605705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso struct nft_table *t; 4615705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso 4625705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso t = nft_table_alloc(); 4635705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso if (t == NULL) 4645705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso return -1; 4655705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso 4665705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso nft_table_attr_set(t, NFT_TABLE_ATTR_NAME, (char *)table); 4675705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso nft_table_attr_set_u32(t, NFT_TABLE_ATTR_FLAGS, 0); 4685705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso 4690391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, h->family, 4705705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso NLM_F_ACK, h->seq); 4715705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso nft_table_nlmsg_build_payload(nlh, t); 4725705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso nft_table_free(t); 4735705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso 4745705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso return mnl_talk(h, nlh, NULL, NULL); 4755705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso} 4765705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso 477384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_chain_print_debug(struct nft_chain *c, struct nlmsghdr *nlh) 478384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 479384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#ifdef NLDEBUG 480384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso char tmp[1024]; 481384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 482384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_snprintf(tmp, sizeof(tmp), c, 0, 0); 483384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("DEBUG: chain: %s", tmp); 484384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct nfgenmsg)); 485384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif 486384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 487384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 488384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int 489384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__nft_chain_set(struct nft_handle *h, const char *table, 490384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *chain, int policy, 491384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const struct xt_counters *counters) 492384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 493384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso char buf[MNL_SOCKET_BUFFER_SIZE]; 494384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nlmsghdr *nlh; 495384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_chain *c; 496c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso struct builtin_table *_t; 497c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso struct builtin_chain *_c; 498e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso int ret; 499c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso 500c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso _t = nft_table_builtin_find(table); 501c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso /* if this built-in table does not exists, create it */ 502c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso if (_t != NULL) 5035705ea1f4e3c9cd3d5d9cbcf84b9733ce1f07e57Pablo Neira Ayuso nft_table_builtin_add(h, _t, false); 504c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso 505e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso _c = nft_chain_builtin_find(_t, chain); 506c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso if (_c != NULL) { 507c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso /* This is a built-in chain */ 508c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso c = nft_chain_builtin_alloc(_t, _c, policy); 509c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso if (c == NULL) 510c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso return -1; 511c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso 512c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso } else { 513c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso /* This is a custom chain */ 514c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso c = nft_chain_alloc(); 515c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso if (c == NULL) 516c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso return -1; 517c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso 518c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table); 519c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)chain); 520c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso nft_chain_attr_set_u32(c, NFT_CHAIN_ATTR_POLICY, policy); 521c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso } 522384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 523384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (counters) { 524384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_BYTES, 525384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso counters->bcnt); 526384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_PACKETS, 527384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso counters->pcnt); 528384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 529384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 5300391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family, 531384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso NLM_F_ACK, h->seq); 532384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_nlmsg_build_payload(nlh, c); 533384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 534384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_print_debug(c, nlh); 535384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 536384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_free(c); 537384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 538384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ret = mnl_talk(h, nlh, NULL, NULL); 539384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (ret < 0) 540384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso perror("mnl_talk:__nft_chain_policy"); 541384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 542384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return ret; 543384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 544384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 545384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_set(struct nft_handle *h, const char *table, 546384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *chain, const char *policy, 547384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const struct xt_counters *counters) 548384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 549384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int ret = -1; 550384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 551384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_fn = nft_chain_set; 552384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 553384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(policy, "DROP") == 0) 554384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ret = __nft_chain_set(h, table, chain, NF_DROP, counters); 555384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso else if (strcmp(policy, "ACCEPT") == 0) 556384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ret = __nft_chain_set(h, table, chain, NF_ACCEPT, counters); 557384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 558384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* the core expects 1 for success and 0 for error */ 559384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return ret == 0 ? 1 : 0; 560384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 561384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 562384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void __add_match(struct nft_rule_expr *e, struct xt_entry_match *m) 563384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 564384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso void *info; 565384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 566384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_set(e, NFT_EXPR_MT_NAME, m->u.user.name, strlen(m->u.user.name)); 567384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_set_u32(e, NFT_EXPR_MT_REV, m->u.user.revision); 568384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 569384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso info = calloc(1, m->u.match_size); 570384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (info == NULL) 571384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 572384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 573384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso memcpy(info, m->data, m->u.match_size); 574384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_set(e, NFT_EXPR_MT_INFO, info, m->u.match_size - sizeof(*m)); 575384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 576384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 577384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_match(struct nft_rule *r, struct xt_entry_match *m) 578384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 579384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_expr *expr; 580384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 581384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso expr = nft_rule_expr_alloc("match"); 582384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (expr == NULL) 583384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 584384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 585384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso __add_match(expr, m); 586384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_add_expr(r, expr); 587384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 588384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 589384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void __add_target(struct nft_rule_expr *e, struct xt_entry_target *t) 590384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 591384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso void *info = NULL; 592384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 593384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_set(e, NFT_EXPR_TG_NAME, t->u.user.name, 594384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso strlen(t->u.user.name)); 595384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_set_u32(e, NFT_EXPR_TG_REV, t->u.user.revision); 596384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 597384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (info == NULL) { 598384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso info = calloc(1, t->u.target_size); 599384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (info == NULL) 600384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 601384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 602384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso memcpy(info, t->data, t->u.target_size); 603384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 604384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 605384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_set(e, NFT_EXPR_TG_INFO, info, t->u.target_size - sizeof(*t)); 606384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 607384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 608384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_target(struct nft_rule *r, struct xt_entry_target *t) 609384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 610384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_expr *expr; 611384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 612384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso expr = nft_rule_expr_alloc("target"); 613384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (expr == NULL) 614384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 615384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 616384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso __add_target(expr, t); 617384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_add_expr(r, expr); 618384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 619384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 620384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_jumpto(struct nft_rule *r, const char *name, int verdict) 621384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 622384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_expr *expr; 623384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 624384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso expr = nft_rule_expr_alloc("immediate"); 625384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (expr == NULL) 626384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 627384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 628384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_DREG, NFT_REG_VERDICT); 629384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_VERDICT, verdict); 630384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_set_str(expr, NFT_EXPR_IMM_CHAIN, (char *)name); 631384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_add_expr(r, expr); 632384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 633384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 634384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_verdict(struct nft_rule *r, int verdict) 635384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 636384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_expr *expr; 637384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 638384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso expr = nft_rule_expr_alloc("immediate"); 639384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (expr == NULL) 640384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 641384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 642384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_DREG, NFT_REG_VERDICT); 643384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_set_u32(expr, NFT_EXPR_IMM_VERDICT, verdict); 644384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_add_expr(r, expr); 645384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 646384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 647384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_rule_print_debug(struct nft_rule *r, struct nlmsghdr *nlh) 648384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 649384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#ifdef NLDEBUG 650384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso char tmp[1024]; 651384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 652384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_snprintf(tmp, sizeof(tmp), r, 0, 0); 653384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("DEBUG: rule: %s", tmp); 654384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len, sizeof(struct nfgenmsg)); 655384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif 656384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 657384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 658384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_meta(struct nft_rule *r, uint32_t key) 659384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 660384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_expr *expr; 661384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 662384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso expr = nft_rule_expr_alloc("meta"); 663384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (expr == NULL) 664384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 665384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 666384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_set_u32(expr, NFT_EXPR_META_KEY, key); 667384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_set_u32(expr, NFT_EXPR_META_DREG, NFT_REG_1); 668384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 669384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_add_expr(r, expr); 670384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 671384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 672384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_payload(struct nft_rule *r, int offset, int len) 673384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 674384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_expr *expr; 675384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 676384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso expr = nft_rule_expr_alloc("payload"); 677384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (expr == NULL) 678384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 679384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 680384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_set_u32(expr, NFT_EXPR_PAYLOAD_BASE, 681384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso NFT_PAYLOAD_NETWORK_HEADER); 682384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_set_u32(expr, NFT_EXPR_PAYLOAD_DREG, NFT_REG_1); 683384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_set_u32(expr, NFT_EXPR_PAYLOAD_OFFSET, offset); 684384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_set_u32(expr, NFT_EXPR_PAYLOAD_LEN, len); 685384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 686384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_add_expr(r, expr); 687384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 688384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 6892f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso/* bitwise operation is = sreg & mask ^ xor */ 6902f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayusostatic void add_bitwise_u16(struct nft_rule *r, int mask, int xor) 6912f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso{ 6922f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso struct nft_rule_expr *expr; 6932f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso 6942f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso expr = nft_rule_expr_alloc("bitwise"); 6952f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso if (expr == NULL) 6962f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso return; 6972f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso 6982f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso nft_rule_expr_set_u32(expr, NFT_EXPR_BITWISE_SREG, NFT_REG_1); 6992f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso nft_rule_expr_set_u32(expr, NFT_EXPR_BITWISE_DREG, NFT_REG_1); 7002f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso nft_rule_expr_set_u32(expr, NFT_EXPR_BITWISE_LEN, sizeof(uint16_t)); 7012f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso nft_rule_expr_set(expr, NFT_EXPR_BITWISE_MASK, &mask, sizeof(uint16_t)); 7022f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso nft_rule_expr_set(expr, NFT_EXPR_BITWISE_XOR, &xor, sizeof(uint16_t)); 7032f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso 7042f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso nft_rule_add_expr(r, expr); 7052f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso} 7062f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso 707384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_cmp_ptr(struct nft_rule *r, uint32_t op, void *data, size_t len) 708384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 709384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_expr *expr; 710384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 711384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso expr = nft_rule_expr_alloc("cmp"); 712384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (expr == NULL) 713384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 714384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 715384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_set_u8(expr, NFT_EXPR_CMP_SREG, NFT_REG_1); 716384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_set_u8(expr, NFT_EXPR_CMP_OP, op); 717384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_set(expr, NFT_EXPR_CMP_DATA, data, len); 718384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 719384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_add_expr(r, expr); 720384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 721384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 7222f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayusostatic void add_cmp_u16(struct nft_rule *r, uint16_t val, uint32_t op) 7232f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso{ 7242f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso add_cmp_ptr(r, op, &val, sizeof(val)); 7252f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso} 7262f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso 727384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_cmp_u32(struct nft_rule *r, uint32_t val, uint32_t op) 728384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 729384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso add_cmp_ptr(r, op, &val, sizeof(val)); 730384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 731384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 732384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void add_counters(struct nft_rule *r, uint64_t packets, uint64_t bytes) 733384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 734384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_expr *expr; 735384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 736384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso expr = nft_rule_expr_alloc("counter"); 737384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (expr == NULL) 738384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 739384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 740384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_set_u64(expr, NFT_EXPR_CTR_BYTES, packets); 741384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_set_u64(expr, NFT_EXPR_CTR_PACKETS, bytes); 742384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 743384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_add_expr(r, expr); 744384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 745384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 7460391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykastatic void add_iniface(struct nft_rule *r, char *iface, int invflags) 7470391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka{ 7480391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka int iface_len; 7490391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka uint32_t op; 7500391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 7510391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka iface_len = strlen(iface); 7520391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 7530391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (invflags & IPT_INV_VIA_IN) 7540391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka op = NFT_CMP_NEQ; 7550391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka else 7560391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka op = NFT_CMP_EQ; 7570391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 7580391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (iface[iface_len - 1] == '+') { 7590391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_meta(r, NFT_META_IIFNAME); 7600391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_cmp_ptr(r, op, iface, iface_len - 1); 7610391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka } else { 7620391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_meta(r, NFT_META_IIF); 7630391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_cmp_u32(r, if_nametoindex(iface), op); 7640391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka } 7650391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka} 7660391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 7670391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykastatic void add_outiface(struct nft_rule *r, char *iface, int invflags) 7680391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka{ 7690391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka int iface_len; 7700391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka uint32_t op; 7710391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 7720391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka iface_len = strlen(iface); 7730391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 7740391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (invflags & IPT_INV_VIA_OUT) 7750391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka op = NFT_CMP_NEQ; 7760391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka else 7770391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka op = NFT_CMP_EQ; 7780391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 7790391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (iface[iface_len - 1] == '+') { 7800391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_meta(r, NFT_META_OIFNAME); 7810391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_cmp_ptr(r, op, iface, iface_len - 1); 7820391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka } else { 7830391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_meta(r, NFT_META_OIF); 7840391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_cmp_u32(r, if_nametoindex(iface), op); 7850391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka } 7860391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka} 7870391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 7880391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykastatic void add_addr(struct nft_rule *r, int offset, 7890391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka void *data, size_t len, int invflags) 7900391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka{ 7910391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka uint32_t op; 7920391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 7930391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_payload(r, offset, len); 7940391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 7950391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (invflags & IPT_INV_SRCIP || invflags & IPT_INV_DSTIP) 7960391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka op = NFT_CMP_NEQ; 7970391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka else 7980391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka op = NFT_CMP_EQ; 7990391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 8000391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_cmp_ptr(r, op, data, len); 8010391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka} 8020391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 8030391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykastatic void add_proto(struct nft_rule *r, int offset, size_t len, 8040391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka uint32_t proto, int invflags) 8050391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka{ 8060391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka uint32_t op; 8070391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 8080391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_payload(r, offset, len); 8090391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 8100391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (invflags & XT_INV_PROTO) 8110391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka op = NFT_CMP_NEQ; 8120391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka else 8130391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka op = NFT_CMP_EQ; 8140391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 8150391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_cmp_u32(r, proto, op); 8160391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka} 8170391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 818384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint 819384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_rule_add(struct nft_handle *h, const char *chain, const char *table, 8200a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka struct iptables_command_state *cs, 8211298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso bool append, uint64_t handle, bool verbose) 822384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 823384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso char buf[MNL_SOCKET_BUFFER_SIZE]; 824384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nlmsghdr *nlh; 825384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct xtables_rule_match *matchp; 826384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule *r; 827384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int ret = 1; 828384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso uint32_t op; 829384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int flags = append ? NLM_F_APPEND : 0; 8300391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka int ip_flags = 0; 831384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 832e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso /* If built-in chains don't exist for this table, create them */ 833c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso nft_chain_builtin_init(h, table, chain, NF_ACCEPT); 834c74f398c58e7b77ca1c82a15d0b2e9eed4fb82adPablo Neira Ayuso 835384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_fn = nft_rule_add; 836384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 837384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso r = nft_rule_alloc(); 838384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (r == NULL) { 839384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ret = 0; 840384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto err; 841384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 842384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 843384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_attr_set(r, NFT_RULE_ATTR_TABLE, (char *)table); 844384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, (char *)chain); 845384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 8460391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka switch (h->family) { 8470391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka case AF_INET: 8480391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (cs->fw.ip.iniface[0] != '\0') 8490391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_iniface(r, cs->fw.ip.iniface, cs->fw.ip.invflags); 8500391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 8510391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (cs->fw.ip.outiface[0] != '\0') 8520391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_outiface(r, cs->fw.ip.outiface, 8530391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka cs->fw.ip.invflags); 8540391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 8550391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (cs->fw.ip.src.s_addr != 0) 8560391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_addr(r, offsetof(struct iphdr, saddr), 8570391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka &cs->fw.ip.src.s_addr, 4, 8580391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka cs->fw.ip.invflags); 8590391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 8600391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (cs->fw.ip.dst.s_addr != 0) 8610391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_addr(r, offsetof(struct iphdr, daddr), 8620391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka &cs->fw.ip.dst.s_addr, 4, 8630391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka cs->fw.ip.invflags); 8640391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 8650391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (cs->fw.ip.proto != 0) 8660391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_proto(r, offsetof(struct iphdr, protocol), 1, 8670391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka cs->fw.ip.proto, cs->fw.ip.invflags); 8680391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 8690391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (cs->fw.ip.flags & IPT_F_FRAG) { 8700391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_payload(r, offsetof(struct iphdr, frag_off), 2); 8710391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka /* get the 13 bits that contain the fragment offset */ 8720391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_bitwise_u16(r, 0x1fff, !0x1fff); 8730391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 8740391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka /* if offset is non-zero, this is a fragment */ 8750391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (cs->fw.ip.invflags & IPT_INV_FRAG) 8760391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka op = NFT_CMP_EQ; 8770391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka else 8780391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka op = NFT_CMP_NEQ; 8790391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 8800391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_cmp_u16(r, 0, op); 881384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 882384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 8830391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka ip_flags = cs->fw.ip.flags; 884384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 8850391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka break; 8860391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka case AF_INET6: 8870391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (cs->fw6.ipv6.iniface[0] != '\0') 8880391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_iniface(r, cs->fw6.ipv6.iniface, 8890391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka cs->fw6.ipv6.invflags); 890384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 8910391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (cs->fw6.ipv6.outiface[0] != '\0') 8920391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_outiface(r, cs->fw6.ipv6.outiface, 8930391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka cs->fw6.ipv6.invflags); 894384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 8950391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (!IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.src)) 8960391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_addr(r, offsetof(struct ip6_hdr, ip6_src), 8970391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka &cs->fw6.ipv6.src, 16, 8980391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka cs->fw6.ipv6.invflags); 899384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 9000391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (!IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.dst)) 9010391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_addr(r, offsetof(struct ip6_hdr, ip6_dst), 9020391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka &cs->fw6.ipv6.dst, 16, 9030391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka cs->fw6.ipv6.invflags); 9042f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso 9050391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (cs->fw6.ipv6.proto != 0) 9060391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka add_proto(r, offsetof(struct ip6_hdr, ip6_nxt), 1, 9070391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka cs->fw6.ipv6.proto, cs->fw6.ipv6.invflags); 9080391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 9090391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka ip_flags = cs->fw6.ipv6.flags; 9102f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso 9110391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka break; 9122f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso } 913384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 914384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso for (matchp = cs->matches; matchp; matchp = matchp->next) 915384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso add_match(r, matchp->match->m); 916384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 917384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* Counters need to me added before the target, otherwise they are 918384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso * increased for each rule because of the way nf_tables works. 919384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso */ 920384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso add_counters(r, cs->counters.pcnt, cs->counters.bcnt); 921384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 922384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* If no target at all, add nothing (default to continue) */ 923384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (cs->target != NULL) { 924384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* Standard target? */ 925384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(cs->jumpto, XTC_LABEL_ACCEPT) == 0) 926384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso add_verdict(r, NF_ACCEPT); 927384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso else if (strcmp(cs->jumpto, XTC_LABEL_DROP) == 0) 928384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso add_verdict(r, NF_DROP); 929384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso else if (strcmp(cs->jumpto, XTC_LABEL_RETURN) == 0) 930384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso add_verdict(r, NFT_RETURN); 931384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso else 932384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso add_target(r, cs->target->t); 933384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } else if (strlen(cs->jumpto) > 0) { 934384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* Not standard, then it's a go / jump to chain */ 9350391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (ip_flags & IPT_F_GOTO) 936384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso add_jumpto(r, cs->jumpto, NFT_GOTO); 937384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso else 938384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso add_jumpto(r, cs->jumpto, NFT_JUMP); 939384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 940384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 941384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* NLM_F_CREATE autoloads the built-in table if it does not exists */ 9420a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka flags |= NLM_F_ACK|NLM_F_CREATE; 9430a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka 9440a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka if (handle > 0) { 9450a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka nft_rule_attr_set(r, NFT_RULE_ATTR_HANDLE, &handle); 9460a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka flags |= NLM_F_REPLACE; 9470a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka } 9480a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka 9499e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso if (h->commit) { 9509e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS, 9519e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso NFT_RULE_F_COMMIT); 9529e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso } 9530a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, 9540391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka h->family, flags, h->seq); 9550a366d8696582e979d55f6832a797d1217f4b908Tomasz Bursztyka 956384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_nlmsg_build_payload(nlh, r); 957384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 958384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_print_debug(r, nlh); 959384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 960384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_free(r); 961384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 962384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ret = mnl_talk(h, nlh, NULL, NULL); 963384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (ret < 0) 964384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso perror("mnl_talk:nft_rule_add"); 965384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 966384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr: 967384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* the core expects 1 for success and 0 for error */ 968384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return ret == 0 ? 1 : 0; 969384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 970384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 971384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_match_save(struct nft_rule_expr *expr) 972384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 973384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *name; 974384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const struct xtables_match *match; 975384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct xt_entry_match *emu; 976384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const void *mtinfo; 977384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso size_t len; 978384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 979384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso name = nft_rule_expr_get_str(expr, NFT_EXPR_MT_NAME); 980384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 981384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso match = xtables_find_match(name, XTF_TRY_LOAD, NULL); 982384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (match == NULL) 983384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 984384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 985384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso mtinfo = nft_rule_expr_get(expr, NFT_EXPR_MT_INFO, &len); 986384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (mtinfo == NULL) 987384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 988384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 989384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso emu = calloc(1, sizeof(struct xt_entry_match) + len); 990384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (emu == NULL) 991384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 992384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 993384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso memcpy(&emu->data, mtinfo, len); 994384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 995384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (match->alias) 996384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("-m %s", match->alias(emu)); 997384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso else 998384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("-m %s", match->name); 999384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1000384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* FIXME missing parameter */ 1001384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso match->save(NULL, emu); 1002384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1003384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(" "); 1004384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1005384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso free(emu); 1006384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1007384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1008384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_target_save(struct nft_rule_expr *expr) 1009384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1010384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *name; 1011384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const struct xtables_target *target; 1012384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct xt_entry_target *emu; 1013384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const void *tginfo; 1014384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso size_t len; 1015384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1016384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso name = nft_rule_expr_get_str(expr, NFT_EXPR_TG_NAME); 1017384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1018384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* Standard target not supported, we use native immediate expression */ 1019384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(name, "") == 0) { 1020384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("ERROR: standard target seen, should not happen\n"); 1021384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 1022384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1023384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1024384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso target = xtables_find_target(name, XTF_TRY_LOAD); 1025384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (target == NULL) 1026384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 1027384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1028384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso tginfo = nft_rule_expr_get(expr, NFT_EXPR_TG_INFO, &len); 1029384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (tginfo == NULL) 1030384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 1031384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1032384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso emu = calloc(1, sizeof(struct xt_entry_match) + len); 1033384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (emu == NULL) 1034384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 1035384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1036384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso memcpy(emu->data, tginfo, len); 1037384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1038384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (target->alias) 1039384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("-j %s", target->alias(emu)); 1040384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso else 1041384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("-j %s", target->name); 1042384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1043384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* FIXME missing parameter */ 1044384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso target->save(NULL, emu); 1045384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1046384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso free(emu); 1047384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1048384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1049384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_immediate_save(struct nft_rule_expr *expr) 1050384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1051384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso uint32_t verdict; 1052384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1053384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso verdict = nft_rule_expr_get_u32(expr, NFT_EXPR_IMM_VERDICT); 1054384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1055384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso switch(verdict) { 1056384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NF_ACCEPT: 1057384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("-j ACCEPT"); 1058384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 1059384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NF_DROP: 1060384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("-j DROP"); 1061384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 1062384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_RETURN: 1063384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("-j RETURN"); 1064384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 1065384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_GOTO: 1066384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("-g %s", 1067384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_get_str(expr, NFT_EXPR_IMM_CHAIN)); 1068384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 1069384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_JUMP: 1070384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("-j %s", 1071384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_get_str(expr, NFT_EXPR_IMM_CHAIN)); 1072384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 1073384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1074384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1075384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1076384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void 1077384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_print_meta(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter) 1078384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1079384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso uint8_t key = nft_rule_expr_get_u8(e, NFT_EXPR_META_KEY); 1080384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso uint32_t value; 1081384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *name; 1082384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso char ifname[IFNAMSIZ]; 1083384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *ifname_ptr; 1084384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso size_t len; 1085384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1086384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso e = nft_rule_expr_iter_next(iter); 1087384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (e == NULL) 1088384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 1089384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1090384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME); 1091384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* meta should be followed by cmp */ 1092384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(name, "cmp") != 0) { 1093384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("skipping no cmp after meta\n"); 1094384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 1095384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1096384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1097384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso switch(key) { 1098384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_META_IIF: 1099384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso value = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_DATA); 1100384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if_indextoname(value, ifname); 1101384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1102384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso switch(nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP)) { 1103384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_CMP_EQ: 1104384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("-i %s ", ifname); 1105384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 1106384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_CMP_NEQ: 1107384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("! -i %s ", ifname); 1108384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 1109384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1110384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 1111384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_META_OIF: 1112384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso value = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_DATA); 1113384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if_indextoname(value, ifname); 1114384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1115384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso switch(nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP)) { 1116384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_CMP_EQ: 1117384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("-o %s ", ifname); 1118384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 1119384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_CMP_NEQ: 1120384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("! -o %s ", ifname); 1121384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 1122384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1123384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 1124384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_META_IIFNAME: 1125384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ifname_ptr = nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len); 1126384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso memcpy(ifname, ifname_ptr, len); 1127384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ifname[len] = '\0'; 1128384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1129384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* if this is zero, then assume this is a interface mask */ 1130384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (if_nametoindex(ifname) == 0) { 1131384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ifname[len] = '+'; 1132384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ifname[len+1] = '\0'; 1133384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1134384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1135384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso switch(nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP)) { 1136384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_CMP_EQ: 1137384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("-i %s ", ifname); 1138384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 1139384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_CMP_NEQ: 1140384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("! -i %s ", ifname); 1141384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 1142384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1143384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 1144384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_META_OIFNAME: 1145384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ifname_ptr = nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len); 1146384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso memcpy(ifname, ifname_ptr, len); 1147384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ifname[len] = '\0'; 1148384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1149384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* if this is zero, then assume this is a interface mask */ 1150384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (if_nametoindex(ifname) == 0) { 1151384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ifname[len] = '+'; 1152384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ifname[len+1] = '\0'; 1153384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1154384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1155384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso switch(nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP)) { 1156384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_CMP_EQ: 1157384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("-o %s ", ifname); 1158384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 1159384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_CMP_NEQ: 1160384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("! -o %s ", ifname); 1161384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 1162384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1163384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 1164384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso default: 1165384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("unknown meta key %d\n", key); 1166384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 1167384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1168384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1169384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1170384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void 1171384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoget_cmp_data(struct nft_rule_expr_iter *iter, void *data, size_t dlen, bool *inv) 1172384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1173384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_expr *e; 1174384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *name; 1175384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso size_t len; 1176384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso uint8_t op; 1177384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1178384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso e = nft_rule_expr_iter_next(iter); 1179384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (e == NULL) 1180384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 1181384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1182384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME); 1183384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(name, "cmp") != 0) { 1184384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("skipping no cmp after meta\n"); 1185384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 1186384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1187384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1188384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso memcpy(data, nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len), dlen); 1189384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso op = nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP); 1190384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (op == NFT_CMP_NEQ) 1191384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso *inv = true; 1192384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso else 1193384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso *inv = false; 1194384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1195384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 11962f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayusostatic void get_frag(struct nft_rule_expr_iter *iter, bool *inv) 11972f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso{ 11982f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso struct nft_rule_expr *e; 11992f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso const char *name; 12002f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso uint8_t op; 12012f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso 12022f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso e = nft_rule_expr_iter_next(iter); 12032f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso if (e == NULL) 12042f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso return; 12052f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso 12062f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso /* we assume correct mask and xor */ 12072f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME); 12082f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso if (strcmp(name, "bitwise") != 0) { 12092f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso DEBUGP("skipping no bitwise after payload\n"); 12102f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso return; 12112f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso } 12122f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso 12132f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso /* Now check for cmp */ 12142f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso e = nft_rule_expr_iter_next(iter); 12152f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso if (e == NULL) 12162f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso return; 12172f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso 12182f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso /* we assume correct data */ 12192f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME); 12202f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso if (strcmp(name, "cmp") != 0) { 12212f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso DEBUGP("skipping no cmp after payload\n"); 12222f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso return; 12232f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso } 12242f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso 12252f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso op = nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP); 12262f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso if (op == NFT_CMP_EQ) 12272f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso *inv = true; 12282f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso else 12292f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso *inv = false; 12302f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso} 12312f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso 12322f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayusostatic void print_frag(bool inv) 12332f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso{ 12342f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso if (inv) 12352f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso printf("! -f "); 12362f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso else 12372f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso printf("-f "); 12382f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso} 12392f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso 1240384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void print_proto(uint16_t proto, int invert) 1241384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1242384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const struct protoent *pent = getprotobynumber(proto); 1243384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1244384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (invert) 1245384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("! "); 1246384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1247384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (pent) { 1248384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("-p %s ", pent->p_name); 1249384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 1250384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1251384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1252384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("-p %u ", proto); 1253384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1254384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1255384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic const char *mask_to_str(uint32_t mask) 1256384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1257384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso static char mask_str[sizeof("255.255.255.255")]; 1258384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso uint32_t bits, hmask = ntohl(mask); 1259384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct in_addr mask_addr = { 1260384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso .s_addr = mask, 1261384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso }; 1262384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int i; 1263384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1264384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (mask == 0xFFFFFFFFU) { 1265384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso sprintf(mask_str, "32"); 1266384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return mask_str; 1267384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1268384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1269384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso i = 32; 1270384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso bits = 0xFFFFFFFEU; 1271384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso while (--i >= 0 && hmask != bits) 1272384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso bits <<= 1; 1273384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (i >= 0) 1274384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso sprintf(mask_str, "%u", i); 1275384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso else 1276384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso sprintf(mask_str, "%s", inet_ntoa(mask_addr)); 1277384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1278384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return mask_str; 1279384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1280384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1281384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void 12820391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykanft_print_payload_ipv4(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter) 1283384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1284384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso uint32_t offset; 1285384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso bool inv; 1286384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1287384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso offset = nft_rule_expr_get_u32(e, NFT_EXPR_PAYLOAD_OFFSET); 1288384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1289384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso switch(offset) { 1290384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct in_addr addr; 1291384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso uint8_t proto; 1292384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1293384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case offsetof(struct iphdr, saddr): 1294384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso get_cmp_data(iter, &addr, sizeof(addr), &inv); 1295384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (inv) 1296384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("! -s %s/%s ", inet_ntoa(addr), 1297384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso mask_to_str(0xffffffff)); 1298384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso else 1299384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("-s %s/%s ", inet_ntoa(addr), 1300384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso mask_to_str(0xffffffff)); 1301384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 1302384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case offsetof(struct iphdr, daddr): 1303384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso get_cmp_data(iter, &addr, sizeof(addr), &inv); 1304384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (inv) 1305384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("! -d %s/%s ", inet_ntoa(addr), 1306384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso mask_to_str(0xffffffff)); 1307384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso else 1308384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("-d %s/%s ", inet_ntoa(addr), 1309384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso mask_to_str(0xffffffff)); 1310384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 1311384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case offsetof(struct iphdr, protocol): 1312384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso get_cmp_data(iter, &proto, sizeof(proto), &inv); 1313384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso print_proto(proto, inv); 1314384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 13152f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso case offsetof(struct iphdr, frag_off): 13162f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso get_frag(iter, &inv); 13172f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso print_frag(inv); 13182f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso break; 1319384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso default: 1320384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("unknown payload offset %d\n", offset); 1321384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 1322384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1323384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1324384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1325384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void 13260391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykanft_print_payload_ipv6(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter) 13270391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka{ 13280391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka uint32_t offset; 13290391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka bool inv; 13300391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 13310391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka offset = nft_rule_expr_get_u32(e, NFT_EXPR_PAYLOAD_OFFSET); 13320391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 13330391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka switch (offset) { 13340391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka char addr_str[INET6_ADDRSTRLEN]; 13350391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka struct in6_addr addr; 13360391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka uint8_t proto; 13370391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka case offsetof(struct ip6_hdr, ip6_src): 13380391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka get_cmp_data(iter, &addr, sizeof(addr), &inv); 13390391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka inet_ntop(AF_INET6, &addr, addr_str, INET6_ADDRSTRLEN); 13400391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 13410391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (inv) 13420391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka printf("! -s %s ", addr_str); 13430391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka else 13440391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka printf("-s %s ", addr_str); 13450391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 13460391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka break; 13470391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka case offsetof(struct ip6_hdr, ip6_dst): 13480391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka get_cmp_data(iter, &addr, sizeof(addr), &inv); 13490391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka inet_ntop(AF_INET6, &addr, addr_str, INET6_ADDRSTRLEN); 13500391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 13510391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (inv) 13520391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka printf("! -d %s ", addr_str); 13530391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka else 13540391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka printf("-d %s ", addr_str); 13550391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 13560391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka break; 13570391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka case offsetof(struct ip6_hdr, ip6_nxt): 13580391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka get_cmp_data(iter, &proto, sizeof(proto), &inv); 13590391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka print_proto(proto, inv); 13600391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka break; 13610391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka default: 13620391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka DEBUGP("unknown payload offset %d\n", offset); 13630391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka break; 13640391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka } 13650391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka} 13660391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 13670391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykastatic void 1368384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_print_counters(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter, 1369384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso bool counters) 1370384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1371384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (counters) { 1372384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("-c %lu %lu ", 1373384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_get_u64(e, NFT_EXPR_CTR_PACKETS), 1374384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_get_u64(e, NFT_EXPR_CTR_BYTES)); 1375384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1376384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1377384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1378384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_rule_print_save(struct nft_rule *r, bool counters) 1379384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1380384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_expr_iter *iter; 1381384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_expr *expr; 1382384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1383384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* print chain name */ 1384384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("-A %s ", nft_rule_attr_get_str(r, NFT_RULE_ATTR_CHAIN)); 1385384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1386384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso iter = nft_rule_expr_iter_create(r); 1387384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (iter == NULL) 1388384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 1389384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1390384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso expr = nft_rule_expr_iter_next(iter); 1391384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso while (expr != NULL) { 1392384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *name = 1393384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME); 1394384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1395384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(name, "counter") == 0) { 1396384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_print_counters(expr, iter, counters); 1397384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } else if (strcmp(name, "payload") == 0) { 13980391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY) == AF_INET) 13990391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka nft_print_payload_ipv4(expr, iter); 14000391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka else 14010391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka nft_print_payload_ipv6(expr, iter); 1402384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } else if (strcmp(name, "meta") == 0) { 1403384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_print_meta(expr, iter); 1404384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } else if (strcmp(name, "match") == 0) { 1405384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_match_save(expr); 1406384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } else if (strcmp(name, "target") == 0) { 1407384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_target_save(expr); 1408384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } else if (strcmp(name, "immediate") == 0) { 1409384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_immediate_save(expr); 1410384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1411384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1412384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso expr = nft_rule_expr_iter_next(iter); 1413384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1414384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1415384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("\n"); 1416384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1417384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1418384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int nft_chain_list_cb(const struct nlmsghdr *nlh, void *data) 1419384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1420384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_chain *c; 1421384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_chain_list *list = data; 1422384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1423384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso c = nft_chain_alloc(); 1424384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (c == NULL) { 1425384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso perror("OOM"); 1426384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto err; 1427384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1428384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1429384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (nft_chain_nlmsg_parse(nlh, c) < 0) { 1430384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso perror("nft_rule_nlmsg_parse"); 1431384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto out; 1432384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1433384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1434384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_list_add(c, list); 1435384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1436384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return MNL_CB_OK; 1437384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoout: 1438384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_free(c); 1439384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr: 1440384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return MNL_CB_OK; 1441384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1442384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1443384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic struct nft_chain_list *nft_chain_list_get(struct nft_handle *h) 1444384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1445384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso char buf[MNL_SOCKET_BUFFER_SIZE]; 1446384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nlmsghdr *nlh; 1447384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int ret; 1448384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_chain_list *list; 1449384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1450384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso list = nft_chain_list_alloc(); 1451384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (list == NULL) { 1452384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("cannot allocate rule list\n"); 1453384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 0; 1454384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1455384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 14560391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family, 1457384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso NLM_F_DUMP, h->seq); 1458384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1459384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ret = mnl_talk(h, nlh, nft_chain_list_cb, list); 1460384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (ret < 0) 1461384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso perror("mnl_talk:nft_chain_list_get"); 1462384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1463384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return list; 1464384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1465384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1466384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostruct nft_chain_list *nft_chain_dump(struct nft_handle *h) 1467384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1468384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return nft_chain_list_get(h); 1469384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1470384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1471384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic const char *policy_name[NF_ACCEPT+1] = { 1472384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso [NF_DROP] = "DROP", 1473384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso [NF_ACCEPT] = "ACCEPT", 1474384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso}; 1475384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1476384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void nft_chain_print_save(struct nft_chain *c, bool basechain) 1477384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1478384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *chain = nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME); 1479384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso uint64_t pkts = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_PACKETS); 1480384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso uint64_t bytes = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_BYTES); 1481384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1482384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* print chain name */ 1483384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (basechain) { 1484384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso uint32_t pol = NF_ACCEPT; 1485384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1486384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* no default chain policy? don't crash, display accept */ 1487384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (nft_chain_attr_get(c, NFT_CHAIN_ATTR_POLICY)) 1488384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso pol = nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_POLICY); 1489384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1490384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(":%s %s [%lu:%lu]\n", chain, policy_name[pol], 1491384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso pkts, bytes); 1492384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } else 1493384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(":%s - [%lu:%lu]\n", chain, pkts, bytes); 1494384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1495384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1496384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_save(struct nft_handle *h, struct nft_chain_list *list, 1497384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *table) 1498384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1499384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_chain_list_iter *iter; 1500384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_chain *c; 1501384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1502384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso iter = nft_chain_list_iter_create(list); 1503384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (iter == NULL) { 1504384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("cannot allocate rule list iterator\n"); 1505384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 0; 1506384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1507384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1508384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso c = nft_chain_list_iter_next(iter); 1509384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso while (c != NULL) { 1510384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *chain_table = 1511384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE); 1512384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso bool basechain = false; 1513384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1514384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(table, chain_table) != 0) 1515384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto next; 1516384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1517384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (nft_chain_attr_get(c, NFT_CHAIN_ATTR_HOOKNUM)) 1518384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso basechain = true; 1519384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1520384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_print_save(c, basechain); 1521384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext: 1522384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso c = nft_chain_list_iter_next(iter); 1523384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1524384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1525384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_list_free(list); 1526384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1527384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 1; 1528384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1529384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1530384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int nft_rule_list_cb(const struct nlmsghdr *nlh, void *data) 1531384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1532384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule *r; 1533384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_list *list = data; 1534384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1535384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso r = nft_rule_alloc(); 1536384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (r == NULL) { 1537384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso perror("OOM"); 1538384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto err; 1539384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1540384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1541384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (nft_rule_nlmsg_parse(nlh, r) < 0) { 1542384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso perror("nft_rule_nlmsg_parse"); 1543384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto out; 1544384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1545384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1546384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_list_add(r, list); 1547384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1548384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return MNL_CB_OK; 1549384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoout: 1550384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_free(r); 1551384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr: 1552384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return MNL_CB_OK; 1553384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1554384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1555384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic struct nft_rule_list *nft_rule_list_get(struct nft_handle *h) 1556384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1557384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso char buf[MNL_SOCKET_BUFFER_SIZE]; 1558384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nlmsghdr *nlh; 1559384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_list *list; 1560384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int ret; 1561384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1562384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso list = nft_rule_list_alloc(); 1563384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (list == NULL) { 1564384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("cannot allocate rule list\n"); 1565384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 0; 1566384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1567384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 15680391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, h->family, 1569384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso NLM_F_DUMP, h->seq); 1570384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1571384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ret = mnl_talk(h, nlh, nft_rule_list_cb, list); 1572384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (ret < 0) { 1573384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso perror("mnl_talk:nft_rule_save"); 1574384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_list_free(list); 1575384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return NULL; 1576384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1577384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1578384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return list; 1579384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1580384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1581384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_save(struct nft_handle *h, const char *table, bool counters) 1582384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1583384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_list *list; 1584384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_list_iter *iter; 1585384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule *r; 1586384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1587384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso list = nft_rule_list_get(h); 1588384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (list == NULL) { 1589384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("cannot retrieve rule list from kernel\n"); 1590384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 0; 1591384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1592384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1593384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso iter = nft_rule_list_iter_create(list); 1594384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (iter == NULL) { 1595384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("cannot allocate rule list iterator\n"); 1596384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 0; 1597384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1598384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1599384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso r = nft_rule_list_iter_next(iter); 1600384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso while (r != NULL) { 1601384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *rule_table = 1602384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_attr_get_str(r, NFT_RULE_ATTR_TABLE); 1603384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1604384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(table, rule_table) != 0) 1605384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto next; 1606384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1607384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_print_save(r, counters); 1608384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1609384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext: 1610384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso r = nft_rule_list_iter_next(iter); 1611384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1612384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1613384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_list_free(list); 1614384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1615384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* the core expects 1 for success and 0 for error */ 1616384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 1; 1617384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1618384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1619384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void 1620384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__nft_rule_flush(struct nft_handle *h, const char *table, const char *chain) 1621384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1622384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso char buf[MNL_SOCKET_BUFFER_SIZE]; 1623384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nlmsghdr *nlh; 1624384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule *r; 1625384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1626384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso r = nft_rule_alloc(); 1627384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (r == NULL) 1628384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 1629384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1630384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_attr_set(r, NFT_RULE_ATTR_TABLE, (char *)table); 1631384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, (char *)chain); 1632384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 16339e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso if (h->commit) { 16349e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS, 16359e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso NFT_RULE_F_COMMIT); 16369e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso } 16379e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso 1638384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* Delete all rules in this table + chain */ 16390391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_DELRULE, h->family, 1640384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso NLM_F_ACK, h->seq); 1641384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_nlmsg_build_payload(nlh, r); 1642384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_free(r); 1643384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1644384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (mnl_talk(h, nlh, NULL, NULL) < 0) { 1645384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (errno != EEXIST) 1646384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso perror("mnl_talk:__nft_rule_flush"); 1647384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1648384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1649384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1650384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_flush(struct nft_handle *h, const char *chain, const char *table) 1651384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1652384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int ret; 1653384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_chain_list *list; 1654384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_chain_list_iter *iter; 1655384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_chain *c; 1656384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1657384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_fn = nft_rule_flush; 1658384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1659384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso list = nft_chain_list_get(h); 1660384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (list == NULL) { 1661384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ret = 0; 1662384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto err; 1663384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1664384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1665384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso iter = nft_chain_list_iter_create(list); 1666384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (iter == NULL) { 1667384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("cannot allocate rule list iterator\n"); 1668384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 0; 1669384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1670384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1671384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso c = nft_chain_list_iter_next(iter); 1672384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso while (c != NULL) { 1673384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *table_name = 1674384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE); 1675384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *chain_name = 1676384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME); 1677384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1678384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(table, table_name) != 0) 1679384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto next; 1680384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1681384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (chain != NULL && strcmp(chain, chain_name) != 0) 1682384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto next; 1683384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1684384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso __nft_rule_flush(h, table_name, chain_name); 1685384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1686384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext: 1687384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso c = nft_chain_list_iter_next(iter); 1688384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1689384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1690384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr: 1691384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_list_free(list); 1692384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1693384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* the core expects 1 for success and 0 for error */ 1694384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return ret == 0 ? 1 : 0; 1695384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1696384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1697384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table) 1698384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1699384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso char buf[MNL_SOCKET_BUFFER_SIZE]; 1700384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nlmsghdr *nlh; 1701384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_chain *c; 1702384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int ret; 1703384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1704e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso /* If built-in chains don't exist for this table, create them */ 1705e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso nft_chain_builtin_init(h, table, NULL, NF_ACCEPT); 1706e17b5f15c2beda86565a8f4e55fdf12ceb20dd59Pablo Neira Ayuso 1707384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso c = nft_chain_alloc(); 1708384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (c == NULL) { 1709384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("cannot allocate chain\n"); 1710384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return -1; 1711384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1712384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1713384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table); 1714384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)chain); 1715384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 17160391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family, 1717384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso NLM_F_ACK|NLM_F_EXCL, h->seq); 1718384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_nlmsg_build_payload(nlh, c); 1719384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_free(c); 1720384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1721384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ret = mnl_talk(h, nlh, NULL, NULL); 1722384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (ret < 0) { 1723384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (errno != EEXIST) 1724384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso perror("mnl_talk:nft_chain_add"); 1725384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1726384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1727384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* the core expects 1 for success and 0 for error */ 1728384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return ret == 0 ? 1 : 0; 1729384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1730384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1731384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int __nft_chain_del(struct nft_handle *h, struct nft_chain *c) 1732384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1733384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso char buf[MNL_SOCKET_BUFFER_SIZE]; 1734384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nlmsghdr *nlh; 1735384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int ret; 1736384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 17370391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_DELCHAIN, h->family, 1738384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso NLM_F_ACK, h->seq); 1739384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_nlmsg_build_payload(nlh, c); 1740384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1741384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ret = mnl_talk(h, nlh, NULL, NULL); 1742384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (ret < 0) { 1743384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (errno != EEXIST && errno != ENOENT) 1744384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso perror("mnl_talk:__nft_chain_del"); 1745384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1746384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1747384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return ret; 1748384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1749384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1750384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool nft_chain_builtin(struct nft_chain *c) 1751384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1752384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* Check if this chain has hook number, in that case is built-in. 1753384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso * Should we better export the flags to user-space via nf_tables? 1754384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso */ 1755384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return nft_chain_attr_get(c, NFT_CHAIN_ATTR_HOOKNUM) != NULL; 1756384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1757384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1758384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_user_del(struct nft_handle *h, const char *chain, const char *table) 1759384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1760384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_chain_list *list; 1761384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_chain_list_iter *iter; 1762384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_chain *c; 1763384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int ret = 0; 1764384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int deleted_ctr = 0; 1765384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1766384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso list = nft_chain_list_get(h); 1767384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (list == NULL) 1768384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto err; 1769384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1770384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso iter = nft_chain_list_iter_create(list); 1771384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (iter == NULL) { 1772384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("cannot allocate rule list iterator\n"); 1773384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 0; 1774384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1775384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1776384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso c = nft_chain_list_iter_next(iter); 1777384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso while (c != NULL) { 1778384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *table_name = 1779384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE); 1780384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *chain_name = 1781384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME); 1782384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1783384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* don't delete built-in chain */ 1784384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (nft_chain_builtin(c)) 1785384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto next; 1786384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1787384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(table, table_name) != 0) 1788384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto next; 1789384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1790384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (chain != NULL && strcmp(chain, chain_name) != 0) 1791384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto next; 1792384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1793384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ret = __nft_chain_del(h, c); 1794384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (ret < 0) 1795384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 1796384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1797384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso deleted_ctr++; 1798384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext: 1799384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso c = nft_chain_list_iter_next(iter); 1800384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1801384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1802384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr: 1803384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_list_free(list); 1804384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1805384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* chain not found */ 1806384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (ret < 0 && deleted_ctr == 0) 1807384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso errno = ENOENT; 1808384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1809384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* the core expects 1 for success and 0 for error */ 1810384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return ret == 0 ? 1 : 0; 1811384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1812384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 18130aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusostruct nft_chain * 18140aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusonft_chain_list_find(struct nft_handle *h, struct nft_chain_list *list, 18150aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso const char *table, const char *chain) 18169c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso{ 18179c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso struct nft_chain_list_iter *iter; 18189c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso struct nft_chain *c; 18199c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso 18209c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso iter = nft_chain_list_iter_create(list); 18219c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso if (iter == NULL) { 18229c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso DEBUGP("cannot allocate rule list iterator\n"); 18239c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso return NULL; 18249c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso } 18259c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso 18269c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso c = nft_chain_list_iter_next(iter); 18279c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso while (c != NULL) { 18289c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso const char *table_name = 18299c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE); 18309c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso const char *chain_name = 18319c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME); 18329c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso 18339c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso if (strcmp(table, table_name) != 0) 18349c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso goto next; 18359c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso 18369c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso if (strcmp(chain, chain_name) != 0) 18379c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso goto next; 18389c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso 18390aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso nft_chain_list_iter_destroy(iter); 18409c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso return c; 18419c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayusonext: 18429c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso c = nft_chain_list_iter_next(iter); 18439c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso } 18440aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso nft_chain_list_iter_destroy(iter); 18459c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso return NULL; 18469c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso} 18479c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso 18480aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusostatic struct nft_chain * 18490aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusonft_chain_find(struct nft_handle *h, const char *table, const char *chain) 18500aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso{ 18510aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso struct nft_chain_list *list; 18520aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso 18530aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso list = nft_chain_list_get(h); 18540aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso if (list == NULL) { 18550aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso DEBUGP("cannot allocate chain list\n"); 18560aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso return NULL; 18570aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso } 18580aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso 18590aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso return nft_chain_list_find(h, list, table, chain); 18600aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso} 18610aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso 1862384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_chain_user_rename(struct nft_handle *h,const char *chain, 1863384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *table, const char *newname) 1864384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 18654493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka char buf[MNL_SOCKET_BUFFER_SIZE]; 18664493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka struct nlmsghdr *nlh; 18674493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka struct nft_chain *c; 18689c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso uint64_t handle; 1869384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int ret; 1870384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 18714493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka /* If built-in chains don't exist for this table, create them */ 18724493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka nft_chain_builtin_init(h, table, NULL, NF_ACCEPT); 18734493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka 18749c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso /* Find the old chain to be renamed */ 18759c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso c = nft_chain_find(h, table, chain); 18769c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso if (c == NULL) { 18779c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso errno = ENOENT; 18789c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso return -1; 18799c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso } 18809c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso handle = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_HANDLE); 18819c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso 18829c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso /* Now prepare the new name for the chain */ 18834493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka c = nft_chain_alloc(); 18844493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka if (c == NULL) { 18854493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka DEBUGP("cannot allocate chain\n"); 18864493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka return -1; 18874493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka } 18884493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka 18894493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table); 18909c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)newname); 18919c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_HANDLE, handle); 1892384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 18930391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family, 18949c541721d318598db45986ee2fd61491fadb53d0Pablo Neira Ayuso NLM_F_ACK, h->seq); 18954493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka nft_chain_nlmsg_build_payload(nlh, c); 18964493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka nft_chain_free(c); 18974493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka 18984493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka ret = mnl_talk(h, nlh, NULL, NULL); 18994493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka if (ret < 0) { 19004493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka if (errno != EEXIST) 19014493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka perror("mnl_talk:nft_chain_rename"); 19024493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka } 19034493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka 19044493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka /* the core expects 1 for success and 0 for error */ 19054493582ccb60a443fc7efeca78edafbefc689aa3Tomasz Bursztyka return ret == 0 ? 1 : 0; 1906384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1907384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1908384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int nft_table_list_cb(const struct nlmsghdr *nlh, void *data) 1909384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1910384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_table *t; 1911384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_table_list *list = data; 1912384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1913384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso t = nft_table_alloc(); 1914384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (t == NULL) { 1915384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso perror("OOM"); 1916384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto err; 1917384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1918384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1919384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (nft_table_nlmsg_parse(nlh, t) < 0) { 1920384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso perror("nft_rule_nlmsg_parse"); 1921384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto out; 1922384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1923384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1924384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_table_list_add(t, list); 1925384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1926384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return MNL_CB_OK; 1927384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoout: 1928384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_table_free(t); 1929384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr: 1930384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return MNL_CB_OK; 1931384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1932384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1933384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic struct nft_table_list *nft_table_list_get(struct nft_handle *h) 1934384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1935384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso char buf[MNL_SOCKET_BUFFER_SIZE]; 1936384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nlmsghdr *nlh; 1937384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int ret; 1938384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_table_list *list; 1939384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1940384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso list = nft_table_list_alloc(); 1941384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (list == NULL) { 1942384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("cannot allocate table list\n"); 1943384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 0; 1944384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1945384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 19460391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, h->family, 1947384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso NLM_F_DUMP, h->seq); 1948384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1949384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ret = mnl_talk(h, nlh, nft_table_list_cb, list); 1950384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (ret < 0) 1951384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso perror("mnl_talk:nft_table_list_get"); 1952384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1953384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return list; 1954384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1955384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1956384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusobool nft_table_find(struct nft_handle *h, const char *tablename) 1957384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1958384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_table_list *list; 1959384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_table_list_iter *iter; 1960384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_table *t; 1961384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso bool ret = false; 1962384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1963384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso list = nft_table_list_get(h); 1964384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (list == NULL) 1965384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto err; 1966384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1967384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso iter = nft_table_list_iter_create(list); 1968384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (iter == NULL) { 1969384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("cannot allocate rule list iterator\n"); 1970384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto err; 1971384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1972384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1973384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso t = nft_table_list_iter_next(iter); 1974384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso while (t != NULL) { 1975384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *this_tablename = 1976384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_table_attr_get(t, NFT_TABLE_ATTR_NAME); 1977384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1978384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(tablename, this_tablename) == 0) 1979384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return true; 1980384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1981384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso t = nft_table_list_iter_next(iter); 1982384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 1983384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1984384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_table_list_free(list); 1985384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1986384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr: 1987384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return ret; 1988384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 1989384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1990384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_for_each_table(struct nft_handle *h, 1991384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int (*func)(struct nft_handle *h, const char *tablename, bool counters), 1992384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso bool counters) 1993384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 1994384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int ret = 1; 1995384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_table_list *list; 1996384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_table_list_iter *iter; 1997384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_table *t; 1998384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 1999384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso list = nft_table_list_get(h); 2000384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (list == NULL) { 2001384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ret = 0; 2002384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto err; 2003384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2004384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2005384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso iter = nft_table_list_iter_create(list); 2006384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (iter == NULL) { 2007384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("cannot allocate rule list iterator\n"); 2008384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 0; 2009384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2010384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2011384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso t = nft_table_list_iter_next(iter); 2012384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso while (t != NULL) { 2013384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *tablename = 2014384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_table_attr_get(t, NFT_TABLE_ATTR_NAME); 2015384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2016384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso func(h, tablename, counters); 2017384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2018384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso t = nft_table_list_iter_next(iter); 2019384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2020384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2021384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_table_list_free(list); 2022384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2023384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr: 2024384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* the core expects 1 for success and 0 for error */ 2025384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return ret == 0 ? 1 : 0; 2026384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 2027384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 20280aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusoint nft_table_purge_chains(struct nft_handle *h, const char *this_table, 20290aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso struct nft_chain_list *chain_list) 20300aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso{ 20310aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso struct nft_chain_list_iter *iter; 20320aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso struct nft_chain *chain_obj; 20330aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso 20340aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso iter = nft_chain_list_iter_create(chain_list); 20350aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso if (iter == NULL) { 20360aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso DEBUGP("cannot allocate rule list iterator\n"); 20370aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso return 0; 20380aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso } 20390aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso 20400aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso chain_obj = nft_chain_list_iter_next(iter); 20410aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso while (chain_obj != NULL) { 20420aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso const char *table = 20430aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso nft_chain_attr_get_str(chain_obj, NFT_CHAIN_ATTR_TABLE); 20440aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso 20450aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso if (strcmp(this_table, table) != 0) 20460aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso goto next; 20470aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso 20480aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso if (nft_chain_builtin(chain_obj)) 20490aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso goto next; 20500aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso 20510aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso if ( __nft_chain_del(h, chain_obj) < 0) { 20520aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso if (errno != EBUSY) 20530aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso return -1; 20540aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso } 20550aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayusonext: 20560aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso chain_obj = nft_chain_list_iter_next(iter); 20570aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso } 20580aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso nft_chain_list_iter_destroy(iter); 20590aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso 20600aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso return 0; 20610aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso} 20620aad20f3979e3b6becd40e4ed5bba8d09d90706ePablo Neira Ayuso 2063384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic inline int 2064384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusomatch_different(const struct xt_entry_match *a, 2065384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const unsigned char *a_elems, 2066384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const unsigned char *b_elems, 2067384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso unsigned char **maskptr) 2068384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 2069384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const struct xt_entry_match *b; 2070384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso unsigned int i; 2071384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2072384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* Offset of b is the same as a. */ 2073384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso b = (void *)b_elems + ((unsigned char *)a - a_elems); 2074384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2075384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (a->u.match_size != b->u.match_size) 2076384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 1; 2077384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2078384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(a->u.user.name, b->u.user.name) != 0) 2079384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 1; 2080384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2081384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso *maskptr += XT_ALIGN(sizeof(*a)); 2082384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2083384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso for (i = 0; i < a->u.match_size - XT_ALIGN(sizeof(*a)); i++) 2084384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0) 2085384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 1; 2086384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso *maskptr += i; 2087384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 0; 2088384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 2089384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2090384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool 20910391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykais_same(int family, const struct iptables_command_state *a, 20920391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka const struct iptables_command_state *b) 2093384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 2094384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso unsigned int i; 20950391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka const char *a_outiface, *a_iniface; 20960391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka unsigned const char *a_iniface_mask, *a_outiface_mask; 20970391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka const char *b_outiface, *b_iniface; 20980391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka unsigned const char *b_iniface_mask, *b_outiface_mask; 2099384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2100384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* Always compare head structures: ignore mask here. */ 21010391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka switch (family) { 21020391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka case AF_INET: 21030391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (a->fw.ip.src.s_addr != b->fw.ip.src.s_addr 21040391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka || a->fw.ip.dst.s_addr != b->fw.ip.dst.s_addr 21050391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka || a->fw.ip.smsk.s_addr != b->fw.ip.smsk.s_addr 21060391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka || a->fw.ip.dmsk.s_addr != b->fw.ip.dmsk.s_addr 21070391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka || a->fw.ip.proto != b->fw.ip.proto 21080391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka || a->fw.ip.flags != b->fw.ip.flags 21090391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka || a->fw.ip.invflags != b->fw.ip.invflags) { 21100391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka DEBUGP("different src/dst/proto/flags/invflags\n"); 21110391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka return false; 21120391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka } 21130391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 21140391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka a_iniface_mask = a->fw.ip.iniface_mask; 21150391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka a_iniface = a->fw.ip.iniface; 21160391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka a_outiface_mask = a->fw.ip.outiface_mask; 21170391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka a_outiface = a->fw.ip.outiface; 21180391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 21190391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka b_iniface_mask = b->fw.ip.iniface_mask; 21200391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka b_iniface = b->fw.ip.iniface; 21210391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka b_outiface_mask = b->fw.ip.outiface_mask; 21220391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka b_outiface = b->fw.ip.outiface; 21230391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 21240391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka break; 21250391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka case AF_INET6: 21260391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (memcmp(a->fw6.ipv6.src.s6_addr, 21270391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka b->fw6.ipv6.src.s6_addr, 21280391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka sizeof(struct in6_addr)) != 0 || 21290391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka memcmp(a->fw6.ipv6.dst.s6_addr, 21300391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka b->fw6.ipv6.dst.s6_addr, 21310391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka sizeof(struct in6_addr)) != 0 || 21320391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka a->fw6.ipv6.proto != b->fw6.ipv6.proto || 21330391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka a->fw6.ipv6.flags != b->fw6.ipv6.flags || 21340391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka a->fw6.ipv6.invflags != b->fw6.ipv6.invflags) { 21350391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka DEBUGP("different src/dst/proto/flags/invflags\n"); 21360391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka return false; 21370391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka } 21380391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 21390391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka a_iniface_mask = a->fw6.ipv6.iniface_mask; 21400391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka a_iniface = a->fw6.ipv6.iniface; 21410391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka a_outiface_mask = a->fw6.ipv6.outiface_mask; 21420391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka a_outiface = a->fw6.ipv6.outiface; 21430391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 21440391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka b_iniface_mask = b->fw6.ipv6.iniface_mask; 21450391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka b_iniface = b->fw6.ipv6.iniface; 21460391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka b_outiface_mask = b->fw6.ipv6.outiface_mask; 21470391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka b_outiface = b->fw6.ipv6.outiface; 21480391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 21490391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka break; 21500391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka default: 2151384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return false; 2152384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2153384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2154384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso for (i = 0; i < IFNAMSIZ; i++) { 21550391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (a_iniface_mask[i] != b_iniface_mask[i]) { 2156384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("different iniface mask %x, %x (%d)\n", 21570391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka a_iniface_mask[i] & 0xff, b_iniface_mask[i] & 0xff, i); 2158384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return false; 2159384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 21600391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if ((a_iniface[i] & a_iniface_mask[i]) 21610391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka != (b_iniface[i] & b_iniface_mask[i])) { 2162384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("different iniface\n"); 2163384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return false; 2164384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 21650391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (a_outiface_mask[i] != b_outiface_mask[i]) { 2166384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("different outiface mask\n"); 2167384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return false; 2168384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 21690391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if ((a_outiface[i] & a_outiface_mask[i]) 21700391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka != (b_outiface[i] & b_outiface_mask[i])) { 2171384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("different outiface\n"); 2172384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return false; 2173384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2174384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2175384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2176384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return true; 2177384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 2178384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2179384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void 2180384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_parse_meta(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter, 21810391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka int family, struct iptables_command_state *cs) 2182384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 2183384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso uint8_t key = nft_rule_expr_get_u8(e, NFT_EXPR_META_KEY); 2184384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso uint32_t value; 2185384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *name; 2186384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const void *ifname; 21870391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka char *iniface, *outiface; 21880391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka unsigned char *iniface_mask, *outiface_mask; 2189384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso size_t len; 21900391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka uint8_t *invflags; 2191384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2192384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso e = nft_rule_expr_iter_next(iter); 2193384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (e == NULL) 2194384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 2195384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2196384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso name = nft_rule_expr_get_str(e, NFT_RULE_EXPR_ATTR_NAME); 2197384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(name, "cmp") != 0) { 2198384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("skipping no cmp after meta\n"); 2199384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 2200384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2201384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 22020391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka switch (family) { 22030391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka case AF_INET: 22040391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka iniface = cs->fw.ip.iniface; 22050391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka outiface = cs->fw.ip.outiface; 22060391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka iniface_mask = cs->fw.ip.iniface_mask; 22070391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka outiface_mask = cs->fw.ip.outiface_mask; 22080391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka invflags = &cs->fw.ip.invflags; 22090391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka break; 22100391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka case AF_INET6: 22110391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka iniface = cs->fw6.ipv6.iniface; 22120391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka outiface = cs->fw6.ipv6.outiface; 22130391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka iniface_mask = cs->fw6.ipv6.iniface_mask; 22140391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka outiface_mask = cs->fw6.ipv6.outiface_mask; 22150391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka invflags = &cs->fw6.ipv6.invflags; 22160391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka break; 22170391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka default: 22180391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka return; 22190391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka } 22200391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 2221384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso switch(key) { 2222384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_META_IIF: 2223384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso value = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_DATA); 2224384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP) == NFT_CMP_NEQ) 22250391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka *invflags |= IPT_INV_VIA_IN; 2226384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 22270391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if_indextoname(value, iniface); 2228384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 22290391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka memset(iniface_mask, 0xff, strlen(iniface)+1); 2230384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 2231384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_META_OIF: 2232384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso value = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_DATA); 2233384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP) == NFT_CMP_NEQ) 22340391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka *invflags |= IPT_INV_VIA_OUT; 2235384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 22360391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if_indextoname(value, outiface); 2237384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 22380391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka memset(outiface_mask, 0xff, strlen(outiface)+1); 2239384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 2240384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_META_IIFNAME: 2241384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ifname = nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len); 2242384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP) == NFT_CMP_NEQ) 22430391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka *invflags |= IPT_INV_VIA_IN; 2244384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 22450391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka memcpy(iniface, ifname, len); 22460391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka iniface[len] = '\0'; 2247384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2248384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* If zero, then this is an interface mask */ 22490391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (if_nametoindex(iniface) == 0) { 22500391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka iniface[len] = '+'; 22510391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka iniface[len+1] = '\0'; 2252384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2253384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 22540391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka memset(iniface_mask, 0xff, len); 2255384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 2256384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_META_OIFNAME: 2257384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ifname = nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len); 2258384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP) == NFT_CMP_NEQ) 22590391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka *invflags |= IPT_INV_VIA_OUT; 2260384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 22610391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka memcpy(outiface, ifname, len); 22620391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka outiface[len] = '\0'; 2263384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2264384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* If zero, then this is an interface mask */ 22650391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (if_nametoindex(outiface) == 0) { 22660391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka outiface[len] = '+'; 22670391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka outiface[len+1] = '\0'; 2268384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2269384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 22700391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka memset(outiface_mask, 0xff, len); 2271384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 2272384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso default: 2273384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("unknown meta key %d\n", key); 2274384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 2275384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2276384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 2277384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2278384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void 22790391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykanft_parse_payload_ipv4(uint32_t offset, struct nft_rule_expr_iter *iter, 22800391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka struct iptables_command_state *cs) 2281384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 2282384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso switch(offset) { 2283384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct in_addr addr; 2284384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso uint8_t proto; 22850391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka bool inv; 2286384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2287384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case offsetof(struct iphdr, saddr): 2288384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso get_cmp_data(iter, &addr, sizeof(addr), &inv); 2289384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso cs->fw.ip.src.s_addr = addr.s_addr; 2290384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso cs->fw.ip.smsk.s_addr = 0xffffffff; 2291384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (inv) 2292384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso cs->fw.ip.invflags |= IPT_INV_SRCIP; 2293384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 2294384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case offsetof(struct iphdr, daddr): 2295384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso get_cmp_data(iter, &addr, sizeof(addr), &inv); 2296384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso cs->fw.ip.dst.s_addr = addr.s_addr; 2297384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso cs->fw.ip.dmsk.s_addr = 0xffffffff; 2298384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (inv) 2299384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso cs->fw.ip.invflags |= IPT_INV_DSTIP; 2300384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 2301384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case offsetof(struct iphdr, protocol): 2302384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso get_cmp_data(iter, &proto, sizeof(proto), &inv); 2303384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso cs->fw.ip.proto = proto; 2304384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (inv) 2305384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso cs->fw.ip.invflags |= IPT_INV_PROTO; 2306384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 23072f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso case offsetof(struct iphdr, frag_off): 23082f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso cs->fw.ip.flags |= IPT_F_FRAG; 23092f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso get_frag(iter, &inv); 23102f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso if (inv) 23112f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso cs->fw.ip.invflags |= IPT_INV_FRAG; 23122f1fbab67157624c0171e55bde08e7e5c8d99fffPablo Neira Ayuso break; 2313384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso default: 2314384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("unknown payload offset %d\n", offset); 2315384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 2316384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2317384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 2318384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2319384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void 23200391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykanft_parse_payload_ipv6(uint32_t offset, struct nft_rule_expr_iter *iter, 23210391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka struct iptables_command_state *cs) 23220391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka{ 23230391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka switch (offset) { 23240391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka struct in6_addr addr; 23250391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka uint8_t proto; 23260391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka bool inv; 23270391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 23280391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka case offsetof(struct ip6_hdr, ip6_src): 23290391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka get_cmp_data(iter, &addr, sizeof(addr), &inv); 23300391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka memcpy(cs->fw6.ipv6.src.s6_addr, &addr, sizeof(addr)); 23310391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (inv) 23320391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka cs->fw6.ipv6.invflags |= IPT_INV_SRCIP; 23330391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka break; 23340391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka case offsetof(struct ip6_hdr, ip6_dst): 23350391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka get_cmp_data(iter, &addr, sizeof(addr), &inv); 23360391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka memcpy(cs->fw6.ipv6.dst.s6_addr, &addr, sizeof(addr)); 23370391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (inv) 23380391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka cs->fw6.ipv6.invflags |= IPT_INV_DSTIP; 23390391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka break; 23400391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka case offsetof(struct ip6_hdr, ip6_nxt): 23410391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka get_cmp_data(iter, &proto, sizeof(proto), &inv); 23420391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka cs->fw6.ipv6.proto = proto; 23430391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (inv) 23440391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka cs->fw6.ipv6.invflags |= IPT_INV_PROTO; 23450391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka default: 23460391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka DEBUGP("unknown payload offset %d\n", offset); 23470391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka break; 23480391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka } 23490391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka} 23500391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 23510391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykastatic void 23520391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykanft_parse_payload(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter, 23530391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka int family, struct iptables_command_state *cs) 23540391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka{ 23550391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka uint32_t offset; 23560391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 23570391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka offset = nft_rule_expr_get_u32(e, NFT_EXPR_PAYLOAD_OFFSET); 23580391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 23590391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka switch (family) { 23600391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka case AF_INET: 23610391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka nft_parse_payload_ipv4(offset, iter, cs); 23620391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka break; 23630391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka case AF_INET6: 23640391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka nft_parse_payload_ipv6(offset, iter, cs); 23650391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka break; 23660391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka } 23670391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka} 23680391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 23690391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykastatic void 2370384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_parse_counter(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter, 2371384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct xt_counters *counters) 2372384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 2373384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso counters->pcnt = nft_rule_expr_get_u64(e, NFT_EXPR_CTR_PACKETS); 2374384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso counters->bcnt = nft_rule_expr_get_u64(e, NFT_EXPR_CTR_BYTES); 2375384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 2376384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2377384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void 2378384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_parse_immediate(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter, 23790391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka int family, struct iptables_command_state *cs) 2380384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 2381384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int verdict = nft_rule_expr_get_u32(e, NFT_EXPR_IMM_VERDICT); 2382384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *chain = nft_rule_expr_get_str(e, NFT_EXPR_IMM_CHAIN); 2383384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2384384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* Standard target? */ 2385384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso switch(verdict) { 2386384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NF_ACCEPT: 2387384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso cs->jumpto = "ACCEPT"; 2388384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 2389384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NF_DROP: 2390384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso cs->jumpto = "DROP"; 2391384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 2392384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_RETURN: 2393384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso cs->jumpto = "RETURN"; 2394384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 2395384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_GOTO: 23960391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (family == AF_INET) 23970391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka cs->fw.ip.flags |= IPT_F_GOTO; 23980391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka else 23990391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka cs->fw6.ipv6.flags |= IPT_F_GOTO; 2400384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_JUMP: 2401384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso cs->jumpto = chain; 2402384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 2403384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2404384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 2405384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2406384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void 2407384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_rule_to_iptables_command_state(struct nft_rule *r, 2408384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct iptables_command_state *cs) 2409384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 2410384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_expr_iter *iter; 2411384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_expr *expr; 24120391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka int family = nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY); 2413384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2414384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso iter = nft_rule_expr_iter_create(r); 2415384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (iter == NULL) 2416384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 2417384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2418384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso expr = nft_rule_expr_iter_next(iter); 2419384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso while (expr != NULL) { 2420384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *name = 2421384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME); 2422384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2423384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(name, "counter") == 0) { 2424384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_parse_counter(expr, iter, &cs->counters); 2425384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } else if (strcmp(name, "payload") == 0) { 24260391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka nft_parse_payload(expr, iter, family, cs); 2427384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } else if (strcmp(name, "meta") == 0) { 24280391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka nft_parse_meta(expr, iter, family, cs); 2429384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } else if (strcmp(name, "immediate") == 0) { 24300391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka nft_parse_immediate(expr, iter, family, cs); 2431384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2432384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2433384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso expr = nft_rule_expr_iter_next(iter); 2434384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2435384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2436384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_iter_destroy(iter); 2437384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 2438384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2439384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int matches_howmany(struct xtables_rule_match *matches) 2440384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 2441384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct xtables_rule_match *matchp; 2442384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int matches_ctr = 0; 2443384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2444384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso for (matchp = matches; matchp; matchp = matchp->next) 2445384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso matches_ctr++; 2446384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2447384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return matches_ctr; 2448384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 2449384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2450384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool 2451384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__find_match(struct nft_rule_expr *expr, struct xtables_rule_match *matches) 2452384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 2453384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *matchname = nft_rule_expr_get_str(expr, NFT_EXPR_MT_NAME); 2454384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* Netlink aligns this match info, don't trust this length variable */ 2455384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *data = nft_rule_expr_get_str(expr, NFT_EXPR_MT_INFO); 2456384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct xtables_rule_match *matchp; 2457384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso bool found = false; 2458384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2459384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso for (matchp = matches; matchp; matchp = matchp->next) { 2460384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct xt_entry_match *m = matchp->match->m; 2461384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2462384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(m->u.user.name, matchname) != 0) { 2463384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("mismatching match name\n"); 2464384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso continue; 2465384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2466384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2467384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (memcmp(data, m->data, m->u.user.match_size - sizeof(*m)) != 0) { 2468384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("mismatch match data\n"); 2469384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso continue; 2470384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2471384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso found = true; 2472384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 2473384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2474384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2475384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return found; 2476384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 2477384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2478384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool find_matches(struct xtables_rule_match *matches, struct nft_rule *r) 2479384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 2480384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_expr_iter *iter; 2481384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_expr *expr; 2482384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int kernel_matches = 0; 2483384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2484384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso iter = nft_rule_expr_iter_create(r); 2485384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (iter == NULL) { 2486384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("cannot allocate rule list iterator\n"); 2487384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return false; 2488384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2489384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2490384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso expr = nft_rule_expr_iter_next(iter); 2491384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso while (expr != NULL) { 2492384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *name = 2493384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME); 2494384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2495384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(name, "match") == 0) { 2496384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (!__find_match(expr, matches)) 2497384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return false; 2498384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2499384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso kernel_matches++; 2500384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2501384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso expr = nft_rule_expr_iter_next(iter); 2502384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2503384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_iter_destroy(iter); 2504384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2505384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* same number of matches? */ 2506384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (matches_howmany(matches) != kernel_matches) 2507384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return false; 2508384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2509384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return true; 2510384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 2511384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2512384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool __find_target(struct nft_rule_expr *expr, struct xt_entry_target *t) 2513384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 2514384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso size_t len; 2515384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *tgname = nft_rule_expr_get_str(expr, NFT_EXPR_TG_NAME); 2516384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* Netlink aligns this target info, don't trust this length variable */ 2517384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *data = nft_rule_expr_get(expr, NFT_EXPR_TG_INFO, &len); 2518384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2519384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(t->u.user.name, tgname) != 0) { 2520384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("mismatching target name\n"); 2521384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return false; 2522384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2523384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2524384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (memcmp(data, t->data, t->u.user.target_size - sizeof(*t)) != 0) 2525384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return false; 2526384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2527384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return true; 2528384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 2529384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2530384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int targets_howmany(struct xtables_target *target) 2531384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 2532384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return target != NULL ? 1 : 0; 2533384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 2534384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2535384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool 2536384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusofind_target(struct xtables_target *target, struct nft_rule *r) 2537384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 2538384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_expr_iter *iter; 2539384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_expr *expr; 2540384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int kernel_targets = 0; 2541384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2542384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* Special case: we use native immediate expressions to emulated 2543384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso * standard targets. Also, we don't want to crash with no targets. 2544384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso */ 2545384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (target == NULL || strcmp(target->name, "standard") == 0) 2546384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return true; 2547384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2548384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso iter = nft_rule_expr_iter_create(r); 2549384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (iter == NULL) { 2550384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("cannot allocate rule list iterator\n"); 2551384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return false; 2552384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2553384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2554384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso expr = nft_rule_expr_iter_next(iter); 2555384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso while (expr != NULL) { 2556384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *name = 2557384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME); 2558384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2559384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(name, "target") == 0) { 2560384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* we may support several targets in the future */ 2561384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (!__find_target(expr, target->t)) 2562384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return false; 2563384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2564384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso kernel_targets++; 2565384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2566384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso expr = nft_rule_expr_iter_next(iter); 2567384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2568384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_iter_destroy(iter); 2569384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2570384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* same number of targets? */ 2571384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (targets_howmany(target) != kernel_targets) { 2572384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("kernel targets is %d but we passed %d\n", 2573384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso kernel_targets, targets_howmany(target)); 2574384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return false; 2575384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2576384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2577384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return true; 2578384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 2579384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2580384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic bool 2581384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusofind_immediate(struct nft_rule *r, const char *jumpto) 2582384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 2583384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_expr_iter *iter; 2584384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_expr *expr; 2585384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2586384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso iter = nft_rule_expr_iter_create(r); 2587384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (iter == NULL) { 2588384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("cannot allocate rule list iterator\n"); 2589384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return false; 2590384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2591384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2592384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso expr = nft_rule_expr_iter_next(iter); 2593384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso while (expr != NULL) { 2594384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *name = 2595384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME); 2596384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2597384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(name, "immediate") == 0) { 2598384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int verdict = nft_rule_expr_get_u32(expr, NFT_EXPR_IMM_VERDICT); 2599384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *verdict_name = NULL; 2600384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2601384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* No target specified but immediate shows up, this 2602384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso * is not the rule we are looking for. 2603384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso */ 2604384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strlen(jumpto) == 0) 2605384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return false; 2606384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2607384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso switch(verdict) { 2608384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NF_ACCEPT: 2609384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso verdict_name = "ACCEPT"; 2610384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 2611384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NF_DROP: 2612384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso verdict_name = "DROP"; 2613384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 2614384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_RETURN: 2615384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso verdict_name = "RETURN"; 2616384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 2617384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2618384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2619384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* Standard target? */ 2620384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (verdict_name && strcmp(jumpto, verdict_name) != 0) 2621384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return false; 2622384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2623384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso expr = nft_rule_expr_iter_next(iter); 2624384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2625384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_iter_destroy(iter); 2626384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2627384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return true; 2628384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 2629384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2630384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void 2631384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__nft_rule_del(struct nft_handle *h, struct nft_rule *r) 2632384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 2633384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso char buf[MNL_SOCKET_BUFFER_SIZE]; 2634384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nlmsghdr *nlh; 2635384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int ret; 2636384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 26370391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_DELRULE, h->family, 2638384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso NLM_F_ACK, h->seq); 2639384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_nlmsg_build_payload(nlh, r); 2640384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2641384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_print_debug(r, nlh); 2642384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2643384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ret = mnl_talk(h, nlh, NULL, NULL); 2644384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (ret < 0) 2645384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso perror("mnl_talk:nft_rule_del"); 2646384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 2647384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 26483aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayusostatic struct nft_rule_list *nft_rule_list_create(struct nft_handle *h) 2649384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 2650384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_list *list; 2651384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2652384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso list = nft_rule_list_get(h); 2653384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (list == NULL) { 2654384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("cannot retrieve rule list from kernel\n"); 26553aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso return NULL; 2656384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2657384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 26583aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso return list; 26593aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso} 26603aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso 26613aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayusostatic void nft_rule_list_destroy(struct nft_rule_list *list) 26623aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso{ 26633aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso nft_rule_list_free(list); 26643aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso} 26653aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso 26663aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayusostatic struct nft_rule * 26673aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayusonft_rule_find(struct nft_rule_list *list, const char *chain, const char *table, 26683aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso struct iptables_command_state *cs, int rulenum) 26693aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso{ 26703aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso struct nft_rule *r; 26713aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso struct nft_rule_list_iter *iter; 26723aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso int rule_ctr = 0; 26733aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso bool found = false; 26743aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso 2675384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso iter = nft_rule_list_iter_create(list); 2676384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (iter == NULL) { 2677384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("cannot allocate rule list iterator\n"); 2678384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 0; 2679384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2680384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2681384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso r = nft_rule_list_iter_next(iter); 2682384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso while (r != NULL) { 2683384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *rule_table = 2684384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_attr_get_str(r, NFT_RULE_ATTR_TABLE); 2685384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *rule_chain = 2686384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_attr_get_str(r, NFT_RULE_ATTR_CHAIN); 2687384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct iptables_command_state this = {}; 2688384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2689384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(table, rule_table) != 0 || 2690384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso strcmp(chain, rule_chain) != 0) { 2691384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("different chain / table\n"); 2692384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto next; 2693384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2694384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2695384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (rulenum >= 0) { 2696384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* Delete by rule number case */ 26974acee778f5712c4cc574e328183a3252ad81a802Tomasz Bursztyka if (rule_ctr != rulenum) 2698384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto next; 26994acee778f5712c4cc574e328183a3252ad81a802Tomasz Bursztyka found = true; 27004acee778f5712c4cc574e328183a3252ad81a802Tomasz Bursztyka break; 2701384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } else { 2702384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* Delete by matching rule case */ 2703384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("comparing with... "); 2704384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#ifdef DEBUG_DEL 2705384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_print_save(r, 0); 2706384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif 2707384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2708384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_to_iptables_command_state(r, &this); 2709384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 27100391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (!is_same(nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY), cs, &this)) 2711384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto next; 2712384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2713384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (!find_matches(cs->matches, r)) { 2714384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("matches not found\n"); 2715384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto next; 2716384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2717384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2718384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (!find_target(cs->target, r)) { 2719384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("target not found\n"); 2720384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto next; 2721384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2722384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2723384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (!find_immediate(r, cs->jumpto)) { 2724384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("immediate not found\n"); 2725384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto next; 2726384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2727384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2728384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso found = true; 2729384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 2730384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2731384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext: 27324acee778f5712c4cc574e328183a3252ad81a802Tomasz Bursztyka rule_ctr++; 2733384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso r = nft_rule_list_iter_next(iter); 2734384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2735384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2736384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_list_iter_destroy(iter); 2737384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 27383aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso return found ? r : NULL; 2739384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 2740384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2741384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_check(struct nft_handle *h, const char *chain, 2742384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *table, struct iptables_command_state *e, 2743384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso bool verbose) 2744384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 27453aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso struct nft_rule_list *list; 27463aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso int ret; 27473aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso 2748384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_fn = nft_rule_check; 2749384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 27503aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso list = nft_rule_list_create(h); 27513aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso if (list == NULL) { 27523aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso DEBUGP("cannot allocate rule list\n"); 27533aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso return 0; 27543aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso } 27553aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso 27563aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso ret = nft_rule_find(list, chain, table, e, -1) ? 1 : 0; 27573aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso if (ret == 0) 27583aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso errno = ENOENT; 27593aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso 27603aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso nft_rule_list_destroy(list); 27613aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso 27623aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso return ret; 2763384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 2764384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2765384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_delete(struct nft_handle *h, const char *chain, 27663aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso const char *table, struct iptables_command_state *cs, 2767384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso bool verbose) 2768384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 27693aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso int ret = 0; 27703aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso struct nft_rule *r; 27713aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso struct nft_rule_list *list; 27723aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso 2773384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_fn = nft_rule_delete; 2774384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 27753aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso list = nft_rule_list_create(h); 27763aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso if (list == NULL) { 27773aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso DEBUGP("cannot allocate rule list\n"); 27783aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso return 0; 27793aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso } 27803aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso 27813aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso r = nft_rule_find(list, chain, table, cs, -1); 27823aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso if (r != NULL) { 27833aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso ret = 1; 27843aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso 27859e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso if (h->commit) { 27869e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS, 27879e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso NFT_RULE_F_COMMIT); 27889e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso } 27893aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso DEBUGP("deleting rule\n"); 27903aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso __nft_rule_del(h, r); 27913aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso } else 27923aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso errno = ENOENT; 27933aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso 27943aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso nft_rule_list_destroy(list); 27953aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso 27963aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso return ret; 2797384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 2798384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2799384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_delete_num(struct nft_handle *h, const char *chain, 28003aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso const char *table, int rulenum, bool verbose) 2801384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 28023aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso int ret = 0; 28033aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso struct nft_rule *r; 28043aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso struct nft_rule_list *list; 28053aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso 2806384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_fn = nft_rule_delete_num; 2807384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 28083aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso list = nft_rule_list_create(h); 28093aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso if (list == NULL) { 28103aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso DEBUGP("cannot allocate rule list\n"); 28113aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso return 0; 28123aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso } 28133aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso 28143aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso r = nft_rule_find(list, chain, table, NULL, rulenum); 28153aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso if (r != NULL) { 28163aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso ret = 1; 28173aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso 28189e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso if (h->commit) { 28199e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS, 28209e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso NFT_RULE_F_COMMIT); 28219e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso } 28223aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso DEBUGP("deleting rule by number %d\n", rulenum); 28233aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso __nft_rule_del(h, r); 28243aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso } else 28253aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso errno = ENOENT; 28263aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso 28273aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso nft_rule_list_destroy(list); 28283aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso 28293aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso return ret; 2830384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 2831384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2832384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_replace(struct nft_handle *h, const char *chain, 2833384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *table, struct iptables_command_state *cs, 2834384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int rulenum, bool verbose) 2835384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 28363aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso int ret = 0; 28373aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso struct nft_rule *r; 28383aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso struct nft_rule_list *list; 2839384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2840384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_fn = nft_rule_replace; 2841384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 28423aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso list = nft_rule_list_create(h); 28433aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso if (list == NULL) { 28443aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso DEBUGP("cannot allocate rule list\n"); 28453aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso return 0; 28463aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso } 28473aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso 28483aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso r = nft_rule_find(list, chain, table, cs, rulenum); 28493aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso if (r != NULL) { 28501298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso DEBUGP("replacing rule with handle=%llu\n", 28511298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso (unsigned long long) 28521298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso nft_rule_attr_get_u64(r, NFT_RULE_ATTR_HANDLE)); 2853384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 28549e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso if (h->commit) { 28559e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS, 28569e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso NFT_RULE_F_COMMIT); 28579e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso } 28583aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso ret = nft_rule_add(h, chain, table, cs, true, 28591298a1014bc14c45de50cc242779dfa382c456c9Pablo Neira Ayuso nft_rule_attr_get_u64(r, NFT_RULE_ATTR_HANDLE), 28603aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso verbose); 28613aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso } else 28623aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso errno = ENOENT; 28633aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso 28643aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso nft_rule_list_destroy(list); 28653aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso 28663aea037f359795edeb69426e2dde63c59540ba5fPablo Neira Ayuso return ret; 2867384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 2868384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2869384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso/* 2870384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso * iptables print output emulation 2871384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso */ 2872384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2873384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_NUMERIC 0x0001 2874384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_NOCOUNTS 0x0002 2875384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_KILOMEGAGIGA 0x0004 2876384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_OPTIONS 0x0008 2877384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_NOTABLE 0x0010 2878384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_NOTARGET 0x0020 2879384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_VIA 0x0040 2880384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_NONEWLINE 0x0080 2881384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_LINENUMBERS 0x0100 2882384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2883384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT_PRINT_RULE (FMT_NOCOUNTS | FMT_OPTIONS | FMT_VIA \ 2884384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso | FMT_NUMERIC | FMT_NOTABLE) 2885384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab)) 2886384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2887384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void 2888384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoprint_num(uint64_t number, unsigned int format) 2889384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 2890384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (format & FMT_KILOMEGAGIGA) { 2891384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (number > 99999) { 2892384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso number = (number + 500) / 1000; 2893384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (number > 9999) { 2894384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso number = (number + 500) / 1000; 2895384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (number > 9999) { 2896384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso number = (number + 500) / 1000; 2897384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (number > 9999) { 2898384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso number = (number + 500) / 1000; 2899384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(FMT("%4lluT ","%lluT "), (unsigned long long)number); 2900384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2901384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso else printf(FMT("%4lluG ","%lluG "), (unsigned long long)number); 2902384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2903384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso else printf(FMT("%4lluM ","%lluM "), (unsigned long long)number); 2904384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } else 2905384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(FMT("%4lluK ","%lluK "), (unsigned long long)number); 2906384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } else 2907384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(FMT("%5llu ","%llu "), (unsigned long long)number); 2908384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } else 2909384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(FMT("%8llu ","%llu "), (unsigned long long)number); 2910384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 2911384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2912384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void 2913384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoprint_header(unsigned int format, const char *chain, const char *pol, 2914384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const struct xt_counters *counters, bool basechain, uint32_t refs) 2915384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 2916384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("Chain %s", chain); 2917384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (basechain) { 2918384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(" (policy %s", pol); 2919384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (!(format & FMT_NOCOUNTS)) { 2920384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso fputc(' ', stdout); 2921384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso print_num(counters->pcnt, (format|FMT_NOTABLE)); 2922384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso fputs("packets, ", stdout); 2923384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso print_num(counters->bcnt, (format|FMT_NOTABLE)); 2924384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso fputs("bytes", stdout); 2925384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2926384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(")\n"); 2927384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } else { 2928384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(" (%u references)\n", refs); 2929384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2930384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2931384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (format & FMT_LINENUMBERS) 2932384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(FMT("%-4s ", "%s "), "num"); 2933384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (!(format & FMT_NOCOUNTS)) { 2934384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (format & FMT_KILOMEGAGIGA) { 2935384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(FMT("%5s ","%s "), "pkts"); 2936384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(FMT("%5s ","%s "), "bytes"); 2937384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } else { 2938384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(FMT("%8s ","%s "), "pkts"); 2939384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(FMT("%10s ","%s "), "bytes"); 2940384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2941384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2942384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (!(format & FMT_NOTARGET)) 2943384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(FMT("%-9s ","%s "), "target"); 2944384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso fputs(" prot ", stdout); 2945384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (format & FMT_OPTIONS) 2946384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso fputs("opt", stdout); 2947384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (format & FMT_VIA) { 2948384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(FMT(" %-6s ","%s "), "in"); 2949384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(FMT("%-6s ","%s "), "out"); 2950384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2951384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(FMT(" %-19s ","%s "), "source"); 2952384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(FMT(" %-19s "," %s "), "destination"); 2953384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("\n"); 2954384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 2955384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2956384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void 2957384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoprint_match(struct nft_rule_expr *expr, int numeric) 2958384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 2959384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso size_t len; 2960384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *match_name = nft_rule_expr_get_str(expr, NFT_EXPR_MT_NAME); 2961384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const void *match_info = nft_rule_expr_get(expr, NFT_EXPR_MT_INFO, &len); 2962384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const struct xtables_match *match = 2963384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso xtables_find_match(match_name, XTF_TRY_LOAD, NULL); 2964384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct xt_entry_match *m = 2965384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso calloc(1, sizeof(struct xt_entry_match) + len); 2966384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2967384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* emulate struct xt_entry_match since ->print needs it */ 2968384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso memcpy((void *)&m->data, match_info, len); 2969384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2970384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (match) { 2971384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (match->print) 2972384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* FIXME missing first parameter */ 2973384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso match->print(NULL, m, numeric); 2974384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso else 2975384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("%s ", match_name); 2976384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } else { 2977384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (match_name[0]) 2978384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("UNKNOWN match `%s' ", match_name); 2979384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 2980384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2981384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso free(m); 2982384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 2983384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 2984384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void 29850391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykaprint_ipv4_addr(const struct iptables_command_state *cs, unsigned int format) 29860391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka{ 29870391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka char buf[BUFSIZ]; 29880391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 29890391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka fputc(cs->fw.ip.invflags & IPT_INV_SRCIP ? '!' : ' ', stdout); 29900391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (cs->fw.ip.smsk.s_addr == 0L && !(format & FMT_NUMERIC)) 29910391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka printf(FMT("%-19s ","%s "), "anywhere"); 29920391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka else { 29930391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (format & FMT_NUMERIC) 29940391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka strcpy(buf, xtables_ipaddr_to_numeric(&cs->fw.ip.src)); 29950391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka else 29960391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka strcpy(buf, xtables_ipaddr_to_anyname(&cs->fw.ip.src)); 29970391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka strcat(buf, xtables_ipmask_to_numeric(&cs->fw.ip.smsk)); 29980391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka printf(FMT("%-19s ","%s "), buf); 29990391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka } 30000391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 30010391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka fputc(cs->fw.ip.invflags & IPT_INV_DSTIP ? '!' : ' ', stdout); 30020391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (cs->fw.ip.dmsk.s_addr == 0L && !(format & FMT_NUMERIC)) 30030391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka printf(FMT("%-19s ","-> %s"), "anywhere"); 30040391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka else { 30050391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (format & FMT_NUMERIC) 30060391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka strcpy(buf, xtables_ipaddr_to_numeric(&cs->fw.ip.dst)); 30070391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka else 30080391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka strcpy(buf, xtables_ipaddr_to_anyname(&cs->fw.ip.dst)); 30090391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka strcat(buf, xtables_ipmask_to_numeric(&cs->fw.ip.dmsk)); 30100391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka printf(FMT("%-19s ","-> %s"), buf); 30110391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka } 30120391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka} 30130391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 30140391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykastatic void 30150391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykaprint_ipv6_addr(const struct iptables_command_state *cs, unsigned int format) 30160391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka{ 30170391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka char buf[BUFSIZ]; 30180391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 30190391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka fputc(cs->fw6.ipv6.invflags & IPT_INV_SRCIP ? '!' : ' ', stdout); 30200391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.src) 30210391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka && !(format & FMT_NUMERIC)) 30220391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka printf(FMT("%-19s ","%s "), "anywhere"); 30230391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka else { 30240391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (format & FMT_NUMERIC) 30250391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka strcpy(buf, 30260391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka xtables_ip6addr_to_numeric(&cs->fw6.ipv6.src)); 30270391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka else 30280391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka strcpy(buf, 30290391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka xtables_ip6addr_to_anyname(&cs->fw6.ipv6.src)); 30300391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka strcat(buf, xtables_ip6mask_to_numeric(&cs->fw6.ipv6.smsk)); 30310391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka printf(FMT("%-19s ","%s "), buf); 30320391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka } 30330391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 30340391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 30350391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka fputc(cs->fw6.ipv6.invflags & IPT_INV_DSTIP ? '!' : ' ', stdout); 30360391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.dst) 30370391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka && !(format & FMT_NUMERIC)) 30380391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka printf(FMT("%-19s ","-> %s"), "anywhere"); 30390391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka else { 30400391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (format & FMT_NUMERIC) 30410391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka strcpy(buf, 30420391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka xtables_ip6addr_to_numeric(&cs->fw6.ipv6.dst)); 30430391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka else 30440391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka strcpy(buf, 30450391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka xtables_ip6addr_to_anyname(&cs->fw6.ipv6.dst)); 30460391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka strcat(buf, xtables_ip6mask_to_numeric(&cs->fw6.ipv6.dmsk)); 30470391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka printf(FMT("%-19s ","-> %s"), buf); 30480391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka } 30490391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka} 30500391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 30510391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztykastatic void 3052384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoprint_firewall(const struct iptables_command_state *cs, struct nft_rule *r, 3053384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso unsigned int num, unsigned int format) 3054384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 3055384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const struct xtables_target *target = NULL; 3056384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *targname = NULL; 3057384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const void *targinfo = NULL; 30580391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka int family; 30590391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka uint8_t flags = 0; 30600391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka uint8_t invflags = 0; 30610391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka uint8_t proto = 0; 30620391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka const char *iniface = NULL, *outiface = NULL; 3063384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_expr_iter *iter; 3064384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_expr *expr; 3065384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct xt_entry_target *t; 3066384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso size_t target_len = 0; 3067384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3068384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso iter = nft_rule_expr_iter_create(r); 3069384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (iter == NULL) { 3070384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("cannot allocate rule list iterator\n"); 3071384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 3072384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3073384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3074384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso expr = nft_rule_expr_iter_next(iter); 3075384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso while (expr != NULL) { 3076384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *name = 3077384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME); 3078384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3079384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(name, "target") == 0) { 30800391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka targname = nft_rule_expr_get_str(expr, 30810391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka NFT_EXPR_TG_NAME); 30820391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka targinfo = nft_rule_expr_get(expr, NFT_EXPR_TG_INFO, 30830391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka &target_len); 3084384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 3085384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } else if (strcmp(name, "immediate") == 0) { 3086384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso uint32_t verdict = 3087384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_get_u32(expr, NFT_EXPR_IMM_VERDICT); 3088384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3089384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso switch(verdict) { 3090384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NF_ACCEPT: 3091384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso targname = "ACCEPT"; 3092384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 3093384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NF_DROP: 3094384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso targname = "DROP"; 3095384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 3096384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_RETURN: 3097384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso targname = "RETURN"; 3098384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 3099384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_GOTO: 31000391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka targname = nft_rule_expr_get_str(expr, 31010391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka NFT_EXPR_IMM_CHAIN); 3102384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 3103384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso case NFT_JUMP: 31040391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka targname = nft_rule_expr_get_str(expr, 31050391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka NFT_EXPR_IMM_CHAIN); 3106384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso break; 3107384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3108384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3109384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso expr = nft_rule_expr_iter_next(iter); 3110384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3111384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_iter_destroy(iter); 3112384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 31130391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka family = nft_rule_attr_get_u8(r, NFT_RULE_ATTR_FAMILY); 31140391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka 31150391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka switch (family) { 31160391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka case AF_INET: 31170391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka flags = cs->fw.ip.flags; 31180391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka invflags = flags = cs->fw.ip.invflags; 31190391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka proto = cs->fw.ip.proto; 31200391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka iniface = cs->fw.ip.iniface; 31210391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka outiface = cs->fw.ip.outiface; 31220391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka break; 31230391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka case AF_INET6: 31240391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka flags = cs->fw6.ipv6.flags; 31250391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka invflags = cs->fw6.ipv6.invflags; 31260391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka proto = cs->fw6.ipv6.proto; 31270391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka iniface = cs->fw6.ipv6.iniface; 31280391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka outiface = cs->fw6.ipv6.outiface; 31290391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka break; 31300391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka } 3131384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3132384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (format & FMT_LINENUMBERS) 3133384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(FMT("%-4u ", "%u "), num); 3134384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3135384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (!(format & FMT_NOCOUNTS)) { 3136384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso print_num(cs->counters.pcnt, format); 3137384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso print_num(cs->counters.bcnt, format); 3138384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3139384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3140384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (!(format & FMT_NOTARGET)) 3141384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(FMT("%-9s ", "%s "), targname ? targname : ""); 3142384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 31430391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka fputc(invflags & XT_INV_PROTO ? '!' : ' ', stdout); 3144384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso { 3145384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *pname = 31460391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka proto_to_name(proto, format&FMT_NUMERIC); 3147384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (pname) 3148384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(FMT("%-5s", "%s "), pname); 3149384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso else 31500391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka printf(FMT("%-5hu", "%hu "), proto); 3151384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3152384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3153384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (format & FMT_OPTIONS) { 3154384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (format & FMT_NOTABLE) 3155384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso fputs("opt ", stdout); 31560391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka fputc(invflags & IPT_INV_FRAG ? '!' : '-', stdout); 3157384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso fputc(flags & IPT_F_FRAG ? 'f' : '-', stdout); 3158384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso fputc(' ', stdout); 3159384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3160384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3161384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (format & FMT_VIA) { 3162384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso char iface[IFNAMSIZ+2]; 31630391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (invflags & IPT_INV_VIA_IN) { 3164384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso iface[0] = '!'; 3165384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso iface[1] = '\0'; 3166384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3167384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso else iface[0] = '\0'; 3168384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 31690391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (iniface[0] != '\0') { 31700391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka strcat(iface, iniface); 3171384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3172384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso else if (format & FMT_NUMERIC) strcat(iface, "*"); 3173384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso else strcat(iface, "any"); 3174384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(FMT(" %-6s ","in %s "), iface); 3175384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 31760391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (invflags & IPT_INV_VIA_OUT) { 3177384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso iface[0] = '!'; 3178384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso iface[1] = '\0'; 3179384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3180384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso else iface[0] = '\0'; 3181384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 31820391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if (outiface[0] != '\0') { 31830391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka strcat(iface, outiface); 3184384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3185384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso else if (format & FMT_NUMERIC) strcat(iface, "*"); 3186384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso else strcat(iface, "any"); 3187384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(FMT("%-6s ","out %s "), iface); 3188384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3189384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3190384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 31910391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka switch (family) { 31920391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka case AF_INET: 31930391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka print_ipv4_addr(cs, format); 31940391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka break; 31950391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka case AF_INET6: 31960391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka print_ipv6_addr(cs, format); 31970391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka break; 3198384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3199384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3200384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (format & FMT_NOTABLE) 3201384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso fputs(" ", stdout); 3202384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3203384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#ifdef IPT_F_GOTO 32040391677c1a0b28c14d01febd9628a543e8e5fd62Tomasz Bursztyka if(flags & IPT_F_GOTO) 3205384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("[goto] "); 3206384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso#endif 3207384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3208384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso iter = nft_rule_expr_iter_create(r); 3209384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (iter == NULL) { 3210384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("cannot allocate rule list iterator\n"); 3211384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 3212384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3213384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3214384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso expr = nft_rule_expr_iter_next(iter); 3215384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso while (expr != NULL) { 3216384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *name = 3217384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME); 3218384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3219384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(name, "match") == 0) 3220384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso print_match(expr, format & FMT_NUMERIC); 3221384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3222384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso expr = nft_rule_expr_iter_next(iter); 3223384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3224384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_expr_iter_destroy(iter); 3225384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3226384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso t = calloc(1, sizeof(struct xt_entry_target) + target_len); 3227384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (t == NULL) 3228384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return; 3229384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3230384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* emulate struct xt_entry_match since ->print needs it */ 3231384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso memcpy((void *)&t->data, targinfo, target_len); 3232384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3233384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (targname) { 3234384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso target = xtables_find_target(targname, XTF_TRY_LOAD); 3235384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (target) { 3236384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (target->print) 3237384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* FIXME missing first parameter */ 3238384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso target->print(NULL, t, format & FMT_NUMERIC); 3239384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } else 3240384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("[%ld bytes of unknown target data] ", 3241384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso target_len); 3242384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3243384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso free(t); 3244384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3245384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (!(format & FMT_NONEWLINE)) 3246384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso fputc('\n', stdout); 3247384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 3248384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3249384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int 3250384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso__nft_rule_list(struct nft_handle *h, struct nft_chain *c, const char *table, 3251384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int rulenum, unsigned int format, 3252384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso void (*cb)(const struct iptables_command_state *cs, 3253384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule *r, unsigned int num, 3254384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso unsigned int format)) 3255384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 3256384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_list *list; 3257384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule_list_iter *iter; 3258384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_rule *r; 3259384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int rule_ctr = 0, ret = 0; 3260384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *chain = nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME); 3261384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3262384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso list = nft_rule_list_get(h); 3263384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (list == NULL) { 3264384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("cannot retrieve rule list from kernel\n"); 3265384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 0; 3266384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3267384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3268384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso iter = nft_rule_list_iter_create(list); 3269384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (iter == NULL) { 3270384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("cannot allocate rule list iterator\n"); 3271384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 0; 3272384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3273384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3274384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso r = nft_rule_list_iter_next(iter); 3275384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso while (r != NULL) { 3276384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *rule_table = 3277384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_attr_get_str(r, NFT_RULE_ATTR_TABLE); 3278384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *rule_chain = 3279384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_attr_get_str(r, NFT_RULE_ATTR_CHAIN); 3280384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3281384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso rule_ctr++; 3282384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3283384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(table, rule_table) != 0 || 3284384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso strcmp(chain, rule_chain) != 0) 3285384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto next; 3286384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3287384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (rulenum > 0) { 3288384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* List by rule number case */ 3289384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (rule_ctr != rulenum) { 3290384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso rule_ctr++; 3291384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto next; 3292384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3293384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } else { 3294384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct iptables_command_state cs = {}; 3295384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* Show all rules case */ 3296384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_to_iptables_command_state(r, &cs); 3297384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3298384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso cb(&cs, r, rule_ctr, format); 3299384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3300384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext: 3301384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso r = nft_rule_list_iter_next(iter); 3302384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3303384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3304384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_list_iter_destroy(iter); 3305384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_list_free(list); 3306384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3307384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (ret == 0) 3308384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso errno = ENOENT; 3309384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3310384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return ret; 3311384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 3312384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3313384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_list(struct nft_handle *h, const char *chain, const char *table, 3314384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int rulenum, unsigned int format) 3315384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 3316384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_chain_list *list; 3317384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_chain_list_iter *iter; 3318384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_chain *c; 3319384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3320384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso list = nft_chain_dump(h); 3321384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3322384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso iter = nft_chain_list_iter_create(list); 3323384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (iter == NULL) { 3324384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("cannot allocate rule list iterator\n"); 3325384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 0; 3326384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3327384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3328384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso c = nft_chain_list_iter_next(iter); 3329384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso while (c != NULL) { 3330384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *chain_table = 3331384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE); 3332384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *chain_name = 3333384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME); 3334384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso uint32_t policy = 3335384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_POLICY); 3336384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso uint32_t refs = 3337384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_USE); 3338384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct xt_counters ctrs = { 3339384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso .pcnt = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_PACKETS), 3340384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso .bcnt = nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_BYTES), 3341384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso }; 3342384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso bool basechain = false; 3343384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3344384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (nft_chain_attr_get(c, NFT_CHAIN_ATTR_HOOKNUM)) 3345384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso basechain = true; 3346384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3347384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(table, chain_table) != 0) 3348384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto next; 3349384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (chain && strcmp(chain, chain_name) != 0) 3350384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto next; 3351384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3352384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso print_header(format, chain_name, policy_name[policy], &ctrs, 3353384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso basechain, refs); 3354384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 335506fc595fa99ab0036d87b259b0d20e4916522969Pablo Neira Ayuso __nft_rule_list(h, c, table, rulenum, format, print_firewall); 3356384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext: 3357384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso c = nft_chain_list_iter_next(iter); 3358384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3359384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3360384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_list_free(list); 3361384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3362384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 1; 3363384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 3364384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3365384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic void 3366384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusolist_save(const struct iptables_command_state *cs, struct nft_rule *r, 3367384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso unsigned int num, unsigned int format) 3368384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 3369384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_print_save(r, !(format & FMT_NOCOUNTS)); 3370384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 3371384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3372384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusostatic int 3373384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonft_rule_list_chain_save(struct nft_handle *h, const char *table, 3374384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_chain_list *list, int counters) 3375384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 3376384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_chain_list_iter *iter; 3377384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_chain *c; 3378384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3379384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso iter = nft_chain_list_iter_create(list); 3380384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (iter == NULL) { 3381384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("cannot allocate rule list iterator\n"); 3382384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 0; 3383384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3384384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3385384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso c = nft_chain_list_iter_next(iter); 3386384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso while (c != NULL) { 3387384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *chain_table = 3388384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE); 3389384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *chain_name = 3390384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME); 3391384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso uint32_t policy = 3392384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_attr_get_u32(c, NFT_CHAIN_ATTR_POLICY); 3393384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3394384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(table, chain_table) != 0) 3395384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto next; 3396384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3397384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* this is a base chain */ 3398384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (nft_chain_attr_get(c, NFT_CHAIN_ATTR_HOOKNUM)) { 3399384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("-P %s %s", chain_name, policy_name[policy]); 3400384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3401384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (counters) { 3402384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf(" -c %lu %lu\n", 3403384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_PACKETS), 3404384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_attr_get_u64(c, NFT_CHAIN_ATTR_BYTES)); 3405384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } else 3406384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("\n"); 3407384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } else { 3408384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso printf("-N %s\n", chain_name); 3409384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3410384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext: 3411384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso c = nft_chain_list_iter_next(iter); 3412384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3413384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3414384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 1; 3415384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 3416384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3417384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_rule_list_save(struct nft_handle *h, const char *chain, 3418384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *table, int rulenum, int counters) 3419384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 3420384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_chain_list *list; 3421384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_chain_list_iter *iter; 3422384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nft_chain *c; 3423384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3424384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso list = nft_chain_dump(h); 3425384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3426384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* Dump policies and custom chains first */ 3427384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_rule_list_chain_save(h, table, list, counters); 3428384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3429384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* Now dump out rules in this table */ 3430384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso iter = nft_chain_list_iter_create(list); 3431384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (iter == NULL) { 3432384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("cannot allocate rule list iterator\n"); 3433384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 0; 3434384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3435384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3436384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso c = nft_chain_list_iter_next(iter); 3437384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso while (c != NULL) { 3438384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *chain_table = 3439384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_TABLE); 3440384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *chain_name = 3441384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_attr_get_str(c, NFT_CHAIN_ATTR_NAME); 3442384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3443384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (strcmp(table, chain_table) != 0) 3444384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto next; 3445384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (chain && strcmp(chain, chain_name) != 0) 3446384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto next; 3447384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3448384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso __nft_rule_list(h, c, table, rulenum, 3449384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso counters ? 0 : FMT_NOCOUNTS, list_save); 3450384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusonext: 3451384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso c = nft_chain_list_iter_next(iter); 3452384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3453384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3454384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nft_chain_list_free(list); 3455384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3456384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 1; 3457384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 3458384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 34599e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayusostatic int nft_action(struct nft_handle *h, int type) 34609e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso{ 34619e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso char buf[MNL_SOCKET_BUFFER_SIZE]; 34629e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso struct nlmsghdr *nlh; 34639e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso uint32_t seq; 34649e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso int ret; 34659e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso 34669e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso nlh = mnl_nlmsg_put_header(buf); 34679e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso nlh->nlmsg_type = (NFNL_SUBSYS_NFTABLES<< 8) | type; 34689e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; 34699e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso nlh->nlmsg_seq = seq = time(NULL); 34709e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso 34719e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg)); 34729e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso nfg->nfgen_family = AF_INET; 34739e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso nfg->version = NFNETLINK_V0; 34749e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso nfg->res_id = 0; 34759e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso 34769e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso ret = mnl_talk(h, nlh, NULL, NULL); 34779e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso if (ret < 0) { 34789e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso if (errno != EEXIST) 34799e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso perror("mnl-talk:nft_commit"); 34809e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso } 34819e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso return ret; 34829e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso} 34839e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso 34849e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayusoint nft_commit(struct nft_handle *h) 34859e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso{ 34869e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso return nft_action(h, NFT_MSG_COMMIT); 34879e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso} 34889e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso 34899e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayusoint nft_abort(struct nft_handle *h) 34909e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso{ 34919e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso return nft_action(h, NFT_MSG_ABORT); 34929e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso} 34939e62dc8637f210cdeaed784396fecab9b6e5f043Pablo Neira Ayuso 3494384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoint nft_compatible_revision(const char *name, uint8_t rev, int opt) 3495384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 3496384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct mnl_socket *nl; 3497384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso char buf[MNL_SOCKET_BUFFER_SIZE]; 3498384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nlmsghdr *nlh; 3499384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso uint32_t portid, seq, type; 3500384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int ret = 0; 3501384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3502384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (opt == IPT_SO_GET_REVISION_MATCH) 3503384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso type = 0; 3504384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso else 3505384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso type = 1; 3506384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3507384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nlh = mnl_nlmsg_put_header(buf); 3508384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nlh->nlmsg_type = (NFNL_SUBSYS_NFT_COMPAT << 8) | NFNL_MSG_COMPAT_GET; 3509384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; 3510384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nlh->nlmsg_seq = seq = time(NULL); 3511384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3512384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg)); 3513384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nfg->nfgen_family = AF_INET; 3514384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nfg->version = NFNETLINK_V0; 3515384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nfg->res_id = 0; 3516384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3517384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso mnl_attr_put_strz(nlh, NFTA_COMPAT_NAME, name); 3518384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso mnl_attr_put_u32(nlh, NFTA_COMPAT_REV, htonl(rev)); 3519384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso mnl_attr_put_u32(nlh, NFTA_COMPAT_TYPE, htonl(type)); 3520384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3521384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso DEBUGP("requesting `%s' rev=%d type=%d via nft_compat\n", 3522384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso name, rev, type); 3523384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3524384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso nl = mnl_socket_open(NETLINK_NETFILTER); 3525384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (nl == NULL) { 3526384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso perror("mnl_socket_open"); 3527384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return 0; 3528384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3529384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3530384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { 3531384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso perror("mnl_socket_bind"); 3532384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto err; 3533384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3534384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso portid = mnl_socket_get_portid(nl); 3535384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3536384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { 3537384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso perror("mnl_socket_send"); 3538384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto err; 3539384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3540384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3541384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); 3542384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (ret == -1) { 3543384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso perror("mnl_socket_recvfrom"); 3544384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto err; 3545384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3546384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3547384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL); 3548384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if (ret == -1) { 3549384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso perror("mnl_cb_run"); 3550384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso goto err; 3551384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3552384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3553384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoerr: 3554384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso mnl_socket_close(nl); 3555384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3556384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return ret < 0 ? 0 : 1; 3557384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 3558384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3559384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso/* Translates errno numbers into more human-readable form than strerror. */ 3560384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayusoconst char *nft_strerror(int err) 3561384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso{ 3562384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso unsigned int i; 3563384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso static struct table_struct { 3564384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso void *fn; 3565384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso int err; 3566384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso const char *message; 3567384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } table[] = 3568384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso { 3569384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso { nft_chain_user_del, ENOTEMPTY, "Chain is not empty" }, 3570384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso { nft_chain_user_del, EINVAL, "Can't delete built-in chain" }, 3571384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso { nft_chain_user_del, EMLINK, 3572384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso "Can't delete chain with references left" }, 3573384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso { nft_chain_user_add, EEXIST, "Chain already exists" }, 3574384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso { nft_rule_add, E2BIG, "Index of insertion too big" }, 3575384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso { nft_rule_replace, E2BIG, "Index of replacement too big" }, 3576384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso { nft_rule_delete_num, E2BIG, "Index of deletion too big" }, 3577384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso/* { TC_READ_COUNTER, E2BIG, "Index of counter too big" }, 3578384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso { TC_ZERO_COUNTER, E2BIG, "Index of counter too big" }, */ 3579384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso { nft_rule_add, ELOOP, "Loop found in table" }, 3580384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso { nft_rule_add, EINVAL, "Target problem" }, 3581384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso /* ENOENT for DELETE probably means no matching rule */ 3582384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso { nft_rule_delete, ENOENT, 3583384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso "Bad rule (does a matching rule exist in that chain?)" }, 3584384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso { nft_chain_set, ENOENT, "Bad built-in chain name" }, 3585384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso { nft_chain_set, EINVAL, "Bad policy name" }, 3586384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso { NULL, EPERM, "Permission denied (you must be root)" }, 3587384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso { NULL, 0, "Incompatible with this kernel" }, 3588384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" }, 3589384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso { NULL, ENOSYS, "Will be implemented real soon. I promise ;)" }, 3590384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso { NULL, ENOMEM, "Memory allocation problem" }, 3591384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso { NULL, ENOENT, "No chain/target/match by that name" }, 3592384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso }; 3593384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3594384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) { 3595384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso if ((!table[i].fn || table[i].fn == nft_fn) 3596384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso && table[i].err == err) 3597384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return table[i].message; 3598384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso } 3599384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso 3600384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso return strerror(err); 3601384958620abab397062b67fb2763e813b63f74f0Pablo Neira Ayuso} 3602