1 /*
2 ** Copyright (C) 2006 Olivier DEMBOUR
3 ** $Id: rr.c,v 1.6.4.3 2010/01/20 16:09:07 collignon Exp $
4 **
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with This program; if not, write to the Free Software
18 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include "list.h"
22 #include "dns.h"
23 #include "server.h"
24 #include "rr.h"
25 #include "requests.h"
26 #include "dns.h"
27 #include "debug.h"
28
29 #include <string.h>
30
31 static const t_rr_functions rr_function[] = {
32 { TYPE_TXT, TYPE_TXT, &rr_add_reply_encode, 0, &rr_get_reply_length_encode},
33 { TYPE_KEY, TYPE_KEY, &rr_add_reply_raw, 0, &rr_get_reply_length_raw},
34 // { TYPE_A, TYPE_CNAME, &rr_add_reply_cname, 0, &rr_get_reply_length_cname},
35 // { TYPE_NS, TYPE_NS, 0, 0, 0},
36 // {TYPE_SIG, TYPE_SIG, &rr_add_reply_raw, 0, &rr_get_reply_length_raw},
37 {0,0,0,0}
38 };
39
40
41 /**
42 * @brief get functions pointer for decoding data
43 * @param[in] request type
44 * @retval functions pointer
45 **/
46
get_rr_function_by_type(uint16_t type)47 const t_rr_functions *get_rr_function_by_type(uint16_t type)
48 {
49 int i = 0;
50
51 while (rr_function[i].type
52 && (rr_function[i].type != type))
53 i++;
54 return (rr_function[i].type ? &rr_function[i] : 0);
55 }
56
57 /**
58 * @brief add a answer in the DNS request
59 * @param[in] hdr DNS header
60 * @param[in] where memory to write
61 * @param[in] type type of request (TXT, KEY ...)
62 * @param[in] encoded_data data to put
63 * @param[in] what compress pointer to the subdomain or 0
64 * @retval rr header
65 **/
66
rr_add_data(struct dns_hdr * hdr,void * where,uint16_t type,char * encoded_data,uint16_t what)67 void *rr_add_data(struct dns_hdr *hdr, void *where, uint16_t type, char *encoded_data, uint16_t what)
68 {
69 struct rr_hdr *rr;
70
71 PUT_16(&hdr->ancount, GET_16(&hdr->ancount)+1);
72 hdr->arcount = 0;
73 if (!what) /* std compression */
74 PUT_16(where, sizeof(struct dns_hdr) | COMPRESS_FLAG);
75 else
76 PUT_16(where, what | COMPRESS_FLAG);
77 rr = where + sizeof(uint16_t);
78 PUT_16(&rr->type, type);
79 PUT_16(&rr->klass, CLASS_IN);
80 PUT_32(&rr->ttl, 3);
81 if (encoded_data)
82 {
83 JUMP_RR_HDR(rr)[0] = 'A' + GET_16(&hdr->ancount)-1;
84 strcpy(JUMP_RR_HDR(rr)+1, encoded_data);
85 }
86 else /* fake IP adress */
87 {
88 PUT_16(&rr->rdlength,4);
89 strcpy(JUMP_RR_HDR(rr), "AAAA");
90 }
91 return (rr);
92 }
93 /**
94 * @brief add data as a CNAME no available
95 **/
96
rr_add_reply_cname(t_conf * conf,t_request * req,struct dns_hdr * hdr,void * where,char * encoded_data)97 void *rr_add_reply_cname(t_conf *conf, t_request *req, struct dns_hdr *hdr, void *where, char *encoded_data)
98 {
99 struct rr_hdr *rr;
100 int len;
101 char domain[MAX_EDNS_LEN];
102 char *my_domain;
103
104 /* TODO : should avoid the strcpy each time */
105 strncpy(domain, req->domain, sizeof(domain));
106 dns_encode(domain);
107
108 my_domain = strstr((char *) (hdr+1), domain);
109 rr = rr_add_data(hdr, where, req->reply_functions->reply_type , encoded_data, 0);
110
111 where = JUMP_RR_HDR(rr);
112 dns_encode(where);
113 len = strlen(where);
114
115 ((char *)where)[len] = COMPRESS_FLAG_CHAR; /* add domain name */
116 ((char *)where)[len+1] = (uint16_t) (my_domain - (char *)hdr);
117 PUT_16(&rr->rdlength,len + 2);
118 /* Add fake entry CNAME is at x.x.x.x */
119 rr = rr_add_data(hdr, where+len+2, TYPE_A, 0, JUMP_RR_HDR(rr) - (char *)hdr);
120 where = JUMP_RR_HDR(rr);
121 // PUT_16(&rr->type, TYPE_A);
122 len = strlen(where);
123 return (where + len);
124 }
125
126 /**
127 * @brief add data and dns_encode it
128 * @param[in] conf configuration
129 * @param[in] req request received
130 * @param[in] hdr DNS header
131 * @param[in] where memory address
132 * @param[in] encoded_data data encoded in base64
133 **/
134
rr_add_reply_encode(t_conf * conf,t_request * req,struct dns_hdr * hdr,void * where,char * encoded_data)135 void *rr_add_reply_encode(t_conf *conf, t_request *req, struct dns_hdr *hdr, void *where, char *encoded_data)
136 {
137 struct rr_hdr *rr;
138 int len;
139
140 rr = rr_add_data(hdr, where, req->reply_functions->reply_type, encoded_data, 0);
141 where = JUMP_RR_HDR(rr);
142 dns_encode(where);
143 len = strlen(where) + 1; /* len + byte 0 (label data) */
144 PUT_16(&rr->rdlength,len);
145 return (where + len);
146 }
147
148 /**
149 * @brief add data but don't dns_encode it
150 * @param[in] conf configuration
151 * @param[in] req request received
152 * @param[in] hdr DNS header
153 * @param[in] where memory address
154 * @param[in] encoded_data data encoded in base64
155 **/
156
rr_add_reply_raw(t_conf * conf,t_request * req,struct dns_hdr * hdr,void * where,char * encoded_data)157 void *rr_add_reply_raw(t_conf *conf, t_request *req, struct dns_hdr *hdr,
158 void *where, char *encoded_data)
159 {
160 struct rr_hdr *rr;
161 int len;
162
163 rr = rr_add_data(hdr, where, req->reply_functions->reply_type, encoded_data, 0);
164 where =JUMP_RR_HDR(rr);
165 len = strlen(where);
166 PUT_16(&rr->rdlength,len);
167 return (where + len);
168 }
169
rr_get_reply_length_cname(struct dns_hdr * hdr,t_simple_list * client,int query_len)170 int rr_get_reply_length_cname(struct dns_hdr *hdr, t_simple_list *client, int query_len)
171 {
172
173 /*
174 */
175 return (0);
176 }
177
178 /**
179 * @brief check available length left before being encoded
180 * @param[in] client client
181 * @param[in] query_len query len
182 * @retval len available
183 **/
184
rr_get_reply_length_encode(struct dns_hdr * hdr,t_simple_list * client,int query_len)185 int rr_get_reply_length_encode(struct dns_hdr *hdr, t_simple_list *client, int query_len)
186 {
187 void *end_query;
188 int len;
189 int total_query_len;
190
191 if (!(end_query = jump_end_answer(hdr, query_len)))
192 return (0);
193 total_query_len = (int) (end_query - (void *)hdr);
194 len = (ENCODE_DATA_AVAILABLE(total_query_len,
195 strlen(JUMP_DNS_HDR(hdr)), MAX_DNS_LEN));
196
197 if ((len > 0) && (len > PACKET_LEN + 2))
198 /* IDX + EOL = 2 bytes */
199 len -= (PACKET_LEN + 2);
200 else
201 len = 0;
202 if (client && client->control.mtu_size)
203 len = MIN(DECODED_LEN(client->control.mtu_size), len);
204 DPRINTF(3, "%s return %d\n", __FUNCTION__, len);
205 return (len);
206 }
207
208 /**
209 * @brief check available length left for raw data
210 * @param[in] client client
211 * @param[in] query_len query len
212 * @retval len available
213 **/
214
rr_get_reply_length_raw(struct dns_hdr * hdr,t_simple_list * client,int query_len)215 int rr_get_reply_length_raw(struct dns_hdr *hdr, t_simple_list *client, int query_len)
216 {
217 char *end_query;
218 int len;
219 int total_query_len;
220
221 if (!(end_query = jump_end_answer(hdr, query_len)))
222 return (0);
223 total_query_len = (int) (end_query - (char *)hdr);
224 len = (RAW_DATA_AVAILABLE(total_query_len,
225 strlen(JUMP_DNS_HDR(hdr)), MAX_DNS_LEN));
226
227 if ((len > 0) && (len > PACKET_LEN + 2))
228 /* IDX + EOL = 2 bytes */
229 len -= (PACKET_LEN + 2);
230 else
231 len = 0;
232 /* max mtu ? */
233 if (client && client->control.mtu_size)
234 len = MIN(client->control.mtu_size, len);
235 DPRINTF(3, "%s return %d\n", __FUNCTION__, len);
236 return (len);
237 }
238