1/* $NetBSD: timed.c,v 1.23 2007/02/04 21:17:01 cbiere Exp $ */ 2 3/*- 4 * Copyright (c) 1985, 1993 The Regents of the University of California. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33#ifndef lint 34__COPYRIGHT("@(#) Copyright (c) 1985, 1993\ 35 The Regents of the University of California. All rights reserved."); 36#endif /* not lint */ 37 38#ifndef lint 39#if 0 40static char sccsid[] = "@(#)timed.c 8.2 (Berkeley) 3/26/95"; 41#else 42__RCSID("$NetBSD: timed.c,v 1.23 2007/02/04 21:17:01 cbiere Exp $"); 43#endif 44#endif /* not lint */ 45 46#define TSPTYPES 47#include "globals.h" 48#include <net/if.h> 49#include <sys/file.h> 50#include <sys/ioctl.h> 51#include <setjmp.h> 52#include "pathnames.h" 53#include <math.h> 54#include <sys/types.h> 55#include <sys/times.h> 56#include <util.h> 57#include <ifaddrs.h> 58#include <err.h> 59 60#ifdef HAVENIS 61#include <netgroup.h> 62#endif 63 64int trace = 0; 65int sock, sock_raw = -1; 66int status = 0; 67u_short sequence; /* sequence number */ 68long delay1; 69long delay2; 70 71int nslavenets; /* nets were I could be a slave */ 72int nmasternets; /* nets were I could be a master */ 73int nignorednets; /* ignored nets */ 74int nnets; /* nets I am connected to */ 75 76FILE *fd; /* trace file FD */ 77 78jmp_buf jmpenv; 79 80struct netinfo *nettab = 0; 81struct netinfo *slavenet; 82int Mflag; 83int justquit = 0; 84int debug; 85 86static struct nets { 87 char *name; 88 in_addr_t net; 89 struct nets *next; 90} *nets = 0; 91 92struct hosttbl hosttbl[NHOSTS+1]; /* known hosts */ 93 94static struct goodhost { /* hosts that we trust */ 95 char name[MAXHOSTNAMELEN+1]; 96 struct goodhost *next; 97 char perm; 98} *goodhosts; 99 100static char *goodgroup; /* net group of trusted hosts */ 101static void checkignorednets(void); 102static void pickslavenet(struct netinfo *); 103static void add_good_host(const char*,char); 104 105 106/* 107 * The timedaemons synchronize the clocks of hosts in a local area network. 108 * One daemon runs as master, all the others as slaves. The master 109 * performs the task of computing clock differences and sends correction 110 * values to the slaves. 111 * Slaves start an election to choose a new master when the latter disappears 112 * because of a machine crash, network partition, or when killed. 113 * A resolution protocol is used to kill all but one of the masters 114 * that happen to exist in segments of a partitioned network when the 115 * network partition is fixed. 116 * 117 * Authors: Riccardo Gusella & Stefano Zatti 118 */ 119 120int 121main(int argc, char *argv[]) 122{ 123 int on; 124 int ret; 125 int nflag, iflag; 126 struct timeval ntime; 127 struct servent *srvp; 128 struct netinfo *ntp; 129 struct netinfo *ntip; 130 struct netinfo *savefromnet; 131 struct netent *nentp; 132 struct nets *nt; 133 struct sockaddr_in server; 134 uint16_t port; 135 int c; 136 extern char *optarg; 137 extern int optind, opterr; 138 struct ifaddrs *ifap, *ifa; 139 140#define IN_MSG "-i and -n make no sense together\n" 141#ifdef HAVENIS 142#define USAGE "[-dtM] [-i net|-n net] [-F host1 host2 ...] [-G netgp]\n" 143#else 144#define USAGE "[-dtM] [-i net|-n net] [-F host1 host2 ...]\n" 145#endif /* HAVENIS */ 146 147 ntip = NULL; 148 149 on = 1; 150 nflag = OFF; 151 iflag = OFF; 152 153 opterr = 0; 154 while ((c = getopt(argc, argv, "Mtdn:i:F:G:P:")) != -1) { 155 switch (c) { 156 case 'M': 157 Mflag = 1; 158 break; 159 160 case 't': 161 trace = 1; 162 break; 163 164 case 'n': 165 if (iflag) 166 errx(EXIT_FAILURE, "%s", IN_MSG); 167 nflag = ON; 168 addnetname(optarg); 169 break; 170 171 case 'i': 172 if (nflag) 173 errx(EXIT_FAILURE, "%s", IN_MSG); 174 iflag = ON; 175 addnetname(optarg); 176 break; 177 178 case 'F': 179 add_good_host(optarg,1); 180 while (optind < argc && argv[optind][0] != '-') 181 add_good_host(argv[optind++], 1); 182 break; 183 184 case 'd': 185 debug = 1; 186 break; 187 case 'G': 188 if (goodgroup != 0) 189 errx(EXIT_FAILURE, "timed: only one net group\n"); 190 goodgroup = optarg; 191 break; 192 default: 193 errx(EXIT_FAILURE, "%s", USAGE); 194 break; 195 } 196 } 197 if (optind < argc) 198 errx(EXIT_FAILURE, "%s", USAGE); 199 200 /* If we care about which machine is the master, then we must 201 * be willing to be a master 202 */ 203 if (0 != goodgroup || 0 != goodhosts) 204 Mflag = 1; 205 206 if (gethostname(hostname, sizeof(hostname)) < 0) 207 err(EXIT_FAILURE, "gethostname"); 208 209 hostname[sizeof(hostname) - 1] = '\0'; 210 self.l_bak = &self; 211 self.l_fwd = &self; 212 self.h_bak = &self; 213 self.h_fwd = &self; 214 self.head = 1; 215 self.good = 1; 216 217 if (goodhosts != 0) /* trust ourself */ 218 add_good_host(hostname,1); 219 220 srvp = getservbyname("timed", "udp"); 221 if (srvp == NULL) 222 errx(EXIT_FAILURE, "unknown service 'timed/udp'\n"); 223 224 port = srvp->s_port; 225 (void)memset(&server, 0, sizeof(server)); 226 server.sin_port = srvp->s_port; 227 server.sin_family = AF_INET; 228 sock = socket(AF_INET, SOCK_DGRAM, 0); 229 if (sock < 0) 230 err(EXIT_FAILURE, "socket"); 231 232 if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) 233 err(EXIT_FAILURE, "setsockopt"); 234 235 if (bind(sock, (struct sockaddr*)(void *)&server, sizeof(server))) { 236 if (errno == EADDRINUSE) 237 errx(EXIT_FAILURE, "time daemon already running\n"); 238 else 239 err(EXIT_FAILURE, "bind"); 240 } 241 242 /* choose a unique seed for random number generation */ 243 (void)gettimeofday(&ntime, 0); 244 srandom((unsigned long)(ntime.tv_sec + ntime.tv_usec)); 245 246 sequence = (u_short)random(); /* initial seq number */ 247 248 /* rounds kernel variable time to multiple of 5 ms. */ 249 ntime.tv_sec = 0; 250 ntime.tv_usec = -((ntime.tv_usec/1000) % 5) * 1000; 251 (void)adjtime(&ntime, (struct timeval *)0); 252 253 for (nt = nets; nt; nt = nt->next) { 254 nentp = getnetbyname(nt->name); 255 if (nentp == 0) { 256 nt->net = inet_network(nt->name); 257 if (nt->net != INADDR_NONE) 258 nentp = getnetbyaddr(nt->net, AF_INET); 259 } 260 if (nentp != 0) 261 nt->net = nentp->n_net; 262 else if (nt->net == INADDR_NONE) 263 errx(EXIT_FAILURE, "unknown net %s\n", nt->name); 264 else if (nt->net == INADDR_ANY) 265 errx(EXIT_FAILURE, "bad net %s\n", nt->name); 266 else 267 warnx("warning: %s unknown in /etc/networks\n", 268 nt->name); 269 270 if (0 == (nt->net & 0xff000000)) 271 nt->net <<= 8; 272 if (0 == (nt->net & 0xff000000)) 273 nt->net <<= 8; 274 if (0 == (nt->net & 0xff000000)) 275 nt->net <<= 8; 276 } 277 if (getifaddrs(&ifap) != 0) 278 err(EXIT_FAILURE, "get interface configuration"); 279 280 ntp = NULL; 281 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 282 if (ifa->ifa_addr->sa_family != AF_INET) 283 continue; 284 if (!ntp) 285 ntp = malloc(sizeof(struct netinfo)); 286 (void)memset(ntp, 0, sizeof(*ntp)); 287 ntp->my_addr=((struct sockaddr_in *)(void *)ifa->ifa_addr)->sin_addr; 288 ntp->status = NOMASTER; 289 290 if ((ifa->ifa_flags & IFF_UP) == 0) 291 continue; 292 if ((ifa->ifa_flags & IFF_BROADCAST) == 0 && 293 (ifa->ifa_flags & IFF_POINTOPOINT) == 0) { 294 continue; 295 } 296 297 ntp->mask = ((struct sockaddr_in *)(void *) 298 ifa->ifa_netmask)->sin_addr.s_addr; 299 300 if (ifa->ifa_flags & IFF_BROADCAST) { 301 ntp->dest_addr = *(struct sockaddr_in *)(void *)ifa->ifa_broadaddr; 302 /* What if the broadcast address is all ones? 303 * So we cannot just mask ntp->dest_addr. */ 304 ntp->net = ntp->my_addr; 305 ntp->net.s_addr &= ntp->mask; 306 } else { 307 ntp->dest_addr = *(struct sockaddr_in *)(void *)ifa->ifa_dstaddr; 308 ntp->net = ntp->dest_addr.sin_addr; 309 } 310 311 ntp->dest_addr.sin_port = port; 312 313 for (nt = nets; nt; nt = nt->next) { 314 if (ntohl(ntp->net.s_addr) == nt->net) 315 break; 316 } 317 if ((nflag && !nt) || (iflag && nt)) 318 continue; 319 320 ntp->next = NULL; 321 if (nettab == NULL) { 322 nettab = ntp; 323 } else { 324 ntip->next = ntp; 325 } 326 ntip = ntp; 327 ntp = NULL; 328 } 329 freeifaddrs(ifap); 330 if (ntp) 331 (void) free(ntp); 332 if (nettab == NULL) 333 errx(EXIT_FAILURE, "no network usable\n"); 334 335 336 /* microseconds to delay before responding to a broadcast */ 337 delay1 = casual(1L, 100*1000L); 338 339 /* election timer delay in secs. */ 340 delay2 = casual((long)MINTOUT, (long)MAXTOUT); 341 342 343 if (!debug) { 344 daemon(debug, 0); 345 pidfile(NULL); 346 } 347 348 if (trace) 349 traceon(); 350 openlog("timed", LOG_PID, LOG_DAEMON); 351 352 /* 353 * keep returning here 354 */ 355 ret = setjmp(jmpenv); 356 savefromnet = fromnet; 357 setstatus(); 358 359 if (Mflag) { 360 switch (ret) { 361 362 case 0: 363 checkignorednets(); 364 pickslavenet(0); 365 break; 366 case 1: 367 /* Just lost our master */ 368 if (slavenet != 0) 369 slavenet->status = election(slavenet); 370 if (!slavenet || slavenet->status == MASTER) { 371 checkignorednets(); 372 pickslavenet(0); 373 } else { 374 makeslave(slavenet); /* prune extras */ 375 } 376 break; 377 378 case 2: 379 /* Just been told to quit */ 380 justquit = 1; 381 pickslavenet(savefromnet); 382 break; 383 } 384 385 setstatus(); 386 if (!(status & MASTER) && sock_raw != -1) { 387 /* sock_raw is not being used now */ 388 (void)close(sock_raw); 389 sock_raw = -1; 390 } 391 392 if (status == MASTER) 393 master(); 394 else 395 slave(); 396 397 } else { 398 if (sock_raw != -1) { 399 (void)close(sock_raw); 400 sock_raw = -1; 401 } 402 403 if (ret) { 404 /* we just lost our master or were told to quit */ 405 justquit = 1; 406 } 407 for (ntp = nettab; ntp != NULL; ntp = ntp->next) { 408 if (ntp->status == MASTER) 409 rmnetmachs(ntp); 410 ntp->status = NOMASTER; 411 } 412 checkignorednets(); 413 pickslavenet(0); 414 setstatus(); 415 416 slave(); 417 } 418 /* NOTREACHED */ 419 return(0); 420} 421 422 423/* suppress an upstart, untrustworthy, self-appointed master 424 */ 425void 426suppress(struct sockaddr_in *addr, char *name, struct netinfo *net) 427{ 428 struct sockaddr_in tgt; 429 char tname[MAXHOSTNAMELEN]; 430 struct tsp msg; 431 static struct timeval wait; 432 433 if (trace) 434 fprintf(fd, "suppress: %s\n", name); 435 tgt = *addr; 436 (void)strlcpy(tname, name, sizeof(tname)); 437 438 while (0 != readmsg(TSP_ANY, ANYADDR, &wait, net)) { 439 if (trace) 440 fprintf(fd, "suppress:\tdiscarded packet from %s\n", 441 name); 442 } 443 444 syslog(LOG_NOTICE, "suppressing false master %s", tname); 445 msg.tsp_type = TSP_QUIT; 446 set_tsp_name(&msg, hostname); 447 (void)acksend(&msg, &tgt, tname, TSP_ACK, 0, 1); 448} 449 450void 451lookformaster(struct netinfo *ntp) 452{ 453 struct tsp resp, conflict, *answer; 454 struct timeval ntime; 455 char mastername[MAXHOSTNAMELEN]; 456 struct sockaddr_in masteraddr; 457 458 get_goodgroup(0); 459 ntp->status = SLAVE; 460 461 /* look for master */ 462 resp.tsp_type = TSP_MASTERREQ; 463 set_tsp_name(&resp, hostname); 464 answer = acksend(&resp, &ntp->dest_addr, ANYADDR, 465 TSP_MASTERACK, ntp, 0); 466 if (answer != 0 && !good_host_name(answer->tsp_name)) { 467 suppress(&from, answer->tsp_name, ntp); 468 ntp->status = NOMASTER; 469 answer = 0; 470 } 471 if (answer == 0) { 472 /* 473 * Various conditions can cause conflict: races between 474 * two just started timedaemons when no master is 475 * present, or timedaemons started during an election. 476 * A conservative approach is taken. Give up and became a 477 * slave, postponing election of a master until first 478 * timer expires. 479 */ 480 ntime.tv_sec = ntime.tv_usec = 0; 481 answer = readmsg(TSP_MASTERREQ, ANYADDR, &ntime, ntp); 482 if (answer != 0) { 483 if (!good_host_name(answer->tsp_name)) { 484 suppress(&from, answer->tsp_name, ntp); 485 ntp->status = NOMASTER; 486 } 487 return; 488 } 489 490 ntime.tv_sec = ntime.tv_usec = 0; 491 answer = readmsg(TSP_MASTERUP, ANYADDR, &ntime, ntp); 492 if (answer != 0) { 493 if (!good_host_name(answer->tsp_name)) { 494 suppress(&from, answer->tsp_name, ntp); 495 ntp->status = NOMASTER; 496 } 497 return; 498 } 499 500 ntime.tv_sec = ntime.tv_usec = 0; 501 answer = readmsg(TSP_ELECTION, ANYADDR, &ntime, ntp); 502 if (answer != 0) { 503 if (!good_host_name(answer->tsp_name)) { 504 suppress(&from, answer->tsp_name, ntp); 505 ntp->status = NOMASTER; 506 } 507 return; 508 } 509 510 if (Mflag) 511 ntp->status = MASTER; 512 else 513 ntp->status = NOMASTER; 514 return; 515 } 516 517 ntp->status = SLAVE; 518 get_tsp_name(answer, mastername, sizeof(mastername)); 519 masteraddr = from; 520 521 /* 522 * If network has been partitioned, there might be other 523 * masters; tell the one we have just acknowledged that 524 * it has to gain control over the others. 525 */ 526 ntime.tv_sec = 0; 527 ntime.tv_usec = 300000; 528 answer = readmsg(TSP_MASTERACK, ANYADDR, &ntime, ntp); 529 /* 530 * checking also not to send CONFLICT to ack'ed master 531 * due to duplicated MASTERACKs 532 */ 533 if (answer != NULL && 534 strcmp(answer->tsp_name, mastername) != 0) { 535 conflict.tsp_type = TSP_CONFLICT; 536 set_tsp_name(&conflict, hostname); 537 if (!acksend(&conflict, &masteraddr, mastername, 538 TSP_ACK, 0, 0)) { 539 syslog(LOG_ERR, 540 "error on sending TSP_CONFLICT"); 541 } 542 } 543} 544 545/* 546 * based on the current network configuration, set the status, and count 547 * networks; 548 */ 549void 550setstatus(void) 551{ 552 struct netinfo *ntp; 553 554 status = 0; 555 nmasternets = nslavenets = nnets = nignorednets = 0; 556 if (trace) 557 fprintf(fd, "Net status:\n"); 558 for (ntp = nettab; ntp != NULL; ntp = ntp->next) { 559 switch ((int)ntp->status) { 560 case MASTER: 561 nmasternets++; 562 break; 563 case SLAVE: 564 nslavenets++; 565 break; 566 case NOMASTER: 567 case IGNORE: 568 nignorednets++; 569 break; 570 } 571 if (trace) { 572 fprintf(fd, "\t%-16s", inet_ntoa(ntp->net)); 573 switch ((int)ntp->status) { 574 case NOMASTER: 575 fprintf(fd, "NOMASTER\n"); 576 break; 577 case MASTER: 578 fprintf(fd, "MASTER\n"); 579 break; 580 case SLAVE: 581 fprintf(fd, "SLAVE\n"); 582 break; 583 case IGNORE: 584 fprintf(fd, "IGNORE\n"); 585 break; 586 default: 587 fprintf(fd, "invalid state %d\n", 588 (int)ntp->status); 589 break; 590 } 591 } 592 nnets++; 593 status |= ntp->status; 594 } 595 status &= ~IGNORE; 596 if (trace) 597 fprintf(fd, 598 "\tnets=%d masters=%d slaves=%d ignored=%d delay2=%ld\n", 599 nnets, nmasternets, nslavenets, nignorednets, (long)delay2); 600} 601 602void 603makeslave(struct netinfo *net) 604{ 605 struct netinfo *ntp; 606 607 for (ntp = nettab; ntp != NULL; ntp = ntp->next) { 608 if (ntp->status == SLAVE && ntp != net) 609 ntp->status = IGNORE; 610 } 611 slavenet = net; 612} 613 614/* 615 * Try to become master over ignored nets.. 616 */ 617static void 618checkignorednets(void) 619{ 620 struct netinfo *ntp; 621 622 for (ntp = nettab; ntp != NULL; ntp = ntp->next) { 623 if (!Mflag && ntp->status == SLAVE) 624 break; 625 626 if (ntp->status == IGNORE || ntp->status == NOMASTER) { 627 lookformaster(ntp); 628 if (!Mflag && ntp->status == SLAVE) 629 break; 630 } 631 } 632} 633 634/* 635 * choose a good network on which to be a slave 636 * The ignored networks must have already been checked. 637 * Take a hint about for a good network. 638 */ 639static void 640pickslavenet(struct netinfo *ntp) 641{ 642 if (slavenet != 0 && slavenet->status == SLAVE) { 643 makeslave(slavenet); /* prune extras */ 644 return; 645 } 646 647 if (ntp == 0 || ntp->status != SLAVE) { 648 for (ntp = nettab; ntp != 0; ntp = ntp->next) { 649 if (ntp->status == SLAVE) 650 break; 651 } 652 } 653 makeslave(ntp); 654} 655 656/* 657 * returns a random number in the range [inf, sup] 658 */ 659long 660casual(long inf, long sup) 661{ 662 double value; 663 664 value = ((double)(random() & 0x7fffffff)) / (0x7fffffff*1.0); 665 return(inf + (sup - inf)*value); 666} 667 668char * 669date(void) 670{ 671 struct timeval tv; 672 time_t t; 673 674 (void)gettimeofday(&tv, (struct timezone *)0); 675 t = tv.tv_sec; 676 return (ctime(&t)); 677} 678 679void 680addnetname(char *name) 681{ 682 struct nets **netlist = &nets; 683 684 while (*netlist) 685 netlist = &((*netlist)->next); 686 *netlist = calloc(1, sizeof **netlist); 687 if (*netlist == NULL) 688 err(EXIT_FAILURE, "malloc failed\n"); 689 (*netlist)->name = name; 690} 691 692/* note a host as trustworthy */ 693static void 694add_good_host(const char* name, 695 char perm) /* 1=not part of the netgroup */ 696{ 697 struct goodhost *ghp; 698 struct hostent *hentp; 699 700 ghp = calloc(1, sizeof(*ghp)); 701 if (!ghp) { 702 syslog(LOG_ERR, "malloc failed"); 703 exit(EXIT_FAILURE); 704 } 705 706 (void)strncpy(&ghp->name[0], name, sizeof(ghp->name)); 707 ghp->next = goodhosts; 708 ghp->perm = perm; 709 goodhosts = ghp; 710 711 hentp = gethostbyname(name); 712 if (NULL == hentp && perm) 713 (void)warnx("unknown host %s\n", name); 714} 715 716 717/* update our image of the net-group of trustworthy hosts 718 */ 719void 720get_goodgroup(int force) 721{ 722# define NG_DELAY (30*60*CLK_TCK) /* 30 minutes */ 723 static unsigned long last_update; 724 static int firsttime; 725 unsigned long new_update; 726 struct goodhost *ghp, **ghpp; 727#ifdef HAVENIS 728 struct hosttbl *htp; 729 const char *mach, *usr, *dom; 730#endif 731 struct tms tm; 732 733 if (firsttime == 0) { 734 last_update = -NG_DELAY; 735 firsttime++; 736 } 737 738 /* if no netgroup, then we are finished */ 739 if (goodgroup == 0 || !Mflag) 740 return; 741 742 /* Do not chatter with the netgroup master too often. 743 */ 744 new_update = times(&tm); 745 if (new_update < last_update + NG_DELAY 746 && !force) 747 return; 748 last_update = new_update; 749 750 /* forget the old temporary entries */ 751 ghpp = &goodhosts; 752 while (0 != (ghp = *ghpp)) { 753 if (!ghp->perm) { 754 *ghpp = ghp->next; 755 free(ghp); 756 } else { 757 ghpp = &ghp->next; 758 } 759 } 760 761#ifdef HAVENIS 762 /* quit now if we are not one of the trusted masters 763 */ 764 if (!innetgr(goodgroup, &hostname[0], 0,0)) { 765 if (trace) 766 (void)fprintf(fd, "get_goodgroup: %s not in %s\n", 767 &hostname[0], goodgroup); 768 return; 769 } 770 if (trace) 771 (void)fprintf(fd, "get_goodgroup: %s in %s\n", 772 &hostname[0], goodgroup); 773 774 /* mark the entire netgroup as trusted */ 775 (void)setnetgrent(goodgroup); 776 while (getnetgrent(&mach,&usr,&dom)) { 777 if (0 != mach) 778 add_good_host(mach,0); 779 } 780 (void)endnetgrent(); 781 782 /* update list of slaves */ 783 for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) { 784 htp->good = good_host_name(&htp->name[0]); 785 } 786#endif /* HAVENIS */ 787} 788 789 790/* see if a machine is trustworthy 791 */ 792int /* 1=trust hp to change our date */ 793good_host_name(char *name) 794{ 795 struct goodhost *ghp = goodhosts; 796 char c; 797 798 if (!ghp || !Mflag) /* trust everyone if no one named */ 799 return 1; 800 801 c = *name; 802 do { 803 if (c == ghp->name[0] 804 && !strcasecmp(name, ghp->name)) 805 return 1; /* found him, so say so */ 806 } while (0 != (ghp = ghp->next)); 807 808 if (!strcasecmp(name,hostname)) /* trust ourself */ 809 return 1; 810 811 return 0; /* did not find him */ 812} 813 814 815