File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / sntp / networking.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:38 2012 UTC (12 years, 1 month ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

    1: #include <config.h>
    2: #include "networking.h"
    3: 
    4: char adr_buf[INET6_ADDRSTRLEN];
    5: 
    6: 
    7: /* resolve_hosts consumes an array of hostnames/addresses and its length, stores a pointer
    8:  * to the array with the resolved hosts in res and returns the size of the array res.
    9:  * pref_family enforces IPv4 or IPv6 depending on commandline options and system 
   10:  * capability. If pref_family is NULL or PF_UNSPEC any compatible family will be accepted.
   11:  * Check here: Probably getaddrinfo() can do without ISC's IPv6 availability check? 
   12:  */
   13: int 
   14: resolve_hosts (
   15: 		const char **hosts, 
   16: 		int hostc, 
   17: 		struct addrinfo ***res,
   18: 		int pref_family
   19: 		) 
   20: {
   21: 	register unsigned int a;
   22: 	unsigned int resc;
   23: 	struct addrinfo **tres;
   24: 
   25: 	if (hostc < 1 || NULL == res)
   26: 		return 0;
   27: 	
   28: 	tres = emalloc(sizeof(struct addrinfo *) * hostc);
   29: 	for (a = 0, resc = 0; a < hostc; a++) {
   30: 		struct addrinfo hints;
   31: 		int error;
   32: 
   33: 		tres[resc] = NULL;
   34: #ifdef DEBUG
   35: 		printf("sntp resolve_hosts: Starting host resolution for %s...\n", hosts[a]); 
   36: #endif
   37: 		memset(&hints, 0, sizeof(hints));
   38: 		if (AF_UNSPEC == pref_family)
   39: 			hints.ai_family = PF_UNSPEC;
   40: 		else 
   41: 			hints.ai_family = pref_family;
   42: 		hints.ai_socktype = SOCK_DGRAM;
   43: 		error = getaddrinfo(hosts[a], "123", &hints, &tres[resc]);
   44: 		if (error) {
   45: 			msyslog(LOG_DEBUG, "Error looking up %s%s: %s",
   46: 				(AF_UNSPEC == hints.ai_family)
   47: 				    ? ""
   48: 				    : (AF_INET == hints.ai_family)
   49: 					  ? "(A) "
   50: 					  : "(AAAA) ",
   51: 				hosts[a], gai_strerror(error));
   52: 		} else {
   53: #ifdef DEBUG
   54: 			for (dres = tres[resc]; dres; dres = dres->ai_next) {
   55: 				getnameinfo(dres->ai_addr, dres->ai_addrlen, adr_buf, sizeof(adr_buf), NULL, 0, NI_NUMERICHOST);
   56: 				STDLINE
   57: 				printf("Resolv No.: %i Result of getaddrinfo for %s:\n", resc, hosts[a]);
   58: 				printf("socktype: %i ", dres->ai_socktype); 
   59: 				printf("protocol: %i ", dres->ai_protocol);
   60: 				printf("Prefered socktype: %i IP: %s\n", dres->ai_socktype, adr_buf);
   61: 				STDLINE
   62: 			}
   63: #endif
   64: 			resc++;
   65: 		}
   66: 	}
   67: 
   68: 	if (resc)
   69: 		*res = realloc(tres, sizeof(struct addrinfo *) * resc);
   70: 	else {
   71: 		free(tres);
   72: 		*res = NULL;
   73: 	}
   74: 	return resc;
   75: }
   76: 
   77: /* Creates a socket and returns. */
   78: void 
   79: create_socket (
   80: 		SOCKET *rsock,
   81: 		sockaddr_u *dest
   82: 		)
   83: {
   84: 	*rsock = socket(AF(dest), SOCK_DGRAM, 0);
   85: 
   86: 	if (-1 == *rsock && ENABLED_OPT(NORMALVERBOSE))
   87: 		printf("Failed to create UDP socket with family %d\n", AF(dest));
   88: }
   89: 
   90: /* Send a packet */
   91: void
   92: sendpkt (
   93: 	SOCKET rsock,
   94: 	sockaddr_u *dest,
   95: 	struct pkt *pkt,
   96: 	int len
   97: 	)
   98: {
   99: 	int cc;
  100: 
  101: #ifdef DEBUG
  102: 	printf("sntp sendpkt: Packet data:\n");
  103: 	pkt_output(pkt, len, stdout);
  104: #endif
  105: 
  106: 	if (ENABLED_OPT(NORMALVERBOSE)) {
  107: 		getnameinfo(&dest->sa, SOCKLEN(dest), adr_buf, sizeof(adr_buf), NULL, 0, NI_NUMERICHOST);
  108: 		printf("sntp sendpkt: Sending packet to %s... ", adr_buf);
  109: 	}
  110: 
  111: 	cc = sendto(rsock, (void *)pkt, len, 0, &dest->sa, SOCKLEN(dest));
  112: 	if (cc == SOCKET_ERROR) {
  113: #ifdef DEBUG
  114: 		printf("\n sntp sendpkt: Socket error: %i. Couldn't send packet!\n", cc);
  115: #endif
  116: 		if (errno != EWOULDBLOCK && errno != ENOBUFS) {
  117: 			/* oh well */
  118: 		}
  119: 	} else if (ENABLED_OPT(NORMALVERBOSE)) {
  120: 		printf("Packet sent.\n");
  121: 	}
  122: }
  123: 
  124: /* Receive raw data */
  125: int
  126: recvdata(
  127: 	SOCKET rsock,
  128: 	sockaddr_u *sender,
  129: 	char *rdata,
  130: 	int rdata_length
  131: 	)
  132: {
  133: 	GETSOCKNAME_SOCKLEN_TYPE slen;
  134: 	int recvc;
  135: 
  136: #ifdef DEBUG
  137: 	printf("sntp recvdata: Trying to receive data from...\n");
  138: #endif
  139: 	slen = sizeof(*sender);
  140: 	recvc = recvfrom(rsock, rdata, rdata_length, 0, 
  141: 			 &sender->sa, &slen);
  142: #ifdef DEBUG
  143: 	if (recvc > 0) {
  144: 		printf("Received %d bytes from %s:\n", recvc, stoa(sender));
  145: 		pkt_output((struct pkt *) rdata, recvc, stdout);
  146: 	} else {
  147: 		saved_errno = errno;
  148: 		printf("recvfrom error %d (%s)\n", errno, strerror(errno));
  149: 		errno = saved_errno;
  150: 	}
  151: #endif
  152: 	return recvc;
  153: }
  154: 
  155: /* Receive data from broadcast. Couldn't finish that. Need to do some digging
  156:  * here, especially for protocol independence and IPv6 multicast */
  157: int 
  158: recv_bcst_data (
  159: 	SOCKET rsock,
  160: 	char *rdata,
  161: 	int rdata_len,
  162: 	sockaddr_u *sas,
  163: 	sockaddr_u *ras
  164: 	)
  165: {
  166: 	char *buf;
  167: 	int btrue = 1;
  168: 	int recv_bytes = 0;
  169: 	int rdy_socks;
  170: 	GETSOCKNAME_SOCKLEN_TYPE ss_len;
  171: 	struct timeval timeout_tv;
  172: 	fd_set bcst_fd;
  173: #ifdef MCAST
  174: 	struct ip_mreq mdevadr;
  175: 	TYPEOF_IP_MULTICAST_LOOP mtrue = 1;
  176: #endif
  177: #ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
  178: 	struct ipv6_mreq mdevadr6;
  179: #endif
  180: 
  181: 	setsockopt(rsock, SOL_SOCKET, SO_REUSEADDR, &btrue, sizeof(btrue));
  182: 	if (IS_IPV4(sas)) {
  183: 		if (bind(rsock, &sas->sa, SOCKLEN(sas)) < 0) {
  184: 			if (ENABLED_OPT(NORMALVERBOSE))
  185: 				printf("sntp recv_bcst_data: Couldn't bind() address %s:%d.\n",
  186: 				       stoa(sas), SRCPORT(sas));
  187: 		}
  188: 
  189: #ifdef MCAST
  190: 		if (setsockopt(rsock, IPPROTO_IP, IP_MULTICAST_LOOP, &mtrue, sizeof(mtrue)) < 0) {
  191: 			/* some error message regarding setting up multicast loop */
  192: 			return BROADCAST_FAILED;
  193: 		}
  194: 		mdevadr.imr_multiaddr.s_addr = NSRCADR(sas); 
  195: 		mdevadr.imr_interface.s_addr = htonl(INADDR_ANY);
  196: 		if (mdevadr.imr_multiaddr.s_addr == -1) {
  197: 			if (ENABLED_OPT(NORMALVERBOSE)) {
  198: 				printf("sntp recv_bcst_data: %s:%d is not a broad-/multicast address, aborting...\n",
  199: 				       stoa(sas), SRCPORT(sas));
  200: 			}
  201: 			return BROADCAST_FAILED;
  202: 		}
  203: 		if (setsockopt(rsock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mdevadr, sizeof(mdevadr)) < 0) {
  204: 			if (ENABLED_OPT(NORMALVERBOSE)) {
  205: 				buf = ss_to_str(sas);
  206: 				printf("sntp recv_bcst_data: Couldn't add IP membership for %s\n", buf);
  207: 				free(buf);
  208: 			}
  209: 		}
  210: #endif	/* MCAST */
  211: 	}
  212: #ifdef ISC_PLATFORM_HAVEIPV6
  213: 	else if (IS_IPV6(sas)) {
  214: 		if (bind(rsock, &sas->sa, SOCKLEN(sas)) < 0) {
  215: 			if (ENABLED_OPT(NORMALVERBOSE))
  216: 				printf("sntp recv_bcst_data: Couldn't bind() address.\n");
  217: 		}
  218: #ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
  219: 		if (setsockopt(rsock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &btrue, sizeof (btrue)) < 0) {
  220: 			/* some error message regarding setting up multicast loop */
  221: 			return BROADCAST_FAILED;
  222: 		}
  223: 		memset(&mdevadr6, 0, sizeof(mdevadr6));
  224: 		mdevadr6.ipv6mr_multiaddr = SOCK_ADDR6(sas);
  225: 		if (!IN6_IS_ADDR_MULTICAST(&mdevadr6.ipv6mr_multiaddr)) {
  226: 			if (ENABLED_OPT(NORMALVERBOSE)) {
  227: 				buf = ss_to_str(sas); 
  228: 				printf("sntp recv_bcst_data: %s is not a broad-/multicast address, aborting...\n", buf);
  229: 				free(buf);
  230: 			}
  231: 			return BROADCAST_FAILED;
  232: 		}
  233: 		if (setsockopt(rsock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
  234: 			       &mdevadr6, sizeof(mdevadr6)) < 0) {
  235: 			if (ENABLED_OPT(NORMALVERBOSE)) {
  236: 				buf = ss_to_str(sas); 
  237: 				printf("sntp recv_bcst_data: Couldn't join group for %s\n", buf);
  238: 				free(buf);
  239: 			}
  240: 		}
  241: #endif	/* INCLUDE_IPV6_MULTICAST_SUPPORT */
  242: 	}
  243: #endif	/* ISC_PLATFORM_HAVEIPV6 */
  244: 	FD_ZERO(&bcst_fd);
  245: 	FD_SET(rsock, &bcst_fd);
  246: 	if (ENABLED_OPT(TIMEOUT)) 
  247: 		timeout_tv.tv_sec = (int) OPT_ARG(TIMEOUT);
  248: 	else 
  249: 		timeout_tv.tv_sec = 68; /* ntpd broadcasts every 64s */
  250: 	timeout_tv.tv_usec = 0;
  251: 	rdy_socks = select(rsock + 1, &bcst_fd, 0, 0, &timeout_tv);
  252: 	switch (rdy_socks) {
  253: 	case -1: 
  254: 		if (ENABLED_OPT(NORMALVERBOSE)) 
  255: 			perror("sntp recv_bcst_data: select()");
  256: 		return BROADCAST_FAILED;
  257: 		break;
  258: 	case 0:
  259: 		if (ENABLED_OPT(NORMALVERBOSE))
  260: 			printf("sntp recv_bcst_data: select() reached timeout (%u sec), aborting.\n", 
  261: 			       (unsigned)timeout_tv.tv_sec);
  262: 		return BROADCAST_FAILED;
  263: 		break;
  264: 	default:
  265: 		ss_len = sizeof(*ras);
  266: 		recv_bytes = recvfrom(rsock, rdata, rdata_len, 0, &ras->sa, &ss_len);
  267: 		break;
  268: 	}
  269: 	if (recv_bytes == -1) {
  270: 		if (ENABLED_OPT(NORMALVERBOSE))
  271: 			perror("sntp recv_bcst_data: recvfrom:");
  272: 		recv_bytes = BROADCAST_FAILED;
  273: 	}
  274: #ifdef MCAST
  275: 	if (IS_IPV4(sas)) 
  276: 		setsockopt(rsock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &btrue, sizeof(btrue));
  277: #endif
  278: #ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
  279: 	if (IS_IPV6(sas))
  280: 		setsockopt(rsock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &btrue, sizeof(btrue));
  281: #endif
  282: 	return recv_bytes;
  283: }
  284: 
  285: int
  286: process_pkt (
  287: 	struct pkt *rpkt,
  288: 	sockaddr_u *sas,
  289: 	int pkt_len,
  290: 	int mode,
  291: 	struct pkt *spkt,
  292: 	char * func_name
  293: 	)
  294: {
  295: 	unsigned int key_id = 0;
  296: 	struct key *pkt_key = NULL;
  297: 	int is_authentic = 0;
  298: 	unsigned int exten_words, exten_words_used = 0;
  299: 	int mac_size;
  300: 	/*
  301: 	 * Parse the extension field if present. We figure out whether
  302: 	 * an extension field is present by measuring the MAC size. If
  303: 	 * the number of words following the packet header is 0, no MAC
  304: 	 * is present and the packet is not authenticated. If 1, the
  305: 	 * packet is a crypto-NAK; if 3, the packet is authenticated
  306: 	 * with DES; if 5, the packet is authenticated with MD5; if 6,
  307: 	 * the packet is authenticated with SHA. If 2 or 4, the packet
  308: 	 * is a runt and discarded forthwith. If greater than 6, an
  309: 	 * extension field is present, so we subtract the length of the
  310: 	 * field and go around again.
  311: 	 */
  312: 	if (pkt_len < LEN_PKT_NOMAC || (pkt_len & 3) != 0) {
  313: unusable:
  314: 		if (ENABLED_OPT(NORMALVERBOSE))
  315: 			printf("sntp %s: Funny packet length: %i. Discarding package.\n", func_name, pkt_len);
  316: 		return PACKET_UNUSEABLE;
  317: 	}
  318: 	/* skip past the extensions, if any */
  319: 	exten_words = ((unsigned)pkt_len - LEN_PKT_NOMAC) >> 2;
  320: 	while (exten_words > 6) {
  321: 		unsigned int exten_len;
  322: 		exten_len = ntohl(rpkt->exten[exten_words_used]) & 0xffff;
  323: 		exten_len = (exten_len + 7) >> 2; /* convert to words, add 1 */
  324: 		if (exten_len > exten_words || exten_len < 5)
  325: 			goto unusable;
  326: 		exten_words -= exten_len;
  327: 		exten_words_used += exten_len;
  328: 	}
  329: 
  330: 	switch (exten_words) {
  331: 	case 1:
  332: 		key_id = ntohl(rpkt->exten[exten_words_used]);
  333: 		printf("Crypto NAK = 0x%08x\n", key_id);
  334: 		break;
  335: 	case 5:
  336: 	case 6:
  337: 		/* Look for the key used by the server in the specified keyfile
  338: 		 * and if existent, fetch it or else leave the pointer untouched */
  339: 		key_id = ntohl(rpkt->exten[exten_words_used]);
  340: 		get_key(key_id, &pkt_key);
  341: 		if (!pkt_key) {
  342: 			printf("unrecognized key ID = 0x%08x\n", key_id);
  343: 			break;
  344: 		}
  345: 		/* Seems like we've got a key with matching keyid */
  346: 		/* Generate a md5sum of the packet with the key from our keyfile
  347: 		 * and compare those md5sums */
  348: 		mac_size = exten_words << 2;
  349: 		if (!auth_md5((char *)rpkt, pkt_len - mac_size, mac_size - 4, pkt_key)) {
  350: 			break;
  351: 		}
  352: 		/* Yay! Things worked out! */
  353: 		if (ENABLED_OPT(NORMALVERBOSE)) {
  354: 			char *hostname = ss_to_str(sas);
  355: 			printf("sntp %s: packet received from %s successfully authenticated using key id %i.\n",
  356: 				func_name, hostname, key_id);
  357: 			free(hostname);
  358: 		}
  359: 		is_authentic = 1;
  360: 		break;
  361: 	case 0:
  362: 		break;
  363: 	default:
  364: 		goto unusable;
  365: 		break;
  366: 	}
  367: 	if (!is_authentic) {
  368: 		if (ENABLED_OPT(AUTHENTICATION)) {
  369: 			/* We want a authenticated packet */
  370: 			if (ENABLED_OPT(NORMALVERBOSE)) {
  371: 				char *hostname = ss_to_str(sas);
  372: 				printf("sntp %s: packet received from %s is not authentic. Will discard it.\n",
  373: 					func_name, hostname);
  374: 				free(hostname);
  375: 			}
  376: 			return SERVER_AUTH_FAIL;
  377: 		}
  378: 		/* We don't know if the user wanted authentication so let's 
  379: 		 * use it anyways */
  380: 		if (ENABLED_OPT(NORMALVERBOSE)) {
  381: 			char *hostname = ss_to_str(sas);
  382: 			printf("sntp %s: packet received from %s is not authentic. Authentication not enforced.\n",
  383: 				func_name, hostname);
  384: 			free(hostname);
  385: 		}
  386: 	}
  387: 	/* Check for server's ntp version */
  388: 	if (PKT_VERSION(rpkt->li_vn_mode) < NTP_OLDVERSION ||
  389: 		PKT_VERSION(rpkt->li_vn_mode) > NTP_VERSION) {
  390: 		if (ENABLED_OPT(NORMALVERBOSE))
  391: 			printf("sntp %s: Packet shows wrong version (%i)\n",
  392: 				func_name, PKT_VERSION(rpkt->li_vn_mode));
  393: 		return SERVER_UNUSEABLE;
  394: 	} 
  395: 	/* We want a server to sync with */
  396: 	if (PKT_MODE(rpkt->li_vn_mode) != mode &&
  397: 	    PKT_MODE(rpkt->li_vn_mode) != MODE_PASSIVE) {
  398: 		if (ENABLED_OPT(NORMALVERBOSE))
  399: 			printf("sntp %s: mode %d stratum %i\n", func_name, 
  400: 			       PKT_MODE(rpkt->li_vn_mode), rpkt->stratum);
  401: 		return SERVER_UNUSEABLE;
  402: 	}
  403: 	/* Stratum is unspecified (0) check what's going on */
  404: 	if (STRATUM_PKT_UNSPEC == rpkt->stratum) {
  405: 		char *ref_char;
  406: 		if (ENABLED_OPT(NORMALVERBOSE))
  407: 			printf("sntp %s: Stratum unspecified, going to check for KOD (stratum: %i)\n", 
  408: 				func_name, rpkt->stratum);
  409: 		ref_char = (char *) &rpkt->refid;
  410: 		if (ENABLED_OPT(NORMALVERBOSE))
  411: 			printf("sntp %s: Packet refid: %c%c%c%c\n", func_name,
  412: 			       ref_char[0], ref_char[1], ref_char[2], ref_char[3]);
  413: 		/* If it's a KOD packet we'll just use the KOD information */
  414: 		if (ref_char[0] != 'X') {
  415: 			if (strncmp(ref_char, "DENY", 4) == 0)
  416: 				return KOD_DEMOBILIZE;
  417: 			if (strncmp(ref_char, "RSTR", 4) == 0)
  418: 				return KOD_DEMOBILIZE;
  419: 			if (strncmp(ref_char, "RATE", 4) == 0)
  420: 				return KOD_RATE;
  421: 			/* There are other interesting kiss codes which might be interesting for authentication */
  422: 		}
  423: 	}
  424: 	/* If the server is not synced it's not really useable for us */
  425: 	if (LEAP_NOTINSYNC == PKT_LEAP(rpkt->li_vn_mode)) {
  426: 		if (ENABLED_OPT(NORMALVERBOSE)) 
  427: 			printf("sntp %s: Server not in sync, skipping this server\n", func_name);
  428: 		return SERVER_UNUSEABLE;
  429: 	}
  430: 
  431: 	/*
  432: 	 * Decode the org timestamp and make sure we're getting a response
  433: 	 * to our last request, but only if we're not in broadcast mode.
  434: 	 */
  435: #ifdef DEBUG
  436: 	printf("rpkt->org:\n");
  437: 	l_fp_output(&rpkt->org, stdout);
  438: 	printf("spkt->xmt:\n");
  439: 	l_fp_output(&spkt->xmt, stdout);
  440: #endif
  441: 	if (mode != MODE_BROADCAST && !L_ISEQU(&rpkt->org, &spkt->xmt)) {
  442: 		if (ENABLED_OPT(NORMALVERBOSE))
  443: 			printf("sntp process_pkt: pkt.org and peer.xmt differ\n");
  444: 		return PACKET_UNUSEABLE;
  445: 	}
  446: 
  447: 	return pkt_len;
  448: }
  449: 
  450: int 
  451: recv_bcst_pkt (
  452: 	SOCKET rsock,
  453: 	struct pkt *rpkt,
  454: 	unsigned int rsize,
  455: 	sockaddr_u *sas
  456: 	)
  457: {
  458: 	sockaddr_u sender;
  459: 	int pkt_len = recv_bcst_data(rsock, (char *)rpkt, rsize, sas, &sender);
  460: 	if (pkt_len < 0) {
  461: 		return BROADCAST_FAILED;
  462: 	}
  463: 	pkt_len = process_pkt(rpkt, sas, pkt_len, MODE_BROADCAST, NULL, "recv_bcst_pkt");
  464: 	return pkt_len;
  465: }
  466: 
  467: /* Fetch data, check if it's data for us and whether it's useable or not. If not, return
  468:  * a failure code so we can delete this server from our list and continue with another one.
  469:  */
  470: int
  471: recvpkt (
  472: 	SOCKET rsock,
  473: 	struct pkt *rpkt,    /* received packet (response) */
  474: 	unsigned int rsize,  /* size of rpkt buffer */
  475: 	struct pkt *spkt     /* sent     packet (request) */
  476: 	)
  477: {
  478: 	int rdy_socks;
  479: 	int pkt_len;
  480: 	sockaddr_u sender;
  481: 	struct timeval timeout_tv;
  482: 	fd_set recv_fd;
  483: 
  484: 	FD_ZERO(&recv_fd);
  485: 	FD_SET(rsock, &recv_fd);
  486: 	if (ENABLED_OPT(TIMEOUT)) 
  487: 		timeout_tv.tv_sec = (int) OPT_ARG(TIMEOUT);
  488: 	else 
  489: 		timeout_tv.tv_sec = 68; /* ntpd broadcasts every 64s */
  490: 	timeout_tv.tv_usec = 0;
  491: 	rdy_socks = select(rsock + 1, &recv_fd, 0, 0, &timeout_tv);
  492: 	switch (rdy_socks) {
  493: 	case -1: 
  494: 		if (ENABLED_OPT(NORMALVERBOSE)) 
  495: 			perror("sntp recvpkt: select()");
  496: 		return PACKET_UNUSEABLE;
  497: 		break;
  498: 	case 0:
  499: 		if (ENABLED_OPT(NORMALVERBOSE))
  500: 			printf("sntp recvpkt: select() reached timeout (%u sec), aborting.\n", 
  501: 			       (unsigned)timeout_tv.tv_sec);
  502: 		return PACKET_UNUSEABLE;
  503: 		break;
  504: 	default:
  505: 		break;
  506: 	}
  507: 	pkt_len = recvdata(rsock, &sender, (char *)rpkt, rsize);
  508: 	if (pkt_len > 0)
  509: 		pkt_len = process_pkt(rpkt, &sender, pkt_len, MODE_SERVER, spkt, "recvpkt");
  510: 
  511: 	return pkt_len;
  512: }
  513: 
  514: /*
  515:  * is_reachable - check to see if we have a route to given destination
  516:  */
  517: int
  518: is_reachable (
  519: 	struct addrinfo *dst
  520: 	)
  521: {
  522: 	SOCKET sockfd = socket(dst->ai_family, SOCK_DGRAM, 0);
  523: 
  524: 	if (-1 == sockfd) {
  525: #ifdef DEBUG
  526: 		printf("is_reachable: Couldn't create socket\n");
  527: #endif
  528: 		return 0;
  529: 	}
  530: 	if (connect(sockfd, dst->ai_addr, SOCKLEN((sockaddr_u *)dst->ai_addr))) {
  531: 		closesocket(sockfd);
  532: 		return 0;
  533: 	}
  534: 	closesocket(sockfd);
  535: 	return 1;
  536: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>