|
Packit |
7b22a4 |
/*
|
|
Packit |
7b22a4 |
* (C) 2012-2013 by Pablo Neira Ayuso <pablo@netfilter.org>
|
|
Packit |
7b22a4 |
*
|
|
Packit |
7b22a4 |
* This program is free software; you can redistribute it and/or modify it
|
|
Packit |
7b22a4 |
* under the terms of the GNU General Public License as published by
|
|
Packit |
7b22a4 |
* the Free Software Foundation; either version 2 of the License, or
|
|
Packit |
7b22a4 |
* (at your option) any later version.
|
|
Packit |
7b22a4 |
*
|
|
Packit |
7b22a4 |
* This software has been sponsored by Sophos Astaro <http://www.sophos.com>
|
|
Packit |
7b22a4 |
*/
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
#define _GNU_SOURCE
|
|
Packit |
7b22a4 |
#include "config.h"
|
|
Packit |
7b22a4 |
#include <errno.h>
|
|
Packit |
7b22a4 |
#include <stdlib.h>
|
|
Packit |
7b22a4 |
#include <time.h>
|
|
Packit |
7b22a4 |
#include <string.h>
|
|
Packit |
7b22a4 |
#include <netinet/ether.h>
|
|
Packit |
7b22a4 |
#include <netinet/in.h>
|
|
Packit |
7b22a4 |
#include <netinet/ip6.h>
|
|
Packit |
7b22a4 |
#include <net/if_arp.h>
|
|
Packit |
7b22a4 |
#include <getopt.h>
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
#include <sys/socket.h>
|
|
Packit |
7b22a4 |
#include <arpa/inet.h>
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
#include <linux/netfilter/nfnetlink.h>
|
|
Packit |
7b22a4 |
#include <linux/netfilter/nf_tables.h>
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
#include <libmnl/libmnl.h>
|
|
Packit |
7b22a4 |
#include <libnftnl/table.h>
|
|
Packit |
7b22a4 |
#include <libnftnl/trace.h>
|
|
Packit |
7b22a4 |
#include <libnftnl/chain.h>
|
|
Packit |
7b22a4 |
#include <libnftnl/rule.h>
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
#include <include/xtables.h>
|
|
Packit |
7b22a4 |
#include "iptables.h" /* for xtables_globals */
|
|
Packit |
7b22a4 |
#include "xtables-multi.h"
|
|
Packit |
7b22a4 |
#include "nft.h"
|
|
Packit |
7b22a4 |
#include "nft-arp.h"
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
struct cb_arg {
|
|
Packit |
7b22a4 |
uint32_t nfproto;
|
|
Packit |
7b22a4 |
bool is_event;
|
|
Packit |
7b22a4 |
struct nft_handle *h;
|
|
Packit |
7b22a4 |
};
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static int table_cb(const struct nlmsghdr *nlh, void *data)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
uint32_t type = nlh->nlmsg_type & 0xFF;
|
|
Packit |
7b22a4 |
const struct cb_arg *arg = data;
|
|
Packit |
7b22a4 |
struct nftnl_table *t;
|
|
Packit |
7b22a4 |
char buf[4096];
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
t = nftnl_table_alloc();
|
|
Packit |
7b22a4 |
if (t == NULL)
|
|
Packit |
7b22a4 |
goto err;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (nftnl_table_nlmsg_parse(nlh, t) < 0)
|
|
Packit |
7b22a4 |
goto err_free;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (arg->nfproto && arg->nfproto != nftnl_table_get_u32(t, NFTNL_TABLE_FAMILY))
|
|
Packit |
7b22a4 |
goto err_free;
|
|
Packit |
7b22a4 |
nftnl_table_snprintf(buf, sizeof(buf), t, NFTNL_OUTPUT_DEFAULT, 0);
|
|
Packit |
7b22a4 |
printf(" EVENT: ");
|
|
Packit |
7b22a4 |
printf("nft: %s table: %s\n", type == NFT_MSG_NEWTABLE ? "NEW" : "DEL", buf);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
err_free:
|
|
Packit |
7b22a4 |
nftnl_table_free(t);
|
|
Packit |
7b22a4 |
err:
|
|
Packit |
7b22a4 |
return MNL_CB_OK;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static bool counters;
|
|
Packit |
7b22a4 |
static bool trace;
|
|
Packit |
7b22a4 |
static bool events;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static int rule_cb(const struct nlmsghdr *nlh, void *data)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
uint32_t type = nlh->nlmsg_type & 0xFF;
|
|
Packit |
7b22a4 |
const struct cb_arg *arg = data;
|
|
Packit |
7b22a4 |
struct nftnl_rule *r;
|
|
Packit |
7b22a4 |
uint8_t family;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
r = nftnl_rule_alloc();
|
|
Packit |
7b22a4 |
if (r == NULL)
|
|
Packit |
7b22a4 |
goto err;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (nftnl_rule_nlmsg_parse(nlh, r) < 0)
|
|
Packit |
7b22a4 |
goto err_free;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
family = nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY);
|
|
Packit |
7b22a4 |
if (arg->nfproto && arg->nfproto != family)
|
|
Packit |
7b22a4 |
goto err_free;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (arg->is_event)
|
|
Packit |
7b22a4 |
printf(" EVENT: ");
|
|
Packit |
7b22a4 |
switch (family) {
|
|
Packit |
7b22a4 |
case AF_INET:
|
|
Packit |
7b22a4 |
case AF_INET6:
|
|
Packit |
7b22a4 |
printf("-%c ", family == AF_INET ? '4' : '6');
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NFPROTO_ARP:
|
|
Packit |
7b22a4 |
printf("-0 ");
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
default:
|
|
Packit |
7b22a4 |
goto err_free;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
printf("-t %s ", nftnl_rule_get_str(r, NFTNL_RULE_TABLE));
|
|
Packit |
7b22a4 |
nft_rule_print_save(arg->h, r, type == NFT_MSG_NEWRULE ? NFT_RULE_APPEND :
|
|
Packit |
7b22a4 |
NFT_RULE_DEL,
|
|
Packit |
7b22a4 |
counters ? 0 : FMT_NOCOUNTS);
|
|
Packit |
7b22a4 |
err_free:
|
|
Packit |
7b22a4 |
nftnl_rule_free(r);
|
|
Packit |
7b22a4 |
err:
|
|
Packit |
7b22a4 |
return MNL_CB_OK;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static int chain_cb(const struct nlmsghdr *nlh, void *data)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
uint32_t type = nlh->nlmsg_type & 0xFF;
|
|
Packit |
7b22a4 |
const struct cb_arg *arg = data;
|
|
Packit |
7b22a4 |
struct nftnl_chain *c;
|
|
Packit |
7b22a4 |
char buf[4096];
|
|
Packit |
7b22a4 |
int family;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
c = nftnl_chain_alloc();
|
|
Packit |
7b22a4 |
if (c == NULL)
|
|
Packit |
7b22a4 |
goto err;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (nftnl_chain_nlmsg_parse(nlh, c) < 0)
|
|
Packit |
7b22a4 |
goto err_free;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
family = nftnl_chain_get_u32(c, NFTNL_CHAIN_FAMILY);
|
|
Packit |
7b22a4 |
if (arg->nfproto && arg->nfproto != family)
|
|
Packit |
7b22a4 |
goto err_free;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (nftnl_chain_is_set(c, NFTNL_CHAIN_PRIO))
|
|
Packit |
7b22a4 |
family = -1;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
printf(" EVENT: ");
|
|
Packit |
7b22a4 |
switch (family) {
|
|
Packit |
7b22a4 |
case NFPROTO_IPV4:
|
|
Packit |
7b22a4 |
family = 4;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NFPROTO_IPV6:
|
|
Packit |
7b22a4 |
family = 6;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
default:
|
|
Packit |
7b22a4 |
nftnl_chain_snprintf(buf, sizeof(buf), c, NFTNL_OUTPUT_DEFAULT, 0);
|
|
Packit |
7b22a4 |
printf("# nft: %s\n", buf);
|
|
Packit |
7b22a4 |
goto err_free;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
printf("-%d -t %s -%c %s\n",
|
|
Packit |
7b22a4 |
family,
|
|
Packit |
7b22a4 |
nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE),
|
|
Packit |
7b22a4 |
type == NFT_MSG_NEWCHAIN ? 'N' : 'X',
|
|
Packit |
7b22a4 |
nftnl_chain_get_str(c, NFTNL_CHAIN_NAME));
|
|
Packit |
7b22a4 |
err_free:
|
|
Packit |
7b22a4 |
nftnl_chain_free(c);
|
|
Packit |
7b22a4 |
err:
|
|
Packit |
7b22a4 |
return MNL_CB_OK;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static int newgen_cb(const struct nlmsghdr *nlh, void *data)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
uint32_t genid = 0, pid = 0;
|
|
Packit |
7b22a4 |
const struct nlattr *attr;
|
|
Packit |
7b22a4 |
const char *name = NULL;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
mnl_attr_for_each(attr, nlh, sizeof(struct nfgenmsg)) {
|
|
Packit |
7b22a4 |
switch (mnl_attr_get_type(attr)) {
|
|
Packit |
7b22a4 |
case NFTA_GEN_ID:
|
|
Packit |
7b22a4 |
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
genid = ntohl(mnl_attr_get_u32(attr));
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NFTA_GEN_PROC_NAME:
|
|
Packit |
7b22a4 |
if (mnl_attr_validate(attr, MNL_TYPE_NUL_STRING) < 0)
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
name = mnl_attr_get_str(attr);
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NFTA_GEN_PROC_PID:
|
|
Packit |
7b22a4 |
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
pid = ntohl(mnl_attr_get_u32(attr));
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (name)
|
|
Packit |
7b22a4 |
printf("NEWGEN: GENID=%u PID=%u NAME=%s\n", genid, pid, name);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
return MNL_CB_OK;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static void trace_print_return(const struct nftnl_trace *nlt)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
const char *chain = NULL;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (nftnl_trace_is_set(nlt, NFTNL_TRACE_JUMP_TARGET)) {
|
|
Packit |
7b22a4 |
chain = nftnl_trace_get_str(nlt, NFTNL_TRACE_JUMP_TARGET);
|
|
Packit |
7b22a4 |
printf("%s", chain);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static void trace_print_rule(const struct nftnl_trace *nlt, struct cb_arg *args)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
uint64_t handle = nftnl_trace_get_u64(nlt, NFTNL_TRACE_RULE_HANDLE);
|
|
Packit |
7b22a4 |
uint32_t family = nftnl_trace_get_u32(nlt, NFTNL_TRACE_FAMILY);
|
|
Packit |
7b22a4 |
const char *table = nftnl_trace_get_str(nlt, NFTNL_TRACE_TABLE);
|
|
Packit |
7b22a4 |
const char *chain = nftnl_trace_get_str(nlt, NFTNL_TRACE_CHAIN);
|
|
Packit |
7b22a4 |
struct nftnl_rule *r;
|
|
Packit |
7b22a4 |
struct mnl_socket *nl;
|
|
Packit |
7b22a4 |
struct nlmsghdr *nlh;
|
|
Packit |
7b22a4 |
uint32_t portid;
|
|
Packit |
7b22a4 |
char buf[16536];
|
|
Packit |
7b22a4 |
int ret;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
r = nftnl_rule_alloc();
|
|
Packit |
7b22a4 |
if (r == NULL) {
|
|
Packit |
7b22a4 |
perror("OOM");
|
|
Packit |
7b22a4 |
exit(EXIT_FAILURE);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, family, NLM_F_DUMP, 0);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
nftnl_rule_set_u32(r, NFTNL_RULE_FAMILY, family);
|
|
Packit |
7b22a4 |
nftnl_rule_set_str(r, NFTNL_RULE_CHAIN, chain);
|
|
Packit |
7b22a4 |
nftnl_rule_set_str(r, NFTNL_RULE_TABLE, table);
|
|
Packit |
7b22a4 |
nftnl_rule_set_u64(r, NFTNL_RULE_POSITION, handle);
|
|
Packit |
7b22a4 |
nftnl_rule_nlmsg_build_payload(nlh, r);
|
|
Packit |
7b22a4 |
nftnl_rule_free(r);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
nl = mnl_socket_open(NETLINK_NETFILTER);
|
|
Packit |
7b22a4 |
if (nl == NULL) {
|
|
Packit |
7b22a4 |
perror("mnl_socket_open");
|
|
Packit |
7b22a4 |
exit(EXIT_FAILURE);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
|
Packit |
7b22a4 |
perror("mnl_socket_bind");
|
|
Packit |
7b22a4 |
exit(EXIT_FAILURE);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
portid = mnl_socket_get_portid(nl);
|
|
Packit |
7b22a4 |
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
|
|
Packit |
7b22a4 |
perror("mnl_socket_send");
|
|
Packit |
7b22a4 |
exit(EXIT_FAILURE);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
|
Packit |
7b22a4 |
while (ret > 0) {
|
|
Packit |
7b22a4 |
args->is_event = false;
|
|
Packit |
7b22a4 |
ret = mnl_cb_run(buf, ret, 0, portid, rule_cb, args);
|
|
Packit |
7b22a4 |
if (ret <= 0)
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
if (ret == -1) {
|
|
Packit |
7b22a4 |
perror("error");
|
|
Packit |
7b22a4 |
exit(EXIT_FAILURE);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
mnl_socket_close(nl);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static void trace_print_packet(const struct nftnl_trace *nlt, struct cb_arg *args)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
struct list_head stmts = LIST_HEAD_INIT(stmts);
|
|
Packit |
7b22a4 |
uint32_t nfproto, family;
|
|
Packit |
7b22a4 |
uint16_t l4proto = 0;
|
|
Packit |
7b22a4 |
uint32_t mark;
|
|
Packit |
7b22a4 |
char name[IFNAMSIZ];
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
printf("PACKET: %d %08x ", args->nfproto, nftnl_trace_get_u32(nlt, NFTNL_TRACE_ID));
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (nftnl_trace_is_set(nlt, NFTNL_TRACE_IIF))
|
|
Packit |
7b22a4 |
printf("IN=%s ", if_indextoname(nftnl_trace_get_u32(nlt, NFTNL_TRACE_IIF), name));
|
|
Packit |
7b22a4 |
if (nftnl_trace_is_set(nlt, NFTNL_TRACE_OIF))
|
|
Packit |
7b22a4 |
printf("OUT=%s ", if_indextoname(nftnl_trace_get_u32(nlt, NFTNL_TRACE_OIF), name));
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
family = nftnl_trace_get_u32(nlt, NFTNL_TRACE_FAMILY);
|
|
Packit |
7b22a4 |
nfproto = family;
|
|
Packit |
7b22a4 |
if (nftnl_trace_is_set(nlt, NFTNL_TRACE_NFPROTO)) {
|
|
Packit |
7b22a4 |
nfproto = nftnl_trace_get_u32(nlt, NFTNL_TRACE_NFPROTO);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (family != nfproto)
|
|
Packit |
7b22a4 |
printf("NFPROTO=%d ", nfproto);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (nftnl_trace_is_set(nlt, NFTNL_TRACE_LL_HEADER)) {
|
|
Packit |
7b22a4 |
const struct ethhdr *eh;
|
|
Packit |
7b22a4 |
const char *linklayer;
|
|
Packit |
7b22a4 |
uint32_t i, len;
|
|
Packit |
7b22a4 |
uint16_t type = nftnl_trace_get_u16(nlt, NFTNL_TRACE_IIFTYPE);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
linklayer = nftnl_trace_get_data(nlt, NFTNL_TRACE_LL_HEADER, &len;;
|
|
Packit |
7b22a4 |
switch (type) {
|
|
Packit |
7b22a4 |
case ARPHRD_ETHER:
|
|
Packit |
7b22a4 |
if (len < sizeof(*eh))
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
eh = (const void *)linklayer;
|
|
Packit |
7b22a4 |
printf("MACSRC=%s ", ether_ntoa((const void *)eh->h_source));
|
|
Packit |
7b22a4 |
printf("MACDST=%s ", ether_ntoa((const void *)eh->h_dest));
|
|
Packit |
7b22a4 |
printf("MACPROTO=%04x ", ntohs(eh->h_proto));
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
default:
|
|
Packit |
7b22a4 |
printf("LL=0x%x ", type);
|
|
Packit |
7b22a4 |
for (i = 0 ; i < len; i++)
|
|
Packit |
7b22a4 |
printf("%02x", linklayer[i]);
|
|
Packit |
7b22a4 |
printf(" ");
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (nftnl_trace_is_set(nlt, NFTNL_TRACE_NETWORK_HEADER)) {
|
|
Packit |
7b22a4 |
const struct ip6_hdr *ip6h;
|
|
Packit |
7b22a4 |
const struct iphdr *iph;
|
|
Packit |
7b22a4 |
uint32_t i, len;
|
|
Packit |
7b22a4 |
const char *nh;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
ip6h = nftnl_trace_get_data(nlt, NFTNL_TRACE_NETWORK_HEADER, &len;;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
switch (nfproto) {
|
|
Packit |
7b22a4 |
case NFPROTO_IPV4: {
|
|
Packit |
7b22a4 |
char addrbuf[INET_ADDRSTRLEN];
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (len < sizeof(*iph))
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
iph = (const void *)ip6h;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
inet_ntop(AF_INET, &iph->saddr, addrbuf, sizeof(addrbuf));
|
|
Packit |
7b22a4 |
printf("SRC=%s ", addrbuf);
|
|
Packit |
7b22a4 |
inet_ntop(AF_INET, &iph->daddr, addrbuf, sizeof(addrbuf));
|
|
Packit |
7b22a4 |
printf("DST=%s ", addrbuf);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
printf("LEN=%d TOS=0x%x TTL=%d ID=%d", ntohs(iph->tot_len), iph->tos, iph->ttl, ntohs(iph->id));
|
|
Packit |
7b22a4 |
if (iph->frag_off & htons(0x8000))
|
|
Packit |
7b22a4 |
printf("CE ");
|
|
Packit |
7b22a4 |
if (iph->frag_off & htons(IP_DF))
|
|
Packit |
7b22a4 |
printf("DF ");
|
|
Packit |
7b22a4 |
if (iph->frag_off & htons(IP_MF))
|
|
Packit |
7b22a4 |
printf("MF ");
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (ntohs(iph->frag_off) & 0x1fff)
|
|
Packit |
7b22a4 |
printf("FRAG:%u ", ntohs(iph->frag_off) & 0x1fff);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
l4proto = iph->protocol;
|
|
Packit |
7b22a4 |
if (iph->ihl * 4 > sizeof(*iph)) {
|
|
Packit |
7b22a4 |
unsigned int optsize;
|
|
Packit |
7b22a4 |
const char *op;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
optsize = iph->ihl * 4 - sizeof(*iph);
|
|
Packit |
7b22a4 |
op = (const char *)iph;
|
|
Packit |
7b22a4 |
op += sizeof(*iph);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
printf("OPT (");
|
|
Packit |
7b22a4 |
for (i = 0; i < optsize; i++)
|
|
Packit |
7b22a4 |
printf("%02X", op[i]);
|
|
Packit |
7b22a4 |
printf(")");
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
case NFPROTO_IPV6: {
|
|
Packit |
7b22a4 |
uint32_t flowlabel = ntohl(*(uint32_t *)ip6h);
|
|
Packit |
7b22a4 |
char addrbuf[INET6_ADDRSTRLEN];
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (len < sizeof(*ip6h))
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
inet_ntop(AF_INET6, &ip6h->ip6_src, addrbuf, sizeof(addrbuf));
|
|
Packit |
7b22a4 |
printf("SRC=%s ", addrbuf);
|
|
Packit |
7b22a4 |
inet_ntop(AF_INET6, &ip6h->ip6_dst, addrbuf, sizeof(addrbuf));
|
|
Packit |
7b22a4 |
printf("DST=%s ", addrbuf);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
printf("LEN=%zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
|
|
Packit |
7b22a4 |
ntohs(ip6h->ip6_plen) + sizeof(*iph),
|
|
Packit |
7b22a4 |
(flowlabel & 0x0ff00000) >> 20,
|
|
Packit |
7b22a4 |
ip6h->ip6_hops,
|
|
Packit |
7b22a4 |
flowlabel & 0x000fffff);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
l4proto = ip6h->ip6_nxt;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
default:
|
|
Packit |
7b22a4 |
nh = (const char *)ip6h;
|
|
Packit |
7b22a4 |
printf("NH=");
|
|
Packit |
7b22a4 |
for (i = 0 ; i < len; i++)
|
|
Packit |
7b22a4 |
printf("%02x", nh[i]);
|
|
Packit |
7b22a4 |
printf(" ");
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (nftnl_trace_is_set(nlt, NFTNL_TRACE_TRANSPORT_HEADER)) {
|
|
Packit |
7b22a4 |
const struct tcphdr *tcph;
|
|
Packit |
7b22a4 |
uint32_t len;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
tcph = nftnl_trace_get_data(nlt, NFTNL_TRACE_TRANSPORT_HEADER, &len;;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
switch (l4proto) {
|
|
Packit |
7b22a4 |
case IPPROTO_DCCP:
|
|
Packit |
7b22a4 |
case IPPROTO_SCTP:
|
|
Packit |
7b22a4 |
case IPPROTO_UDPLITE:
|
|
Packit |
7b22a4 |
case IPPROTO_UDP:
|
|
Packit |
7b22a4 |
if (len < 4)
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
printf("SPORT=%d DPORT=%d ", ntohs(tcph->source), ntohs(tcph->dest));
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case IPPROTO_TCP:
|
|
Packit |
7b22a4 |
if (len < sizeof(*tcph))
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
printf("SPORT=%d DPORT=%d ", ntohs(tcph->source), ntohs(tcph->dest));
|
|
Packit |
7b22a4 |
if (tcph->syn)
|
|
Packit |
7b22a4 |
printf("SYN ");
|
|
Packit |
7b22a4 |
if (tcph->ack)
|
|
Packit |
7b22a4 |
printf("ACK ");
|
|
Packit |
7b22a4 |
if (tcph->fin)
|
|
Packit |
7b22a4 |
printf("FIN ");
|
|
Packit |
7b22a4 |
if (tcph->rst)
|
|
Packit |
7b22a4 |
printf("RST ");
|
|
Packit |
7b22a4 |
if (tcph->psh)
|
|
Packit |
7b22a4 |
printf("PSH ");
|
|
Packit |
7b22a4 |
if (tcph->urg)
|
|
Packit |
7b22a4 |
printf("URG ");
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
default:
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
mark = nftnl_trace_get_u32(nlt, NFTNL_TRACE_MARK);
|
|
Packit |
7b22a4 |
if (mark)
|
|
Packit |
7b22a4 |
printf("MARK=0x%x ", mark);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static void print_verdict(struct nftnl_trace *nlt, uint32_t verdict)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
const char *chain;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
switch (verdict) {
|
|
Packit |
7b22a4 |
case NF_ACCEPT:
|
|
Packit |
7b22a4 |
printf("ACCEPT");
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NF_DROP:
|
|
Packit |
7b22a4 |
printf("DROP");
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NF_QUEUE:
|
|
Packit |
7b22a4 |
printf("QUEUE");
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NF_STOLEN:
|
|
Packit |
7b22a4 |
printf("STOLEN");
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NFT_BREAK:
|
|
Packit |
7b22a4 |
printf("BREAK");
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NFT_CONTINUE:
|
|
Packit |
7b22a4 |
printf("CONTINUE");
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NFT_GOTO:
|
|
Packit |
7b22a4 |
printf("GOTO");
|
|
Packit |
7b22a4 |
if (nftnl_trace_is_set(nlt, NFTNL_TRACE_JUMP_TARGET)) {
|
|
Packit |
7b22a4 |
chain = nftnl_trace_get_str(nlt, NFTNL_TRACE_JUMP_TARGET);
|
|
Packit |
7b22a4 |
printf(":%s", chain);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NFT_JUMP:
|
|
Packit |
7b22a4 |
printf("JUMP");
|
|
Packit |
7b22a4 |
if (nftnl_trace_is_set(nlt, NFTNL_TRACE_JUMP_TARGET)) {
|
|
Packit |
7b22a4 |
chain = nftnl_trace_get_str(nlt, NFTNL_TRACE_JUMP_TARGET);
|
|
Packit |
7b22a4 |
printf(":%s", chain);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
default:
|
|
Packit |
7b22a4 |
printf("0x%x", verdict);
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
printf(" ");
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static int trace_cb(const struct nlmsghdr *nlh, struct cb_arg *arg)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
struct nftnl_trace *nlt;
|
|
Packit |
7b22a4 |
uint32_t verdict;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
nlt = nftnl_trace_alloc();
|
|
Packit |
7b22a4 |
if (nlt == NULL)
|
|
Packit |
7b22a4 |
goto err;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (nftnl_trace_nlmsg_parse(nlh, nlt) < 0)
|
|
Packit |
7b22a4 |
goto err_free;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (arg->nfproto &&
|
|
Packit |
7b22a4 |
arg->nfproto != nftnl_trace_get_u32(nlt, NFTNL_TABLE_FAMILY))
|
|
Packit |
7b22a4 |
goto err_free;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
printf(" TRACE: %d %08x %s:%s", nftnl_trace_get_u32(nlt, NFTNL_TABLE_FAMILY),
|
|
Packit |
7b22a4 |
nftnl_trace_get_u32(nlt, NFTNL_TRACE_ID),
|
|
Packit |
7b22a4 |
nftnl_trace_get_str(nlt, NFTNL_TRACE_TABLE),
|
|
Packit |
7b22a4 |
nftnl_trace_get_str(nlt, NFTNL_TRACE_CHAIN));
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
switch (nftnl_trace_get_u32(nlt, NFTNL_TRACE_TYPE)) {
|
|
Packit |
7b22a4 |
case NFT_TRACETYPE_RULE:
|
|
Packit |
7b22a4 |
verdict = nftnl_trace_get_u32(nlt, NFTNL_TRACE_VERDICT);
|
|
Packit |
7b22a4 |
printf(":rule:0x%llx:", (unsigned long long)nftnl_trace_get_u64(nlt, NFTNL_TRACE_RULE_HANDLE));
|
|
Packit |
7b22a4 |
print_verdict(nlt, verdict);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (nftnl_trace_is_set(nlt, NFTNL_TRACE_RULE_HANDLE))
|
|
Packit |
7b22a4 |
trace_print_rule(nlt, arg);
|
|
Packit |
7b22a4 |
if (nftnl_trace_is_set(nlt, NFTNL_TRACE_LL_HEADER) ||
|
|
Packit |
7b22a4 |
nftnl_trace_is_set(nlt, NFTNL_TRACE_NETWORK_HEADER))
|
|
Packit |
7b22a4 |
trace_print_packet(nlt, arg);
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NFT_TRACETYPE_POLICY:
|
|
Packit |
7b22a4 |
printf(":policy:");
|
|
Packit |
7b22a4 |
verdict = nftnl_trace_get_u32(nlt, NFTNL_TRACE_POLICY);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
print_verdict(nlt, verdict);
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NFT_TRACETYPE_RETURN:
|
|
Packit |
7b22a4 |
printf(":return:");
|
|
Packit |
7b22a4 |
trace_print_return(nlt);
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
puts("");
|
|
Packit |
7b22a4 |
err_free:
|
|
Packit |
7b22a4 |
nftnl_trace_free(nlt);
|
|
Packit |
7b22a4 |
err:
|
|
Packit |
7b22a4 |
return MNL_CB_OK;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static int monitor_cb(const struct nlmsghdr *nlh, void *data)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
uint32_t type = nlh->nlmsg_type & 0xFF;
|
|
Packit |
7b22a4 |
struct cb_arg *arg = data;
|
|
Packit |
7b22a4 |
int ret = MNL_CB_OK;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
switch(type) {
|
|
Packit |
7b22a4 |
case NFT_MSG_NEWTABLE:
|
|
Packit |
7b22a4 |
case NFT_MSG_DELTABLE:
|
|
Packit |
7b22a4 |
ret = table_cb(nlh, data);
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NFT_MSG_NEWCHAIN:
|
|
Packit |
7b22a4 |
case NFT_MSG_DELCHAIN:
|
|
Packit |
7b22a4 |
ret = chain_cb(nlh, data);
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NFT_MSG_NEWRULE:
|
|
Packit |
7b22a4 |
case NFT_MSG_DELRULE:
|
|
Packit |
7b22a4 |
arg->is_event = true;
|
|
Packit |
7b22a4 |
ret = rule_cb(nlh, data);
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NFT_MSG_NEWGEN:
|
|
Packit |
7b22a4 |
ret = newgen_cb(nlh, data);
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case NFT_MSG_TRACE:
|
|
Packit |
7b22a4 |
ret = trace_cb(nlh, data);
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
return ret;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static const struct option options[] = {
|
|
Packit |
7b22a4 |
{.name = "counters", .has_arg = false, .val = 'c'},
|
|
Packit |
7b22a4 |
{.name = "trace", .has_arg = false, .val = 't'},
|
|
Packit |
7b22a4 |
{.name = "event", .has_arg = false, .val = 'e'},
|
|
Packit |
7b22a4 |
{.name = "ipv4", .has_arg = false, .val = '4'},
|
|
Packit |
7b22a4 |
{.name = "ipv6", .has_arg = false, .val = '6'},
|
|
Packit |
7b22a4 |
{.name = "version", .has_arg = false, .val = 'V'},
|
|
Packit |
7b22a4 |
{.name = "help", .has_arg = false, .val = 'h'},
|
|
Packit |
7b22a4 |
{NULL},
|
|
Packit |
7b22a4 |
};
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
static void print_usage(void)
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
printf("%s %s\n", xtables_globals.program_name,
|
|
Packit |
7b22a4 |
xtables_globals.program_version);
|
|
Packit |
7b22a4 |
printf("Usage: %s [ -t | -e ]\n"
|
|
Packit |
7b22a4 |
" --trace -t trace ruleset traversal of packets tagged via -j TRACE rule\n"
|
|
Packit |
7b22a4 |
" --event -e show events that modify the ruleset\n"
|
|
Packit |
7b22a4 |
"Optional arguments:\n"
|
|
Packit |
7b22a4 |
" --ipv4 -4 only monitor IPv4\n"
|
|
Packit |
7b22a4 |
" --ipv6 -6 only monitor IPv6\n"
|
|
Packit |
7b22a4 |
" --counters -c show counters in rules\n"
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
, xtables_globals.program_name);
|
|
Packit |
7b22a4 |
exit(EXIT_FAILURE);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
int xtables_monitor_main(int argc, char *argv[])
|
|
Packit |
7b22a4 |
{
|
|
Packit |
7b22a4 |
struct mnl_socket *nl;
|
|
Packit |
7b22a4 |
char buf[MNL_SOCKET_BUFFER_SIZE];
|
|
Packit |
7b22a4 |
uint32_t nfgroup = 0;
|
|
Packit |
7b22a4 |
struct nft_handle h = {};
|
|
Packit |
7b22a4 |
struct cb_arg cb_arg = {
|
|
Packit |
7b22a4 |
.h = &h,
|
|
Packit |
7b22a4 |
};
|
|
Packit |
7b22a4 |
int ret, c;
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
xtables_globals.program_name = "xtables-monitor";
|
|
Packit |
7b22a4 |
/* XXX xtables_init_all does several things we don't want */
|
|
Packit |
7b22a4 |
c = xtables_init_all(&xtables_globals, NFPROTO_IPV4);
|
|
Packit |
7b22a4 |
if (c < 0) {
|
|
Packit |
7b22a4 |
fprintf(stderr, "%s/%s Failed to initialize xtables\n",
|
|
Packit |
7b22a4 |
xtables_globals.program_name,
|
|
Packit |
7b22a4 |
xtables_globals.program_version);
|
|
Packit |
7b22a4 |
exit(1);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
|
|
Packit |
7b22a4 |
init_extensions();
|
|
Packit |
7b22a4 |
init_extensions4();
|
|
Packit |
7b22a4 |
#endif
|
|
Packit |
7b22a4 |
|
|
Packit Service |
635b90 |
if (nft_init(&h, xtables_ipv4)) {
|
|
Packit |
7b22a4 |
fprintf(stderr, "%s/%s Failed to initialize nft: %s\n",
|
|
Packit |
7b22a4 |
xtables_globals.program_name,
|
|
Packit |
7b22a4 |
xtables_globals.program_version,
|
|
Packit |
7b22a4 |
strerror(errno));
|
|
Packit |
7b22a4 |
exit(EXIT_FAILURE);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
opterr = 0;
|
|
Packit |
7b22a4 |
while ((c = getopt_long(argc, argv, "ceht46V", options, NULL)) != -1) {
|
|
Packit |
7b22a4 |
switch (c) {
|
|
Packit |
7b22a4 |
case 'c':
|
|
Packit |
7b22a4 |
counters = true;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case 't':
|
|
Packit |
7b22a4 |
trace = true;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case 'e':
|
|
Packit |
7b22a4 |
events = true;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case 'h':
|
|
Packit |
7b22a4 |
print_usage();
|
|
Packit |
7b22a4 |
exit(0);
|
|
Packit |
7b22a4 |
case '4':
|
|
Packit |
7b22a4 |
cb_arg.nfproto = NFPROTO_IPV4;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case '6':
|
|
Packit |
7b22a4 |
cb_arg.nfproto = NFPROTO_IPV6;
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
case 'V':
|
|
Packit |
7b22a4 |
printf("xtables-monitor %s\n", PACKAGE_VERSION);
|
|
Packit |
7b22a4 |
exit(0);
|
|
Packit |
7b22a4 |
default:
|
|
Packit |
7b22a4 |
fprintf(stderr, "xtables-monitor %s: Bad argument.\n", PACKAGE_VERSION);
|
|
Packit |
7b22a4 |
fprintf(stderr, "Try `xtables-monitor -h' for more information.\n");
|
|
Packit |
7b22a4 |
exit(PARAMETER_PROBLEM);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (trace)
|
|
Packit |
7b22a4 |
nfgroup |= 1 << (NFNLGRP_NFTRACE - 1);
|
|
Packit |
7b22a4 |
if (events)
|
|
Packit |
7b22a4 |
nfgroup |= 1 << (NFNLGRP_NFTABLES - 1);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (nfgroup == 0) {
|
|
Packit |
7b22a4 |
print_usage();
|
|
Packit |
7b22a4 |
exit(EXIT_FAILURE);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
nl = mnl_socket_open(NETLINK_NETFILTER);
|
|
Packit |
7b22a4 |
if (nl == NULL) {
|
|
Packit |
7b22a4 |
perror("cannot open nfnetlink socket");
|
|
Packit |
7b22a4 |
exit(EXIT_FAILURE);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
if (mnl_socket_bind(nl, nfgroup, MNL_SOCKET_AUTOPID) < 0) {
|
|
Packit |
7b22a4 |
perror("cannot bind to nfnetlink socket");
|
|
Packit |
7b22a4 |
exit(EXIT_FAILURE);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
|
Packit |
7b22a4 |
while (ret > 0) {
|
|
Packit |
7b22a4 |
ret = mnl_cb_run(buf, ret, 0, 0, monitor_cb, &cb_arg);
|
|
Packit |
7b22a4 |
if (ret <= 0)
|
|
Packit |
7b22a4 |
break;
|
|
Packit |
7b22a4 |
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
if (ret == -1) {
|
|
Packit |
7b22a4 |
perror("cannot receive from nfnetlink socket");
|
|
Packit |
7b22a4 |
exit(EXIT_FAILURE);
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
mnl_socket_close(nl);
|
|
Packit |
7b22a4 |
|
|
Packit |
7b22a4 |
return EXIT_SUCCESS;
|
|
Packit |
7b22a4 |
}
|
|
Packit |
7b22a4 |
|