libmnl 1.0.5
nf-log.c
1/* This example is placed in the public domain. */
2#include <stdio.h>
3#include <stdlib.h>
4#include <unistd.h>
5#include <string.h>
6#include <time.h>
7#include <arpa/inet.h>
8
9#include <libmnl/libmnl.h>
10#include <linux/netfilter.h>
11#include <linux/netfilter/nfnetlink.h>
12#include <linux/netfilter/nfnetlink_log.h>
13
14static int parse_attr_cb(const struct nlattr *attr, void *data)
15{
16 const struct nlattr **tb = data;
17 int type = mnl_attr_get_type(attr);
18
19 /* skip unsupported attribute in user-space */
20 if (mnl_attr_type_valid(attr, NFULA_MAX) < 0)
21 return MNL_CB_OK;
22
23 switch(type) {
24 case NFULA_MARK:
25 case NFULA_IFINDEX_INDEV:
26 case NFULA_IFINDEX_OUTDEV:
27 case NFULA_IFINDEX_PHYSINDEV:
28 case NFULA_IFINDEX_PHYSOUTDEV:
29 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
30 perror("mnl_attr_validate");
31 return MNL_CB_ERROR;
32 }
33 break;
34 case NFULA_TIMESTAMP:
35 if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC,
36 sizeof(struct nfulnl_msg_packet_timestamp)) < 0) {
37 perror("mnl_attr_validate2");
38 return MNL_CB_ERROR;
39 }
40 break;
41 case NFULA_HWADDR:
42 if (mnl_attr_validate2(attr, MNL_TYPE_UNSPEC,
43 sizeof(struct nfulnl_msg_packet_hw)) < 0) {
44 perror("mnl_attr_validate2");
45 return MNL_CB_ERROR;
46 }
47 break;
48 case NFULA_PREFIX:
49 if (mnl_attr_validate(attr, MNL_TYPE_NUL_STRING) < 0) {
50 perror("mnl_attr_validate");
51 return MNL_CB_ERROR;
52 }
53 break;
54 case NFULA_PAYLOAD:
55 break;
56 }
57 tb[type] = attr;
58 return MNL_CB_OK;
59}
60
61static int log_cb(const struct nlmsghdr *nlh, void *data)
62{
63 struct nlattr *tb[NFULA_MAX+1] = {};
64 struct nfulnl_msg_packet_hdr *ph = NULL;
65 const char *prefix = NULL;
66 uint32_t mark = 0;
67
68 mnl_attr_parse(nlh, sizeof(struct nfgenmsg), parse_attr_cb, tb);
69 if (tb[NFULA_PACKET_HDR])
70 ph = mnl_attr_get_payload(tb[NFULA_PACKET_HDR]);
71 if (tb[NFULA_PREFIX])
72 prefix = mnl_attr_get_str(tb[NFULA_PREFIX]);
73 if (tb[NFULA_MARK])
74 mark = ntohl(mnl_attr_get_u32(tb[NFULA_MARK]));
75
76 printf("log received (prefix=\"%s\" hw=0x%04x hook=%u mark=%u)\n",
77 prefix ? prefix : "", ntohs(ph->hw_protocol), ph->hook,
78 mark);
79
80 return MNL_CB_OK;
81}
82
83static struct nlmsghdr *
84nflog_build_cfg_pf_request(char *buf, uint8_t command)
85{
86 struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
87 nlh->nlmsg_type = (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG;
88 nlh->nlmsg_flags = NLM_F_REQUEST;
89
90 struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
91 nfg->nfgen_family = AF_INET;
92 nfg->version = NFNETLINK_V0;
93
94 struct nfulnl_msg_config_cmd cmd = {
95 .command = command,
96 };
97 mnl_attr_put(nlh, NFULA_CFG_CMD, sizeof(cmd), &cmd);
98
99 return nlh;
100}
101
102static struct nlmsghdr *
103nflog_build_cfg_request(char *buf, uint8_t command, int qnum)
104{
105 struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
106 nlh->nlmsg_type = (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG;
107 nlh->nlmsg_flags = NLM_F_REQUEST;
108
109 struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
110 nfg->nfgen_family = AF_INET;
111 nfg->version = NFNETLINK_V0;
112 nfg->res_id = htons(qnum);
113
114 struct nfulnl_msg_config_cmd cmd = {
115 .command = command,
116 };
117 mnl_attr_put(nlh, NFULA_CFG_CMD, sizeof(cmd), &cmd);
118
119 return nlh;
120}
121
122static struct nlmsghdr *
123nflog_build_cfg_params(char *buf, uint8_t mode, int range, int qnum)
124{
125 struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
126 nlh->nlmsg_type = (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG;
127 nlh->nlmsg_flags = NLM_F_REQUEST;
128
129 struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
130 nfg->nfgen_family = AF_UNSPEC;
131 nfg->version = NFNETLINK_V0;
132 nfg->res_id = htons(qnum);
133
134 struct nfulnl_msg_config_mode params = {
135 .copy_range = htonl(range),
136 .copy_mode = mode,
137 };
138 mnl_attr_put(nlh, NFULA_CFG_MODE, sizeof(params), &params);
139
140 return nlh;
141}
142
143int main(int argc, char *argv[])
144{
145 struct mnl_socket *nl;
146 char buf[MNL_SOCKET_BUFFER_SIZE];
147 struct nlmsghdr *nlh;
148 int ret;
149 unsigned int portid, qnum;
150
151 if (argc != 2) {
152 printf("Usage: %s [queue_num]\n", argv[0]);
153 exit(EXIT_FAILURE);
154 }
155 qnum = atoi(argv[1]);
156
157 nl = mnl_socket_open(NETLINK_NETFILTER);
158 if (nl == NULL) {
159 perror("mnl_socket_open");
160 exit(EXIT_FAILURE);
161 }
162
163 if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
164 perror("mnl_socket_bind");
165 exit(EXIT_FAILURE);
166 }
167 portid = mnl_socket_get_portid(nl);
168
169 nlh = nflog_build_cfg_pf_request(buf, NFULNL_CFG_CMD_PF_UNBIND);
170
171 if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
172 perror("mnl_socket_sendto");
173 exit(EXIT_FAILURE);
174 }
175
176 nlh = nflog_build_cfg_pf_request(buf, NFULNL_CFG_CMD_PF_BIND);
177
178 if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
179 perror("mnl_socket_sendto");
180 exit(EXIT_FAILURE);
181 }
182
183 nlh = nflog_build_cfg_request(buf, NFULNL_CFG_CMD_BIND, qnum);
184
185 if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
186 perror("mnl_socket_sendto");
187 exit(EXIT_FAILURE);
188 }
189
190 nlh = nflog_build_cfg_params(buf, NFULNL_COPY_PACKET, 0xFFFF, qnum);
191
192 if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
193 perror("mnl_socket_sendto");
194 exit(EXIT_FAILURE);
195 }
196
197 ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
198 if (ret == -1) {
199 perror("mnl_socket_recvfrom");
200 exit(EXIT_FAILURE);
201 }
202 while (ret > 0) {
203 ret = mnl_cb_run(buf, ret, 0, portid, log_cb, NULL);
204 if (ret < 0){
205 perror("mnl_cb_run");
206 exit(EXIT_FAILURE);
207 }
208
209 ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
210 if (ret == -1) {
211 perror("mnl_socket_recvfrom");
212 exit(EXIT_FAILURE);
213 }
214 }
215
217
218 return 0;
219}
void * mnl_attr_get_payload(const struct nlattr *attr)
Definition attr.c:72
int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type)
Definition attr.c:207
int mnl_attr_parse(const struct nlmsghdr *nlh, unsigned int offset, mnl_attr_cb_t cb, void *data)
Definition attr.c:255
int mnl_attr_type_valid(const struct nlattr *attr, uint16_t max)
Definition attr.c:127
uint16_t mnl_attr_get_type(const struct nlattr *attr)
Definition attr.c:38
int mnl_attr_validate2(const struct nlattr *attr, enum mnl_attr_data_type type, size_t exp_len)
Definition attr.c:229
uint32_t mnl_attr_get_u32(const struct nlattr *attr)
Definition attr.c:354
const char * mnl_attr_get_str(const struct nlattr *attr)
Definition attr.c:380
void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type, size_t len, const void *data)
Definition attr.c:395
int mnl_cb_run(const void *buf, size_t numbytes, unsigned int seq, unsigned int portid, mnl_cb_t cb_data, void *data)
Definition callback.c:159
struct nlmsghdr * mnl_nlmsg_put_header(void *buf)
Definition nlmsg.c:80
void * mnl_nlmsg_put_extra_header(struct nlmsghdr *nlh, size_t size)
Definition nlmsg.c:101
int mnl_socket_close(struct mnl_socket *nl)
Definition socket.c:296
unsigned int mnl_socket_get_portid(const struct mnl_socket *nl)
Definition socket.c:99
struct mnl_socket * mnl_socket_open(int bus)
Definition socket.c:128
ssize_t mnl_socket_recvfrom(const struct mnl_socket *nl, void *buf, size_t bufsiz)
Definition socket.c:256
int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups, pid_t pid)
Definition socket.c:193
ssize_t mnl_socket_sendto(const struct mnl_socket *nl, const void *buf, size_t len)
Definition socket.c:232