Esempio n. 1
0
static int net_ifc_cmp (struct ifconf *ifc1, struct ifconf *ifc2) {
	struct ifreq *ifr_p1;
	struct ifreq *ifr_p2;
	u_char *cp1;
	u_char *cp2;

	if (ifc1->ifc_len != ifc2->ifc_len) {
		if (T.debug > 4) 
			syslog (LOG_DEBUG, "net_ifc_cmp(): lengths differ");
		return 1;
	}

	cp1 = ifc1->ifc_buf;
	cp2 = ifc2->ifc_buf;

	while (*cp1 && *cp2) {
		ifr_p1 = (struct ifreq *) cp1;
		ifr_p2 = (struct ifreq *) cp2;

		cp1 = cp1 + IFNAMSIZ + SOCKADDR_SIZEOF (ifr_p1->ifr_addr);
		cp2 = cp2 + IFNAMSIZ + SOCKADDR_SIZEOF (ifr_p2->ifr_addr);

		if (T.debug > 4) {
			char astr[MAX_DNAME], bstr[MAX_DNAME];

			sprint_inet(&ifr_p1->ifr_addr, astr);
			sprint_inet(&ifr_p2->ifr_addr, bstr);
			
			syslog (LOG_DEBUG, "net_ifc_cmp(): if1 %s, if2 %s, \
af1 %d, af2 %d, addr1 %s, addr2 %s", ifr_p1->ifr_name, ifr_p2->ifr_name, \
ifr_p1->ifr_addr.sa_family, ifr_p1->ifr_addr.sa_family, astr, bstr);
		}

#ifdef USE_INET4
		if (ifr_p1->ifr_addr.sa_family != AF_INET &&
		    ifr_p2->ifr_addr.sa_family != AF_INET)
#endif
#ifdef USE_INET6
			if (ifr_p1->ifr_addr.sa_family != AF_INET6 &&
		    	    ifr_p2->ifr_addr.sa_family != AF_INET6)
#endif
				continue; /* skip */

		/* comparison only AF_INET and AF_INET6 */
		if (ifr_p1->ifr_addr.sa_family != ifr_p2->ifr_addr.sa_family)
			return 1;

		if (strcmp (ifr_p1->ifr_name, ifr_p2->ifr_name))
			return 1;

		if (memcmp (&(ifr_p1->ifr_addr), &(ifr_p2->ifr_addr),
			    SOCKADDR_SIZEOF (ifr_p1->ifr_addr)))
			return 1;
	}

	return 0; /* equal! */
}
Esempio n. 2
0
int net_mesg_socket (Nia *ni) {
	const char *fn = "net_mesg_socket()";
	char astr[MAX_DNAME];
	const int on = 1;
	int sock;

	ni->udp_sock = -1;

	sock = socket (ni->sa_p->sa_family, SOCK_DGRAM, 0);
	if (sock < 0) {
		syslog (LOG_ERR, "%s: socket open failed: %m", fn);
		return -1;
	}
	if (T.debug > 4)
		syslog (LOG_DEBUG, "%s: socket open(fd = %d)", fn, sock);

	if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
			(char *) &on, sizeof (on)))
		syslog (LOG_WARNING, "setsockopt: %m");


	if (bind (sock, ni->sa_p, SOCKADDR_SIZEOF (*ni->sa_p)) < 0) {
		syslog (LOG_ERR, "Can not bind datagram socket: %m");
		close (sock);
		return -1;
	}

	/* if no port set, then it is for outgoing messages only */
	if (((struct sockaddr_in *)ni->sa_p)->sin_port) {
		sprint_inet(ni->sa_p, astr);
		syslog (LOG_NOTICE, "Listening on %s for UDP", astr);
	}

#ifdef USE_INET6
#ifdef IPV6_USE_MIN_MTU
	if (ni->sa_p->sa_family == AF_INET6) {
		const int on = 1;

		/* ignore error */
		(void)setsockopt(sock, IPPROTO_IPV6,
			IPV6_USE_MIN_MTU, &on, sizeof(on));
	}
#endif
#endif

	ni->udp_sock = sock;
	return sock;
}
Esempio n. 3
0
int net_stream_socket (Nia *ni) {
	const char *fn = "net_stream_socket()";
	char astr[MAX_DNAME];
	const int on = 1;
	int sock;

	ni->tcp_sock = -1;

	/* if no port set, do nothing for TCP */
	if (!((struct sockaddr_in *)ni->sa_p)->sin_port)
		return -1;

	sock = socket (ni->sa_p->sa_family, SOCK_STREAM, 0);
	if (sock < 0) {
		syslog (LOG_ERR, "%s: socket open failed: %m", fn);
		return -1;
	}
	if (T.debug > 4)
		syslog (LOG_DEBUG, "%s: socket open(fd = %d)", fn, sock);

	if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
			(char *) &on, sizeof (on)))
		syslog (LOG_WARNING, "setsockopt: %m");

	if (bind (sock, ni->sa_p, SOCKADDR_SIZEOF (*ni->sa_p)) != 0) {
		syslog (LOG_ERR, "Can't bind TCP socket: %m");
		close (sock);
		return -1;
	}

	if (ioctl (sock, FIONBIO, (char *) &on) < 0) {
		syslog (LOG_ERR, "Can't ioctl on service socket: %m");
		return -1;
	}

	if (listen (sock, 5) != 0) {
		syslog (LOG_ERR, "Listen failed: %m");
		close (sock);
		return -1;
	}

	sprint_inet(ni->sa_p, astr);
	syslog (LOG_NOTICE, "Listening on %s for TCP", astr);

	ni->tcp_sock = sock;
	return sock;
}
Esempio n. 4
0
/*
 * The fact that this routines gets called is a first hint that
 * the current forwarder/nameserver is down at this point in time.
 * Actually, it may just be slow, be overloaded, or the network may
 * be congested. In any way, from our point of view it is slow or
 * down and thus we may gain by trying a configured backup forwarder.
 * 
 * This routines marks the forwarder with the given address (if any)
 * with a `minus' point. If a forwarder has gathered `enough' minus points
 * it will be marked down, such that it will not be used for a while.
 *
 * Note that the current forwarder (T.current_fwd) is never marked down!
 */
void fwd_mark (struct sockaddr *sa, int up) {
	char *fn = "fwd_mark";
    	char astr[MAX_DNAME];
    	char bstr[MAX_DNAME];
	G_List *gl;
	Fwd *fwd;

	syslog (LOG_DEBUG, "%s: start()", fn);

	if (!T.Fwd_list || !T.current_fwd)
		return;

	fwd = NULL;
        for (gl = T.Fwd_list->next; gl->list_data; gl = gl->next) {
	        fwd = (Fwd *)gl->list_data;

		if (sa->sa_family != fwd->sa->sa_family)
			continue;

#ifdef USE_INET6
		if (sa->sa_family == AF_INET6) {
			struct sockaddr_in6 *sina, *sinb;

			sina = (struct sockaddr_in6 *) (fwd->sa);
			sinb = (struct sockaddr_in6 *) sa;
			if (IN6_ARE_ADDR_EQUAL(&sina->sin6_addr, &sinb->sin6_addr)
			    && sina->sin6_port == sinb->sin6_port) {
				fwd->ticks += up;
				break;
			}
		}
#endif
#ifdef USE_INET4
		if (sa->sa_family == AF_INET) {
			struct sockaddr_in *sina, *sinb;

			sina = (struct sockaddr_in *) (fwd->sa);
			sinb = (struct sockaddr_in *) sa;
			if (sina->sin_addr.s_addr == sinb->sin_addr.s_addr &&
			    sina->sin_port == sinb->sin_port) {
				fwd->ticks += up;
				break;
			}
		}
#endif
	}

	if (!fwd)
		return;

	if (fwd->ticks < 0)
		fwd->ticks = 0;

	if (gl->list_data)
		syslog (LOG_DEBUG, "Mark forwarder with %d: %s ", fwd->ticks,
		    sprint_inet(sa, astr));

	if (fwd->ticks < FORWARDER_DEATH_MARK)
		return;
	else
		fwd->went_down_at = time(NULL);

	if (((Fwd *)(T.current_fwd->list_data))->went_down_at) {
		G_List *new_fwd;
		Fwd *fwd_tmp;

		/*
		 * we marked current forwarder down, so
		 * select new next valid forwarder
		 */
		new_fwd = T.current_fwd->next;
		fwd_tmp = (Fwd *)new_fwd->list_data;
		while (fwd_tmp) {
			if (fwd_tmp->sa && !fwd_tmp->went_down_at) 
				break;
			new_fwd = new_fwd->next;
	        	fwd_tmp = (Fwd *)new_fwd->list_data;
		}

		if (!fwd_tmp || !fwd_tmp->sa) {
			/*
			 * we didn't find a next valid forwarder, game over!
			 * Note that we do not mark current forwarder down
			 * (the current one never is) nor do we change it.
			 *
			 * Actually, we mark all forwarders up again! No use
			 * discriminating between things that seem to behave
			 * the same ;)
			 */
			new_fwd = T.Fwd_list->next;
			fwd_tmp = (Fwd *)new_fwd->list_data;
			while (fwd_tmp) {
				/* mark 'em `up' again */
				fwd_tmp->ticks = 0;
				fwd_tmp->went_down_at = 0;
				new_fwd = new_fwd->next;
	        		fwd_tmp = (Fwd *)new_fwd->list_data;
			}
			return;
		}

		syslog (LOG_NOTICE, "Disabling forwarder %s (next %s)", 
			sprint_inet(((Fwd *)T.current_fwd->list_data)->sa, astr), 
			sprint_inet(fwd_tmp->sa, bstr));

		T.current_fwd = new_fwd;
	}
}
Esempio n. 5
0
/*
 * Selects nameserver to initially forward incoming requests to.
 */
void fwd_select (void) {
	char *fn = "fwd_select";
    	char astr[MAX_DNAME];
	G_List *list_tmp;
	Fwd *fwd_tmp;

	syslog (LOG_DEBUG, "%s: start()", fn);

	if (!T.current_fwd) {
	    /* No forwarder selected yet, just pick first valid one */
	    if (!T.Fwd_list)
		return;

	    T.current_fwd = T.Fwd_list->next;
	    fwd_tmp = (Fwd *)T.current_fwd->list_data;
	    while (fwd_tmp && !fwd_tmp->sa) {
	    	T.current_fwd = T.current_fwd->next;
	        fwd_tmp = (Fwd *)T.current_fwd->list_data;
	    }

	    if (!fwd_tmp || !fwd_tmp->sa) {
		/* we didn't find a valid forwarder at all */
		T.current_fwd = NULL;
	    	syslog (LOG_ERR, "No forwarder configured!");
		return;
	    }
	    syslog (LOG_DEBUG, "Use initial forwarder %s",
		    sprint_inet(fwd_tmp->sa, astr));
	} else if (T.current_fwd->prev->list_data) {
	    /* 
	     * We're not using the first nameserver listed, i.e.
	     * we are using a backup server. After a while we should
	     * try to go back to an earlier nameserver.
	     */
	    time_t waittime, downtime, current_time;

	    current_time = time(NULL);
	    list_tmp = T.current_fwd->prev;
	    fwd_tmp = (Fwd *)list_tmp->list_data;
	    while (fwd_tmp) {
		waittime = (current_time - fwd_tmp->went_down_at);
		downtime = (time_t) (T.retry_interval);

		if (fwd_tmp->sa && waittime > downtime) {
		    /* waited long enough, let's try again! */
		    syslog (LOG_NOTICE, "Enable forwarder %s again",
			    sprint_inet(fwd_tmp->sa, astr));
		    /* for the occasion, we mark it up again */
		    fwd_tmp->went_down_at = 0;
		    if (fwd_tmp->ticks > 0)
		    	fwd_tmp->ticks--;
		    T.current_fwd = list_tmp;
		    /* only one at a time, the rest will follow */
		    break;
		}
		list_tmp = list_tmp->prev;
	    	fwd_tmp = (Fwd *)list_tmp->list_data;
	    }
	}

	syslog (LOG_DEBUG, "Current forwarder %s",
		    sprint_inet(((Fwd *)T.current_fwd->list_data)->sa, astr));
	syslog (LOG_DEBUG, "%s: end()", fn);
	return;
}
Esempio n. 6
0
static int net_get_ifaddrs (G_List *list_head, int port) {
	const char *fn = "net_get_ifaddrs()";
	static struct ifconf ifc_old;
	struct ifconf ifc;
	int dummy_sock = -1, status;
	u_char buf[8192];
	u_char *cp;

	memset (buf, 0, sizeof (buf));
	ifc.ifc_len = sizeof (buf);
	ifc.ifc_buf = buf;

#ifdef USE_INET6
	if (dummy_sock < 0)
		dummy_sock = socket (AF_INET6, SOCK_STREAM, 0);
#endif
#ifdef USE_INET4
	if (dummy_sock < 0)
		dummy_sock = socket (AF_INET, SOCK_STREAM, 0);
#endif
	if (dummy_sock < 0)
		return -1;

	/*
	 * check whether list of interface addresses has changed
	 */
	if (ioctl (dummy_sock, SIOCGIFCONF, (char *) &ifc) < 0) {
		close(dummy_sock);
		syslog (LOG_ERR, "%s: get iflist error: %m", fn);
		return -1;
	}
	close(dummy_sock);

	status = 1;
	if (ifc_old.ifc_buf) {
		status = net_ifc_cmp (&ifc_old, &ifc);
		syslog (LOG_DEBUG, "%s: checked interface data %d", fn, status);
	}

	/*
	 * Interface address list changed or we got called for
	 * for the first time
	 */

	cp = buf;
	while (*cp) {
		int valid_address = 0;
		char astr[MAX_DNAME];
		struct ifreq *ifr_p;

		ifr_p = (struct ifreq *) cp;
		sprint_inet(&ifr_p->ifr_addr, astr);

#ifdef USE_INET6
		if (T.ip6 && ifr_p->ifr_addr.sa_family == AF_INET6)
			if (nia_is_in_totd_iflist(ifr_p->ifr_name))
				valid_address = 1;
#endif
#ifdef USE_INET4
		if (T.ip4 && ifr_p->ifr_addr.sa_family == AF_INET)
			if (T.ip4 && nia_is_in_totd_iflist(ifr_p->ifr_name))
				valid_address = 1;
#endif

		if (valid_address) {
			Nia *ni;

			ni = nia_alloc (&ifr_p->ifr_addr, -1, -1);
			if (!ni)
				return -1;

#ifdef USE_INET6
			if (T.ip6 && ni->sa_p->sa_family == AF_INET6) {
				struct sockaddr_in6 *sa_p;

				sa_p = (struct sockaddr_in6 *) ni->sa_p;
				sa_p->sin6_port = htons (port);
			}
#endif

#ifdef USE_INET6
			if (T.ip4 && ni->sa_p->sa_family == AF_INET) {
				struct sockaddr_in *sa_p;

				sa_p = (struct sockaddr_in *) ni->sa_p;
				sa_p->sin_port = htons (port);
			}
#endif

			if (*astr && T.debug > 3)
				syslog (LOG_DEBUG, "Found address %s on if %s",
					astr, ifr_p->ifr_name);

			/* ok! add to the list */
			if (list_add (list_head, ni) < 0)
                        	return -1;

		} else if (*astr && T.debug > 3)
			syslog (LOG_DEBUG, "Ignoring address %s on if %s",
				astr, ifr_p->ifr_name);

		/* point to next address entry in list */
		cp = cp + IFNAMSIZ + SOCKADDR_SIZEOF (ifr_p->ifr_addr);
	}

	/*
	 * preserve old buffer
	 */

	if (ifc_old.ifc_buf)
		free (ifc_old.ifc_buf);

	ifc_old.ifc_buf = malloc (ifc.ifc_len);
	if (ifc_old.ifc_buf) {
		memcpy (ifc_old.ifc_buf, buf, ifc.ifc_len);
		ifc_old.ifc_len = ifc.ifc_len;
	}

	return status;
}