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>