Hi,
I wrote a DNS server and I'm collecting TTL information from the remote
nameservers that query my daemon. Everything works well, when I view the
logs I see:
Feb 3 10:43:48 uranus wildcarddnsd[5705]: request on descriptor 14 interface
"em0" from XXX.XXX.XXX.XX (ttl=113, region=255) for "centroid.eu." type=A(1)
class=1, answering "centroid.eu."
Where the TTL is logged as 113 in this example.
But occasionally I get this on OpenBSD/i386 and /amd64...
Feb 3 10:45:01 uranus wildcarddnsd[5705]: request on descriptor 14 interface
"em0" from XXX.XX.XX.XX (ttl=27263547, region=255) for "goldflipper.net."
type=A(1) class=1, answering "goldflipper.net."
Where the TTL is a bad value. I think I'm using the code the right way after
the manpage ip(4):
If the IP_RECVTTL option is enabled on a SOCK_DGRAM or SOCK_RAW socket,
the recvmsg(2) call will return the TTL of the received datagram. The
msg_control field in the msghdr structure points to a buffer that
contains a cmsghdr structure followed by the TTL value. The cmsghdr
fields have the following values:
cmsg_len = CMSG_LEN(sizeof(struct in_addr))
cmsg_level = IPPROTO_IP
cmsg_type = IP_RECVTTL
And if I'm not mistaken the size of struct in_addr is 4.
Since sourceforge is down I can't refer you to the webcvs but they still
offer the files for download if you want to take a peak at the source code
that'd be great! http://sourceforge.net/projects/wildcarddns/files/
Here are some snippets from my source code perhaps you can spot what I'm
doing wrong?
...
if (setsockopt(udp[i], IPPROTO_IP, IP_RECVTTL, &on, sizeof(on)) < 0) {
...
#ifdef __FreeBSD__
u_char *ttlptr;
#elif __OpenBSD__
struct in_addr *ttlptr;
#else
int *ttlptr;
#endif
u_int32_t received_ttl;
...
#if __FreeBSD__
ttlptr = (u_char *) CMSG_DATA(cmsg);
received_ttl = (u_int)*ttlptr;
#elif __OpenBSD__
ttlptr = (struct in_addr *) CMSG_DATA(cmsg);
memcpy(&received_ttl, ttlptr, sizeof(u_int32_t));
#else
ttlptr = (int *) CMSG_DATA(cmsg);
received_ttl = (u_int)*ttlptr;
#endif
...
syslog(LOG_INFO, "request on descriptor %u interface \"%s\" from %s (ttl=%u,
region=%d) for \"%s\" type=%s class=%u, answering \"%s\"", so, ident[i],
address, received_ttl, aregion, question->converted_name,
get_dns_type(ntohs(question->hdr->qtype)), ntohs(question->hdr->qclass),
replystring);
...
Unfortunately this #define hell is a mess but it's the only way to get this
portable among BSD's and Linux. I'm hoping someone can tell where I'm going
wrong with this and why it's right sometimes and wrong the occasional time.
Regards,
-peter