IP option IP_RECVTTL question

2011-02-03 Thread Peter J. Philipp
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



Re: IP option IP_RECVTTL question

2011-02-03 Thread Otto Moerbeek
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



Re: IP option IP_RECVTTL question

2011-02-03 Thread Peter J. Philipp
On Thu, Feb 03, 2011 at 01:51:47PM +0100, Otto Moerbeek wrote:
 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

Hi,

At first glance it seems to be working with the FreeBSD code.  On both i386
and amd64.  Thanks!

So it must be a documentation bug.  Thanks for your help!

-peter