📄 ntp_io.c
字号:
stoa(addr)); exit(1); /*NOTREACHED*/ }#elif defined(FNDELAY) if (fcntl(fd, F_SETFL, FNDELAY) < 0) { netsyslog(LOG_ERR, "fcntl(FNDELAY) fails on address %s: %m", stoa(addr)); exit(1); /*NOTREACHED*/ }#elif defined(O_NDELAY) /* generally the same as FNDELAY */ if (fcntl(fd, F_SETFL, O_NDELAY) < 0) { netsyslog(LOG_ERR, "fcntl(O_NDELAY) fails on address %s: %m", stoa(addr)); exit(1); /*NOTREACHED*/ }#elif defined(FIONBIO)# if defined(SYS_WINNT) if (ioctlsocket(fd,FIONBIO,(u_long *) &on) == SOCKET_ERROR)# else if (ioctl(fd,FIONBIO,&on) < 0)# endif { netsyslog(LOG_ERR, "ioctl(FIONBIO) fails on address %s: %m", stoa(addr)); exit(1); /*NOTREACHED*/ }#elif defined(FIOSNBIO) if (ioctl(fd,FIOSNBIO,&on) < 0) { netsyslog(LOG_ERR, "ioctl(FIOSNBIO) fails on address %s: %m", stoa(addr)); exit(1); /*NOTREACHED*/ }#else# include "Bletch: Need non-blocking I/O!"#endif#ifdef HAVE_SIGNALED_IO init_socket_sig(fd);#endif /* not HAVE_SIGNALED_IO */ /* * Turn off the SO_REUSEADDR socket option. It apparently * causes heartburn on systems with multicast IP installed. * On normal systems it only gets looked at when the address * is being bound anyway.. */ if (turn_off_reuse) if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&off, sizeof(off))) { netsyslog(LOG_ERR, "setsockopt SO_REUSEADDR off fails on address %s: %m", stoa(addr)); }#if !defined(SYS_WINNT) && !defined(VMS)# ifdef DEBUG if (debug > 1) printf("flags for fd %d: 0%o\n", fd, fcntl(fd, F_GETFL, 0));# endif#endif /* SYS_WINNT || VMS */#if defined (HAVE_IO_COMPLETION_PORT)/* * Add the socket to the completion port */ io_completion_port_add_socket(fd, interf);#endif return fd;}/* * close_socket - close a socket and remove from the activefd list */static voidclose_socket( SOCKET fd ){ SOCKET i, newmax; if (fd < 0) return; (void) closesocket(fd); /* * I/O Completion Ports don't care about select and fd_set */#ifndef HAVE_IO_COMPLETION_PORT FD_CLR( (u_int) fd, &activefds); if (fd == maxactivefd) { newmax = 0; for (i = 0; i < maxactivefd; i++) if (FD_ISSET(i, &activefds)) newmax = i; maxactivefd = newmax; }#endif delete_socket_from_list(fd);}/* * close_file - close a file and remove from the activefd list * added 1/31/1997 Greg Schueman for Windows NT portability */#ifdef REFCLOCKstatic voidclose_file( SOCKET fd ){ int i, newmax; if (fd < 0) return; (void) close(fd);#ifndef HAVE_IO_COMPLETION_PORT /* * I/O Completion Ports don't care about select and fd_set */ FD_CLR( (u_int) fd, &activefds); if (fd == maxactivefd) { newmax = 0; for (i = 0; i < maxactivefd; i++) if (FD_ISSET(i, &activefds)) newmax = i; maxactivefd = newmax; }#endif delete_socket_from_list(fd);}#endif/* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c *//* * sendpkt - send a packet to the specified destination. Maintain a * send error cache so that only the first consecutive error for a * destination is logged. */voidsendpkt( struct sockaddr_storage *dest, struct interface *inter, int ttl, struct pkt *pkt, int len ){ int cc, slot;#ifdef SYS_WINNT DWORD err;#endif /* SYS_WINNT */ /* * Send error caches. Empty slots have port == 0 * Set ERRORCACHESIZE to 0 to disable */ struct cache { u_short port; struct in_addr addr; };#ifdef INCLUDE_IPV6_SUPPORT struct cache6 { u_short port; struct in6_addr addr; };#endif /* INCLUDE_IPV6_SUPPORT */#ifndef ERRORCACHESIZE#define ERRORCACHESIZE 8#endif#if ERRORCACHESIZE > 0 static struct cache badaddrs[ERRORCACHESIZE];#ifdef INCLUDE_IPV6_SUPPORT static struct cache6 badaddrs6[ERRORCACHESIZE];#endif /* INCLUDE_IPV6_SUPPORT */#else#define badaddrs ((struct cache *)0) /* Only used in empty loops! */#ifdef INCLUDE_IPV6_SUPPORT#define badaddrs6 ((struct cache6 *)0) /* Only used in empty loops! */#endif /* INCLUDE_IPV6_SUPPORT */#endif#ifdef DEBUG if (debug > 1) printf("%ssendpkt(fd=%d dst=%s, src=%s, ttl=%d, len=%d)\n", (ttl > 0) ? "\tMCAST\t*****" : "", inter->fd, stoa(dest), stoa(&inter->sin), ttl, len);#endif#ifdef MCAST switch (inter->sin.ss_family) { case AF_INET : /* * for the moment we use the bcast option to set multicast ttl */ if (ttl > 0 && ttl != inter->last_ttl) { /* * set the multicast ttl for outgoing packets */ u_char mttl = (u_char) ttl; if (setsockopt(inter->fd, IPPROTO_IP, IP_MULTICAST_TTL, (const void *) &mttl, sizeof(mttl)) != 0) { netsyslog(LOG_ERR, "setsockopt IP_MULTICAST_TTL fails on address %s: %m", stoa(&inter->sin)); } else inter->last_ttl = ttl; } break;#ifdef INCLUDE_IPV6_SUPPORT case AF_INET6 : /* * for the moment we use the bcast option to set * multicast max hops */ if (ttl > 0 && ttl != inter->last_ttl) { /* * set the multicast ttl for outgoing packets */ u_int ittl = (u_int) ttl; if (setsockopt(inter->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (const void *) &ittl, sizeof(ittl)) == -1) netsyslog(LOG_ERR, "setsockopt IP_MULTICAST_TTL fails on address %s: %m", stoa(&inter->sin)); else inter->last_ttl = ttl; } break;#endif /* INCLUDE_IPV6_SUPPORT */ default : exit(1); }#endif /* MCAST */ for (slot = ERRORCACHESIZE; --slot >= 0; ) if(dest->ss_family == AF_INET) { if (badaddrs[slot].port == ((struct sockaddr_in*)dest)->sin_port && badaddrs[slot].addr.s_addr == ((struct sockaddr_in*)dest)->sin_addr.s_addr) break; }#ifdef INCLUDE_IPV6_SUPPORT else if (dest->ss_family == AF_INET6) { if (badaddrs6[slot].port == ((struct sockaddr_in6*)dest)->sin6_port && badaddrs6[slot].addr.s6_addr == ((struct sockaddr_in6*)dest)->sin6_addr.s6_addr) break; }#endif /* INCLUDE_IPV6_SUPPORT */ else exit(1); /* address family not supported yet */#if defined(HAVE_IO_COMPLETION_PORT) err = io_completion_port_sendto(inter, pkt, len, dest); if (err != ERROR_SUCCESS)#else#ifdef SIM cc = srvr_rply(&ntp_node, dest, inter, pkt);#else /* SIM */ cc = sendto(inter->fd, (char *)pkt, (unsigned int)len, 0, (struct sockaddr *)dest, SOCKLEN(dest));#endif /* SIM */ if (cc == -1)#endif { inter->notsent++; packets_notsent++;#if defined(HAVE_IO_COMPLETION_PORT) err = WSAGetLastError(); if (err != WSAEWOULDBLOCK && err != WSAENOBUFS && slot < 0)#else if (errno != EWOULDBLOCK && errno != ENOBUFS && slot < 0)#endif { /* * Remember this, if there's an empty slot */ switch (dest->ss_family) { case AF_INET : for (slot = ERRORCACHESIZE; --slot >= 0; ) if (badaddrs[slot].port == 0) { badaddrs[slot].port = SRCPORT(dest); badaddrs[slot].addr = ((struct sockaddr_in*)dest)->sin_addr; break; } break;#ifdef INCLUDE_IPV6_SUPPORT case AF_INET6 : for (slot = ERRORCACHESIZE; --slot >= 0; ) if (badaddrs6[slot].port == 0) { badaddrs6[slot].port = SRCPORT(dest); badaddrs6[slot].addr = ((struct sockaddr_in6*)dest)->sin6_addr; break; } break;#endif /* INCLUDE_IPV6_SUPPORT */ default : exit(1); } netsyslog(LOG_ERR, "sendto(%s) (fd=%d): %m", stoa(dest), inter->fd); } } else { inter->sent++; packets_sent++; /* * He's not bad any more */ if (slot >= 0) { netsyslog(LOG_INFO, "Connection re-established to %s", stoa(dest)); switch (dest->ss_family) { case AF_INET : badaddrs[slot].port = 0; break;#ifdef INCLUDE_IPV6_SUPPORT case AF_INET6 : badaddrs6[slot].port = 0; break;#endif /* INCLUDE_IPV6_SUPPORT */ } } }}#if !defined(HAVE_IO_COMPLETION_PORT)/* * fdbits - generate ascii representation of fd_set (FAU debug support) * HFDF format - highest fd first. */static char *fdbits( int count, fd_set *set ){ static char buffer[256]; char * buf = buffer; count = (count < 256) ? count : 255; while (count >= 0) { *buf++ = FD_ISSET(count, set) ? '#' : '-'; count--; } *buf = '\0'; return buffer;}/* * Routine to read the refclock packets for a specific interface * Return the number of bytes read. That way we know if we should * read it again or go on to the next one if no bytes returned */static inline intread_refclock_packet(SOCKET fd, struct refclockio *rp, l_fp ts){ int i; int buflen; register struct recvbuf *rb; if (free_recvbuffs() == 0) { char buf[RX_BUFF_SIZE]; buflen = read(fd, buf, sizeof buf); packets_dropped++; return (buflen); /* Return what we found */ } rb = get_free_recv_buffer(); i = (rp->datalen == 0 || rp->datalen > sizeof(rb->recv_space)) ? sizeof(rb->recv_space) : rp->datalen; buflen = read(fd, (char *)&rb->recv_space, (unsigned)i); if (buflen < 0) { if (errno != EINTR && errno != EAGAIN) { netsyslog(LOG_ERR, "clock read fd %d: %m", fd); } freerecvbuf(rb); return (0); } /* * Got one. Mark how and when it got here, * put it on the full list and do bookkeeping. */ rb->recv_length = buflen; rb->recv_srcclock = rp->srcclock; rb->dstadr = 0; rb->fd = fd; rb->recv_time = ts; rb->receiver = rp->clock_recv; if (rp->io_input) { /* * have direct input routine for refclocks */ if (rp->io_input(rb) == 0) { /* * data was consumed - nothing to pass up * into block input machine */ freerecvbuf(rb); return (buflen); } } add_full_recv_buffer(rb); rp->recvcount++; packets_received++; return (buflen);}/* * Routine to read the network NTP packets for a specific interface * Return the number of bytes read. That way we know if we should * read it again or go on to the next one if no bytes returned */static inline intread_network_packet(SOCKET fd, struct interface *itf, l_fp ts){ int fromlen; int buflen; register struct recvbuf *rb; /* * Get a buffer and read the frame. If we * haven't got a buffer, or this is received * on a disallowed socket, just dump the * packet. */ if (free_recvbuffs() == 0 || itf->ignore_packets == ISC_TRUE) { char buf[RX_BUFF_SIZE]; struct sockaddr_storage from; fromlen = sizeof from; buflen = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr*)&from, &fromlen);#ifdef DEBUG if (debug > 3) printf("%s on (%lu) fd=%d from %s\n", (itf->ignore_packets == ISC_TRUE) ? "ignore" : "drop", free_recvbuffs(), fd, stoa(&from));#endif if (itf->ignore_packets == ISC_TRUE) packets_ignored++; else packets_dropped++; return (buflen); } rb = get_free_recv_buffer(); fromlen = sizeof(struct sockaddr_storage); rb->recv_length = recvfrom(fd, (char *)&rb->recv_space, sizeof(rb->recv_space), 0, (struct sockaddr *)&rb->recv_srcadr, &fromlen); if (rb->recv_length == 0|| (rb->recv_length == -1 && (errno==EWOULDBLOCK#ifdef EAGAIN || errno==EAGAIN#endif ))) { freerecvbuf(rb); return (rb->recv_length); } else if (rb->recv_length < 0) { netsyslog(LOG_ERR, "recvfrom(%s) fd=%d: %m", stoa(&rb->recv_srcadr), fd);#ifdef DEBUG if (debug) printf("input_handler: fd=%d dropped (bad recvfrom)\n", fd);#endif freerecvbuf(rb);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -