main() { char *x; int udp53; x = env_get("IP"); if (!x) strerr_die2x(111,fatal,"$IP not set"); if (!ip4_scan(x,ip)) strerr_die3x(111,fatal,"unable to parse IP address ",x); udp53 = socket_udp(); if (udp53 == -1) strerr_die2sys(111,fatal,"unable to create UDP socket: "); if (socket_bind4_reuse(udp53,ip,53) == -1) strerr_die2sys(111,fatal,"unable to bind UDP socket: "); droproot(fatal); initialize(); ndelay_off(udp53); socket_tryreservein(udp53,65536); for (;;) { len = socket_recv4(udp53,buf,sizeof buf,ip,&port); if (len < 0) continue; if (!doit()) continue; if (response_len > 512) response_tc(); socket_send4(udp53,response,response_len,ip,port); /* may block for buffer space; if it fails, too bad */ } }
int main (int argc, char *argv[]) { time_t t = 0; char *x = NULL; struct sigaction sa; iopause_fd *iop = NULL; int i = 0, n = 0, *udp53 = NULL; prog = strdup ((x = strrchr (argv[0], '/')) != NULL ? x + 1 : argv[0]); sa.sa_handler = handle_term; sigaction (SIGINT, &sa, NULL); sigaction (SIGTERM, &sa, NULL); sa.sa_handler = SIG_IGN; sigaction (SIGPIPE, &sa, NULL); i = check_option (argc, argv); argc -= i; argv += i; if (mode & DAEMON) { i = fork (); if (i == -1) err (-1, "could not fork a daemon process"); if (i > 0) return 0; } time (&t); memset (buf, 0, sizeof (buf)); strftime (buf, sizeof (buf), "%b-%d %Y %T %Z", localtime (&t)); warnx ("version %s: starting: %s\n", VERSION, buf); set_timezone (); if (debug_level) warnx ("TIMEZONE: %s", env_get ("TZ")); initialize (); if (!debug_level) if ((x = env_get ("DEBUG_LEVEL"))) debug_level = atol (x); warnx ("DEBUG_LEVEL set to `%d'", debug_level); if ((x = env_get ("DATALIMIT"))) { struct rlimit r; unsigned long dlimit = atol (x); if (getrlimit (RLIMIT_DATA, &r) != 0) err (-1, "could not get resource RLIMIT_DATA"); r.rlim_cur = (dlimit <= r.rlim_max) ? dlimit : r.rlim_max; if (setrlimit (RLIMIT_DATA, &r) != 0) err (-1, "could not set resource RLIMIT_DATA"); if (debug_level) warnx ("DATALIMIT set to `%ld' bytes", r.rlim_cur); } if (!(x = env_get ("IP"))) err (-1, "$IP not set"); for (i = 0; (unsigned)i < strlen (x); i++) n = (x[i] == ',') ? n+1 : n; if (!(udp53 = calloc (n+1, sizeof (int)))) err (-1, "could not allocate enough memory for udp53"); if (!(iop = calloc (n+1, sizeof (iopause_fd)))) err (-1, "could not allocate enough memory for iop"); i = n = 0; while (x[i]) { unsigned int l = 0; if (!(l = ip4_scan(x+i, ip))) errx (-1, "could not parse IP address `%s'", x + i); udp53[n] = socket_udp(); if (udp53[n] == -1) errx (-1, "could not open UDP socket"); if (socket_bind4_reuse (udp53[n], ip, server_port) == -1) errx (-1, "could not bind UDP socket"); ndelay_off (udp53[n]); socket_tryreservein (udp53[n], 65536); iop[n].fd = udp53[n]; iop[n].events = IOPAUSE_READ; n++; i += (x[i + l] == ',') ? l + 1 : l; } droproot (); while (1) { struct taia stamp; struct in_addr odst; /* original destination IP */ struct taia deadline; taia_now (&stamp); taia_uint (&deadline, 300); taia_add (&deadline, &deadline, &stamp); iopause (iop, n, &deadline, &stamp); for (i = 0; i < n; i++) { if (!iop[i].revents) continue; len = socket_recv4 (udp53[i], buf, sizeof (buf), ip, &port, &odst); if (len < 0) continue; if (!doit ()) continue; if (response_len > 512) response_tc (); /* may block for buffer space; if it fails, too bad */ len = socket_send4 (udp53[i], response, response_len, ip, port, &odst); if (len < 0) continue; if (debug_level > 1) log_querydone(qnum, response, response_len); } } return 0; }
int main (int argc, char *argv[]) { int i = 0; time_t t = 0; struct sigaction sa; unsigned long cachesize = 0; char *x = NULL, char_seed[128]; sa.sa_handler = handle_term; sigaction (SIGINT, &sa, NULL); sigaction (SIGTERM, &sa, NULL); sa.sa_handler = SIG_IGN; sigaction (SIGPIPE, &sa, NULL); seed_addtime (); seed_adduint32 (getpid ()); seed_adduint32 (getppid ()); seed_adduint32 (getuid ()); seed_adduint32 (getgid ()); seed_addtime (); prog = strdup ((x = strrchr (argv[0], '/')) != NULL ? x + 1 : argv[0]); i = check_option (argc, argv); argc -= i; argv += i; if (mode & DAEMON) { i = fork (); if (i == -1) err (-1, "could not fork a daemon process"); if (i > 0) return 0; } time (&t); strftime (char_seed, sizeof (char_seed), "%b-%d %Y %T %Z", localtime (&t)); warnx ("version %s: starting: %s\n", VERSION, char_seed); set_timezone (); if (debug_level) warnx ("TIMEZONE: %s", env_get ("TZ")); read_conf (CFGFILE); if (!debug_level) if ((x = env_get ("DEBUG_LEVEL"))) debug_level = atol (x); warnx ("DEBUG_LEVEL set to `%d'", debug_level); if ((x = env_get ("DATALIMIT"))) { struct rlimit r; unsigned long dlimit = atol (x); if (getrlimit (RLIMIT_DATA, &r) != 0) err (-1, "could not get resource RLIMIT_DATA"); r.rlim_cur = (dlimit <= r.rlim_max) ? dlimit : r.rlim_max; if (setrlimit (RLIMIT_DATA, &r) != 0) err (-1, "could not set resource RLIMIT_DATA"); if (debug_level) warnx ("DATALIMIT set to `%ld' bytes", r.rlim_cur); } if (!(x = env_get ("IP"))) err (-1, "$IP not set"); if (!ip4_scan (x, myipincoming)) err (-1, "could not parse IP address `%s'", x); seed_addtime (); udp53 = socket_udp (); if (udp53 == -1) err (-1, "could not open UDP socket"); if (socket_bind4_reuse (udp53, myipincoming, 53) == -1) err (-1, "could not bind UDP socket"); seed_addtime (); tcp53 = socket_tcp (); if (tcp53 == -1) err (-1, "could not open TCP socket"); if (socket_bind4_reuse (tcp53, myipincoming, 53) == -1) err (-1, "could not bind TCP socket"); if (mode & DAEMON) { /* redirect stdout & stderr to a log file */ redirect_to_log (LOGFILE, STDOUT_FILENO | STDERR_FILENO); write_pid (PIDFILE); } seed_addtime (); droproot (); if (mode & DAEMON) /* crerate a new session & detach from controlling tty */ if (setsid () < 0) err (-1, "could not start a new session for the daemon"); seed_addtime (); socket_tryreservein (udp53, 131072); memset (char_seed, 0, sizeof (char_seed)); for (i = 0, x = (char *)seed; (unsigned)i < sizeof (char_seed); i++, x++) char_seed[i] = *x; dns_random_init (char_seed); if (!(x = env_get ("IPSEND"))) err (-1, "$IPSEND not set"); if (!ip4_scan (x, myipoutgoing)) err (-1, "could not parse IP address `%s'", x); if (!(x = env_get ("CACHESIZE"))) err (-1, "$CACHESIZE not set"); scan_ulong (x, &cachesize); if (!cache_init (cachesize)) err (-1, "could not allocate `%ld' bytes for cache", cachesize); if (env_get ("HIDETTL")) response_hidettl (); if (env_get ("FORWARDONLY")) query_forwardonly (); if (env_get ("MERGEQUERIES")) dns_enable_merge (log_merge); if (!roots_init ()) err (-1, "could not read servers"); if (debug_level > 3) roots_display(); if (socket_listen (tcp53, 20) == -1) err (-1, "could not listen on TCP socket"); if (!dbl_init() && debug_level > 1) warnx ("could not read dnsbl.cdb"); doit (); return 0; }
void process_args(nmsgtool_ctx *c) { char *t; FILE *fp_pidfile = NULL; nmsg_msgmod_t mod = NULL; if (c->help) usage(NULL); if (c->version) { #ifdef HAVE_LIBXS fprintf(stderr, "%s: version %s\n", argv_program, PACKAGE_VERSION); #else /* HAVE_LIBXS */ fprintf(stderr, "%s: version %s (without libxs support)\n", argv_program, PACKAGE_VERSION); #endif /* HAVE_LIBXS */ exit(EXIT_SUCCESS); } if (c->endline == NULL) c->endline_str = strdup("\n"); else c->endline_str = unescape(c->endline); if (c->mtu == 0) c->mtu = NMSG_WBUFSZ_JUMBO; if (c->vname == NULL && c->mname != NULL) c->vname = "base"; if (c->vname != NULL) { if (c->mname == NULL) usage("-V requires -T"); c->vid = nmsg_msgmod_vname_to_vid(c->vname); if (c->vid == 0) usage("invalid vendor ID"); if (c->debug >= 2) fprintf(stderr, "%s: input vendor = %s\n", argv_program, c->vname); } if (c->mname != NULL) { if (c->vname == NULL) usage("-T requires -V"); c->msgtype = nmsg_msgmod_mname_to_msgtype(c->vid, c->mname); if (c->msgtype == 0) usage("invalid message type"); if (c->debug >= 2) fprintf(stderr, "%s: input msgtype = %s\n", argv_program, c->mname); } if (c->debug < 1) c->debug = 1; if (c->debug > 0) nmsg_io_set_debug(c->io, c->debug); if (c->count > 0) nmsg_io_set_count(c->io, c->count); if (c->interval > 0) nmsg_io_set_interval(c->io, c->interval); if (c->mirror == true) nmsg_io_set_output_mode(c->io, nmsg_io_output_mode_mirror); /* bpf string */ if (c->bpfstr == NULL) { t = getenv("NMSG_BPF"); if (t != NULL) c->bpfstr = strdup(t); } /* kicker command */ if (c->kicker == NULL) { t = getenv("NMSG_KICKER"); if (t != NULL) c->kicker = strdup(t); } /* set source, operator, group */ if (c->set_source_str != NULL) { c->set_source = (unsigned) strtoul(c->set_source_str, &t, 0); if (*t != '\0') usage("invalid source ID"); if (c->debug >= 2) fprintf(stderr, "%s: nmsg source set to %#.08x\n", argv_program, c->set_source); } if (c->set_operator_str != NULL) { c->set_operator = nmsg_alias_by_value(nmsg_alias_operator, c->set_operator_str); if (c->set_operator == 0) usage("unknown operator name"); if (c->debug >= 2) fprintf(stderr, "%s: nmsg operator set to '%s' (%u)\n", argv_program, c->set_operator_str, c->set_operator); } if (c->set_group_str != NULL) { c->set_group = nmsg_alias_by_value(nmsg_alias_group, c->set_group_str); if (c->set_group == 0) usage("unknown group name"); if (c->debug >= 2) fprintf(stderr, "%s: nmsg group set to '%s' (%u)\n", argv_program, c->set_group_str, c->set_group); } /* get source, operator, group */ if (c->get_source_str != NULL) { c->get_source = (unsigned) strtoul(c->get_source_str, &t, 0); if (*t != '\0') usage("invalid filter source ID"); if (c->debug >= 2) fprintf(stderr, "%s: nmsg source filter set to " "%#.08x\n", argv_program, c->get_source); } if (c->get_operator_str != NULL) { c->get_operator = nmsg_alias_by_value(nmsg_alias_operator, c->get_operator_str); if (c->get_operator == 0) usage("unknown filter operator name"); if (c->debug >= 2) fprintf(stderr, "%s: nmsg filter operator set to " "'%s' (%u)\n", argv_program, c->get_operator_str, c->get_operator); } if (c->get_group_str != NULL) { c->get_group = nmsg_alias_by_value(nmsg_alias_group, c->get_group_str); if (c->get_group == 0) usage("unknown filter group name"); if (c->debug >= 2) fprintf(stderr, "%s: nmsg filter group set to " "'%s' (%u)\n", argv_program, c->get_group_str, c->get_group); } /* -V, -T sanity check */ if (ARGV_ARRAY_COUNT(c->r_pres) > 0 || ARGV_ARRAY_COUNT(c->r_pcapfile) > 0 || ARGV_ARRAY_COUNT(c->r_pcapif) > 0) { if (c->vname == NULL || c->mname == NULL) usage("reading presentation or pcap data requires " "-V, -T"); mod = nmsg_msgmod_lookup(c->vid, c->msgtype); if (mod == NULL) usage("unknown msgmod"); } #define process_args_loop(arry, func) do { \ for (int i = 0; i < ARGV_ARRAY_COUNT(arry); i++) \ func(c, *ARGV_ARRAY_ENTRY_P(arry, char *, i)); \ } while(0) #define process_args_loop_mod(arry, func, mod) do { \ for (int i = 0; i < ARGV_ARRAY_COUNT(arry); i++) \ func(c, mod, *ARGV_ARRAY_ENTRY_P(arry, char *, i)); \ } while(0) /* pcap interface inputs */ process_args_loop_mod(c->r_pcapif, add_pcapif_input, mod); /* open pidfile if necessary */ if (c->pidfile != NULL) fp_pidfile = pidfile_open(c->pidfile); else fp_pidfile = NULL; /* drop privileges */ if (c->username != NULL) droproot(c, fp_pidfile); /* pcap file inputs */ process_args_loop_mod(c->r_pcapfile, add_pcapfile_input, mod); /* XS context */ if (ARGV_ARRAY_COUNT(c->r_xsock) > 0 || ARGV_ARRAY_COUNT(c->w_xsock) > 0 || ARGV_ARRAY_COUNT(c->r_xchannel) > 0) { #ifdef HAVE_LIBXS c->xs_ctx = xs_init(); if (c->xs_ctx == NULL) { fprintf(stderr, "%s: xs_init() failed: %s\n", argv_program, strerror(errno)); exit(EXIT_FAILURE); } #else /* HAVE_LIBXS */ fprintf(stderr, "%s: Error: compiled without libxs support\n", argv_program); exit(EXIT_FAILURE); #endif /* HAVE_LIBXS */ } /* nmsg inputs and outputs */ process_args_loop(c->r_sock, add_sock_input); process_args_loop(c->w_sock, add_sock_output); process_args_loop(c->r_xsock, add_xsock_input); process_args_loop(c->w_xsock, add_xsock_output); process_args_loop(c->r_nmsg, add_file_input); process_args_loop(c->w_nmsg, add_file_output); for (int i = 0; i < ARGV_ARRAY_COUNT(c->r_channel); i++) { char *ch; char **alias = NULL; int num_aliases; ch = *ARGV_ARRAY_ENTRY_P(c->r_channel, char *, i); if (c->debug >= 2) fprintf(stderr, "%s: looking up channel '%s'\n", argv_program, ch); num_aliases = nmsg_chalias_lookup(ch, &alias); if (num_aliases <= 0) usage("channel alias lookup failed"); for (int j = 0; j < num_aliases; j++) { if (strstr(alias[j], "://")) usage("channel alias appears to be an xchannel"); add_sock_input(c, alias[j]); } nmsg_chalias_free(&alias); } for (int i = 0; i < ARGV_ARRAY_COUNT(c->r_xchannel); i++) { char *ch; char **alias = NULL; int num_aliases; ch = *ARGV_ARRAY_ENTRY_P(c->r_xchannel, char *, i); if (c->debug >= 2) fprintf(stderr, "%s: looking up xchannel '%s'\n", argv_program, ch); num_aliases = nmsg_chalias_lookup(ch, &alias); if (num_aliases <= 0) usage("xchannel alias lookup failed"); for (int j = 0; j < num_aliases; j++) add_xsock_input(c, alias[j]); nmsg_chalias_free(&alias); } /* pres inputs and outputs */ process_args_loop_mod(c->r_pres, add_pres_input, mod); process_args_loop(c->w_pres, add_pres_output); #undef process_args_loop #undef process_args_loop_mod /* validation */ if (c->n_inputs == 0) usage("no data sources specified"); if (c->n_outputs == 0) { /* implicit "-o -" */ add_pres_output(c, "-"); } /* daemonize if necessary */ if (c->daemon) { if (!daemonize()) { fprintf(stderr, "nmsgtool: unable to daemonize: %s\n", strerror(errno)); exit(EXIT_FAILURE); } } /* write pidfile if necessary */ if (c->pidfile != NULL && fp_pidfile != NULL) pidfile_write(fp_pidfile); }
int main (int argc, char *argv[]) { int n = 0; time_t t = 0; struct sigaction sa; char qtype[2]; char qclass[2]; char header[12]; const char *x = NULL; unsigned int pos = 0; unsigned long long qnum = 0; sa.sa_handler = handle_term; sigaction (SIGINT, &sa, NULL); sigaction (SIGTERM, &sa, NULL); sa.sa_handler = SIG_IGN; sigaction (SIGPIPE, &sa, NULL); prog = strdup ((x = strrchr (argv[0], '/')) != NULL ? x + 1 : argv[0]); n = check_option (argc, argv); argc -= n; argv += n; if (mode & DAEMON) /* redirect stderr to a log file */ redirect_to_log (logfile, STDERR_FILENO); time (&t); memset (seed, 0, sizeof (seed)); strftime (seed, sizeof (seed), "%b-%d %Y %T %Z", localtime (&t)); warnx ("version %s: starting %s\n", VERSION, seed); set_timezone (); if (debug_level) warnx ("TIMEZONE: %s", env_get ("TZ")); read_conf (cfgfile); if (!debug_level) if ((x = env_get ("DEBUG_LEVEL"))) debug_level = atol (x); warnx ("DEBUG_LEVEL set to `%d'", debug_level); dns_random_init (seed); axfr = env_get ("AXFR"); if (debug_level) warnx ("AXFR set to `%s'", axfr); x = env_get ("TCPREMOTEIP"); if (debug_level) warnx ("TCPREMOTEIP set to `%s'", x); if (x) ip4_scan (x, ip); else byte_zero (ip, 4); x = env_get ("TCPREMOTEPORT"); if (debug_level) warnx ("TCPREMOTEPORT set to `%s'", x); if (!x) x = "0"; scan_ulong (x, &port); droproot (); for (;;) { netread (tcpheader, 2); uint16_unpack_big (tcpheader, &len); if (len > 512) errx (-1, "excessively large request"); netread (buf, len); pos = dns_packet_copy (buf, len, 0, header, 12); if (!pos) errx (-1, "truncated request"); if (header[2] & 254) errx (-1, "bogus query"); if (header[4] || (header[5] != 1)) errx (-1, "bogus query"); pos = dns_packet_getname (buf, len, pos, &zone); if (!pos) errx (-1, "truncated request"); zonelen = dns_domain_length (zone); pos = dns_packet_copy (buf, len, pos, qtype, 2); if (!pos) errx (-1, "truncated request"); pos = dns_packet_copy (buf, len, pos, qclass, 2); if (!pos) errx (-1, "truncated request"); if (byte_diff(qclass, 2, DNS_C_IN) && byte_diff(qclass, 2, DNS_C_ANY)) errx (-1, "bogus query: bad class"); log_query (++qnum, ip, port, header, zone, qtype); if (byte_equal(qtype,2,DNS_T_AXFR)) { case_lowerb (zone, zonelen); fdcdb = open_read ("data.cdb"); if (fdcdb == -1) errx (-1, "could not read from file `data.cdb'"); doaxfr (header); close (fdcdb); } else { if (!response_query (zone, qtype, qclass)) err (-1, "could not allocate enough memory"); response[2] |= 4; case_lowerb (zone, zonelen); response_id (header); response[3] &= ~128; if (!(header[2] & 1)) response[2] &= ~1; if (!respond (zone, qtype, ip)) errx (-1, "could not find information in file `data.cdb'"); print (response, response_len); } } }
int main() { unsigned char *remotehost, *remoteinfo, *remoteip, *remoteport; unsigned char query[256]; unsigned char clean_query[256]; unsigned char *qptr, *qptr2; int len, query_len; int fd, r = 0; struct cdb c; stralloc answer = {0}; /* chroot() to $ROOT and switch to $UID:$GID */ droproot("dffingerd: "); /* since we run under tcpserver, we can get all info about the remote side from the enviroment */ remotehost = env_get("TCPREMOTEHOST"); if (!remotehost) remotehost = "unknown"; remoteinfo = env_get("TCPREMOTEINFO"); if (!remoteinfo) remoteinfo = "-"; remoteip = env_get("TCPREMOTEIP"); if (!remoteip) remoteip = "unknown"; remoteport = env_get("TCPREMOTEPORT"); if (!remoteport) remoteport = "unknown"; /* now: remotehost is the remote hostname or "unknown" remoteinfo is some ident string or "-" remoteip is the remote ipadress or "unknown" (?) */ /* Read the request from the client and \0-terminate it */ /* timeout after 60 seconds */ query_len = timeoutread(60, stdin, query, sizeof(query) - 1); query[query_len] = '\0'; /* Handle RfC 1288 stuff */ qptr=query; if (*qptr==' ') qptr++; if (*qptr=='/' && (*(qptr+1)=='W' || *(qptr+1)=='w') && *(qptr+2) == ' ') qptr+=3; /* \0-terminate query at the first \r or \n */ for (len = 0; query[len]; len++) { if (query[len] == '\r' || query[len] == '\n') { query[len] = '\0'; break; } } /* clean up query string a bit by removing chars witch could clobber logging or so and replace them with _ -> extra Paranoia */ for(qptr2 = clean_query; *qptr; qptr++) { if(is_meta (*qptr)) { *qptr2++ = '_'; } else { *qptr2++ = *qptr; } } *qptr2 = '\0'; /* Do logging */ buffer_puts(buffer_2, remotehost); buffer_puts(buffer_2, " ["); buffer_puts(buffer_2, remoteip); buffer_puts(buffer_2, ":"); buffer_puts(buffer_2, remoteport); buffer_puts(buffer_2, "] "); buffer_puts(buffer_2, remoteinfo); buffer_puts(buffer_2, " "); buffer_puts(buffer_2, clean_query); buffer_puts(buffer_2, "\n"); buffer_flush(buffer_2); /* If there was any data we will go on */ if (query_len > 0) { /* Open & init our cdb */ fd = open_read("data.cdb"); if (fd == -1) { /* If opening failed quit */ strerr_die2sys(111, FATAL, "can't open data.cdb"); } cdb_init(&c, fd); /* Search query for "user" on the database */ r = cdb_find(&c, clean_query, str_len(clean_query)); if (r == 1) { /* read data */ stralloc_ready(&answer, cdb_datalen(&c)); if (cdb_read(&c, answer.s, cdb_datalen(&c), cdb_datapos(&c)) == -1) { strerr_die2sys(111, FATAL, "can't read from data.cdb"); } else { answer.len = cdb_datalen(&c); } } else { /* We didn't find the requested user, try DEFAULTUSER */ r = cdb_find(&c,DEFAULTUSER, str_len(DEFAULTUSER)); if (r == 1) { /* read data */ stralloc_ready(&answer, cdb_datalen(&c)); if (cdb_read(&c, answer.s ,cdb_datalen(&c) ,cdb_datapos(&c)) == -1) { strerr_die2sys(111, FATAL, "can't read from data.cdb"); } else { answer.len = cdb_datalen(&c); } } else { /* no data for DEFAULTUSER either, so we don't have any data for the client */ stralloc_copys(&answer, NOPE); } } /* write to the network with 120s timeout */ /* I guess the timeout isn't needed on an usual Unix */ r = timeoutwrite(120, stdout, answer.s, answer.len); if (r <= 0) { strerr_die2sys(111, FATAL, "unable to write to network: "); } /* free database */ cdb_free(&c); close(fd); } else { *clean_query = '\0'; } return 0; }
int main() { char *x; unsigned int i, j, k; unsigned long cachesize; static stralloc sa = {0}; x = env_get("INTERFACE"); if (x) scan_ulong(x,&interface); x = env_get("IP"); if (!x) strerr_die2x(111,FATAL,"$IP not set"); if (!ip6_scan(x,myipincoming)) strerr_die3x(111,FATAL,"unable to parse IP address ",x); #if 0 /* if if IP is a mapped-IPv4 address, disable IPv6 functionality */ /* this is actually a bad idea */ if (ip6_isv4mapped(myipincoming)) noipv6 = 1; #endif udp53 = socket_udp6(); if (udp53 == -1) strerr_die2sys(111,FATAL,"unable to create UDP socket: "); if (socket_bind6_reuse(udp53,myipincoming,53,interface) == -1) strerr_die2sys(111,FATAL,"unable to bind UDP socket: "); tcp53 = socket_tcp6(); if (tcp53 == -1) strerr_die2sys(111,FATAL,"unable to create TCP socket: "); if (socket_bind6_reuse(tcp53,myipincoming,53,interface) == -1) strerr_die2sys(111,FATAL,"unable to bind TCP socket: "); droproot(FATAL); socket_tryreservein(udp53,131072); byte_zero(seed,sizeof seed); read(0,seed,sizeof seed); dns_random_init(seed); close(0); x = env_get("IPSEND"); if (!x) strerr_die2x(111,FATAL,"$IPSEND not set"); if (!ip6_scan(x,myipoutgoing)) strerr_die3x(111,FATAL,"unable to parse IP address ",x); x = env_get("CACHESIZE"); if (!x) strerr_die2x(111,FATAL,"$CACHESIZE not set"); scan_ulong(x,&cachesize); if (!cache_init(cachesize)) strerr_die3x(111,FATAL,"not enough memory for cache of size ",x); if (openreadclose("ignoreip",&sa,64) < 0) strerr_die2x(111,FATAL,"trouble reading ignoreip"); for(j = k = i = 0; i < sa.len; i++) if (sa.s[i] == '\n') { sa.s[i] = '\0'; if (!stralloc_readyplus(&ignoreip,16)) strerr_die2x(111,FATAL,"out of memory parsing ignoreip"); if (!ip6_scan(sa.s+k,ignoreip.s+j)) strerr_die3x(111,FATAL,"unable to parse address in ignoreip ",ignoreip.s+k); j += 16; k = i + 1; } ignoreip.len = j; if (env_get("HIDETTL")) response_hidettl(); if (env_get("FORWARDONLY")) query_forwardonly(); if (!roots_init()) strerr_die2sys(111,FATAL,"unable to read servers: "); if (socket_listen(tcp53,20) == -1) strerr_die2sys(111,FATAL,"unable to listen on TCP socket: "); log_startup(); doit(); }
int main() { unsigned int pos; char header[12]; char qtype[2]; char qclass[2]; const char *x; droproot(FATAL); dns_random_init(seed); axfr = env_get("AXFR"); x = env_get("TCPREMOTEIP"); if (x && ip6_scan(x,ip)) ; else byte_zero(ip,16); x = env_get("TCPREMOTEPORT"); if (!x) x = "0"; scan_ulong(x,&port); for (;;) { netread(tcpheader,2); uint16_unpack_big(tcpheader,&len); if (len > 512) strerr_die2x(111,FATAL,"excessively large request"); netread(buf,len); pos = dns_packet_copy(buf,len,0,header,12); if (!pos) die_truncated(); if (header[2] & 254) strerr_die2x(111,FATAL,"bogus query"); if (header[4] || (header[5] != 1)) strerr_die2x(111,FATAL,"bogus query"); pos = dns_packet_getname(buf,len,pos,&zone); if (!pos) die_truncated(); zonelen = dns_domain_length(zone); pos = dns_packet_copy(buf,len,pos,qtype,2); if (!pos) die_truncated(); pos = dns_packet_copy(buf,len,pos,qclass,2); if (!pos) die_truncated(); if (byte_diff(qclass,2,DNS_C_IN) && byte_diff(qclass,2,DNS_C_ANY)) strerr_die2x(111,FATAL,"bogus query: bad class"); pos = check_edns0(header, buf, len, pos); if (!pos) die_truncated(); qlog(ip,port,header,zone,qtype," "); if (byte_equal(qtype,2,DNS_T_AXFR)) { case_lowerb(zone,zonelen); fdcdb = open_read("data.cdb"); if (fdcdb == -1) die_cdbread(); doaxfr(header); close(fdcdb); } else { if (!response_query(zone,qtype,qclass)) nomem(); response[2] |= 4; case_lowerb(zone,zonelen); response_id(header); response[3] &= ~128; if (!(header[2] & 1)) response[2] &= ~1; if (!respond(zone,qtype,ip)) die_outside(); print(response,response_len); } } }