4 # include <sys/socket.h>
5 # include <netinet/in.h>
6 # include <arpa/inet.h>
15 # include <ws2tcpip.h>
18 #include <dnscrypt/plugin.h>
19 #include <ldns/ldns.h>
20 #include <ldns/util.h>
22 DCPLUGIN_MAIN(__FILE__
);
24 #define EDNS_HEADER "4f56" "0014" "4f444e5300" "00"
25 #define EDNS_HEADER_CLIENT_IP "10"
26 #define EDNS_CLIENT_IP "7f000001"
27 #define EDNS_HEADER_FODDER "40"
28 #define EDNS_FODDER "deadbeefabad1dea"
30 #define EDNS_DATA EDNS_HEADER \
31 EDNS_HEADER_CLIENT_IP EDNS_CLIENT_IP EDNS_HEADER_FODDER EDNS_FODDER
33 #define EDNS_CLIENT_IP_OFFSET (sizeof EDNS_HEADER - 1U + \
34 sizeof EDNS_HEADER_CLIENT_IP - 1U)
36 #define EDNS_FODDER_OFFSET (sizeof EDNS_HEADER - 1U + \
37 sizeof EDNS_HEADER_CLIENT_IP - 1U + \
38 sizeof EDNS_CLIENT_IP - 1U + \
39 sizeof EDNS_HEADER_FODDER - 1U)
42 dcplugin_description(DCPlugin
* const dcplugin
)
44 return "Apply the OpenDNS settings defined for a specific IP address";
48 dcplugin_long_description(DCPlugin
* const dcplugin
)
51 "The IP address must be a hex-encoded IPv4 address.\n"
55 "# dnscrypt-proxy --plugin \\\n"
56 " libdcplugin_example_ldns_opendns_set_client_ip.la,192.30.252.130";
60 _inet_pton(const int af
, const char * const src
, void * const dst
)
63 unsigned int a
, b
, c
, d
;
70 if (sscanf(src
, "%u.%u.%u.%u%c", &a
, &b
, &c
, &d
, &more
) != 4) {
73 if (a
> 0xff || b
> 0xff || c
> 0xff || d
> 0xff) {
76 dstc
= (unsigned char *) dst
;
77 assert(sizeof(struct in_addr
) >= 4U);
78 dstc
[0] = (unsigned char) a
;
79 dstc
[1] = (unsigned char) b
;
80 dstc
[2] = (unsigned char) c
;
81 dstc
[3] = (unsigned char) d
;
87 parse_client_ip(const char *ip_s
, char * const edns_hex
)
90 struct in_addr ip_in_addr
;
92 const size_t ip_s_len
= strlen(ip_s
);
94 if (ip_s_len
<= INET_ADDRSTRLEN
&& strchr(ip_s
, '.') != NULL
&&
95 _inet_pton(AF_INET
, ip_s
, &ip_in_addr
) > 0) {
96 sa
= (unsigned char *) &ip_in_addr
.s_addr
;
97 snprintf(ip_hex
, sizeof ip_hex
, "%02X%02X%02X%02X",
98 sa
[0], sa
[1], sa
[2], sa
[3]);
99 memcpy(edns_hex
+ EDNS_CLIENT_IP_OFFSET
,
100 ip_hex
, sizeof EDNS_CLIENT_IP
- 1U);
101 } else if (ip_s_len
== sizeof EDNS_CLIENT_IP
- 1U) {
102 memcpy(edns_hex
+ EDNS_CLIENT_IP_OFFSET
,
103 ip_s
, sizeof EDNS_CLIENT_IP
- 1U);
111 dcplugin_init(DCPlugin
* const dcplugin
, int argc
, char *argv
[])
114 size_t edns_hex_size
= sizeof EDNS_DATA
;
116 ldns_init_random(NULL
, 0U);
117 edns_hex
= malloc(edns_hex_size
);
118 dcplugin_set_user_data(dcplugin
, edns_hex
);
119 if (edns_hex
== NULL
) {
122 memcpy(edns_hex
, EDNS_DATA
, edns_hex_size
);
123 assert(sizeof EDNS_CLIENT_IP
- 1U == (size_t) 8U);
124 if (argc
> 1 && argv
[1] != NULL
) {
125 parse_client_ip(argv
[1], edns_hex
);
131 dcplugin_destroy(DCPlugin
*dcplugin
)
133 free(dcplugin_get_user_data(dcplugin
));
139 fill_with_random_hex_data(char * const str
, size_t size
)
141 size_t i
= (size_t) 0U;
145 rnd
= ldns_get_random();
146 str
[i
++] = "0123456789abcdef"[rnd
& 0xf];
147 str
[i
++] = "0123456789abcdef"[(rnd
>> 8) & 0xf];
151 DCPluginSyncFilterResult
152 dcplugin_sync_pre_filter(DCPlugin
*dcplugin
, DCPluginDNSPacket
*dcp_packet
)
158 size_t new_packet_size
;
160 ldns_wire2pkt(&packet
, dcplugin_get_wire_data(dcp_packet
),
161 dcplugin_get_wire_data_len(dcp_packet
));
163 edns_data_str
= dcplugin_get_user_data(dcplugin
);
164 fill_with_random_hex_data(edns_data_str
+ EDNS_FODDER_OFFSET
,
165 sizeof EDNS_FODDER
- 1U);
166 edns_data
= ldns_rdf_new_frm_str(LDNS_RDF_TYPE_HEX
, edns_data_str
);
167 ldns_pkt_set_edns_data(packet
, edns_data
);
169 ldns_pkt2wire(&new_packet
, packet
, &new_packet_size
);
170 if (dcplugin_get_wire_data_max_len(dcp_packet
) >= new_packet_size
) {
171 dcplugin_set_wire_data(dcp_packet
, new_packet
, new_packet_size
);
175 ldns_pkt_free(packet
);
177 return DCP_SYNC_FILTER_RESULT_OK
;