Annotation of embedaddon/dnsmasq/src/loop.c, revision 1.1.1.2
1.1.1.2 ! misho 1: /* dnsmasq is Copyright (c) 2000-2021 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;
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>