📄 ntp_io.c
字号:
netsyslog(LOG_ERR, "setsockopt IPV6_LEAVE_GROUP failure: %m on socket %d, addr %s for %d(%s)", iface->fd, stoa(&iface->sin), mreq6.ipv6mr_interface, stoa(maddr)); return ISC_FALSE; } break;#else return ISC_FALSE;#endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */ } iface->num_mcast--; if (iface->num_mcast <= 0) { iface->flags &= ~INT_MCASTOPEN; modify_addr_in_list(maddr, iface->flags); } return ISC_TRUE;}#endif /* MCAST *//* * io_setbclient - open the broadcast client sockets */voidio_setbclient(void){#ifdef OPEN_BCAST_SOCKET int i; int nif = 0; isc_boolean_t jstatus; SOCKET fd; set_reuseaddr(1); for (i = nwilds; i < ninterfaces; i++) { /* use only allowed addresses */ if (inter_list[i].ignore_packets == ISC_TRUE) continue; /* Only IPv4 addresses are valid for broadcast */ if (inter_list[i].sin.ss_family != AF_INET) continue; /* Is this a broadcast address? */ if (!(inter_list[i].flags & INT_BROADCAST)) continue; /* Skip the loopback addresses */ if (inter_list[i].flags & INT_LOOPBACK) continue; /* Do we already have the broadcast address open? */ if (inter_list[i].flags & INT_BCASTOPEN) continue; /* * Try to open the broadcast address */ inter_list[i].family = AF_INET; inter_list[i].bfd = open_socket(&inter_list[i].bcast, INT_BROADCAST, 1, &inter_list[i], i); /* * If we succeeded then we use it otherwise * enable the underlying address */ if (inter_list[i].bfd == INVALID_SOCKET) { fd = inter_list[i].fd; } else { fd = inter_list[i].bfd; } /* Enable Broadcast on socket */ jstatus = socket_broadcast_enable(&inter_list[i], fd, &inter_list[i].sin); if (jstatus == ISC_TRUE) { nif++; netsyslog(LOG_INFO,"io_setbclient: Opened broadcast client on interface %d, socket: %d", i, fd); } } set_reuseaddr(0);#ifdef DEBUG if (debug) if (nif > 0) printf("io_setbclient: Opened broadcast clients\n");#endif if (nif == 0) netsyslog(LOG_ERR, "Unable to listen for broadcasts, no broadcast interfaces available");#else netsyslog(LOG_ERR, "io_setbclient: Broadcast Client disabled by build");#endif}/* * io_unsetbclient - close the broadcast client sockets */voidio_unsetbclient(void){#ifdef OPEN_BCAST_SOCKET int i; isc_boolean_t lstatus; for (i = nwilds; i < ninterfaces; i++) { if (!(inter_list[i].flags & INT_BCASTOPEN)) continue; lstatus = socket_broadcast_disable(&inter_list[i], i, &inter_list[i].sin); }#endif}voidio_multicast_add( struct sockaddr_storage addr ){#ifdef MCAST int i; isc_boolean_t jstatus; int ind; int lscope = 0; /* * Check to see if this is a multicast address */ if (addr_ismulticast(&addr) == ISC_FALSE) return; /* If we already have it we can just return */ ind = find_flagged_addr_in_list(&addr, INT_MCASTOPEN); if (ind >= 0) { netsyslog(LOG_INFO, "Duplicate request found for multicast address %s", stoa(&addr)); return; }#ifndef MULTICAST_NONEWSOCKET /* * Find an empty slot to use */ ind = -1; for (i = nwilds; i < ninterfaces; i++) { /* found a free slot */ if (SOCKNUL(&inter_list[i].sin) && inter_list[i].fd <= 0 && inter_list[i].bfd <= 0) { ind = i; break; } } /* * We didn't find a slot and nothing available. Log and return */ if (ind < 0 && ninterfaces >= MAXINTERFACES) { netsyslog(LOG_ERR, "No interface available to use for address %s", stoa(&addr)); return; } else { ind = ninterfaces; } /* * Open a new socket for the multicast address */ memset((char *)&inter_list[ind], 0, sizeof(struct interface)); inter_list[ind].sin.ss_family = addr.ss_family; inter_list[ind].family = addr.ss_family; switch(addr.ss_family) { case AF_INET: memcpy(&(((struct sockaddr_in *)&inter_list[ind].sin)->sin_addr), &(((struct sockaddr_in*)&addr)->sin_addr), sizeof(struct in_addr)); ((struct sockaddr_in*)&inter_list[ind].sin)->sin_port = htons(NTP_PORT); memset(&((struct sockaddr_in*)&inter_list[ind].mask)->sin_addr.s_addr, 0xff, sizeof(struct in_addr)); break; case AF_INET6:#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT memcpy(&(((struct sockaddr_in6 *)&inter_list[ind].sin)->sin6_addr), &((struct sockaddr_in6*)&addr)->sin6_addr, sizeof(struct in6_addr)); ((struct sockaddr_in6*)&inter_list[ind].sin)->sin6_port = htons(NTP_PORT);#ifdef ISC_PLATFORM_HAVESCOPEID ((struct sockaddr_in6*)&inter_list[ind].sin)->sin6_scope_id = ((struct sockaddr_in6*)&addr)->sin6_scope_id;#endif memset(&((struct sockaddr_in6*)&inter_list[ind].mask)->sin6_addr.s6_addr, 0xff, sizeof(struct in6_addr));#endif i = findlocalcastinterface(&addr, INT_MULTICAST);# ifdef ISC_PLATFORM_HAVESCOPEID if (i >= 0) lscope = ((struct sockaddr_in6*)&inter_list[i].sin)->sin6_scope_id;# endif#ifdef DEBUG if (debug > 1) printf("Found interface index %d, scope: %d for address %s\n", i, lscope, stoa(&addr));#endif break; } set_reuseaddr(1); inter_list[ind].bfd = INVALID_SOCKET; inter_list[ind].fd = open_socket(&inter_list[ind].sin, INT_MULTICAST, 1, &inter_list[ind], ind); set_reuseaddr(0); if (inter_list[ind].fd != INVALID_SOCKET) { inter_list[ind].bfd = INVALID_SOCKET; inter_list[ind].ignore_packets = ISC_FALSE; (void) strncpy(inter_list[ind].name, "multicast", sizeof(inter_list[ind].name)); ((struct sockaddr_in*)&inter_list[ind].mask)->sin_addr.s_addr = htonl(~(u_int32)0); if (ind >= ninterfaces) ninterfaces = ind + 1;#ifdef DEBUG if(debug > 1) print_interface(ind);#endif } else { memset((char *)&inter_list[ind], 0, sizeof(struct interface)); ind = -1; if (addr.ss_family == AF_INET) ind = wildipv4; else if (addr.ss_family == AF_INET6) ind = wildipv6; if (ind >= 0) { /* HACK ! -- stuff in an address */ inter_list[ind].bcast = addr; netsyslog(LOG_ERR, "...multicast address %s using wildcard socket", stoa(&addr)); } else { netsyslog(LOG_ERR, "No multicast socket available to use for address %s", stoa(&addr)); return; } }#else /* * For the case where we can't use a separate socket */ ind = findlocalcastinterface(&addr, INT_MULTICAST);#endif /* * If we don't have a valid socket, just return */ if (ind < 0) { netsyslog(LOG_ERR, "Cannot add multicast address %s: Cannot find slot", stoa(&addr)); return; } jstatus = socket_multicast_enable(&inter_list[ind], ind, lscope, &addr); if (jstatus == ISC_TRUE) netsyslog(LOG_INFO, "Added Multicast Listener %s on interface %d\n", stoa(&addr), ind); else netsyslog(LOG_ERR, "Failed to add Multicast Listener %s\n", stoa(&addr));#else /* MCAST */ netsyslog(LOG_ERR, "Cannot add multicast address %s: no Multicast support", stoa(&addr));#endif /* MCAST */ return;}/* * io_multicast_del() - delete multicast group address */voidio_multicast_del( struct sockaddr_storage addr ){#ifdef MCAST int i; isc_boolean_t lstatus; /* * Check to see if this is a multicast address */ if (addr_ismulticast(&addr) == ISC_FALSE) { netsyslog(LOG_ERR, "invalid multicast address %s", stoa(&addr)); return; } switch (addr.ss_family) { case AF_INET : /* * Disable reception of multicast packets */ i = find_flagged_addr_in_list(&addr, INT_MCASTOPEN); while ( i > 0) { lstatus = socket_multicast_disable(&inter_list[i], i, &addr); i = find_flagged_addr_in_list(&addr, INT_MCASTOPEN); } break;#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT case AF_INET6 : /* * Disable reception of multicast packets */ for (i = 0; i < ninterfaces; i++) { /* Be sure it's the correct family */ if (inter_list[i].sin.ss_family != AF_INET6) continue; if (!(inter_list[i].flags & INT_MCASTOPEN)) continue; if (!(inter_list[i].fd < 0)) continue; if (!SOCKCMP(&addr, &inter_list[i].sin)) continue; lstatus = socket_multicast_disable(&inter_list[i], i, &addr); } break;#endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */ }/* switch */ delete_addr_from_list(&addr);#else /* not MCAST */ netsyslog(LOG_ERR, "this function requires multicast kernel");#endif /* not MCAST */}/* * open_socket - open a socket, returning the file descriptor */static SOCKETopen_socket( struct sockaddr_storage *addr, int flags, int turn_off_reuse, struct interface *interf, int ind ){ int errval; SOCKET fd; int on = 1, off = 0;#if defined(IPTOS_LOWDELAY) && defined(IPPROTO_IP) && defined(IP_TOS) int tos;#endif /* IPTOS_LOWDELAY && IPPROTO_IP && IP_TOS */ if ((addr->ss_family == AF_INET6) && (isc_net_probeipv6() != ISC_R_SUCCESS)) return (INVALID_SOCKET); /* create a datagram (UDP) socket */#ifndef SYS_WINNT if ( (fd = socket(addr->ss_family, SOCK_DGRAM, 0)) < 0) { errval = errno;#else if ( (fd = socket(addr->ss_family, SOCK_DGRAM, 0)) == INVALID_SOCKET) { errval = WSAGetLastError();#endif if(addr->ss_family == AF_INET) netsyslog(LOG_ERR, "socket(AF_INET, SOCK_DGRAM, 0) failed on address %s: %m", stoa(addr)); else if(addr->ss_family == AF_INET6) netsyslog(LOG_ERR, "socket(AF_INET6, SOCK_DGRAM, 0) failed on address %s: %m", stoa(addr));#ifndef SYS_WINNT if (errval == EPROTONOSUPPORT || errval == EAFNOSUPPORT || errval == EPFNOSUPPORT)#else if (errval == WSAEPROTONOSUPPORT || errval == WSAEAFNOSUPPORT || errval == WSAEPFNOSUPPORT)#endif return (INVALID_SOCKET); exit(1); /*NOTREACHED*/ }#ifdef SYS_WINNT if (connection_reset_fix(fd) != ISC_R_SUCCESS) { netsyslog(LOG_ERR, "connection_reset_fix(fd) failed on address %s: %m", stoa(addr)); }#endif /* SYS_WINNT */ /* set SO_REUSEADDR since we will be binding the same port number on each interface */ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on))) { netsyslog(LOG_ERR, "setsockopt SO_REUSEADDR on fails on address %s: %m", stoa(addr)); } /* * IPv4 specific options go here */ if (addr->ss_family == AF_INET) {#if defined(IPTOS_LOWDELAY) && defined(IPPROTO_IP) && defined(IP_TOS) /* set IP_TOS to minimize packet delay */ tos = IPTOS_LOWDELAY; if (setsockopt(fd, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(tos)) < 0) { netsyslog(LOG_ERR, "setsockopt IPTOS_LOWDELAY on fails on address %s: %m", stoa(addr)); }#endif /* IPTOS_LOWDELAY && IPPROTO_IP && IP_TOS */ } /* * IPv6 specific options go here */ if (addr->ss_family == AF_INET6) {#if defined(IPV6_V6ONLY) if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&on, sizeof(on))) { netsyslog(LOG_ERR, "setsockopt IPV6_V6ONLY on fails on address %s: %m", stoa(addr)); }#endif /* IPV6_V6ONLY */#if defined(IPV6_BINDV6ONLY) if (setsockopt(fd, IPPROTO_IPV6, IPV6_BINDV6ONLY, (char*)&on, sizeof(on))) { netsyslog(LOG_ERR, "setsockopt IPV6_BINDV6ONLY on fails on address %s: %m", stoa(addr)); }#endif /* IPV6_BINDV6ONLY */ } /* * bind the local address. */ if (bind(fd, (struct sockaddr *)addr, SOCKLEN(addr)) < 0) { char buff[160]; if(addr->ss_family == AF_INET) sprintf(buff, "bind() fd %d, family %d, port %d, addr %s, in_classd=%d flags=%d fails: %%m", fd, addr->ss_family, (int)ntohs(((struct sockaddr_in*)addr)->sin_port), stoa(addr), IN_CLASSD(ntohl(((struct sockaddr_in*)addr)->sin_addr.s_addr)), flags);#ifdef INCLUDE_IPV6_SUPPORT else if(addr->ss_family == AF_INET6) sprintf(buff, "bind() fd %d, family %d, port %d, scope %d, addr %s, in6_is_addr_multicast=%d flags=%d fails: %%m", fd, addr->ss_family, (int)ntohs(((struct sockaddr_in6*)addr)->sin6_port),# ifdef ISC_PLATFORM_HAVESCOPEID ((struct sockaddr_in6*)addr)->sin6_scope_id# else -1# endif , stoa(addr), IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)addr)->sin6_addr), flags);#endif else return (INVALID_SOCKET); /* * Don't log this under all conditions */ if (turn_off_reuse == 0 || debug > 1) netsyslog(LOG_ERR, buff); closesocket(fd); return (INVALID_SOCKET); }#ifdef DEBUG if (debug) printf("bind() fd %d, family %d, port %d, addr %s, flags=%d\n", fd, addr->ss_family, (int)ntohs(((struct sockaddr_in*)addr)->sin_port), stoa(addr), flags);#endif /* * I/O Completion Ports don't care about the select and FD_SET */#ifndef HAVE_IO_COMPLETION_PORT if (fd > maxactivefd) maxactivefd = fd; FD_SET(fd, &activefds);#endif add_socket_to_list(fd); add_addr_to_list(addr, ind, interf->flags); /* * set non-blocking, */#ifdef USE_FIONBIO /* in vxWorks we use FIONBIO, but the others are defined for old systems, so * all hell breaks loose if we leave them defined */#undef O_NONBLOCK#undef FNDELAY#undef O_NDELAY#endif#if defined(O_NONBLOCK) /* POSIX */ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { netsyslog(LOG_ERR, "fcntl(O_NONBLOCK) fails on address %s: %m",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -