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

Reply via email to