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

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

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