Lines Matching +full:- +full:- +full:daemon
1 /* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
61 if (to->sa.sa_family == AF_INET) { in send_from()
64 pkt->ipi_ifindex = 0; in send_from()
65 pkt->ipi_spec_dst = source->addr.addr4; in send_from()
66 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); in send_from()
67 cmptr->cmsg_level = SOL_IP; in send_from()
68 cmptr->cmsg_type = IP_PKTINFO; in send_from()
71 *a = source->addr.addr4; in send_from()
72 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); in send_from()
73 cmptr->cmsg_level = IPPROTO_IP; in send_from()
74 cmptr->cmsg_type = IP_SENDSRCADDR; in send_from()
80 pkt->ipi6_ifindex = iface; /* Need iface for IPv6 to handle link-local addrs */ in send_from()
81 pkt->ipi6_addr = source->addr.addr6; in send_from()
82 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); in send_from()
83 cmptr->cmsg_type = IPV6_PKTINFO; in send_from()
84 cmptr->cmsg_level = IPV6_LEVEL; in send_from()
92 if (sendmsg(fd, &msg, 0) == -1) { in send_from()
117 for (serv = daemon->servers; serv; serv = serv->next) in search_servers()
119 if ((serv->flags & SERV_FOR_NODOTS) && *type != SERV_HAS_DOMAIN && !strchr(qdomain, '.') && in search_servers()
121 unsigned short sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6; in search_servers()
123 if (serv->flags & SERV_NO_ADDR) in search_servers()
125 else if (serv->flags & SERV_LITERAL_ADDRESS) { in search_servers()
128 if (serv->addr.sa.sa_family == AF_INET) in search_servers()
129 *addrpp = (struct all_addr*) &serv->addr.in.sin_addr; in search_servers()
132 *addrpp = (struct all_addr*) &serv->addr.in6.sin6_addr; in search_servers()
137 } else if (serv->flags & SERV_HAS_DOMAIN) { in search_servers()
138 unsigned int domainlen = strlen(serv->domain); in search_servers()
139 char* matchstart = qdomain + namelen - domainlen; in search_servers()
140 if (namelen >= domainlen && hostname_isequal(matchstart, serv->domain) && in search_servers()
142 (domainlen == 0 || namelen == domainlen || *(serv->domain) == '.' || in search_servers()
143 *(matchstart - 1) == '.')) { in search_servers()
144 unsigned short sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6; in search_servers()
146 *domain = serv->domain; in search_servers()
148 if (serv->flags & SERV_NO_ADDR) in search_servers()
150 else if (serv->flags & SERV_LITERAL_ADDRESS) { in search_servers()
153 if (serv->addr.sa.sa_family == AF_INET) in search_servers()
154 *addrpp = (struct all_addr*) &serv->addr.in.sin_addr; in search_servers()
157 *addrpp = (struct all_addr*) &serv->addr.in6.sin6_addr; in search_servers()
165 if (flags == 0 && !(qtype & F_BIGNAME) && (daemon->options & OPT_NODOTS_LOCAL) && in search_servers()
189 unsigned int crc = questions_crc(header, plen, daemon->namebuff); in forward_query()
191 unsigned short gotname = extract_request(header, plen, daemon->namebuff, NULL); in forward_query()
195 if (!daemon->servers) in forward_query()
197 else if (forward || (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, crc))) { in forward_query()
199 domain = forward->sentto->domain; in forward_query()
200 forward->sentto->failed_queries++; in forward_query()
201 if (!(daemon->options & OPT_ORDER)) { in forward_query()
202 forward->forwardall = 1; in forward_query()
203 daemon->last_server = NULL; in forward_query()
205 type = forward->sentto->flags & SERV_TYPE; in forward_query()
206 if (!(start = forward->sentto->next)) start = daemon->servers; /* at end of list, recycle */ in forward_query()
207 header->id = htons(forward->new_id); in forward_query()
209 if (gotname) flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain); in forward_query()
211 if (!flags && !(forward = get_new_frec(now, NULL))) /* table full - server failure. */ in forward_query()
219 forward->source = *udpaddr; in forward_query()
220 forward->dest = *dst_addr; in forward_query()
221 forward->iface = dst_iface; in forward_query()
222 forward->orig_id = ntohs(header->id); in forward_query()
223 forward->new_id = get_id(is_sign, forward->orig_id, crc); in forward_query()
224 forward->fd = udpfd; in forward_query()
225 forward->crc = crc; in forward_query()
226 forward->forwardall = 0; in forward_query()
227 header->id = htons(forward->new_id); in forward_query()
233 if (type != 0 || (daemon->options & OPT_ORDER)) in forward_query()
234 start = daemon->servers; in forward_query()
235 else if (!(start = daemon->last_server) || daemon->forwardcount++ > FORWARD_TEST || in forward_query()
236 difftime(now, daemon->forwardtime) > FORWARD_TIME) { in forward_query()
237 start = daemon->servers; in forward_query()
238 forward->forwardall = 1; in forward_query()
239 daemon->forwardcount = 0; in forward_query()
240 daemon->forwardtime = now; in forward_query()
255 domain may be NULL, in which case server->domain in forward_query()
258 if (type == (start->flags & SERV_TYPE) && in forward_query()
259 (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) && in forward_query()
260 !(start->flags & SERV_LITERAL_ADDRESS)) { in forward_query()
264 if (start->sfd) in forward_query()
265 fd = start->sfd->fd; in forward_query()
268 if (start->addr.sa.sa_family == AF_INET6) { in forward_query()
269 if (!forward->rfd6 && !(forward->rfd6 = allocate_rfd(AF_INET6))) break; in forward_query()
270 daemon->rfd_save = forward->rfd6; in forward_query()
271 fd = forward->rfd6->fd; in forward_query()
275 if (!forward->rfd4 && !(forward->rfd4 = allocate_rfd(AF_INET))) break; in forward_query()
276 daemon->rfd_save = forward->rfd4; in forward_query()
277 fd = forward->rfd4->fd; in forward_query()
282 // that we never clear the mark, only re-set it the next time we in forward_query()
284 // queries (in daemon->srv_save, daemon->packet_len) and socket in forward_query()
285 // file descriptors (in daemon->rfd_save) with the expectation of in forward_query()
289 setsockopt(fd, SOL_SOCKET, SO_MARK, &start->mark, sizeof(start->mark)); in forward_query()
293 if (sendto(fd, (char*) header, plen, 0, &start->addr.sa, sa_len(&start->addr)) == in forward_query()
294 -1) { in forward_query()
297 /* Keep info in case we want to re-send this packet */ in forward_query()
298 daemon->srv_save = start; in forward_query()
299 daemon->packet_len = plen; in forward_query()
301 if (!gotname) strcpy(daemon->namebuff, "query"); in forward_query()
302 if (start->addr.sa.sa_family == AF_INET) in forward_query()
303 log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff, in forward_query()
304 (struct all_addr*) &start->addr.in.sin_addr, NULL); in forward_query()
307 log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff, in forward_query()
308 (struct all_addr*) &start->addr.in6.sin6_addr, NULL); in forward_query()
310 start->queries++; in forward_query()
312 forward->sentto = start; in forward_query()
313 if (!forward->forwardall) break; in forward_query()
314 forward->forwardall++; in forward_query()
318 if (!(start = start->next)) start = daemon->servers; in forward_query()
326 header->id = htons(forward->orig_id); in forward_query()
331 if (udpfd != -1) { in forward_query()
332 plen = setup_reply(header, plen, addrp, flags, daemon->local_ttl); in forward_query()
333 send_from(udpfd, daemon->options & OPT_NOWILD, (char*) header, plen, udpaddr, dst_addr, in forward_query()
354 if (udpsz > daemon->edns_pktsz) PUTSHORT(daemon->edns_pktsz, psave); in process_reply()
357 if (header->opcode != QUERY || (header->rcode != NOERROR && header->rcode != NXDOMAIN)) in process_reply()
360 /* Complain loudly if the upstream server is non-recursive. */ in process_reply()
361 if (!header->ra && header->rcode == NOERROR && ntohs(header->ancount) == 0 && server && in process_reply()
362 !(server->flags & SERV_WARNED_RECURSIVE)) { in process_reply()
363 prettyprint_addr(&server->addr, daemon->namebuff); in process_reply()
364 … my_syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff); in process_reply()
365 if (!(daemon->options & OPT_LOG)) server->flags |= SERV_WARNED_RECURSIVE; in process_reply()
368 if (daemon->bogus_addr && header->rcode != NXDOMAIN && in process_reply()
369 check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now)) { in process_reply()
371 header->rcode = NXDOMAIN; in process_reply()
372 header->aa = 0; in process_reply()
374 if (header->rcode == NXDOMAIN && extract_request(header, n, daemon->namebuff, NULL) && in process_reply()
375 check_for_local_domain(daemon->namebuff, now)) { in process_reply()
380 header->aa = 1; in process_reply()
381 header->rcode = NOERROR; in process_reply()
384 if (extract_addresses(header, n, daemon->namebuff, now)) { in process_reply()
385 my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected")); in process_reply()
394 header->ancount = htons(0); in process_reply()
395 header->nscount = htons(0); in process_reply()
396 header->arcount = htons(0); in process_reply()
399 /* the bogus-nxdomain stuff, doctor and NXDOMAIN->NODATA munging can all elide in process_reply()
413 ssize_t n = recvfrom(fd, daemon->packet, daemon->edns_pktsz, 0, &serveraddr.sa, &addrlen); in reply_query()
418 daemon->srv_save = NULL; in reply_query()
427 for (server = daemon->servers; server; server = server->next) in reply_query()
428 if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) && in reply_query()
429 sockaddr_isequal(&server->addr, &serveraddr)) in reply_query()
432 header = (HEADER*) daemon->packet; in reply_query()
434 if (!server || n < (int) sizeof(HEADER) || !header->qr || in reply_query()
435 !(forward = lookup_frec(ntohs(header->id), questions_crc(header, n, daemon->namebuff)))) in reply_query()
438 server = forward->sentto; in reply_query()
440 if ((header->rcode == SERVFAIL || header->rcode == REFUSED) && !(daemon->options & OPT_ORDER) && in reply_query()
441 forward->forwardall == 0) in reply_query()
451 header->ancount = htons(0); in reply_query()
452 header->nscount = htons(0); in reply_query()
453 header->arcount = htons(0); in reply_query()
455 header->qr = 0; in reply_query()
456 header->tc = 0; in reply_query()
457 forward_query(-1, NULL, NULL, 0, header, nn, now, forward); in reply_query()
463 if ((forward->sentto->flags & SERV_TYPE) == 0) { in reply_query()
464 if (header->rcode == SERVFAIL || header->rcode == REFUSED) in reply_query()
470 for (last_server = daemon->servers; last_server; last_server = last_server->next) in reply_query()
471 if (!(last_server->flags & in reply_query()
473 sockaddr_isequal(&last_server->addr, &serveraddr)) { in reply_query()
478 if (!(daemon->options & OPT_ALL_SERVERS)) daemon->last_server = server; in reply_query()
485 if (forward->forwardall == 0 || --forward->forwardall == 1 || in reply_query()
486 (header->rcode != REFUSED && header->rcode != SERVFAIL)) { in reply_query()
488 header->id = htons(forward->orig_id); in reply_query()
489 header->ra = 1; /* recursion if available */ in reply_query()
490 send_from(forward->fd, daemon->options & OPT_NOWILD, daemon->packet, nn, in reply_query()
491 &forward->source, &forward->dest, forward->iface); in reply_query()
498 HEADER* header = (HEADER*) daemon->packet; in receive_query()
522 daemon->srv_save = NULL; in receive_query()
524 if (listen->family == AF_INET && (daemon->options & OPT_NOWILD)) { in receive_query()
525 dst_addr_4 = listen->iface->addr.in.sin_addr; in receive_query()
526 netmask = listen->iface->netmask; in receive_query()
532 iov[0].iov_base = daemon->packet; in receive_query()
533 iov[0].iov_len = daemon->edns_pktsz; in receive_query()
543 if ((n = recvmsg(listen->fd, &msg, 0)) == -1) return; in receive_query()
545 if (n < (int) sizeof(HEADER) || (msg.msg_flags & MSG_TRUNC) || header->qr) return; in receive_query()
547 source_addr.sa.sa_family = listen->family; in receive_query()
549 if (listen->family == AF_INET6) source_addr.in6.sin6_flowinfo = 0; in receive_query()
552 if (!(daemon->options & OPT_NOWILD)) { in receive_query()
558 if (listen->family == AF_INET) in receive_query()
560 if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO) { in receive_query()
562 ((struct in_pktinfo*) CMSG_DATA(cmptr))->ipi_spec_dst; in receive_query()
563 if_index = ((struct in_pktinfo*) CMSG_DATA(cmptr))->ipi_ifindex; in receive_query()
566 if (listen->family == AF_INET) { in receive_query()
568 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR) in receive_query()
570 else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF) in receive_query()
571 if_index = ((struct sockaddr_dl*) CMSG_DATA(cmptr))->sdl_index; in receive_query()
576 if (listen->family == AF_INET6) { in receive_query()
578 if (cmptr->cmsg_level == IPV6_LEVEL && cmptr->cmsg_type == IPV6_PKTINFO) { in receive_query()
579 dst_addr.addr.addr6 = ((struct in6_pktinfo*) CMSG_DATA(cmptr))->ipi6_addr; in receive_query()
580 if_index = ((struct in6_pktinfo*) CMSG_DATA(cmptr))->ipi6_ifindex; in receive_query()
587 if (!indextoname(listen->fd, if_index, ifr.ifr_name) || in receive_query()
588 !iface_check(listen->family, &dst_addr, ifr.ifr_name, &if_index)) in receive_query()
591 if (listen->family == AF_INET && (daemon->options & OPT_LOCALISE) && in receive_query()
592 ioctl(listen->fd, SIOCGIFNETMASK, &ifr) == -1) in receive_query()
595 netmask = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr; in receive_query()
598 if (extract_request(header, (size_t) n, daemon->namebuff, &type)) { in receive_query()
603 if (listen->family == AF_INET) in receive_query()
604 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, in receive_query()
608 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff, in receive_query()
615 send_from(listen->fd, daemon->options & OPT_NOWILD, (char*) header, m, &source_addr, in receive_query()
617 daemon->local_answer++; in receive_query()
618 } else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index, header, (size_t) n, now, in receive_query()
620 daemon->queries_forwarded++; in receive_query()
622 daemon->local_answer++; in receive_query()
625 /* The daemon forks before calling this: it should deal with one connection,
649 if ((gotname = extract_request(header, (unsigned int) size, daemon->namebuff, &qtype))) { in tcp_request()
653 if (getpeername(confd, (struct sockaddr*) &peer_addr, &peer_len) != -1) { in tcp_request()
659 log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, in tcp_request()
663 log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff, in tcp_request()
683 flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain); in tcp_request()
685 if (type != 0 || (daemon->options & OPT_ORDER) || !daemon->last_server) in tcp_request()
686 last_server = daemon->servers; in tcp_request()
688 last_server = daemon->last_server; in tcp_request()
692 unsigned int crc = questions_crc(header, (unsigned int) size, daemon->namebuff); in tcp_request()
701 if (!(last_server = last_server->next)) last_server = daemon->servers; in tcp_request()
707 if (type != (last_server->flags & SERV_TYPE) || in tcp_request()
708 (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, last_server->domain))) in tcp_request()
711 if ((last_server->tcpfd == -1) && in tcp_request()
712 (last_server->tcpfd = in tcp_request()
713 socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) != -1 && in tcp_request()
714 (!local_bind(last_server->tcpfd, &last_server->source_addr, in tcp_request()
715 last_server->interface, last_server->mark, 1) || in tcp_request()
716 connect(last_server->tcpfd, &last_server->addr.sa, in tcp_request()
717 sa_len(&last_server->addr)) == -1)) { in tcp_request()
718 close(last_server->tcpfd); in tcp_request()
719 last_server->tcpfd = -1; in tcp_request()
722 if (last_server->tcpfd == -1) continue; in tcp_request()
727 if (!read_write(last_server->tcpfd, &c1, 1, 0) || in tcp_request()
728 !read_write(last_server->tcpfd, &c2, 1, 0) || in tcp_request()
729 !read_write(last_server->tcpfd, packet, size, 0) || in tcp_request()
730 !read_write(last_server->tcpfd, &c1, 1, 1) || in tcp_request()
731 !read_write(last_server->tcpfd, &c2, 1, 1)) { in tcp_request()
732 close(last_server->tcpfd); in tcp_request()
733 last_server->tcpfd = -1; in tcp_request()
738 if (!read_write(last_server->tcpfd, packet, m, 1)) return packet; in tcp_request()
740 if (!gotname) strcpy(daemon->namebuff, "query"); in tcp_request()
741 if (last_server->addr.sa.sa_family == AF_INET) in tcp_request()
742 log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff, in tcp_request()
743 (struct all_addr*) &last_server->addr.in.sin_addr, NULL); in tcp_request()
746 log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff, in tcp_request()
747 (struct all_addr*) &last_server->addr.in6.sin6_addr, NULL); in tcp_request()
752 bogus-nxdomain side-effects. */ in tcp_request()
756 if (crc == questions_crc(header, (unsigned int) m, daemon->namebuff)) in tcp_request()
765 m = setup_reply(header, (unsigned int) size, addrp, flags, daemon->local_ttl); in tcp_request()
782 f->next = daemon->frec_list; in allocate_frec()
783 f->time = now; in allocate_frec()
784 f->sentto = NULL; in allocate_frec()
785 f->rfd4 = NULL; in allocate_frec()
787 f->rfd6 = NULL; in allocate_frec()
789 daemon->frec_list = f; in allocate_frec()
803 if (daemon->randomsocks[i].refcount == 0) { in allocate_rfd()
804 if ((daemon->randomsocks[i].fd = random_sock(family)) == -1) break; in allocate_rfd()
806 daemon->randomsocks[i].refcount = 1; in allocate_rfd()
807 daemon->randomsocks[i].family = family; in allocate_rfd()
808 return &daemon->randomsocks[i]; in allocate_rfd()
814 if (daemon->randomsocks[j].refcount != 0 && daemon->randomsocks[j].family == family && in allocate_rfd()
815 daemon->randomsocks[j].refcount != 0xffff) { in allocate_rfd()
817 daemon->randomsocks[j].refcount++; in allocate_rfd()
818 return &daemon->randomsocks[j]; in allocate_rfd()
826 if (f->rfd4 && --(f->rfd4->refcount) == 0) close(f->rfd4->fd); in free_frec()
828 f->rfd4 = NULL; in free_frec()
829 f->sentto = NULL; in free_frec()
832 if (f->rfd6 && --(f->rfd6->refcount) == 0) close(f->rfd6->fd); in free_frec()
834 f->rfd6 = NULL; in free_frec()
840 when the oldest in-use record will expire. Impose an absolute
848 for (f = daemon->frec_list, oldest = NULL, target = NULL, count = 0; f; f = f->next, count++) in get_new_frec()
849 if (!f->sentto) in get_new_frec()
852 if (difftime(now, f->time) >= 4 * TIMEOUT) { in get_new_frec()
857 if (!oldest || difftime(f->time, oldest->time) <= 0) oldest = f; in get_new_frec()
861 target->time = now; in get_new_frec()
867 if (oldest && ((int) difftime(now, oldest->time)) >= TIMEOUT) { in get_new_frec()
870 if (difftime(now, oldest->time) < 2 * TIMEOUT && count <= daemon->ftabsize && in get_new_frec()
876 oldest->time = now; in get_new_frec()
882 if (count > daemon->ftabsize) { in get_new_frec()
883 if (oldest && wait) *wait = oldest->time + (time_t) TIMEOUT - now; in get_new_frec()
893 /* crc is all-ones if not known. */
897 for (f = daemon->frec_list; f; f = f->next) in lookup_frec()
898 if (f->sentto && f->new_id == id && (f->crc == crc || crc == 0xffffffff)) return f; in lookup_frec()
907 for (f = daemon->frec_list; f; f = f->next) in lookup_frec_by_sender()
908 if (f->sentto && f->orig_id == id && f->crc == crc && sockaddr_isequal(&f->source, addr)) in lookup_frec_by_sender()
918 for (f = daemon->frec_list; f; f = f->next) in server_gone()
919 if (f->sentto && f->sentto == server) free_frec(f); in server_gone()
921 if (daemon->last_server == server) daemon->last_server = NULL; in server_gone()
923 if (daemon->srv_save == server) daemon->srv_save = NULL; in server_gone()