aboutsummaryrefslogtreecommitdiff
path: root/networking
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-03-17 09:02:21 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-03-17 09:02:21 +0000
commit081eb71ebd7954a67287816a9a6fff80e8c5319a (patch)
tree963536f5609d23c6b0f9a31cd4a17dc629fe0842 /networking
parent68404f13d4bf4826e3609703dad5375763db28ab (diff)
downloadbusybox-w32-081eb71ebd7954a67287816a9a6fff80e8c5319a.tar.gz
busybox-w32-081eb71ebd7954a67287816a9a6fff80e8c5319a.tar.bz2
busybox-w32-081eb71ebd7954a67287816a9a6fff80e8c5319a.zip
dnsd: properly set _src_ IP:port on outgoing UDP packets
function old new delta send_to_from - 258 +258 dnsd_main 1500 1568 +68 interrupt 17 19 +2 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 2/0 up/down: 328/0) Total: 328 bytes text data bss dec hex filename 797101 658 7428 805187 c4943 busybox_old 797429 658 7428 805515 c4a8b busybox_unstripped
Diffstat (limited to 'networking')
-rw-r--r--networking/dnsd.c117
1 files changed, 59 insertions, 58 deletions
diff --git a/networking/dnsd.c b/networking/dnsd.c
index b269bc52a..cb62d2081 100644
--- a/networking/dnsd.c
+++ b/networking/dnsd.c
@@ -36,7 +36,7 @@ enum {
36 ttl(4B) + rlen(2B) + r (MAX_NAME_LEN =21B) + 36 ttl(4B) + rlen(2B) + r (MAX_NAME_LEN =21B) +
37 2*querystring (2 MAX_NAME_LEN= 42B), all together 90 Byte 37 2*querystring (2 MAX_NAME_LEN= 42B), all together 90 Byte
38*/ 38*/
39 MAX_PACK_LEN = 512 + 1, 39 MAX_PACK_LEN = 512,
40 40
41 DEFAULT_TTL = 30, // increase this when not testing? 41 DEFAULT_TTL = 30, // increase this when not testing?
42 42
@@ -44,12 +44,6 @@ enum {
44 REQ_PTR = 12 44 REQ_PTR = 12
45}; 45};
46 46
47struct dns_repl { // resource record, add 0 or 1 to accepted dns_msg in resp
48 uint16_t rlen;
49 uint8_t *r; // resource
50 uint16_t flags;
51};
52
53struct dns_head { // the message from client and first part of response mag 47struct dns_head { // the message from client and first part of response mag
54 uint16_t id; 48 uint16_t id;
55 uint16_t flags; 49 uint16_t flags;
@@ -218,20 +212,20 @@ static int table_lookup(uint16_t type, uint8_t * as, uint8_t * qs)
218 return -1; 212 return -1;
219} 213}
220 214
221
222/* 215/*
223 * Decode message and generate answer 216 * Decode message and generate answer
224 */ 217 */
225static int process_packet(uint8_t * buf) 218static int process_packet(uint8_t *buf)
226{ 219{
220 uint8_t answstr[MAX_NAME_LEN + 1];
227 struct dns_head *head; 221 struct dns_head *head;
228 struct dns_prop *qprop; 222 struct dns_prop *qprop;
229 struct dns_repl outr; 223 uint8_t *from, *answb;
230 void *next, *from, *answb; 224 uint16_t outr_rlen;
231 225 uint16_t outr_flags;
232 uint8_t answstr[MAX_NAME_LEN + 1];
233 int lookup_result, type, len, packet_len;
234 uint16_t flags; 226 uint16_t flags;
227 int lookup_result, type, packet_len;
228 int querystr_len;
235 229
236 answstr[0] = '\0'; 230 answstr[0] = '\0';
237 231
@@ -247,11 +241,12 @@ static int process_packet(uint8_t * buf)
247 } 241 }
248 242
249 from = (void *)&head[1]; // start of query string 243 from = (void *)&head[1]; // start of query string
250 next = answb = from + strlen((char *)from) + 1 + sizeof(struct dns_prop); // where to append answer block 244//FIXME: strlen of untrusted data??!
245 querystr_len = strlen((char *)from) + 1 + sizeof(struct dns_prop);
246 answb = from + querystr_len; // where to append answer block
251 247
252 outr.rlen = 0; // may change later 248 outr_rlen = 0;
253 outr.r = NULL; 249 outr_flags = 0;
254 outr.flags = 0;
255 250
256 qprop = (struct dns_prop *)(answb - 4); 251 qprop = (struct dns_prop *)(answb - 4);
257 type = ntohs(qprop->type); 252 type = ntohs(qprop->type);
@@ -262,7 +257,7 @@ static int process_packet(uint8_t * buf)
262 } 257 }
263 258
264 if (ntohs(qprop->class) != 1 /* class INET */ ) { 259 if (ntohs(qprop->class) != 1 /* class INET */ ) {
265 outr.flags = 4; /* not supported */ 260 outr_flags = 4; /* not supported */
266 goto empty_packet; 261 goto empty_packet;
267 } 262 }
268 /* we only support standard queries */ 263 /* we only support standard queries */
@@ -272,49 +267,50 @@ static int process_packet(uint8_t * buf)
272 267
273 // We have a standard query 268 // We have a standard query
274 bb_info_msg("%s", (char *)from); 269 bb_info_msg("%s", (char *)from);
275 lookup_result = table_lookup(type, answstr, (uint8_t*)from); 270 lookup_result = table_lookup(type, answstr, from);
276 if (lookup_result != 0) { 271 if (lookup_result != 0) {
277 outr.flags = 3 | 0x0400; //name do not exist and auth 272 outr_flags = 3 | 0x0400; // name do not exist and auth
278 goto empty_packet; 273 goto empty_packet;
279 } 274 }
280 if (type == REQ_A) { // return an address 275 if (type == REQ_A) { // return an address
281 struct in_addr a; 276 struct in_addr a; // NB! its "struct { unsigned __long__ s_addr; }"
282 if (!inet_aton((char*)answstr, &a)) {//dotted dec to long conv 277 uint32_t v32;
283 outr.flags = 1; /* Frmt err */ 278 if (!inet_aton((char*)answstr, &a)) { //dotted dec to long conv
279 outr_flags = 1; /* Frmt err */
284 goto empty_packet; 280 goto empty_packet;
285 } 281 }
286 memcpy(answstr, &a.s_addr, 4); // save before a disappears 282 v32 = a.s_addr; /* in case long != int */
287 outr.rlen = 4; // uint32_t IP 283 memcpy(answstr, &v32, 4);
284 outr_rlen = 4; // uint32_t IP
288 } else 285 } else
289 outr.rlen = strlen((char *)answstr) + 1; // a host name 286 outr_rlen = strlen((char *)answstr) + 1; // a host name
290 outr.r = answstr; // 32 bit ip or a host name 287 outr_flags |= 0x0400; /* authority-bit */
291 outr.flags |= 0x0400; /* authority-bit */
292 // we have an answer 288 // we have an answer
293 head->nansw = htons(1); 289 head->nansw = htons(1);
294 290
295 // copy query block to answer block 291 // copy query block to answer block
296 len = answb - from; 292 memcpy(answb, from, querystr_len);
297 memcpy(answb, from, len); 293 answb += querystr_len;
298 next += len;
299 294
300 // and append answer rr 295 // and append answer rr
301 *(uint32_t *) next = htonl(ttl); 296// FIXME: unaligned accesses??
302 next += 4; 297 *(uint32_t *) answb = htonl(ttl);
303 *(uint16_t *) next = htons(outr.rlen); 298 answb += 4;
304 next += 2; 299 *(uint16_t *) answb = htons(outr_rlen);
305 memcpy(next, (void *)answstr, outr.rlen); 300 answb += 2;
306 next += outr.rlen; 301 memcpy(answb, answstr, outr_rlen);
302 answb += outr_rlen;
307 303
308 empty_packet: 304 empty_packet:
309 305
310 flags = ntohs(head->flags); 306 flags = ntohs(head->flags);
311 // clear rcode and RA, set responsebit and our new flags 307 // clear rcode and RA, set responsebit and our new flags
312 flags |= (outr.flags & 0xff80) | 0x8000; 308 flags |= (outr_flags & 0xff80) | 0x8000;
313 head->flags = htons(flags); 309 head->flags = htons(flags);
314 head->nauth = head->nadd = htons(0); 310 head->nauth = head->nadd = 0;
315 head->nquer = htons(1); 311 head->nquer = htons(1);
316 312
317 packet_len = (uint8_t *)next - buf; 313 packet_len = answb - buf;
318 return packet_len; 314 return packet_len;
319} 315}
320 316
@@ -333,10 +329,13 @@ int dnsd_main(int argc ATTRIBUTE_UNUSED, char **argv)
333{ 329{
334 const char *listen_interface = "0.0.0.0"; 330 const char *listen_interface = "0.0.0.0";
335 char *sttl, *sport; 331 char *sttl, *sport;
336 len_and_sockaddr *lsa; 332 len_and_sockaddr *lsa, *from, *to;
333 unsigned lsa_size;
337 int udps; 334 int udps;
338 uint16_t port = 53; 335 uint16_t port = 53;
339 uint8_t buf[MAX_PACK_LEN]; 336 /* Paranoid sizing: querystring x2 + ttl + outr_rlen + answstr */
337 /* I'd rather see process_packet() fixed instead... */
338 uint8_t buf[MAX_PACK_LEN * 2 + 4 + 2 + (MAX_NAME_LEN+1)];
340 339
341 getopt32(argv, "i:c:t:p:dv", &listen_interface, &fileconf, &sttl, &sport); 340 getopt32(argv, "i:c:t:p:dv", &listen_interface, &fileconf, &sttl, &sport);
342 //if (option_mask32 & 0x1) // -i 341 //if (option_mask32 & 0x1) // -i
@@ -375,32 +374,34 @@ int dnsd_main(int argc ATTRIBUTE_UNUSED, char **argv)
375 lsa = xdotted2sockaddr(listen_interface, port); 374 lsa = xdotted2sockaddr(listen_interface, port);
376 udps = xsocket(lsa->u.sa.sa_family, SOCK_DGRAM, 0); 375 udps = xsocket(lsa->u.sa.sa_family, SOCK_DGRAM, 0);
377 xbind(udps, &lsa->u.sa, lsa->len); 376 xbind(udps, &lsa->u.sa, lsa->len);
378 /* xlisten(udps, 50); - ?!! DGRAM sockets are never listened on I think? */ 377 socket_want_pktinfo(udps); /* needed for recv_from_to to work */
378 lsa_size = LSA_LEN_SIZE + lsa->len;
379 from = xzalloc(lsa_size);
380 to = xzalloc(lsa_size);
381
379 bb_info_msg("Accepting UDP packets on %s", 382 bb_info_msg("Accepting UDP packets on %s",
380 xmalloc_sockaddr2dotted(&lsa->u.sa)); 383 xmalloc_sockaddr2dotted(&lsa->u.sa));
381 384
382 while (1) { 385 while (1) {
383 int r; 386 int r;
384 socklen_t fromlen = lsa->len; 387 /* Try to get *DEST* address (to which of our addresses
385// FIXME: need to get *DEST* address (to which of our addresses 388 * this query was directed), and reply from the same address.
386// this query was directed), and reply from the same address. 389 * Or else we can exhibit usual UDP ugliness:
387// Or else we can exhibit usual UDP ugliness: 390 * [ip1.multihomed.ip2] <= query to ip1 <= peer
388// [ip1.multihomed.ip2] <= query to ip1 <= peer 391 * [ip1.multihomed.ip2] => reply from ip2 => peer (confused) */
389// [ip1.multihomed.ip2] => reply from ip2 => peer (confused) 392 memcpy(to, lsa, lsa_size);
390 393 r = recv_from_to(udps, buf, MAX_PACK_LEN + 1, 0, &from->u.sa, &to->u.sa, lsa->len);
391// TODO: recv_from_to 394 if (r < 12 || r > MAX_PACK_LEN) {
392
393 r = recvfrom(udps, buf, sizeof(buf), 0, &lsa->u.sa, &fromlen);
394 if (OPT_verbose)
395 bb_info_msg("Got UDP packet");
396 if (r < 12 || r > 512) {
397 bb_error_msg("invalid packet size"); 395 bb_error_msg("invalid packet size");
398 continue; 396 continue;
399 } 397 }
398 if (OPT_verbose)
399 bb_info_msg("Got UDP packet");
400 buf[r] = '\0'; /* paranoia */
400 r = process_packet(buf); 401 r = process_packet(buf);
401 if (r <= 0) 402 if (r <= 0)
402 continue; 403 continue;
403 sendto(udps, buf, r, 0, &lsa->u.sa, fromlen); 404 send_to_from(udps, buf, r, 0, &to->u.sa, &from->u.sa, lsa->len);
404 } 405 }
405 return 0; 406 return 0;
406} 407}