Annotation of embedaddon/dnsmasq/src/loop.c, revision 1.1.1.3

1.1.1.3 ! misho       1: /* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
1.1       misho       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_LOOP
                     20: static ssize_t loop_make_probe(u32 uid);
                     21: 
                     22: void loop_send_probes()
                     23: {
                     24:    struct server *serv;
1.1.1.3 ! misho      25:    struct randfd_list *rfds = NULL;
1.1       misho      26:    
                     27:    if (!option_bool(OPT_LOOP_DETECT))
                     28:      return;
                     29: 
                     30:    /* Loop through all upstream servers not for particular domains, and send a query to that server which is
                     31:       identifiable, via the uid. If we see that query back again, then the server is looping, and we should not use it. */
                     32:    for (serv = daemon->servers; serv; serv = serv->next)
1.1.1.3 ! misho      33:      if (strlen(serv->domain) == 0 &&
        !            34:         !(serv->flags & (SERV_FOR_NODOTS)))
1.1       misho      35:        {
                     36:         ssize_t len = loop_make_probe(serv->uid);
                     37:         int fd;
                     38:         
1.1.1.3 ! misho      39:         serv->flags &= ~SERV_LOOP;
1.1       misho      40: 
1.1.1.3 ! misho      41:         if ((fd = allocate_rfd(&rfds, serv)) == -1)
        !            42:           continue;
        !            43:         
1.1       misho      44:         while (retry_send(sendto(fd, daemon->packet, len, 0, 
                     45:                                  &serv->addr.sa, sa_len(&serv->addr))));
                     46:        }
1.1.1.3 ! misho      47: 
        !            48:    free_rfds(&rfds);
1.1       misho      49: }
                     50:   
                     51: static ssize_t loop_make_probe(u32 uid)
                     52: {
                     53:   struct dns_header *header = (struct dns_header *)daemon->packet;
                     54:   unsigned char *p = (unsigned char *)(header+1);
1.1.1.3 ! misho      55:   
1.1       misho      56:   /* packet buffer overwritten */
                     57:   daemon->srv_save = NULL;
                     58:   
                     59:   header->id = rand16();
                     60:   header->ancount = header->nscount = header->arcount = htons(0);
                     61:   header->qdcount = htons(1);
                     62:   header->hb3 = HB3_RD;
                     63:   header->hb4 = 0;
                     64:   SET_OPCODE(header, QUERY);
                     65: 
                     66:   *p++ = 8;
                     67:   sprintf((char *)p, "%.8x", uid);
                     68:   p += 8;
                     69:   *p++ = strlen(LOOP_TEST_DOMAIN);
                     70:   strcpy((char *)p, LOOP_TEST_DOMAIN); /* Add terminating zero */
                     71:   p += strlen(LOOP_TEST_DOMAIN) + 1;
                     72: 
                     73:   PUTSHORT(LOOP_TEST_TYPE, p);
                     74:   PUTSHORT(C_IN, p);
                     75: 
                     76:   return p - (unsigned char *)header;
                     77: }
                     78:   
                     79: 
                     80: int detect_loop(char *query, int type)
                     81: {
                     82:   int i;
                     83:   u32 uid;
                     84:   struct server *serv;
                     85:   
                     86:   if (!option_bool(OPT_LOOP_DETECT))
                     87:     return 0;
                     88: 
                     89:   if (type != LOOP_TEST_TYPE ||
                     90:       strlen(LOOP_TEST_DOMAIN) + 9 != strlen(query) ||
                     91:       strstr(query, LOOP_TEST_DOMAIN) != query + 9)
                     92:     return 0;
                     93: 
                     94:   for (i = 0; i < 8; i++)
1.1.1.3 ! misho      95:     if (!isxdigit((unsigned char)query[i]))
1.1       misho      96:       return 0;
                     97: 
                     98:   uid = strtol(query, NULL, 16);
                     99: 
                    100:   for (serv = daemon->servers; serv; serv = serv->next)
1.1.1.3 ! misho     101:     if (strlen(serv->domain) == 0 &&
        !           102:        !(serv->flags & SERV_LOOP) &&
        !           103:        uid == serv->uid)
        !           104:       {
        !           105:        serv->flags |= SERV_LOOP;
        !           106:        check_servers(1); /* log new state - don't send more probes. */
        !           107:        return 1;
        !           108:       }
        !           109:   
1.1       misho     110:   return 0;
                    111: }
                    112: 
                    113: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>