• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/ap/gpl/conntrack-tools/conntrack-tools-1.4.0/src/nfct-extensions/
1/*
2 * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published
6 * by the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This code has been sponsored by Vyatta Inc. <http://www.vyatta.com>
10 */
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <sys/types.h>
16#include <dirent.h>
17#include <sys/stat.h>
18#include <fcntl.h>
19#include <unistd.h>
20#include <time.h>
21#include <netinet/in.h>
22#include <errno.h>
23
24#include <libmnl/libmnl.h>
25#include <linux/netfilter/nfnetlink_cttimeout.h>
26#include <libnetfilter_cttimeout/libnetfilter_cttimeout.h>
27
28#include "nfct.h"
29
30static void
31nfct_cmd_timeout_usage(char *argv[])
32{
33	fprintf(stderr, "nfct v%s: Missing command\n"
34			"%s timeout list|add|delete|get|flush "
35			"[parameters...]\n", VERSION, argv[0]);
36}
37
38int nfct_cmd_timeout_parse_params(int argc, char *argv[])
39{
40	int cmd = NFCT_CMD_NONE, ret;
41
42	if (argc < 3) {
43		nfct_cmd_timeout_usage(argv);
44		return -1;
45	}
46	if (strncmp(argv[2], "list", strlen(argv[2])) == 0)
47		cmd = NFCT_CMD_LIST;
48	else if (strncmp(argv[2], "add", strlen(argv[2])) == 0)
49		cmd = NFCT_CMD_ADD;
50	else if (strncmp(argv[2], "delete", strlen(argv[2])) == 0)
51		cmd = NFCT_CMD_DELETE;
52	else if (strncmp(argv[2], "get", strlen(argv[2])) == 0)
53		cmd = NFCT_CMD_GET;
54	else if (strncmp(argv[2], "flush", strlen(argv[2])) == 0)
55		cmd = NFCT_CMD_FLUSH;
56	else {
57		fprintf(stderr, "nfct v%s: Unknown command: %s\n",
58			VERSION, argv[2]);
59		nfct_cmd_timeout_usage(argv);
60		return -1;
61	}
62	switch(cmd) {
63	case NFCT_CMD_LIST:
64		ret = nfct_cmd_timeout_list(argc, argv);
65		break;
66	case NFCT_CMD_ADD:
67		ret = nfct_cmd_timeout_add(argc, argv);
68		break;
69	case NFCT_CMD_DELETE:
70		ret = nfct_cmd_timeout_delete(argc, argv);
71		break;
72	case NFCT_CMD_GET:
73		ret = nfct_cmd_timeout_get(argc, argv);
74		break;
75	case NFCT_CMD_FLUSH:
76		ret = nfct_cmd_timeout_flush(argc, argv);
77		break;
78	}
79
80	return ret;
81}
82
83static int nfct_timeout_cb(const struct nlmsghdr *nlh, void *data)
84{
85	struct nfct_timeout *t;
86	char buf[4096];
87
88	t = nfct_timeout_alloc();
89	if (t == NULL) {
90		nfct_perror("OOM");
91		goto err;
92	}
93
94	if (nfct_timeout_nlmsg_parse_payload(nlh, t) < 0) {
95		nfct_perror("nfct_timeout_nlmsg_parse_payload");
96		goto err_free;
97	}
98
99	nfct_timeout_snprintf(buf, sizeof(buf), t, NFCT_TIMEOUT_O_DEFAULT, 0);
100	printf("%s\n", buf);
101
102err_free:
103	nfct_timeout_free(t);
104err:
105	return MNL_CB_OK;
106}
107
108int nfct_cmd_timeout_list(int argc, char *argv[])
109{
110	struct mnl_socket *nl;
111	char buf[MNL_SOCKET_BUFFER_SIZE];
112	struct nlmsghdr *nlh;
113	unsigned int seq, portid;
114	int ret;
115
116	if (argc > 3) {
117		nfct_perror("too many arguments");
118		return -1;
119	}
120
121	seq = time(NULL);
122	nlh = nfct_timeout_nlmsg_build_hdr(buf, IPCTNL_MSG_TIMEOUT_GET,
123						NLM_F_DUMP, seq);
124
125	nl = mnl_socket_open(NETLINK_NETFILTER);
126	if (nl == NULL) {
127		nfct_perror("mnl_socket_open");
128		return -1;
129	}
130
131	if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
132		nfct_perror("mnl_socket_bind");
133		return -1;
134	}
135	portid = mnl_socket_get_portid(nl);
136
137	if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
138		nfct_perror("mnl_socket_send");
139		return -1;
140	}
141
142	ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
143	while (ret > 0) {
144		ret = mnl_cb_run(buf, ret, seq, portid, nfct_timeout_cb, NULL);
145		if (ret <= 0)
146			break;
147		ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
148	}
149	if (ret == -1) {
150		nfct_perror("error");
151		return -1;
152	}
153	mnl_socket_close(nl);
154
155	return 0;
156}
157
158static uint32_t nfct_timeout_attr_max[IPPROTO_MAX] = {
159	[IPPROTO_ICMP]		= NFCT_TIMEOUT_ATTR_ICMP_MAX,
160	[IPPROTO_TCP]		= NFCT_TIMEOUT_ATTR_TCP_MAX,
161	[IPPROTO_UDP]		= NFCT_TIMEOUT_ATTR_UDP_MAX,
162	[IPPROTO_UDPLITE]	= NFCT_TIMEOUT_ATTR_UDPLITE_MAX,
163	[IPPROTO_SCTP]		= NFCT_TIMEOUT_ATTR_SCTP_MAX,
164	[IPPROTO_DCCP]		= NFCT_TIMEOUT_ATTR_DCCP_MAX,
165	[IPPROTO_ICMPV6]	= NFCT_TIMEOUT_ATTR_ICMPV6_MAX,
166	[IPPROTO_GRE]		= NFCT_TIMEOUT_ATTR_GRE_MAX,
167	[IPPROTO_RAW]		= NFCT_TIMEOUT_ATTR_GENERIC_MAX,
168};
169
170int nfct_cmd_timeout_add(int argc, char *argv[])
171{
172	struct mnl_socket *nl;
173	char buf[MNL_SOCKET_BUFFER_SIZE];
174	struct nlmsghdr *nlh;
175	uint32_t portid, seq;
176	struct nfct_timeout *t;
177	uint16_t l3proto;
178	uint8_t l4proto;
179	int ret, i;
180	unsigned int j;
181
182	if (argc < 6) {
183		nfct_perror("missing parameters\n"
184			    "syntax: nfct timeout add name "
185			    "family protocol state1 "
186			    "timeout1 state2 timeout2...");
187		return -1;
188	}
189
190	t = nfct_timeout_alloc();
191	if (t == NULL) {
192		nfct_perror("OOM");
193		return -1;
194	}
195
196	nfct_timeout_attr_set(t, NFCT_TIMEOUT_ATTR_NAME, argv[3]);
197
198	if (strcmp(argv[4], "inet") == 0)
199		l3proto = AF_INET;
200	else if (strcmp(argv[4], "inet6") == 0)
201		l3proto = AF_INET6;
202	else {
203		nfct_perror("unknown layer 3 protocol");
204		return -1;
205	}
206	nfct_timeout_attr_set_u16(t, NFCT_TIMEOUT_ATTR_L3PROTO, l3proto);
207
208	if (strcmp(argv[5], "tcp") == 0)
209		l4proto = IPPROTO_TCP;
210	else if (strcmp(argv[5], "udp") == 0)
211		l4proto = IPPROTO_UDP;
212	else if (strcmp(argv[5], "udplite") == 0)
213		l4proto = IPPROTO_UDPLITE;
214	else if (strcmp(argv[5], "sctp") == 0)
215		l4proto = IPPROTO_SCTP;
216	else if (strcmp(argv[5], "dccp") == 0)
217		l4proto = IPPROTO_DCCP;
218	else if (strcmp(argv[5], "icmp") == 0)
219		l4proto = IPPROTO_ICMP;
220	else if (strcmp(argv[5], "icmpv6") == 0)
221		l4proto = IPPROTO_ICMPV6;
222	else if (strcmp(argv[5], "gre") == 0)
223		l4proto = IPPROTO_GRE;
224	else if (strcmp(argv[5], "generic") == 0)
225		l4proto = IPPROTO_RAW;
226	else {
227		nfct_perror("unknown layer 4 protocol");
228		return -1;
229	}
230	nfct_timeout_attr_set_u8(t, NFCT_TIMEOUT_ATTR_L4PROTO, l4proto);
231
232	for (i=6; i<argc; i+=2) {
233		int matching = -1;
234
235		for (j=0; j<nfct_timeout_attr_max[l4proto]; j++) {
236			const char *state_name;
237
238			state_name =
239				nfct_timeout_policy_attr_to_name(l4proto, j);
240			if (state_name == NULL) {
241				nfct_perror("state name is NULL");
242				return -1;
243			}
244			if (strcasecmp(argv[i], state_name) != 0)
245				continue;
246
247			matching = j;
248			break;
249		}
250		if (matching != -1) {
251			if (i+1 >= argc) {
252				nfct_perror("missing value for this timeout");
253				return -1;
254			}
255			nfct_timeout_policy_attr_set_u32(t, matching,
256							 atoi(argv[i+1]));
257			matching = -1;
258		} else {
259			fprintf(stderr, "nfct v%s: Wrong state name: `%s' "
260					"for protocol `%s'\n",
261					VERSION, argv[i], argv[5]);
262			return -1;
263		}
264	}
265
266	seq = time(NULL);
267	nlh = nfct_timeout_nlmsg_build_hdr(buf, IPCTNL_MSG_TIMEOUT_NEW,
268				     NLM_F_CREATE | NLM_F_ACK, seq);
269	nfct_timeout_nlmsg_build_payload(nlh, t);
270
271	nfct_timeout_free(t);
272
273	nl = mnl_socket_open(NETLINK_NETFILTER);
274	if (nl == NULL) {
275		nfct_perror("mnl_socket_open");
276		return -1;
277	}
278
279	if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
280		nfct_perror("mnl_socket_bind");
281		return -1;
282	}
283	portid = mnl_socket_get_portid(nl);
284
285	if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
286		nfct_perror("mnl_socket_send");
287		return -1;
288	}
289
290	ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
291	while (ret > 0) {
292		ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
293		if (ret <= 0)
294			break;
295		ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
296	}
297	if (ret == -1) {
298		nfct_perror("error");
299		return -1;
300	}
301	mnl_socket_close(nl);
302
303	return 0;
304}
305
306int nfct_cmd_timeout_delete(int argc, char *argv[])
307{
308	struct mnl_socket *nl;
309	char buf[MNL_SOCKET_BUFFER_SIZE];
310	struct nlmsghdr *nlh;
311	uint32_t portid, seq;
312	struct nfct_timeout *t;
313	int ret;
314
315	if (argc < 4) {
316		nfct_perror("missing timeout policy name");
317		return -1;
318	} else if (argc > 4) {
319		nfct_perror("too many arguments");
320		return -1;
321	}
322
323	t = nfct_timeout_alloc();
324	if (t == NULL) {
325		nfct_perror("OOM");
326		return -1;
327	}
328
329	nfct_timeout_attr_set(t, NFCT_TIMEOUT_ATTR_NAME, argv[3]);
330
331	seq = time(NULL);
332	nlh = nfct_timeout_nlmsg_build_hdr(buf, IPCTNL_MSG_TIMEOUT_DELETE,
333				     NLM_F_ACK, seq);
334	nfct_timeout_nlmsg_build_payload(nlh, t);
335
336	nfct_timeout_free(t);
337
338	nl = mnl_socket_open(NETLINK_NETFILTER);
339	if (nl == NULL) {
340		nfct_perror("mnl_socket_open");
341		return -1;
342	}
343
344	if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
345		nfct_perror("mnl_socket_bind");
346		return -1;
347	}
348	portid = mnl_socket_get_portid(nl);
349
350	if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
351		nfct_perror("mnl_socket_send");
352		return -1;
353	}
354
355	ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
356	while (ret > 0) {
357		ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
358		if (ret <= 0)
359			break;
360		ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
361	}
362	if (ret == -1) {
363		nfct_perror("error");
364		return -1;
365	}
366
367	mnl_socket_close(nl);
368
369	return 0;
370}
371
372int nfct_cmd_timeout_get(int argc, char *argv[])
373{
374	struct mnl_socket *nl;
375	char buf[MNL_SOCKET_BUFFER_SIZE];
376	struct nlmsghdr *nlh;
377	uint32_t portid, seq;
378	struct nfct_timeout *t;
379	int ret;
380
381	if (argc < 4) {
382		nfct_perror("missing timeout policy name");
383		return -1;
384	} else if (argc > 4) {
385		nfct_perror("too many arguments");
386		return -1;
387	}
388
389	t = nfct_timeout_alloc();
390	if (t == NULL) {
391		nfct_perror("OOM");
392		return -1;
393	}
394	nfct_timeout_attr_set(t, NFCT_TIMEOUT_ATTR_NAME, argv[3]);
395
396	seq = time(NULL);
397	nlh = nfct_timeout_nlmsg_build_hdr(buf, IPCTNL_MSG_TIMEOUT_GET,
398				     NLM_F_ACK, seq);
399
400	nfct_timeout_nlmsg_build_payload(nlh, t);
401
402	nfct_timeout_free(t);
403
404	nl = mnl_socket_open(NETLINK_NETFILTER);
405	if (nl == NULL) {
406		nfct_perror("mnl_socket_open");
407		return -1;
408	}
409
410	if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
411		nfct_perror("mnl_socket_bind");
412		return -1;
413	}
414	portid = mnl_socket_get_portid(nl);
415
416	if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
417		nfct_perror("mnl_socket_send");
418		return -1;
419	}
420
421	ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
422	while (ret > 0) {
423		ret = mnl_cb_run(buf, ret, seq, portid, nfct_timeout_cb, NULL);
424		if (ret <= 0)
425			break;
426		ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
427	}
428	if (ret == -1) {
429		nfct_perror("error");
430		return -1;
431	}
432	mnl_socket_close(nl);
433
434	return 0;
435}
436
437int nfct_cmd_timeout_flush(int argc, char *argv[])
438{
439	struct mnl_socket *nl;
440	char buf[MNL_SOCKET_BUFFER_SIZE];
441	struct nlmsghdr *nlh;
442	uint32_t portid, seq;
443	int ret;
444
445	if (argc > 3) {
446		nfct_perror("too many arguments");
447		return -1;
448	}
449
450	seq = time(NULL);
451	nlh = nfct_timeout_nlmsg_build_hdr(buf, IPCTNL_MSG_TIMEOUT_DELETE,
452					   NLM_F_ACK, seq);
453
454	nl = mnl_socket_open(NETLINK_NETFILTER);
455	if (nl == NULL) {
456		nfct_perror("mnl_socket_open");
457		return -1;
458	}
459
460	if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
461		nfct_perror("mnl_socket_bind");
462		return -1;
463	}
464	portid = mnl_socket_get_portid(nl);
465
466	if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
467		nfct_perror("mnl_socket_send");
468		return -1;
469	}
470
471	ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
472	while (ret > 0) {
473		ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
474		if (ret <= 0)
475			break;
476		ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
477	}
478	if (ret == -1) {
479		nfct_perror("error");
480		return -1;
481	}
482
483	mnl_socket_close(nl);
484
485	return 0;
486}
487