DTS Application Library  0.2.3
Application library containing referenced objects and interfaces to common libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
nf_ctrack.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 2012 Gregory Nietsky <gregory@distrotetch.co.za>
3  http://www.distrotech.co.za
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 by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
25 #include "config.h"
26 
27 #include <stdint.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <unistd.h>
31 #include <fcntl.h>
32 #include <errno.h>
33 #include <sys/ioctl.h>
34 #include <netinet/in.h>
35 #include <linux/types.h>
36 #include <linux/netfilter.h>
37 #include <libnetfilter_conntrack/libnetfilter_conntrack.h>
38 #include <libnetfilter_conntrack/libnetfilter_conntrack_tcp.h>
39 
40 #include "include/dtsapp.h"
41 #include "include/private.h"
42 
45  NFCTRACK_DONE = 1 << 0
46 };
47 
48 static struct nfct_struct {
49  struct nfct_handle *nfct;
50  int fd;
51  int flags;
52 } *ctrack = NULL;
53 
54 static void close_nfct(void *data) {
55  struct nfct_struct *nfct = data;
56 
57  nfct_close(nfct->nfct);
58 }
59 
60 static int nfct_cb(enum nf_conntrack_msg_type type, struct nf_conntrack *ct, void *data) {
61  char buf[1024];
62 
63  nfct_snprintf(buf, sizeof(buf), ct, NFCT_T_UNKNOWN, NFCT_O_DEFAULT, NFCT_OF_SHOW_LAYER3 | NFCT_OF_TIME | NFCT_OF_TIMESTAMP);
64  printf("%s\n", buf);
65 
66  return (NFCT_CB_CONTINUE);
67 }
68 
69 static struct nfct_struct *nf_ctrack_alloc(uint8_t subsys_id, unsigned subscriptions) {
70  struct nfct_struct *nfct;
71 
72  if (!(nfct = objalloc((sizeof *ctrack), close_nfct))) {
73  return (NULL);
74  }
75 
76  /* expectations and conntrack*/
77  if (!(nfct->nfct = nfct_open(subsys_id, subscriptions))) {
78  objunref(nfct);
79  return (NULL);
80  }
81 
82  if ((nfct->fd = nfct_fd(nfct->nfct)) < 0) {
83  objunref(nfct);
84  return (NULL);
85  }
86 
87  return (nfct);
88 }
89 
90 extern uint8_t nf_ctrack_init(void) {
91  if (!ctrack && !(ctrack = nf_ctrack_alloc(CONNTRACK, 0))) {
92  return (-1);
93  }
94  return (0);
95 }
96 
97 extern struct nf_conntrack *nf_ctrack_buildct(uint8_t *pkt) {
98  struct nf_conntrack *ct;
99  struct iphdr *ip = (struct iphdr *)pkt;
100  union l4hdr *l4 = (union l4hdr *)(pkt + (ip->ihl * 4));
101 
102  if (!(ct = nfct_new())) {
103  return (NULL);
104  };
105 
106  /*Build tuple*/
107  nfct_set_attr_u8(ct, ATTR_L3PROTO, PF_INET);
108  nfct_set_attr_u32(ct, ATTR_IPV4_SRC, ip->saddr);
109  nfct_set_attr_u32(ct, ATTR_IPV4_DST, ip->daddr);
110  nfct_set_attr_u8(ct, ATTR_L4PROTO, ip->protocol);
111  switch(ip->protocol) {
112  case IPPROTO_TCP:
113  nfct_set_attr_u16(ct, ATTR_PORT_SRC, l4->tcp.source);
114  nfct_set_attr_u16(ct, ATTR_PORT_DST, l4->tcp.dest);
115  break;
116  case IPPROTO_UDP:
117  nfct_set_attr_u16(ct, ATTR_PORT_SRC, l4->udp.source);
118  nfct_set_attr_u16(ct, ATTR_PORT_DST, l4->udp.dest);
119  break;
120  case IPPROTO_ICMP:
121  nfct_set_attr_u8(ct, ATTR_ICMP_TYPE, l4->icmp.type);
122  nfct_set_attr_u8(ct, ATTR_ICMP_CODE, l4->icmp.code);
123  nfct_set_attr_u16(ct, ATTR_ICMP_ID, l4->icmp.un.echo.id);
124  /* no break */
125  default
126  :
127  break;
128  };
129 
130  return (ct);
131 }
132 
133 extern uint8_t nf_ctrack_delete(uint8_t *pkt) {
134  struct nf_conntrack *ct;
135  uint8_t unref = 0;
136  uint8_t ret = 0;
137 
138  if (!ctrack) {
139  if (nf_ctrack_init()) {
140  return (-1);
141  }
142  unref = 1;
143  }
144 
145  ct = nf_ctrack_buildct(pkt);
146  objlock(ctrack);
147  if (nfct_query(ctrack->nfct, NFCT_Q_DESTROY, ct) < 0) {
148  ret = -1;
149  }
150  objunlock(ctrack);
151  nfct_destroy(ct);
152 
153  if (unref) {
154  nf_ctrack_close();
155  }
156 
157  return (ret);
158 }
159 
160 extern uint8_t nf_ctrack_nat(uint8_t *pkt, uint32_t addr, uint16_t port, uint8_t dnat) {
161  struct iphdr *ip = (struct iphdr *)pkt;
162  struct nf_conntrack *ct;
163  uint8_t unref = 0;
164  uint8_t ret = 0;
165 
166  if (!ctrack) {
167  if (nf_ctrack_init()) {
168  return (-1);
169  }
170  unref = 1;
171  }
172 
173  ct = nf_ctrack_buildct(pkt);
174  nfct_setobjopt(ct, NFCT_SOPT_SETUP_REPLY);
175 
176  nfct_set_attr_u32(ct, ATTR_TIMEOUT, 120);
177  nfct_set_attr_u32(ct, (dnat) ? ATTR_DNAT_IPV4 : ATTR_SNAT_IPV4, addr);
178 
179  switch(ip->protocol) {
180  case IPPROTO_TCP:
181  nfct_set_attr_u8(ct, ATTR_TCP_STATE, TCP_CONNTRACK_ESTABLISHED);
182  /* no break */
183  case IPPROTO_UDP:
184  if (port) {
185  nfct_set_attr_u16(ct, (dnat) ? ATTR_DNAT_PORT : ATTR_SNAT_PORT, port);
186  }
187  break;
188  }
189 
190  objlock(ctrack);
191  if (nfct_query(ctrack->nfct, NFCT_Q_CREATE_UPDATE, ct) < 0) {
192  ret = -1;
193  }
194  objunlock(ctrack);
195  nfct_destroy(ct);
196 
197  if (unref) {
198  nf_ctrack_close();
199  }
200 
201  return (ret);
202 }
203 
204 extern void nf_ctrack_dump(void) {
205  uint32_t family = PF_INET;
206  uint8_t unref = 0;
207 
208  if (!ctrack) {
209  if (nf_ctrack_init()) {
210  return;
211  }
212  unref = 1;
213  }
214 
215  objlock(ctrack);
216  nfct_callback_register(ctrack->nfct, NFCT_T_ALL, nfct_cb, NULL);
217  nfct_query(ctrack->nfct, NFCT_Q_DUMP, &family);
218  nfct_callback_unregister(ctrack->nfct);
219  objunlock(ctrack);
220 
221  if (unref) {
222  nf_ctrack_close();
223  }
224 }
225 
226 static void *nf_ctrack_trace_th(void *data) {
227  struct nfct_struct *nfct = data;
228  fd_set rd_set, act_set;
229  struct timeval tv;
230  int selfd;
231  int opt = 1;
232 
233  nfct_callback_register(nfct->nfct, NFCT_T_ALL, nfct_cb, NULL);
234 
235  FD_ZERO(&rd_set);
236  FD_SET(nfct->fd, &rd_set);
237  fcntl(nfct->fd, F_SETFD, O_NONBLOCK);
238  ioctl(nfct->fd, FIONBIO, &opt);
239 
240  while (!testflag(nfct, NFCTRACK_DONE) && framework_threadok()) {
241  act_set = rd_set;
242  tv.tv_sec = 0;
243  tv.tv_usec = 20000;
244  selfd = select(nfct->fd + 1, &act_set, NULL, NULL, &tv);
245 
246  /*returned due to interupt continue or timed out*/
247  if ((selfd < 0 && errno == EINTR) || (!selfd)) {
248  continue;
249  } else
250  if (selfd < 0) {
251  break;
252  }
253 
254  if (FD_ISSET(nfct->fd, &act_set)) {
255  nfct_catch(nfct->nfct);
256  }
257  }
258  return (NULL);
259 }
260 
262  struct nfct_struct *nfct;
263  void *thr;
264 
265  if (!(nfct = nf_ctrack_alloc(CONNTRACK, NFCT_ALL_CT_GROUPS))) {
266  return (NULL);
267  }
268 
269  if (!(thr = framework_mkthread(nf_ctrack_trace_th, NULL, NULL, nfct, THREAD_OPTION_RETURN))) {
270  objunref(nfct);
271  return NULL;
272  }
273  objunref(thr);
274 
275  return (nfct);
276 }
277 
278 extern void nf_ctrack_endtrace(struct nfct_struct *nfct) {
279  if (nfct) {
280  setflag(nfct, NFCTRACK_DONE);
281  }
282  objunref(nfct);
283 }
284 
285 extern void nf_ctrack_close(void) {
286  if (ctrack) {
287  objunref(ctrack);
288  }
289  ctrack = NULL;
290 }
291 
uint8_t nf_ctrack_delete(uint8_t *pkt)
Definition: nf_ctrack.c:133
#define testflag(obj, flag)
Atomically test a flag in the flags field of a referenced object.
Definition: dtsapp.h:932
struct nf_conntrack * nf_ctrack_buildct(uint8_t *pkt)
Definition: nf_ctrack.c:97
uint8_t nf_ctrack_init(void)
Definition: nf_ctrack.c:90
int objlock(void *data)
Lock the reference.
Definition: refobj.c:269
uint8_t nf_ctrack_nat(uint8_t *pkt, uint32_t addr, uint16_t port, uint8_t dnat)
Definition: nf_ctrack.c:160
void * objalloc(int size, objdestroy)
Allocate a referenced lockable object.
Definition: refobj.c:129
void nf_ctrack_endtrace(struct nfct_struct *nfct)
Definition: nf_ctrack.c:278
#define setflag(obj, flag)
Atomically set a flag in the flags field of a referenced object.
Definition: dtsapp.h:925
DTS Application library API Include file.
struct thread_pvt * framework_mkthread(threadfunc, threadcleanup, threadsighandler, void *data, int flags)
create a thread result must be unreferenced
Definition: thread.c:387
Return reference to thread this must be unreferenced.
Definition: dtsapp.h:124
void nf_ctrack_close(void)
Definition: nf_ctrack.c:285
int objunlock(void *data)
Unlock a reference.
Definition: refobj.c:301
struct nfct_struct * nf_ctrack_trace(void)
Definition: nf_ctrack.c:261
struct nfct_struct nfct_struct
Forward decleration of structure.
Definition: dtsapp.h:205
int framework_threadok(void)
let threads check there status.
Definition: thread.c:143
void nf_ctrack_dump(void)
Definition: nf_ctrack.c:204
NF_CTRACK_FLAGS
Netfilter Ctrack Flags.
Definition: nf_ctrack.c:44
int objunref(void *data)
Drop reference held.
Definition: refobj.c:184