1 /* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
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.
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.
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/>.
20 static ssize_t
loop_make_probe(u32 uid
);
22 void loop_send_probes()
26 if (!option_bool(OPT_LOOP_DETECT
))
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
)
33 (SERV_LITERAL_ADDRESS
| SERV_NO_ADDR
| SERV_USE_RESOLV
| SERV_NO_REBIND
| SERV_HAS_DOMAIN
| SERV_FOR_NODOTS
| SERV_LOOP
)))
35 ssize_t len
= loop_make_probe(serv
->uid
);
37 struct randfd
*rfd
= NULL
;
43 if (!(rfd
= allocate_rfd(serv
->addr
.sa
.sa_family
)))
48 while (retry_send(sendto(fd
, daemon
->packet
, len
, 0,
49 &serv
->addr
.sa
, sa_len(&serv
->addr
))));
55 static ssize_t
loop_make_probe(u32 uid
)
57 struct dns_header
*header
= (struct dns_header
*)daemon
->packet
;
58 unsigned char *p
= (unsigned char *)(header
+1);
60 /* packet buffer overwritten */
61 daemon
->srv_save
= NULL
;
63 header
->id
= rand16();
64 header
->ancount
= header
->nscount
= header
->arcount
= htons(0);
65 header
->qdcount
= htons(1);
68 SET_OPCODE(header
, QUERY
);
71 sprintf((char *)p
, "%.8x", uid
);
73 *p
++ = strlen(LOOP_TEST_DOMAIN
);
74 strcpy((char *)p
, LOOP_TEST_DOMAIN
); /* Add terminating zero */
75 p
+= strlen(LOOP_TEST_DOMAIN
) + 1;
77 PUTSHORT(LOOP_TEST_TYPE
, p
);
80 return p
- (unsigned char *)header
;
84 int detect_loop(char *query
, int type
)
90 if (!option_bool(OPT_LOOP_DETECT
))
93 if (type
!= LOOP_TEST_TYPE
||
94 strlen(LOOP_TEST_DOMAIN
) + 9 != strlen(query
) ||
95 strstr(query
, LOOP_TEST_DOMAIN
) != query
+ 9)
98 for (i
= 0; i
< 8; i
++)
99 if (!isxdigit(query
[i
]))
102 uid
= strtol(query
, NULL
, 16);
104 for (serv
= daemon
->servers
; serv
; serv
= serv
->next
)
106 (SERV_LITERAL_ADDRESS
| SERV_NO_ADDR
| SERV_USE_RESOLV
| SERV_NO_REBIND
| SERV_HAS_DOMAIN
| SERV_FOR_NODOTS
| SERV_LOOP
)) &&
109 serv
->flags
|= SERV_LOOP
;
110 check_servers(); /* log new state */