On Thu, Feb 03, 2011 at 12:24:37PM +0100, Peter J. Philipp wrote:
> 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.
This looks like a documentation error. Actually, the data length is
CMSG_LEN(sizeof(u_char)), as can be seen in
src/netinet/ip_input.c:1744 and the implementation of
sbcreatecontrol() in src/kern/uipc_socket2.c. Try the FreeBSD code, it
looks that has a goof chanche of working.
If this is indeed the case, I'd like to know so I can fix the man page.
-Otto
>
> 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