📄 ntp_io.c
字号:
sizeof(struct in6_addr)); ((struct sockaddr_in6 *)&itf->sin)->sin6_port = port;#ifdef ISC_PLATFORM_HAVESCOPEID ((struct sockaddr_in6 *)&itf->sin)->sin6_scope_id = isc_netaddr_getzone(&isc_if->address); itf->scopeid = isc_netaddr_getzone(&isc_if->address);#endif itf->mask.ss_family = itf->sin.ss_family; memcpy(&(((struct sockaddr_in6 *)&itf->mask)->sin6_addr), &(isc_if->netmask.type.in6), sizeof(struct in6_addr)); ((struct sockaddr_in6 *)&itf->mask)->sin6_port = port; if (((isc_if->flags & INTERFACE_F_LOOPBACK) != 0) && (loopback6_interface == NULL)) { loopback6_interface = itf; } /* Copy the scopeid and the interface index */ itf->ifindex = isc_if->ifindex; }#endif /* INCLUDE_IPV6_SUPPORT */ /* Process the rest of the flags */ if((isc_if->flags & INTERFACE_F_UP) != 0) itf->flags |= INT_UP; if((isc_if->flags & INTERFACE_F_LOOPBACK) != 0) itf->flags |= INT_LOOPBACK; if((isc_if->flags & INTERFACE_F_POINTTOPOINT) != 0) itf->flags |= INT_PPP; if((isc_if->flags & INTERFACE_F_MULTICAST) != 0) itf->flags |= INT_MULTICAST;}/* * create_sockets - create a socket for each interface plus a default * socket for when we don't know where to send */static intcreate_sockets( u_short port ){ struct sockaddr_storage resmask; int i; isc_mem_t *mctx = NULL; isc_interfaceiter_t *iter = NULL; isc_boolean_t scan_ipv4 = ISC_FALSE; isc_boolean_t scan_ipv6 = ISC_FALSE; isc_result_t result; int idx = 0;#ifndef HAVE_IO_COMPLETION_PORT /* * I/O Completion Ports don't care about the select and FD_SET */ maxactivefd = 0; FD_ZERO(&activefds);#endif#ifdef DEBUG if (debug) printf("create_sockets(%d)\n", ntohs( (u_short) port));#endif#ifdef INCLUDE_IPV6_SUPPORT if (isc_net_probeipv6() == ISC_R_SUCCESS) scan_ipv6 = ISC_TRUE;#if defined(DEBUG) else if(debug) netsyslog(LOG_ERR, "no IPv6 interfaces found");#endif#endif if (isc_net_probeipv4() == ISC_R_SUCCESS) scan_ipv4 = ISC_TRUE;#ifdef DEBUG else if(debug) netsyslog(LOG_ERR, "no IPv4 interfaces found");#endif /* * Create wildcard addresses * This ensures that no other application * can be receiving ntp packets */ nwilds = create_wildcards(port); idx = nwilds; result = isc_interfaceiter_create(mctx, &iter); if (result != ISC_R_SUCCESS) return (result); for (result = isc_interfaceiter_first(iter); result == ISC_R_SUCCESS; result = isc_interfaceiter_next(iter)) { isc_interface_t isc_if; unsigned int family; result = isc_interfaceiter_current(iter, &isc_if); if (result != ISC_R_SUCCESS) break; /* See if we have a valid family to use */ family = isc_if.address.family; if (family != AF_INET && family != AF_INET6) continue; if (scan_ipv4 == ISC_FALSE && family == AF_INET) continue; if (scan_ipv6 == ISC_FALSE && family == AF_INET6) continue; /* * Check to see if we are going to use the interface * If we don't use it we mark it to drop any packet * received but we still must create the socket and * bind to it. This prevents other apps binding to it * and potentially causing problems with more than one * process fiddling with the clock */ if (address_okay(&isc_if) == ISC_TRUE) { inter_list[idx].ignore_packets = ISC_FALSE; } else { inter_list[idx].ignore_packets = ISC_TRUE; } convert_isc_if(&isc_if, &inter_list[idx], port); inter_list[idx].fd = INVALID_SOCKET; inter_list[idx].bfd = INVALID_SOCKET; inter_list[idx].num_mcast = 0; inter_list[idx].received = 0; inter_list[idx].sent = 0; inter_list[idx].notsent = 0; idx++; } isc_interfaceiter_destroy(&iter); ninterfaces = idx; /* * Create the sockets */ for (i = 0; i < ninterfaces; i++) { inter_list[i].fd = open_socket(&inter_list[i].sin, inter_list[i].flags, 0, &inter_list[i], i); if (inter_list[i].fd != INVALID_SOCKET) msyslog(LOG_INFO, "Listening on interface %s, %s#%d %s", inter_list[i].name, stoa((&inter_list[i].sin)), NTP_PORT, (inter_list[i].ignore_packets == ISC_FALSE) ? "Enabled": "Disabled"); /* * Calculate the address hash for each interface address. */ inter_list[i].addr_refid = addr2refid(&inter_list[i].sin); } /* * Now that we have opened all the sockets, turn off the reuse * flag for security. */ set_reuseaddr(0); /* * Blacklist all bound interface addresses * Wildcard interfaces, if any, are ignored. */ for (i = nwilds; i < ninterfaces; i++) { SET_HOSTMASK(&resmask, inter_list[i].sin.ss_family); hack_restrict(RESTRICT_FLAGS, &inter_list[i].sin, &resmask, RESM_NTPONLY|RESM_INTERFACE, RES_IGNORE); }#ifdef DEBUG if (debug > 1) { printf("create_sockets: Total interfaces = %d\n", ninterfaces); for (i = 0; i < ninterfaces; i++) { print_interface(i); } }#endif return ninterfaces;}/* * set_reuseaddr() - set/clear REUSEADDR on all sockets * NB possible hole - should we be doing this on broadcast * fd's also? */static voidset_reuseaddr(int flag) { int i; for (i=0; i < ninterfaces; i++) { /* * if inter_list[ n ].fd is -1, we might have a adapter * configured but not present */ if (inter_list[i].fd != INVALID_SOCKET) { if (setsockopt(inter_list[i].fd, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof(flag))) { netsyslog(LOG_ERR, "set_reuseaddr: setsockopt(SO_REUSEADDR, %s) failed: %m", flag ? "on" : "off"); } } }}/* * This is just a wrapper around an internal function so we can * make other changes as necessary later on */voidenable_broadcast(struct interface *iface, struct sockaddr_storage *baddr){#ifdef SO_BROADCAST socket_broadcast_enable(iface, iface->fd, baddr);#endif}#ifdef OPEN_BCAST_SOCKET /* * Enable a broadcast address to a given socket * The socket is in the inter_list all we need to do is enable * broadcasting. It is not this function's job to select the socket */static isc_boolean_tsocket_broadcast_enable(struct interface *iface, SOCKET fd, struct sockaddr_storage *maddr){#ifdef SO_BROADCAST int on = 1; if (maddr->ss_family == AF_INET) { /* if this interface can support broadcast, set SO_BROADCAST */ if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char *)&on, sizeof(on))) { netsyslog(LOG_ERR, "setsockopt(SO_BROADCAST) enable failure on address %s: %m", stoa(maddr)); }#ifdef DEBUG else if (debug > 1) { printf("Broadcast enabled on socket %d for address %s\n", fd, stoa(maddr)); }#endif } iface->flags |= INT_BCASTOPEN; modify_addr_in_list(maddr, iface->flags); return ISC_TRUE;#else return ISC_FALSE;#endif /* SO_BROADCAST */}/* * Remove a broadcast address from a given socket * The socket is in the inter_list all we need to do is disable * broadcasting. It is not this function's job to select the socket */static isc_boolean_tsocket_broadcast_disable(struct interface *iface, int ind, struct sockaddr_storage *maddr){#ifdef SO_BROADCAST int off = 0; if (maddr->ss_family == AF_INET) { if (setsockopt(iface->fd, SOL_SOCKET, SO_BROADCAST, (char *)&off, sizeof(off))) { netsyslog(LOG_ERR, "setsockopt(SO_BROADCAST) disable failure on address %s: %m", stoa(maddr)); } } iface->flags &= ~INT_BCASTOPEN; modify_addr_in_list(maddr, iface->flags); return ISC_TRUE;#else return ISC_FALSE;#endif /* SO_BROADCAST */}#endif /* OPEN_BCAST_SOCKET *//* * Check to see if the address is a multicast address */static isc_boolean_taddr_ismulticast(struct sockaddr_storage *maddr){ switch (maddr->ss_family) { case AF_INET : if (!IN_CLASSD(ntohl(((struct sockaddr_in*)maddr)->sin_addr.s_addr))) {#ifdef DEBUG if (debug > 1) printf("multicast address %s not class D\n", stoa(maddr));#endif return (ISC_FALSE); } else { return (ISC_TRUE); } case AF_INET6 :#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT if (!IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)maddr)->sin6_addr)) {#ifdef DEBUG if (debug > 1) printf("address %s not IPv6 multicast address\n", stoa(maddr));#endif return (ISC_FALSE); } else { return (ISC_TRUE); }/* * If we don't have IPV6 support any IPV6 address is not multicast */#else return (ISC_FALSE);#endif /* * Never valid */ default: return (ISC_FALSE); }}/* * Multicast servers need to set the appropriate Multicast interface * socket option in order for it to know which interface to use for * send the multicast packet. */voidenable_multicast_if(struct interface *iface, struct sockaddr_storage *maddr){#ifdef MCAST switch (maddr->ss_family) { case AF_INET: if (setsockopt(iface->fd, IPPROTO_IP, IP_MULTICAST_IF, (char *)&(((struct sockaddr_in*)&iface->sin)->sin_addr.s_addr), sizeof(struct sockaddr_in*)) == -1) { netsyslog(LOG_ERR, "setsockopt IP_MULTICAST_IF failure: %m on socket %d, addr %s for multicast address %s", iface->fd, stoa(&iface->sin), stoa(maddr)); return; }#ifdef DEBUG if (debug > 0) { printf( "Added IPv4 multicast interface on socket %d, addr %s for multicast address %s\n", iface->fd, stoa(&iface->sin), stoa(maddr)); }#endif break; case AF_INET6:#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT if (setsockopt(iface->fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &iface->scopeid, sizeof(iface->scopeid)) == -1) { netsyslog(LOG_ERR, "setsockopt IPV6_MULTICAST_IF failure: %m on socket %d, addr %s, scope %d for multicast address %s", iface->fd, stoa(&iface->sin), iface->scopeid, stoa(maddr)); return; }#ifdef DEBUG if (debug > 0) { printf( "Added IPv6 multicast interface on socket %d, addr %s, scope %d for multicast address %s\n", iface->fd, stoa(&iface->sin), iface->scopeid, stoa(maddr)); }#endif break;#else return;#endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */ } return;#endif}/* * NOTE: Not all platforms support multicast */#ifdef MCAST/* * Add a multicast address to a given socket * The socket is in the inter_list all we need to do is enable * multicasting. It is not this function's job to select the socket */static isc_boolean_tsocket_multicast_enable(struct interface *iface, int ind, int lscope, struct sockaddr_storage *maddr){#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT struct ipv6_mreq mreq6; struct in6_addr iaddr6;#endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */ struct ip_mreq mreq; switch (maddr->ss_family) { case AF_INET: memset((char *)&mreq, 0, sizeof(mreq)); mreq.imr_multiaddr = (((struct sockaddr_in*)maddr)->sin_addr); mreq.imr_interface.s_addr = htonl(INADDR_ANY); if (setsockopt(iface->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq)) == -1) { netsyslog(LOG_ERR, "setsockopt IP_ADD_MEMBERSHIP failure: %m on socket %d, addr %s for %x / %x (%s)", iface->fd, stoa(&iface->sin), mreq.imr_multiaddr.s_addr, mreq.imr_interface.s_addr, stoa(maddr)); return ISC_FALSE; }#ifdef DEBUG if (debug > 0) { printf( "Added IPv4 multicast membership on socket %d, addr %s for %x / %x (%s)\n", iface->fd, stoa(&iface->sin), mreq.imr_multiaddr.s_addr, mreq.imr_interface.s_addr, stoa(maddr)); }#endif break; case AF_INET6:#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT /* * Enable reception of multicast packets * If the address is link-local we can get the interface index * from the scope id. Don't do this for other types of multicast * addresses. For now let the kernel figure it out. */ memset((char *)&mreq6, 0, sizeof(mreq6)); iaddr6 = ((struct sockaddr_in6*)maddr)->sin6_addr; mreq6.ipv6mr_multiaddr = iaddr6; mreq6.ipv6mr_interface = lscope; if (setsockopt(iface->fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mreq6, sizeof(mreq6)) == -1) { netsyslog(LOG_ERR, "setsockopt IPV6_JOIN_GROUP failure: %m on socket %d, addr %s for interface %d(%s)", iface->fd, stoa(&iface->sin), mreq6.ipv6mr_interface, stoa(maddr)); return ISC_FALSE; }#ifdef DEBUG if (debug > 0) { printf( "Added IPv6 multicast group on socket %d, addr %s for interface %d(%s)\n", iface->fd, stoa(&iface->sin), mreq6.ipv6mr_interface, stoa(maddr)); }#endif break;#else return ISC_FALSE;#endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */ } iface->flags |= INT_MCASTOPEN; iface->num_mcast++; add_addr_to_list(maddr, ind, iface->flags); return ISC_TRUE;}/* * Remove a multicast address from a given socket * The socket is in the inter_list all we need to do is disable * multicasting. It is not this function's job to select the socket */static isc_boolean_tsocket_multicast_disable(struct interface *iface, int ind, struct sockaddr_storage *maddr){#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT struct ipv6_mreq mreq6; struct in6_addr iaddr6;#endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */ struct ip_mreq mreq; memset((char *)&mreq, 0, sizeof(mreq)); switch (maddr->ss_family) { case AF_INET: mreq.imr_multiaddr = (((struct sockaddr_in*)&maddr)->sin_addr); mreq.imr_interface.s_addr = ((struct sockaddr_in*)&iface->sin)->sin_addr.s_addr; if (setsockopt(iface->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *)&mreq, sizeof(mreq)) == -1) { netsyslog(LOG_ERR, "setsockopt IP_DROP_MEMBERSHIP failure: %m on socket %d, addr %s for %x / %x (%s)", iface->fd, stoa(&iface->sin), mreq.imr_multiaddr.s_addr, mreq.imr_interface.s_addr, stoa(maddr)); return ISC_FALSE; } break; case AF_INET6:#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT /* * Disable reception of multicast packets * If the address is link-local we can get the interface index * from the scope id. Don't do this for other types of multicast * addresses. For now let the kernel figure it out. */ iaddr6 = ((struct sockaddr_in6*)&maddr)->sin6_addr; mreq6.ipv6mr_multiaddr = iaddr6; mreq6.ipv6mr_interface = iface->scopeid; if (setsockopt(iface->fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP, (char *)&mreq6, sizeof(mreq6)) == -1) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -