manual and pktinfo.
git-svn-id: https://unbound.nlnetlabs.nl/svn/trunk@873 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
53d2c4e67b
commit
dda09cdbb0
@ -3,6 +3,8 @@
|
||||
- fixup a couple of doxygen warnings, about enum variables.
|
||||
- interface-automatic now copies the interface address from the
|
||||
PKT_INFO structure as well.
|
||||
- manual page with library API, all on one page 'man libunbound'.
|
||||
- rewrite of PKTINFO structure, it also captures IP4 PKTINFO.
|
||||
|
||||
16 January 2008: Wouter
|
||||
- incoming queries to the server with TC bit on are replied FORMERR.
|
||||
|
1
doc/TODO
1
doc/TODO
@ -56,3 +56,4 @@ o in an ipv6 connected only environment unbound cannot use outgoing IP6
|
||||
V6ONLY socket option.
|
||||
o support multiple dns messages in a TCP query stream for the unbound server.
|
||||
o SIG(0) and TSIG.
|
||||
o examine errno threaded trouble with EAGAIN in netevent.
|
||||
|
264
doc/libunbound.3
Normal file
264
doc/libunbound.3
Normal file
@ -0,0 +1,264 @@
|
||||
.TH "libunbound" "3" "@date@" "NLnet Labs" "unbound @version@"
|
||||
.\"
|
||||
.\" libunbound.3 -- unbound library functions manual
|
||||
.\"
|
||||
.\" Copyright (c) 2007, NLnet Labs. All rights reserved.
|
||||
.\"
|
||||
.\" See LICENSE for the license.
|
||||
.\"
|
||||
.\"
|
||||
.SH "NAME"
|
||||
.LP
|
||||
.B libunbound,
|
||||
.B unbound.h,
|
||||
.B ub_val_ctx,
|
||||
.B ub_val_result,
|
||||
.B ub_val_callback_t,
|
||||
.B ub_val_ctx_create,
|
||||
.B ub_val_ctx_delete,
|
||||
.B ub_val_ctx_config,
|
||||
.B ub_val_ctx_add_ta,
|
||||
.B ub_val_ctx_add_ta_file,
|
||||
.B ub_val_ctx_trustedkeys,
|
||||
.B ub_val_ctx_debuglevel,
|
||||
.B ub_val_ctx_async,
|
||||
.B ub_val_ctx_poll,
|
||||
.B ub_val_ctx_wait,
|
||||
.B ub_val_ctx_fd,
|
||||
.B ub_val_ctx_process,
|
||||
.B ub_val_resolve,
|
||||
.B ub_val_resolve_async,
|
||||
.B ub_val_cancel,
|
||||
.B ub_val_result_free,
|
||||
.B ub_val_strerror
|
||||
\- Unbound DNS validating resolver @version@ functions.
|
||||
.SH "SYNOPSIS"
|
||||
.LP
|
||||
.B #include <unbound.h>
|
||||
.LP
|
||||
\fIstruct ub_val_ctx *\fR
|
||||
\fBub_val_ctx_create\fR(\fIvoid\fR);
|
||||
.LP
|
||||
\fIvoid\fR
|
||||
\fBub_val_ctx_delete\fR(\fIstruct ub_val_ctx*\fR ctx);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_val_ctx_config\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR fname);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\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);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_val_ctx_trustedkeys\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR fname);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_val_ctx_debuglevel\fR(\fIstruct ub_val_ctx*\fR ctx, \fIint\fR d);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_val_ctx_async\fR(\fIstruct ub_val_ctx*\fR ctx, \fIint\fR dothread);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_val_ctx_poll\fR(\fIstruct ub_val_ctx*\fR ctx);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_val_ctx_wait\fR(\fIstruct ub_val_ctx*\fR ctx);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_val_ctx_fd\fR(\fIstruct ub_val_ctx*\fR ctx);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_val_ctx_process\fR(\fIstruct ub_val_ctx*\fR ctx);
|
||||
.LP
|
||||
\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,
|
||||
.br
|
||||
\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,
|
||||
.br
|
||||
\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);
|
||||
.LP
|
||||
\fIvoid\fR
|
||||
\fBub_val_result_free\fR(\fIstruct ub_val_result*\fR result);
|
||||
.LP
|
||||
\fIconst char *\fR
|
||||
\fBub_val_strerror\fR(\fIint\fR err);
|
||||
.SH "DESCRIPTION"
|
||||
.LP
|
||||
.B Unbound
|
||||
is an implementation of a DNS resolver, that does caching and
|
||||
DNSSEC validation. This is the library API, for using the \-lunbound library.
|
||||
The server daemon is described in \fIunbound\fR(8).
|
||||
The library can be used to convert hostnames to ip addresses, and back,
|
||||
and obtain other information from the DNS. The library performs public\-key
|
||||
validation of results with DNSSEC.
|
||||
.P
|
||||
The library uses a variable of type \fIstruct ub_val_ctx\fR to keep context
|
||||
between calls. The user must maintain it, creating it with
|
||||
.B ub_val_ctx_create
|
||||
and deleting it with
|
||||
.B ub_val_ctx_delete\fR.
|
||||
It can be created and deleted at any time. Creating it anew removes any
|
||||
previous configuration (such as trusted keys) and clears any cached results.
|
||||
.P
|
||||
The functions are thread\-safe, and a context an be used in a threaded (as
|
||||
well as in a non\-threaded) environment. Also resolution (and validation)
|
||||
can be performed blocking and non\-blocking (also called asynchronous).
|
||||
The async method returns from the call immediately, so that processing
|
||||
can go on, while the results become available later.
|
||||
.P
|
||||
The functions are discussed in turn below.
|
||||
.SH "FUNCTIONS"
|
||||
.TP
|
||||
.B ub_val_ctx_create
|
||||
Create a new context, initialised with defaults.
|
||||
.TP
|
||||
.B ub_val_ctx_delete
|
||||
Delete validation context and free associated resources.
|
||||
Outstanding async queries are killed and callbacks are not called for them.
|
||||
.TP
|
||||
.B ub_val_ctx_config
|
||||
A power\-user interface that lets you specify an unbound config file, see
|
||||
\fIunbound.conf\fR(5), which is read for configuration. Not all options are
|
||||
relevant. For some specific options, such as adding trust anchors, special
|
||||
routines exist.
|
||||
.TP
|
||||
.B
|
||||
ub_val_ctx_add_ta
|
||||
Add a trust anchor to the given context.
|
||||
At this time it is only possible to add trusted keys before the
|
||||
first resolve is done.
|
||||
The format is a string, similar to the zone-file format,
|
||||
[domainname] [type] [rdata contents]. Both DS and DNSKEY records are accepted.
|
||||
.TP
|
||||
.B ub_val_ctx_add_ta_file
|
||||
Add trust anchors to the given context.
|
||||
Pass name of a file with DS and DNSKEY records in zone file format.
|
||||
At this time it is only possible to add trusted keys before the
|
||||
first resolve is done.
|
||||
.TP
|
||||
.B ub_val_ctx_trustedkeys
|
||||
Add trust anchors to the given context.
|
||||
Pass the name of a bind-style config file with trusted-keys{}.
|
||||
At this time it is only possible to add trusted keys before the
|
||||
first resolve is done.
|
||||
.TP
|
||||
.B ub_val_ctx_debuglevel
|
||||
Set debug verbosity for the context. Output is directed to stderr.
|
||||
Higher debug level gives more output.
|
||||
.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()
|
||||
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).
|
||||
.TP
|
||||
.B ub_val_ctx_poll
|
||||
Poll a context to see if it has any new results.
|
||||
Do not poll in a loop, instead extract the fd below to poll for readiness,
|
||||
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
|
||||
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.
|
||||
.TP
|
||||
.B ub_val_ctx_fd
|
||||
Get file descriptor. Wait for it to become readable, at this point
|
||||
answers are returned from the asynchronous validating resolver.
|
||||
Then call the \fBub_val_ctx_process\fR to continue processing.
|
||||
.TP
|
||||
.B ub_val_ctx_process
|
||||
Call this routine to continue processing results from the validating
|
||||
resolver (when the fd becomes readable).
|
||||
Will perform necessary callbacks.
|
||||
.TP
|
||||
.B ub_val_resolve
|
||||
Perform resolution and validation of the target name.
|
||||
The name is a domain name in a zero terminated text string.
|
||||
The rrtype and rrclass are DNS type and class codes.
|
||||
The value secure returns true if the answer validated securely.
|
||||
The value data returns true if there was data.
|
||||
The result structure is newly allocated with the resulting data.
|
||||
.TP
|
||||
.B ub_val_resolve_async
|
||||
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
|
||||
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,
|
||||
.br
|
||||
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.
|
||||
.TP
|
||||
.B ub_val_cancel
|
||||
Cancel an async query in progress.
|
||||
.TP
|
||||
.B ub_val_result_free
|
||||
Free struct ub_val_result contents after use.
|
||||
.TP
|
||||
.B ub_val_strerror
|
||||
Convert error value from one of the unbound library functions
|
||||
to a human readable string.
|
||||
.SH "RESULT DATA STRUCTURE"
|
||||
.LP
|
||||
The result of the DNS resolution and validation is returned as
|
||||
\fIstruct ub_val_result\fR. The result structure contains the following entries.
|
||||
.P
|
||||
.nf
|
||||
struct ub_val_result {
|
||||
char* qname; /* text string, original question */
|
||||
int qtype; /* type code asked for */
|
||||
int qclass; /* class code asked for */
|
||||
char** data; /* array of rdata items, NULL terminated*/
|
||||
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 */
|
||||
};
|
||||
.fi
|
||||
.SH "RETURN VALUES"
|
||||
Many routines return an error code. The value 0 (zero) denotes no error
|
||||
happened. Other values can be passed to
|
||||
.B ub_val_strerror
|
||||
to obtain a readable error string.
|
||||
.B ub_val_strerror
|
||||
returns a zero terminated string.
|
||||
.B ub_val_ctx_create
|
||||
returns NULL on an error (a malloc failure).
|
||||
.B ub_val_ctx_poll
|
||||
returns true if some information may be available, false otherwise.
|
||||
.B ub_val_ctx_fd
|
||||
returns a file descriptor or -1 on error.
|
||||
.SH "SEE ALSO"
|
||||
\fIunbound.conf\fR(5),
|
||||
\fIunbound\fR(8).
|
||||
.SH "AUTHORS"
|
||||
.B Unbound
|
||||
developers are mentioned in the CREDITS file in the distribution.
|
@ -155,19 +155,19 @@ enum ub_ctx_err {
|
||||
/** no error */
|
||||
UB_NOERROR = 0,
|
||||
/** alloc failure */
|
||||
UB_NOMEM,
|
||||
UB_NOMEM = -1,
|
||||
/** socket operation */
|
||||
UB_SOCKET,
|
||||
UB_SOCKET = -2,
|
||||
/** syntax error */
|
||||
UB_SYNTAX,
|
||||
UB_SYNTAX = -3,
|
||||
/** DNS service failed */
|
||||
UB_SERVFAIL,
|
||||
UB_SERVFAIL = -4,
|
||||
/** fork() failed */
|
||||
UB_FORKFAIL,
|
||||
UB_FORKFAIL = -5,
|
||||
/** cfg change after finalize() */
|
||||
UB_AFTERFINAL,
|
||||
UB_AFTERFINAL = -6,
|
||||
/** initialization failed (bad settings) */
|
||||
UB_INITFAIL
|
||||
UB_INITFAIL = -7
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -266,13 +266,14 @@ int ub_val_ctx_async(struct ub_val_ctx* ctx, int dothread);
|
||||
* and then check, or wait using the wait routine.
|
||||
* @param ctx: context.
|
||||
* @return: 0 if nothing to read, or nonzero if a result is available.
|
||||
* If nonzero, call ctx_process() to get do any callbacks.
|
||||
* If nonzero, call ctx_process() to do callbacks.
|
||||
*/
|
||||
int ub_val_ctx_poll(struct ub_val_ctx* ctx);
|
||||
|
||||
/**
|
||||
* Wait for a context to finish with results. Calls ctx_process() after
|
||||
* the wait for you. After the wait, there are no more outstanding queries.
|
||||
* the wait for you. After the wait, there are no more outstanding
|
||||
* asynchronous queries.
|
||||
* @param ctx: context.
|
||||
* @return: 0 if OK, else error.
|
||||
*/
|
||||
|
@ -263,6 +263,18 @@ set_ip6_recvpktinfo(int s)
|
||||
"disable interface-automatic in config");
|
||||
return 0;
|
||||
#endif /* defined IPV6_RECVPKTINFO */
|
||||
|
||||
#ifdef 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 "
|
||||
"interface-automatic in config");
|
||||
return 0;
|
||||
#endif /* IP_PKTINFO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -178,12 +178,46 @@ comm_point_send_udp_msg(struct comm_point *c, ldns_buffer* packet,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** 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(r->srctype != 4 && r->srctype != 6) {
|
||||
log_info("%s: unknown srctype %d", str, r->srctype);
|
||||
return;
|
||||
}
|
||||
if(r->srctype == 6) {
|
||||
char buf[1024];
|
||||
if(inet_ntop(AF_INET6, &r->pktinfo.v6info.ipi6_addr,
|
||||
buf, (socklen_t)sizeof(buf)) == 0) {
|
||||
strncpy(buf, "(inet_ntop error)", sizeof(buf));
|
||||
}
|
||||
buf[sizeof(buf)-1]=0;
|
||||
log_info("%s: %s %d", str, buf, r->pktinfo.v6info.ipi6_ifindex);
|
||||
} else if(r->srctype == 4) {
|
||||
char buf1[1024], buf2[1024];
|
||||
if(inet_ntop(AF_INET, &r->pktinfo.v4info.ipi_addr,
|
||||
buf1, (socklen_t)sizeof(buf1)) == 0) {
|
||||
strncpy(buf1, "(inet_ntop error)", sizeof(buf1));
|
||||
}
|
||||
buf1[sizeof(buf1)-1]=0;
|
||||
if(inet_ntop(AF_INET, &r->pktinfo.v4info.ipi_spec_dst,
|
||||
buf2, (socklen_t)sizeof(buf2)) == 0) {
|
||||
strncpy(buf2, "(inet_ntop error)", sizeof(buf2));
|
||||
}
|
||||
buf2[sizeof(buf2)-1]=0;
|
||||
log_info("%s: %d %s %s", str, r->pktinfo.v4info.ipi_ifindex,
|
||||
buf1, buf2);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/** send a UDP reply over specified interface*/
|
||||
int
|
||||
comm_point_send_udp_msg_if(struct comm_point *c, ldns_buffer* packet,
|
||||
struct sockaddr* addr, socklen_t addrlen, void* ifaddr, int ifnum)
|
||||
struct sockaddr* addr, socklen_t addrlen, struct comm_reply* r)
|
||||
{
|
||||
#if defined(AF_INET6) && defined(IPV6_PKTINFO)
|
||||
#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(IP_PKTINFO)
|
||||
ssize_t sent;
|
||||
struct msghdr msg;
|
||||
struct iovec iov[1];
|
||||
@ -210,15 +244,29 @@ comm_point_send_udp_msg_if(struct comm_point *c, ldns_buffer* packet,
|
||||
|
||||
#ifndef S_SPLINT_S
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
cmsg->cmsg_level = IPPROTO_IPV6;
|
||||
cmsg->cmsg_type = IPV6_PKTINFO;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
|
||||
memmove(&((struct in6_pktinfo*)CMSG_DATA(cmsg))->ipi6_addr,
|
||||
ifaddr, sizeof(struct in6_addr));
|
||||
((struct in6_pktinfo*)CMSG_DATA(cmsg))->ipi6_ifindex = ifnum;
|
||||
if(r->srctype == 4) {
|
||||
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));
|
||||
} else if(r->srctype == 6) {
|
||||
cmsg->cmsg_level = IPPROTO_IPV6;
|
||||
cmsg->cmsg_type = IPV6_PKTINFO;
|
||||
memmove(CMSG_DATA(cmsg), &r->pktinfo.v6info,
|
||||
sizeof(struct in6_pktinfo));
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
|
||||
} else {
|
||||
/* try to pass all 0 to use default route */
|
||||
cmsg->cmsg_level = IPPROTO_IPV6;
|
||||
cmsg->cmsg_type = IPV6_PKTINFO;
|
||||
memset(CMSG_DATA(cmsg), 0, sizeof(struct in6_pktinfo));
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
|
||||
}
|
||||
msg.msg_controllen = cmsg->cmsg_len;
|
||||
#endif /* S_SPLINT_S */
|
||||
|
||||
p_ancil("send_udp over interface", r);
|
||||
sent = sendmsg(c->fd, &msg, 0);
|
||||
if(sent == -1) {
|
||||
verbose(VERB_OPS, "sendmsg failed: %s", strerror(errno));
|
||||
@ -238,7 +286,7 @@ comm_point_send_udp_msg_if(struct comm_point *c, ldns_buffer* packet,
|
||||
void
|
||||
comm_point_udp_ancil_callback(int fd, short event, void* arg)
|
||||
{
|
||||
#if defined(AF_INET6) && defined(IPV6_PKTINFO)
|
||||
#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(IP_PKTINFO)
|
||||
struct comm_reply rep;
|
||||
struct msghdr msg;
|
||||
struct iovec iov[1];
|
||||
@ -279,26 +327,35 @@ comm_point_udp_ancil_callback(int fd, short event, void* arg)
|
||||
rep.addrlen = msg.msg_namelen;
|
||||
ldns_buffer_skip(rep.c->buffer, recv);
|
||||
ldns_buffer_flip(rep.c->buffer);
|
||||
rep.ifnum = 0;
|
||||
rep.srctype = 0;
|
||||
#ifndef S_SPLINT_S
|
||||
for(cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
|
||||
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
|
||||
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);
|
||||
if( cmsg->cmsg_level == IPPROTO_IPV6 &&
|
||||
cmsg->cmsg_type == IPV6_PKTINFO) {
|
||||
rep.ifnum = ((struct in6_pktinfo*)CMSG_DATA(cmsg))->
|
||||
ipi6_ifindex;
|
||||
memmove(&rep.ifaddr, &((struct in6_pktinfo*)
|
||||
CMSG_DATA(cmsg))->ipi6_addr,
|
||||
sizeof(struct in6_addr));
|
||||
rep.srctype = 6;
|
||||
memmove(&rep.pktinfo.v6info, CMSG_DATA(cmsg),
|
||||
sizeof(struct in6_pktinfo));
|
||||
break;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
p_ancil("receive_udp on interface", &rep);
|
||||
#endif /* S_SPLINT_S */
|
||||
log_assert(fptr_whitelist_comm_point(rep.c->callback));
|
||||
if((*rep.c->callback)(rep.c, rep.c->cb_arg, NETEVENT_NOERROR, &rep)) {
|
||||
/* send back immediate reply */
|
||||
(void)comm_point_send_udp_msg_if(rep.c, rep.c->buffer,
|
||||
(struct sockaddr*)&rep.addr, rep.addrlen,
|
||||
&rep.ifaddr, rep.ifnum);
|
||||
(struct sockaddr*)&rep.addr, rep.addrlen, &rep);
|
||||
}
|
||||
#else
|
||||
fatal_exit("recvmsg: No support for IPV6_PKTINFO. "
|
||||
@ -333,7 +390,7 @@ comm_point_udp_callback(int fd, short event, void* arg)
|
||||
}
|
||||
ldns_buffer_skip(rep.c->buffer, recv);
|
||||
ldns_buffer_flip(rep.c->buffer);
|
||||
rep.ifnum = -1;
|
||||
rep.srctype = 0;
|
||||
log_assert(fptr_whitelist_comm_point(rep.c->callback));
|
||||
if((*rep.c->callback)(rep.c, rep.c->cb_arg, NETEVENT_NOERROR, &rep)) {
|
||||
/* send back immediate reply */
|
||||
@ -1007,10 +1064,10 @@ comm_point_send_reply(struct comm_reply *repinfo)
|
||||
{
|
||||
log_assert(repinfo && repinfo->c);
|
||||
if(repinfo->c->type == comm_udp) {
|
||||
if(repinfo->ifnum != -1)
|
||||
if(repinfo->srctype)
|
||||
comm_point_send_udp_msg_if(repinfo->c,
|
||||
repinfo->c->buffer, (struct sockaddr*)&repinfo->addr,
|
||||
repinfo->addrlen, &repinfo->ifaddr, repinfo->ifnum);
|
||||
repinfo->addrlen, repinfo);
|
||||
else
|
||||
comm_point_send_udp_msg(repinfo->c, repinfo->c->buffer,
|
||||
(struct sockaddr*)&repinfo->addr, repinfo->addrlen);
|
||||
|
@ -98,12 +98,19 @@ struct comm_reply {
|
||||
struct sockaddr_storage addr;
|
||||
/** length of address */
|
||||
socklen_t addrlen;
|
||||
#ifdef AF_INET6
|
||||
/** the interface address */
|
||||
struct in6_addr ifaddr;
|
||||
/** return type 0 (none), 4(IP4), 6(IP6) */
|
||||
int srctype;
|
||||
/** the return source interface data */
|
||||
union {
|
||||
#ifdef IPV6_PKTINFO
|
||||
struct in6_pktinfo v6info;
|
||||
#endif
|
||||
/** the interface received (for UDPautomaticinterface) or 0 */
|
||||
int ifnum;
|
||||
#ifdef IP_PKTINFO
|
||||
struct in_pktinfo v4info;
|
||||
#endif
|
||||
}
|
||||
/** variable with return source data */
|
||||
pktinfo;
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user