ntp_sock.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 381 行
C
381 行
#ifndef lintstatic char *sccsid = "@(#)ntp_sock.c 4.1 (ULTRIX) 7/2/90";#endif lint/************************************************************************ * * * Copyright (c) 1989-1990 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************/#ifndef lintstatic char *RCSid = "$Source: /usr/users/louie/ntp/RCS/ntp_sock.c,v $ $Revision: 3.4.1.3 $ $Date: 89/05/18 18:28:20 $";#endif/* * $Log: ntp_sock.c,v $ * Revision 3.4.1.3 89/05/18 18:28:20 louie * In ntp_sock.c, change the order that the bind() call is done for each socket. * It turns out that if you have the Multicast code installed, incoming packets * will be delived to the *first* socket that matches. It also turns out that * when binding sockets, the first one bound is the last on checked, so we want * to bind the wildcard socket first. * * Revision 3.4.1.2 89/04/07 19:07:46 louie * Deleted unused variables in ntp_sock.c * * Revision 3.4.1.1 89/03/22 18:31:20 louie * patch3: Use new RCS headers. * * Revision 3.4 89/03/17 18:37:09 louie * Latest test release. * * Revision 3.3 89/03/15 14:19:53 louie * New baseline for next release. * * Revision 3.2.1.1 89/03/10 11:30:41 louie * 1 * * Revision 3.2 89/03/07 18:26:26 louie * New version of UNIX NTP daemon based on the 6 March 1989 draft of the new * NTP protocol specification. This version has a bunch of bugs fixes and * new algorithms which were discussed on the NTP mailing list over the past * few weeks. * * Revision 3.1.1.1 89/02/15 08:56:28 louie * *** empty log message *** * * * Revision 3.1 89/01/30 14:43:12 louie * Second UNIX NTP test release. * * Revision 3.0 88/12/12 16:00:15 louie * Test release of new UNIX NTP software. This version should conform to the * revised NTP protocol specification. * */#include <sys/types.h>#include <sys/param.h>#include <sys/ioctl.h>#include <sys/file.h>#include <sys/socket.h>#include <netinet/in.h>#include <net/if.h>#include <errno.h>#include <syslog.h>#include <stdio.h>#include "ntp.h"#define MAX_INTF 10struct intf addrs[MAX_INTF];int nintf;#ifdef TESTextern int errno;main() { int i, cc, val; char foo[10]; syslog(LOG_ERR, "ifconfig test"); create_sockets(htons(43242)); for (i = 0; i < nintf; i++) { printf("%d: %s fd %d addr %s mask %x ", i, addrs[i].name, addrs[i].fd, inet_ntoa(addrs[i].sin.sin_addr.s_addr), ntohl(addrs[i].mask.sin_addr.s_addr)); cc = sizeof(val); if (getsockopt(addrs[0].fd, SOL_SOCKET, SO_BROADCAST, (char*)&val, &cc)) { perror("getsockopt"); exit(1); } printf("BCAST opt %d", val); cc = sizeof(val); if (getsockopt(addrs[0].fd, SOL_SOCKET, SO_RCVBUF, (char*)&val, &cc)) { perror("getsockopt"); exit(1); } printf("sockbuf size = %d ", val); putchar('\n'); } for (i=0; i < nintf; i++) { fprintf(stderr, "Read fd %d.. ", addrs[i].fd); cc = read(addrs[i].fd, foo, 10); fprintf(stderr, " returns %d ", cc); perror("read errno"); }}#endif#ifndef SIOCGIFCONF/* * If we can't determine the interface configuration, just listen with one * socket at the INADDR_ANY address. */create_sockets(port) unsigned int port;{ addrs[0].sin.sin_family = AF_INET; addrs[0].sin.sin_port = 0; addrs[0].sin.sin_addr.s_addr = INADDR_ANY; addrs[0].sin.sin_mask.s_addr = htonl(~0); addrs[0].name = "wildcard"; if ((addrs[0].fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { syslog(LOG_ERR, "socket() failed: %m");#ifdef TEST perror( "socket() failed");#endif exit(1); /*NOTREACHED*/ } if (fcntl(addrs[i].fd, F_SETFL, FNDELAY) < 0) { syslog(LOG_ERR, "fcntl(FNDELAY) fails: %m");#ifdef TEST perror("fcntl(FNDELAY) fails");#endif exit(1); /*NOTREACHED*/ } addrs[0].sin.sin_family = AF_INET; addrs[0].sin.sin_port = port; addrs[0].if_flags = 0; if (bind(addrs[0].fd, (struct sockaddr *)&addrs[0].sin, sizeof(addrs[0].sin)) < 0) { syslog(LOG_ERR, "bind() fails: %m");#ifdef TEST perror("bind fails\n");#endif exit(1); } nintf = 1; return nintf;}#else/* * Grab interface configuration, and create a socket for each interface * address. */create_sockets(port) unsigned int port;{ char buf[1024]; struct ifconf ifc; struct ifreq ifreq, *ifr; int on = 1, off = 0; int n, i, vs; extern char *malloc(); /* * create pseudo-interface with wildcard address */ addrs[nintf].sin.sin_family = AF_INET; addrs[nintf].sin.sin_port = 0; addrs[nintf].sin.sin_addr.s_addr = INADDR_ANY; addrs[nintf].name = "wild"; addrs[nintf].mask.sin_addr.s_addr = htonl(~0); nintf = 1; if ((vs = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { syslog(LOG_ERR, "vs=socket(AF_INET, SOCK_DGRAM) %m");#ifdef TEST perror("vs=socket(AF_INET, SOCK_DGRAM)");#endif exit(1); } ifc.ifc_len = sizeof(buf); ifc.ifc_buf = buf; if (ioctl(vs, SIOCGIFCONF, (char *)&ifc) < 0) { syslog(LOG_ERR, "get interface configuration: %m");#ifdef TEST perror("ioctl(SIOCGIFCONF) fails");#endif exit(1); } n = ifc.ifc_len/sizeof(struct ifreq); for (ifr = ifc.ifc_req; n > 0; n--, ifr++) { if (ifr->ifr_addr.sa_family != AF_INET) continue; ifreq = *ifr; if (ioctl(vs, SIOCGIFFLAGS, (char *)&ifreq) < 0) { syslog(LOG_ERR, "get interface flags: %m");#ifdef TEST perror("SIOCGIFFFLAGS fails");#endif continue; } if ((ifreq.ifr_flags & IFF_UP) == 0) continue; addrs[nintf].if_flags = ifreq.ifr_flags; if (ioctl(vs, SIOCGIFADDR, (char *)&ifreq) < 0) { syslog(LOG_ERR, "get interface addr: %m");#ifdef TEST perror("SIOCGIFADDR fails");#endif continue; } if ((addrs[nintf].name = malloc(strlen(ifreq.ifr_name)+1)) == NULL) { syslog(LOG_ERR, "malloc failed"); exit(1); } strcpy(addrs[nintf].name, ifreq.ifr_name); addrs[nintf].sin = *(struct sockaddr_in *)&ifreq.ifr_addr;#ifdef SIOCGIFBRDADDR if (addrs[nintf].if_flags & IFF_BROADCAST) { if (ioctl(vs, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { syslog(LOG_ERR, "SIOCGIFBRDADDR fails");#ifdef TEST perror("SIOCGIFBRDADDR fails");#endif exit(1); }#ifndef SUN_3_3 addrs[nintf].bcast = *(struct sockaddr_in *)&ifreq.ifr_broadaddr;#else addrs[nintf].bcast = *(struct sockaddr_in *)&ifreq.ifr_addr;#endif }#endif /* SIOCGIFBRDADDR */#ifdef SIOCGIFNETMASK if (ioctl(vs, SIOCGIFNETMASK, (char *)&ifreq) < 0) { syslog(LOG_ERR, "SIOCGIFNETMASK fails");#ifdef TEST perror("SIOCGIFNETMASK fails");#endif exit(1); } addrs[nintf].mask = *(struct sockaddr_in *)&ifreq.ifr_addr;#endif /* SIOCGIFNETMASK */ /* * look for an already existing source interface address. If * the machine has multiple point to point interfaces, then * the local address may appear more than once. */ for (i=0; i < nintf; i++) if (addrs[i].sin.sin_addr.s_addr == addrs[nintf].sin.sin_addr.s_addr) {#ifdef TEST printf("dup interface address %s on %s\n", inet_ntoa(addrs[nintf].sin.sin_addr.s_addr), ifreq.ifr_name);#endif goto next; } nintf++; next:; } close(vs); for (i = 0; i < nintf; i++) { /* create a datagram (UDP) socket */ if ((addrs[i].fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { syslog(LOG_ERR, "socket() failed: %m");#ifdef TEST perror("socket(AF_INET, SOCK_DGRAM) fails");#endif exit(1); /*NOTREACHED*/ } /* set SO_REUSEADDR since we will be binding the same port number on each interface */ if (setsockopt(addrs[i].fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on))) {#ifdef TEST perror("setsockopt SO_REUSEADDR on");#endif syslog(LOG_ERR, "setsockopt SO_REUSEADDR on fails: %m"); } /* * set non-blocking I/O on the descriptor */ if (fcntl(addrs[i].fd, F_SETFL, FNDELAY) < 0) { syslog(LOG_ERR, "fcntl(FNDELAY) fails: %m");#ifdef TEST perror("fcntl(F_SETFL, FNDELAY) fails");#endif exit(1); /*NOTREACHED*/ } /* * finally, bind the local address address. */ addrs[i].sin.sin_family = AF_INET; addrs[i].sin.sin_port = port; if (bind(addrs[i].fd, (struct sockaddr *)&addrs[i].sin, sizeof(addrs[i].sin)) < 0) { syslog(LOG_ERR, "bind() fails: %m");#ifdef TEST perror("bind fails");#endif exit(1); } /* * 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 (setsockopt(addrs[i].fd, SOL_SOCKET, SO_REUSEADDR, (char *)&off, sizeof(off))) { syslog(LOG_ERR, "setsockopt SO_REUSEADDR off fails: %m");#ifdef TEST perror("setsockopt SO_REUSEADDR off");#endif }#ifdef SO_BROADCAST /* if this interface can support broadcast, set SO_BROADCAST */ if (addrs[i].if_flags & IFF_BROADCAST) { if (setsockopt(addrs[i].fd, SOL_SOCKET, SO_BROADCAST, (char *)&on, sizeof(on))) { syslog(LOG_ERR, "setsockopt(SO_BROADCAST): %m");#ifdef TEST perror("setsockopt(SO_BROADCAST) on");#endif } }#endif /* SO_BROADCAST */ } return nintf;}#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?