libnftnl 1.3.1
utils.c
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * (C) 2012-2013 by Pablo Neira Ayuso <pablo@netfilter.org>
4 * (C) 2013 by Arturo Borrero Gonzalez <arturo@debian.org>
5 */
6
7#include <internal.h>
8#include <stdlib.h>
9#include <string.h>
10#include <limits.h>
11#include <stdint.h>
12#include <arpa/inet.h>
13#include <errno.h>
14#include <inttypes.h>
15
16#include <libmnl/libmnl.h>
17
18#include <libnftnl/common.h>
19
20#include <linux/if.h>
21#include <linux/netfilter.h>
22#include <linux/netfilter/nf_tables.h>
23
24static const char *const nftnl_family_str[NFPROTO_NUMPROTO] = {
25 [NFPROTO_INET] = "inet",
26 [NFPROTO_IPV4] = "ip",
27 [NFPROTO_ARP] = "arp",
28 [NFPROTO_NETDEV] = "netdev",
29 [NFPROTO_BRIDGE] = "bridge",
30 [NFPROTO_IPV6] = "ip6",
31};
32
33const char *nftnl_family2str(uint32_t family)
34{
35 if (family >= NFPROTO_NUMPROTO || !nftnl_family_str[family])
36 return "unknown";
37
38 return nftnl_family_str[family];
39}
40
41const char *nftnl_verdict2str(uint32_t verdict)
42{
43 switch (verdict) {
44 case NF_ACCEPT:
45 return "accept";
46 case NF_DROP:
47 return "drop";
48 case NF_STOLEN:
49 return "stolen";
50 case NF_QUEUE:
51 return "queue";
52 case NF_REPEAT:
53 return "repeat";
54 case NF_STOP:
55 return "stop";
56 case NFT_RETURN:
57 return "return";
58 case NFT_JUMP:
59 return "jump";
60 case NFT_GOTO:
61 return "goto";
62 case NFT_CONTINUE:
63 return "continue";
64 case NFT_BREAK:
65 return "break";
66 default:
67 return "unknown";
68 }
69}
70
71enum nftnl_cmd_type nftnl_flag2cmd(uint32_t flags)
72{
73 if (flags & NFTNL_OF_EVENT_NEW)
74 return NFTNL_CMD_ADD;
75 else if (flags & NFTNL_OF_EVENT_DEL)
76 return NFTNL_CMD_DELETE;
77
78 return NFTNL_CMD_UNSPEC;
79}
80
81int nftnl_fprintf(FILE *fp, const void *obj, uint32_t cmd, uint32_t type,
82 uint32_t flags,
83 int (*snprintf_cb)(char *buf, size_t bufsiz, const void *obj,
84 uint32_t cmd, uint32_t type,
85 uint32_t flags))
86{
87 char _buf[NFTNL_SNPRINTF_BUFSIZ];
88 char *buf = _buf;
89 size_t bufsiz = sizeof(_buf);
90 int ret;
91
92 ret = snprintf_cb(buf, bufsiz, obj, cmd, type, flags);
93 if (ret <= 0)
94 goto out;
95
96 if (ret >= NFTNL_SNPRINTF_BUFSIZ) {
97 bufsiz = ret + 1;
98
99 buf = malloc(bufsiz);
100 if (buf == NULL)
101 return -1;
102
103 ret = snprintf_cb(buf, bufsiz, obj, cmd, type, flags);
104 if (ret <= 0)
105 goto out;
106 }
107
108 ret = fprintf(fp, "%s", buf);
109
110out:
111 if (buf != _buf)
112 xfree(buf);
113
114 return ret;
115}
116
117void __nftnl_assert_attr_exists(uint16_t attr, uint16_t attr_max,
118 const char *filename, int line)
119{
120 fprintf(stderr, "libnftnl: attribute %d > %d (maximum) assertion failed in %s:%d\n",
121 attr, attr_max, filename, line);
122 exit(EXIT_FAILURE);
123}
124
125void __nftnl_assert_fail(uint16_t attr, const char *filename, int line)
126{
127 fprintf(stderr, "libnftnl: attribute %d assertion failed in %s:%d\n",
128 attr, filename, line);
129 exit(EXIT_FAILURE);
130}
131
132void __noreturn __abi_breakage(const char *file, int line, const char *reason)
133{
134 fprintf(stderr, "nf_tables kernel ABI is broken, contact your vendor.\n"
135 "%s:%d reason: %s\n", file, line, reason);
136 exit(EXIT_FAILURE);
137}
138
139int nftnl_set_str_attr(const char **dptr, uint32_t *flags,
140 uint16_t attr, const void *data, uint32_t data_len)
141{
142 if (*flags & (1 << attr))
143 xfree(*dptr);
144
145 *dptr = strndup(data, data_len);
146 if (!*dptr)
147 return -1;
148
149 *flags |= (1 << attr);
150 return 0;
151}
152
153static bool is_wildcard_str(const char *str)
154{
155 size_t len = strlen(str);
156
157 if (len < 1 || str[len - 1] != '*')
158 return false;
159 if (len < 2 || str[len - 2] != '\\')
160 return true;
161 /* XXX: ignore backslash escaping for now */
162 return false;
163}
164
165void nftnl_attr_put_ifname(struct nlmsghdr *nlh, const char *ifname)
166{
167 uint16_t attr = NFTA_DEVICE_NAME;
168 char pfx[IFNAMSIZ];
169
170 if (is_wildcard_str(ifname)) {
171 snprintf(pfx, IFNAMSIZ, "%s", ifname);
172 pfx[strlen(pfx) - 1] = '\0';
173
174 attr = NFTA_DEVICE_PREFIX;
175 ifname = pfx;
176 }
177 mnl_attr_put_strz(nlh, attr, ifname);
178}
179
180char *nftnl_attr_get_ifname(const struct nlattr *attr)
181{
182 const char *dev = mnl_attr_get_str(attr);
183 char buf[IFNAMSIZ];
184
185 switch (mnl_attr_get_type(attr)) {
186 case NFTA_DEVICE_NAME:
187 return strdup(dev);
188 case NFTA_DEVICE_PREFIX:
189 snprintf(buf, IFNAMSIZ, "%s*", dev);
190 return strdup(buf);
191 default:
192 return NULL;
193 }
194}
195
196int nftnl_parse_str_attr(const struct nlattr *tb, int attr,
197 const char **field, uint32_t *flags)
198{
199 if (!tb)
200 return 0;
201
202 if (*flags & (1 << attr))
203 xfree(*field);
204 *field = strdup(mnl_attr_get_str(tb));
205 if (!*field)
206 return -1;
207 *flags |= (1 << attr);
208 return 0;
209}