1: #ifndef lint
   2: static char *RCSid = "$Source: /usr/users/louie/ntp/RCS/ntp_sock.c,v $ $Revision: 3.4.1.3 $ $Date: 89/05/18 18:28:20 $";
   3: #endif
   4: 
   5: /*
   6:  * $Log:	ntp_sock.c,v $
   7:  * Revision 3.4.1.3  89/05/18  18:28:20  louie
   8:  * In ntp_sock.c, change the order that the bind() call is done for each socket.
   9:  * It turns out that if you have the Multicast code installed, incoming packets
  10:  * will be delived to the *first* socket that matches.  It also turns out that
  11:  * when binding sockets, the first one bound is the last on checked, so we want
  12:  * to bind the wildcard socket first.
  13:  *
  14:  * Revision 3.4.1.2  89/04/07  19:07:46  louie
  15:  * Deleted unused variables in ntp_sock.c
  16:  *
  17:  * Revision 3.4.1.1  89/03/22  18:31:20  louie
  18:  * patch3: Use new RCS headers.
  19:  *
  20:  * Revision 3.4  89/03/17  18:37:09  louie
  21:  * Latest test release.
  22:  *
  23:  * Revision 3.3  89/03/15  14:19:53  louie
  24:  * New baseline for next release.
  25:  *
  26:  * Revision 3.2.1.1  89/03/10  11:30:41  louie
  27:  * 1
  28:  *
  29:  * Revision 3.2  89/03/07  18:26:26  louie
  30:  * New version of UNIX NTP daemon based on the 6 March 1989 draft of the new
  31:  * NTP protocol specification.  This version has a bunch of bugs fixes and
  32:  * new algorithms which were discussed on the NTP mailing list over the past
  33:  * few weeks.
  34:  *
  35:  * Revision 3.1.1.1  89/02/15  08:56:28  louie
  36:  * *** empty log message ***
  37:  *
  38:  *
  39:  * Revision 3.1  89/01/30  14:43:12  louie
  40:  * Second UNIX NTP test release.
  41:  *
  42:  * Revision 3.0  88/12/12  16:00:15  louie
  43:  * Test release of new UNIX NTP software.  This version should conform to the
  44:  * revised NTP protocol specification.
  45:  *
  46:  */
  47: 
  48: #include <sys/types.h>
  49: #include <sys/param.h>
  50: #include <sys/ioctl.h>
  51: #include <sys/file.h>
  52: #include <sys/socket.h>
  53: #include <netinet/in.h>
  54: #include <net/if.h>
  55: #include <errno.h>
  56: #include <syslog.h>
  57: #include <stdio.h>
  58: #include "ntp.h"
  59: 
  60: #define MAX_INTF    10
  61: struct intf addrs[MAX_INTF];
  62: int nintf;
  63: 
  64: #ifdef  TEST
  65: extern int errno;
  66: 
  67: main() {
  68:     int i, cc, val;
  69:     char foo[10];
  70: 
  71:     syslog(LOG_ERR, "ifconfig test");
  72:     create_sockets(htons(43242));
  73:     for (i = 0; i < nintf; i++) {
  74:         printf("%d: %s fd %d  addr %s  mask %x ",
  75:                i, addrs[i].name, addrs[i].fd,
  76:                inet_ntoa(addrs[i].sin.sin_addr.s_addr),
  77:                ntohl(addrs[i].mask.sin_addr.s_addr));
  78:         cc = sizeof(val);
  79:         if (getsockopt(addrs[0].fd, SOL_SOCKET, SO_BROADCAST,
  80:                    (char*)&val, &cc)) {
  81:             perror("getsockopt");
  82:             exit(1);
  83:         }
  84:         printf("BCAST opt %d", val);
  85:         cc = sizeof(val);
  86:         if (getsockopt(addrs[0].fd, SOL_SOCKET, SO_RCVBUF,
  87:                    (char*)&val, &cc)) {
  88:             perror("getsockopt");
  89:             exit(1);
  90:         }
  91:         printf("sockbuf size = %d ", val);
  92:         putchar('\n');
  93:     }
  94: 
  95:     for (i=0; i < nintf; i++) {
  96:         fprintf(stderr, "Read fd %d.. ", addrs[i].fd);
  97:         cc = read(addrs[i].fd, foo, 10);
  98:         fprintf(stderr, " returns %d ", cc);
  99:         perror("read errno");
 100:     }
 101: }
 102: #endif
 103: 
 104: #ifndef SIOCGIFCONF
 105: /*
 106:  *  If we can't determine the interface configuration, just listen with one
 107:  *  socket at the INADDR_ANY address.
 108:  */
 109: create_sockets(port)
 110:     unsigned int port;
 111: {
 112:     addrs[0].sin.sin_family = AF_INET;
 113:     addrs[0].sin.sin_port = 0;
 114:     addrs[0].sin.sin_addr.s_addr = INADDR_ANY;
 115:     addrs[0].sin.sin_mask.s_addr = htonl(~0);
 116:     addrs[0].name = "wildcard";
 117: 
 118:     if ((addrs[0].fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
 119:         syslog(LOG_ERR, "socket() failed: %m");
 120: #ifdef  TEST
 121:         perror( "socket() failed");
 122: #endif
 123:         exit(1);
 124:         /*NOTREACHED*/
 125:     }
 126: 
 127:     if (fcntl(addrs[i].fd, F_SETFL, FNDELAY) < 0) {
 128:         syslog(LOG_ERR, "fcntl(FNDELAY) fails: %m");
 129: #ifdef  TEST
 130:         perror("fcntl(FNDELAY) fails");
 131: #endif
 132:         exit(1);
 133:         /*NOTREACHED*/
 134:     }
 135:     addrs[0].sin.sin_family = AF_INET;
 136:     addrs[0].sin.sin_port = port;
 137:     addrs[0].if_flags = 0;
 138:     if (bind(addrs[0].fd, (struct sockaddr *)&addrs[0].sin,
 139:          sizeof(addrs[0].sin)) < 0) {
 140:         syslog(LOG_ERR, "bind() fails: %m");
 141: #ifdef  TEST
 142:         perror("bind fails\n");
 143: #endif
 144:         exit(1);
 145:     }
 146:     nintf = 1;
 147:     return nintf;
 148: }
 149: #else
 150: /*
 151:  *  Grab interface configuration, and create a socket for each interface
 152:  *  address.
 153:  */
 154: create_sockets(port)
 155:     unsigned int port;
 156: {
 157:     char    buf[1024];
 158:     struct  ifconf  ifc;
 159:     struct  ifreq   ifreq, *ifr;
 160:     int on = 1, off = 0;
 161:     int n, i, vs;
 162:     extern char *malloc();
 163: 
 164:     /*
 165: 	 * create pseudo-interface with wildcard address
 166: 	 */
 167:     addrs[nintf].sin.sin_family = AF_INET;
 168:     addrs[nintf].sin.sin_port = 0;
 169:     addrs[nintf].sin.sin_addr.s_addr = INADDR_ANY;
 170:     addrs[nintf].name = "wild";
 171:     addrs[nintf].mask.sin_addr.s_addr = htonl(~0);
 172: 
 173:     nintf = 1;
 174: 
 175:     if ((vs = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
 176:         syslog(LOG_ERR, "vs=socket(AF_INET, SOCK_DGRAM) %m");
 177: #ifdef  TEST
 178:         perror("vs=socket(AF_INET, SOCK_DGRAM)");
 179: #endif
 180:         exit(1);
 181:     }
 182:     ifc.ifc_len = sizeof(buf);
 183:     ifc.ifc_buf = buf;
 184:     if (ioctl(vs, SIOCGIFCONF, (char *)&ifc) < 0) {
 185:         syslog(LOG_ERR, "get interface configuration: %m");
 186: #ifdef  TEST
 187:         perror("ioctl(SIOCGIFCONF) fails");
 188: #endif
 189:         exit(1);
 190:     }
 191:     n = ifc.ifc_len/sizeof(struct ifreq);
 192: 
 193:     for (ifr = ifc.ifc_req; n > 0; n--, ifr++) {
 194:         if (ifr->ifr_addr.sa_family != AF_INET)
 195:             continue;
 196:         ifreq = *ifr;
 197:         if (ioctl(vs, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
 198:             syslog(LOG_ERR, "get interface flags: %m");
 199: #ifdef  TEST
 200:             perror("SIOCGIFFFLAGS fails");
 201: #endif
 202:             continue;
 203:         }
 204:         if ((ifreq.ifr_flags & IFF_UP) == 0)
 205:             continue;
 206:         addrs[nintf].if_flags = ifreq.ifr_flags;
 207: 
 208:         if (ioctl(vs, SIOCGIFADDR, (char *)&ifreq) < 0) {
 209:             syslog(LOG_ERR, "get interface addr: %m");
 210: #ifdef  TEST
 211:             perror("SIOCGIFADDR fails");
 212: #endif
 213:             continue;
 214:         }
 215:         if ((addrs[nintf].name = malloc(strlen(ifreq.ifr_name)+1))
 216:                 == NULL) {
 217:             syslog(LOG_ERR, "malloc failed");
 218:             exit(1);
 219:         }
 220:         strcpy(addrs[nintf].name, ifreq.ifr_name);
 221:         addrs[nintf].sin = *(struct sockaddr_in *)&ifreq.ifr_addr;
 222: 
 223: #ifdef SIOCGIFBRDADDR
 224:         if (addrs[nintf].if_flags & IFF_BROADCAST) {
 225:             if (ioctl(vs, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
 226:                 syslog(LOG_ERR, "SIOCGIFBRDADDR fails");
 227: #ifdef  TEST
 228:                 perror("SIOCGIFBRDADDR fails");
 229: #endif
 230:                 exit(1);
 231:             }
 232: #ifndef SUN_3_3
 233:             addrs[nintf].bcast =
 234:                 *(struct sockaddr_in *)&ifreq.ifr_broadaddr;
 235: #else
 236:             addrs[nintf].bcast =
 237:                 *(struct sockaddr_in *)&ifreq.ifr_addr;
 238: #endif
 239:         }
 240: #endif /* SIOCGIFBRDADDR */
 241: #ifdef SIOCGIFNETMASK
 242:         if (ioctl(vs, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
 243:             syslog(LOG_ERR, "SIOCGIFNETMASK fails");
 244: #ifdef  TEST
 245:             perror("SIOCGIFNETMASK fails");
 246: #endif
 247:             exit(1);
 248:         }
 249:         addrs[nintf].mask = *(struct sockaddr_in *)&ifreq.ifr_addr;
 250: #endif /* SIOCGIFNETMASK */
 251: 
 252:         /*
 253: 		 * look for an already existing source interface address.  If
 254: 		 * the machine has multiple point to point interfaces, then
 255: 		 * the local address may appear more than once.
 256: 		 */
 257:         for (i=0; i < nintf; i++)
 258:             if (addrs[i].sin.sin_addr.s_addr ==
 259:                 addrs[nintf].sin.sin_addr.s_addr) {
 260: #ifdef TEST
 261:                 printf("dup interface address %s on %s\n",
 262:                     inet_ntoa(addrs[nintf].sin.sin_addr.s_addr),
 263:                     ifreq.ifr_name);
 264: #endif
 265:                 goto next;
 266:             }
 267:         nintf++;
 268:        next:;
 269:     }
 270:     close(vs);
 271: 
 272:     for (i = 0; i < nintf; i++) {
 273:         /* create a datagram (UDP) socket */
 274:         if ((addrs[i].fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
 275:             syslog(LOG_ERR, "socket() failed: %m");
 276: #ifdef  TEST
 277:             perror("socket(AF_INET, SOCK_DGRAM) fails");
 278: #endif
 279:             exit(1);
 280:             /*NOTREACHED*/
 281:         }
 282: 
 283:         /* set SO_REUSEADDR since we will be binding the same port
 284: 		   number on each interface */
 285:         if (setsockopt(addrs[i].fd, SOL_SOCKET, SO_REUSEADDR,
 286:                   (char *)&on, sizeof(on))) {
 287: #ifdef  TEST
 288:             perror("setsockopt SO_REUSEADDR on");
 289: #endif
 290:             syslog(LOG_ERR, "setsockopt SO_REUSEADDR on fails: %m");
 291:         }
 292: 
 293:         /*
 294: 		 * set non-blocking I/O on the descriptor
 295: 		 */
 296:         if (fcntl(addrs[i].fd, F_SETFL, FNDELAY) < 0) {
 297:             syslog(LOG_ERR, "fcntl(FNDELAY) fails: %m");
 298: #ifdef  TEST
 299:             perror("fcntl(F_SETFL, FNDELAY) fails");
 300: #endif
 301:             exit(1);
 302:             /*NOTREACHED*/
 303:         }
 304: 
 305:         /*
 306: 		 * finally, bind the local address address.
 307: 		 */
 308:         addrs[i].sin.sin_family = AF_INET;
 309:         addrs[i].sin.sin_port = port;
 310:         if (bind(addrs[i].fd, (struct sockaddr *)&addrs[i].sin,
 311:              sizeof(addrs[i].sin)) < 0) {
 312:             syslog(LOG_ERR, "bind() fails: %m");
 313: #ifdef  TEST
 314:             perror("bind fails");
 315: #endif
 316:             exit(1);
 317:         }
 318: 
 319:         /*
 320: 		 *  Turn off the SO_REUSEADDR socket option.  It apparently
 321: 		 *  causes heartburn on systems with multicast IP installed.
 322: 		 *  On normal systems it only gets looked at when the address
 323: 		 *  is being bound anyway..
 324: 		 */
 325:         if (setsockopt(addrs[i].fd, SOL_SOCKET, SO_REUSEADDR,
 326:                    (char *)&off, sizeof(off))) {
 327:             syslog(LOG_ERR, "setsockopt SO_REUSEADDR off fails: %m");
 328: #ifdef  TEST
 329:             perror("setsockopt SO_REUSEADDR off");
 330: #endif
 331:         }
 332: 
 333: #ifdef SO_BROADCAST
 334:         /* if this interface can support broadcast, set SO_BROADCAST */
 335:         if (addrs[i].if_flags & IFF_BROADCAST) {
 336:             if (setsockopt(addrs[i].fd, SOL_SOCKET, SO_BROADCAST,
 337:                        (char *)&on, sizeof(on))) {
 338:                 syslog(LOG_ERR, "setsockopt(SO_BROADCAST): %m");
 339: #ifdef  TEST
 340:                 perror("setsockopt(SO_BROADCAST) on");
 341: #endif
 342:             }
 343:         }
 344: #endif /* SO_BROADCAST */
 345:     }
 346:     return nintf;
 347: }
 348: 
 349: #endif

Defined functions

create_sockets defined in line 154; used 3 times
main defined in line 67; never used

Defined variables

RCSid defined in line 2; never used
addrs defined in line 61; used 119 times
nintf defined in line 62; used 54 times

Defined macros

MAX_INTF defined in line 60; used 1 times
  • in line 61
Last modified: 1989-05-19
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4485
Valid CSS Valid XHTML 1.0 Strict