libnftnl  1.1.5
socket.c
1 /*
2  * Copyright (c) 2018 Máté Eckl <ecklm94@gmail.com>
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 
10 #include <stdio.h>
11 #include <stdint.h>
12 #include <string.h>
13 #include <arpa/inet.h>
14 #include <errno.h>
15 #include <linux/netfilter/nf_tables.h>
16 
17 #include "internal.h"
18 #include <libmnl/libmnl.h>
19 #include <libnftnl/expr.h>
20 #include <libnftnl/rule.h>
21 
23  enum nft_socket_keys key;
24  enum nft_registers dreg;
25 };
26 
27 static int
28 nftnl_expr_socket_set(struct nftnl_expr *e, uint16_t type,
29  const void *data, uint32_t data_len)
30 {
31  struct nftnl_expr_socket *socket = nftnl_expr_data(e);
32 
33  switch (type) {
34  case NFTNL_EXPR_SOCKET_KEY:
35  memcpy(&socket->key, data, sizeof(socket->key));
36  break;
37  case NFTNL_EXPR_SOCKET_DREG:
38  memcpy(&socket->dreg, data, sizeof(socket->dreg));
39  break;
40  default:
41  return -1;
42  }
43  return 0;
44 }
45 
46 static const void *
47 nftnl_expr_socket_get(const struct nftnl_expr *e, uint16_t type,
48  uint32_t *data_len)
49 {
50  struct nftnl_expr_socket *socket = nftnl_expr_data(e);
51 
52  switch (type) {
53  case NFTNL_EXPR_SOCKET_KEY:
54  *data_len = sizeof(socket->key);
55  return &socket->key;
56  case NFTNL_EXPR_SOCKET_DREG:
57  *data_len = sizeof(socket->dreg);
58  return &socket->dreg;
59  }
60  return NULL;
61 }
62 
63 static int nftnl_expr_socket_cb(const struct nlattr *attr, void *data)
64 {
65  const struct nlattr **tb = data;
66  int type = mnl_attr_get_type(attr);
67 
68  if (mnl_attr_type_valid(attr, NFTA_SOCKET_MAX) < 0)
69  return MNL_CB_OK;
70 
71  switch (type) {
72  case NFTA_SOCKET_KEY:
73  case NFTA_SOCKET_DREG:
74  if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
75  abi_breakage();
76  break;
77  }
78 
79  tb[type] = attr;
80  return MNL_CB_OK;
81 }
82 
83 static void
84 nftnl_expr_socket_build(struct nlmsghdr *nlh, const struct nftnl_expr *e)
85 {
86  struct nftnl_expr_socket *socket = nftnl_expr_data(e);
87 
88  if (e->flags & (1 << NFTNL_EXPR_SOCKET_KEY))
89  mnl_attr_put_u32(nlh, NFTA_SOCKET_KEY, htonl(socket->key));
90  if (e->flags & (1 << NFTNL_EXPR_SOCKET_DREG))
91  mnl_attr_put_u32(nlh, NFTA_SOCKET_DREG, htonl(socket->dreg));
92 }
93 
94 static int
95 nftnl_expr_socket_parse(struct nftnl_expr *e, struct nlattr *attr)
96 {
97  struct nftnl_expr_socket *socket = nftnl_expr_data(e);
98  struct nlattr *tb[NFTA_SOCKET_MAX+1] = {};
99 
100  if (mnl_attr_parse_nested(attr, nftnl_expr_socket_cb, tb) < 0)
101  return -1;
102 
103  if (tb[NFTA_SOCKET_KEY]) {
104  socket->key = ntohl(mnl_attr_get_u32(tb[NFTA_SOCKET_KEY]));
105  e->flags |= (1 << NFTNL_EXPR_SOCKET_KEY);
106  }
107  if (tb[NFTA_SOCKET_DREG]) {
108  socket->dreg = ntohl(mnl_attr_get_u32(tb[NFTA_SOCKET_DREG]));
109  e->flags |= (1 << NFTNL_EXPR_SOCKET_DREG);
110  }
111 
112  return 0;
113 }
114 
115 static const char *socket_key2str_array[NFT_SOCKET_MAX + 1] = {
116  [NFT_SOCKET_TRANSPARENT] = "transparent",
117  [NFT_SOCKET_MARK] = "mark",
118 };
119 
120 static const char *socket_key2str(uint8_t key)
121 {
122  if (key < NFT_SOCKET_MAX + 1)
123  return socket_key2str_array[key];
124 
125  return "unknown";
126 }
127 
128 static inline int str2socket_key(const char *str)
129 {
130  int i;
131 
132  for (i = 0; i < NFT_SOCKET_MAX + 1; i++) {
133  if (strcmp(str, socket_key2str_array[i]) == 0)
134  return i;
135  }
136 
137  errno = EINVAL;
138  return -1;
139 }
140 
141 static int
142 nftnl_expr_socket_snprintf_default(char *buf, size_t len,
143  const struct nftnl_expr *e)
144 {
145  struct nftnl_expr_socket *socket = nftnl_expr_data(e);
146 
147  if (e->flags & (1 << NFTNL_EXPR_SOCKET_DREG)) {
148  return snprintf(buf, len, "load %s => reg %u ",
149  socket_key2str(socket->key), socket->dreg);
150  }
151  return 0;
152 }
153 
154 static int
155 nftnl_expr_socket_snprintf(char *buf, size_t len, uint32_t type,
156  uint32_t flags, const struct nftnl_expr *e)
157 {
158  switch (type) {
159  case NFTNL_OUTPUT_DEFAULT:
160  return nftnl_expr_socket_snprintf_default(buf, len, e);
161  case NFTNL_OUTPUT_XML:
162  case NFTNL_OUTPUT_JSON:
163  default:
164  break;
165  }
166  return -1;
167 }
168 
169 struct expr_ops expr_ops_socket = {
170  .name = "socket",
171  .alloc_len = sizeof(struct nftnl_expr_socket),
172  .max_attr = NFTA_SOCKET_MAX,
173  .set = nftnl_expr_socket_set,
174  .get = nftnl_expr_socket_get,
175  .parse = nftnl_expr_socket_parse,
176  .build = nftnl_expr_socket_build,
177  .snprintf = nftnl_expr_socket_snprintf,
178 };