1/* dnsmasq is Copyright (c) 2000 - 2003 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. 6 7 This program is distributed in the hope that it will be useful, 8 but WITHOUT ANY WARRANTY; without even the implied warranty of 9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 GNU General Public License for more details. 11*/ 12 13/* Author's email: simon@thekelleys.org.uk */ 14 15#include "dnsmasq.h" 16 17/* foxconn wklin added start, 08/31/2007 @mpoe */ 18#ifdef MULTIPLE_PPPOE 19int mpoe = 0; /* for multiple wan, forward dns query to all ifs */ 20#endif /* MULTIPLE_PPPOE */ 21/* foxconn wklin added end, 08/31/2007 */ 22 23static struct frec *frec_list; 24 25static struct frec *get_new_frec(time_t now); 26static struct frec *lookup_frec(unsigned short id); 27static struct frec *lookup_frec_by_sender(unsigned short id, 28 union mysockaddr *addr); 29static unsigned short get_id(void); 30static void get_device_id(char src_mac[], char id[]); 31 32/* foxconn removed start by Jenny Zhao, 12/10/2008,@Russia_PPTP new spec*/ 33#if 0 34/* Foxconn added start, zacker, 07/29/2008,@Russia_PPTP */ 35extern keyword_t pptp_domain; 36extern Session2_DNS pptp_dhcp_dns_tbl; 37 38int is_pptp_dhcp_dns(unsigned long uiDNSIP) 39{ 40 int i; 41 42 for(i=0; i<pptp_dhcp_dns_tbl.iDNSCount; i++) 43 { 44 if(uiDNSIP == pptp_dhcp_dns_tbl.DNSEntry[i]) 45 { 46 return 1; 47 } 48 } 49 50 return 0; 51} 52 53int is_pptp_domain_matched(char *namebuff) 54{ 55 keyword_t *keyword=NULL; 56 int matched = 0; 57 58 if (!namebuff) 59 return matched; 60 61 for (keyword = &pptp_domain; keyword; keyword=keyword->next) 62 { 63 if (keyword->wildcard == 1) 64 { 65 char *p; 66 if (p=strcasestr(namebuff,keyword->name)) 67 { 68 if (*(p+strlen(keyword->name)) == '\0') 69 { 70 matched = 1; 71 fprintf(stderr, "wildcard matched %s\n", keyword->name); 72 break; 73 } 74 } 75 } 76 else if (strcasecmp(namebuff,keyword->name) == 0) 77 { 78 matched = 1; 79 fprintf(stderr, "matched %s\n", keyword->name); 80 break; 81 } 82 } 83 return matched; 84} 85/* Foxconn added end, zacker, 07/29/2008,@Russia_PPTP */ 86#endif 87/* foxconn removed end by Jenny Zhao, 12/10/2008,@Russia_PPTP new spec*/ 88 89/* foxconn wklin added start, 09/03/2007 @mpoe */ 90#ifdef MULTIPLE_PPPOE 91 92/* foxconn added start Bob Guo, 10/24/2007 */ 93 94extern Session2_DNS Session2_Dns_Tbl; 95 96int IsSession2DNS(unsigned long uiDNSIP) 97{ 98 int i; 99 100 for(i=0; i<Session2_Dns_Tbl.iDNSCount; i++) 101 { 102 if(uiDNSIP == Session2_Dns_Tbl.DNSEntry[i]) 103 { 104 return 1; 105 } 106 } 107 108 return 0; 109} 110 111int IsDomainKeywordMatched(char *namebuff) 112{ 113 extern keyword_t *keyword_list; 114 keyword_t *keyword=NULL; 115 int matched = 0; 116 117 if (!namebuff) 118 return matched; 119 for (keyword = keyword_list; keyword; keyword=keyword->next) 120 { 121 if (keyword->wildcard == 1) 122 { 123 char *p; 124 if (p=strcasestr(namebuff,keyword->name)) 125 { 126 if (*(p+strlen(keyword->name)) == '\0') 127 { 128 matched = 1; 129 fprintf(stderr, "wildcard matched %s\n", keyword->name); 130 break; 131 } 132 } 133 } 134 else if (strcasestr(namebuff,keyword->name)) 135 { 136 matched = 1; 137 fprintf(stderr, "matched %s\n", keyword->name); 138 break; 139 } 140 } 141 return matched; 142 143} 144/* foxconn added end Bob Guo, 10/24/2007 */ 145#if 0 146static void private_domain_check(HEADER *header, int n, char *namebuff) 147{ 148 extern void extract_set_addr(HEADER *, int); 149 150 if(IsDomainKeywordMatched(namebuff) == 1) 151 extract_set_addr(header, n); 152 153} 154#else 155#define MAX_QUERY_NAME 1500 156static void private_domain_check(HEADER *header, int n, char *namebuff) 157{ 158 char qryname[MAX_QUERY_NAME], *p; 159 int i, j=0; 160 extern void extract_set_addr(HEADER *, int); 161 162 if ( NULL == header ) 163 return; 164 p= (char *)header + sizeof(HEADER); 165 i = *p; 166 167 /* Find the domain name in questions area, and use this name to compare with the 168 keyword. weal @ March 4, 2008 */ 169 while (i && j < MAX_QUERY_NAME ){ 170 for(;i>0;i--){ 171 qryname[j++] = *(++p); 172 } 173 i = *(++p); 174 if (i) 175 qryname[j++] = '.'; 176 } 177 178 qryname[j++] = '\0'; 179 180 if(IsDomainKeywordMatched(qryname) == 1) 181 extract_set_addr(header, n); 182 183} 184#endif 185 186#endif /* MULTIPLE_PPPOE */ 187/* foxconn wklin added end, 09/03/2007 */ 188/* May be called more than once. */ 189void forward_init(int first) 190{ 191 struct frec *f; 192 193 if (first) 194 frec_list = NULL; 195 for (f = frec_list; f; f = f->next) 196 f->new_id = 0; 197} 198 199/* Send a UDP packet with it's source address set as "source" 200 unless nowild is true, when we just send it with the kernel default */ 201static void send_from(int fd, int nowild, char *packet, int len, 202 union mysockaddr *to, struct all_addr *source, 203 unsigned int iface) 204{ 205 struct msghdr msg; 206 struct iovec iov[1]; 207 union { 208 struct cmsghdr align; /* this ensures alignment */ 209#if defined(IP_PKTINFO) 210 char control[CMSG_SPACE(sizeof(struct in_pktinfo))]; 211#elif defined(IP_SENDSRCADDR) 212 char control[CMSG_SPACE(sizeof(struct in_addr))]; 213#endif 214#ifdef HAVE_IPV6 215 char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; 216#endif 217 } control_u; 218 219 iov[0].iov_base = packet; 220 iov[0].iov_len = len; 221 222 msg.msg_control = NULL; 223 msg.msg_controllen = 0; 224 msg.msg_flags = 0; 225 msg.msg_name = to; 226 msg.msg_namelen = sa_len(to); 227 msg.msg_iov = iov; 228 msg.msg_iovlen = 1; 229 230 if (!nowild && to->sa.sa_family == AF_INET) 231 { 232 msg.msg_control = &control_u; 233 msg.msg_controllen = sizeof(control_u); 234 { 235 struct cmsghdr *cmptr = CMSG_FIRSTHDR(&msg); 236#if defined(IP_PKTINFO) 237 238 struct in_pktinfo *pkt = (struct in_pktinfo *)CMSG_DATA(cmptr); 239 pkt->ipi_ifindex = 0; 240 pkt->ipi_spec_dst = source->addr.addr4; 241 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); 242 cmptr->cmsg_level = SOL_IP; 243 cmptr->cmsg_type = IP_PKTINFO; 244#elif defined(IP_SENDSRCADDR) 245 struct in_addr *a = (struct in_addr *)CMSG_DATA(cmptr); 246 *a = source->addr.addr4; 247 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); 248 cmptr->cmsg_level = IPPROTO_IP; 249 cmptr->cmsg_type = IP_SENDSRCADDR; 250#endif 251 } 252 } 253 254#ifdef HAVE_IPV6 255 if (to->sa.sa_family == AF_INET6) 256 { 257 msg.msg_control = &control_u; 258 msg.msg_controllen = sizeof(control_u); 259 { 260 struct cmsghdr *cmptr = CMSG_FIRSTHDR(&msg); 261 struct in6_pktinfo *pkt = (struct in6_pktinfo *)CMSG_DATA(cmptr); 262 pkt->ipi6_ifindex = iface; /* Need iface for IPv6 to handle link-local addrs */ 263 pkt->ipi6_addr = source->addr.addr6; 264 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 265 cmptr->cmsg_type = IPV6_PKTINFO; 266 cmptr->cmsg_level = IPV6_LEVEL; 267 } 268 } 269#endif 270 271 /* certain Linux kernels seem to object to setting the source address in the IPv6 stack 272 by returning EINVAL from sendmsg. In that case, try again without setting the 273 source address, since it will nearly alway be correct anyway. IPv6 stinks. */ 274 if (sendmsg(fd, &msg, 0) == -1 && errno == EINVAL) 275 { 276 msg.msg_controllen = 0; 277 sendmsg(fd, &msg, 0); 278 } 279} 280 281static unsigned short search_servers(struct daemon *daemon, time_t now, struct all_addr **addrpp, 282 unsigned short qtype, char *qdomain, int *type, char **domain) 283 284{ 285 /* If the query ends in the domain in one of our servers, set 286 domain to point to that name. We find the largest match to allow both 287 domain.org and sub.domain.org to exist. */ 288 289 unsigned int namelen = strlen(qdomain); 290 unsigned int matchlen = 0; 291 struct server *serv; 292 unsigned short flags = 0; 293 294 for (serv = daemon->servers; serv; serv=serv->next) 295 /* domain matches take priority over NODOTS matches */ 296 if ((serv->flags & SERV_FOR_NODOTS) && *type != SERV_HAS_DOMAIN && !strchr(qdomain, '.')) 297 { 298 unsigned short sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6; 299 *type = SERV_FOR_NODOTS; 300 if (serv->flags & SERV_NO_ADDR) 301 flags = F_NXDOMAIN; 302 else if (serv->flags & SERV_LITERAL_ADDRESS) 303 { 304 if (sflag & qtype) 305 { 306 flags = sflag; 307 if (serv->addr.sa.sa_family == AF_INET) 308 *addrpp = (struct all_addr *)&serv->addr.in.sin_addr; 309#ifdef HAVE_IPV6 310 else 311 *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr; 312#endif 313 } 314 else if (!flags) 315 flags = F_NOERR; 316 } 317 } 318 else if (serv->flags & SERV_HAS_DOMAIN) 319 { 320 unsigned int domainlen = strlen(serv->domain); 321 if (namelen >= domainlen && 322 hostname_isequal(qdomain + namelen - domainlen, serv->domain) && 323 domainlen >= matchlen) 324 { 325 unsigned short sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6; 326 *type = SERV_HAS_DOMAIN; 327 *domain = serv->domain; 328 matchlen = domainlen; 329 if (serv->flags & SERV_NO_ADDR) 330 flags = F_NXDOMAIN; 331 else if (serv->flags & SERV_LITERAL_ADDRESS) 332 { 333 if ((sflag | F_QUERY ) & qtype) 334 { 335 flags = qtype; 336 if (serv->addr.sa.sa_family == AF_INET) 337 *addrpp = (struct all_addr *)&serv->addr.in.sin_addr; 338#ifdef HAVE_IPV6 339 else 340 *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr; 341#endif 342 } 343 else if (!flags) 344 flags = F_NOERR; 345 } 346 } 347 } 348 349 if (flags & ~(F_NOERR | F_NXDOMAIN)) /* flags set here means a literal found */ 350 { 351 if (flags & F_QUERY) 352 log_query(F_CONFIG | F_FORWARD | F_NEG, qdomain, NULL, 0); 353 else 354 log_query(F_CONFIG | F_FORWARD | flags, qdomain, *addrpp, 0); 355 } 356 else if (qtype && (daemon->options & OPT_NODOTS_LOCAL) && !strchr(qdomain, '.')) 357 flags = F_NXDOMAIN; 358 359 if (flags == F_NXDOMAIN && check_for_local_domain(qdomain, now, daemon->mxnames)) 360 flags = F_NOERR; 361 362 if (flags == F_NXDOMAIN || flags == F_NOERR) 363 log_query(F_CONFIG | F_FORWARD | F_NEG | qtype | (flags & F_NXDOMAIN), qdomain, NULL, 0); 364 365 return flags; 366} 367 368/* Foxconn add start, Tony W.Y. Wang, 12/02/2008, @Parental Control OpenDNS */ 369#ifdef OPENDNS_PARENTAL_CONTROL 370#define HTONS_CHARS(n) (unsigned char)((n) >> 8), (unsigned char)(n) 371 372static int add_device_id(struct daemon *daemon, HEADER *header, size_t plen, unsigned char *pheader, 373 size_t pheader_len, struct frec *forward) 374{ 375 const unsigned char clientid[11] = { HTONS_CHARS(4), HTONS_CHARS(15), 376 'O', 'p', 'e', 'n', 'D', 'N', 'S' }; 377 const unsigned char fixed[11] = { 0, HTONS_CHARS(T_OPT), 378 HTONS_CHARS(PACKETSZ), 379 0, 0, 0, 0, HTONS_CHARS(0) }; 380 const int option_len = sizeof(clientid) + sizeof(daemon->device_id); 381 unsigned char *p = (unsigned char *)header; 382 unsigned short rdlen; 383 384 if ((pheader == NULL && plen + sizeof(fixed) + option_len <= PACKETSZ) 385 || (pheader != NULL && pheader + pheader_len == p + plen 386 && plen + option_len <= PACKETSZ)) 387 { 388 if (pheader == NULL) 389 { 390 pheader = p + plen; 391 memcpy(p + plen, fixed, sizeof(fixed)); 392 plen += sizeof(fixed); 393 header->arcount = htons(ntohs(header->arcount) + 1); 394 /* Since the client didn't send a pseudoheader, it won't be 395 expecting one in the response. */ 396 forward->discard_pseudoheader = 1; 397#ifdef USE_SYSLOG 398 if (daemon->options & OPT_LOG) 399 my_syslog(LOG_DEBUG, "pseudoheader added"); 400#endif 401 } 402 /* Append a CLIENTID option to the pseudoheader. */ 403 memcpy(p + plen, clientid, sizeof(clientid)); 404 plen += sizeof(clientid); 405 memcpy(p + plen, daemon->device_id, 406 sizeof(daemon->device_id)); 407 plen += sizeof(daemon->device_id); 408 /* Update the pseudoheader's RDLEN field. */ 409 p = pheader + 9; 410 GETSHORT(rdlen, p); 411 p = pheader + 9; 412 PUTSHORT(rdlen + option_len, p); 413#ifdef USE_SYSLOG 414 if (daemon->options & OPT_LOG) 415 my_syslog(LOG_DEBUG, "device ID added"); 416#endif 417 } 418 return plen; 419} 420#endif 421/* Foxconn add end , Tony W.Y. Wang, 12/02/2008, @Parental Control OpenDNS */ 422 423//#define QUERY_DEBUG 1 /* Michael */ 424 425/* returns new last_server */ 426static void forward_query(struct daemon *daemon, int udpfd, union mysockaddr *udpaddr, 427 struct all_addr *dst_addr, unsigned int dst_iface, 428 HEADER *header, size_t plen, time_t now, struct frec *forward) 429{ 430 //struct frec *forward; /* Foxconn removed by EricHuang, 12/28/2007 */ 431 char *domain = NULL; 432 int forwardall = 0, type = 0; 433 struct all_addr *addrp = NULL; 434 unsigned short flags = 0; 435 unsigned short gotname = extract_request(header, (unsigned int)plen, daemon->namebuff, NULL); 436 struct server *start = NULL; 437 438 /* Foxconn, add by MJ., for clarifying this issue. 2011.07.04 */ 439#ifdef QUERY_DEBUG 440 printf("\n\n%s: sent from %s\n", __FUNCTION__, inet_ntoa(udpaddr->in.sin_addr)); 441 if(udpaddr->sa.sa_family == AF_INET) 442 printf("A query from IPv4.\n"); 443 else 444 printf("A query from IPv6.\n"); 445#endif 446 /* Foxconn, add-end by MJ., for clarifying this issue. 2011.07.04 */ 447 448 /* Foxconn add start, Tony W.Y. Wang, 12/05/2008, @Parental Control OpenDNS */ 449#ifdef OPENDNS_PARENTAL_CONTROL 450 FILE *fp; 451 char flag; 452 char dnsquery_src_mac[20] = ""; 453 char device_id[32] = ""; 454 if((fp = fopen("/tmp/opendns.flag", "r"))) 455 { 456 flag = fgetc(fp); 457 fclose(fp); 458 } 459 daemon->have_device_id = 0; 460 if(flag == '1') /* Parental Control Enabled */ 461 { 462 get_mac_from_arp(inet_ntoa(udpaddr->in.sin_addr), dnsquery_src_mac); /* Get MAC Address from ARP according to Soure IP */ 463 get_device_id(dnsquery_src_mac, device_id); 464 daemon->have_device_id = 1; 465 if(char_to_byte(device_id, daemon->device_id)) 466 return; 467 } 468#endif 469 /* Foxconn add end , Tony W.Y. Wang, 12/05/2008, @Parental Control OpenDNS */ 470#ifdef MULTIPLE_PPPOE 471 int iToSession2, iIsSession2DNS; 472 473 iToSession2 = IsDomainKeywordMatched(daemon->namebuff); 474 /* if (mpoe == 1) */ /* Foxconn modified, zacker, 07/29/2008 */ 475 if (mpoe == 1 && forward) 476 forward->forwardall = 1; //forwardall = 1; /* Foxconn modified by EricHuang, 01/02/2008 */ 477 478#endif 479/* foxconn removed start by Jenny Zhao, 12/10/2008,@Russia_PPTP new spec*/ 480#if 0 481 /* Foxconn added start, zacker, 07/29/2008,@Russia_PPTP */ 482 int iToDhcpDNS, iIsDhcpDNS; 483 iToDhcpDNS = is_pptp_domain_matched(daemon->namebuff); 484 /* Foxconn added end, zacker, 07/29/2008,@Russia_PPTP */ 485#endif 486/* foxconn removed end by Jenny Zhao, 12/10/2008,@Russia_PPTP new spec*/ 487 488 /* may be recursion not speced or no servers available. */ 489 if (!header->rd || !daemon->servers) 490 forward = NULL; 491 /* Foxconn modified , Tony W.Y. Wang, 12/11/2008, @Parental Control OpenDNS to add device id in every DNS Query */ 492#ifdef OPENDNS_PARENTAL_CONTROL 493 else if ( (forward || (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr))) && (flag != '1')) /* Foxconn modified by EricHuang, 01/02/2008 */ 494#else 495 else if ( forward || (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr))) /* Foxconn modified by EricHuang, 01/02/2008 */ 496#endif 497 { 498 /* retry on existing query, send to all available servers */ 499 domain = forward->sentto->domain; 500 if (!(daemon->options & OPT_ORDER)) 501 { 502 forward->forwardall = 1; //forwardall = 1; /* Foxconn modified by EricHuang, 01/02/2008 */ 503 daemon->last_server = NULL; 504 } 505 type = forward->sentto->flags & SERV_TYPE; 506 if (!(start = forward->sentto->next)) 507 start = daemon->servers; /* at end of list, recycle */ 508 header->id = htons(forward->new_id); 509 } 510 else 511 { 512 if (gotname) 513 flags = search_servers(daemon, now, &addrp, gotname, daemon->namebuff, &type, &domain); 514 515 if (!flags && !(forward = get_new_frec(now))) 516 /* table full - server failure. */ 517 flags = F_NEG; 518 519 if (forward) 520 { 521 /* Foxconn add start, Tony W.Y. Wang, 12/02/2008, @Parental Control OpenDNS */ 522#ifdef OPENDNS_PARENTAL_CONTROL 523 size_t pheader_len; 524 unsigned char *pheader; 525 pheader = find_pseudoheader(header, plen, &pheader_len, NULL); 526#endif 527 /* Foxconn add end , Tony W.Y. Wang, 12/02/2008, @Parental Control OpenDNS */ 528 /* Foxconn moved start by EricHuang, 01/02/2008 */ 529 /* foxconn added start Bob, 07/15/2011, check NULL pointer */ 530 if(udpaddr==NULL) 531 { 532 return; 533 } 534 /* foxconn added end Bob, 07/15/2011, check NULL pointer */ 535 forward->source = *udpaddr; 536 forward->dest = *dst_addr; 537 forward->iface = dst_iface; 538 forward->new_id = get_id(); 539 forward->fd = udpfd; 540 forward->orig_id = ntohs(header->id); 541 forward->forwardall = 0; /* Foxconn added by EricHuang, 01/02/2007 */ 542#ifdef OPENDNS_PARENTAL_CONTROL 543 forward->discard_pseudoheader = 0; /* Foxconn add, Tony W.Y. Wang, 12/02/2008, @Parental Control OpenDNS */ 544#endif 545 header->id = htons(forward->new_id); 546 /* Foxconn moved start by EricHuang, 01/02/2008 */ 547 548 /* In strict_order mode, or when using domain specific servers 549 always try servers in the order specified in resolv.conf, 550 otherwise, use the one last known to work. */ 551 552 if (type != 0 || (daemon->options & OPT_ORDER)) 553 start = daemon->servers; 554 else if (!(start = daemon->last_server)) 555 { 556 start = daemon->servers; 557 forward->forwardall = 1; //forwardall = 1; /* Foxconn modified by EricHuang, 01/02/2007 */ 558 } 559 /* Foxconn add start, Tony W.Y. Wang, 12/02/2008, @Parental Control OpenDNS */ 560#ifdef OPENDNS_PARENTAL_CONTROL 561 if (daemon->have_device_id) 562 plen = add_device_id(daemon, header, plen, pheader, pheader_len, forward); 563#endif 564 /* Foxconn add end , Tony W.Y. Wang, 12/02/2008, @Parental Control OpenDNS */ 565 /* 566 forward->source = *udpaddr; 567 forward->dest = *dst_addr; 568 forward->iface = dst_iface; 569 forward->new_id = get_id(); 570 forward->fd = udpfd; 571 forward->orig_id = ntohs(header->id); 572 header->id = htons(forward->new_id); 573 */ 574 } 575 } 576 577 /* check for send errors here (no route to host) 578 if we fail to send to all nameservers, send back an error 579 packet straight away (helps modem users when offline) */ 580 581 if (!flags && forward) 582 { 583 struct server *firstsentto = start; 584 int forwarded = 0; 585 /* Foxconn add start, Max Ding, 07/06/2011 */ 586 /* According to spec: 587 * When the DNS query includes the type of AAAA or A6, 588 * if there is a DNS server configured with an IPv6 address, 589 * forward the query to the IPv6 DNS server. If there is 590 * no DNS server configured with an IPv6 address or the 591 * query fails to get an answer from the IPv6 DNS server (e.g. timeout, error...), 592 * forward the query to the IPv4 DNS server configured. 593 * 594 * "query fail case" is to be implemented. 595 */ 596 unsigned short sflag = 0; 597 int second_try = 0; 598 /* Foxconn add end, Max Ding, 07/06/2011 */ 599 600 while (1) 601 { 602 /* only send to servers dealing with our domain. 603 domain may be NULL, in which case server->domain 604 must be NULL also. */ 605 sflag = (start->addr.sa.sa_family == AF_INET) ? F_IPV4 : F_IPV6;/* Foxconn added by Max Ding, 07/06/2011 */ 606 607 if (type == (start->flags & SERV_TYPE) && 608 ((gotname & F_QUERY) || (sflag & gotname)) &&/* Foxconn added by Max Ding, 07/06/2011 */ 609 (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain))) 610 { 611#ifdef MULTIPLE_PPPOE 612 char *pdnsServer; 613 struct sockaddr_in *p; 614 int iSendResult = 0; 615 616#if 0 617 /* Foxconn, add by MJ., 2011.07.05 */ 618 /* We don't forward a ipv4 query packets to DNS server with ipv6 619 * address, vice versa*/ 620 if(udpaddr) /* foxconn added Bob, 07/15/2011, check NULL pointer */ 621 { 622 if(!(start->flags & SERV_LITERAL_ADDRESS) && (start->addr.sa.sa_family != udpaddr->sa.sa_family) ) 623 { 624 //printf("=> don't forward this query.\n"); 625 goto try_next_server; 626 } 627 } 628 /* Foxconn, add-end by MJ., 2011.07.05 */ 629#endif 630 631 p = (struct sockaddr_in *)&(start->addr.sa); 632 pdnsServer = inet_ntoa(p->sin_addr); 633 iIsSession2DNS = IsSession2DNS(p->sin_addr.s_addr); 634 635 if(iIsSession2DNS == iToSession2) 636 { 637 iSendResult = sendto(start->sfd->fd, (char *)header, plen, 0, &start->addr.sa, sa_len(&start->addr)); 638 } 639 if (!(start->flags & SERV_LITERAL_ADDRESS) && iSendResult != -1) 640#else 641 642 643/* foxconn modified start by Jenny Zhao, 12/10/2008,@Russia_PPTP new spec*/ 644#if 0 645 /* Foxconn, add by MJ., 2011.07.05 */ 646 /* We don't forward a ipv4 query packets to DNS server with ipv6 address, vice versa*/ 647 if(!(start->flags & SERV_LITERAL_ADDRESS) && (start->addr.sa.sa_family != udpaddr->sa.sa_family) ){ 648 //printf("=> don't forward this query 2.\n"); 649 goto try_next_server; 650 } 651 /* Foxconn, add-end by MJ., 2011.07.05 */ 652#endif 653 /* Foxconn modified start, zacker, 07/29/2008,@Russia_PPTP */ 654 if (!(start->flags & SERV_LITERAL_ADDRESS) && 655 sendto(start->sfd->fd, (char *)header, plen, 0, 656 &start->addr.sa, 657 sa_len(&start->addr)) != -1) 658#if 0 659 char *pdnsServer; 660 struct sockaddr_in *p; 661 int iSendResult = 0; 662 p = (struct sockaddr_in *)&(start->addr.sa); 663 pdnsServer = inet_ntoa(p->sin_addr); 664 iIsDhcpDNS = is_pptp_dhcp_dns(p->sin_addr.s_addr); 665 666 if(iIsDhcpDNS == iToDhcpDNS) 667 { 668 iSendResult = sendto(start->sfd->fd, (char *)header, plen, 0, &start->addr.sa, sa_len(&start->addr)); 669 } 670 if (!(start->flags & SERV_LITERAL_ADDRESS) && iSendResult != -1) 671 /* Foxconn modified end, zacker, 07/29/2008,@Russia_PPTP */ 672#endif 673/* foxconn modified end by Jenny Zhao, 12/10/2008,@Russia_PPTP new spec*/ 674#endif /* MULTIPLE_PPPOE */ 675 { 676 677 /* Foxconn, add by MJ., for clarifying this issue. */ 678#ifdef QUERY_DEBUG 679 char *pdnsServer; 680 struct sockaddr_in *p; 681 682 p = (struct sockaddr_in *)&(start->addr.sa); 683 pdnsServer = inet_ntoa(p->sin_addr); 684 printf("\nsend to %s\n", pdnsServer); 685 if (start->addr.sa.sa_family == AF_INET) 686 printf("DNS server is using an IPv4 address.\n"); 687 else 688 printf("DNS server is using an IPv6 address.\n"); 689#endif 690 /* Foxconn, add-end by MJ., for clarifying this issue. */ 691 692 693 694 if (!gotname) 695 strcpy(daemon->namebuff, "query"); 696 if (start->addr.sa.sa_family == AF_INET) 697 log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff, 698 (struct all_addr *)&start->addr.in.sin_addr, 0); 699#ifdef HAVE_IPV6 700 else 701 log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff, 702 (struct all_addr *)&start->addr.in6.sin6_addr, 0); 703#endif 704 forwarded = 1; 705 forward->sentto = start; 706 //if (!forwardall) 707 if (!forward->forwardall) /* Foxconn modified by EricHuang, 01/02/2008 */ 708 break; 709 710 forward->forwardall++; /* Foxconn added by EricHuang, 01/02/2008 */ 711 }/* Sento */ 712 } /* check if server is legal */ 713 714try_next_server: 715 if (!(start = start->next)) 716 start = daemon->servers; 717 718 if (start == firstsentto) 719 { 720 /* Foxconn add start, Max Ding, 07/06/2011 */ 721 /* According to Home Router Spec IPv6 part: 722 * if there is no DNS server configured with an IPv6 address, 723 * forward the query to the IPv4 DNS server configured. 724 * if there is no DNS server configured with an IPv4 address, 725 * forward the query to the IPv6 DNS server configured. 726 */ 727 if ((second_try == 0) && (forwarded == 0)) 728 { 729 if ((gotname & F_IPV4) && !(gotname & F_IPV6)) 730 { 731 gotname = F_IPV6; 732 second_try = 1; 733 continue; 734 } 735 else if ((gotname & F_IPV6) && !(gotname & F_IPV4)) 736 { 737 gotname = F_IPV4; 738 second_try = 1; 739 continue; 740 } 741 } 742 break; 743 } 744 }/* End of while(1) */ 745 746 if (forwarded) 747 return; 748 749 /* could not send on, prepare to return */ 750 header->id = htons(forward->orig_id); 751 forward->new_id = 0; /* cancel */ 752 } 753 754 /* could not send on, return empty answer or address if known for whole domain */ 755 plen = setup_reply(header, (unsigned int)plen, addrp, flags, daemon->local_ttl); 756 if( udpaddr && dst_addr) 757 { 758 send_from(udpfd, daemon->options & OPT_NOWILD, (char *)header, plen, udpaddr, dst_addr, dst_iface); 759 } 760 761 return; 762} 763 764/* Foxconn modified, Tony W.Y. Wang, 12/02/2008, @Parental Control OpenDNS */ 765#ifdef OPENDNS_PARENTAL_CONTROL 766static int process_reply(struct daemon *daemon, HEADER *header, time_t now, 767 union mysockaddr *serveraddr, unsigned int n, int discard_pseudoheader) 768#else 769static int process_reply(struct daemon *daemon, HEADER *header, time_t now, 770 union mysockaddr *serveraddr, unsigned int n) 771#endif 772{ 773 unsigned char *pheader, *sizep; 774 unsigned int plen; 775 776 /* If upstream is advertising a larger UDP packet size 777 than we allow, trim it so that we don't get overlarge 778 requests for the client. */ 779 780 if ((pheader = find_pseudoheader(header, n, &plen, &sizep))) 781 { 782 unsigned short udpsz; 783 unsigned char *psave = sizep; 784 785 GETSHORT(udpsz, sizep); 786 if (udpsz > daemon->edns_pktsz) 787 PUTSHORT(daemon->edns_pktsz, psave); 788 /* Foxconn add start, Tony W.Y. Wang, 12/02/2008, @Parental Control OpenDNS */ 789#ifdef OPENDNS_PARENTAL_CONTROL 790 if (discard_pseudoheader 791 && pheader + plen == (unsigned char *)header + n) 792 { 793 header->arcount = htons(ntohs(header->arcount) - 1); 794 n -= plen; 795 pheader = NULL; 796 } 797#endif 798 /* Foxconn add end , Tony W.Y. Wang, 12/02/2008, @Parental Control OpenDNS */ 799 } 800 801 /* Complain loudly if the upstream server is non-recursive. */ 802 if (!header->ra && header->rcode == NOERROR && ntohs(header->ancount) == 0) 803 { 804 char addrbuff[ADDRSTRLEN]; 805#ifdef HAVE_IPV6 806 if (serveraddr->sa.sa_family == AF_INET) 807 inet_ntop(AF_INET, &serveraddr->in.sin_addr, addrbuff, ADDRSTRLEN); 808 else if (serveraddr->sa.sa_family == AF_INET6) 809 inet_ntop(AF_INET6, &serveraddr->in6.sin6_addr, addrbuff, ADDRSTRLEN); 810#else 811 strcpy(addrbuff, inet_ntoa(serveraddr->in.sin_addr)); 812#endif 813#ifdef USE_SYSLOG /* foxconn wklin added, 08/13/2007 */ 814 syslog(LOG_WARNING, "nameserver %s refused to do a recursive query", addrbuff); 815#endif 816 return 0; 817 } 818 819 if (header->opcode != QUERY || (header->rcode != NOERROR && header->rcode != NXDOMAIN)) 820 return n; 821 822 if (header->rcode == NOERROR && ntohs(header->ancount) != 0) 823 { 824 if (!(daemon->bogus_addr && 825 check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now))) 826 extract_addresses(header, n, daemon->namebuff, now, daemon->doctors); 827 } 828 else 829 { 830 unsigned short flags = F_NEG; 831 int munged = 0; 832 833 if (header->rcode == NXDOMAIN) 834 { 835 /* if we forwarded a query for a locally known name (because it was for 836 an unknown type) and the answer is NXDOMAIN, convert that to NODATA, 837 since we know that the domain exists, even if upstream doesn't */ 838 if (extract_request(header, n, daemon->namebuff, NULL) && 839 check_for_local_domain(daemon->namebuff, now, daemon->mxnames)) 840 { 841 munged = 1; 842 header->rcode = NOERROR; 843 } 844 else 845 flags |= F_NXDOMAIN; 846 } 847 848 if (!(daemon->options & OPT_NO_NEG)) 849 extract_neg_addrs(header, n, daemon->namebuff, now, flags); 850 851 /* do this after extract_neg_addrs. Ensure NODATA reply and remove 852 nameserver info. */ 853 if (munged) 854 { 855 header->ancount = htons(0); 856 header->nscount = htons(0); 857 header->arcount = htons(0); 858 } 859 } 860 861 /* the bogus-nxdomain stuff, doctor and NXDOMAIN->NODATA munging can all elide 862 sections of the packet. Find the new length here and put back pseudoheader 863 if it was removed. */ 864 return resize_packet(header, n, pheader, plen); 865} 866 867/* sets new last_server */ 868void reply_query(struct serverfd *sfd, struct daemon *daemon, time_t now) 869{ 870 /* packet from peer server, extract data for cache, and send to 871 original requester */ 872 struct frec *forward; 873 HEADER *header; 874 union mysockaddr serveraddr; 875 socklen_t addrlen = sizeof(serveraddr); 876 int n = recvfrom(sfd->fd, daemon->packet, daemon->edns_pktsz, 0, &serveraddr.sa, &addrlen); 877 size_t nn; 878 879 /* Foxconn add start, Tony W.Y. Wang, 07/09/2010, @Parental Control OpenDNS */ 880#ifdef OPENDNS_PARENTAL_CONTROL 881 FILE *fp; 882 char flag; 883 if((fp = fopen("/tmp/opendns.flag", "r"))) 884 { 885 flag = fgetc(fp); 886 fclose(fp); 887 } 888#endif 889 /* Foxconn add start, Tony W.Y. Wang, 07/09/2010, @Parental Control OpenDNS */ 890 /* Determine the address of the server replying so that we can mark that as good */ 891 serveraddr.sa.sa_family = sfd->source_addr.sa.sa_family; 892#ifdef HAVE_IPV6 893 if (serveraddr.sa.sa_family == AF_INET6) 894 serveraddr.in6.sin6_flowinfo = htonl(0); 895#endif 896 897 header = (HEADER *)daemon->packet; 898 forward = lookup_frec(ntohs(header->id)); /* Foxconn added by EricHuang, 01/02/2008 */ 899 900 if (n >= (int)sizeof(HEADER) && header->qr && forward) 901 { 902 /* Foxconn added start by EricHuang, 01/02/2008 */ 903 struct server *server = forward->sentto; 904 /* Foxconn add start, Tony W.Y. Wang, 07/09/2010 */ 905#ifdef OPENDNS_PARENTAL_CONTROL 906 if ((header->rcode == SERVFAIL || header->rcode == REFUSED) && forward->forwardall == 0 && (flag != '1')) 907#else 908 if ((header->rcode == SERVFAIL || header->rcode == REFUSED) && forward->forwardall == 0) 909#endif 910 /* Foxconn add end, Tony W.Y. Wang, 07/09/2010 */ 911 /* for broken servers, attempt to send to another one. */ 912 { 913 unsigned char *pheader; 914 size_t plen; 915 916 /* recreate query from reply */ 917 pheader = find_pseudoheader(header, (size_t)n, &plen, NULL); 918 header->ancount = htons(0); 919 header->nscount = htons(0); 920 header->arcount = htons(0); 921 if ((nn = resize_packet(header, (size_t)n, pheader, plen))) 922 { 923 forward->forwardall = 1; 924 header->qr = 0; 925 header->tc = 0; 926 forward_query(daemon, -1, NULL, NULL, 0, header, nn, now, forward); 927 return; 928 } 929 } 930 /* Foxconn added end by EricHuang, 01/02/2008 */ 931 932 933 /* find good server by address if possible, otherwise assume the last one we sent to */ 934 if ((forward->sentto->flags & SERV_TYPE) == 0) 935 { 936 937 if (header->rcode == SERVFAIL || header->rcode == REFUSED) 938 server = NULL; 939 else 940 { 941 struct server *last_server; 942 /* find good server by address if possible, otherwise assume the last one we sent to */ 943 for (last_server = daemon->servers; last_server; last_server = last_server->next) 944 if (!(last_server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR)) && 945 sockaddr_isequal(&last_server->addr, &serveraddr)) 946 { 947 server = last_server; 948 break; 949 } 950 } 951 daemon->last_server = server; 952 953 } 954 955 956 /* If the answer is an error, keep the forward record in place in case 957 we get a good reply from another server. Kill it when we've 958 had replies from all to avoid filling the forwarding table when 959 everything is broken */ 960 if (forward->forwardall == 0 || --forward->forwardall == 1 || 961 (header->rcode != REFUSED && header->rcode != SERVFAIL)) 962 { 963#ifdef OPENDNS_PARENTAL_CONTROL 964 if ((nn = process_reply(daemon, header, now, &server->addr, (size_t)n, 965 forward->discard_pseudoheader))) /* Foxconn modified, Tony W.Y. Wang, 12/02/2008, @Parental Control OpenDNS */ 966#else 967 if ((nn = process_reply(daemon, header, now, &server->addr, (size_t)n))) 968#endif 969 { 970 /* foxconn wklin added start, 09/03/2007 @mpoe */ 971#ifdef MULTIPLE_PPPOE 972 private_domain_check(header, n, daemon->namebuff); 973#endif /* MULTIPLE_PPPOE */ 974 /* foxconn wklin added end, 09/03/2007 */ 975 976 header->id = htons(forward->orig_id); 977 header->ra = 1; /* recursion if available */ 978 send_from(forward->fd, daemon->options & OPT_NOWILD, daemon->packet, nn, 979 &forward->source, &forward->dest, forward->iface); 980 } 981 forward->new_id = 0; /* cancel */ 982 } 983 } 984} 985 986void receive_query(struct listener *listen, struct daemon *daemon, time_t now) 987{ 988 HEADER *header = (HEADER *)daemon->packet; 989 union mysockaddr source_addr; 990 unsigned short type; 991 struct iname *tmp; 992 struct all_addr dst_addr; 993 int check_dst = !(daemon->options & OPT_NOWILD); 994 int m, n, if_index = 0; 995 struct iovec iov[1]; 996 struct msghdr msg; 997 struct cmsghdr *cmptr; 998 union { 999 struct cmsghdr align; /* this ensures alignment */ 1000#ifdef HAVE_IPV6 1001 char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; 1002#endif 1003#if defined(IP_PKTINFO) 1004 char control[CMSG_SPACE(sizeof(struct in_pktinfo))]; 1005#elif defined(IP_RECVDSTADDR) 1006 char control[CMSG_SPACE(sizeof(struct in_addr)) + 1007 CMSG_SPACE(sizeof(struct sockaddr_dl))]; 1008#endif 1009 } control_u; 1010 1011 iov[0].iov_base = daemon->packet; 1012 iov[0].iov_len = daemon->edns_pktsz; 1013 1014 msg.msg_control = control_u.control; 1015 msg.msg_controllen = sizeof(control_u); 1016 msg.msg_flags = 0; 1017 msg.msg_name = &source_addr; 1018 msg.msg_namelen = sizeof(source_addr); 1019 msg.msg_iov = iov; 1020 msg.msg_iovlen = 1; 1021 1022 if ((n = recvmsg(listen->fd, &msg, 0)) == -1) 1023 return; 1024 1025 /* wklin modified start, 01/24/2007 */ 1026 /* Before getting dns IPs from ISP, dnsmasq will reject the 1027 * queries from clients, and client will thus think the dns queries 1028 * fails. When DoD is on, the first Internet access will always fail. 1029 * Modified the code here after the packet is consumed, so that the 1030 * dnsmasq won't reject the queries. 1031 */ 1032 if (!daemon->servers) 1033 return; 1034 /* wklin modified end, 01/24/2007 */ 1035 1036 source_addr.sa.sa_family = listen->family; 1037#ifdef HAVE_IPV6 1038 if (listen->family == AF_INET6) 1039 { 1040 check_dst = 1; 1041 source_addr.in6.sin6_flowinfo = htonl(0); 1042 } 1043#endif 1044 1045 if (check_dst && msg.msg_controllen < sizeof(struct cmsghdr)) 1046 return; 1047 1048#if defined(IP_PKTINFO) 1049 if (check_dst && listen->family == AF_INET) 1050 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) 1051 if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO) 1052 { 1053 dst_addr.addr.addr4 = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_spec_dst; 1054 if_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex; 1055 } 1056#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF) 1057 if (check_dst && listen->family == AF_INET) 1058 { 1059 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) 1060 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR) 1061 dst_addr.addr.addr4 = *((struct in_addr *)CMSG_DATA(cmptr)); 1062 else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF) 1063 if_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index; 1064 } 1065#endif 1066 1067#ifdef HAVE_IPV6 1068 if (listen->family == AF_INET6) 1069 { 1070 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) 1071 if (cmptr->cmsg_level == IPV6_LEVEL && cmptr->cmsg_type == IPV6_PKTINFO) 1072 { 1073 dst_addr.addr.addr6 = ((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_addr; 1074 if_index =((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_ifindex; 1075 } 1076 } 1077#endif 1078 1079 if (n < (int)sizeof(HEADER) || header->qr) 1080 return; 1081 1082 /* enforce available interface configuration */ 1083 if (check_dst) 1084 { 1085 struct ifreq ifr; 1086 1087 if (if_index == 0) 1088 return; 1089 1090 if (daemon->if_except || daemon->if_names) 1091 { 1092#ifdef SIOCGIFNAME 1093 ifr.ifr_ifindex = if_index; 1094 if (ioctl(listen->fd, SIOCGIFNAME, &ifr) == -1) 1095 return; 1096#else 1097 if (!if_indextoname(if_index, ifr.ifr_name)) 1098 return; 1099#endif 1100 } 1101 1102 for (tmp = daemon->if_except; tmp; tmp = tmp->next) 1103 if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0)) 1104 return; 1105 1106 if (daemon->if_names || daemon->if_addrs) 1107 { 1108 for (tmp = daemon->if_names; tmp; tmp = tmp->next) 1109 if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0)) 1110 break; 1111 if (!tmp) 1112 for (tmp = daemon->if_addrs; tmp; tmp = tmp->next) 1113 if (tmp->addr.sa.sa_family == listen->family) 1114 { 1115 if (tmp->addr.sa.sa_family == AF_INET && 1116 tmp->addr.in.sin_addr.s_addr == dst_addr.addr.addr4.s_addr) 1117 break; 1118#ifdef HAVE_IPV6 1119 else if (tmp->addr.sa.sa_family == AF_INET6 && 1120 memcmp(&tmp->addr.in6.sin6_addr, 1121 &dst_addr.addr.addr6, 1122 sizeof(struct in6_addr)) == 0) 1123 break; 1124#endif 1125 } 1126 if (!tmp) 1127 return; 1128 } 1129 } 1130 1131 if (extract_request(header, (unsigned int)n, daemon->namebuff, &type)) 1132 { 1133 if (listen->family == AF_INET) 1134 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, 1135 (struct all_addr *)&source_addr.in.sin_addr, type); 1136#ifdef HAVE_IPV6 1137 else 1138 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff, 1139 (struct all_addr *)&source_addr.in6.sin6_addr, type); 1140#endif 1141 } 1142 1143 m = answer_request (header, ((char *) header) + PACKETSZ, (unsigned int)n, daemon, now); 1144 if (m >= 1) 1145 send_from(listen->fd, daemon->options & OPT_NOWILD, (char *)header, m, &source_addr, &dst_addr, if_index); 1146 else 1147 forward_query(daemon, listen->fd, &source_addr, &dst_addr, if_index, 1148 header, n, now, NULL); /* Foxconn modified by EricHuang, 01/02/2008 */ 1149} 1150 1151static int read_write(int fd, char *packet, int size, int rw) 1152{ 1153 int n, done; 1154 1155 for (done = 0; done < size; done += n) 1156 { 1157 retry: 1158 if (rw) 1159 n = read(fd, &packet[done], (size_t)(size - done)); 1160 else 1161 n = write(fd, &packet[done], (size_t)(size - done)); 1162 1163 if (n == 0) 1164 return 0; 1165 else if (n == -1) 1166 { 1167 if (errno == EINTR) 1168 goto retry; 1169 else if (errno == EAGAIN) 1170 { 1171 struct timespec waiter; 1172 waiter.tv_sec = 0; 1173 waiter.tv_nsec = 10000; 1174 nanosleep(&waiter, NULL); 1175 goto retry; 1176 } 1177 else 1178 return 0; 1179 } 1180 } 1181 return 1; 1182} 1183 1184/* The daemon forks before calling this: it should deal with one connection, 1185 blocking as neccessary, and then return. Note, need to be a bit careful 1186 about resources for debug mode, when the fork is suppressed: that's 1187 done by the caller. */ 1188char *tcp_request(struct daemon *daemon, int confd, time_t now) 1189{ 1190 int size = 0, m; 1191 unsigned short qtype, gotname; 1192 unsigned char c1, c2; 1193 /* Max TCP packet + slop */ 1194 char *packet = malloc(65536 + MAXDNAME + RRFIXEDSZ); 1195 HEADER *header; 1196 struct server *last_server; 1197 1198 while (1) 1199 { 1200 if (!packet || 1201 !read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) || 1202 !(size = c1 << 8 | c2) || 1203 !read_write(confd, packet, size, 1)) 1204 return packet; 1205 1206 if (size < (int)sizeof(HEADER)) 1207 continue; 1208 1209 header = (HEADER *)packet; 1210 1211 if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype))) 1212 { 1213 union mysockaddr peer_addr; 1214 socklen_t peer_len = sizeof(union mysockaddr); 1215 1216 if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) != -1) 1217 { 1218 if (peer_addr.sa.sa_family == AF_INET) 1219 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, 1220 (struct all_addr *)&peer_addr.in.sin_addr, qtype); 1221#ifdef HAVE_IPV6 1222 else 1223 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff, 1224 (struct all_addr *)&peer_addr.in6.sin6_addr, qtype); 1225#endif 1226 } 1227 } 1228 1229 /* m > 0 if answered from cache */ 1230 m = answer_request(header, ((char *) header) + 65536, (unsigned int)size, daemon, now); 1231 1232 if (m == 0) 1233 { 1234 unsigned short flags = 0; 1235 struct all_addr *addrp = NULL; 1236 int type = 0; 1237 char *domain = NULL; 1238 1239 if (gotname) 1240 flags = search_servers(daemon, now, &addrp, gotname, daemon->namebuff, &type, &domain); 1241 1242 if (type != 0 || (daemon->options & OPT_ORDER) || !daemon->last_server) 1243 last_server = daemon->servers; 1244 else 1245 last_server = daemon->last_server; 1246 1247 if (!flags && last_server) 1248 { 1249 struct server *firstsendto = NULL; 1250 1251 /* Loop round available servers until we succeed in connecting to one. 1252 Note that this code subtley ensures that consecutive queries on this connection 1253 which can go to the same server, do so. */ 1254 while (1) 1255 { 1256 if (!firstsendto) 1257 firstsendto = last_server; 1258 else 1259 { 1260 if (!(last_server = last_server->next)) 1261 last_server = daemon->servers; 1262 1263 if (last_server == firstsendto) 1264 break; 1265 } 1266 1267 /* server for wrong domain */ 1268 if (type != (last_server->flags & SERV_TYPE) || 1269 (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, last_server->domain))) 1270 continue; 1271 1272 if ((last_server->tcpfd == -1) && 1273 (last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) != -1 && 1274 connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1) 1275 { 1276 close(last_server->tcpfd); 1277 last_server->tcpfd = -1; 1278 } 1279 1280 if (last_server->tcpfd == -1) 1281 continue; 1282 1283 c1 = size >> 8; 1284 c2 = size; 1285 1286 if (!read_write(last_server->tcpfd, &c1, 1, 0) || 1287 !read_write(last_server->tcpfd, &c2, 1, 0) || 1288 !read_write(last_server->tcpfd, packet, size, 0) || 1289 !read_write(last_server->tcpfd, &c1, 1, 1) || 1290 !read_write(last_server->tcpfd, &c2, 1, 1)) 1291 { 1292 close(last_server->tcpfd); 1293 last_server->tcpfd = -1; 1294 continue; 1295 } 1296 1297 m = (c1 << 8) | c2; 1298 if (!read_write(last_server->tcpfd, packet, m, 1)) 1299 return packet; 1300 1301 if (!gotname) 1302 strcpy(daemon->namebuff, "query"); 1303 if (last_server->addr.sa.sa_family == AF_INET) 1304 log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff, 1305 (struct all_addr *)&last_server->addr.in.sin_addr, 0); 1306#ifdef HAVE_IPV6 1307 else 1308 log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff, 1309 (struct all_addr *)&last_server->addr.in6.sin6_addr, 0); 1310#endif 1311 1312 /* There's no point in updating the cache, since this process will exit and 1313 lose the information after one query. We make this call for the alias and 1314 bogus-nxdomain side-effects. */ 1315 /* Foxconn modified, Tony W.Y. Wang, 12/02/2008, @Parental Control OpenDNS */ 1316#ifdef OPENDNS_PARENTAL_CONTROL 1317 m = process_reply(daemon, header, now, &last_server->addr, (unsigned int)m, 0); 1318#else 1319 m = process_reply(daemon, header, now, &last_server->addr, (unsigned int)m); 1320#endif 1321 break; 1322 } 1323 } 1324 1325 /* In case of local answer or no connections made. */ 1326 if (m == 0) 1327 m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl); 1328 } 1329 1330 c1 = m>>8; 1331 c2 = m; 1332 if (!read_write(confd, &c1, 1, 0) || 1333 !read_write(confd, &c2, 1, 0) || 1334 !read_write(confd, packet, m, 0)) 1335 return packet; 1336 } 1337} 1338 1339static struct frec *get_new_frec(time_t now) 1340{ 1341 struct frec *f = frec_list, *oldest = NULL; 1342 time_t oldtime = now; 1343 int count = 0; 1344 static time_t warntime = 0; 1345 1346 while (f) 1347 { 1348 if (f->new_id == 0) 1349 { 1350 f->time = now; 1351 return f; 1352 } 1353 1354 if (difftime(f->time, oldtime) <= 0) 1355 { 1356 oldtime = f->time; 1357 oldest = f; 1358 } 1359 1360 count++; 1361 f = f->next; 1362 } 1363 1364 /* can't find empty one, use oldest if there is one 1365 and it's older than timeout */ 1366 if (oldest && difftime(now, oldtime) > TIMEOUT) 1367 { 1368 oldest->time = now; 1369 return oldest; 1370 } 1371 1372 if (count > FTABSIZ) 1373 { /* limit logging rate so syslog isn't DOSed either */ 1374 if (!warntime || difftime(now, warntime) > LOGRATE) 1375 { 1376 warntime = now; 1377#ifdef USE_SYSLOG /* foxconn wklin added, 08/13/2007 */ 1378 syslog(LOG_WARNING, "forwarding table overflow: check for server loops."); 1379#endif 1380 } 1381 return NULL; 1382 } 1383 1384 if ((f = (struct frec *)malloc(sizeof(struct frec)))) 1385 { 1386 f->next = frec_list; 1387 f->time = now; 1388 frec_list = f; 1389 } 1390 return f; /* OK if malloc fails and this is NULL */ 1391} 1392 1393static struct frec *lookup_frec(unsigned short id) 1394{ 1395 struct frec *f; 1396 1397 for(f = frec_list; f; f = f->next) 1398 if (f->new_id == id) 1399 return f; 1400 1401 return NULL; 1402} 1403 1404static struct frec *lookup_frec_by_sender(unsigned short id, 1405 union mysockaddr *addr) 1406{ 1407 struct frec *f; 1408 1409 if( addr ) 1410 { 1411 for(f = frec_list; f; f = f->next) 1412 if (f->new_id && 1413 f->orig_id == id && 1414 sockaddr_isequal(&f->source, addr)) 1415 return f; 1416 } 1417 1418 return NULL; 1419} 1420 1421 1422/* return unique random ids between 1 and 65535 */ 1423static unsigned short get_id(void) 1424{ 1425 unsigned short ret = 0; 1426 1427 while (ret == 0) 1428 { 1429 ret = rand16(); 1430 1431 /* scrap ids already in use */ 1432 if ((ret != 0) && lookup_frec(ret)) 1433 ret = 0; 1434 } 1435 1436 return ret; 1437} 1438 1439/* Foxconn add start, Tony W.Y. Wang, 12/05/2008, @Parental Control OpenDNS */ 1440#ifdef OPENDNS_PARENTAL_CONTROL 1441#define PROC_ARP_FILE "/proc/net/arp" 1442int get_mac_from_arp(char *dnsquery_src_ip, char *src_mac) 1443{ 1444 FILE *fp; 1445 char buf[512]; 1446 char buffer[64]; 1447 int i = 0, index = 0; 1448 int exist_num = 0; 1449 char *p_str; 1450 if (!(fp = fopen(PROC_ARP_FILE, "r"))) { 1451 perror(PROC_ARP_FILE); 1452 return 0; 1453 } 1454 fgets(buf, sizeof(buf), fp); /* ignore the first line */ 1455 while (fgets(buf, sizeof(buf), fp)) { /* get all the lines */ 1456 p_str = strstr (buf, dnsquery_src_ip); /* check whether the src_ip exist in the line */ 1457 if(p_str) 1458 { 1459 p_str = p_str + 41; 1460 strncpy(buf,p_str,17); /* get MAC 00:11:22:33:44:55 */ 1461 buf[17] = '\0'; 1462 for(i=0; i<17; i++) /* transfor MAC to 001122334455 */ 1463 { 1464 if(buf[i] != ':') 1465 { 1466 buffer[index] = buf[i]; 1467 index++; 1468 } 1469 } 1470 buffer[index] = '\0'; 1471 strcpy(src_mac, buffer); 1472 fclose(fp); 1473 return 0; 1474 } 1475 } 1476 fclose(fp); 1477 return 1; 1478} 1479 1480int char_to_byte(char string_id[], unsigned char byte_id[]) 1481{ 1482 int i = 0; 1483 int tmp = 0; 1484 for (i=0; i<16; i+=2) 1485 { 1486 if(string_id[i] >= '0' && string_id[i] <= '9') 1487 tmp = string_id[i] - '0'; 1488 else if(string_id[i] >= 'A' && string_id[i] <= 'F') 1489 tmp = string_id[i] - 'A' + 10; 1490 if(string_id[i+1] >= '0' && string_id[i+1] <= '9') 1491 tmp = tmp*16 + (string_id[i+1] - '0'); 1492 else if(string_id[i+1] >= 'A' && string_id[i+1] <= 'F') 1493 tmp = tmp*16 + (string_id[i+1] - 'A' + 10); 1494 byte_id[i/2] = (unsigned char)tmp; 1495 } 1496 return 0; 1497} 1498 1499static void get_device_id(char src_mac[], char id[]) 1500{ 1501 FILE *fp; 1502 char opendns_tbl[2048] = ""; 1503 int is_found = 0; 1504 char *p_str = NULL; 1505 1506 if((fp = fopen("/tmp/opendns.tbl", "r"))) 1507 { 1508 while (fgets(opendns_tbl, sizeof(opendns_tbl), fp)) 1509 { 1510 p_str = strstr (opendns_tbl, "DEFAULT"); 1511 if(p_str) 1512 { 1513 is_found = 1; 1514 p_str = p_str + strlen("DEFAULT") + 1; 1515 strncpy(id, p_str, 16); 1516 id[16] = '\0'; 1517 } 1518 //p_str = strstr (opendns_tbl, src_mac); 1519 p_str = strcasestr (opendns_tbl, src_mac); 1520 if(p_str) 1521 { 1522 is_found = 1; 1523 p_str = p_str + strlen(src_mac) + 1; 1524 strncpy(id, p_str, 16); 1525 id[16] = '\0'; 1526 break; 1527 } 1528 } 1529 fclose(fp); 1530 } 1531 if(!is_found) 1532 { 1533 strcpy(id, "0000111111111111"); 1534 } 1535} 1536#endif 1537/* Foxconn add end , Tony W.Y. Wang, 12/05/2008, @Parental Control OpenDNS */ 1538 1539 1540