libnftnl  1.0.2
utils.c
1 /*
2  * (C) 2012-2013 by Pablo Neira Ayuso <pablo@netfilter.org>
3  * (C) 2013 by Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published
7  * by the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  */
10 
11 #include <internal.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <limits.h>
15 #include <stdint.h>
16 #include <arpa/inet.h>
17 #include <errno.h>
18 #include <inttypes.h>
19 
20 #include <linux/netfilter.h>
21 #include <linux/netfilter/nf_tables.h>
22 
23 const char *nft_family2str(uint32_t family)
24 {
25  switch (family) {
26  case AF_INET:
27  return "ip";
28  case AF_INET6:
29  return "ip6";
30  case 1:
31  return "inet";
32  case AF_BRIDGE:
33  return "bridge";
34  case 3: /* NFPROTO_ARP */
35  return "arp";
36  default:
37  return "unknown";
38  }
39 }
40 
41 int nft_str2family(const char *family)
42 {
43  if (strcmp(family, "ip") == 0)
44  return AF_INET;
45  else if (strcmp(family, "ip6") == 0)
46  return AF_INET6;
47  else if (strcmp(family, "inet") == 0)
48  return 1;
49  else if (strcmp(family, "bridge") == 0)
50  return AF_BRIDGE;
51  else if (strcmp(family, "arp") == 0)
52  return 0;
53 
54  errno = EAFNOSUPPORT;
55  return -1;
56 }
57 
58 static struct {
59  int len;
60  int64_t min;
61  uint64_t max;
62 } basetype[] = {
63  [NFT_TYPE_U8] = { .len = sizeof(uint8_t), .max = UINT8_MAX },
64  [NFT_TYPE_U16] = { .len = sizeof(uint16_t), .max = UINT16_MAX },
65  [NFT_TYPE_U32] = { .len = sizeof(uint32_t), .max = UINT32_MAX },
66  [NFT_TYPE_U64] = { .len = sizeof(uint64_t), .max = UINT64_MAX },
67  [NFT_TYPE_S8] = { .len = sizeof(int8_t), .min = INT8_MIN, .max = INT8_MAX },
68  [NFT_TYPE_S16] = { .len = sizeof(int16_t), .min = INT16_MIN, .max = INT16_MAX },
69  [NFT_TYPE_S32] = { .len = sizeof(int32_t), .min = INT32_MIN, .max = INT32_MAX },
70  [NFT_TYPE_S64] = { .len = sizeof(int64_t), .min = INT64_MIN, .max = INT64_MAX },
71 };
72 
73 
74 int nft_get_value(enum nft_type type, void *val, void *out)
75 {
76  int64_t sval;
77  uint64_t uval;
78 
79  switch (type) {
80  case NFT_TYPE_U8:
81  case NFT_TYPE_U16:
82  case NFT_TYPE_U32:
83  case NFT_TYPE_U64:
84  uval = *((uint64_t *)val);
85  if (uval > basetype[type].max) {
86  errno = ERANGE;
87  return -1;
88  }
89  memcpy(out, &uval, basetype[type].len);
90  break;
91  case NFT_TYPE_S8:
92  case NFT_TYPE_S16:
93  case NFT_TYPE_S32:
94  case NFT_TYPE_S64:
95  sval = *((int64_t *)val);
96  if (sval < basetype[type].min ||
97  sval > (int64_t)basetype[type].max) {
98  errno = ERANGE;
99  return -1;
100  }
101  memcpy(out, &sval, basetype[type].len);
102  break;
103  }
104 
105  return 0;
106 }
107 
108 int nft_strtoi(const char *string, int base, void *out, enum nft_type type)
109 {
110  int ret;
111  int64_t sval = 0;
112  uint64_t uval = -1;
113  char *endptr;
114 
115  switch (type) {
116  case NFT_TYPE_U8:
117  case NFT_TYPE_U16:
118  case NFT_TYPE_U32:
119  case NFT_TYPE_U64:
120  uval = strtoll(string, &endptr, base);
121  ret = nft_get_value(type, &uval, out);
122  break;
123  case NFT_TYPE_S8:
124  case NFT_TYPE_S16:
125  case NFT_TYPE_S32:
126  case NFT_TYPE_S64:
127  sval = strtoull(string, &endptr, base);
128  ret = nft_get_value(type, &sval, out);
129  break;
130  default:
131  errno = EINVAL;
132  return -1;
133  }
134 
135  if (*endptr) {
136  errno = EINVAL;
137  return -1;
138  }
139 
140  return ret;
141 }
142 
143 const char *nft_verdict2str(uint32_t verdict)
144 {
145  switch (verdict) {
146  case NF_ACCEPT:
147  return "accept";
148  case NF_DROP:
149  return "drop";
150  case NFT_RETURN:
151  return "return";
152  case NFT_JUMP:
153  return "jump";
154  case NFT_GOTO:
155  return "goto";
156  default:
157  return "unknown";
158  }
159 }
160 
161 int nft_str2verdict(const char *verdict, int *verdict_num)
162 {
163  if (strcmp(verdict, "accept") == 0) {
164  *verdict_num = NF_ACCEPT;
165  return 0;
166  } else if (strcmp(verdict, "drop") == 0) {
167  *verdict_num = NF_DROP;
168  return 0;
169  } else if (strcmp(verdict, "return") == 0) {
170  *verdict_num = NFT_RETURN;
171  return 0;
172  } else if (strcmp(verdict, "jump") == 0) {
173  *verdict_num = NFT_JUMP;
174  return 0;
175  } else if (strcmp(verdict, "goto") == 0) {
176  *verdict_num = NFT_GOTO;
177  return 0;
178  }
179 
180  return -1;
181 }
182 
183 void xfree(const void *ptr)
184 {
185  free((void *)ptr);
186 }
187 
188 int nft_fprintf(FILE *fp, void *obj, uint32_t type, uint32_t flags,
189  int (*snprintf_cb)(char *buf, size_t bufsiz, void *obj,
190  uint32_t type, uint32_t flags))
191 {
192  char _buf[NFT_SNPRINTF_BUFSIZ];
193  char *buf = _buf;
194  size_t bufsiz = sizeof(_buf);
195  int ret;
196 
197  ret = snprintf_cb(buf, bufsiz, obj, type, flags);
198  if (ret < 0)
199  goto out;
200 
201  if (ret >= NFT_SNPRINTF_BUFSIZ) {
202  bufsiz = ret + 1;
203 
204  buf = malloc(bufsiz);
205  if (buf == NULL)
206  return -1;
207 
208  ret = snprintf_cb(buf, bufsiz, obj, type, flags);
209  if (ret < 0)
210  goto out;
211  }
212 
213  ret = fprintf(fp, "%s", buf);
214 
215 out:
216  if (buf != _buf)
217  xfree(buf);
218 
219  return ret;
220 }
221 
222 void __nft_assert_fail(uint16_t attr, const char *filename, int line)
223 {
224  fprintf(stderr, "libnftnl: attribute %d assertion failed in %s:%d\n",
225  attr, filename, line);
226  exit(EXIT_FAILURE);
227 }