support for IP_RECVDSTADDR.

git-svn-id: file:///svn/unbound/trunk@874 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2008-01-18 08:51:19 +00:00
parent 95b0a129e2
commit 306db56f1f
5 changed files with 77 additions and 25 deletions

View file

@ -1,3 +1,7 @@
18 January 2008: Wouter
- touch up of manpage for libunbound.
- support for IP_RECVDSTADDR (for *BSD ip4).
17 January 2008: Wouter 17 January 2008: Wouter
- fixup configure in case -lldns is installed. - fixup configure in case -lldns is installed.
- fixup a couple of doxygen warnings, about enum variables. - fixup a couple of doxygen warnings, about enum variables.

View file

@ -49,10 +49,14 @@
\fBub_val_ctx_add_ta\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR ta); \fBub_val_ctx_add_ta\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR ta);
.LP .LP
\fIint\fR \fIint\fR
\fBub_val_ctx_add_ta_file\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR fname); \fBub_val_ctx_add_ta_file\fR(\fIstruct ub_val_ctx*\fR ctx,
.br
\fIchar*\fR fname);
.LP .LP
\fIint\fR \fIint\fR
\fBub_val_ctx_trustedkeys\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR fname); \fBub_val_ctx_trustedkeys\fR(\fIstruct ub_val_ctx*\fR ctx,
.br
\fIchar*\fR fname);
.LP .LP
\fIint\fR \fIint\fR
\fBub_val_ctx_debuglevel\fR(\fIstruct ub_val_ctx*\fR ctx, \fIint\fR d); \fBub_val_ctx_debuglevel\fR(\fIstruct ub_val_ctx*\fR ctx, \fIint\fR d);
@ -160,11 +164,14 @@ Higher debug level gives more output.
.TP .TP
.B ub_val_ctx_async .B ub_val_ctx_async
Set a context behaviour for asynchronous action. Set a context behaviour for asynchronous action.
if set to true, enables threading and a call to resolve_async() if set to true, enables threading and a call to
.B ub_val_resolve_async
creates a thread to handle work in the background. creates a thread to handle work in the background.
If false, a process is forked to handle work in the background. If false, a process is forked to handle work in the background.
Changes to this setting after async() calls have been made have Changes to this setting after
no effect (delete and re\-create the context to change). .B ub_val_resolve_async
calls have been made have no effect (delete and re\-create the context
to change).
.TP .TP
.B ub_val_ctx_poll .B ub_val_ctx_poll
Poll a context to see if it has any new results. Poll a context to see if it has any new results.
@ -172,14 +179,14 @@ Do not poll in a loop, instead extract the fd below to poll for readiness,
and then check, or wait using the wait routine. and then check, or wait using the wait routine.
Returns 0 if nothing to read, or nonzero if a result is available. Returns 0 if nothing to read, or nonzero if a result is available.
If nonzero, call If nonzero, call
.B ctx_process .B ub_val_ctx_process
to do callbacks. to do callbacks.
.TP .TP
.B ub_val_ctx_wait .B ub_val_ctx_wait
Wait for a context to finish with results. Calls Wait for a context to finish with results. Calls
.B ub_val_ctx_process after .B ub_val_ctx_process
the wait for you. After the wait, there are no more outstanding asynchronous after the wait for you. After the wait, there are no more outstanding
queries. asynchronous queries.
.TP .TP
.B ub_val_ctx_fd .B ub_val_ctx_fd
Get file descriptor. Wait for it to become readable, at this point Get file descriptor. Wait for it to become readable, at this point
@ -203,7 +210,7 @@ The result structure is newly allocated with the resulting data.
Perform asynchronous resolution and validation of the target name. Perform asynchronous resolution and validation of the target name.
Arguments mean the same as for \fBub_val_resolve\fR except no Arguments mean the same as for \fBub_val_resolve\fR except no
data is returned immediately, instead a callback is called later. data is returned immediately, instead a callback is called later.
The callback receives a copy of the mydata point, that you can use to pass The callback receives a copy of the mydata pointer, that you can use to pass
information to the callback. The callback type is a function pointer to information to the callback. The callback type is a function pointer to
a function declared as a function declared as
.IP .IP
@ -239,8 +246,8 @@ The result of the DNS resolution and validation is returned as
int* len; /* array with lengths of rdata items */ int* len; /* array with lengths of rdata items */
char* canonname; /* canonical name of result */ char* canonname; /* canonical name of result */
int rcode; /* additional error code in case of error */ int rcode; /* additional error code in case of error */
int nxdomain; /* if nodata because no domain */ int nxdomain; /* true if nodata because no domain */
int bogus; /* if not secure due to security failure */ int bogus; /* true if there was a security failure */
}; };
.fi .fi
.SH "RETURN VALUES" .SH "RETURN VALUES"

View file

@ -264,14 +264,20 @@ set_ip6_recvpktinfo(int s)
return 0; return 0;
#endif /* defined IPV6_RECVPKTINFO */ #endif /* defined IPV6_RECVPKTINFO */
#ifdef IP_PKTINFO #ifdef IP_RECVDSTADDR
if(setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR,
&on, (socklen_t)sizeof(on)) < 0) {
log_err("setsockopt(..., IP_RECVDSTADDR, ...) failed: %s",
strerror(errno));
}
#elif defined(IP_PKTINFO)
if(setsockopt(s, IPPROTO_IP, IP_PKTINFO, if(setsockopt(s, IPPROTO_IP, IP_PKTINFO,
&on, (socklen_t)sizeof(on)) < 0) { &on, (socklen_t)sizeof(on)) < 0) {
log_err("setsockopt(..., IP_PKTINFO, ...) failed: %s", log_err("setsockopt(..., IP_PKTINFO, ...) failed: %s",
strerror(errno)); strerror(errno));
} }
#else #else
log_err("no IP_PKTINFO option, please disable " log_err("no IP_RECVDSTADDR or IP_PKTINFO option, please disable "
"interface-automatic in config"); "interface-automatic in config");
return 0; return 0;
#endif /* IP_PKTINFO */ #endif /* IP_PKTINFO */

View file

@ -181,7 +181,7 @@ comm_point_send_udp_msg(struct comm_point *c, ldns_buffer* packet,
/** print debug ancillary info */ /** print debug ancillary info */
void p_ancil(const char* str, struct comm_reply* r) void p_ancil(const char* str, struct comm_reply* r)
{ {
#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(IP_PKTINFO) #if defined(AF_INET6) && defined(IPV6_PKTINFO)
if(r->srctype != 4 && r->srctype != 6) { if(r->srctype != 4 && r->srctype != 6) {
log_info("%s: unknown srctype %d", str, r->srctype); log_info("%s: unknown srctype %d", str, r->srctype);
return; return;
@ -195,6 +195,15 @@ void p_ancil(const char* str, struct comm_reply* r)
buf[sizeof(buf)-1]=0; buf[sizeof(buf)-1]=0;
log_info("%s: %s %d", str, buf, r->pktinfo.v6info.ipi6_ifindex); log_info("%s: %s %d", str, buf, r->pktinfo.v6info.ipi6_ifindex);
} else if(r->srctype == 4) { } else if(r->srctype == 4) {
#ifdef IP_RECVDSTADDR
char buf1[1024];
if(inet_ntop(AF_INET, &r->pktinfo.v4addr,
buf1, (socklen_t)sizeof(buf1)) == 0) {
strncpy(buf1, "(inet_ntop error)", sizeof(buf1));
}
buf1[sizeof(buf1)-1]=0;
log_info("%s: %s", str, buf1);
#elif defined(IP_PKTINFO)
char buf1[1024], buf2[1024]; char buf1[1024], buf2[1024];
if(inet_ntop(AF_INET, &r->pktinfo.v4info.ipi_addr, if(inet_ntop(AF_INET, &r->pktinfo.v4info.ipi_addr,
buf1, (socklen_t)sizeof(buf1)) == 0) { buf1, (socklen_t)sizeof(buf1)) == 0) {
@ -208,6 +217,7 @@ void p_ancil(const char* str, struct comm_reply* r)
buf2[sizeof(buf2)-1]=0; buf2[sizeof(buf2)-1]=0;
log_info("%s: %d %s %s", str, r->pktinfo.v4info.ipi_ifindex, log_info("%s: %d %s %s", str, r->pktinfo.v4info.ipi_ifindex,
buf1, buf2); buf1, buf2);
#endif
} }
#endif #endif
} }
@ -217,7 +227,7 @@ int
comm_point_send_udp_msg_if(struct comm_point *c, ldns_buffer* packet, comm_point_send_udp_msg_if(struct comm_point *c, ldns_buffer* packet,
struct sockaddr* addr, socklen_t addrlen, struct comm_reply* r) struct sockaddr* addr, socklen_t addrlen, struct comm_reply* r)
{ {
#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(IP_PKTINFO) #if defined(AF_INET6) && defined(IPV6_PKTINFO)
ssize_t sent; ssize_t sent;
struct msghdr msg; struct msghdr msg;
struct iovec iov[1]; struct iovec iov[1];
@ -245,11 +255,19 @@ comm_point_send_udp_msg_if(struct comm_point *c, ldns_buffer* packet,
#ifndef S_SPLINT_S #ifndef S_SPLINT_S
cmsg = CMSG_FIRSTHDR(&msg); cmsg = CMSG_FIRSTHDR(&msg);
if(r->srctype == 4) { if(r->srctype == 4) {
#ifdef IP_RECVDSTADDR
cmsg->cmsg_level = IPPROTO_IP;
cmsg->cmsg_type = IP_RECVDSTADDR;
memmove(CMSG_DATA(cmsg), &r->pktinfo.v4addr,
sizeof(struct in_addr));
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
#elif defined(IP_PKTINFO)
cmsg->cmsg_level = IPPROTO_IP; cmsg->cmsg_level = IPPROTO_IP;
cmsg->cmsg_type = IP_PKTINFO; cmsg->cmsg_type = IP_PKTINFO;
memmove(CMSG_DATA(cmsg), &r->pktinfo.v4info, memmove(CMSG_DATA(cmsg), &r->pktinfo.v4info,
sizeof(struct in_pktinfo)); sizeof(struct in_pktinfo));
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
#endif
} else if(r->srctype == 6) { } else if(r->srctype == 6) {
cmsg->cmsg_level = IPPROTO_IPV6; cmsg->cmsg_level = IPPROTO_IPV6;
cmsg->cmsg_type = IPV6_PKTINFO; cmsg->cmsg_type = IPV6_PKTINFO;
@ -286,7 +304,7 @@ comm_point_send_udp_msg_if(struct comm_point *c, ldns_buffer* packet,
void void
comm_point_udp_ancil_callback(int fd, short event, void* arg) comm_point_udp_ancil_callback(int fd, short event, void* arg)
{ {
#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(IP_PKTINFO) #if defined(AF_INET6) && defined(IPV6_PKTINFO)
struct comm_reply rep; struct comm_reply rep;
struct msghdr msg; struct msghdr msg;
struct iovec iov[1]; struct iovec iov[1];
@ -334,19 +352,34 @@ comm_point_udp_ancil_callback(int fd, short event, void* arg)
log_info("looking at hdr %d %d (need %d %d or %d %d)", log_info("looking at hdr %d %d (need %d %d or %d %d)",
cmsg->cmsg_level, cmsg->cmsg_type, cmsg->cmsg_level, cmsg->cmsg_type,
IPPROTO_IPV6, IPV6_PKTINFO, IPPROTO_IPV6, IPV6_PKTINFO,
IPPROTO_IP, IP_PKTINFO); IPPROTO_IP,
#ifdef IP_RECVDSTADDR
IP_RECVDSTADDR
#elif defined(IP_PKTINFO)
IP_PKTINFO
#endif
);
if( cmsg->cmsg_level == IPPROTO_IPV6 && if( cmsg->cmsg_level == IPPROTO_IPV6 &&
cmsg->cmsg_type == IPV6_PKTINFO) { cmsg->cmsg_type == IPV6_PKTINFO) {
rep.srctype = 6; rep.srctype = 6;
memmove(&rep.pktinfo.v6info, CMSG_DATA(cmsg), memmove(&rep.pktinfo.v6info, CMSG_DATA(cmsg),
sizeof(struct in6_pktinfo)); sizeof(struct in6_pktinfo));
break; break;
#ifdef IP_RECVDSTADDR
} else if( cmsg->cmsg_level == IPPROTO_IP &&
cmsg->cmsg_type == IP_RECVDSTADDR) {
rep.srctype = 4;
memmove(&rep.v4addr, CMSG_DATA(cmsg),
sizeof(struct in_addr));
break;
#elif defined(IP_PKTINFO)
} else if( cmsg->cmsg_level == IPPROTO_IP && } else if( cmsg->cmsg_level == IPPROTO_IP &&
cmsg->cmsg_type == IP_PKTINFO) { cmsg->cmsg_type == IP_PKTINFO) {
rep.srctype = 4; rep.srctype = 4;
memmove(&rep.pktinfo.v4info, CMSG_DATA(cmsg), memmove(&rep.pktinfo.v4info, CMSG_DATA(cmsg),
sizeof(struct in_pktinfo)); sizeof(struct in_pktinfo));
break; break;
#endif
} }
} }
p_ancil("receive_udp on interface", &rep); p_ancil("receive_udp on interface", &rep);

View file

@ -105,7 +105,9 @@ struct comm_reply {
#ifdef IPV6_PKTINFO #ifdef IPV6_PKTINFO
struct in6_pktinfo v6info; struct in6_pktinfo v6info;
#endif #endif
#ifdef IP_PKTINFO #ifdef IP_RECVDSTADDR
struct in_addr v4addr;
#elif defined(IP_PKTINFO)
struct in_pktinfo v4info; struct in_pktinfo v4info;
#endif #endif
} }