Imported Upstream version 2.88
[platform/upstream/dnsmasq.git] / src / conntrack.c
1 /* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
2
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; version 2 dated June, 1991, or
6    (at your option) version 3 dated 29 June, 2007.
7  
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12      
13    You should have received a copy of the GNU General Public License
14    along with this program.  If not, see <http://www.gnu.org/licenses/>.
15 */
16
17 #include "dnsmasq.h"
18
19 #ifdef HAVE_CONNTRACK
20
21 #include <libnetfilter_conntrack/libnetfilter_conntrack.h>
22
23 static int gotit = 0; /* yuck */
24
25 static int callback(enum nf_conntrack_msg_type type, struct nf_conntrack *ct, void *data);
26
27 int get_incoming_mark(union mysockaddr *peer_addr, union all_addr *local_addr, int istcp, unsigned int *markp)
28 {
29   struct nf_conntrack *ct;
30   struct nfct_handle *h;
31   
32   gotit = 0;
33   
34   if ((ct = nfct_new())) 
35     {
36       nfct_set_attr_u8(ct, ATTR_L4PROTO, istcp ? IPPROTO_TCP : IPPROTO_UDP);
37       nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(daemon->port));
38       
39       if (peer_addr->sa.sa_family == AF_INET6)
40         {
41           nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET6);
42           nfct_set_attr(ct, ATTR_IPV6_SRC, peer_addr->in6.sin6_addr.s6_addr);
43           nfct_set_attr_u16(ct, ATTR_PORT_SRC, peer_addr->in6.sin6_port);
44           nfct_set_attr(ct, ATTR_IPV6_DST, local_addr->addr6.s6_addr);
45         }
46       else
47         {
48           nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET);
49           nfct_set_attr_u32(ct, ATTR_IPV4_SRC, peer_addr->in.sin_addr.s_addr);
50           nfct_set_attr_u16(ct, ATTR_PORT_SRC, peer_addr->in.sin_port);
51           nfct_set_attr_u32(ct, ATTR_IPV4_DST, local_addr->addr4.s_addr);
52         }
53       
54       
55       if ((h = nfct_open(CONNTRACK, 0))) 
56         {
57           nfct_callback_register(h, NFCT_T_ALL, callback, (void *)markp);  
58           if (nfct_query(h, NFCT_Q_GET, ct) == -1)
59             {
60               static int warned = 0;
61               if (!warned)
62                 {
63                   my_syslog(LOG_ERR, _("Conntrack connection mark retrieval failed: %s"), strerror(errno));
64                   warned = 1;
65                 }
66             }
67           nfct_close(h);  
68         }
69       nfct_destroy(ct);
70     }
71
72   return gotit;
73 }
74
75 static int callback(enum nf_conntrack_msg_type type, struct nf_conntrack *ct, void *data)
76 {
77   unsigned int *ret = (unsigned int *)data;
78   *ret = nfct_get_attr_u32(ct, ATTR_MARK);
79   (void)type; /* eliminate warning */
80   gotit = 1;
81
82   return NFCT_CB_CONTINUE;
83 }
84
85 #endif /* HAVE_CONNTRACK */