📄 ntp_io.c
字号:
return (rb->recv_length); }#ifdef DEBUG if (debug > 2) { if(rb->recv_srcadr.ss_family == AF_INET) printf("input_handler: fd=%d length %d from %08lx %s\n", fd, rb->recv_length, (u_long)ntohl(((struct sockaddr_in*)&rb->recv_srcadr)->sin_addr.s_addr) & 0x00000000ffffffff, stoa(&rb->recv_srcadr)); else printf("input_handler: fd=%d length %d from %s\n", fd, rb->recv_length, stoa(&rb->recv_srcadr)); }#endif /* * Got one. Mark how and when it got here, * put it on the full list and do bookkeeping. */ rb->dstadr = itf; rb->fd = fd; rb->recv_time = ts; rb->receiver = receive; add_full_recv_buffer(rb); itf->received++; packets_received++; return (rb->recv_length);}/* * input_handler - receive packets asynchronously */voidinput_handler( l_fp *cts ){ int buflen; register int i, n; register int doing; register SOCKET fd; struct timeval tvzero; l_fp ts; /* Timestamp at BOselect() gob */#ifdef DEBUG l_fp ts_e; /* Timestamp at EOselect() gob */#endif fd_set fds; int select_count = 0; handler_calls++; /* * If we have something to do, freeze a timestamp. * See below for the other cases (nothing (left) to do or error) */ ts = *cts; /* * Do a poll to see who has data */ fds = activefds; tvzero.tv_sec = tvzero.tv_usec = 0;#ifdef REFCLOCK /* * Check out the reference clocks first, if any */ n = select(maxactivefd+1, &fds, (fd_set *)0, (fd_set *)0, &tvzero); /* * If there are no packets waiting just return */ if (n < 0) { int err = errno; /* * extended FAU debugging output */ if (err != EINTR) netsyslog(LOG_ERR, "select(%d, %s, 0L, 0L, &0.0) error: %m", maxactivefd+1, fdbits(maxactivefd, &activefds)); if (err == EBADF) { int j, b; fds = activefds; for (j = 0; j <= maxactivefd; j++) if ((FD_ISSET(j, &fds) && (read(j, &b, 0) == -1))) netsyslog(LOG_ERR, "Bad file descriptor %d", j); } return; } else if (n == 0) return; ++handler_pkts; if (refio != 0) { register struct refclockio *rp; for (rp = refio; rp != 0; rp = rp->next) { fd = rp->fd; if (FD_ISSET(fd, &fds)) { do { ++select_count; buflen = read_refclock_packet(fd, rp, ts); } while (buflen > 0); } /* End if (FD_ISSET(fd, &fds)) */ } /* End for (rp = refio; rp != 0 && n > 0; rp = rp->next) */ } /* End if (refio != 0) */#endif /* REFCLOCK */ /* * Loop through the interfaces looking for data to read. */ for (i = ninterfaces - 1; (i >= 0) ; i--) { for (doing = 0; (doing < 2); doing++) { if (doing == 0) { fd = inter_list[i].fd; } else { if (!(inter_list[i].flags & INT_BCASTOPEN)) break; fd = inter_list[i].bfd; } if (fd < 0) continue; if (FD_ISSET(fd, &fds)) { do { ++select_count; buflen = read_network_packet(fd, &inter_list[i], ts); } while (buflen > 0); } /* Check more interfaces */ } } /* * Done everything from that select. */ /* * If nothing to do, just return. * If an error occurred, complain and return. */ if (select_count == 0) /* We really had nothing to do */ {#ifdef DEBUG if (debug) netsyslog(LOG_DEBUG, "input_handler: select() returned 0");#endif return; } /* We've done our work */#ifdef DEBUG get_systime(&ts_e); /* * (ts_e - ts) is the amount of time we spent * processing this gob of file descriptors. Log * it. */ L_SUB(&ts_e, &ts); if (debug > 3) netsyslog(LOG_INFO, "input_handler: Processed a gob of fd's in %s msec", lfptoms(&ts_e, 6));#endif /* just bail. */ return;}#endif/* * findinterface - find local interface corresponding to address */struct interface *findinterface( struct sockaddr_storage *addr ){ int retind; retind = findlocalinterface(addr);#ifdef DEBUG if (debug > 1) printf("Found interface index %d for address %s\n", retind, stoa(addr));#endif if (retind < 0) { return (ANY_INTERFACE_CHOOSE(addr)); } else { return (&inter_list[retind]); }}/* * findlocalinterface - find local interface index corresponding to address */intfindlocalinterface( struct sockaddr_storage *addr ){ SOCKET s; int rtn, i, idx; struct sockaddr_storage saddr; int saddrlen = SOCKLEN(addr);#ifdef DEBUG if (debug>2) printf("Finding interface for addr %s in list of addresses\n", stoa(addr));#endif /* * This is considerably hoke. We open a socket, connect to it * and slap a getsockname() on it. If anything breaks, as it * probably will in some j-random knockoff, we just return the * wildcard interface. */ memset(&saddr, 0, sizeof(saddr)); saddr.ss_family = addr->ss_family; if(addr->ss_family == AF_INET) { memcpy(&((struct sockaddr_in*)&saddr)->sin_addr, &((struct sockaddr_in*)addr)->sin_addr, sizeof(struct in_addr)); ((struct sockaddr_in*)&saddr)->sin_port = htons(2000); }#ifdef INCLUDE_IPV6_SUPPORT else if(addr->ss_family == AF_INET6) { memcpy(&((struct sockaddr_in6*)&saddr)->sin6_addr, &((struct sockaddr_in6*)addr)->sin6_addr, sizeof(struct in6_addr)); ((struct sockaddr_in6*)&saddr)->sin6_port = htons(2000);# ifdef ISC_PLATFORM_HAVESCOPEID ((struct sockaddr_in6*)&saddr)->sin6_scope_id = ((struct sockaddr_in6*)addr)->sin6_scope_id;# endif }#endif s = socket(addr->ss_family, SOCK_DGRAM, 0); if (s == INVALID_SOCKET) return (-1); rtn = connect(s, (struct sockaddr *)&saddr, SOCKLEN(&saddr));#ifndef SYS_WINNT if (rtn < 0)#else if (rtn == SOCKET_ERROR)#endif { closesocket(s); return (-1); } rtn = getsockname(s, (struct sockaddr *)&saddr, &saddrlen); closesocket(s);#ifndef SYS_WINNT if (rtn < 0)#else if (rtn == SOCKET_ERROR)#endif return (-1); idx = -1; for (i = nwilds; i < ninterfaces; i++) { /* Don't both with ignore interfaces */ if (inter_list[i].ignore_packets == ISC_TRUE) continue; /* * First look if is the the correct family */ if(inter_list[i].sin.ss_family != saddr.ss_family) continue; /* * We match the unicast address only. */ if (SOCKCMP(&inter_list[i].sin, &saddr)) { idx = i; break; } } if (idx != -1) { return (idx); } return (-1);}/* * findlocalcastinterface - find local *cast interface index corresponding to address * depending on the flags passed */intfindlocalcastinterface( struct sockaddr_storage *addr, int flags ){ int i; int nif = -1;#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT isc_boolean_t want_linklocal = ISC_FALSE; if (addr_ismulticast(addr) && flags == INT_MULTICAST) { if (IN6_IS_ADDR_MC_LINKLOCAL(&((struct sockaddr_in6*)addr)->sin6_addr)) { want_linklocal = ISC_TRUE; } else if (IN6_IS_ADDR_MC_SITELOCAL(&((struct sockaddr_in6*)addr)->sin6_addr)) { want_linklocal = ISC_TRUE; } }#endif for (i = nwilds; i < ninterfaces; i++) { /* use only allowed addresses */ if (inter_list[i].ignore_packets == ISC_TRUE) continue; /* Skip the loopback addresses */ if (inter_list[i].flags & INT_LOOPBACK) continue; /* Skip if different family */ if(inter_list[i].sin.ss_family != addr->ss_family) continue; /* Is this it one of these based on flags? */ if (!(inter_list[i].flags & flags)) continue; /* for IPv6 multicast check the address for linklocal */#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT if (flags == INT_MULTICAST && inter_list[i].sin.ss_family == AF_INET6 && (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6*)&inter_list[i].sin)->sin6_addr)) && want_linklocal == ISC_TRUE) { nif = i; break; } /* If we want a linklocal address and this isn't it, skip */\ if (want_linklocal == ISC_TRUE) continue;#endif /* Otherwise just look for the flag */ if((inter_list[i].flags & flags)) { nif = i; break; } }#ifdef DEBUG if (debug > 1) printf("findlocalcastinterface: found index = %d\n", nif);#endif return (nif);}/* * findbcastinter - find broadcast interface corresponding to address */struct interface *findbcastinter( struct sockaddr_storage *addr ){#if !defined(MPE) && (defined(SIOCGIFCONF) || defined(SYS_WINNT)) int i = -1; #ifdef DEBUG if (debug>2) printf("Finding broadcast interface for addr %s in list of addresses\n", stoa(addr));#endif i = find_flagged_addr_in_list(addr, INT_BCASTOPEN|INT_MCASTOPEN);#ifdef DEBUG if (debug > 1) printf("Found bcastinter index %d\n", i);#endif /* * Do nothing right now * Eventually we will find the interface this * way, but until it works properly we just see * which one we got *//* if(i >= 0) { return (&inter_list[i]); }*/ for (i = nwilds; i < ninterfaces; i++) { /* Don't bother with ignored interfaces */ if (inter_list[i].ignore_packets == ISC_TRUE) continue; /* * First look if this is the correct family */ if(inter_list[i].sin.ss_family != addr->ss_family) continue; /* Skip the loopback addresses */ if (inter_list[i].flags & INT_LOOPBACK) continue; /* for IPv6 multicast check the address for linklocal */#ifdef INCLUDE_IPV6_SUPPORT if (inter_list[i].sin.ss_family == AF_INET6 && (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6*)&inter_list[i].sin)->sin6_addr))) {/* continue; */ }#endif /* * If we are looking to match a multicast address grab it. * We must not do this before we have eliminated any linklocal * addresses */ if (addr_ismulticast(addr) == ISC_TRUE && inter_list[i].flags & INT_MULTICAST) { return (&inter_list[i]); } /* * We match only those interfaces marked as * broadcastable and either the explicit broadcast * address or the network portion of the IP address. * Sloppy. */ if(addr->ss_family == AF_INET) { if (SOCKCMP(&inter_list[i].bcast, addr)) return (&inter_list[i]); if ((NSRCADR(&inter_list[i].sin) & NSRCADR(&inter_list[i].mask)) == (NSRCADR(addr) & NSRCADR(&inter_list[i].mask))) return (&inter_list[i]); }#ifdef INCLUDE_IPV6_SUPPORT else if(addr->ss_family == AF_INET6) { if (SOCKCMP(&inter_list[i].bcast, addr)) return (&inter_list[i]); if (SOCKCMP(netof(&inter_list[i].sin), netof(addr))) return (&inter_list[i]); }#endif }#endif /* SIOCGIFCONF */ return ANY_INTERFACE_CHOOSE(addr);}/* * io_clr_stats - clear I/O module statistics */voidio_clr_stats(void){ packets_dropped = 0; packets_ignored = 0; packets_received = 0; packets_sent = 0; packets_notsent = 0; handler_calls = 0; handler_pkts = 0; io_timereset = current_time;}#ifdef REFCLOCK/* * This is a hack so that I don't have to fool with these ioctls in the * pps driver ... we are already non-blocking and turn on SIGIO thru * another mechanisim */intio_addclock_simple( struct refclockio *rio ){ BLOCKIO(); /* * Stuff the I/O structure in the list and mark the descriptor * in use. There is a harmless (I hope) race condition here. */ rio->next = refio; refio = rio; /* * I/O Completion Ports don't care about select and fd_set */#ifndef HAVE_IO_COMPLETION_PORT if (rio->fd > maxactivefd) maxactivefd = rio->fd; FD_SET(rio->fd, &activefds);#endif UNBLOCKIO(); return 1;}/* * io_addclock - add a reference clock to the list and arrange that we * get SIGIO interrupts from it. */intio_addclock( struc
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -