mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-03 16:15:27 +00:00
netmgr: add isc_nm_routeconnect()
isc_nm_routeconnect() opens a route/netlink socket, then calls a connect callback, much like isc_nm_udpconnect(), with a handle that can then be monitored for network changes. Internally the socket is treated as a UDP socket, since route/netlink sockets follow the datagram contract.
This commit is contained in:
@@ -232,6 +232,18 @@ isc_nm_udpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
|
|||||||
* 'cb'.
|
* 'cb'.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
isc_result_t
|
||||||
|
isc_nm_routeconnect(isc_nm_t *mgr, isc_nm_cb_t cb, void *cbarg,
|
||||||
|
size_t extrahandlesize);
|
||||||
|
/*%<
|
||||||
|
* Open a route/netlink socket and call 'cb', so the caller can be
|
||||||
|
* begin listening for interface changes. This behaves similarly to
|
||||||
|
* isc_nm_udpconnect().
|
||||||
|
*
|
||||||
|
* Returns ISC_R_NOTIMPLEMENTED on systems where route/netlink sockets
|
||||||
|
* are not supported.
|
||||||
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
isc_nm_stoplistening(isc_nmsocket_t *sock);
|
isc_nm_stoplistening(isc_nmsocket_t *sock);
|
||||||
/*%<
|
/*%<
|
||||||
|
@@ -240,6 +240,8 @@ typedef enum isc__netievent_type {
|
|||||||
netievent_udpread,
|
netievent_udpread,
|
||||||
netievent_udpcancel,
|
netievent_udpcancel,
|
||||||
|
|
||||||
|
netievent_routeconnect,
|
||||||
|
|
||||||
netievent_tcpconnect,
|
netievent_tcpconnect,
|
||||||
netievent_tcpclose,
|
netievent_tcpclose,
|
||||||
netievent_tcpsend,
|
netievent_tcpsend,
|
||||||
@@ -967,6 +969,8 @@ struct isc_nmsocket {
|
|||||||
atomic_bool active;
|
atomic_bool active;
|
||||||
atomic_bool destroying;
|
atomic_bool destroying;
|
||||||
|
|
||||||
|
bool route_sock;
|
||||||
|
|
||||||
/*%
|
/*%
|
||||||
* Socket is closed if it's not active and all the possible
|
* Socket is closed if it's not active and all the possible
|
||||||
* callbacks were fired, there are no active handles, etc.
|
* callbacks were fired, there are no active handles, etc.
|
||||||
@@ -1351,6 +1355,12 @@ isc__nm_async_udpclose(isc__networker_t *worker, isc__netievent_t *ev0);
|
|||||||
* Callback handlers for asynchronous UDP events (listen, stoplisten, send).
|
* Callback handlers for asynchronous UDP events (listen, stoplisten, send).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
isc__nm_async_routeconnect(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||||
|
/*%<
|
||||||
|
* Callback handler for route socket events.
|
||||||
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
isc__nm_tcp_send(isc_nmhandle_t *handle, const isc_region_t *region,
|
isc__nm_tcp_send(isc_nmhandle_t *handle, const isc_region_t *region,
|
||||||
isc_nm_cb_t cb, void *cbarg);
|
isc_nm_cb_t cb, void *cbarg);
|
||||||
@@ -1880,6 +1890,8 @@ NETIEVENT_SOCKET_TYPE(tcpstartread);
|
|||||||
NETIEVENT_SOCKET_REQ_TYPE(tlssend);
|
NETIEVENT_SOCKET_REQ_TYPE(tlssend);
|
||||||
NETIEVENT_SOCKET_REQ_TYPE(udpconnect);
|
NETIEVENT_SOCKET_REQ_TYPE(udpconnect);
|
||||||
|
|
||||||
|
NETIEVENT_SOCKET_REQ_TYPE(routeconnect);
|
||||||
|
|
||||||
NETIEVENT_SOCKET_REQ_RESULT_TYPE(connectcb);
|
NETIEVENT_SOCKET_REQ_RESULT_TYPE(connectcb);
|
||||||
NETIEVENT_SOCKET_REQ_RESULT_TYPE(readcb);
|
NETIEVENT_SOCKET_REQ_RESULT_TYPE(readcb);
|
||||||
NETIEVENT_SOCKET_REQ_RESULT_TYPE(sendcb);
|
NETIEVENT_SOCKET_REQ_RESULT_TYPE(sendcb);
|
||||||
@@ -1946,6 +1958,8 @@ NETIEVENT_SOCKET_REQ_DECL(tcpsend);
|
|||||||
NETIEVENT_SOCKET_REQ_DECL(tlssend);
|
NETIEVENT_SOCKET_REQ_DECL(tlssend);
|
||||||
NETIEVENT_SOCKET_REQ_DECL(udpconnect);
|
NETIEVENT_SOCKET_REQ_DECL(udpconnect);
|
||||||
|
|
||||||
|
NETIEVENT_SOCKET_REQ_DECL(routeconnect);
|
||||||
|
|
||||||
NETIEVENT_SOCKET_REQ_RESULT_DECL(connectcb);
|
NETIEVENT_SOCKET_REQ_RESULT_DECL(connectcb);
|
||||||
NETIEVENT_SOCKET_REQ_RESULT_DECL(readcb);
|
NETIEVENT_SOCKET_REQ_RESULT_DECL(readcb);
|
||||||
NETIEVENT_SOCKET_REQ_RESULT_DECL(sendcb);
|
NETIEVENT_SOCKET_REQ_RESULT_DECL(sendcb);
|
||||||
|
@@ -913,6 +913,8 @@ process_netievent(isc__networker_t *worker, isc__netievent_t *ievent) {
|
|||||||
NETIEVENT_CASE(udpcancel);
|
NETIEVENT_CASE(udpcancel);
|
||||||
NETIEVENT_CASE(udpclose);
|
NETIEVENT_CASE(udpclose);
|
||||||
|
|
||||||
|
NETIEVENT_CASE(routeconnect);
|
||||||
|
|
||||||
NETIEVENT_CASE(tcpaccept);
|
NETIEVENT_CASE(tcpaccept);
|
||||||
NETIEVENT_CASE(tcpconnect);
|
NETIEVENT_CASE(tcpconnect);
|
||||||
NETIEVENT_CASE(tcplisten);
|
NETIEVENT_CASE(tcplisten);
|
||||||
@@ -1072,6 +1074,7 @@ NETIEVENT_SOCKET_REQ_DEF(tcpconnect);
|
|||||||
NETIEVENT_SOCKET_REQ_DEF(tcpsend);
|
NETIEVENT_SOCKET_REQ_DEF(tcpsend);
|
||||||
NETIEVENT_SOCKET_REQ_DEF(tlssend);
|
NETIEVENT_SOCKET_REQ_DEF(tlssend);
|
||||||
NETIEVENT_SOCKET_REQ_DEF(udpconnect);
|
NETIEVENT_SOCKET_REQ_DEF(udpconnect);
|
||||||
|
NETIEVENT_SOCKET_REQ_DEF(routeconnect);
|
||||||
NETIEVENT_SOCKET_REQ_RESULT_DEF(connectcb);
|
NETIEVENT_SOCKET_REQ_RESULT_DEF(connectcb);
|
||||||
NETIEVENT_SOCKET_REQ_RESULT_DEF(readcb);
|
NETIEVENT_SOCKET_REQ_RESULT_DEF(readcb);
|
||||||
NETIEVENT_SOCKET_REQ_RESULT_DEF(sendcb);
|
NETIEVENT_SOCKET_REQ_RESULT_DEF(sendcb);
|
||||||
@@ -1447,12 +1450,8 @@ isc___nmsocket_init(isc_nmsocket_t *sock, isc_nm_t *mgr, isc_nmsocket_type type,
|
|||||||
|
|
||||||
REQUIRE(sock != NULL);
|
REQUIRE(sock != NULL);
|
||||||
REQUIRE(mgr != NULL);
|
REQUIRE(mgr != NULL);
|
||||||
REQUIRE(iface != NULL);
|
|
||||||
|
|
||||||
family = iface->type.sa.sa_family;
|
|
||||||
|
|
||||||
*sock = (isc_nmsocket_t){ .type = type,
|
*sock = (isc_nmsocket_t){ .type = type,
|
||||||
.iface = *iface,
|
|
||||||
.fd = -1,
|
.fd = -1,
|
||||||
.ah_size = 32,
|
.ah_size = 32,
|
||||||
.inactivehandles = isc_astack_new(
|
.inactivehandles = isc_astack_new(
|
||||||
@@ -1460,6 +1459,13 @@ isc___nmsocket_init(isc_nmsocket_t *sock, isc_nm_t *mgr, isc_nmsocket_type type,
|
|||||||
.inactivereqs = isc_astack_new(
|
.inactivereqs = isc_astack_new(
|
||||||
mgr->mctx, ISC_NM_REQS_STACK_SIZE) };
|
mgr->mctx, ISC_NM_REQS_STACK_SIZE) };
|
||||||
|
|
||||||
|
if (iface != NULL) {
|
||||||
|
family = iface->type.sa.sa_family;
|
||||||
|
sock->iface = *iface;
|
||||||
|
} else {
|
||||||
|
family = AF_UNSPEC;
|
||||||
|
}
|
||||||
|
|
||||||
#if NETMGR_TRACE
|
#if NETMGR_TRACE
|
||||||
sock->backtrace_size = isc_backtrace(sock->backtrace, TRACE_SIZE);
|
sock->backtrace_size = isc_backtrace(sock->backtrace, TRACE_SIZE);
|
||||||
ISC_LINK_INIT(sock, active_link);
|
ISC_LINK_INIT(sock, active_link);
|
||||||
@@ -1492,6 +1498,12 @@ isc___nmsocket_init(isc_nmsocket_t *sock, isc_nm_t *mgr, isc_nmsocket_type type,
|
|||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
sock->statsindex = udp6statsindex;
|
sock->statsindex = udp6statsindex;
|
||||||
break;
|
break;
|
||||||
|
case AF_UNSPEC:
|
||||||
|
/*
|
||||||
|
* Route sockets are AF_UNSPEC, and don't
|
||||||
|
* have stats counters.
|
||||||
|
*/
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
INSIST(0);
|
INSIST(0);
|
||||||
ISC_UNREACHABLE();
|
ISC_UNREACHABLE();
|
||||||
@@ -1521,6 +1533,10 @@ isc___nmsocket_init(isc_nmsocket_t *sock, isc_nm_t *mgr, isc_nmsocket_type type,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sock->statsindex != NULL) {
|
||||||
|
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_ACTIVE]);
|
||||||
|
}
|
||||||
|
|
||||||
isc_mutex_init(&sock->lock);
|
isc_mutex_init(&sock->lock);
|
||||||
isc_condition_init(&sock->cond);
|
isc_condition_init(&sock->cond);
|
||||||
isc_condition_init(&sock->scond);
|
isc_condition_init(&sock->scond);
|
||||||
|
@@ -31,6 +31,32 @@
|
|||||||
#include "netmgr-int.h"
|
#include "netmgr-int.h"
|
||||||
#include "uv-compat.h"
|
#include "uv-compat.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_NET_ROUTE_H
|
||||||
|
#include <net/route.h>
|
||||||
|
#if defined(RTM_VERSION) && defined(RTM_NEWADDR) && defined(RTM_DELADDR)
|
||||||
|
#define USE_ROUTE_SOCKET 1
|
||||||
|
#define ROUTE_SOCKET_PF PF_ROUTE
|
||||||
|
#define ROUTE_SOCKET_PROTOCOL 0
|
||||||
|
#define MSGHDR rt_msghdr
|
||||||
|
#define MSGTYPE rtm_type
|
||||||
|
#endif /* if defined(RTM_VERSION) && defined(RTM_NEWADDR) && \
|
||||||
|
* defined(RTM_DELADDR) */
|
||||||
|
#endif /* ifdef HAVE_NET_ROUTE_H */
|
||||||
|
|
||||||
|
#if defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H)
|
||||||
|
#include <linux/netlink.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
#if defined(RTM_NEWADDR) && defined(RTM_DELADDR)
|
||||||
|
#define USE_ROUTE_SOCKET 1
|
||||||
|
#define USE_NETLINK 1
|
||||||
|
#define ROUTE_SOCKET_PF PF_NETLINK
|
||||||
|
#define ROUTE_SOCKET_PROTOCOL NETLINK_ROUTE
|
||||||
|
#define MSGHDR nlmsghdr
|
||||||
|
#define MSGTYPE nlmsg_type
|
||||||
|
#endif /* if defined(RTM_NEWADDR) && defined(RTM_DELADDR) */
|
||||||
|
#endif /* if defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H) \
|
||||||
|
*/
|
||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
udp_send_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req,
|
udp_send_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req,
|
||||||
isc_sockaddr_t *peer);
|
isc_sockaddr_t *peer);
|
||||||
@@ -189,6 +215,197 @@ isc_nm_listenudp(isc_nm_t *mgr, isc_sockaddr_t *iface, isc_nm_recv_cb_t cb,
|
|||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_ROUTE_SOCKET
|
||||||
|
static isc_result_t
|
||||||
|
route_socket(uv_os_sock_t *fdp) {
|
||||||
|
isc_result_t result;
|
||||||
|
uv_os_sock_t fd;
|
||||||
|
#ifdef USE_NETLINK
|
||||||
|
struct sockaddr_nl sa;
|
||||||
|
int r;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
result = isc__nm_socket(ROUTE_SOCKET_PF, SOCK_RAW,
|
||||||
|
ROUTE_SOCKET_PROTOCOL, &fd);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_NETLINK
|
||||||
|
sa.nl_family = PF_NETLINK;
|
||||||
|
sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;
|
||||||
|
r = bind(fd, (struct sockaddr *)&sa, sizeof(sa));
|
||||||
|
if (r < 0) {
|
||||||
|
isc__nm_closesocket(fd);
|
||||||
|
return (isc_errno_toresult(r));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
*fdp = fd;
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
route_connect_direct(isc_nmsocket_t *sock) {
|
||||||
|
isc__networker_t *worker = NULL;
|
||||||
|
isc_result_t result = ISC_R_UNSET;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
REQUIRE(isc__nm_in_netthread());
|
||||||
|
REQUIRE(sock->tid == isc_nm_tid());
|
||||||
|
|
||||||
|
worker = &sock->mgr->workers[isc_nm_tid()];
|
||||||
|
|
||||||
|
atomic_store(&sock->connecting, true);
|
||||||
|
|
||||||
|
r = uv_udp_init(&worker->loop, &sock->uv_handle.udp);
|
||||||
|
RUNTIME_CHECK(r == 0);
|
||||||
|
uv_handle_set_data(&sock->uv_handle.handle, sock);
|
||||||
|
|
||||||
|
r = uv_timer_init(&worker->loop, &sock->timer);
|
||||||
|
RUNTIME_CHECK(r == 0);
|
||||||
|
uv_handle_set_data((uv_handle_t *)&sock->timer, sock);
|
||||||
|
|
||||||
|
if (isc__nm_closing(sock)) {
|
||||||
|
result = ISC_R_SHUTTINGDOWN;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = uv_udp_open(&sock->uv_handle.udp, sock->fd);
|
||||||
|
if (r != 0) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc__nm_set_network_buffers(sock->mgr, &sock->uv_handle.handle);
|
||||||
|
|
||||||
|
atomic_store(&sock->connecting, false);
|
||||||
|
atomic_store(&sock->connected, true);
|
||||||
|
|
||||||
|
done:
|
||||||
|
result = isc__nm_uverr2result(r);
|
||||||
|
error:
|
||||||
|
|
||||||
|
LOCK(&sock->lock);
|
||||||
|
sock->result = result;
|
||||||
|
SIGNAL(&sock->cond);
|
||||||
|
if (!atomic_load(&sock->active)) {
|
||||||
|
WAIT(&sock->scond, &sock->lock);
|
||||||
|
}
|
||||||
|
INSIST(atomic_load(&sock->active));
|
||||||
|
UNLOCK(&sock->lock);
|
||||||
|
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Asynchronous 'udpconnect' call handler: open a new UDP socket and
|
||||||
|
* call the 'open' callback with a handle.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
isc__nm_async_routeconnect(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||||
|
isc__netievent_routeconnect_t *ievent =
|
||||||
|
(isc__netievent_routeconnect_t *)ev0;
|
||||||
|
isc_nmsocket_t *sock = ievent->sock;
|
||||||
|
isc__nm_uvreq_t *req = ievent->req;
|
||||||
|
isc_result_t result;
|
||||||
|
|
||||||
|
UNUSED(worker);
|
||||||
|
|
||||||
|
REQUIRE(VALID_NMSOCK(sock));
|
||||||
|
REQUIRE(sock->type == isc_nm_udpsocket);
|
||||||
|
REQUIRE(sock->parent == NULL);
|
||||||
|
REQUIRE(sock->tid == isc_nm_tid());
|
||||||
|
|
||||||
|
result = route_connect_direct(sock);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
atomic_store(&sock->active, false);
|
||||||
|
isc__nm_udp_close(sock);
|
||||||
|
isc__nm_connectcb(sock, req, result, true);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* The callback has to be called after the socket has been
|
||||||
|
* initialized
|
||||||
|
*/
|
||||||
|
isc__nm_connectcb(sock, req, ISC_R_SUCCESS, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The sock is now attached to the handle.
|
||||||
|
*/
|
||||||
|
isc__nmsocket_detach(&sock);
|
||||||
|
}
|
||||||
|
#endif /* USE_ROUTE_SOCKET */
|
||||||
|
|
||||||
|
isc_result_t
|
||||||
|
isc_nm_routeconnect(isc_nm_t *mgr, isc_nm_cb_t cb, void *cbarg,
|
||||||
|
size_t extrahandlesize) {
|
||||||
|
#ifdef USE_ROUTE_SOCKET
|
||||||
|
isc_result_t result = ISC_R_SUCCESS;
|
||||||
|
isc_nmsocket_t *sock = NULL;
|
||||||
|
isc__netievent_udpconnect_t *event = NULL;
|
||||||
|
isc__nm_uvreq_t *req = NULL;
|
||||||
|
|
||||||
|
REQUIRE(VALID_NM(mgr));
|
||||||
|
|
||||||
|
sock = isc_mem_get(mgr->mctx, sizeof(*sock));
|
||||||
|
isc__nmsocket_init(sock, mgr, isc_nm_udpsocket, NULL);
|
||||||
|
|
||||||
|
sock->connect_cb = cb;
|
||||||
|
sock->connect_cbarg = cbarg;
|
||||||
|
sock->extrahandlesize = extrahandlesize;
|
||||||
|
sock->result = ISC_R_UNSET;
|
||||||
|
atomic_init(&sock->client, true);
|
||||||
|
sock->route_sock = true;
|
||||||
|
|
||||||
|
req = isc__nm_uvreq_get(mgr, sock);
|
||||||
|
req->cb.connect = cb;
|
||||||
|
req->cbarg = cbarg;
|
||||||
|
req->handle = isc__nmhandle_get(sock, NULL, NULL);
|
||||||
|
|
||||||
|
result = route_socket(&sock->fd);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
if (isc__nm_in_netthread()) {
|
||||||
|
sock->tid = isc_nm_tid();
|
||||||
|
}
|
||||||
|
isc__nmsocket_clearcb(sock);
|
||||||
|
isc__nm_connectcb(sock, req, result, true);
|
||||||
|
atomic_store(&sock->closed, true);
|
||||||
|
isc__nmsocket_detach(&sock);
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
event = isc__nm_get_netievent_routeconnect(mgr, sock, req);
|
||||||
|
|
||||||
|
if (isc__nm_in_netthread()) {
|
||||||
|
atomic_store(&sock->active, true);
|
||||||
|
sock->tid = isc_nm_tid();
|
||||||
|
isc__nm_async_routeconnect(&mgr->workers[sock->tid],
|
||||||
|
(isc__netievent_t *)event);
|
||||||
|
isc__nm_put_netievent_routeconnect(mgr, event);
|
||||||
|
} else {
|
||||||
|
atomic_init(&sock->active, false);
|
||||||
|
sock->tid = 0;
|
||||||
|
isc__nm_enqueue_ievent(&mgr->workers[sock->tid],
|
||||||
|
(isc__netievent_t *)event);
|
||||||
|
}
|
||||||
|
LOCK(&sock->lock);
|
||||||
|
while (sock->result == ISC_R_UNSET) {
|
||||||
|
WAIT(&sock->cond, &sock->lock);
|
||||||
|
}
|
||||||
|
atomic_store(&sock->active, true);
|
||||||
|
BROADCAST(&sock->scond);
|
||||||
|
UNLOCK(&sock->lock);
|
||||||
|
|
||||||
|
return (sock->result);
|
||||||
|
#else /* USE_ROUTE_SOCKET */
|
||||||
|
UNUSED(mgr);
|
||||||
|
UNUSED(cb);
|
||||||
|
UNUSED(cbarg);
|
||||||
|
UNUSED(extrahandlesize);
|
||||||
|
return (ISC_R_NOTIMPLEMENTED);
|
||||||
|
#endif /* USE_ROUTE_SOCKET */
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Asynchronous 'udplisten' call handler: start listening on a UDP socket.
|
* Asynchronous 'udplisten' call handler: start listening on a UDP socket.
|
||||||
*/
|
*/
|
||||||
@@ -338,8 +555,8 @@ udp_recv_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf,
|
|||||||
isc__nm_uvreq_t *req = NULL;
|
isc__nm_uvreq_t *req = NULL;
|
||||||
uint32_t maxudp;
|
uint32_t maxudp;
|
||||||
bool free_buf;
|
bool free_buf;
|
||||||
isc_sockaddr_t sockaddr;
|
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
|
isc_sockaddr_t sockaddr, *sa = NULL;
|
||||||
|
|
||||||
REQUIRE(VALID_NMSOCK(sock));
|
REQUIRE(VALID_NMSOCK(sock));
|
||||||
REQUIRE(sock->tid == isc_nm_tid());
|
REQUIRE(sock->tid == isc_nm_tid());
|
||||||
@@ -398,10 +615,13 @@ udp_recv_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf,
|
|||||||
goto free;
|
goto free;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = isc_sockaddr_fromsockaddr(&sockaddr, addr);
|
if (!sock->route_sock) {
|
||||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
result = isc_sockaddr_fromsockaddr(&sockaddr, addr);
|
||||||
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
|
sa = &sockaddr;
|
||||||
|
}
|
||||||
|
|
||||||
req = isc__nm_get_read_req(sock, &sockaddr);
|
req = isc__nm_get_read_req(sock, sa);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The callback will be called synchronously, because result is
|
* The callback will be called synchronously, because result is
|
||||||
|
Reference in New Issue
Block a user