+18 January 2008: Wouter
+ - touch up of manpage for libunbound.
+ - support for IP_RECVDSTADDR (for *BSD ip4).
+
17 January 2008: Wouter
- fixup configure in case -lldns is installed.
- fixup a couple of doxygen warnings, about enum variables.
\fBub_val_ctx_add_ta\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR ta);
.LP
\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
\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
\fIint\fR
\fBub_val_ctx_debuglevel\fR(\fIstruct ub_val_ctx*\fR ctx, \fIint\fR d);
\fIint\fR
\fBub_val_resolve\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR name,
.br
- \fIint\fR rrtype, \fIint\fR rrclass, \fIint*\fR secure,
+ \fIint\fR rrtype, \fIint\fR rrclass, \fIint*\fR secure,
.br
- \fIint*\fR data, \fIstruct ub_val_result**\fR result);
+ \fIint*\fR data, \fIstruct ub_val_result**\fR result);
.LP
\fIint\fR
\fBub_val_resolve_async\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR name,
.br
- \fIint\fR rrtype, \fIint\fR rrclass, \fIvoid*\fR mydata,
+ \fIint\fR rrtype, \fIint\fR rrclass, \fIvoid*\fR mydata,
.br
- \fIub_val_callback_t\fR callback, \fIint*\fR async_id);
+ \fIub_val_callback_t\fR callback, \fIint*\fR async_id);
.LP
\fIint\fR
\fBub_val_cancel\fR(\fIstruct ub_val_ctx*\fR ctx, \fIint\fR async_id);
.TP
.B ub_val_ctx_async
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.
If false, a process is forked to handle work in the background.
-Changes to this setting after async() calls have been made have
-no effect (delete and re\-create the context to change).
+Changes to this setting after
+.B ub_val_resolve_async
+calls have been made have no effect (delete and re\-create the context
+to change).
.TP
.B ub_val_ctx_poll
Poll a context to see if it has any new results.
and then check, or wait using the wait routine.
Returns 0 if nothing to read, or nonzero if a result is available.
If nonzero, call
-.B ctx_process
+.B ub_val_ctx_process
to do callbacks.
.TP
.B ub_val_ctx_wait
Wait for a context to finish with results. Calls
-.B ub_val_ctx_process after
-the wait for you. After the wait, there are no more outstanding asynchronous
-queries.
+.B ub_val_ctx_process
+after the wait for you. After the wait, there are no more outstanding
+asynchronous queries.
.TP
.B ub_val_ctx_fd
Get file descriptor. Wait for it to become readable, at this point
Perform asynchronous resolution and validation of the target name.
Arguments mean the same as for \fBub_val_resolve\fR except no
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
a function declared as
.IP
void my_callback_function(void* my_arg, int err,
.br
- int secure, int havedata,
+ int secure, int havedata,
.br
- struct ub_val_result* result);
+ struct ub_val_result* result);
.IP
The async_id is returned so you can (at your option) decide to track it
and cancel the request if needed.
int* len; /* array with lengths of rdata items */
char* canonname; /* canonical name of result */
int rcode; /* additional error code in case of error */
- int nxdomain; /* if nodata because no domain */
- int bogus; /* if not secure due to security failure */
+ int nxdomain; /* true if nodata because no domain */
+ int bogus; /* true if there was a security failure */
};
.fi
.SH "RETURN VALUES"
return 0;
#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,
&on, (socklen_t)sizeof(on)) < 0) {
log_err("setsockopt(..., IP_PKTINFO, ...) failed: %s",
strerror(errno));
}
#else
- log_err("no IP_PKTINFO option, please disable "
+ log_err("no IP_RECVDSTADDR or IP_PKTINFO option, please disable "
"interface-automatic in config");
return 0;
#endif /* IP_PKTINFO */
/** print debug ancillary info */
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) {
log_info("%s: unknown srctype %d", str, r->srctype);
return;
buf[sizeof(buf)-1]=0;
log_info("%s: %s %d", str, buf, r->pktinfo.v6info.ipi6_ifindex);
} 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];
if(inet_ntop(AF_INET, &r->pktinfo.v4info.ipi_addr,
buf1, (socklen_t)sizeof(buf1)) == 0) {
buf2[sizeof(buf2)-1]=0;
log_info("%s: %d %s %s", str, r->pktinfo.v4info.ipi_ifindex,
buf1, buf2);
+#endif
}
#endif
}
comm_point_send_udp_msg_if(struct comm_point *c, ldns_buffer* packet,
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;
struct msghdr msg;
struct iovec iov[1];
#ifndef S_SPLINT_S
cmsg = CMSG_FIRSTHDR(&msg);
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_type = IP_PKTINFO;
memmove(CMSG_DATA(cmsg), &r->pktinfo.v4info,
sizeof(struct in_pktinfo));
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
+#endif
} else if(r->srctype == 6) {
cmsg->cmsg_level = IPPROTO_IPV6;
cmsg->cmsg_type = IPV6_PKTINFO;
void
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 msghdr msg;
struct iovec iov[1];
log_info("looking at hdr %d %d (need %d %d or %d %d)",
cmsg->cmsg_level, cmsg->cmsg_type,
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 &&
cmsg->cmsg_type == IPV6_PKTINFO) {
rep.srctype = 6;
memmove(&rep.pktinfo.v6info, CMSG_DATA(cmsg),
sizeof(struct in6_pktinfo));
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 &&
cmsg->cmsg_type == IP_PKTINFO) {
rep.srctype = 4;
memmove(&rep.pktinfo.v4info, CMSG_DATA(cmsg),
sizeof(struct in_pktinfo));
break;
+#endif
}
}
p_ancil("receive_udp on interface", &rep);
#ifdef IPV6_PKTINFO
struct in6_pktinfo v6info;
#endif
-#ifdef IP_PKTINFO
+#ifdef IP_RECVDSTADDR
+ struct in_addr v4addr;
+#elif defined(IP_PKTINFO)
struct in_pktinfo v4info;
#endif
}