X-Git-Url: http://dolda2000.com/gitweb/?a=blobdiff_plain;f=icmpdnd.c;h=3cd6f5f3cee1d12bf765126a033b6e7d59d296b6;hb=15a913c297d12c0a4b14c01437420ac0df8b6675;hp=0169e6daf552da7e759c03cc8c0f6d87442ecc90;hpb=fa6ac2fc3180a275d59bff8da4e4883fd40a5de7;p=icmp-dn.git diff --git a/icmpdnd.c b/icmpdnd.c index 0169e6d..3cd6f5f 100644 --- a/icmpdnd.c +++ b/icmpdnd.c @@ -1,6 +1,6 @@ /* * icmpdnd - ICMP Domain Name responder daemon for Linux - * Copyright (C) 2004 Fredrik Tolf + * Copyright (C) 2005 Fredrik Tolf * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include #include @@ -53,8 +55,6 @@ struct rephdr { #define ICMP_NAMEREQ 37 #define ICMP_NAMEREP 38 -#define TTL 3600 - volatile int alive; size_t filldn(char *dst) @@ -131,53 +131,85 @@ void cksum(void *hdr, size_t len) int main(int argc, char **argv) { int ret; - int s, namelen, datalen; + int c, s, namelen, datalen; + int daemonize, ttl; unsigned char buf[65536]; struct sockaddr_in name; struct reqhdr req; struct rephdr rep; struct iphdr iphdr; - + time_t curtime, lasterr; + + daemonize = 1; + ttl = 3600; + while((c = getopt(argc, argv, "nht:")) != -1) { + switch(c) { + case 't': + ttl = atoi(optarg); + break; + case 'n': + daemonize = 0; + break; + case 'h': + case '?': + case ':': + default: + fprintf(stderr, "usage: icmpdnd [-n]"); + exit((c == 'h')?0:1); + } + } + if((s = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) { perror("could not create raw socket"); exit(1); } + if(daemonize) + daemon(0, 0); + + openlog("icmpdnd", LOG_PID, LOG_DAEMON); + alive = 1; + lasterr = 0; while(alive) { namelen = sizeof(name); ret = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *)&name, &namelen); + + curtime = time(NULL); if(ret < 0) { if(errno == EINTR) continue; - perror("recvfrom"); - exit(1); + syslog(LOG_ERR, "error in receiving datagram: %m"); + if(lasterr == curtime) { + syslog(LOG_CRIT, "exiting due to repeated errors"); + exit(1); + } + lasterr = curtime; } - if(ret < sizeof(iphdr)) + + if(ret < sizeof(iphdr) + sizeof(req)) continue; memcpy(&iphdr, buf, sizeof(iphdr)); + memcpy(&req, buf + sizeof(iphdr), sizeof(req)); if(iphdr.protocol != IPPROTO_ICMP) continue; - if(ret < sizeof(iphdr) + sizeof(req)) - continue; - memcpy(&req, buf + sizeof(iphdr), sizeof(req)); if(req.type != ICMP_NAMEREQ) continue; rep.type = ICMP_NAMEREP; rep.code = 0; rep.id = req.id; rep.seq = req.seq; - rep.ttl = htonl(TTL); + rep.ttl = htonl(ttl); memcpy(buf, &rep, sizeof(rep)); datalen = filldn(buf + sizeof(rep)); - + cksum(buf, datalen + sizeof(rep)); - + + /* XXX: The correct source address needs to be filled in from + * the request's destination address. */ ret = sendto(s, buf, datalen + sizeof(rep), 0, (struct sockaddr *)&name, namelen); - if(ret < 0) { - perror("sendto"); - exit(1); - } + if(ret < 0) + syslog(LOG_WARNING, "error in sending reply: %m"); } close(s);