int wait(int sockfd,User_List play_list[]){ printf("\nDoi nguoi choi khac...(hoac an 1 phim de vao MENU)"); printf("\n"); int rv,t,x,n; char mesg[LEN],nick_name[LEN],buff[LEN]; fd_set readSet; struct timeval tv; while(1){ tv.tv_sec = 5; tv.tv_usec =0; FD_SET(sockfd, &readSet); FD_SET(fileno(stdin), &readSet); select(sockfd +1, &readSet, NULL, NULL, &tv); if (FD_ISSET(fileno(stdin), &readSet)){ fgets(buff,LEN,stdin); return 0; }else if(FD_ISSET(sockfd, &readSet)){ strcpy(mesg,""); n=recv(sockfd,mesg,LEN,0); if(n==0) return 3; t=check_mark(mesg); if(t == 3) x = answer_request(sockfd,mesg,play_list); return 1; } } }
int main (int argc, char **argv) { char *int_err_string; int cachesize = CACHESIZ; int port = NAMESERVER_PORT; int query_port = 0; unsigned long local_ttl = 0; int logged_lease = 0, first_loop = 1; unsigned int options; char *runfile = RUNFILE; time_t resolv_changed = 0; time_t now, last = 0; time_t lease_file_change = 0; ino_t lease_file_inode = (ino_t)0; struct irec *iface, *interfaces = NULL; char *mxname = NULL; char *mxtarget = NULL; char *lease_file = NULL; char *addn_hosts = NULL; char *domain_suffix = NULL; char *username = CHUSER; char *groupname = CHGRP; struct iname *if_names = NULL; struct iname *if_addrs = NULL; struct iname *if_except = NULL; struct iname *if_tmp; struct server *serv_addrs = NULL; char *dnamebuff, *packet; struct server *servers, *last_server; struct resolvc default_resolv = { NULL, 1, 0, RESOLVFILE }; struct resolvc *resolv = &default_resolv; struct bogus_addr *bogus_addr = NULL; struct serverfd *serverfdp, *sfds = NULL; sighup = 1; /* init cache the first time through */ sigusr1 = 0; /* but don't dump */ sigusr2 = 0; /* or rescan interfaces */ signal(SIGUSR1, sig_handler); signal(SIGUSR2, sig_handler); signal(SIGHUP, sig_handler); /* These get allocated here to avoid overflowing the small stack on embedded systems. dnamebuff is big enough to hold one maximal sixed domain name and gets passed into all the processing code. We manage to get away with one buffer. */ dnamebuff = safe_malloc(MAXDNAME); /* Size: we check after adding each record, so there must be memory for the largest packet, and the largest record */ packet = safe_malloc(PACKETSZ+MAXDNAME+RRFIXEDSZ); options = read_opts(argc, argv, dnamebuff, &resolv, &mxname, &mxtarget, &lease_file, &username, &groupname, &domain_suffix, &runfile, &if_names, &if_addrs, &if_except, &bogus_addr, &serv_addrs, &cachesize, &port, &query_port, &local_ttl, &addn_hosts); int_err_string = enumerate_interfaces(&interfaces, if_names, if_addrs, if_except, port); if (int_err_string) die(int_err_string, NULL); for (if_tmp = if_names; if_tmp; if_tmp = if_tmp->next) if (if_tmp->name && !if_tmp->found) die("unknown interface %s", if_tmp->name); for (if_tmp = if_addrs; if_tmp; if_tmp = if_tmp->next) if (!if_tmp->found) { char addrbuff[ADDRSTRLEN]; #ifdef HAVE_IPV6 if (if_tmp->addr.sa.sa_family == AF_INET) inet_ntop(AF_INET, &if_tmp->addr.in.sin_addr, addrbuff, ADDRSTRLEN); else inet_ntop(AF_INET6, &if_tmp->addr.in6.sin6_addr, addrbuff, ADDRSTRLEN); #else strcpy(addrbuff, inet_ntoa(if_tmp->addr.in.sin_addr)); #endif die("no interface with address %s", addrbuff); } forward_init(1); cache_init(cachesize, options & OPT_LOG); setbuf(stdout, NULL); if (!(options & OPT_DEBUG)) { FILE *pidfile; struct passwd *ent_pw; int i; /* The following code "daemonizes" the process. See Stevens section 12.4 */ #ifndef NO_FORK if (fork() != 0 ) exit(0); setsid(); if (fork() != 0) exit(0); #endif chdir("/"); umask(022); /* make pidfile 0644 */ /* write pidfile _after_ forking ! */ if (runfile && (pidfile = fopen(runfile, "w"))) { fprintf(pidfile, "%d\n", (int) getpid()); fclose(pidfile); } umask(0); for (i=0; i<64; i++) { for (iface = interfaces; iface; iface = iface->next) if (iface->fd == i) break; if (iface) continue; close(i); } /* Change uid and gid for security */ if (username && (ent_pw = getpwnam(username))) { gid_t dummy; struct group *gp; /* remove all supplimentary groups */ setgroups(0, &dummy); /* change group for /etc/ppp/resolv.conf otherwise get the group for "nobody" */ if ((groupname && (gp = getgrnam(groupname))) || (gp = getgrgid(ent_pw->pw_gid))) setgid(gp->gr_gid); /* finally drop root */ setuid(ent_pw->pw_uid); } } openlog("dnsmasq", DNSMASQ_LOG_OPT(options & OPT_DEBUG), DNSMASQ_LOG_FAC(options & OPT_DEBUG)); if (cachesize) syslog(LOG_INFO, "started, version %s cachesize %d", VERSION, cachesize); else syslog(LOG_INFO, "started, version %s cache disabled", VERSION); if (options & OPT_LOCALMX) syslog(LOG_INFO, "serving MX record for local hosts target %s", mxtarget); else if (mxname) syslog(LOG_INFO, "serving MX record for mailhost %s target %s", mxname, mxtarget); if (getuid() == 0 || geteuid() == 0) syslog(LOG_WARNING, "failed to drop root privs"); servers = last_server = check_servers(serv_addrs, interfaces, &sfds); while (1) { int ready, maxfd = 0; fd_set rset; HEADER *header; struct stat statbuf; if (first_loop) /* do init stuff only first time round. */ { first_loop = 0; ready = 0; } else { FD_ZERO(&rset); for (serverfdp = sfds; serverfdp; serverfdp = serverfdp->next) { FD_SET(serverfdp->fd, &rset); if (serverfdp->fd > maxfd) maxfd = serverfdp->fd; } for (iface = interfaces; iface; iface = iface->next) { FD_SET(iface->fd, &rset); if (iface->fd > maxfd) maxfd = iface->fd; } ready = select(maxfd+1, &rset, NULL, NULL, NULL); if (ready == -1) { if (errno == EINTR) ready = 0; /* do signal handlers */ else continue; } } if (sighup) { signal(SIGHUP, SIG_IGN); cache_reload(options, dnamebuff, domain_suffix, addn_hosts); if (resolv && (options & OPT_NO_POLL)) servers = last_server = check_servers(reload_servers(resolv->name, dnamebuff, servers, query_port), interfaces, &sfds); sighup = 0; signal(SIGHUP, sig_handler); } if (sigusr1) { signal(SIGUSR1, SIG_IGN); dump_cache(options & (OPT_DEBUG | OPT_LOG), cachesize); sigusr1 = 0; signal(SIGUSR1, sig_handler); } if (sigusr2) { signal(SIGUSR2, SIG_IGN); if (getuid() != 0 && port <= 1024) syslog(LOG_ERR, "cannot re-scan interfaces unless --user=root"); else { syslog(LOG_INFO, "rescanning network interfaces"); int_err_string = enumerate_interfaces(&interfaces, if_names, if_addrs, if_except, port); if (int_err_string) syslog(LOG_ERR, int_err_string, strerror(errno)); } sigusr2 = 0; signal(SIGUSR2, sig_handler); /* may be new file descriptors now, so redo select() */ ready = 0; } now = time(NULL); /* Check for changes to resolv files and DHCP leases file once per second max. */ if (last == 0 || now > last) { last = now; if (!(options & OPT_NO_POLL)) { struct resolvc *res = resolv, *latest = NULL; time_t last_change = 0; /* There may be more than one possible file. Go through and find the one which changed _last_. Warn of any which can't be read. */ while (res) { if (stat(res->name, &statbuf) == -1) { if (!res->logged) syslog(LOG_WARNING, "failed to access %s: %m", res->name); res->logged = 1; } else { res->logged = 0; if (statbuf.st_mtime > last_change) { last_change = statbuf.st_mtime; latest = res; } } res = res->next; } if (latest && last_change > resolv_changed) { resolv_changed = last_change; servers = last_server = check_servers(reload_servers(latest->name, dnamebuff, servers, query_port), interfaces, &sfds); } } if (lease_file) { syslog(LOG_WARNING, "checking lease file %s", lease_file); if (stat(lease_file, &statbuf) == -1) { if (!logged_lease) syslog(LOG_WARNING, "failed to access %s: %m", lease_file); logged_lease = 1; } else { logged_lease = 0; if ((statbuf.st_mtime != lease_file_change) || (statbuf.st_ino != lease_file_inode)) { lease_file_change = statbuf.st_mtime; lease_file_inode = statbuf.st_ino; load_dhcp(lease_file, domain_suffix, now, dnamebuff); } } } } if (ready == 0) continue; /* no sockets ready */ for (serverfdp = sfds; serverfdp; serverfdp = serverfdp->next) if (FD_ISSET(serverfdp->fd, &rset)) last_server = reply_query(serverfdp->fd, options, packet, now, dnamebuff, last_server, bogus_addr); for (iface = interfaces; iface; iface = iface->next) { if (FD_ISSET(iface->fd, &rset)) { /* request packet, deal with query */ union mysockaddr udpaddr; socklen_t udplen = sizeof(udpaddr); int m, n = recvfrom(iface->fd, packet, PACKETSZ, 0, &udpaddr.sa, &udplen); udpaddr.sa.sa_family = iface->addr.sa.sa_family; #ifdef HAVE_IPV6 if (udpaddr.sa.sa_family == AF_INET6) udpaddr.in6.sin6_flowinfo = htonl(0); #endif header = (HEADER *)packet; if (n >= (int)sizeof(HEADER) && !header->qr) { if (extract_request(header, (unsigned int)n, dnamebuff)) { if (udpaddr.sa.sa_family == AF_INET) log_query(F_QUERY | F_IPV4 | F_FORWARD, dnamebuff, (struct all_addr *)&udpaddr.in.sin_addr); #ifdef HAVE_IPV6 else log_query(F_QUERY | F_IPV6 | F_FORWARD, dnamebuff, (struct all_addr *)&udpaddr.in6.sin6_addr); #endif } m = answer_request (header, ((char *) header) + PACKETSZ, (unsigned int)n, mxname, mxtarget, options, now, local_ttl, dnamebuff); if (m >= 1) { /* answered from cache, send reply */ sendto(iface->fd, (char *)header, m, 0, &udpaddr.sa, sa_len(&udpaddr)); } else { /* cannot answer from cache, send on to real nameserver */ last_server = forward_query(iface->fd, &udpaddr, header, n, options, dnamebuff, servers, last_server, now, local_ttl); } } } } } return 0; }
/* The daemon forks before calling this: it should deal with one connection, blocking as neccessary, and then return. Note, need to be a bit careful about resources for debug mode, when the fork is suppressed: that's done by the caller. */ unsigned char *tcp_request(int confd, time_t now, struct in_addr local_addr, struct in_addr netmask) { int size = 0; size_t m; unsigned short qtype, gotname; unsigned char c1, c2; /* Max TCP packet + slop */ unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ); HEADER *header; struct server *last_server; while (1) { if (!packet || !read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) || !(size = c1 << 8 | c2) || !read_write(confd, packet, size, 1)) return packet; if (size < (int)sizeof(HEADER)) continue; header = (HEADER *)packet; if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype))) { union mysockaddr peer_addr; socklen_t peer_len = sizeof(union mysockaddr); if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) != -1) { char types[20]; querystr(types, qtype); if (peer_addr.sa.sa_family == AF_INET) log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, (struct all_addr *)&peer_addr.in.sin_addr, types); #ifdef HAVE_IPV6 else log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff, (struct all_addr *)&peer_addr.in6.sin6_addr, types); #endif } } /* m > 0 if answered from cache */ m = answer_request(header, ((char *) header) + 65536, (unsigned int)size, local_addr, netmask, now); /* Do this by steam now we're not in the select() loop */ check_log_writer(NULL); if (m == 0) { unsigned short flags = 0; struct all_addr *addrp = NULL; int type = 0; char *domain = NULL; if (gotname) flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain); if (type != 0 || (daemon->options & OPT_ORDER) || !daemon->last_server) last_server = daemon->servers; else last_server = daemon->last_server; if (!flags && last_server) { struct server *firstsendto = NULL; unsigned int crc = questions_crc(header, (unsigned int)size, daemon->namebuff); /* Loop round available servers until we succeed in connecting to one. Note that this code subtley ensures that consecutive queries on this connection which can go to the same server, do so. */ while (1) { if (!firstsendto) firstsendto = last_server; else { if (!(last_server = last_server->next)) last_server = daemon->servers; if (last_server == firstsendto) break; } /* server for wrong domain */ if (type != (last_server->flags & SERV_TYPE) || (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, last_server->domain))) continue; if ((last_server->tcpfd == -1) && (last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) != -1 && (!local_bind(last_server->tcpfd, &last_server->source_addr, last_server->interface, last_server->mark, 1) || connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1)) { close(last_server->tcpfd); last_server->tcpfd = -1; } if (last_server->tcpfd == -1) continue; c1 = size >> 8; c2 = size; if (!read_write(last_server->tcpfd, &c1, 1, 0) || !read_write(last_server->tcpfd, &c2, 1, 0) || !read_write(last_server->tcpfd, packet, size, 0) || !read_write(last_server->tcpfd, &c1, 1, 1) || !read_write(last_server->tcpfd, &c2, 1, 1)) { close(last_server->tcpfd); last_server->tcpfd = -1; continue; } m = (c1 << 8) | c2; if (!read_write(last_server->tcpfd, packet, m, 1)) return packet; if (!gotname) strcpy(daemon->namebuff, "query"); if (last_server->addr.sa.sa_family == AF_INET) log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff, (struct all_addr *)&last_server->addr.in.sin_addr, NULL); #ifdef HAVE_IPV6 else log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff, (struct all_addr *)&last_server->addr.in6.sin6_addr, NULL); #endif /* There's no point in updating the cache, since this process will exit and lose the information after a few queries. We make this call for the alias and bogus-nxdomain side-effects. */ /* If the crc of the question section doesn't match the crc we sent, then someone might be attempting to insert bogus values into the cache by sending replies containing questions and bogus answers. */ if (crc == questions_crc(header, (unsigned int)m, daemon->namebuff)) m = process_reply(header, now, last_server, (unsigned int)m); break; } } /* In case of local answer or no connections made. */ if (m == 0) m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl); } check_log_writer(NULL); c1 = m>>8; c2 = m; if (!read_write(confd, &c1, 1, 0) || !read_write(confd, &c2, 1, 0) || !read_write(confd, packet, m, 0)) return packet; }
void receive_query(struct listener *listen, time_t now) { HEADER *header = (HEADER *)daemon->packet; union mysockaddr source_addr; unsigned short type; struct all_addr dst_addr; struct in_addr netmask, dst_addr_4; size_t m; ssize_t n; int if_index = 0; struct iovec iov[1]; struct msghdr msg; struct cmsghdr *cmptr; union { struct cmsghdr align; /* this ensures alignment */ #ifdef HAVE_IPV6 char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; #endif #if defined(HAVE_LINUX_NETWORK) char control[CMSG_SPACE(sizeof(struct in_pktinfo))]; #elif defined(IP_RECVDSTADDR) char control[CMSG_SPACE(sizeof(struct in_addr)) + CMSG_SPACE(sizeof(struct sockaddr_dl))]; #endif } control_u; /* packet buffer overwritten */ daemon->srv_save = NULL; if (listen->family == AF_INET && (daemon->options & OPT_NOWILD)) { dst_addr_4 = listen->iface->addr.in.sin_addr; netmask = listen->iface->netmask; } else { dst_addr_4.s_addr = 0; netmask.s_addr = 0; } iov[0].iov_base = daemon->packet; iov[0].iov_len = daemon->edns_pktsz; msg.msg_control = control_u.control; msg.msg_controllen = sizeof(control_u); msg.msg_flags = 0; msg.msg_name = &source_addr; msg.msg_namelen = sizeof(source_addr); msg.msg_iov = iov; msg.msg_iovlen = 1; if ((n = recvmsg(listen->fd, &msg, 0)) == -1) return; if (n < (int)sizeof(HEADER) || (msg.msg_flags & MSG_TRUNC) || header->qr) return; source_addr.sa.sa_family = listen->family; #ifdef HAVE_IPV6 if (listen->family == AF_INET6) source_addr.in6.sin6_flowinfo = 0; #endif if (!(daemon->options & OPT_NOWILD)) { struct ifreq ifr; if (msg.msg_controllen < sizeof(struct cmsghdr)) return; #if defined(HAVE_LINUX_NETWORK) if (listen->family == AF_INET) for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO) { dst_addr_4 = dst_addr.addr.addr4 = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_spec_dst; if_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex; } #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF) if (listen->family == AF_INET) { for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR) dst_addr_4 = dst_addr.addr.addr4 = *((struct in_addr *)CMSG_DATA(cmptr)); else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF) if_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index; } #endif #ifdef HAVE_IPV6 if (listen->family == AF_INET6) { for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) if (cmptr->cmsg_level == IPV6_LEVEL && cmptr->cmsg_type == IPV6_PKTINFO) { dst_addr.addr.addr6 = ((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_addr; if_index =((struct in6_pktinfo *)CMSG_DATA(cmptr))->ipi6_ifindex; } } #endif /* enforce available interface configuration */ if (!indextoname(listen->fd, if_index, ifr.ifr_name) || !iface_check(listen->family, &dst_addr, ifr.ifr_name, &if_index)) return; if (listen->family == AF_INET && (daemon->options & OPT_LOCALISE) && ioctl(listen->fd, SIOCGIFNETMASK, &ifr) == -1) return; netmask = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr; } if (extract_request(header, (size_t)n, daemon->namebuff, &type)) { char types[20]; querystr(types, type); if (listen->family == AF_INET) log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, (struct all_addr *)&source_addr.in.sin_addr, types); #ifdef HAVE_IPV6 else log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff, (struct all_addr *)&source_addr.in6.sin6_addr, types); #endif } m = answer_request (header, ((char *) header) + PACKETSZ, (size_t)n, dst_addr_4, netmask, now); if (m >= 1) { send_from(listen->fd, daemon->options & OPT_NOWILD, (char *)header, m, &source_addr, &dst_addr, if_index); daemon->local_answer++; } else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index, header, (size_t)n, now, NULL)) daemon->queries_forwarded++; else daemon->local_answer++; }
void receive_query(struct listener *listen, time_t now) { struct dns_header *header = (struct dns_header *)daemon->packet; union mysockaddr source_addr; unsigned short type; struct all_addr dst_addr; struct in_addr netmask, dst_addr_4; size_t m; ssize_t n; int if_index = 0; struct iovec iov[1]; struct msghdr msg; struct cmsghdr *cmptr; union { struct cmsghdr align; /* this ensures alignment */ #ifdef HAVE_IPV6 char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; #endif #if defined(HAVE_LINUX_NETWORK) char control[CMSG_SPACE(sizeof(struct in_pktinfo))]; #elif defined(IP_RECVDSTADDR) && defined(HAVE_SOLARIS_NETWORK) char control[CMSG_SPACE(sizeof(struct in_addr)) + CMSG_SPACE(sizeof(unsigned int))]; #elif defined(IP_RECVDSTADDR) char control[CMSG_SPACE(sizeof(struct in_addr)) + CMSG_SPACE(sizeof(struct sockaddr_dl))]; #endif } control_u; /* packet buffer overwritten */ daemon->srv_save = NULL; if (listen->iface && listen->family == AF_INET && option_bool(OPT_NOWILD)) { dst_addr_4 = listen->iface->addr.in.sin_addr; netmask = listen->iface->netmask; } else { dst_addr_4.s_addr = 0; netmask.s_addr = 0; } iov[0].iov_base = daemon->packet; iov[0].iov_len = daemon->edns_pktsz; msg.msg_control = control_u.control; msg.msg_controllen = sizeof(control_u); msg.msg_flags = 0; msg.msg_name = &source_addr; msg.msg_namelen = sizeof(source_addr); msg.msg_iov = iov; msg.msg_iovlen = 1; if ((n = recvmsg(listen->fd, &msg, 0)) == -1) return; if (n < (int)sizeof(struct dns_header) || (msg.msg_flags & MSG_TRUNC) || (header->hb3 & HB3_QR)) return; source_addr.sa.sa_family = listen->family; #ifdef HAVE_IPV6 if (listen->family == AF_INET6) source_addr.in6.sin6_flowinfo = 0; #endif if (!option_bool(OPT_NOWILD)) { struct ifreq ifr; if (msg.msg_controllen < sizeof(struct cmsghdr)) return; #if defined(HAVE_LINUX_NETWORK) if (listen->family == AF_INET) for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO) { union { unsigned char *c; struct in_pktinfo *p; } p; p.c = CMSG_DATA(cmptr); dst_addr_4 = dst_addr.addr.addr4 = p.p->ipi_spec_dst; if_index = p.p->ipi_ifindex; } #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF) if (listen->family == AF_INET) { for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) { union { unsigned char *c; unsigned int *i; struct in_addr *a; #ifndef HAVE_SOLARIS_NETWORK struct sockaddr_dl *s; #endif } p; p.c = CMSG_DATA(cmptr); if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR) dst_addr_4 = dst_addr.addr.addr4 = *(p.a); else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF) #ifdef HAVE_SOLARIS_NETWORK if_index = *(p.i); #else if_index = p.s->sdl_index; #endif } } #endif #ifdef HAVE_IPV6 if (listen->family == AF_INET6) { for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo) { union { unsigned char *c; struct in6_pktinfo *p; } p; p.c = CMSG_DATA(cmptr); dst_addr.addr.addr6 = p.p->ipi6_addr; if_index = p.p->ipi6_ifindex; } } #endif /* enforce available interface configuration */ if (!indextoname(listen->fd, if_index, ifr.ifr_name) || !iface_check(listen->family, &dst_addr, ifr.ifr_name)) return; if (listen->family == AF_INET && option_bool(OPT_LOCALISE)) { struct irec *iface; /* get the netmask of the interface whch has the address we were sent to. This is no neccessarily the interface we arrived on. */ for (iface = daemon->interfaces; iface; iface = iface->next) if (iface->addr.sa.sa_family == AF_INET && iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr) break; /* interface may be new */ if (!iface) enumerate_interfaces(); for (iface = daemon->interfaces; iface; iface = iface->next) if (iface->addr.sa.sa_family == AF_INET && iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr) break; /* If we failed, abandon localisation */ if (iface) netmask = iface->netmask; else dst_addr_4.s_addr = 0; } } if (extract_request(header, (size_t)n, daemon->namebuff, &type)) { char types[20]; querystr(types, type); if (listen->family == AF_INET) log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, (struct all_addr *)&source_addr.in.sin_addr, types); #ifdef HAVE_IPV6 else log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff, (struct all_addr *)&source_addr.in6.sin6_addr, types); #endif } m = answer_request (header, ((char *) header) + PACKETSZ, (size_t)n, dst_addr_4, netmask, now); if (m >= 1) { send_from(listen->fd, option_bool(OPT_NOWILD), (char *)header, m, &source_addr, &dst_addr, if_index); daemon->local_answer++; } else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index, header, (size_t)n, now, NULL)) daemon->queries_forwarded++; else daemon->local_answer++; }
int main (int argc, char **argv) { int i; int cachesize = CACHESIZ; int port = NAMESERVER_PORT; unsigned int options; int first_loop = 1; #ifdef HAVE_FILE_SYSTEM int logged_resolv = 0, logged_lease = 0; char *resolv = RESOLVFILE; char *runfile = RUNFILE; time_t resolv_changed = 0; char *lease_file = NULL; off_t lease_file_size = (off_t)0; ino_t lease_file_inode = (ino_t)0; #endif struct irec *iface; int peerfd, peerfd6; struct irec *interfaces = NULL; char *mxname = NULL; char *mxtarget = NULL; char *domain_suffix = NULL; char *username = CHUSER; struct iname *if_names = NULL; struct iname *if_addrs = NULL; struct server *serv_addrs = NULL; char *dnamebuff, *packet; struct server *servers, *last_server; sighup = 1; /* init cache the first time through */ sigusr1 = 0; /* but don't dump */ signal(SIGUSR1, sig_handler); signal(SIGHUP, sig_handler); /* These get allocated here to avoid overflowing the small stack on embedded systems. dnamebuff is big enough to hold one maximal sixed domain name and gets passed into all the processing code. We manage to get away with one buffer. */ dnamebuff = safe_malloc(MAXDNAME); /* Size: we check after adding each record, so there must be memory for the largest packet, and the largest record */ packet = safe_malloc(PACKETSZ+MAXDNAME+RRFIXEDSZ); #ifdef HAVE_FILE_SYSTEM options = read_opts(argc, argv, dnamebuff, &resolv, &mxname, &mxtarget, &lease_file, &username, &domain_suffix, &runfile, &if_names, &if_addrs, &serv_addrs, &cachesize, &port) ; #else options = read_opts(argc, argv, dnamebuff, NULL, &mxname, &mxtarget, NULL, &username, &domain_suffix, NULL, &if_names, &if_addrs, &serv_addrs, &cachesize, &port) ; #endif /* peerfd is not bound to a low port so that we can send queries out on it without them getting blocked at firewalls */ if ((peerfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 && errno != EAFNOSUPPORT && errno != EINVAL) die("dnsmasq: cannot create socket: %s", NULL); #ifdef HAVE_IPV6 if ((peerfd6 = socket(AF_INET6, SOCK_DGRAM, 0)) == -1 && errno != EAFNOSUPPORT && errno != EINVAL) die("dnsmasq: cannot create IPv6 socket: %s", NULL); #else peerfd6 = -1; #endif if (peerfd == -1 && peerfd6 == -1) die("dnsmasq: no kernel support for IPv4 _or_ IPv6.", NULL); interfaces = find_all_interfaces(if_names, if_addrs, port); /* open a socket bound to NS port on each local interface. this is necessary to ensure that our replies originate from the address they were sent to. See Stevens page 531 */ for (iface = interfaces; iface; iface = iface->next) { if ((iface->fd = socket(iface->addr.sa.sa_family, SOCK_DGRAM, 0)) == -1) die("cannot create socket: %s", NULL); if (bind(iface->fd, &iface->addr.sa, sa_len(&iface->addr))) die("bind failed: %s", NULL); } forward_init(1); cache_init(cachesize, options & OPT_LOG); setbuf(stdout, NULL); #ifdef HAVE_FILE_SYSTEM if (!(options & OPT_DEBUG)) { FILE *pidfile; struct passwd *ent_pw; /* The following code "daemonizes" the process. See Stevens section 12.4 */ #ifdef HAVE_FORK if (fork() != 0 ) exit(0); setsid(); if (fork() != 0) exit(0); #endif chdir("/"); umask(022); /* make pidfile 0644 */ /* write pidfile _after_ forking ! */ if (runfile && (pidfile = fopen(runfile, "w"))) { fprintf(pidfile, "%d\n", (int) getpid()); fclose(pidfile); } umask(0); for (i=0; i<64; i++) { if (i == peerfd || i == peerfd6) continue; for (iface = interfaces; iface; iface = iface->next) if (iface->fd == i) break; if (!iface) close(i); } /* Change uid and gid for security */ if (username && (ent_pw = getpwnam(username))) { gid_t dummy; struct group *gp; /* remove all supplimentary groups */ setgroups(0, &dummy); /* change group to "dip" if it exists, for /etc/ppp/resolv.conf otherwise get the group for "nobody" */ if ((gp = getgrnam("dip")) || (gp = getgrgid(ent_pw->pw_gid))) setgid(gp->gr_gid); /* finally drop root */ setuid(ent_pw->pw_uid); } } #else #endif /* In debug mode, log to stderr too and cut the prefix crap. */ openlog("dnsmasq", options & OPT_DEBUG ? LOG_PERROR : LOG_PID, LOG_DAEMON); if (cachesize) syslog(LOG_INFO, "started, version %s cachesize %d", VERSION, cachesize); else syslog(LOG_INFO, "started, version %s cache disabled", VERSION); if (mxname) syslog(LOG_INFO, "serving MX record for mailhost %s target %s", mxname, mxtarget); if (getuid() == 0 || geteuid() == 0) syslog(LOG_WARNING, "failed to drop root privs"); serv_addrs = servers = last_server = check_servers(serv_addrs, interfaces, peerfd, peerfd6); while (1) { int ready, maxfd = peerfd > peerfd6 ? peerfd : peerfd6; fd_set rset; HEADER *header; #ifdef HAVE_FILE_SYSTEM struct stat statbuf; #endif if (first_loop) /* do init stuff only first time round. */ { first_loop = 0; ready = 0; } else { FD_ZERO(&rset); if (peerfd != -1) FD_SET(peerfd, &rset); if (peerfd6 != -1) FD_SET(peerfd6, &rset); for (iface = interfaces; iface; iface = iface->next) { FD_SET(iface->fd, &rset); if (iface->fd > maxfd) maxfd = iface->fd; } ready = select(maxfd+1, &rset, NULL, NULL, NULL); if (ready == -1) { if (errno == EINTR) ready = 0; /* do signal handlers */ else continue; } } #ifdef HAVE_FILE_SYSTEM if (sighup) { signal(SIGHUP, SIG_IGN); cache_reload(options & OPT_NO_HOSTS, dnamebuff); if (resolv && (options & OPT_NO_POLL)) servers = last_server = check_servers(reload_servers(resolv, dnamebuff, servers), interfaces, peerfd, peerfd6); sighup = 0; signal(SIGHUP, sig_handler); } if (sigusr1) { signal(SIGUSR1, SIG_IGN); dump_cache(options & (OPT_DEBUG | OPT_LOG), cachesize); sigusr1 = 0; signal(SIGUSR1, sig_handler); } if (resolv && !(options & OPT_NO_POLL)) { if (stat(resolv, &statbuf) == -1) { if (!logged_resolv) syslog(LOG_WARNING, "failed to access %s: %m", resolv); logged_resolv = 1; } else { logged_resolv = 0; if ((statbuf.st_mtime > resolv_changed) && (statbuf.st_mtime < time(NULL) || resolv_changed == 0)) { resolv_changed = statbuf.st_mtime; servers = last_server = check_servers(reload_servers(resolv, dnamebuff, servers), interfaces, peerfd, peerfd6); } } } #else #endif #ifdef HAVE_FILE_SYSTEM if (lease_file) { if (stat(lease_file, &statbuf) == -1) { if (!logged_lease) syslog(LOG_WARNING, "failed to access %s: %m", lease_file); logged_lease = 1; } else { logged_lease = 0; if ((lease_file_size == (off_t)0) || (statbuf.st_size > lease_file_size) || (statbuf.st_ino != lease_file_inode)) { lease_file_size = statbuf.st_size; lease_file_inode = statbuf.st_ino; load_dhcp(lease_file, domain_suffix, time(NULL), dnamebuff); } } } #else #endif if (ready == 0) continue; /* no sockets ready */ if (peerfd != -1 && FD_ISSET(peerfd, &rset)) last_server = reply_query(peerfd, packet, dnamebuff, last_server); if (peerfd6 != -1 && FD_ISSET(peerfd6, &rset)) last_server = reply_query(peerfd6, packet, dnamebuff, last_server); for (iface = interfaces; iface; iface = iface->next) { if (FD_ISSET(iface->fd, &rset)) { /* request packet, deal with query */ union mysockaddr udpaddr; socklen_t udplen = sizeof(udpaddr); int m, n = recvfrom(iface->fd, packet, PACKETSZ, 0, &udpaddr.sa, &udplen); udpaddr.sa.sa_family = iface->addr.sa.sa_family; #ifdef HAVE_IPV6 if (udpaddr.sa.sa_family == AF_INET6) udpaddr.in6.sin6_flowinfo = htonl(0); #endif header = (HEADER *)packet; if (n >= (int)sizeof(HEADER) && !header->qr) { m = answer_request (header, ((char *) header) + PACKETSZ, (unsigned int)n, mxname, mxtarget, options, dnamebuff); if (m >= 1) { /* answered from cache, send reply */ sendto(iface->fd, (char *)header, m, 0, &udpaddr.sa, sa_len(&udpaddr)); } else { /* cannot answer from cache, send on to real nameserver */ last_server = forward_query(iface->fd, peerfd, peerfd6, &udpaddr, header, n, options && OPT_ORDER, dnamebuff, servers, last_server); } } } } } return 0; }
void main(TCommandLine cmd) { fshutdown=-1; agent_state = 3; vccID = cmd.argv(0); agentID = cmd.argv(1); passwd = cmd.argv(2); var TInteger FSM; FSM = getfsmid(); CorrelationKey = sprintf('%04d', FSM); print(sprintf('***The SL %s starts ,vccID:%s agentID:%s passwd:%s ***\n', CorrelationKey,vccID,agentID,passwd)); initialize_packet(); initial(); while(fshutdown==-1) { print(sprintf('***The SL %s is alive', CorrelationKey)); sleep(2); } on(serviceEvent, TCommandLine backevent) { print(sprintf('***The SL %s got message is %s***\n', CorrelationKey, backevent.argv())); var TString xmlstr = strstr(backevent.argv(),'<acp'); var TXMLTree root = hxmlparse(xmlstr); var TString type, name; type = hxmlgetattr(root, 'acpMessage/body/type' , 'null'); if(type!='null') { name = hxmlgetattr(root, 'acpMessage/body/name', 'null'); switch(type) { case 'response': if(name == 'Initial') { var TString ip = hxmlgetattr(root,'acpMessage/body/parameter/ip', 'null'); var TInteger port = atoi(hxmlgetattr(root,'acpMessage/body/parameter/port','0')); sign_in(ip, port); } else if(name == 'SignIn') { agent_state=2; timeStamp = hxml(root,'acpMessage/header/timeStamp', 'null'); send_state_msg(); set_idle(); } else if(name == 'SetIdle') { agent_state=0; var TString temp = hxmlgetattr(root, 'acpMessage/header/timeStamp', 'null'); if(timeStamp == '') { if(temp != 'null') timeStamp = temp; } send_state_msg(); } break; case 'event': if(name == 'OnAnswerRequest') answer_request(); else if(name == 'OnForceOut') { agent_state=3; send_state_msg(); force_out(); } else if(name == 'OnAnswerSuccess') answer_success(); break; default: print(sprintf('***The SL %s got unknown cmd***\n', CorrelationKey)); }