⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ntpq.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 5 页
字号:
	 * First try to resolve it as an ip address and if that fails,	 * do a fullblown (dns) lookup. That way we only use the dns	 * when it is needed and work around some implementations that	 * will return an "IPv4-mapped IPv6 address" address if you	 * give it an IPv4 address to lookup.	 */	strcpy(service, "ntp");	memset((char *)&hints, 0, sizeof(struct addrinfo));	hints.ai_family = ai_fam_templ;	hints.ai_protocol = IPPROTO_UDP;	hints.ai_socktype = SOCK_DGRAM;	hints.ai_flags = AI_NUMERICHOST;	a_info = getaddrinfo(hname, service, &hints, &ai);	if (a_info == EAI_NONAME#ifdef EAI_NODATA	    || a_info == EAI_NODATA#endif	   ) {		hints.ai_flags = AI_CANONNAME;#ifdef AI_ADDRCONFIG		hints.ai_flags |= AI_ADDRCONFIG;#endif		a_info = getaddrinfo(hname, service, &hints, &ai);		}	/* Some older implementations don't like AI_ADDRCONFIG. */	if (a_info == EAI_BADFLAGS) {		hints.ai_flags = AI_CANONNAME;		a_info = getaddrinfo(hname, service, &hints, &ai);		}	if (a_info != 0) {		(void) fprintf(stderr, "%s\n", gai_strerror(a_info));		return 0;	}	if (ai->ai_canonname == NULL) {		strncpy(temphost, stoa((struct sockaddr_storage *)ai->ai_addr),		    LENHOSTNAME);		temphost[LENHOSTNAME-1] = '\0';	} else {		strncpy(temphost, ai->ai_canonname, LENHOSTNAME);		temphost[LENHOSTNAME-1] = '\0';	}	if (debug > 2)	    printf("Opening host %s\n", temphost);	if (havehost == 1) {		if (debug > 2)		    printf("Closing old host %s\n", currenthost);		(void) closesocket(sockfd);		havehost = 0;	}	(void) strcpy(currenthost, temphost);	/* port maps to the same location in both families */	s_port = ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port;#ifdef SYS_VXWORKS	((struct sockaddr_in6 *)&hostaddr)->sin6_port = htons(SERVER_PORT_NUM);	if (ai->ai_family == AF_INET)		*(struct sockaddr_in *)&hostaddr=			*((struct sockaddr_in *)ai->ai_addr);	else		*(struct sockaddr_in6 *)&hostaddr=			*((struct sockaddr_in6 *)ai->ai_addr);#endif /* SYS_VXWORKS */#ifdef SYS_WINNT	{		int optionValue = SO_SYNCHRONOUS_NONALERT;		int err;		err = setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *)&optionValue, sizeof(optionValue));		if (err != NO_ERROR) {			(void) fprintf(stderr, "cannot open nonoverlapped sockets\n");			exit(1);		}	}#endif /* SYS_WINNT */	sockfd = socket(ai->ai_family, SOCK_DGRAM, 0);	if (sockfd == INVALID_SOCKET) {		error("socket", "", "");	}	#ifdef NEED_RCVBUF_SLOP# ifdef SO_RCVBUF	{ int rbufsize = DATASIZE + 2048;	/* 2K for slop */	if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF,		       &rbufsize, sizeof(int)) == -1)	    error("setsockopt", "", "");	}# endif#endif#ifdef SYS_VXWORKS	if (connect(sockfd, (struct sockaddr *)&hostaddr,		    sizeof(hostaddr)) == -1)#else	if (connect(sockfd, (struct sockaddr *)ai->ai_addr,		    ai->ai_addrlen) == -1)#endif /* SYS_VXWORKS */	    error("connect", "", "");	if (a_info == 0)		freeaddrinfo(ai);	havehost = 1;	return 1;}/* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c *//* * sendpkt - send a packet to the remote host */static intsendpkt(	char *xdata,	int xdatalen	){	if (debug >= 3)	    printf("Sending %d octets\n", xdatalen);	if (send(sockfd, xdata, (size_t)xdatalen, 0) == -1) {		warning("write to %s failed", currenthost, "");		return -1;	}	if (debug >= 4) {		int first = 8;		printf("Packet data:\n");		while (xdatalen-- > 0) {			if (first-- == 0) {				printf("\n");				first = 7;			}			printf(" %02x", *xdata++ & 0xff);		}		printf("\n");	}	return 0;}/* * getresponse - get a (series of) response packet(s) and return the data */static intgetresponse(	int opcode,	int associd,	u_short *rstatus,	int *rsize,	char **rdata,	int timeo	){	struct ntp_control rpkt;	struct timeval tvo;	u_short offsets[MAXFRAGS+1];	u_short counts[MAXFRAGS+1];	u_short offset;	u_short count;	int numfrags;	int seenlastfrag;	fd_set fds;	int n;	/*	 * This is pretty tricky.  We may get between 1 and MAXFRAG packets	 * back in response to the request.  We peel the data out of	 * each packet and collect it in one long block.  When the last	 * packet in the sequence is received we'll know how much data we	 * should have had.  Note we use one long time out, should reconsider.	 */	*rsize = 0;	if (rstatus)	    *rstatus = 0;	*rdata = (char *)pktdata;	numfrags = 0;	seenlastfrag = 0;	FD_ZERO(&fds);    again:	if (numfrags == 0)	    tvo = tvout;	else	    tvo = tvsout;		FD_SET(sockfd, &fds);	n = select(sockfd+1, &fds, (fd_set *)0, (fd_set *)0, &tvo);#if 0	if (debug >= 1)	    printf("select() returns %d\n", n);#endif	if (n == -1) {		warning("select fails", "", "");		return -1;	}	if (n == 0) {		/*		 * Timed out.  Return what we have		 */		if (numfrags == 0) {			if (timeo)			    (void) fprintf(stderr,					   "%s: timed out, nothing received\n",					   currenthost);			return ERR_TIMEOUT;		} else {			if (timeo)			    (void) fprintf(stderr,					   "%s: timed out with incomplete data\n",					   currenthost);			if (debug) {				printf("Received fragments:\n");				for (n = 0; n < numfrags; n++)				    printf("%4d %d\n", offsets[n],					   counts[n]);				if (seenlastfrag)				    printf("last fragment received\n");				else				    printf("last fragment not received\n");			}			return ERR_INCOMPLETE;		}	}	n = recv(sockfd, (char *)&rpkt, sizeof(rpkt), 0);	if (n == -1) {		warning("read", "", "");		return -1;	}	if (debug >= 4) {		int len = n, first = 8;		char *data = (char *)&rpkt;		printf("Packet data:\n");		while (len-- > 0) {			if (first-- == 0) {				printf("\n");				first = 7;			}			printf(" %02x", *data++ & 0xff);		}		printf("\n");	}	/*	 * Check for format errors.  Bug proofing.	 */	if (n < CTL_HEADER_LEN) {		if (debug)		    printf("Short (%d byte) packet received\n", n);		goto again;	}	if (PKT_VERSION(rpkt.li_vn_mode) > NTP_VERSION	    || PKT_VERSION(rpkt.li_vn_mode) < NTP_OLDVERSION) {		if (debug)		    printf("Packet received with version %d\n",			   PKT_VERSION(rpkt.li_vn_mode));		goto again;	}	if (PKT_MODE(rpkt.li_vn_mode) != MODE_CONTROL) {		if (debug)		    printf("Packet received with mode %d\n",			   PKT_MODE(rpkt.li_vn_mode));		goto again;	}	if (!CTL_ISRESPONSE(rpkt.r_m_e_op)) {		if (debug)		    printf("Received request packet, wanted response\n");		goto again;	}	/*	 * Check opcode and sequence number for a match.	 * Could be old data getting to us.	 */	if (ntohs(rpkt.sequence) != sequence) {		if (debug)		    printf(			    "Received sequnce number %d, wanted %d\n",			    ntohs(rpkt.sequence), sequence);		goto again;	}	if (CTL_OP(rpkt.r_m_e_op) != opcode) {		if (debug)		    printf(			    "Received opcode %d, wanted %d (sequence number okay)\n",			    CTL_OP(rpkt.r_m_e_op), opcode);		goto again;	}	/*	 * Check the error code.  If non-zero, return it.	 */	if (CTL_ISERROR(rpkt.r_m_e_op)) {		int errcode;		errcode = (ntohs(rpkt.status) >> 8) & 0xff;		if (debug && CTL_ISMORE(rpkt.r_m_e_op)) {			printf("Error code %d received on not-final packet\n",			       errcode);		}		if (errcode == CERR_UNSPEC)		    return ERR_UNSPEC;		return errcode;	}	/*	 * Check the association ID to make sure it matches what	 * we sent.	 */	if (ntohs(rpkt.associd) != associd) {		if (debug)		    printf("Association ID %d doesn't match expected %d\n",			   ntohs(rpkt.associd), associd);		/*		 * Hack for silly fuzzballs which, at the time of writing,		 * return an assID of sys.peer when queried for system variables.		 */#ifdef notdef		goto again;#endif	}	/*	 * Collect offset and count.  Make sure they make sense.	 */	offset = ntohs(rpkt.offset);	count = ntohs(rpkt.count);	if (debug >= 3) {		int shouldbesize;		u_long key;		u_long *lpkt;		int maclen;		/*		 * Usually we ignore authentication, but for debugging purposes		 * we watch it here.		 */		shouldbesize = CTL_HEADER_LEN + count;		/* round to 8 octet boundary */		shouldbesize = (shouldbesize + 7) & ~7;		if (n & 0x3) {			printf("Packet not padded, size = %d\n", n);		} if ((maclen = n - shouldbesize) >= MIN_MAC_LEN) {			printf(				"Packet shows signs of authentication (total %d, data %d, mac %d)\n",				n, shouldbesize, maclen);			lpkt = (u_long *)&rpkt;			printf("%08lx %08lx %08lx %08lx %08lx %08lx\n",			       (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_long) - 3]),			       (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_long) - 2]),			       (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_long) - 1]),			       (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_long)]),			       (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_long) + 1]),			       (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_long) + 2]));			key = ntohl(lpkt[(n - maclen) / sizeof(u_long)]);			printf("Authenticated with keyid %lu\n", (u_long)key);			if (key != 0 && key != info_auth_keyid) {				printf("We don't know that key\n");			} else {				if (authdecrypt(key, (u_int32 *)&rpkt,				    n - maclen, maclen)) {					printf("Auth okay!\n");				} else {					printf("Auth failed!\n");				}			}		}	}	if (debug >= 2)	    printf("Got packet, size = %d\n", n);	if (count > (u_short)(n-CTL_HEADER_LEN)) {		if (debug)		    printf(			    "Received count of %d octets, data in packet is %d\n",			    count, n-CTL_HEADER_LEN);		goto again;	}	if (count == 0 && CTL_ISMORE(rpkt.r_m_e_op)) {		if (debug)		    printf("Received count of 0 in non-final fragment\n");		goto again;	}	if (offset + count > sizeof(pktdata)) {		if (debug)		    printf("Offset %d, count %d, too big for buffer\n",			   offset, count);		return ERR_TOOMUCH;	}	if (seenlastfrag && !CTL_ISMORE(rpkt.r_m_e_op)) {		if (debug)		    printf("Received second last fragment packet\n");		goto again;	}	/*	 * So far, so good.  Record this fragment, making sure it doesn't	 * overlap anything.	 */	if (debug >= 2)	    printf("Packet okay\n");;	if (numfrags == MAXFRAGS) {		if (debug)		    printf("Number of fragments exceeds maximum\n");		return ERR_TOOMUCH;	}		for (n = 0; n < numfrags; n++) {		if (offset == offsets[n])		    goto again;	/* duplicate */		if (offset < offsets[n])		    break;	}		if ((u_short)(n > 0 && offsets[n-1] + counts[n-1]) > offset)	    goto overlap;	if (n < numfrags && (u_short)(offset + count) > offsets[n])	    goto overlap;		{		register int i;				for (i = numfrags; i > n; i--) {			offsets[i] = offsets[i-1];			counts[i] = counts[i-1];		}	}	offsets[n] = offset;	counts[n] = count;	numfrags++;	/*	 * Got that stuffed in right.  Figure out if this was the last.	 * Record status info out of the last packet.	 */	if (!CTL_ISMORE(rpkt.r_m_e_op)) {		seenlastfrag = 1;		if (rstatus != 0)		    *rstatus = ntohs(rpkt.status);	}	/*	 * Copy the data into the data buffer.	 */	memmove((char *)pktdata + offset, (char *)rpkt.data, count);	/*	 * If we've seen the last fragment, look for holes in the sequence.	 * If there aren't any, we're done.	 */	if (seenlastfrag && offsets[0] == 0) {		for (n = 1; n < numfrags; n++) {			if (offsets[n-1] + counts[n-1] != offsets[n])			    break;		}		if (n == numfrags) {			*rsize = offsets[numfrags-1] + counts[numfrags-1];			return 0;		}	}	goto again;    overlap:	/*	 * Print debugging message about overlapping fragments	 */	if (debug)	    printf("Overlapping fragments returned in response\n");	goto again;}/* * sendrequest - format and send a request packet */static intsendrequest(	int opcode,	int associd,	int auth,	int qsize,	char *qdata	){	struct ntp_control qpkt;	int pktsize;	/*	 * Check to make sure the data will fit in one packet	 */	if (qsize > CTL_MAX_DATA_LEN) {		(void) fprintf(stderr,			       "***Internal error!  qsize (%d) too large\n",			       qsize);		return 1;	}	/*	 * Fill in the packet	 */	qpkt.li_vn_mode = PKT_LI_VN_MODE(0, pktversion, MODE_CONTROL);	qpkt.r_m_e_op = (u_char)(opcode & CTL_OP_MASK);	qpkt.sequence = htons(sequence);	qpkt.status = 0;	qpkt.associd = htons((u_short)associd);	qpkt.offset = 0;	qpkt.count = htons((u_short)qsize);	/*	 * If we have data, copy it in and pad it out to a 64	 * bit boundary.	 */	if (qsize > 0) {		memmove((char *)qpkt.data, qdata, (unsigned)qsize);		pktsize = qsize + CTL_HEADER_LEN;		while (pktsize & (sizeof(u_long) - 1)) {			qpkt.data[qsize++] = 0;			pktsize++;		}	} else {		pktsize = CTL_HEADER_LEN;	}	/*	 * If it isn't authenticated we can just send it.  Otherwise	 * we're going to have to think about it a little.	 */	if (!auth && !always_auth) {		return sendpkt((char *)&qpkt, pktsize);	} else {		const char *pass = "\0";		int maclen = 0;		u_long my_keyid;		/*		 * Pad out packet to a multiple of 8 octets to be sure		 * receiver can handle it.		 */		while (pktsize & 7) {			qpkt.data[qsize++] = 0;			pktsize++;		}		/*		 * Get the keyid and the password if we don't have one.		 */		if (info_auth_keyid == 0) {			int u_keyid = getkeyid("Keyid: ");			if (u_keyid == 0 || u_keyid > NTP_MAXKEY) {				(void) fprintf(stderr,				   "Invalid key identifier\n");				return 1;			}			info_auth_keyid = u_keyid;		}		if (!authistrusted(info_auth_keyid)) {			pass = getpass("MD5 Password: ");			if (*pass == '\0') {				(void) fprintf(stderr,				  "Invalid password\n");				return (1);			}		}		authusekey(info_auth_keyid, info_auth_keytype, (const u_char *)pass);		authtrust(info_auth_keyid, 1);		/*		 * Stick the keyid in the packet where		 * cp currently points.  Cp should be aligned		 * properly.  Then do the encryptions.		 */		my_keyid = htonl(info_auth_keyid);		memcpy(&qpkt.data[qsize], &my_keyid, sizeof my_keyid);		maclen = authencrypt(info_auth_keyid, (u_int32 *)&qpkt,		    pktsize);		if (maclen == 0) {			(void) fprintf(stderr, "Key not found\n");			return (1);		}		return sendpkt((char *)&qpkt, pktsize + maclen);	}	/*NOTREACHED*/}/* * doquery - send a request and process the response */intdoquery(	int opcode,	int associd,	int auth,	int qsize,	char *qdata,	u_short *rstatus,	int *rsize,	char **rdata	){	int res;	int done;	/*	 * Check to make sure host is open

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -