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

📄 ntp_refclock.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 2 页
字号:
		peer->timereachable = current_time;	}	peer->reach |= 1;	peer->reftime = pp->lastref;	peer->org = pp->lastrec;	peer->rootdispersion = pp->disp;	get_systime(&peer->rec);	if (!refclock_sample(pp))		return;	clock_filter(peer, pp->offset, 0., pp->jitter);	record_peer_stats(&peer->srcadr, ctlpeerstatus(peer),	    peer->offset, peer->delay, clock_phi * (current_time -	    peer->epoch), peer->jitter);	if (cal_enable && last_offset < MINDISPERSE) {#ifdef KERNEL_PLL		if (peer != sys_peer || pll_status & STA_PPSTIME)#else		if (peer != sys_peer)#endif /* KERNEL_PLL */			pp->fudgetime1 -= pp->offset * FUDGEFAC;		else			pp->fudgetime1 -= pp->fudgetime1 * FUDGEFAC;	}}/* * refclock_gtlin - groom next input line and extract timestamp * * This routine processes the timecode received from the clock and * strips the parity bit and control characters. It returns the number * of characters in the line followed by a NULL character ('\0'), which * is not included in the count. In case of an empty line, the previous * line is preserved. */intrefclock_gtlin(	struct recvbuf *rbufp,	/* receive buffer pointer */	char	*lineptr,	/* current line pointer */	int	bmax,		/* remaining characters in line */	l_fp	*tsptr		/* pointer to timestamp returned */	){	char	s[BMAX];	char	*dpt, *dpend, *dp;	dpt = s;	dpend = s + refclock_gtraw(rbufp, s, BMAX - 1, tsptr);	if (dpend - dpt > bmax - 1)		dpend = dpt + bmax - 1;	for (dp = lineptr; dpt < dpend; dpt++) {		char	c;		c = *dpt & 0x7f;		if (c >= 0x20 && c < 0x7f)			*dp++ = c;	}	if (dp == lineptr)		return (0);	*dp = '\0';	return (dp - lineptr);}/* * refclock_gtraw - get next line/chunk of data * * This routine returns the raw data received from the clock in both * canonical or raw modes. The terminal interface routines map CR to LF. * In canonical mode this results in two lines, one containing data * followed by LF and another containing only LF. In raw mode the * interface routines can deliver arbitraty chunks of data from one * character to a maximum specified by the calling routine. In either * mode the routine returns the number of characters in the line * followed by a NULL character ('\0'), which is not included in the * count. * * If a timestamp is present in the timecode, as produced by the tty_clk * STREAMS module, it returns that as the timestamp; otherwise, it * returns the buffer timestamp. */intrefclock_gtraw(	struct recvbuf *rbufp,	/* receive buffer pointer */	char	*lineptr,	/* current line pointer */	int	bmax,		/* remaining characters in line */	l_fp	*tsptr		/* pointer to timestamp returned */	){	char	*dpt, *dpend, *dp;	l_fp	trtmp, tstmp;	int	i;	/*	 * Check for the presence of a timestamp left by the tty_clock	 * module and, if present, use that instead of the buffer	 * timestamp captured by the I/O routines. We recognize a	 * timestamp by noting its value is earlier than the buffer	 * timestamp, but not more than one second earlier.	 */	dpt = (char *)rbufp->recv_buffer;	dpend = dpt + rbufp->recv_length;	trtmp = rbufp->recv_time;	if (dpend >= dpt + 8) {		if (buftvtots(dpend - 8, &tstmp)) {			L_SUB(&trtmp, &tstmp);			if (trtmp.l_ui == 0) {#ifdef DEBUG				if (debug > 1) {					printf(					    "refclock_gtlin: fd %d ldisc %s",					    rbufp->fd, lfptoa(&trtmp,					    6));					get_systime(&trtmp);					L_SUB(&trtmp, &tstmp);					printf(" sigio %s\n",					    lfptoa(&trtmp, 6));				}#endif				dpend -= 8;				trtmp = tstmp;			} else				trtmp = rbufp->recv_time;		}	}	/*	 * Copy the raw buffer to the user string. The string is padded	 * with a NULL, which is not included in the character count.	 */	if (dpend - dpt > bmax - 1)		dpend = dpt + bmax - 1;	for (dp = lineptr; dpt < dpend; dpt++)		*dp++ = *dpt;	*dp = '\0';	i = dp - lineptr;#ifdef DEBUG	if (debug > 1)		printf("refclock_gtraw: fd %d time %s timecode %d %s\n",		    rbufp->fd, ulfptoa(&trtmp, 6), i, lineptr);#endif	*tsptr = trtmp;	return (i);}/* * The following code does not apply to WINNT & VMS ... */#if !defined SYS_VXWORKS && !defined SYS_WINNT#if defined(HAVE_TERMIOS) || defined(HAVE_SYSV_TTYS) || defined(HAVE_BSD_TTYS)/* * refclock_open - open serial port for reference clock * * This routine opens a serial port for I/O and sets default options. It * returns the file descriptor if success and zero if failure. */intrefclock_open(	char	*dev,		/* device name pointer */	u_int	speed,		/* serial port speed (code) */	u_int	lflags		/* line discipline flags */	){	int	fd;	int	omode;	/*	 * Open serial port and set default options	 */	omode = O_RDWR;#ifdef O_NONBLOCK	omode |= O_NONBLOCK;#endif#ifdef O_NOCTTY	omode |= O_NOCTTY;#endif	fd = open(dev, omode, 0777);	if (fd < 0) {		msyslog(LOG_ERR, "refclock_open %s: %m", dev);		return (0);	}	if (!refclock_setup(fd, speed, lflags)) {		close(fd);		return (0);	}	if (!refclock_ioctl(fd, lflags)) {		close(fd);		return (0);	}	return (fd);}/* * refclock_setup - initialize terminal interface structure */intrefclock_setup(	int	fd,		/* file descriptor */	u_int	speed,		/* serial port speed (code) */	u_int	lflags		/* line discipline flags */	){	int	i;	TTY	ttyb, *ttyp;#ifdef PPS	fdpps = fd;		/* ppsclock legacy */#endif /* PPS */	/*	 * By default, the serial line port is initialized in canonical	 * (line-oriented) mode at specified line speed, 8 bits and no	 * parity. LF ends the line and CR is mapped to LF. The break,	 * erase and kill functions are disabled. There is a different	 * section for each terminal interface, as selected at compile	 * time. The flag bits can be used to set raw mode and echo.	 */	ttyp = &ttyb;#ifdef HAVE_TERMIOS	/*	 * POSIX serial line parameters (termios interface)	 */	if (tcgetattr(fd, ttyp) < 0) {		msyslog(LOG_ERR,			"refclock_setup fd %d tcgetattr: %m", fd);		return (0);	}	/*	 * Set canonical mode and local connection; set specified speed,	 * 8 bits and no parity; map CR to NL; ignore break.	 */	if (speed) {		u_int	ltemp = 0;		ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL;		ttyp->c_oflag = 0;		ttyp->c_cflag = CS8 | CLOCAL | CREAD;		if (lflags & LDISC_7O1) {			/* HP Z3801A needs 7-bit, odd parity */  			ttyp->c_cflag = CS7 | PARENB | PARODD | CLOCAL | CREAD;		}		cfsetispeed(&ttyb, speed);		cfsetospeed(&ttyb, speed);		for (i = 0; i < NCCS; ++i)			ttyp->c_cc[i] = '\0';#if defined(TIOCMGET) && !defined(SCO5_CLOCK)		/*		 * If we have modem control, check to see if modem leads		 * are active; if so, set remote connection. This is		 * necessary for the kernel pps mods to work.		 */		if (ioctl(fd, TIOCMGET, (char *)&ltemp) < 0)			msyslog(LOG_ERR,			    "refclock_setup fd %d TIOCMGET: %m", fd);#ifdef DEBUG		if (debug)			printf("refclock_setup fd %d modem status: 0x%x\n",			    fd, ltemp);#endif		if (ltemp & TIOCM_DSR && lflags & LDISC_REMOTE)			ttyp->c_cflag &= ~CLOCAL;#endif /* TIOCMGET */	}	/*	 * Set raw and echo modes. These can be changed on-fly.	 */	ttyp->c_lflag = ICANON;	if (lflags & LDISC_RAW) {		ttyp->c_lflag = 0;		ttyp->c_cc[VMIN] = 1;	}	if (lflags & LDISC_ECHO)		ttyp->c_lflag |= ECHO;	if (tcsetattr(fd, TCSANOW, ttyp) < 0) {		msyslog(LOG_ERR,		    "refclock_setup fd %d TCSANOW: %m", fd);		return (0);	}#endif /* HAVE_TERMIOS */#ifdef HAVE_SYSV_TTYS	/*	 * System V serial line parameters (termio interface)	 *	 */	if (ioctl(fd, TCGETA, ttyp) < 0) {		msyslog(LOG_ERR,		    "refclock_setup fd %d TCGETA: %m", fd);		return (0);	}	/*	 * Set canonical mode and local connection; set specified speed,	 * 8 bits and no parity; map CR to NL; ignore break.	 */	if (speed) {		u_int	ltemp = 0;		ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL;		ttyp->c_oflag = 0;		ttyp->c_cflag = speed | CS8 | CLOCAL | CREAD;		for (i = 0; i < NCCS; ++i)			ttyp->c_cc[i] = '\0';#if defined(TIOCMGET) && !defined(SCO5_CLOCK)		/*		 * If we have modem control, check to see if modem leads		 * are active; if so, set remote connection. This is		 * necessary for the kernel pps mods to work.		 */		if (ioctl(fd, TIOCMGET, (char *)&ltemp) < 0)			msyslog(LOG_ERR,			    "refclock_setup fd %d TIOCMGET: %m", fd);#ifdef DEBUG		if (debug)			printf("refclock_setup fd %d modem status: %x\n",			    fd, ltemp);#endif		if (ltemp & TIOCM_DSR)			ttyp->c_cflag &= ~CLOCAL;#endif /* TIOCMGET */	}	/*	 * Set raw and echo modes. These can be changed on-fly.	 */	ttyp->c_lflag = ICANON;	if (lflags & LDISC_RAW) {		ttyp->c_lflag = 0;		ttyp->c_cc[VMIN] = 1;	}	if (ioctl(fd, TCSETA, ttyp) < 0) {		msyslog(LOG_ERR,		    "refclock_setup fd %d TCSETA: %m", fd);		return (0);	}#endif /* HAVE_SYSV_TTYS */#ifdef HAVE_BSD_TTYS	/*	 * 4.3bsd serial line parameters (sgttyb interface)	 */	if (ioctl(fd, TIOCGETP, (char *)ttyp) < 0) {		msyslog(LOG_ERR,		    "refclock_setup fd %d TIOCGETP: %m", fd);		return (0);	}	if (speed)		ttyp->sg_ispeed = ttyp->sg_ospeed = speed;	ttyp->sg_flags = EVENP | ODDP | CRMOD;	if (ioctl(fd, TIOCSETP, (char *)ttyp) < 0) {		msyslog(LOG_ERR,		    "refclock_setup TIOCSETP: %m");		return (0);	}#endif /* HAVE_BSD_TTYS */	return(1);}#endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS */#endif /* SYS_VXWORKS SYS_WINNT *//* * refclock_ioctl - set serial port control functions * * This routine attempts to hide the internal, system-specific details * of serial ports. It can handle POSIX (termios), SYSV (termio) and BSD * (sgtty) interfaces with varying degrees of success. The routine sets * up optional features such as tty_clk. The routine returns 1 if * success and 0 if failure. */intrefclock_ioctl(	int	fd, 		/* file descriptor */	u_int	lflags		/* line discipline flags */	){	/*	 * simply return 1 if no UNIX line discipline is supported	 */#if !defined SYS_VXWORKS && !defined SYS_WINNT#if defined(HAVE_TERMIOS) || defined(HAVE_SYSV_TTYS) || defined(HAVE_BSD_TTYS)#ifdef DEBUG	if (debug)		printf("refclock_ioctl: fd %d flags 0x%x\n", fd,		    lflags);#endif#ifdef TTYCLK	/*	 * The TTYCLK option provides timestamping at the driver level.	 * It requires the tty_clk streams module and System V STREAMS	 * support. If not available, don't complain.	 */	if (lflags & (LDISC_CLK | LDISC_CLKPPS | LDISC_ACTS)) {		int rval = 0;		if (ioctl(fd, I_PUSH, "clk") < 0) {			msyslog(LOG_NOTICE,			    "refclock_ioctl fd %d I_PUSH: %m", fd);			return (0);#ifdef CLK_SETSTR		} else {			char *str;			if (lflags & LDISC_CLKPPS)				str = "\377";			else if (lflags & LDISC_ACTS)				str = "*";			else				str = "\n";			if (ioctl(fd, CLK_SETSTR, str) < 0) {				msyslog(LOG_ERR,				    "refclock_ioctl fd %d CLK_SETSTR: %m", fd);				return (0);			}#endif /*CLK_SETSTR */		}	}#endif /* TTYCLK */#endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS */#endif /* SYS_VXWORKS SYS_WINNT */	return (1);}/* * refclock_control - set and/or return clock values * * This routine is used mainly for debugging. It returns designated * values from the interface structure that can be displayed using * ntpdc and the clockstat command. It can also be used to initialize * configuration variables, such as fudgetimes, fudgevalues, reference * ID and stratum. */voidrefclock_control(	struct sockaddr_storage *srcadr,	struct refclockstat *in,	struct refclockstat *out	){	struct peer *peer;	struct refclockproc *pp;	u_char clktype;	int unit;	/*	 * Check for valid address and running peer	 */	if (srcadr->ss_family != AF_INET)		return;	if (!ISREFCLOCKADR(srcadr))		return;	clktype = (u_char)REFCLOCKTYPE(srcadr);	unit = REFCLOCKUNIT(srcadr);	if (clktype >= num_refclock_conf || unit >= MAXUNIT)		return;	peer = typeunit[clktype][unit];	if (peer == NULL)		return;	if (peer->procptr == NULL)		return;	pp = peer->procptr;	/*	 * Initialize requested data	 */	if (in != 0) {		if (in->haveflags & CLK_HAVETIME1)			pp->fudgetime1 = in->fudgetime1;		if (in->haveflags & CLK_HAVETIME2)			pp->fudgetime2 = in->fudgetime2;		if (in->haveflags & CLK_HAVEVAL1)			peer->stratum = pp->stratum = (u_char)in->fudgeval1;		if (in->haveflags & CLK_HAVEVAL2)			peer->refid = pp->refid = in->fudgeval2;		if (in->haveflags & CLK_HAVEFLAG1) {			pp->sloppyclockflag &= ~CLK_FLAG1;			pp->sloppyclockflag |= in->flags & CLK_FLAG1;		}		if (in->haveflags & CLK_HAVEFLAG2) {			pp->sloppyclockflag &= ~CLK_FLAG2;			pp->sloppyclockflag |= in->flags & CLK_FLAG2;		}		if (in->haveflags & CLK_HAVEFLAG3) {			pp->sloppyclockflag &= ~CLK_FLAG3;			pp->sloppyclockflag |= in->flags & CLK_FLAG3;		}		if (in->haveflags & CLK_HAVEFLAG4) {			pp->sloppyclockflag &= ~CLK_FLAG4;			pp->sloppyclockflag |= in->flags & CLK_FLAG4;		}	}	/*	 * Readback requested data	 */	if (out != 0) {		out->haveflags = CLK_HAVETIME1 | CLK_HAVEVAL1 |			CLK_HAVEVAL2 | CLK_HAVEFLAG4;		out->fudgetime1 = pp->fudgetime1;		out->fudgetime2 = pp->fudgetime2;		out->fudgeval1 = pp->stratum;		out->fudgeval2 = pp->refid;		out->flags = (u_char) pp->sloppyclockflag;		out->timereset = current_time - pp->timestarted;		out->polls = pp->polls;		out->noresponse = pp->noreply;		out->badformat = pp->badformat;		out->baddata = pp->baddata;		out->lastevent = pp->lastevent;		out->currentstatus = pp->currentstatus;		out->type = pp->type;		out->clockdesc = pp->clockdesc;		out->lencode = pp->lencode;		out->p_lastcode = pp->a_lastcode;	}	/*	 * Give the stuff to the clock	 */	if (refclock_conf[clktype]->clock_control != noentry)		(refclock_conf[clktype]->clock_control)(unit, in, out, peer);}/* * refclock_buginfo - return debugging info * * This routine is used mainly for debugging. It returns designated * values from the interface structure that can be displayed using * ntpdc and the clkbug command. */voidrefclock_buginfo(	struct sockaddr_storage *srcadr, /* clock address */	struct refclockbug *bug /* output structure */	){	struct peer *peer;	struct refclockproc *pp;	u_char clktype;	int unit;	int i;	/*	 * Check for valid address and peer structure	 */	if (srcadr->ss_family != AF_INET)		return;	if (!ISREFCLOCKADR(srcadr))		return;	clktype = (u_char) REFCLOCKTYPE(srcadr);	unit = REFCLOCKUNIT(srcadr);	if (clktype >= num_refclock_conf || unit >= MAXUNIT)		return;	peer = typeunit[clktype][unit];	if (peer == NULL)		return;	pp = peer->procptr;	/*	 * Copy structure values	 */	bug->nvalues = 8;	bug->svalues = 0x0000003f;	bug->values[0] = pp->year;	bug->values[1] = pp->day;	bug->values[2] = pp->hour;	bug->values[3] = pp->minute;	bug->values[4] = pp->second;	bug->values[5] = pp->nsec;	bug->values[6] = pp->yearstart;	bug->values[7] = pp->coderecv;	bug->stimes = 0xfffffffc;	bug->times[0] = pp->lastref;	bug->times[1] = pp->lastrec;	for (i = 2; i < (int)bug->ntimes; i++)		DTOLFP(pp->filter[i - 2], &bug->times[i]);	/*	 * Give the stuff to the clock	 */	if (refclock_conf[clktype]->clock_buginfo != noentry)		(refclock_conf[clktype]->clock_buginfo)(unit, bug, peer);}#endif /* REFCLOCK */

⌨️ 快捷键说明

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