Пример #1
0
static void
ns_interface_destroy(ns_interface_t *ifp) {
	isc_mem_t *mctx = ifp->mgr->mctx;
	int disp;

	REQUIRE(NS_INTERFACE_VALID(ifp));

	ns_interface_shutdown(ifp);

	for (disp = 0; disp < ifp->nudpdispatch; disp++)
		if (ifp->udpdispatch[disp] != NULL) {
			dns_dispatch_changeattributes(ifp->udpdispatch[disp], 0,
						    DNS_DISPATCHATTR_NOLISTEN);
			dns_dispatch_detach(&(ifp->udpdispatch[disp]));
		}

	if (ifp->tcpsocket != NULL)
		isc_socket_detach(&ifp->tcpsocket);

	DESTROYLOCK(&ifp->lock);

	ns_interfacemgr_detach(&ifp->mgr);

	ifp->magic = 0;
	isc_mem_put(mctx, ifp, sizeof(*ifp));
}
Пример #2
0
isc_result_t
ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
		       isc_socketmgr_t *socketmgr,
		       dns_dispatchmgr_t *dispatchmgr,
		       isc_task_t *task, ns_interfacemgr_t **mgrp)
{
	isc_result_t result;
	ns_interfacemgr_t *mgr;

#ifndef USE_ROUTE_SOCKET
	UNUSED(task);
#endif

	REQUIRE(mctx != NULL);
	REQUIRE(mgrp != NULL);
	REQUIRE(*mgrp == NULL);

	mgr = isc_mem_get(mctx, sizeof(*mgr));
	if (mgr == NULL)
		return (ISC_R_NOMEMORY);

	mgr->mctx = NULL;
	isc_mem_attach(mctx, &mgr->mctx);

	result = isc_mutex_init(&mgr->lock);
	if (result != ISC_R_SUCCESS)
		goto cleanup_mem;

	mgr->taskmgr = taskmgr;
	mgr->socketmgr = socketmgr;
	mgr->dispatchmgr = dispatchmgr;
	mgr->generation = 1;
	mgr->listenon4 = NULL;
	mgr->listenon6 = NULL;

	ISC_LIST_INIT(mgr->interfaces);
	ISC_LIST_INIT(mgr->listenon);

	/*
	 * The listen-on lists are initially empty.
	 */
	result = ns_listenlist_create(mctx, &mgr->listenon4);
	if (result != ISC_R_SUCCESS)
		goto cleanup_mem;
	ns_listenlist_attach(mgr->listenon4, &mgr->listenon6);

	result = dns_aclenv_init(mctx, &mgr->aclenv);
	if (result != ISC_R_SUCCESS)
		goto cleanup_listenon;
#ifdef HAVE_GEOIP
	mgr->aclenv.geoip = ns_g_geoip;
#endif

#ifdef USE_ROUTE_SOCKET
	mgr->route = NULL;
	result = isc_socket_create(mgr->socketmgr, ROUTE_SOCKET_PROTOCOL,
				   isc_sockettype_raw, &mgr->route);
	switch (result) {
	case ISC_R_NOPERM:
	case ISC_R_SUCCESS:
	case ISC_R_NOTIMPLEMENTED:
	case ISC_R_FAMILYNOSUPPORT:
	    break;
	default:
		goto cleanup_aclenv;
	}

	mgr->task = NULL;
	if (mgr->route != NULL)
		isc_task_attach(task, &mgr->task);
	mgr->references = (mgr->route != NULL) ? 2 : 1;
#else
	mgr->references = 1;
#endif
	mgr->magic = IFMGR_MAGIC;
	*mgrp = mgr;

#ifdef USE_ROUTE_SOCKET
	if (mgr->route != NULL) {
		isc_region_t r = { mgr->buf, sizeof(mgr->buf) };

		result = isc_socket_recv(mgr->route, &r, 1, mgr->task,
					 route_event, mgr);
		if (result != ISC_R_SUCCESS) {
			isc_task_detach(&mgr->task);
			isc_socket_detach(&mgr->route);
			ns_interfacemgr_detach(&mgr);
		}
	}
#endif
	return (ISC_R_SUCCESS);

#ifdef USE_ROUTE_SOCKET
 cleanup_aclenv:
	dns_aclenv_destroy(&mgr->aclenv);
#endif
 cleanup_listenon:
	ns_listenlist_detach(&mgr->listenon4);
	ns_listenlist_detach(&mgr->listenon6);
 cleanup_mem:
	isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr));
	return (result);
}
Пример #3
0
static void
route_event(isc_task_t *task, isc_event_t *event) {
	isc_socketevent_t *sevent = NULL;
	ns_interfacemgr_t *mgr = NULL;
	isc_region_t r;
	isc_result_t result;
	struct MSGHDR *rtm;
	isc_boolean_t done = ISC_TRUE;

	UNUSED(task);

	REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
	mgr = event->ev_arg;
	sevent = (isc_socketevent_t *)event;

	if (sevent->result != ISC_R_SUCCESS) {
		if (sevent->result != ISC_R_CANCELED)
			isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
				      "automatic interface scanning "
				      "terminated: %s",
				      isc_result_totext(sevent->result));
		ns_interfacemgr_detach(&mgr);
		isc_event_free(&event);
		return;
	}

	rtm = (struct MSGHDR *)mgr->buf;
#ifdef RTM_VERSION
	if (rtm->rtm_version != RTM_VERSION) {
		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
			      "automatic interface rescanning disabled: "
			      "rtm->rtm_version mismatch (%u != %u) "
			      "recompile required", rtm->rtm_version,
			      RTM_VERSION);
		ns_interfacemgr_detach(&mgr);
		isc_event_free(&event);
		return;
	}
#endif

	switch (rtm->MSGTYPE) {
	case RTM_NEWADDR:
	case RTM_DELADDR:
		if (mgr->route != NULL && ns_g_server->interface_auto)
			ns_server_scan_interfaces(ns_g_server);
		break;
	default:
		break;
	}

	LOCK(&mgr->lock);
	if (mgr->route != NULL) {
		/*
		 * Look for next route event.
		 */
		r.base = mgr->buf;
		r.length = sizeof(mgr->buf);
		result = isc_socket_recv(mgr->route, &r, 1, mgr->task,
					 route_event, mgr);
		if (result == ISC_R_SUCCESS)
			done = ISC_FALSE;
	}
	UNLOCK(&mgr->lock);

	if (done)
		ns_interfacemgr_detach(&mgr);
	isc_event_free(&event);
	return;
}