char* canon(Biobuf *bp, char *header, char *body, int *n) { int hsize, base64; static char *raw; hsize = 0; base64 = 0; *header = 0; *body = 0; if(raw == 0){ raw = readmsg(bp, &hsize, n); if(raw) base64 = convert(raw, raw+hsize, header, Hdrsize, 0); } else { free(raw); raw = readmsg(bp, 0, n); } if(raw){ if(base64) conv64(raw+hsize, raw+*n, body, Bodysize); else convert(raw+hsize, raw+*n, body, Bodysize, 1); } return raw; }
void* controler(void *t) //control the game's order. { int i, n, j; struct msgbuf msg; char buf[512], current_user_put_pokers[512], current_round_pokers[512], current_user_claim_pokers[512]; regist(); poker_gen(); poker_sender(); while(1) { memset(current_round_pokers, '\0', sizeof(current_round_pokers)); for(i = 0; i < MAXUSERNUM; i++) { printf("LOG: controler SEND \"TURN\" TO %d\n", connecter_fd[i]); write(connecter_fd[i], "TURN", strlen("TURN")); //read the real pokers msg = readmsg(); strcpy(buf, msg.mtext); printf("LOG: %d-----%s\n", msg.mtype, msg.mtext); sscanf(buf, "%*s%s", current_user_put_pokers); printf("LOG: %d CURRENT_USER_PUT_POKERS: %s\n", connecter_fd[i], current_user_put_pokers); strcat(current_round_pokers, current_user_put_pokers); printf("LOG: %d CURRENT_ROUND_POKERS: %s\n", connecter_fd[i], current_round_pokers); //read the claim pokers msg = readmsg(); strcpy(buf, msg.mtext); printf("LOG: %d-----%s\n", msg.mtype, msg.mtext); sscanf(buf, "%*s%s", current_user_claim_pokers); printf("LOG: %d CURRENT_USER_CLAIM_POKERS: %s\n", connecter_fd[i], current_user_claim_pokers); broadcast(connecter_fd[i], current_user_claim_pokers); //Judge Part judgement(i, current_round_pokers, current_user_put_pokers, current_user_claim_pokers); //Add pokers part, under consideration, add this function further. printf("%s\n", msg.mtext); if (!strcmp(msg.mtext, "OVER")) { printf("GAME OVER, THE WINNER IS %d\n", msg.mtype); break; } } } }
int msglist (void) { int x; if (server) { x = writemsg (MSGLIST); if (x == SCMOK) x = Tprocess (listT,listone); if (x == SCMOK) x = writestring ((char *)NULL); if (x == SCMOK) x = writeint ((int)scantime); if (x == SCMOK) x = writemend (); } else { char *name; int mode,flags,mtime; TREE *t; x = readmsg (MSGLIST); if (x == SCMOK) x = readstring (&name); while (x == SCMOK) { if (name == NULL) break; x = readint (&mode); if (x == SCMOK) x = readint (&flags); if (x == SCMOK) x = readint (&mtime); if (x != SCMOK) break; t = Tinsert (&listT,name,TRUE); free (name); t->Tmode = mode; t->Tflags = flags; t->Tmtime = mtime; x = readstring (&name); } if (x == SCMOK) x = readint ((int *)&scantime); if (x == SCMOK) x = readmend (); } return (x); }
int msgneed (void) { int x; if (server) { char *name; int update; TREE *t; x = readmsg (MSGNEED); if (x == SCMOK) x = readstring (&name); while (x == SCMOK) { if (name == NULL) break; x = readint (&update); if (x != SCMOK) break; t = Tinsert (&needT,name,TRUE); free (name); if (update) t->Tflags |= FUPDATE; x = readstring (&name); } if (x == SCMOK) x = readmend (); } else { x = writemsg (MSGNEED); if (x == SCMOK) x = Tprocess (needT,needone); if (x == SCMOK) x = writestring ((char *)NULL); if (x == SCMOK) x = writemend (); } return (x); }
int msgxpatch (void) { int x; int i; if (server) { x = readmsg (MSGXPATCH); if (x != SCMOK) return (x); x = readint (&xargc); if (x != SCMOK) return (x); xargc += 2; xargv = (char **)calloc (sizeof (char *),(unsigned)xargc+1); if (xargv == NULL) return (SCMERR); for (i = 2; i < xargc; i++) { x = readstring (&xargv[i]); if (x != SCMOK) return (x); } x = readmend (); } else { x = writemsg (MSGXPATCH); if (x != SCMOK) return (x); x = writeint (xargc); if (x != SCMOK) return (x); for (i = 0; i < xargc; i++) { x = writestring (xargv[i]); if (x != SCMOK) return (x); } x = writemend (); } return (x); }
int main(int argc, const char **argv) { unsigned char *sk, *pk, *n, *m, *c; size_t mlen, clen; if (argc < 2) { puts("usage: cbox SK PK NONCE"); return 1; } if (strlen(argv[1]) != crypto_box_SECRETKEYBYTES * 2) errx(1, "bad SK length"); sk = decodehex(argv[1]); if (strlen(argv[2]) != crypto_box_PUBLICKEYBYTES * 2) errx(1, "bad PK length"); pk = decodehex(argv[2]); if (strlen(argv[3]) != crypto_box_NONCEBYTES * 2) errx(1, "bad NONCE length"); n = decodehex(argv[3]); mlen = readmsg(&m); if ((c = calloc(mlen, 1)) == NULL) err(1, NULL); crypto_box(c, m, mlen, n, pk, sk); c += crypto_box_BOXZEROBYTES; clen = mlen - crypto_box_BOXZEROBYTES; if (fwrite(c, 1, clen, stdout) != clen) err(1, NULL); return 0; }
static int socket_recv(CTXTdeclc int *rc, char** buffer, UInteger *buffer_len, int timeout) { SOCKET sock_handle = (SOCKET) ptoc_int(CTXTc 2); if (read_select(sock_handle, timeout)) { *rc = readmsg(sock_handle, buffer, buffer_len); return NORMAL_TERMINATION; } else return TIMED_OUT; }
/* * Acksend implements reliable datagram transmission by using sequence * numbers and retransmission when necessary. * If `name' is ANYADDR, this routine implements reliable broadcast. * * Because this function calls readmsg(), none of its args may be in * a message provided by readmsg(). */ struct tsp * acksend(struct tsp *message, /* this message */ struct sockaddr_in *addr, /* to here */ char *name, int ack, /* look for this ack */ struct netinfo *net, /* receive from this network */ int bad) /* 1=losing patience */ { struct timeval twait; int count; long msec; message->tsp_vers = TSPVERSION; message->tsp_seq = sequence; if (trace) { fprintf(fd, "acksend: to %s: ", (name == ANYADDR ? "broadcast" : name)); print(message, addr); } bytenetorder(message); msec = 200; count = bad ? 1 : 5; /* 5 packets in 6.4 seconds */ answer = NULL; do { if (!answer) { /* do not go crazy transmitting just because the * other guy cannot keep our sequence numbers * straight. */ if (sendto(sock, (char *)message, sizeof(struct tsp), 0, (struct sockaddr*)addr, sizeof(struct sockaddr)) < 0) { trace_sendto_err(addr->sin_addr); break; } } mstotvround(&twait, msec); answer = readmsg(ack, name, &twait, net); if (answer != NULL) { if (answer->tsp_seq != sequence) { if (trace) fprintf(fd,"acksend: seq # %u!=%u\n", answer->tsp_seq, sequence); continue; } break; } msec *= 2; } while (--count > 0); sequence++; return(answer); }
int msgsetup (void) { int x; if (server) { x = readmsg (MSGSETUP); if (x != SCMOK) return (x); if (protver >= 7) { x = readint (&xpatch); if (x != SCMOK) return (x); } else xpatch = FALSE; if (xpatch) { x = readstring (&xuser); if (x != SCMOK) return (x); return (readmend ()); } x = readstring (&collname_g); if (x == SCMOK) x = readint ((int *)&lasttime); if (x == SCMOK) x = readstring (&basedir_g); if (x == SCMOK) x = readint (&basedev); if (x == SCMOK) x = readint (&baseino); if (x == SCMOK) x = readint (&listonly); if (x == SCMOK) x = readint (&newonly); if (x == SCMOK) if (protver < 6) release = (char *)NULL; else x = readstring (&release); if (x == SCMOK) x = readmend (); } else { x = writemsg (MSGSETUP); if (x != SCMOK) return (x); if (protver >= 7) { x = writeint (xpatch); if (x != SCMOK) return (x); } if (xpatch) { x = writestring (xuser); if (x != SCMOK) return (x); return (writemend ()); } if (x == SCMOK) x = writestring (collname_g); if (x == SCMOK) x = writeint ((int)lasttime); if (x == SCMOK) x = writestring (basedir_g); if (x == SCMOK) x = writeint (basedev); if (x == SCMOK) x = writeint (baseino); if (x == SCMOK) x = writeint (listonly); if (x == SCMOK) x = writeint (newonly); if (x == SCMOK && protver >= 6) x = writestring (release); if (x == SCMOK) x = writemend (); } return (x); }
int main(int argc, const char **argv) { unsigned char *m, h[crypto_hash_BYTES]; size_t mlen, i; mlen = readmsg(&m); crypto_hash(h, m, mlen); for (i = 0; i < sizeof(h); i++) printf("%02x", h[i]); return 0; }
int smtpfilter_ctlmsg() { std::string cmd=getcmd(); std::string msg(readmsg()); std::string addr; { const char *address_cstr; if ((address_cstr=is_cmd(cmd.c_str(), "subscribe")) != 0) { addr=returnaddr(msg, address_cstr); } else if ((address_cstr=is_cmd(cmd.c_str(), "alias-subscribe")) != 0) { addr=extract_alias_to_subscribe(msg); } else { std::cerr << "200 Ok" << std::endl; return 0; } } uaddrlower(addr); if (cmdget_s("UNICODE") != "1") { std::string::const_iterator b=addr.begin(), e=addr.end(); while (b != e) { if (*b & 0x80) { std::cerr << "550 This mailing list does not " "accept Unicode E-mail addresses, yet." << std::endl; return EX_SOFTWARE; } ++b; } } std::cerr << "200 Ok" << std::endl; return 0; }
int msglogack (void) { int x; if (server) { x = writemsg (MSGLOGACK); if (x == SCMOK) x = writeint (logack); if (x == SCMOK) x = writestring (logerror); if (x == SCMOK) x = writemend (); } else { x = readmsg (MSGLOGACK); if (x == SCMOK) x = readint (&logack); if (x == SCMOK) x = readstring (&logerror); if (x == SCMOK) x = readmend (); } return (x); }
void serve(Chan *chan) { int i, nin, p9, npid; uint8_t inbuf[1024]; void (*s)(Chan*, uint8_t*, int); int *pid; Waitmsg *w; p9 = 0; if((nin = readmsg(chan, inbuf, sizeof inbuf, &p9)) < 0) return; switch(p9){ default: print("unknown 9P type\n"); return; case 1: s = serve9p1; break; case 2: s = serve9p2; break; } pid = malloc(sizeof(pid)*(conf.nserve-1)); if(pid == nil) return; for(i=1; i<conf.nserve; i++) pid[i-1] = startserveproc(s, "srv", chan, nil, 0); (*s)(chan, inbuf, nin); /* wait till all other servers for this chan are done */ for(npid = conf.nserve-1; npid > 0;){ w = wait(); if(w == 0) break; for(i = 0; i < conf.nserve-1; i++) if(pid[i] == w->pid) npid--; free(w); } free(pid); }
int msglogin (void) { int x; if (server) { x = readmsg (MSGLOGIN); if (x == SCMOK) x = readstring (&logcrypt); if (x == SCMOK) x = readstring (&loguser); if (x == SCMOK) x = readstring (&logpswd); if (x == SCMOK) x = readmend (); } else { x = writemsg (MSGLOGIN); if (x == SCMOK) x = writestring (logcrypt); if (x == SCMOK) x = writestring (loguser); if (x == SCMOK) x = writestring (logpswd); if (x == SCMOK) x = writemend (); } return (x); }
char* canon(Biobuf *bp, char *header, char *body, int *n) { int hsize; char *raw; hsize = 0; *header = 0; *body = 0; raw = readmsg(bp, &hsize, n); if(raw) { if(convert(raw, raw+hsize, header, Hdrsize, 0)) conv64(raw+hsize, raw+*n, body, Bodysize); /* base64 */ else convert(raw+hsize, raw+*n, body, Bodysize, 1); /* text */ } return raw; }
int msgsignon (void) { int x; if (server) { x = readmsg (MSGSIGNON); if (x == SCMOK) x = readint (&protver); if (x == SCMOK) x = readint (&pgmver); if (x == SCMOK) x = readstring (&scmver); if (x == SCMOK) x = readmend (); } else { x = writemsg (MSGSIGNON); if (x == SCMOK) x = writeint (PROTOVERSION); if (x == SCMOK) x = writeint (pgmversion); if (x == SCMOK) x = writestring (scmversion); if (x == SCMOK) x = writemend (); } return (x); }
int msgsignonack () { register int x; if (server) { x = writemsg (MSGSIGNONACK); if (x == SCMOK) x = writeint (PROTOVERSION); if (x == SCMOK) x = writeint (pgmversion); if (x == SCMOK) x = writestring (scmversion); if (x == SCMOK) x = writeint (fspid); if (x == SCMOK) x = writemend (); } else { x = readmsg (MSGSIGNONACK); if (x == SCMOK) x = readint (&protver); if (x == SCMOK) x = readint (&pgmver); if (x == SCMOK) x = readstring (&scmver); if (x == SCMOK) x = readint (&fspid); if (x == SCMOK) x = readmend (); } return (x); }
int msgdone (void) { int x; if (protver < 6) { printf ("Error, msgdone should not have been called."); return (SCMERR); } if (server) { x = readmsg (MSGDONE); if (x == SCMOK) x = readint (&doneack); if (x == SCMOK) x = readstring (&donereason); if (x == SCMOK) x = readmend (); } else { x = writemsg (MSGDONE); if (x == SCMOK) x = writeint (doneack); if (x == SCMOK) x = writestring (donereason); if (x == SCMOK) x = writemend (); } return (x); }
int msgdeny (void) { int x; if (server) { x = writemsg (MSGDENY); if (x == SCMOK) x = Tprocess (denyT,denyone); if (x == SCMOK) x = writestring ((char *)NULL); if (x == SCMOK) x = writemend (); } else { char *name; x = readmsg (MSGDENY); if (x == SCMOK) x = readstring (&name); while (x == SCMOK) { if (name == NULL) break; (void) Tinsert (&denyT,name,FALSE); free (name); x = readstring (&name); } if (x == SCMOK) x = readmend (); } return (x); }
int msgrefuse (void) { int x; if (server) { char *name; x = readmsg (MSGREFUSE); if (x == SCMOK) x = readstring (&name); while (x == SCMOK) { if (name == NULL) break; (void) Tinsert (&refuseT,name,FALSE); free (name); x = readstring (&name); } if (x == SCMOK) x = readmend (); } else { x = writemsg (MSGREFUSE); if (x == SCMOK) x = Tprocess (refuseT,refuseone); if (x == SCMOK) x = writestring ((char *)NULL); if (x == SCMOK) x = writemend (); } return (x); }
void judgement(int start, char* current_round_pokers, char* current_user_put_pokers, char* current_user_claim_pokers) { int i; char buf[512], user_judge[512]; for(i = 1; i < MAXUSERNUM; i++) { write(connecter_fd[(i+start)%MAXUSERNUM], "JUDGE", strlen("JUDGE")); msg = readmsg(); strcpy(buf, msg.mtext); printf("LOG: %d-----%s\n", msg.mtype, msg.mtext); sscanf(buf, "%*s%s", user_judge); broadcast(connecter_fd[(i+start)%MAXUSERNUM], user_judge); if (!strcmp(user_judge, "FALSE")) { sprintf(buf, "%s %s ", "FORCE", current_round_pokers); printf("%d\n", strcmp(current_user_put_pokers, current_user_claim_pokers)); if(strcmp(current_user_put_pokers, current_user_claim_pokers) != 0) write(connecter_fd[start], buf, sizeof(buf)); else write(connecter_fd[(i+start)%MAXUSERNUM], buf, sizeof(buf)); } } }
int main(int argc, const char **argv) { unsigned char *sk, *m, *sm; size_t mlen, n; long long unsigned int smlen; if (argc < 2) { puts("usage: csign PRIVATE_KEY"); return 1; } if (strlen(argv[1]) != crypto_sign_SECRETKEYBYTES * 2) errx(1, "bad key length"); sk = decodehex(argv[1]); mlen = readmsg(&m); if ((sm = calloc(mlen + crypto_sign_BYTES, 1)) == NULL) err(1, NULL); crypto_sign(sm, &smlen, m, mlen, sk); if ((n = fwrite(sm, 1, crypto_sign_BYTES, stdout)) != smlen) err(1, NULL); return 0; }
/* * suppress an upstart, untrustworthy, self-appointed master */ void suppress(struct sockaddr_in *addr, char *name, struct netinfo *net) { struct sockaddr_in tgt; char tname[MAXHOSTNAMELEN]; struct tsp msg; static struct timeval wait; if (trace) fprintf(fd, "suppress: %s\n", name); tgt = *addr; (void)strlcpy(tname, name, sizeof(tname)); while (0 != readmsg(TSP_ANY, ANYADDR, &wait, net)) { if (trace) fprintf(fd, "suppress:\tdiscarded packet from %s\n", name); } syslog(LOG_NOTICE, "suppressing false master %s", tname); msg.tsp_type = TSP_QUIT; (void)strcpy(msg.tsp_name, hostname); (void)acksend(&msg, &tgt, tname, TSP_ACK, 0, 1); }
void main(int argc, char *argv[]) { int len, rcode; char tname[32]; char *err, *ext = ""; unsigned char buf[64*1024], callip[IPaddrlen]; DNSmsg reqmsg, repmsg; Request req; alarm(2*60*1000); cfg.cachedb = 1; ARGBEGIN{ case 'd': debug++; break; case 'f': dbfile = EARGF(usage()); break; case 'r': cfg.resolver = 1; break; case 'R': norecursion = 1; break; case 'x': ext = EARGF(usage()); break; default: usage(); break; }ARGEND if(debug < 2) debug = 0; if(argc > 0) getcaller(argv[0]); cfg.inside = 1; dninit(); snprint(mntpt, sizeof mntpt, "/net%s", ext); if(myipaddr(ipaddr, mntpt) < 0) sysfatal("can't read my ip address"); dnslog("dnstcp call from %s to %I", caller, ipaddr); memset(callip, 0, sizeof callip); parseip(callip, caller); db2cache(1); memset(&req, 0, sizeof req); setjmp(req.mret); req.isslave = 0; procsetname("main loop"); /* loop on requests */ for(;; putactivity(0)){ now = time(nil); memset(&repmsg, 0, sizeof repmsg); len = readmsg(0, buf, sizeof buf); if(len <= 0) break; getactivity(&req, 0); req.aborttime = timems() + S2MS(15*Min); rcode = 0; memset(&reqmsg, 0, sizeof reqmsg); err = convM2DNS(buf, len, &reqmsg, &rcode); if(err){ dnslog("server: input error: %s from %s", err, caller); free(err); break; } if (rcode == 0) { if(reqmsg.qdcount < 1){ dnslog("server: no questions from %s", caller); break; } else if(reqmsg.flags & Fresp){ dnslog("server: reply not request from %s", caller); break; } else if((reqmsg.flags & Omask) != Oquery){ dnslog("server: op %d from %s", reqmsg.flags & Omask, caller); break; } } if(debug) dnslog("[%d] %d: serve (%s) %d %s %s", getpid(), req.id, caller, reqmsg.id, reqmsg.qd->owner->name, rrname(reqmsg.qd->type, tname, sizeof tname)); /* loop through each question */ while(reqmsg.qd) if(reqmsg.qd->type == Taxfr) dnzone(&reqmsg, &repmsg, &req); else { dnserver(&reqmsg, &repmsg, &req, callip, rcode); reply(1, &repmsg, &req); rrfreelist(repmsg.qd); rrfreelist(repmsg.an); rrfreelist(repmsg.ns); rrfreelist(repmsg.ar); } rrfreelist(reqmsg.qd); /* qd will be nil */ rrfreelist(reqmsg.an); rrfreelist(reqmsg.ns); rrfreelist(reqmsg.ar); if(req.isslave){ putactivity(0); _exits(0); } } refreshmain(mntpt); }
int main(int argc, char **argv) { int sl, sa, sc; struct sockaddr_in saddr, clientaddr; struct sockaddr_can caddr; struct ifreq ifr; socklen_t sin_size = sizeof(clientaddr); char buf[100]; struct { struct bcm_msg_head msg_head; struct can_frame frame; } msg; if((sl = socket(PF_INET, SOCK_STREAM, 0)) < 0) { perror("inetsocket"); exit(1); } saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl(INADDR_ANY); saddr.sin_port = htons(28600); while(bind(sl,(struct sockaddr*)&saddr, sizeof(saddr)) < 0) { printf(".");fflush(NULL); usleep(100000); } if (listen(sl,3) != 0) { perror("listen"); exit(1); } while (1) { sa = accept(sl,(struct sockaddr *)&clientaddr, &sin_size); if (sa > 0 ){ if (fork()) close(sa); else break; } else { if (errno != EINTR) { /* * If the cause for the error was NOT the signal from * a dying child, than give an error */ perror("accept"); exit(1); } } } /* open BCM socket */ if ((sc = socket(PF_CAN, SOCK_DGRAM, CAN_BCM)) < 0) { perror("bcmsocket"); return 1; } caddr.can_family = PF_CAN; caddr.can_ifindex = 0; /* any device => need for sendto() */ if (connect(sc, (struct sockaddr *)&caddr, sizeof(caddr)) < 0) { perror("connect"); return 1; } /* prepare stable settings */ msg.msg_head.nframes = 1; msg.msg_head.count = 0; msg.msg_head.ival1.tv_sec = 0; msg.msg_head.ival1.tv_usec = 0; while (1) { char cmd; int items; readmsg(sa, buf, sizeof(buf)); // printf("read '%s'\n", buf); items = sscanf(buf, "< %6s %c %lu %lu %x %hhu " "%hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx >", ifr.ifr_name, &cmd, &msg.msg_head.ival2.tv_sec, &msg.msg_head.ival2.tv_usec, &msg.msg_head.can_id, &msg.frame.can_dlc, &msg.frame.data[0], &msg.frame.data[1], &msg.frame.data[2], &msg.frame.data[3], &msg.frame.data[4], &msg.frame.data[5], &msg.frame.data[6], &msg.frame.data[7]); if (items < 6) break; if (msg.frame.can_dlc > 8) break; if (items != 6 + msg.frame.can_dlc) break; msg.frame.can_id = msg.msg_head.can_id; switch (cmd) { case 'S': msg.msg_head.opcode = TX_SEND; break; case 'A': msg.msg_head.opcode = TX_SETUP; msg.msg_head.flags |= SETTIMER|STARTTIMER; break; case 'U': msg.msg_head.opcode = TX_SETUP; msg.msg_head.flags = 0; break; case 'D': msg.msg_head.opcode = TX_DELETE; break; default: printf("unknown command '%c'.\n", cmd); exit(1); } if (!ioctl(sc, SIOCGIFINDEX, &ifr)) { caddr.can_ifindex = ifr.ifr_ifindex; sendto(sc, &msg, sizeof(msg), 0, (struct sockaddr*)&caddr, sizeof(caddr)); } } close(sc); close(sa); return 0; }
slave() { int length; int senddateack; long electiontime, refusetime, looktime; u_short seq; char candidate[MAXHOSTNAMELEN]; struct tsp *msg, to, *readmsg(); struct sockaddr_in saveaddr, msaveaddr; struct timeval wait; struct timeval time, otime; struct tsp *answer, *acksend(); int timeout(); char *date(); long casual(); int bytenetorder(); char olddate[32]; struct sockaddr_in server; register struct netinfo *ntp; int ind; struct tsp resp; extern int Mflag; extern int justquit; #ifdef MEASURE extern FILE *fp; #endif if (slavenet) { resp.tsp_type = TSP_SLAVEUP; resp.tsp_vers = TSPVERSION; (void)strcpy(resp.tsp_name, hostname); bytenetorder(&resp); if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, &slavenet->dest_addr, sizeof(struct sockaddr_in)) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } } if (status & MASTER) { #ifdef MEASURE if (fp == NULL) { fp = fopen("/usr/adm/timed.masterlog", "w"); setlinebuf(fp); } #endif syslog(LOG_INFO, "THIS MACHINE IS A SUBMASTER"); if (trace) { fprintf(fd, "THIS MACHINE IS A SUBMASTER\n"); } for (ntp = nettab; ntp != NULL; ntp = ntp->next) if (ntp->status == MASTER) masterup(ntp); } else { syslog(LOG_INFO, "THIS MACHINE IS A SLAVE"); if (trace) { fprintf(fd, "THIS MACHINE IS A SLAVE\n"); } } seq = 0; senddateack = OFF; refusetime = 0; (void)gettimeofday(&time, (struct timezone *)0); electiontime = time.tv_sec + delay2; if (Mflag) if (justquit) looktime = time.tv_sec + delay2; else looktime = 1; else looktime = 0; loop: length = sizeof(struct sockaddr_in); (void)gettimeofday(&time, (struct timezone *)0); if (time.tv_sec > electiontime) { if (trace) fprintf(fd, "election timer expired\n"); longjmp(jmpenv, 1); } if (looktime && time.tv_sec > looktime) { if (trace) fprintf(fd, "Looking for nets to master and loops\n"); if (nignorednets > 0) { for (ntp = nettab; ntp != NULL; ntp = ntp->next) { if (ntp->status == IGNORE) { lookformaster(ntp); if (ntp->status == MASTER) masterup(ntp); else ntp->status = IGNORE; } } setstatus(); #ifdef MEASURE /* * Check to see if we just became master * (file not open) */ if (fp == NULL) { fp = fopen("/usr/adm/timed.masterlog", "w"); setlinebuf(fp); } #endif } for (ntp = nettab; ntp != NULL; ntp = ntp->next) { if (ntp->status == MASTER) { to.tsp_type = TSP_LOOP; to.tsp_vers = TSPVERSION; to.tsp_seq = sequence++; to.tsp_hopcnt = 10; (void)strcpy(to.tsp_name, hostname); bytenetorder(&to); if (sendto(sock, (char *)&to, sizeof(struct tsp), 0, &ntp->dest_addr, sizeof(struct sockaddr_in)) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } } } (void)gettimeofday(&time, (struct timezone *)0); looktime = time.tv_sec + delay2; } wait.tv_sec = electiontime - time.tv_sec + 10; wait.tv_usec = 0; msg = readmsg(TSP_ANY, (char *)ANYADDR, &wait, (struct netinfo *)NULL); if (msg != NULL) { switch (msg->tsp_type) { case TSP_SETDATE: #ifdef TESTING case TSP_TEST: #endif case TSP_MSITE: case TSP_TRACEOFF: case TSP_TRACEON: break; case TSP_MASTERUP: if (fromnet == NULL) { if (trace) { fprintf(fd, "slave ignored: "); print(msg, &from); } goto loop; } break; default: if (fromnet == NULL || fromnet->status == IGNORE) { if (trace) { fprintf(fd, "slave ignored: "); print(msg, &from); } goto loop; } break; } switch (msg->tsp_type) { case TSP_ADJTIME: if (fromnet->status != SLAVE) break; (void)gettimeofday(&time, (struct timezone *)0); electiontime = time.tv_sec + delay2; if (seq != msg->tsp_seq) { seq = msg->tsp_seq; if ((status & SUBMASTER) == SUBMASTER) { synch((msg->tsp_time.tv_sec * 1000) + (msg->tsp_time.tv_usec / 1000)); } else { adjclock(&(msg->tsp_time)); } } break; case TSP_SETTIME: if (fromnet->status != SLAVE) break; if (seq == msg->tsp_seq) break; seq = msg->tsp_seq; (void)strcpy(olddate, date()); (void)gettimeofday(&otime, (struct timezone *)0); (void)settimeofday(&msg->tsp_time, (struct timezone *)0); syslog(LOG_NOTICE, "date changed by %s from: %s", msg->tsp_name, olddate); logwtmp(otime, msg->tsp_time); if ((status & SUBMASTER) == SUBMASTER) spreadtime(); (void)gettimeofday(&time, (struct timezone *)0); electiontime = time.tv_sec + delay2; if (senddateack == ON) { senddateack = OFF; msg->tsp_type = TSP_DATEACK; (void)strcpy(msg->tsp_name, hostname); bytenetorder(msg); length = sizeof(struct sockaddr_in); if (sendto(sock, (char *)msg, sizeof(struct tsp), 0, &saveaddr, length) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } } break; case TSP_MASTERUP: if (slavenet && fromnet != slavenet) break; makeslave(fromnet); setstatus(); msg->tsp_type = TSP_SLAVEUP; msg->tsp_vers = TSPVERSION; (void)strcpy(msg->tsp_name, hostname); bytenetorder(msg); answerdelay(); length = sizeof(struct sockaddr_in); if (sendto(sock, (char *)msg, sizeof(struct tsp), 0, &from, length) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } backoff = 1; delay2 = casual((long)MINTOUT, (long)MAXTOUT); (void)gettimeofday(&time, (struct timezone *)0); electiontime = time.tv_sec + delay2; refusetime = 0; break; case TSP_MASTERREQ: if (fromnet->status != SLAVE) break; (void)gettimeofday(&time, (struct timezone *)0); electiontime = time.tv_sec + delay2; break; case TSP_SETDATE: saveaddr = from; msg->tsp_type = TSP_SETDATEREQ; msg->tsp_vers = TSPVERSION; (void)strcpy(msg->tsp_name, hostname); for (ntp = nettab; ntp != NULL; ntp = ntp->next) { if (ntp->status == SLAVE) break; } if (ntp == NULL) break; answer = acksend(msg, &ntp->dest_addr, (char *)ANYADDR, TSP_DATEACK, ntp); if (answer != NULL) { msg->tsp_type = TSP_ACK; bytenetorder(msg); length = sizeof(struct sockaddr_in); if (sendto(sock, (char *)msg, sizeof(struct tsp), 0, &saveaddr, length) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } senddateack = ON; } break; case TSP_SETDATEREQ: saveaddr = from; if (status != SUBMASTER || fromnet->status != MASTER) break; for (ntp = nettab; ntp != NULL; ntp = ntp->next) { if (ntp->status == SLAVE) break; } ind = findhost(msg->tsp_name); if (ind < 0) { syslog(LOG_WARNING, "DATEREQ from uncontrolled machine"); break; } syslog(LOG_DEBUG, "forwarding date change request for %s", msg->tsp_name); (void)strcpy(msg->tsp_name, hostname); answer = acksend(msg, &ntp->dest_addr, (char *)ANYADDR, TSP_DATEACK, ntp); if (answer != NULL) { msg->tsp_type = TSP_DATEACK; bytenetorder(msg); length = sizeof(struct sockaddr_in); if (sendto(sock, (char *)msg, sizeof(struct tsp), 0, &saveaddr, length) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } } break; case TSP_TRACEON: if (!(trace)) { fd = fopen(tracefile, "w"); setlinebuf(fd); fprintf(fd, "Tracing started on: %s\n\n", date()); } trace = ON; break; case TSP_TRACEOFF: if (trace) { fprintf(fd, "Tracing ended on: %s\n", date()); (void)fclose(fd); } #ifdef GPROF moncontrol(0); _mcleanup(); moncontrol(1); #endif trace = OFF; break; case TSP_SLAVEUP: if ((status & MASTER) && fromnet->status == MASTER) { ind = addmach(msg->tsp_name, &from); newslave(ind, msg->tsp_seq); } break; case TSP_ELECTION: if (fromnet->status == SLAVE) { (void)gettimeofday(&time, (struct timezone *)0); electiontime = time.tv_sec + delay2; seq = 0; /* reset sequence number */ if (time.tv_sec < refusetime) msg->tsp_type = TSP_REFUSE; else { msg->tsp_type = TSP_ACCEPT; refusetime = time.tv_sec + 30; } (void)strcpy(candidate, msg->tsp_name); (void)strcpy(msg->tsp_name, hostname); answerdelay(); server = from; answer = acksend(msg, &server, candidate, TSP_ACK, (struct netinfo *)NULL); if (answer == NULL) syslog(LOG_WARNING, "no answer from master candidate\n"); } else { /* fromnet->status == MASTER */ to.tsp_type = TSP_QUIT; (void)strcpy(to.tsp_name, hostname); server = from; answer = acksend(&to, &server, msg->tsp_name, TSP_ACK, (struct netinfo *)NULL); if (answer == NULL) { syslog(LOG_WARNING, "election error: no reply to QUIT"); } else { (void) addmach(msg->tsp_name, &from); } } break; case TSP_CONFLICT: if (fromnet->status != MASTER) break; /* * After a network partition, there can be * more than one master: the first slave to * come up will notify here the situation. */ (void)strcpy(to.tsp_name, hostname); if (fromnet == NULL) break; for(;;) { to.tsp_type = TSP_RESOLVE; answer = acksend(&to, &fromnet->dest_addr, (char *)ANYADDR, TSP_MASTERACK, fromnet); if (answer == NULL) break; to.tsp_type = TSP_QUIT; server = from; msg = acksend(&to, &server, answer->tsp_name, TSP_ACK, (struct netinfo *)NULL); if (msg == NULL) { syslog(LOG_WARNING, "conflict error: no reply to QUIT"); } else { (void) addmach(answer->tsp_name, &from); } } masterup(fromnet); break; case TSP_MSITE: if (!slavenet) break; msaveaddr = from; msg->tsp_type = TSP_MSITEREQ; msg->tsp_vers = TSPVERSION; (void)strcpy(msg->tsp_name, hostname); answer = acksend(msg, &slavenet->dest_addr, (char *)ANYADDR, TSP_ACK, slavenet); if (answer != NULL) { msg->tsp_type = TSP_ACK; length = sizeof(struct sockaddr_in); bytenetorder(msg); if (sendto(sock, (char *)msg, sizeof(struct tsp), 0, &msaveaddr, length) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } } break; case TSP_ACCEPT: case TSP_REFUSE: break; case TSP_RESOLVE: break; case TSP_QUIT: /* become slave */ #ifdef MEASURE if (fp != NULL) { (void)fclose(fp); fp = NULL; } #endif longjmp(jmpenv, 2); break; #ifdef TESTING case TSP_TEST: electiontime = 0; break; #endif case TSP_MSITEREQ: if (status & MASTER) break; if (trace) { fprintf(fd, "garbage: "); print(msg, &from); } break; case TSP_LOOP: /* looking for loops of masters */ if ( !(status & MASTER)) break; if (fromnet->status == SLAVE) { if ( !strcmp(msg->tsp_name, hostname)) { for(;;) { to.tsp_type = TSP_RESOLVE; answer = acksend(&to, &fromnet->dest_addr, (char *)ANYADDR, TSP_MASTERACK, fromnet); if (answer == NULL) break; to.tsp_type = TSP_QUIT; (void)strcpy(to.tsp_name, hostname); server = from; answer = acksend(&to, &server, answer->tsp_name, TSP_ACK, (struct netinfo *)NULL); if (answer == NULL) { syslog(LOG_ERR, "loop kill error"); } else { electiontime = 0; } } } else { if (msg->tsp_hopcnt-- <= 0) break; bytenetorder(msg); ntp = nettab; for (; ntp != NULL; ntp = ntp->next) if (ntp->status == MASTER) if (sendto(sock, (char *)msg, sizeof(struct tsp), 0, &ntp->dest_addr, length) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } } } else { /* * We should not have received this from a net * we are master on. There must be two masters * in this case. */ if (fromnet->my_addr.s_addr == from.sin_addr.s_addr) break; for (;;) { to.tsp_type = TSP_RESOLVE; answer = acksend(&to, &fromnet->dest_addr, (char *)ANYADDR, TSP_MASTERACK, fromnet); if (answer == NULL) break; to.tsp_type = TSP_QUIT; (void)strcpy(to.tsp_name, hostname); server = from; answer = acksend(&to, &server, answer->tsp_name, TSP_ACK, (struct netinfo *)NULL); if (answer == NULL) { syslog(LOG_ERR, "loop kill error2"); } else { (void)addmach(msg->tsp_name, &from); } } } break; default: if (trace) { fprintf(fd, "garbage: "); print(msg, &from); } break; } } goto loop; }
void lookformaster(struct netinfo *ntp) { struct tsp resp, conflict, *answer; struct timeval ntime; char mastername[MAXHOSTNAMELEN]; struct sockaddr_in masteraddr; get_goodgroup(0); ntp->status = SLAVE; /* look for master */ resp.tsp_type = TSP_MASTERREQ; (void)strcpy(resp.tsp_name, hostname); answer = acksend(&resp, &ntp->dest_addr, ANYADDR, TSP_MASTERACK, ntp, 0); if (answer != NULL && !good_host_name(answer->tsp_name)) { suppress(&from, answer->tsp_name, ntp); ntp->status = NOMASTER; answer = NULL; } if (answer == NULL) { /* * Various conditions can cause conflict: races between * two just started timedaemons when no master is * present, or timedaemons started during an election. * A conservative approach is taken. Give up and became a * slave, postponing election of a master until first * timer expires. */ ntime.tv_sec = ntime.tv_usec = 0; answer = readmsg(TSP_MASTERREQ, ANYADDR, &ntime, ntp); if (answer != NULL) { if (!good_host_name(answer->tsp_name)) { suppress(&from, answer->tsp_name, ntp); ntp->status = NOMASTER; } return; } ntime.tv_sec = ntime.tv_usec = 0; answer = readmsg(TSP_MASTERUP, ANYADDR, &ntime, ntp); if (answer != NULL) { if (!good_host_name(answer->tsp_name)) { suppress(&from, answer->tsp_name, ntp); ntp->status = NOMASTER; } return; } ntime.tv_sec = ntime.tv_usec = 0; answer = readmsg(TSP_ELECTION, ANYADDR, &ntime, ntp); if (answer != NULL) { if (!good_host_name(answer->tsp_name)) { suppress(&from, answer->tsp_name, ntp); ntp->status = NOMASTER; } return; } if (Mflag) ntp->status = MASTER; else ntp->status = NOMASTER; return; } ntp->status = SLAVE; (void)strcpy(mastername, answer->tsp_name); masteraddr = from; /* * If network has been partitioned, there might be other * masters; tell the one we have just acknowledged that * it has to gain control over the others. */ ntime.tv_sec = 0; ntime.tv_usec = 300000; answer = readmsg(TSP_MASTERACK, ANYADDR, &ntime, ntp); /* * checking also not to send CONFLICT to ack'ed master * due to duplicated MASTERACKs */ if (answer != NULL && strcmp(answer->tsp_name, mastername) != 0) { conflict.tsp_type = TSP_CONFLICT; (void)strcpy(conflict.tsp_name, hostname); if (!acksend(&conflict, &masteraddr, mastername, TSP_ACK, 0, 0)) { syslog(LOG_ERR, "error on sending TSP_CONFLICT"); } } }
/* * The main function of `master' is to periodically compute the differences * (deltas) between its clock and the clocks of the slaves, to compute the * network average delta, and to send to the slaves the differences between * their individual deltas and the network delta. * While waiting, it receives messages from the slaves (i.e. requests for * master's name, remote requests to set the network time, ...), and * takes the appropriate action. */ int master() { struct hosttbl *htp; long pollingtime; #define POLLRATE 4 int polls; struct timeval wait, ntime; time_t tsp_time_sec; struct tsp *msg, *answer, to; char newdate[32]; struct sockaddr_in taddr; char tname[MAXHOSTNAMELEN]; struct netinfo *ntp; int i; syslog(LOG_NOTICE, "This machine is master"); if (trace) fprintf(fd, "This machine is master\n"); for (ntp = nettab; ntp != NULL; ntp = ntp->next) { if (ntp->status == MASTER) masterup(ntp); } (void)gettimeofday(&ntime, 0); pollingtime = ntime.tv_sec+3; if (justquit) polls = 0; else polls = POLLRATE-1; /* Process all outstanding messages before spending the long time necessary * to update all timers. */ loop: (void)gettimeofday(&ntime, 0); wait.tv_sec = pollingtime - ntime.tv_sec; if (wait.tv_sec < 0) wait.tv_sec = 0; wait.tv_usec = 0; msg = readmsg(TSP_ANY, ANYADDR, &wait, 0); if (!msg) { (void)gettimeofday(&ntime, 0); if (ntime.tv_sec >= pollingtime) { pollingtime = ntime.tv_sec + SAMPLEINTVL; get_goodgroup(0); /* If a bogus master told us to quit, we can have decided to ignore a * network. Therefore, periodically try to take over everything. */ polls = (polls + 1) % POLLRATE; if (0 == polls && nignorednets > 0) { trace_msg("Looking for nets to re-master\n"); for (ntp = nettab; ntp; ntp = ntp->next) { if (ntp->status == IGNORE || ntp->status == NOMASTER) { lookformaster(ntp); if (ntp->status == MASTER) { masterup(ntp); polls = POLLRATE-1; } } if (ntp->status == MASTER && --ntp->quit_count < 0) ntp->quit_count = 0; } if (polls != 0) setstatus(); } synch(0L); for (ntp = nettab; ntp != NULL; ntp = ntp->next) { to.tsp_type = TSP_LOOP; to.tsp_vers = TSPVERSION; to.tsp_seq = sequence++; to.tsp_hopcnt = MAX_HOPCNT; (void)strcpy(to.tsp_name, hostname); bytenetorder(&to); if (sendto(sock, (char *)&to, sizeof(struct tsp), 0, (struct sockaddr*)&ntp->dest_addr, sizeof(ntp->dest_addr)) < 0) { trace_sendto_err(ntp->dest_addr.sin_addr); } } } } else { switch (msg->tsp_type) { case TSP_MASTERREQ: break; case TSP_SLAVEUP: newslave(msg); break; case TSP_SETDATE: /* * XXX check to see it is from ourself */ tsp_time_sec = msg->tsp_time.tv_sec; (void)strcpy(newdate, ctime(&tsp_time_sec)); if (!good_host_name(msg->tsp_name)) { syslog(LOG_NOTICE, "attempted date change by %s to %s", msg->tsp_name, newdate); spreadtime(); break; } mchgdate(msg); (void)gettimeofday(&ntime, 0); pollingtime = ntime.tv_sec + SAMPLEINTVL; break; case TSP_SETDATEREQ: if (!fromnet || fromnet->status != MASTER) break; tsp_time_sec = msg->tsp_time.tv_sec; (void)strcpy(newdate, ctime(&tsp_time_sec)); htp = findhost(msg->tsp_name); if (htp == 0) { syslog(LOG_ERR, "attempted SET DATEREQ by uncontrolled %s to %s", msg->tsp_name, newdate); break; } if (htp->seq == msg->tsp_seq) break; htp->seq = msg->tsp_seq; if (!htp->good) { syslog(LOG_NOTICE, "attempted SET DATEREQ by untrusted %s to %s", msg->tsp_name, newdate); spreadtime(); break; } mchgdate(msg); (void)gettimeofday(&ntime, 0); pollingtime = ntime.tv_sec + SAMPLEINTVL; break; case TSP_MSITE: xmit(TSP_ACK, msg->tsp_seq, &from); break; case TSP_MSITEREQ: break; case TSP_TRACEON: traceon(); break; case TSP_TRACEOFF: traceoff("Tracing ended at %s\n"); break; case TSP_ELECTION: if (!fromnet) break; if (fromnet->status == MASTER) { pollingtime = 0; (void)addmach(msg->tsp_name, &from,fromnet); } taddr = from; (void)strcpy(tname, msg->tsp_name); to.tsp_type = TSP_QUIT; (void)strcpy(to.tsp_name, hostname); answer = acksend(&to, &taddr, tname, TSP_ACK, 0, 1); if (answer == NULL) { syslog(LOG_ERR, "election error by %s", tname); } break; case TSP_CONFLICT: /* * After a network partition, there can be * more than one master: the first slave to * come up will notify here the situation. */ if (!fromnet || fromnet->status != MASTER) break; (void)strcpy(to.tsp_name, hostname); /* The other master often gets into the same state, * with boring results if we stay at it forever. */ ntp = fromnet; /* (acksend() can leave fromnet=0 */ for (i = 0; i < 3; i++) { to.tsp_type = TSP_RESOLVE; (void)strcpy(to.tsp_name, hostname); answer = acksend(&to, &ntp->dest_addr, ANYADDR, TSP_MASTERACK, ntp, 0); if (!answer) break; htp = addmach(answer->tsp_name,&from,ntp); to.tsp_type = TSP_QUIT; msg = acksend(&to, &htp->addr, htp->name, TSP_ACK, 0, htp->noanswer); if (msg == NULL) { syslog(LOG_ERR, "no response from %s to CONFLICT-QUIT", htp->name); } } masterup(ntp); pollingtime = 0; break; case TSP_RESOLVE: if (!fromnet || fromnet->status != MASTER) break; /* * do not want to call synch() while waiting * to be killed! */ (void)gettimeofday(&ntime, (struct timezone *)0); pollingtime = ntime.tv_sec + SAMPLEINTVL; break; case TSP_QUIT: doquit(msg); /* become a slave */ break; case TSP_LOOP: if (!fromnet || fromnet->status != MASTER || !strcmp(msg->tsp_name, hostname)) break; /* * We should not have received this from a net * we are master on. There must be two masters. */ htp = addmach(msg->tsp_name, &from,fromnet); to.tsp_type = TSP_QUIT; (void)strcpy(to.tsp_name, hostname); answer = acksend(&to, &htp->addr, htp->name, TSP_ACK, 0, 1); if (!answer) { syslog(LOG_WARNING, "loop breakage: no reply from %s=%s to QUIT", htp->name, inet_ntoa(htp->addr.sin_addr)); (void)remmach(htp); } case TSP_TEST: if (trace) { fprintf(fd, "\tnets = %d, masters = %d, slaves = %d, ignored = %d\n", nnets, nmasternets, nslavenets, nignorednets); setstatus(); } pollingtime = 0; polls = POLLRATE-1; break; default: if (trace) { fprintf(fd, "garbage message: "); print(msg, &from); } break; } } goto loop; }
int slave() { int tries; long electiontime, refusetime, looktime, looptime, adjtime; u_short seq; long fastelection; #define FASTTOUT 3 struct in_addr cadr; struct timeval otime; struct sockaddr_in taddr; char tname[MAXHOSTNAMELEN]; struct tsp *msg, to; struct timeval ntime, wait, tmptv; time_t tsp_time_sec; struct tsp *answer; int timeout(); char olddate[32]; char newdate[32]; struct netinfo *ntp; struct hosttbl *htp; struct utmpx utx; old_slavenet = 0; seq = 0; refusetime = 0; adjtime = 0; (void)gettimeofday(&ntime, NULL); electiontime = ntime.tv_sec + delay2; fastelection = ntime.tv_sec + FASTTOUT; if (justquit) looktime = electiontime; else looktime = fastelection; looptime = fastelection; if (slavenet) xmit(TSP_SLAVEUP, 0, &slavenet->dest_addr); if (status & MASTER) { for (ntp = nettab; ntp != NULL; ntp = ntp->next) { if (ntp->status == MASTER) masterup(ntp); } } loop: get_goodgroup(0); (void)gettimeofday(&ntime, NULL); if (ntime.tv_sec > electiontime) { if (trace) fprintf(fd, "election timer expired\n"); longjmp(jmpenv, 1); } if (ntime.tv_sec >= looktime) { if (trace) fprintf(fd, "Looking for nets to master\n"); if (Mflag && nignorednets > 0) { for (ntp = nettab; ntp != NULL; ntp = ntp->next) { if (ntp->status == IGNORE || ntp->status == NOMASTER) { lookformaster(ntp); if (ntp->status == MASTER) { masterup(ntp); } else if (ntp->status == MASTER) { ntp->status = NOMASTER; } } if (ntp->status == MASTER && --ntp->quit_count < 0) ntp->quit_count = 0; } makeslave(slavenet); /* prune extras */ setstatus(); } (void)gettimeofday(&ntime, NULL); looktime = ntime.tv_sec + delay2; } if (ntime.tv_sec >= looptime) { if (trace) fprintf(fd, "Looking for loops\n"); for (ntp = nettab; ntp != NULL; ntp = ntp->next) { if (ntp->status == MASTER) { to.tsp_type = TSP_LOOP; to.tsp_vers = TSPVERSION; to.tsp_seq = sequence++; to.tsp_hopcnt = MAX_HOPCNT; (void)strcpy(to.tsp_name, hostname); bytenetorder(&to); if (sendto(sock, (char *)&to, sizeof(struct tsp), 0, (struct sockaddr*)&ntp->dest_addr, sizeof(ntp->dest_addr)) < 0) { trace_sendto_err(ntp->dest_addr.sin_addr); } } } (void)gettimeofday(&ntime, NULL); looptime = ntime.tv_sec + delay2; } wait.tv_sec = min(electiontime,min(looktime,looptime)) - ntime.tv_sec; if (wait.tv_sec < 0) wait.tv_sec = 0; wait.tv_sec += FASTTOUT; wait.tv_usec = 0; msg = readmsg(TSP_ANY, ANYADDR, &wait, 0); if (msg != NULL) { /* * filter stuff not for us */ switch (msg->tsp_type) { case TSP_SETDATE: case TSP_TRACEOFF: case TSP_TRACEON: /* * XXX check to see they are from ourself */ break; case TSP_TEST: case TSP_MSITE: break; case TSP_MASTERUP: if (!fromnet) { if (trace) { fprintf(fd, "slave ignored: "); print(msg, &from); } goto loop; } break; default: if (!fromnet || fromnet->status == IGNORE || fromnet->status == NOMASTER) { if (trace) { fprintf(fd, "slave ignored: "); print(msg, &from); } goto loop; } break; } /* * now process the message */ switch (msg->tsp_type) { case TSP_ADJTIME: if (fromnet != slavenet) break; if (!good_host_name(msg->tsp_name)) { syslog(LOG_NOTICE, "attempted time adjustment by %s", msg->tsp_name); suppress(&from, msg->tsp_name, fromnet); break; } /* * Speed up loop detection in case we have a loop. * Otherwise the clocks can race until the loop * is found. */ (void)gettimeofday(&otime, NULL); if (adjtime < otime.tv_sec) looptime -= (looptime-otime.tv_sec)/2 + 1; setmaster(msg); if (seq != msg->tsp_seq) { seq = msg->tsp_seq; synch(tvtomsround(msg->tsp_time)); } (void)gettimeofday(&ntime, NULL); electiontime = ntime.tv_sec + delay2; fastelection = ntime.tv_sec + FASTTOUT; adjtime = ntime.tv_sec + SAMPLEINTVL*2; break; case TSP_SETTIME: if (fromnet != slavenet) break; if (seq == msg->tsp_seq) break; seq = msg->tsp_seq; /* adjust time for residence on the queue */ (void)gettimeofday(&otime, NULL); adj_msg_time(msg,&otime); /* * the following line is necessary due to syslog * calling ctime() which clobbers the static buffer */ (void)strcpy(olddate, date()); tsp_time_sec = msg->tsp_time.tv_sec; (void)strcpy(newdate, ctime(&tsp_time_sec)); if (!good_host_name(msg->tsp_name)) { syslog(LOG_NOTICE, "attempted time setting by untrusted %s to %s", msg->tsp_name, newdate); suppress(&from, msg->tsp_name, fromnet); break; } setmaster(msg); tmptv.tv_sec = msg->tsp_time.tv_sec; tmptv.tv_usec = msg->tsp_time.tv_usec; timevalsub(&ntime, &tmptv, &otime); if (ntime.tv_sec < MAXADJ && ntime.tv_sec > -MAXADJ) { /* * do not change the clock if we can adjust it */ synch(tvtomsround(ntime)); } else { utx.ut_type = OLD_TIME; gettimeofday(&utx.ut_tv, NULL); pututxline(&utx); (void)settimeofday(&tmptv, 0); utx.ut_type = NEW_TIME; gettimeofday(&utx.ut_tv, NULL); pututxline(&utx); syslog(LOG_NOTICE, "date changed by %s from %s", msg->tsp_name, olddate); if (status & MASTER) spreadtime(); } (void)gettimeofday(&ntime, NULL); electiontime = ntime.tv_sec + delay2; fastelection = ntime.tv_sec + FASTTOUT; /* This patches a bad protocol bug. Imagine a system with several networks, * where there are a pair of redundant gateways between a pair of networks, * each running timed. Assume that we start with a third machine mastering * one of the networks, and one of the gateways mastering the other. * Imagine that the third machine goes away and the non-master gateway * decides to replace it. If things are timed just 'right,' we will have * each gateway mastering one network for a little while. If a SETTIME * message gets into the network at that time, perhaps from the newly * masterful gateway as it was taking control, the SETTIME will loop * forever. Each time a gateway receives it on its slave side, it will * call spreadtime to forward it on its mastered network. We are now in * a permanent loop, since the SETTIME msgs will keep any clock * in the network from advancing. Normally, the 'LOOP' stuff will detect * and correct the situation. However, with the clocks stopped, the * 'looptime' timer cannot expire. While they are in this state, the * masters will try to saturate the network with SETTIME packets. */ looptime = ntime.tv_sec + (looptime-otime.tv_sec)/2-1; break; case TSP_MASTERUP: if (slavenet && fromnet != slavenet) break; if (!good_host_name(msg->tsp_name)) { suppress(&from, msg->tsp_name, fromnet); if (electiontime > fastelection) electiontime = fastelection; break; } makeslave(fromnet); setmaster(msg); setstatus(); answerdelay(); xmit(TSP_SLAVEUP, 0, &from); (void)gettimeofday(&ntime, NULL); electiontime = ntime.tv_sec + delay2; fastelection = ntime.tv_sec + FASTTOUT; refusetime = 0; break; case TSP_MASTERREQ: if (fromnet->status != SLAVE) break; (void)gettimeofday(&ntime, NULL); electiontime = ntime.tv_sec + delay2; break; case TSP_SETDATE: tsp_time_sec = msg->tsp_time.tv_sec; (void)strcpy(newdate, ctime(&tsp_time_sec)); schgdate(msg, newdate); break; case TSP_SETDATEREQ: if (fromnet->status != MASTER) break; tsp_time_sec = msg->tsp_time.tv_sec; (void)strcpy(newdate, ctime(&tsp_time_sec)); htp = findhost(msg->tsp_name); if (0 == htp) { syslog(LOG_WARNING, "DATEREQ from uncontrolled machine"); break; } if (!htp->good) { syslog(LOG_WARNING, "attempted date change by untrusted %s to %s", htp->name, newdate); spreadtime(); break; } schgdate(msg, newdate); break; case TSP_TRACEON: traceon(); break; case TSP_TRACEOFF: traceoff("Tracing ended at %s\n"); break; case TSP_SLAVEUP: newslave(msg); break; case TSP_ELECTION: if (fromnet->status == SLAVE) { (void)gettimeofday(&ntime, NULL); electiontime = ntime.tv_sec + delay2; fastelection = ntime.tv_sec + FASTTOUT; seq = 0; if (!good_host_name(msg->tsp_name)) { syslog(LOG_NOTICE, "suppress election of %s", msg->tsp_name); to.tsp_type = TSP_QUIT; electiontime = fastelection; } else if (cadr.s_addr != from.sin_addr.s_addr && ntime.tv_sec < refusetime) { /* if the candidate has to repeat itself, the old code would refuse it * the second time. That would prevent elections. */ to.tsp_type = TSP_REFUSE; } else { cadr.s_addr = from.sin_addr.s_addr; to.tsp_type = TSP_ACCEPT; refusetime = ntime.tv_sec + 30; } taddr = from; (void)strcpy(tname, msg->tsp_name); (void)strcpy(to.tsp_name, hostname); answerdelay(); if (!acksend(&to, &taddr, tname, TSP_ACK, 0, 0)) syslog(LOG_WARNING, "no answer from candidate %s\n", tname); } else { /* fromnet->status == MASTER */ htp = addmach(msg->tsp_name, &from,fromnet); to.tsp_type = TSP_QUIT; (void)strcpy(to.tsp_name, hostname); if (!acksend(&to, &htp->addr, htp->name, TSP_ACK, 0, htp->noanswer)) { syslog(LOG_ERR, "no reply from %s to ELECTION-QUIT", htp->name); (void)remmach(htp); } } break; case TSP_CONFLICT: if (fromnet->status != MASTER) break; /* * After a network partition, there can be * more than one master: the first slave to * come up will notify here the situation. */ (void)strcpy(to.tsp_name, hostname); /* The other master often gets into the same state, * with boring results. */ ntp = fromnet; /* (acksend() can leave fromnet=0 */ for (tries = 0; tries < 3; tries++) { to.tsp_type = TSP_RESOLVE; answer = acksend(&to, &ntp->dest_addr, ANYADDR, TSP_MASTERACK, ntp, 0); if (answer == NULL) break; htp = addmach(answer->tsp_name,&from,ntp); to.tsp_type = TSP_QUIT; answer = acksend(&to, &htp->addr, htp->name, TSP_ACK, 0, htp->noanswer); if (!answer) { syslog(LOG_WARNING, "conflict error: no reply from %s to QUIT", htp->name); (void)remmach(htp); } } masterup(ntp); break; case TSP_MSITE: if (!slavenet) break; taddr = from; to.tsp_type = TSP_MSITEREQ; to.tsp_vers = TSPVERSION; to.tsp_seq = 0; (void)strcpy(to.tsp_name, hostname); answer = acksend(&to, &slavenet->dest_addr, ANYADDR, TSP_ACK, slavenet, 0); if (answer != NULL && good_host_name(answer->tsp_name)) { setmaster(answer); to.tsp_type = TSP_ACK; (void)strcpy(to.tsp_name, answer->tsp_name); bytenetorder(&to); if (sendto(sock, (char *)&to, sizeof(struct tsp), 0, (struct sockaddr*)&taddr, sizeof(taddr)) < 0) { trace_sendto_err(taddr.sin_addr); } } break; case TSP_MSITEREQ: break; case TSP_ACCEPT: case TSP_REFUSE: case TSP_RESOLVE: break; case TSP_QUIT: doquit(msg); /* become a slave */ break; case TSP_TEST: electiontime = 0; break; case TSP_LOOP: /* looking for loops of masters */ if (!(status & MASTER)) break; if (fromnet->status == SLAVE) { if (!strcmp(msg->tsp_name, hostname)) { /* * Someone forwarded our message back to * us. There must be a loop. Tell the * master of this network to quit. * * The other master often gets into * the same state, with boring results. */ ntp = fromnet; for (tries = 0; tries < 3; tries++) { to.tsp_type = TSP_RESOLVE; answer = acksend(&to, &ntp->dest_addr, ANYADDR, TSP_MASTERACK, ntp,0); if (answer == NULL) break; taddr = from; (void)strcpy(tname, answer->tsp_name); to.tsp_type = TSP_QUIT; (void)strcpy(to.tsp_name, hostname); if (!acksend(&to, &taddr, tname, TSP_ACK, 0, 1)) { syslog(LOG_ERR, "no reply from %s to slave LOOP-QUIT", tname); } else { electiontime = 0; } } (void)gettimeofday(&ntime, NULL); looptime = ntime.tv_sec + FASTTOUT; } else { if (msg->tsp_hopcnt-- < 1) break; bytenetorder(msg); for (ntp = nettab; ntp != 0; ntp = ntp->next) { if (ntp->status == MASTER && 0 > sendto(sock, (char *)msg, sizeof(struct tsp), 0, (struct sockaddr*)&ntp->dest_addr, sizeof(ntp->dest_addr))) trace_sendto_err(ntp->dest_addr.sin_addr); } } } else { /* fromnet->status == MASTER */ /* * We should not have received this from a net * we are master on. There must be two masters, * unless the packet was really from us. */ if (from.sin_addr.s_addr == fromnet->my_addr.s_addr) { if (trace) fprintf(fd,"discarding forwarded LOOP\n"); break; } /* * The other master often gets into the same * state, with boring results. */ ntp = fromnet; for (tries = 0; tries < 3; tries++) { to.tsp_type = TSP_RESOLVE; answer = acksend(&to, &ntp->dest_addr, ANYADDR, TSP_MASTERACK, ntp,0); if (!answer) break; htp = addmach(answer->tsp_name, &from,ntp); to.tsp_type = TSP_QUIT; (void)strcpy(to.tsp_name, hostname); if (!acksend(&to,&htp->addr,htp->name, TSP_ACK, 0, htp->noanswer)) { syslog(LOG_ERR, "no reply from %s to master LOOP-QUIT", htp->name); (void)remmach(htp); } } (void)gettimeofday(&ntime, NULL); looptime = ntime.tv_sec + FASTTOUT; } break; default: if (trace) { fprintf(fd, "garbage message: "); print(msg, &from); } break; } } goto loop; }
void multiplexer(int listener) { fd_set readfds, masterfd; FD_ZERO(&readfds); FD_ZERO(&masterfd); FD_SET(listener, &masterfd); FD_SET(STDIN, &masterfd); int fdmax; socklen_t addrsize; struct sockaddr_storage their_addr; int inbytes, new_fd, var; char outmsg[1024], inmsg[1024]; char incoming_IP[INET6_ADDRSTRLEN]; //Extra size doesn't hurt fdmax = listener; while(1) { readfds = masterfd; if (select(fdmax+1, &readfds, NULL, NULL, NULL) == -1) { perror("select"); exit(4); } for(int i=0; i<=fdmax; i++) { if(FD_ISSET(i, &readfds)) { if(i==listener) { addrsize = sizeof their_addr; if((new_fd = accept(listener, (struct sockaddr *)&their_addr, &addrsize)) == -1) { perror("server: accept error"); } else { char c[1024]; FD_SET(new_fd, &masterfd); // add to master set if (new_fd > fdmax) fdmax = new_fd; inet_ntop(their_addr.ss_family, get_in_addr(&their_addr), incoming_IP, INET6_ADDRSTRLEN); printf("Server received a connection from %s on socket %d\n",incoming_IP, new_fd); getnick(new_fd, c); client_t *cli = (client_t *)malloc(sizeof(client_t)); cli->connfd = new_fd; cli->uid = uid++; sprintf(cli->name, "%s", c); /* Add client to the queue */ queue_add(cli); var = get_index(new_fd); sprintf(outmsg, "%s %s %s", "||| WELCOME",clients[var]->name, "|||\n"); send_private(new_fd, outmsg); sprintf(outmsg, "%s joined the room\n",clients[var]->name); printf("%s", outmsg); //display on server broadcast_msg(new_fd, outmsg, &masterfd, fdmax, listener); } } else if(i == 0) { if(fgets(outmsg, 1023, stdin)==NULL) return ; else { char out[1024]; sprintf(out, "%s %s","[Server] : ", outmsg); broadcast_msg(i, out, &masterfd, fdmax, listener); } } else //Only case left is that a client got some data { var = get_index(i); if(readmsg(i, 1023, inmsg)) { printf("[%s] : %s", clients[var]->name, inmsg); //display on server sprintf(outmsg, "[%s] : %s",clients[var]->name, inmsg); broadcast_msg(i, outmsg, &masterfd, fdmax, listener); } else { printf("%s left the room\n", clients[var]->name); //display on server sprintf(outmsg, "%s %s",clients[var]->name, "left the room\n"); broadcast_msg(i, outmsg, &masterfd, fdmax, listener); FD_CLR(i, &masterfd); close(i); queue_delete(i); } } } } } }