signed evse_cm_slac_match (struct session * session, struct channel * channel, struct message * message) { struct cm_slac_match_request * request = (struct cm_slac_match_request *) (message); struct cm_slac_match_confirm * confirm = (struct cm_slac_match_confirm *) (message); while (readmessage (channel, message, HOMEPLUG_MMV, (CM_SLAC_MATCH | MMTYPE_REQ)) > 0) { if (! memcmp (session->RunID, request->MatchVarField.RunID, sizeof (session->RunID))) { slac_debug (session, 0, __func__, "<-- CM_SLAC_MATCH.REQ"); memcpy (session->PEV_ID, request->MatchVarField.PEV_ID, sizeof (session->PEV_ID)); memcpy (session->PEV_MAC, request->MatchVarField.PEV_MAC, sizeof (session->PEV_MAC)); memcpy (session->RunID, request->MatchVarField.RunID, sizeof (session->RunID)); #if SLAC_DEBUG if (_anyset (session->flags, SLAC_VERBOSE)) { char string [256]; slac_debug (session, 0, __func__, "CM_SLAC_MATCH.REQ.APPLICATION_TYPE %d", request->APPLICATION_TYPE); slac_debug (session, 0, __func__, "CM_SLAC_MATCH.REQ.SECURITY_TYPE %d", request->SECURITY_TYPE); slac_debug (session, 0, __func__, "CM_SLAC_MATCH.REQ.MVFLength %d", LE16TOH (request->MVFLength)); slac_debug (session, 0, __func__, "CM_SLAC_MATCH.REQ.PEV_ID %s", HEXSTRING (string, request->MatchVarField.PEV_ID)); slac_debug (session, 0, __func__, "CM_SLAC_MATCH.REQ.PEV_MAC %s", HEXSTRING (string, request->MatchVarField.PEV_MAC)); slac_debug (session, 0, __func__, "CM_SLAC_MATCH.REQ.EVSE_ID %s", HEXSTRING (string, request->MatchVarField.EVSE_ID)); slac_debug (session, 0, __func__, "CM_SLAC_MATCH.REQ.EVSE_MAC %s", HEXSTRING (string, request->MatchVarField.EVSE_MAC)); slac_debug (session, 0, __func__, "CM_SLAC_MATCH.REQ.RunID %s", HEXSTRING (string, request->MatchVarField.RunID)); } #endif slac_debug (session, 0, __func__, "--> CM_SLAC_MATCH.CNF"); memset (message, 0, sizeof (* message)); EthernetHeader (& confirm->ethernet, session->PEV_MAC, channel->host, channel->type); HomePlugHeader1 (& confirm->homeplug, HOMEPLUG_MMV, (CM_SLAC_MATCH | MMTYPE_CNF)); confirm->APPLICATION_TYPE = session->APPLICATION_TYPE; confirm->SECURITY_TYPE = session->SECURITY_TYPE; confirm->MVFLength = HTOLE16 (sizeof (confirm->MatchVarField)); memcpy (confirm->MatchVarField.PEV_ID, session->PEV_ID, sizeof (confirm->MatchVarField.PEV_ID)); memcpy (confirm->MatchVarField.PEV_MAC, session->PEV_MAC, sizeof (confirm->MatchVarField.PEV_MAC)); memcpy (confirm->MatchVarField.EVSE_ID, session->EVSE_ID, sizeof (confirm->MatchVarField.EVSE_ID)); memcpy (confirm->MatchVarField.EVSE_MAC, session->EVSE_MAC, sizeof (confirm->MatchVarField.EVSE_MAC)); memcpy (confirm->MatchVarField.RunID, session->RunID, sizeof (confirm->MatchVarField.RunID)); memcpy (confirm->MatchVarField.NID, session->NID, sizeof (confirm->MatchVarField.NID)); memcpy (confirm->MatchVarField.NMK, session->NMK, sizeof (confirm->MatchVarField.NMK)); if (sendmessage (channel, message, sizeof (* confirm)) <= 0) { return (slac_debug (session, 1, __func__, CHANNEL_CANTSEND)); } return (0); } } return (slac_debug (session, session->exit, __func__, "<-- CM_SLAC_MATCH.REQ ?")); }
int attack(int s, char *user, char *password, int idx, char *exec) { fd_set fs; int selret, state, len, code; char buffer[2048] = ""; FD_ZERO(&fs); FD_SET(s, &fs); state = SENDUSER; do { selret = select(s + 1, &fs, NULL, NULL, NULL); if (selret > 0 && FD_ISSET(s, &fs)) { memset(buffer, 0, sizeof(buffer)); len = read(s, buffer, sizeof(buffer)); printf("<<< %s\n", buffer); sscanf(buffer, "%d", &code); switch(state) { case SENDUSER: sendlogin(s, user); state = SENDPASS; break; case SENDPASS: sendpassword(s, password); state = DELMESSAGE; break; case DELMESSAGE: delmessage(s); state = PURGEMESSAGE; break; case PURGEMESSAGE: purgemessage(s); state = SENDMESSAGE; break; case SENDMESSAGE: if (code > 500) { fprintf(stderr, "[*] login failed\n"); len = -1; } else if (code == 230) { fprintf(stderr, "[*] sending exploit code ...\n"); sendexploit(s, user, idx, exec); state = READMESSAGE; } break; case READMESSAGE: sleep(5); readmessage(s); state = READING; break; case READING: if (code == 200 && strstr(buffer, "00000") && strstr(buffer, exec)) { printf("[*] done\n"); } break; } } } while (len > 0); }
signed evse_cm_atten_char (struct session * session, struct channel * channel, struct message * message) { struct cm_atten_char_indicate * indicate = (struct cm_atten_char_indicate *) (message); struct cm_atten_char_response * response = (struct cm_atten_char_response *) (message); slac_debug (session, 0, __func__, "--> CM_ATTEN_CHAR.IND"); memset (message, 0, sizeof (* message)); EthernetHeader (& indicate->ethernet, session->PEV_MAC, channel->host, channel->type); HomePlugHeader1 (& indicate->homeplug, HOMEPLUG_MMV, (CM_ATTEN_CHAR | MMTYPE_IND)); indicate->APPLICATION_TYPE = session->APPLICATION_TYPE; indicate->SECURITY_TYPE = session->SECURITY_TYPE; memcpy (indicate->ACVarField.SOURCE_ADDRESS, session->PEV_MAC, sizeof (indicate->ACVarField.SOURCE_ADDRESS)); memcpy (indicate->ACVarField.RunID, session->RunID, sizeof (indicate->ACVarField.RunID)); memset (indicate->ACVarField.SOURCE_ID, 0, sizeof (indicate->ACVarField.SOURCE_ID)); memset (indicate->ACVarField.RESP_ID, 0, sizeof (indicate->ACVarField.RESP_ID)); indicate->ACVarField.NUM_SOUNDS = session->sounds; indicate->ACVarField.ATTEN_PROFILE.NumGroups = session->NumGroups; memcpy (indicate->ACVarField.ATTEN_PROFILE.AAG, session->AAG, session->NumGroups); if (sendmessage (channel, message, sizeof (* indicate)) <= 0) { return (slac_debug (session, 1, __func__, CHANNEL_CANTSEND)); } if (readmessage (channel, message, HOMEPLUG_MMV, (CM_ATTEN_CHAR | MMTYPE_RSP)) > 0) { if (! memcmp (session->RunID, response->ACVarField.RunID, sizeof (session->RunID))) { slac_debug (session, 0, __func__, "<-- CM_ATTEN_CHAR.RSP"); #if SLAC_DEBUG if (_anyset (session->flags, SLAC_VERBOSE)) { char string [256]; slac_debug (session, 0, __func__, "CM_ATTEN_CHAR.RSP.APPLICATION_TYPE %d", response->APPLICATION_TYPE); slac_debug (session, 0, __func__, "CM_ATTEN_CHAR.RSP.SECURITY_TYPE %d", response->SECURITY_TYPE); slac_debug (session, 0, __func__, "CM_ATTEN_CHAR.RSP.ACVarfield.SOURCE_ADDRESS %s", HEXSTRING (string, response->ACVarField.SOURCE_ADDRESS)); slac_debug (session, 0, __func__, "CM_ATTEN_CHAR.RSP.ACVarFIeld.RunID %s", HEXSTRING (string, response->ACVarField.RunID)); slac_debug (session, 0, __func__, "CM_ATTEN_CHAR.RSP.ACVarField.SOURCE_ID %s", HEXSTRING (string, response->ACVarField.SOURCE_ID)); slac_debug (session, 0, __func__, "CM_ATTEN_CHAR.RSP.ACVarField.RESP_ID %s", HEXSTRING (string, response->ACVarField.RESP_ID)); slac_debug (session, 0, __func__, "CM_ATTEN_CHAR.RSP.ACVarField.Result %d", response->ACVarField.Result); } #endif return (0); } } return (slac_debug (session, session->exit, __func__, "<-- CM_ATTEN_CHAR.RSP ?")); }
signed evse_cm_start_atten_char (struct session * session, struct channel * channel, struct message * message) { struct cm_start_atten_char_indicate * indicate = (struct cm_start_atten_char_indicate *) (message); if (readmessage (channel, message, HOMEPLUG_MMV, (CM_START_ATTEN_CHAR | MMTYPE_IND)) > 0) { if (! memcmp (session->RunID, indicate->ACVarField.RunID, sizeof (session->RunID))) { slac_debug (session, 0, __func__, "<-- CM_START_ATTEN_CHAR.IND"); #if SLAC_DEBUG if (_anyset (session->flags, SLAC_VERBOSE)) { char string [256]; slac_debug (session, 0, __func__, "CM_START_ATTEN_CHAR.IND.APPLICATION_TYPE %d", indicate->APPLICATION_TYPE); slac_debug (session, 0, __func__, "CM_START_ATTEN_CHAR.IND.SECURITY_TYPE %d", indicate->SECURITY_TYPE); slac_debug (session, 0, __func__, "CM_START_ATTEN_CHAR.IND.ACVarField.NUM_SOUNDS %d", indicate->ACVarField.NUM_SOUNDS); slac_debug (session, 0, __func__, "CM_START_ATTEN_CHAR.IND.ACVarField.TIME_OUT %d", indicate->ACVarField.TIME_OUT); slac_debug (session, 0, __func__, "CM_START_ATTEN_CHAR.IND.ACVarField.RESP_TYPE %d", indicate->ACVarField.RESP_TYPE); slac_debug (session, 0, __func__, "CM_START_ATTEN_CHAR.IND.ACVarField.FORWARDING_STA %s", HEXSTRING (string, indicate->ACVarField.FORWARDING_STA)); slac_debug (session, 0, __func__, "CM_START_ATTEN_CHAR.IND.ACVarField.RunID %s", HEXSTRING (string, indicate->ACVarField.RunID)); } #endif if (indicate->APPLICATION_TYPE != session->APPLICATION_TYPE) { slac_debug (session, session->exit, __func__, "%s: APPLICATION_TYPE", __func__); } if (indicate->SECURITY_TYPE != session->SECURITY_TYPE) { slac_debug (session, session->exit, __func__, "%s: SECURITY_TYPE", __func__); } session->NUM_SOUNDS = indicate->ACVarField.NUM_SOUNDS; session->TIME_OUT = indicate->ACVarField.TIME_OUT; if (indicate->ACVarField.RESP_TYPE != session->RESP_TYPE) { slac_debug (session, session->exit, __func__, "%s: RESP_TYPE", __func__); } memcpy (session->FORWARDING_STA, indicate->ACVarField.FORWARDING_STA, sizeof (session->FORWARDING_STA)); return (0); } } return (slac_debug (session, session->exit, __func__, "CM_START_ATTEN_CHAR.IND ?")); }
/* ----------------- if dsi->in_write is set attention, tickle (and close?) msg aren't sent. We don't care about tickle */ static void pending_request(DSI *dsi) { /* send pending attention */ /* read msg if any, it could be done in afp_getsrvrmesg */ if (dsi->msg_request) { if (dsi->msg_request == 2) { /* didn't send it in signal handler */ dsi_attention(AFPobj->handle, AFPATTN_MESG | AFPATTN_TIME(5)); } dsi->msg_request = 0; readmessage(AFPobj); } if (dsi->down_request) { dsi->down_request = 0; dsi_attention(AFPobj->handle, AFPATTN_SHUTDOWN | AFPATTN_NORECONNECT | AFPATTN_MESG | AFPATTN_TIME(5)); } }
// // read in the mailbox and parse into messages. // static char* _readmbox(Mailbox *mb, int doplumb, Mlock *lk) { int fd, n; String *tmp; Dir *d; static char err[128]; Message *m, **l; Inbuf *inb; char *x; l = &mb->root->part; /* * open the mailbox. If it doesn't exist, try the temporary one. */ n = 0; retry: fd = open(mb->path, OREAD); if(fd < 0){ rerrstr(err, sizeof(err)); if(strstr(err, "exclusive lock") != 0 && n++ < 20){ sleep(500); /* wait for lock to go away */ goto retry; } if(strstr(err, "exist") != 0){ tmp = s_copy(mb->path); s_append(tmp, ".tmp"); if(sysrename(s_to_c(tmp), mb->path) == 0){ s_free(tmp); goto retry; } s_free(tmp); } return err; } /* * a new qid.path means reread the mailbox, while * a new qid.vers means read any new messages */ d = dirfstat(fd); if(d == nil){ close(fd); errstr(err, sizeof(err)); return err; } if(mb->d != nil){ if(d->qid.path == mb->d->qid.path && d->qid.vers == mb->d->qid.vers){ close(fd); free(d); return nil; } if(d->qid.path == mb->d->qid.path){ while(*l != nil) l = &(*l)->next; seek(fd, mb->d->length, 0); } free(mb->d); } mb->d = d; mb->vers++; henter(PATH(0, Qtop), mb->name, (Qid){PATH(mb->id, Qmbox), mb->vers, QTDIR}, nil, mb); inb = emalloc(sizeof(Inbuf)); inb->rptr = inb->wptr = inb->data; inb->fd = fd; // read new messages snprint(err, sizeof err, "reading '%s'", mb->path); logmsg(err, nil); for(;;){ if(lk != nil) syslockrefresh(lk); m = newmessage(mb->root); m->mallocd = 1; m->inmbox = 1; if(readmessage(m, inb) < 0){ delmessage(mb, m); mb->root->subname--; break; } // merge mailbox versions while(*l != nil){ if(memcmp((*l)->digest, m->digest, SHA1dlen) == 0){ // matches mail we already read, discard logmsg("duplicate", *l); delmessage(mb, m); mb->root->subname--; m = nil; l = &(*l)->next; break; } else { // old mail no longer in box, mark deleted logmsg("disappeared", *l); if(doplumb) mailplumb(mb, *l, 1); (*l)->inmbox = 0; (*l)->deleted = 1; l = &(*l)->next; } } if(m == nil) continue; x = strchr(m->start, '\n'); if(x == nil) m->header = m->end; else m->header = x + 1; m->mheader = m->mhend = m->header; parseunix(m); parse(m, 0, mb, 0); logmsg("new", m); /* chain in */ *l = m; l = &m->next; if(doplumb) mailplumb(mb, m, 0); } logmsg("mbox read", nil); // whatever is left has been removed from the mbox, mark deleted while(*l != nil){ if(doplumb) mailplumb(mb, *l, 1); (*l)->inmbox = 0; (*l)->deleted = 1; l = &(*l)->next; } close(fd); free(inb); return nil; }
/********************************************************************** * edit room description * Ask user if they want to edit <R>oom aide only, <D>escription only, * <B>oth, or <Q>uit. * Contingent on option chosen, edit the item(s). When done, write * the description to the descfile. * raname is taken either from reading the description or set anew. * If a new aide is chosen, read his/her user file and assign ->usernum * to be roomaide. **********************************************************************/ void editdesc(void) { char choice = '0'; char descfile[100]; char newdescfile[100]; int dfd; /* desc file descriptor */ int dummy; /* readmsg() needs this: returns YES/NO */ int err; /* makemessage returns this */ char raname[MAXALIAS+1]; int upload; char *cp; struct mheader *mh; int size; unsigned char *infop; struct user *tmpuser; sprintf(descfile, "%sroom%d", DESCDIR, curr); sprintf(newdescfile, "%sroom%d.NEW", DESCDIR, curr); size = 0; if (!(infop = (unsigned char *)mymmap(descfile, &size, 0)) || !size) { colorize("@RDescription doesn't yet exist@G\n"); choice = 'B'; } else { readmessage(infop, &dummy, raname, FALSE, 0); munmap((void *)infop, size); } /* if it's a new description, don't bother prompting for choice */ if (choice != 'B') { printf("\nEdit <F>orum moderator only, <D>escription only, <B>oth, <Q>uit -> "); choice = get_single_quiet("FDBQ \n"); putchar('\n'); } if (choice == 'Q' || choice == ' ' || choice == '\n') return; if (choice == 'B' || choice == 'F') { cp = get_name("\nNew forum moderator -> ", 2); if (!*cp) return; if (!strcmp(cp, "Sysop")) msg->room[curr].roomaide = 0; else if (!(tmpuser = getuser(cp)) || tmpuser->f_invisible) { if (tmpuser) freeuser(tmpuser); printf("\nThere is no user %s on this BBS.\n", cp); return; } else { msg->room[curr].roomaide = tmpuser->usernum; freeuser(tmpuser); } if (choice == 'F') return; } printf("\nHit Y to upload a description or N to enter it normally (Y/N) -> "); if ((upload = yesno(-1))) printf("\n(Use control-D to end!)\n"); printf("\nEnter a new forum description...\n\n"); err = makemessage(NULL, MES_DESC, upload); if (err == ABORT) colorize("@RDescription not entered\n@G"); else if (err != SAVE) colorize("@RSome mystical error - can't make description\n@G"); else if ((dfd = open(newdescfile, O_WRONLY | O_CREAT | O_EXCL, 0640)) < 0) printf("error opening desc file to make final copy\n"); else { mh = (struct mheader *)(void *)tmpstart; write(dfd, tmpstart, mh->hlen + mh->len + 1); close(dfd); rename(newdescfile, descfile); } munmap((void *)tmpstart, 53248); if (err == SAVE) { printf("\nMark forum info as having been updated? (Y/N) -> "); if (yesno(-1)) msg->room[curr].descupdate = msg->room[curr].highest; } }
signed pev_cm_slac_param (struct session * session, struct channel * channel, struct message * message) { extern byte const broadcast [ETHER_ADDR_LEN]; struct cm_slac_param_request * request = (struct cm_slac_param_request *) (message); struct cm_slac_param_confirm * confirm = (struct cm_slac_param_confirm *) (message); slac_debug (session, 0, __func__, "--> CM_SLAC_PARAM.REQ"); memset (message, 0, sizeof (* message)); EthernetHeader (& request->ethernet, broadcast, channel->host, channel->type); HomePlugHeader1 (& request->homeplug, HOMEPLUG_MMV, (CM_SLAC_PARAM | MMTYPE_REQ)); request->APPLICATION_TYPE = session->APPLICATION_TYPE; request->SECURITY_TYPE = session->SECURITY_TYPE; memcpy (request->RunID, session->RunID, sizeof (request->RunID)); request->CipherSuite [0] = HTOLE16 ((uint16_t) (session->counter)); if (sendmessage (channel, message, (ETHER_MIN_LEN - ETHER_CRC_LEN)) <= 0) { return (slac_debug (session, 1, __func__, CHANNEL_CANTSEND)); } while (readmessage (channel, message, HOMEPLUG_MMV, (CM_SLAC_PARAM | MMTYPE_CNF)) > 0) { if (! memcmp (session->RunID, confirm->RunID, sizeof (session->RunID))) { slac_debug (session, 0, __func__, "<-- CM_SLAC_PARAM.CNF"); if (confirm->APPLICATION_TYPE != session->APPLICATION_TYPE) { slac_debug (session, session->exit, __func__, "Unexpected APPLICATION_TYPE"); } if (confirm->SECURITY_TYPE != session->SECURITY_TYPE) { slac_debug (session, session->exit, __func__, "Unexpected SECURITY_TYPE"); } if (_anyset (session->flags, SLAC_COMPARE)) { if (LE16TOH (confirm->CipherSuite) != (uint16_t) (session->counter)) { slac_debug (session, session->exit, __func__, "session->counter mismatch! PEV=(%d) EVSE=(%d)", LE16TOH (confirm->CipherSuite), session->counter); } } #if SLAC_DEBUG if (_anyset (session->flags, SLAC_VERBOSE)) { char string [256]; slac_debug (session, 0, __func__, "CM_SLAC_PARAM.CNF.MSOUND_TARGET %s", HEXSTRING (string, confirm->MSOUND_TARGET)); slac_debug (session, 0, __func__, "CM_SLAC_PARAM.CNF.NUM_SOUNDS %d", confirm->NUM_SOUNDS); slac_debug (session, 0, __func__, "CM_SLAC_PARAM.CNF.TIME_OUT %d", confirm->TIME_OUT); slac_debug (session, 0, __func__, "CM_SLAC_PARAM.CNF.RESP_TYPE %d", confirm->RESP_TYPE); slac_debug (session, 0, __func__, "CM_SLAC_PARAM.CNF.FORWARDING_STA %s", HEXSTRING (string, confirm->FORWARDING_STA)); slac_debug (session, 0, __func__, "CM_SLAC_PARAM.CNF.APPLICATION_TYPE %d", confirm->APPLICATION_TYPE); slac_debug (session, 0, __func__, "CM_SLAC_PARAM.CNF.SECURITY_TYPE %d", confirm->SECURITY_TYPE); slac_debug (session, 0, __func__, "CM_SLAC_PARAM.CNF.RunID %s", HEXSTRING (string, confirm->RunID)); slac_debug (session, 0, __func__, "CM_SLAC_PARAM.CNF.CipherSuite %d", confirm->CipherSuite); } #endif memcpy (session->FORWARDING_STA, confirm->FORWARDING_STA, sizeof (session->FORWARDING_STA)); memcpy (session->MSOUND_TARGET, confirm->MSOUND_TARGET, sizeof (session->MSOUND_TARGET)); session->NUM_SOUNDS = confirm->NUM_SOUNDS; session->TIME_OUT = confirm->TIME_OUT; session->RESP_TYPE = confirm->RESP_TYPE; return (0); } } return (slac_debug (session, 0, __func__, "<-- CM_SLAC_PARAM.CNF ?")); }
int bbftp_list(char *line,char **filelist,int *filelistlen,int *errcode) { char minbuffer[MINMESSLEN] ; int msglen ; int code ; struct message *msg ; struct mess_integer *msg_integer ; fd_set selectmask ; /* Select mask */ int nfds ; /* Max number of file descriptor */ char *buffer ; int retcode ; if ( verbose) printmessage(stdout,CASE_NORMAL,0,timestamp,">> COMMAND : list %s\n",line) ; msg = (struct message *)minbuffer ; msg->code = MSG_LIST_V2 ; #ifndef WORDS_BIGENDIAN msg->msglen = ntohl(strlen(line)+sizeof(int)) ; #else msg->msglen = strlen(line)+sizeof(int) ; #endif if ( writemessage(outcontrolsock,minbuffer,MINMESSLEN,sendcontrolto,0) < 0 ) { /* ** We were not able to send the minimum message so ** we are going to close the control socket and to ** tell the calling program to restart a connection */ printmessage(stderr,CASE_ERROR,64,timestamp,"Error sending %s message\n","MSG_LIST_V2"); *errcode = 64 ; bbftp_free_all_var() ; bbftp_close_control() ; return BB_RET_CONN_BROKEN ; /* restart connection */ } /* ** Sending transfer options */ msg_integer = (struct mess_integer*)minbuffer ; msg_integer->myint = transferoption ; if ( writemessage(outcontrolsock,minbuffer,sizeof(int),sendcontrolto,0) < 0 ) { printmessage(stderr,CASE_ERROR,64,timestamp,"Error sending %s message\n","MSG_LIST_V2 (transferoption)"); *errcode = 64 ; bbftp_close_control() ; return BB_RET_CONN_BROKEN ; /* restart connection */ } /* ** Directory name */ if ( writemessage(outcontrolsock,line,strlen(line),sendcontrolto,0) < 0 ) { printmessage(stderr,CASE_ERROR,64,timestamp,"Error sending %s message\n","MSG_LIST_V2 (directory name)"); *errcode = 64 ; bbftp_close_control() ; return BB_RET_CONN_BROKEN ; /* restart connection */ } /* ** Now we are going to wait for the message on the control ** connection */ waitcontrol: nfds = sysconf(_SC_OPEN_MAX) ; FD_ZERO(&selectmask) ; FD_SET(incontrolsock,&selectmask) ; retcode = select(FD_SETSIZE,&selectmask,0,0,0) ; if ( retcode < 0 ) { /* ** Select error */ if ( errno != EINTR ) { /* ** we have got an error so close the connection ** and restart */ printmessage(stderr,CASE_ERROR,66,timestamp,"Error select on control connection : %s\n",strerror(errno)); *errcode = 66 ; bbftp_close_control() ; return BB_RET_CONN_BROKEN ; } else { /* ** Interrupted by a signal */ FD_ZERO(&selectmask) ; FD_SET(incontrolsock,&selectmask) ; goto waitcontrol ; } } else if ( retcode == 0 ) { /* ** Impossible we do not set any timer */ FD_ZERO(&selectmask) ; FD_SET(incontrolsock,&selectmask) ; goto waitcontrol ; } else { /* ** read the message */ if ( readmessage(incontrolsock,minbuffer,MINMESSLEN,recvcontrolto,0) < 0 ) { printmessage(stderr,CASE_ERROR,61,timestamp,"Error waiting %s message\n","MSG_OK (on MSG_LIST_V2)"); *errcode = 61 ; bbftp_close_control() ; return BB_RET_CONN_BROKEN ; } code = msg->code ; if ( code == MSG_BAD || code == MSG_BAD_NO_RETRY) { /* ** The change directory has failed so ... */ #ifndef WORDS_BIGENDIAN msglen = ntohl(msg->msglen) ; #else msglen = msg->msglen ; #endif if ( (buffer = (char *) malloc(msglen+1) ) == NULL) { printmessage(stderr,CASE_ERROR,35,timestamp,"Error allocating memory for %s : %s\n","buffer (bbftp_list)",strerror(errno)) ; *errcode = 35 ; bbftp_close_control() ; return BB_RET_CONN_BROKEN ; } if ( readmessage(incontrolsock,buffer,msglen,recvcontrolto,0) < 0 ) { printmessage(stderr,CASE_ERROR,67,timestamp,"Error reading data for %s message\n","MSG_BAD (on MSG_LIST_V2)"); *errcode = 67 ; bbftp_close_control() ; free(buffer) ; if ( code == MSG_BAD ) { return BB_RET_CONN_BROKEN ; } else { return BB_RET_FT_NR_CONN_BROKEN ; } } else { buffer[msglen] = '\0' ; printmessage(stderr,CASE_ERROR,100,timestamp,"%s\n",buffer) ; if (verbose) printmessage(stdout,CASE_NORMAL,0,timestamp,"<< %s\n",buffer) ; free(buffer) ; if ( code == MSG_BAD ) { *errcode = 100 ; return BB_RET_ERROR; } else { /* ** In case of no retry we are going to wait 2 seconds ** in order for the server to finish its cleaning (in ** fact if the error message is du to a server child ** abnormal termination, the message is sent on the death ** of the first child and the server has some cleaning ** to do). */ sleep(2) ; *errcode = 100 ; return BB_RET_FT_NR ; } } } else if (msg->code == MSG_LIST_REPL_V2 ) { /* ** At this stage the transfer is OK but we need ** the answer because it gives all file names */ #ifndef WORDS_BIGENDIAN msglen = ntohl(msg->msglen) ; #else msglen = msg->msglen ; #endif if ( msglen == 0 ) { /* ** There was no file corresponding */ if ( verbose) printmessage(stdout,CASE_NORMAL,0,timestamp,"<< OK : no file\n") ; *filelistlen = 0 ; return BB_RET_OK ; } else { if ( ((*filelist) = (char *) malloc(msglen+1) ) == NULL) { printmessage(stderr,CASE_ERROR,35,timestamp,"Error allocating memory for %s : %s\n","filelist (bbftp_list)",strerror(errno)) ; *errcode = 35 ; bbftp_close_control() ; return BB_RET_CONN_BROKEN ; } if ( readmessage(incontrolsock,*filelist,msglen,recvcontrolto,0) < 0) { printmessage(stderr,CASE_ERROR,67,timestamp,"Error reading data for %s message\n","MSG_LIST_REPL_V2 (on MSG_LIST_V2)"); *errcode = 67 ; bbftp_close_control() ; free(*filelist) ; return BB_RET_CONN_BROKEN ; } (*filelist)[msglen] = '\0' ; *filelistlen = msglen ; if ( verbose ) printmessage(stdout,CASE_NORMAL,0,timestamp,"<< OK\n") ; return BB_RET_OK ; } } else { /* ** Receive unkwown message so something is ** going wrong. close the control socket ** and restart */ printmessage(stderr,CASE_ERROR,62,timestamp,"Unknown message while waiting for %s message\n","MSG_OK (on MSG_MKDIR_V2)"); *errcode = 62 ; bbftp_close_control() ; return BB_RET_CONN_BROKEN ; } } }
int main(int argc, char **argv) { bool noheader = FALSE; /* set if don't want header */ bool headeronly = FALSE; /* set if only want header */ bool examine = FALSE; /* set if examine a character */ time_t seconds; /* for time of day */ double dtemp; /* for temporary calculations */ initialstate(); /* init globals */ /* process arguments */ while (--argc && (*++argv)[0] == '-') switch ((*argv)[1]) { case 's': /* short */ noheader = TRUE; break; case 'H': /* Header */ headeronly = TRUE; break; case 'a': /* all users */ activelist(); cleanup(TRUE); /* NOTREACHED */ case 'p': /* purge old players */ purgeoldplayers(); cleanup(TRUE); /* NOTREACHED */ case 'S': /* set 'Wizard' */ Wizard = !getuid(); break; case 'x': /* examine */ examine = TRUE; break; case 'm': /* monsters */ monstlist(); cleanup(TRUE); /* NOTREACHED */ case 'b': /* scoreboard */ scorelist(); cleanup(TRUE); /* NOTREACHED */ } if (!isatty(0)) /* don't let non-tty's play */ cleanup(TRUE); /* NOTREACHED */ playinit(); /* set up to catch signals, init curses */ if (examine) { changestats(FALSE); cleanup(TRUE); /* NOTREACHED */ } if (!noheader) { titlelist(); purgeoldplayers(); /* clean up old characters */ } if (headeronly) cleanup(TRUE); /* NOTREACHED */ do { /* get the player structure filled */ Fileloc = -1L; mvaddstr(22, 17, "Do you have a character to run [Q = Quit] ? "); switch (getanswer("NYQ", FALSE)) { case 'Y': Fileloc = recallplayer(); break; case 'Q': cleanup(TRUE); /* NOTREACHED */ default: Fileloc = rollnewplayer(); break; } clear(); } while (Fileloc < 0L); if (Player.p_level > 5.0) /* low level players have long timeout */ Timeout = TRUE; /* update some important player statistics */ strcpy(Player.p_login, Login); time(&seconds); Player.p_lastused = localtime(&seconds)->tm_yday; Player.p_status = S_PLAYING; writerecord(&Player, Fileloc); Statptr = &Stattable[Player.p_type]; /* initialize pointer */ /* catch interrupts */ #ifdef BSD41 sigset(SIGINT, interrupt); #endif #ifdef BSD42 signal(SIGINT, interrupt); #endif #ifdef SYS3 signal(SIGINT, interrupt); #endif #ifdef SYS5 signal(SIGINT, interrupt); #endif altercoordinates(Player.p_x, Player.p_y, A_FORCED); /* set some flags */ clear(); for (;;) { /* loop forever, processing input */ adjuststats(); /* cleanup stats */ if (Throne && Player.p_crowns == 0 && Player.p_specialtype != SC_KING) { /* not allowed on throne -- move */ mvaddstr(5, 0, "You're not allowed in the Lord's Chamber without a crown.\n"); altercoordinates(0.0, 0.0, A_NEAR); } checktampered(); /* check for energy voids, etc. */ if (Player.p_status != S_CLOAKED /* not cloaked */ && (dtemp = fabs(Player.p_x)) == fabs(Player.p_y) /* |x| = |y| */ && !Throne) { /* not on throne */ dtemp = sqrt(dtemp / 100.0); if (floor(dtemp) == dtemp) { /* |x| / 100 == n*n; at a trading post */ tradingpost(); clear(); } } checkbattle(); /* check for player to player battle */ neatstuff(); /* gurus, medics, etc. */ if (Player.p_status == S_CLOAKED) { /* costs 3 mana per turn to be cloaked */ if (Player.p_mana > 3.0) Player.p_mana -= 3.0; else { /* ran out of mana, uncloak */ Player.p_status = S_PLAYING; Changed = TRUE; } } if (Player.p_status != S_PLAYING && Player.p_status != S_CLOAKED) { /* change status back to S_PLAYING */ Player.p_status = S_PLAYING; Changed = TRUE; } if (Changed) { /* update file only if important stuff has changed */ writerecord(&Player, Fileloc); Changed = FALSE; continue; } readmessage(); /* read message, if any */ displaystats(); /* print statistics */ move(6, 0); if (Throne) /* maybe make king, print prompt, etc. */ throneroom(); /* print status line */ addstr("1:Move 2:Players 3:Talk 4:Stats 5:Quit "); if (Player.p_level >= MEL_CLOAK && Player.p_magiclvl >= ML_CLOAK) addstr("6:Cloak "); if (Player.p_level >= MEL_TELEPORT && Player.p_magiclvl >= ML_TELEPORT) addstr("7:Teleport "); if (Player.p_specialtype >= SC_COUNCIL || Wizard) addstr("8:Intervene "); procmain(); /* process input */ } }
int createadir(int code, int msglen) { char receive_buffer[MAXMESSLEN] ; int savederrno ; char logmessage[256] ; #ifndef WORDS_BIGENDIAN msglen = ntohl(msglen) ; #endif if ( msglen > MAXMESSLEN ) { /* ** In order to avoid buffer overflow we reject message to ** big */ syslog(BBFTPD_ERR,"Message to big in createdir (%d,%d)",msglen,MAXMESSLEN) ; reply(MSG_BAD_NO_RETRY,"Directory too long") ; return -1 ; } /* ** Read the characteristics of the directory */ if ( readmessage(msgsock,receive_buffer,msglen,recvcontrolto) < 0 ) { /* ** Error ... */ return -1 ; } /* ** receive_buffer contains the directory to create */ receive_buffer[msglen] = '\0' ; if ( code == MSG_MKDIR ) { syslog(BBFTPD_DEBUG,"Creating directory %s",receive_buffer) ; } /* ** We create the directory */ if ( mkdir(receive_buffer,S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP) < 0 ) { /* ** Depending on errno we are going to tell the client to ** retry or not */ savederrno = errno ; sprintf(logmessage,"Error creation directory %s : %s",receive_buffer,strerror(errno)) ; syslog(BBFTPD_ERR,"Error creation directory %s : %s",receive_buffer,strerror(errno)) ; /* ** We tell the client not to retry in the following case (even in waiting ** WAITRETRYTIME the problem will not be solved) : ** EACCES : Search permission denied ** EDQUOT : No more quota ** ENOSPC : No more space ** ELOOP : To many symbolic links on path ** ENAMETOOLONG: Path argument too long ** ENOTDIR : A component in path is not a directory ** EROFS : The path prefix resides on a read-only file system. ** ENOENT : A component of the path prefix does not exist or is a null pathname. ** EEXIST : The named file already exists. */ if ( savederrno == EACCES || savederrno == EDQUOT || savederrno == ENOSPC || savederrno == ELOOP || savederrno == ENAMETOOLONG || savederrno == ENOTDIR || savederrno == EROFS || savederrno == ENOENT || savederrno == EEXIST ) { reply(MSG_BAD_NO_RETRY,logmessage) ; } else { reply(MSG_BAD,logmessage) ; } return 0 ; } reply(MSG_OK,"OK") ; return 0 ; }
/*main loop, message sender, etc.pp.*/ int main(int argc,char**argv) { int c,optindex=1; struct dhcp_msg *msg; /*parse options*/ argv0=*argv; while(1){ c=getopt_long(argc,argv,shortopt,longopt,&optindex); if(c==-1)break; switch(c){ case 'p':getprefix=1;break; case 'P':getprefix=0;break; case 'a':getaddress=1;break; case 'A':getaddress=0;break; case 'd':getdns=1;break; case 'D':getdns=0;break; case 'r':retries=atoi(optarg);break; case 'l':localid=optarg;break; case 'u':setduid(optarg);break; case 'c':userapid=1;break; case 'C':userapid=0;break; case 'L':setloglevel(optarg);break; default: fprintf(stderr,"Syntax error in arguments.\n"); printhelp(); return 1; break; case 'h': printhelp(); return 0; break; } } if((optind+2)!=argc){ fprintf(stderr,"Syntax error.\n"); printhelp(); return 1; } device=argv[optind]; script=argv[optind+1]; if(DUIDLEN==0){ if(localid) setlocalid(localid); else initlocalid(); } /*init socket*/ initsocket(DHCP_CLIENTPORT,device); if(sockfd<0){ td_log(LOGERROR,"unable to allocate socket, exiting."); exit(1); } /*init my own stuff*/ inititems(); /*init SOLICIT/IREQ msg*/ if(!getaddress && !getprefix){ msg=newmessage(MSG_IREQUEST); addrecvfilter(MSG_REPLY); }else{ msg=newmessage(MSG_SOLICIT); addrecvfilter(MSG_ADVERTISE); } COMPAREMSGID=1; settargetserver(&msg->msg_peer); messageaddopt(msg,OPT_CLIENTID); if(getdns){ messageaddoptrequest(msg,OPT_DNS_SERVER); messageaddoptrequest(msg,OPT_DNS_NAME); } if(getaddress)messageaddopt(msg,OPT_IANA); if(getprefix)messageaddopt(msg,OPT_IAPD); if(userapid&&(getaddress||getprefix))messageaddopt(msg,OPT_RAPIDCOMMIT); /*start main loop*/ for(c=0;c<retries;c++){ sendmessage(msg); fd_set rfd,xfd; struct timeval tv; int sret; //wait for event FD_ZERO(&rfd); FD_ZERO(&xfd); FD_SET(sockfd,&rfd); FD_SET(sockfd,&xfd); tv.tv_sec=1; tv.tv_usec=0; sret=select(sockfd+1,&rfd,0,&xfd,&tv); //check for errors if(sret<0){ int e=errno; if(e==EAGAIN)continue; td_log(LOGERROR,"Error caught: %s\n",strerror(e)); return 1; } //check for event if(sret>0){ if(FD_ISSET(sockfd,&rfd)){ struct dhcp_msg*msg2; msg2=readmessage(); if(msg2) if(handlemessage(msg2,msg)==0)break; } if(FD_ISSET(sockfd,&xfd)){ td_log(LOGERROR,"Exception on socket caught.\n"); return 1; } }else td_log(LOGDEBUG,"timeout, iteration %i",c); } /*execute script*/ return execscript(); }
int sendafile(int code) { char receive_buffer[MAXMESSLEN] ; char receive_buffer_sup[MAXMESSLEN] ; char send_buffer[MAXMESSLEN] ; int savederrno ; char readbuffer[READBUFLEN] ; char buffercomp[READBUFLEN] ; struct mess_compress *msg_compress ; #ifdef WITH_GZIP uLong buflen ; uLong bufcomplen ; #endif my64_t filelen64 ; my64_t toprint64 ; #ifdef STANDART_FILE_CALL off_t nbperchild ; off_t nbtosend ; off_t nbread ; off_t nbsent ; off_t numberread ; off_t startpoint ; off_t realnbtosend ; off_t filelen ; struct stat statbuf ; #else off64_t nbperchild ; off64_t nbtosend ; off64_t nbread ; off64_t nbsent ; off64_t numberread ; off64_t startpoint ; off64_t realnbtosend ; off64_t filelen ; struct stat64 statbuf ; #endif int lentosend ; char readfilename[MAXLENFILE] ; int retcode ; int fd ; int i ; int sendsock ; char logmessage[256] ; int compressiontype ; struct message *msg ; struct mess_store *msg_store ; struct mess_retr_ok *msg_retr_ok ; int nfds ; fd_set selectmask ; /* Select mask */ struct timeval wait_timer; /* ** Initilize the pid array */ for ( i=0 ; i< MAXPORT ; i++) { pid_child[i] = 0 ; } childendinerror = 0 ; /* No child so no error */ strcpy(currentfilename,"") ; if ( (retcode = readmessage(msgsock,receive_buffer,STORMESSLEN,recvcontrolto) ) < 0 ) { syslog(BBFTPD_ERR,"Error receiving file char") ; return retcode ; } msg_store = (struct mess_store *) receive_buffer ; strcpy(readfilename,msg_store->filename) ; #ifndef WORDS_BIGENDIAN msg_store->nbport = ntohl(msg_store->nbport) ; for (i = 0 ; i< MAXPORT ; i++ ) { msg_store->port[i] = ntohl(msg_store->port[i]) ; } #endif if ( code == MSG_RETR ) { compressiontype = NOCOMPRESSION ; syslog(BBFTPD_DEBUG,"Retreiving file %s with %d children",readfilename,msg_store->nbport) ; } else { compressiontype = COMPRESSION ; syslog(BBFTPD_DEBUG,"Retreiving file %s with %d children in compressed mode",readfilename,msg_store->nbport) ; } /* ** WARNING ---------- ** ** Do not use the receive buffer in father before having forked ** because all data related to the ports are in it ** ** WARNING ---------- */ /* ** First stat the file in order to know if it is a directory */ #ifdef STANDART_FILE_CALL if ( stat(readfilename,&statbuf) < 0 ) { #else if ( stat64(readfilename,&statbuf) < 0 ) { #endif /* ** We tell the client not to retry in the following case (even in waiting ** WAITRETRYTIME the problem will not be solved) : ** EACCES : Search permission denied ** ELOOP : To many symbolic links on path ** ENAMETOOLONG: Path argument too long ** ENOENT : The file does not exists ** ENOTDIR : A component in path is not a directory */ savederrno = errno ; sprintf(logmessage,"Error stating file %s : %s ",readfilename,strerror(savederrno)) ; syslog(BBFTPD_ERR,"Error stating file %s : %s ",readfilename,strerror(savederrno)) ; if ( savederrno == EACCES || savederrno == ELOOP || savederrno == ENAMETOOLONG || savederrno == ENOENT || savederrno == ENOTDIR ) { reply(MSG_BAD_NO_RETRY,logmessage) ; return 0 ; } else { reply(MSG_BAD,logmessage) ; return 0 ; } } else { /* ** The file exists so check if it is a directory */ if ( (statbuf.st_mode & S_IFDIR) == S_IFDIR) { syslog(BBFTPD_ERR,"file %s is a directory",readfilename) ; sprintf(logmessage,"File %s is a directory",readfilename) ; reply(MSG_BAD_NO_RETRY,logmessage) ; return 0 ; } } /* ** Getting filesize in order to send it to the client */ #ifdef STANDART_FILE_CALL if ( (fd = open(readfilename,O_RDONLY)) < 0 ) { #else if ( (fd = open64(readfilename,O_RDONLY)) < 0 ) { #endif /* ** An error on openning the local file is considered ** as fatal. Maybe this need to be improved depending ** on errno */ savederrno = errno ; syslog(BBFTPD_ERR,"Error opening local file %s : %s",readfilename,strerror(errno)) ; sprintf(logmessage,"Error opening local file %s : %s ",readfilename,strerror(errno)) ; /* ** We tell the client not to retry in the following case (even in waiting ** WAITRETRYTIME the problem will not be solved) : ** EACCES : Search permission denied ** ELOOP : To many symbolic links on path ** ENOENT : No such file or directory ** ENAMETOOLONG: Path argument too long ** ENOTDIR : A component in path is not a directory */ if ( savederrno == EACCES || savederrno == ELOOP || savederrno == ENOENT || savederrno == ENAMETOOLONG || savederrno == ENOTDIR ) { reply(MSG_BAD_NO_RETRY,logmessage) ; } else { reply(MSG_BAD,logmessage) ; } return 0 ; } #ifdef STANDART_FILE_CALL if ( (filelen = lseek(fd,0,SEEK_END) ) < 0 ) { #else if ( (filelen = lseek64(fd,0,SEEK_END) ) < 0 ) { #endif /* ** An error on seekin the local file is considered ** as fatal. lseek error in this case is completly ** abnormal */ close(fd) ; syslog(BBFTPD_ERR,"Error seeking local file %s : %s",readfilename,strerror(errno)) ; sprintf(logmessage,"Error seeking local file %s : %s ",readfilename,strerror(errno)) ; reply(MSG_BAD,logmessage) ; return 0 ; } filelen64 = filelen ; /* ** Close the file as the only interresting thing was the length */ close(fd) ; /* ** We are going to send the file length */ msg = (struct message *) send_buffer ; msg->code = MSG_RETR_OK ; #ifndef WORDS_BIGENDIAN msg->msglen = ntohl(RETROKMESSLEN) ; #else msg->msglen = RETROKMESSLEN ; #endif if ( writemessage(msgsock,send_buffer,MINMESSLEN,recvcontrolto) < 0 ) { /* ** Something wrong in sending message ** tell calling to close the connection */ syslog(BBFTPD_ERR,"Error sending RETROK part 1") ; return -1 ; } msg_retr_ok = (struct mess_retr_ok *) send_buffer ; #ifndef WORDS_BIGENDIAN msg_retr_ok->filesize = ntohll(filelen64) ; #else msg_retr_ok->filesize = filelen64 ; #endif if ( writemessage(msgsock,send_buffer,RETROKMESSLEN,recvcontrolto) < 0 ) { /* ** Something wrong in sending message ** tell calling to close the connection */ syslog(BBFTPD_ERR,"Error sending RETROK part 2") ; return -1 ; } /* ** Wait for the START message */ if ( readmessage(msgsock,receive_buffer_sup,MINMESSLEN,RETRSTARTTO) < 0 ) { /* ** Something wrong in receiving message ** tell calling to close the connection */ syslog(BBFTPD_ERR,"Error receiving RETRSTART") ; return -1 ; } msg = (struct message *) receive_buffer_sup ; if ( msg->code == MSG_ABR) { /* ** In this case the client will not close the connection ** so do the same */ syslog(BBFTPD_ERR,"Receive ABORT message") ; return 0 ; } else if ( msg->code == MSG_CREATE_ZERO ) { syslog(BBFTPD_INFO,"Send zero length file") ; return 0 ; } else if ( msg->code != MSG_RETR_START ) { syslog(BBFTPD_ERR,"Receive Unknown message code while waiting RETRSTART %d",msg->code) ; return -1 ; } /* ** So we receive the start message ... */ /* ** Now start all our children */ nbperchild = filelen/msg_store->nbport ; for (i = 1 ; i <= msg_store->nbport ; i++) { if ( i == msg_store->nbport) { startpoint = (i-1)*nbperchild; nbtosend = filelen-(nbperchild*(msg_store->nbport-1)) ; } else { startpoint = (i-1)*nbperchild; nbtosend = nbperchild ; } /* ** Now create the socket to send */ sendsock = 0 ; while (sendsock == 0 ) { sendsock = createreceivesock(msg_store->port[i-1],i,logmessage) ; } if ( sendsock < 0 ) { /* ** We set childendinerror to 1 in order to prevent the father ** to send a BAD message which can desynchronize the client and the ** server (We need only one error message) ** Bug discovered by amlutz on 2000/03/11 */ if ( childendinerror == 0 ) { childendinerror = 1 ; reply(MSG_BAD,logmessage) ; } clean_child() ; return 0 ; } /* ** Set flagsighup to zero in order to be able in child ** not to wait STARTCHILDTO if signal was sent before ** entering select. (Seen on Linux with one child) */ flagsighup = 0 ; /* ** At this stage we are ready to receive packets ** So we are going to fork */ if ( (retcode = fork()) == 0 ) { /* ** We are in child */ /* ** Pause until father send a SIGHUP in order to prevent ** child to die before father has started all children */ if ( flagsighup == 0) { nfds = sysconf(_SC_OPEN_MAX) ; wait_timer.tv_sec = STARTCHILDTO ; wait_timer.tv_usec = 0 ; select(nfds,0,0,0,&wait_timer) ; } syslog(BBFTPD_DEBUG,"Child Starting") ; /* ** Close all unnecessary stuff */ close(msgsock) ; /* ** And open the file */ #ifdef STANDART_FILE_CALL if ( (fd = open(readfilename,O_RDONLY)) < 0 ) { #else if ( (fd = open64(readfilename,O_RDONLY)) < 0 ) { #endif /* ** An error on openning the local file is considered ** as fatal. Maybe this need to be improved depending ** on errno */ i = errno ; syslog(BBFTPD_ERR,"Error opening local file %s : %s",readfilename,strerror(errno)) ; close(sendsock) ; exit(i) ; } #ifdef STANDART_FILE_CALL if ( lseek(fd,startpoint,SEEK_SET) < 0 ) { #else if ( lseek64(fd,startpoint,SEEK_SET) < 0 ) { #endif i = errno ; close(fd) ; syslog(BBFTPD_ERR,"Error seeking file : %s",strerror(errno)) ; close(sendsock) ; exit(i) ; } /* ** Start the sending loop */ nbread = 0 ; while ( nbread < nbtosend ) { if ( (numberread = read ( fd, readbuffer, (sizeof(readbuffer) <= nbtosend - nbread) ? sizeof(readbuffer) : nbtosend-nbread) ) > 0 ) { nbread = nbread+numberread ; #ifdef WITH_GZIP if ( compressiontype == COMPRESSION ) { /* ** In case of compression we are going to use ** a temporary buffer */ bufcomplen = READBUFLEN ; buflen = numberread ; msg_compress = ( struct mess_compress *) send_buffer; retcode = compress((Bytef *)buffercomp,&bufcomplen,(Bytef *)readbuffer,buflen) ; if ( retcode != 0 ) { /* ** Compress error, in this cas we are sending the ** date uncompressed */ msg_compress->code = DATA_NOCOMPRESS ; lentosend = numberread ; #ifndef WORDS_BIGENDIAN msg_compress->datalen = ntohl(lentosend) ; #else msg_compress->datalen = lentosend ; #endif realnbtosend = numberread ; } else { msg_compress->code = DATA_COMPRESS ; lentosend = bufcomplen ; #ifndef WORDS_BIGENDIAN msg_compress->datalen = ntohl(lentosend) ; #else msg_compress->datalen = lentosend ; #endif realnbtosend = bufcomplen ; memcpy(readbuffer,buffercomp,READBUFLEN) ; } /* ** Send the header */ if ( writemessage(sendsock,send_buffer,COMPMESSLEN,datato) < 0 ) { i = ETIMEDOUT ; syslog(BBFTPD_ERR,"Error sending header data") ; close(sendsock) ; exit(i) ; } } else { realnbtosend = numberread ; } #else realnbtosend = numberread ; #endif /* ** Send the data */ nbsent = 0 ; while ( nbsent < realnbtosend ) { lentosend = realnbtosend-nbsent ; nfds = sysconf(_SC_OPEN_MAX) ; FD_ZERO(&selectmask) ; FD_SET(sendsock,&selectmask) ; wait_timer.tv_sec = datato ; wait_timer.tv_usec = 0 ; if ( (retcode = select(nfds,0,&selectmask,0,&wait_timer) ) == -1 ) { /* ** Select error */ i = errno ; syslog(BBFTPD_ERR,"Error select while sending : %s",strerror(errno)) ; close(fd) ; close(sendsock) ; exit(i) ; } else if ( retcode == 0 ) { syslog(BBFTPD_ERR,"Time out while sending") ; close(fd) ; i=ETIMEDOUT ; close(sendsock) ; exit(i) ; } else { retcode = send(sendsock,&readbuffer[nbsent],lentosend,0) ; if ( retcode < 0 ) { i = errno ; syslog(BBFTPD_ERR,"Error while sending %s",strerror(i)) ; close(sendsock) ; exit(i) ; } else if ( retcode == 0 ) { i = ECONNRESET ; syslog(BBFTPD_ERR,"Connexion breaks") ; close(fd) ; close(sendsock) ; exit(i) ; } else { nbsent = nbsent+retcode ; } } } } else { i = errno ; syslog(BBFTPD_ERR,"Child Error reading : %s",strerror(errno)) ; close(sendsock) ; exit(i) ; } } /* ** All data has been sent so wait for the acknoledge */ if ( readmessage(sendsock,receive_buffer,MINMESSLEN,ackto) < 0 ) { syslog(BBFTPD_ERR,"Error waiting ACK") ; close(sendsock) ; exit(ETIMEDOUT) ; } msg = (struct message *) receive_buffer ; if ( msg->code != MSG_ACK) { syslog(BBFTPD_ERR,"Error unknown messge while waiting ACK %d",msg->code) ; close(sendsock) ; exit(1) ; } toprint64 = nbtosend ; syslog(BBFTPD_DEBUG,"Child send %" LONG_LONG_FORMAT " bytes ; end correct ",toprint64) ; close(sendsock) ; exit(0) ; } else { /* ** We are in father */ if ( retcode == -1 ) { /* ** Fork failed ... */ syslog(BBFTPD_ERR,"fork failed : %s",strerror(errno)) ; sprintf(logmessage,"fork failed : %s ",strerror(errno)) ; if ( childendinerror == 0 ) { childendinerror = 1 ; reply(MSG_BAD,logmessage) ; } clean_child() ; return 0 ; } else { syslog(BBFTPD_DEBUG,"Started child pid %d",retcode) ; pid_child[i-1] = retcode ; close(sendsock) ; } } } /* ** Set the state before starting children because if the file was ** small the child has ended before state was setup to correct value */ state = S_SENDING ; /* ** Start all children */ for (i = 0 ; i<MAXPORT ; i++) { if (pid_child[i] != 0) { kill(pid_child[i],SIGHUP) ; } } return 0 ; }
int bbftp_retrlistdir(char *pattern,char **filelist,int *filelistlen,char *logmessage,int *errcode) { int lastslash ; char *pointer ; char *dirpath ; DIR *curdir ; #ifdef STANDART_FILE_CALL struct dirent *dp ; struct stat statbuf; #else #ifdef STANDART_READDIR_CALL struct dirent *dp ; #else struct dirent64 *dp ; #endif struct stat64 statbuf ; #endif int lengthtosend; int numberoffile ; /* ** Structure to keep the filenames */ struct keepfile { char *filename ; char filechar[3] ; struct keepfile *next ; } ; struct keepfile *first_item ; struct keepfile *current_item ; struct keepfile *used_item ; char *filepos ; int i ; /* ** Check if it is a rfio creation */ #if defined(WITH_RFIO) || defined(WITH_RFIO64) if ( (transferoption & TROPT_RFIO_O) == TROPT_RFIO_O ) { return bbftp_retrlistdir_rfio(pattern,filelist,filelistlen,logmessage,errcode) ; } #endif if ( (dirpath = (char *) malloc ( strlen(pattern) + 1 + 3 )) == NULL ) { sprintf(logmessage,"Error allocating memory for dirpath %s",strerror(errno)) ; *errcode = 35 ; return -1 ; } pointer = pattern ; lastslash = strlen(pointer) - 1 ; while ( lastslash >= 0 && pointer[lastslash] != '/') lastslash-- ; if ( lastslash == -1 ) { /* ** No slash in the path, so this is a pattern and we have ** to opendir . */ if ( (curdir = opendir(".")) == NULL ) { sprintf(logmessage,"opendir . failed : %s ",strerror(errno)) ; *errcode = 86 ; free(dirpath) ; return -1 ; } strcpy(dirpath,"./") ; } else if ( lastslash == 0 ) { /* ** A slash in first position so we are going to open the ** / directory */ if ( (curdir = opendir("/")) == NULL ) { sprintf(logmessage,"opendir / failed : %s ",strerror(errno)) ; *errcode = 86 ; free(dirpath) ; return -1 ; } strcpy(dirpath,"/") ; pointer++ ; } else if ( lastslash == strlen(pointer) - 1 ) { /* ** The filename end with a slash ..... error */ sprintf(logmessage,"Pattern %s ends with a /",pattern) ; *errcode = 87 ; free(dirpath) ; return -1; } else { pointer[lastslash] = '\0'; /* ** Srip unnecessary / at the end of dirpath and reset ** only one */ strcpy(dirpath,pointer) ; strip_trailing_slashes(dirpath) ; dirpath[strlen(dirpath)+1] = '\0'; dirpath[strlen(dirpath)] = '/'; if ( (curdir = opendir(dirpath)) == NULL ) { sprintf(logmessage,"opendir %s failed : %s ",dirpath,strerror(errno)) ; *errcode = 86 ; free(dirpath) ; return -1 ; } for ( i = 0 ; i <= lastslash ; i++ ) pointer++ ; } /* ** At this stage pointer point to the pattern and curdir ** is the opened directory and dirpath contain the ** directory name */ /* ** As we are using the fnmatch routine we are obliged to ** first count the number of bytes we are sending. */ lengthtosend = 0 ; numberoffile = 0 ; errno = 0 ; first_item = NULL ; #ifdef STANDART_FILE_CALL while ( (dp = readdir(curdir) ) != NULL) { #else #ifdef STANDART_READDIR_CALL while ( (dp = readdir(curdir) ) != NULL) { #else while ( (dp = readdir64(curdir) ) != NULL) { #endif #endif if ( fnmatch(pointer, dp->d_name,0) == 0) { numberoffile++ ; lengthtosend = lengthtosend + strlen(dirpath) + strlen(dp->d_name) + 1 + 3 ; if ( ( current_item = (struct keepfile *) malloc( sizeof(struct keepfile)) ) == NULL ) { sprintf(logmessage,"Error getting memory for structure : %s",strerror(errno)) ; *errcode = 35 ; current_item = first_item ; while ( current_item != NULL ) { free(current_item->filename) ; used_item = current_item->next ; free(current_item) ; current_item = used_item ; } closedir(curdir) ; free(dirpath) ; return -1 ; } if ( ( current_item->filename = (char *) malloc( strlen(dirpath) + strlen(dp->d_name) + 1) ) == NULL ) { sprintf(logmessage,"Error getting memory for filename : %s",strerror(errno)) ; *errcode = 35 ; /* ** Clean memory */ free(current_item) ; current_item = first_item ; while ( current_item != NULL ) { free(current_item->filename) ; used_item = current_item->next ; free(current_item) ; current_item = used_item ; } closedir(curdir) ; free(dirpath) ; return -1 ; } current_item->next = NULL ; if ( first_item == NULL ) { first_item = current_item ; used_item = first_item ; } else { used_item = first_item ; while ( used_item->next != NULL ) used_item = used_item->next ; used_item->next = current_item ; } sprintf(current_item->filename,"%s%s",dirpath,dp->d_name) ; #ifdef STANDART_FILE_CALL if ( lstat(current_item->filename,&statbuf) < 0 ) { #else if ( lstat64(current_item->filename,&statbuf) < 0 ) { #endif sprintf(logmessage,"Error lstating file %s",current_item->filename) ; *errcode = 89 ; current_item = first_item ; while ( current_item != NULL ) { free(current_item->filename) ; used_item = current_item->next ; free(current_item) ; current_item = used_item ; } closedir(curdir) ; free(dirpath) ; return -1 ; } if ( (statbuf.st_mode & S_IFLNK) == S_IFLNK) { current_item->filechar[0] = 'l' ; #ifdef STANDART_FILE_CALL if ( stat(current_item->filename,&statbuf) < 0 ) { #else if ( stat64(current_item->filename,&statbuf) < 0 ) { #endif /* ** That means that the link refer to an unexisting file */ current_item->filechar[1] = 'u' ; } else { if ( (statbuf.st_mode & S_IFDIR) == S_IFDIR) { current_item->filechar[1] = 'd' ; } else { current_item->filechar[1] = 'f' ; } } } else { current_item->filechar[0] = ' ' ; if ( (statbuf.st_mode & S_IFDIR) == S_IFDIR) { current_item->filechar[1] = 'd' ; } else { current_item->filechar[1] = 'f' ; } } current_item->filechar[2] = '\0' ; } errno = 0 ; } /* ** Check errno in case of error during readdir ** for the following readir we are not going to check ** so that may be a cause of problem */ if ( errno != 0 ) { sprintf(logmessage,"Error on readdir %s : %s ",dirpath,strerror(errno)) ; *errcode = 88 ; closedir(curdir) ; current_item = first_item ; while ( current_item != NULL ) { free(current_item->filename) ; used_item = current_item->next ; free(current_item) ; current_item = used_item ; } free(dirpath) ; return -1 ; } /* ** Check if numberoffile is zero and reply now in this ** case */ if ( numberoffile == 0 ) { *filelistlen = 0 ; closedir(curdir) ; current_item = first_item ; while ( current_item != NULL ) { free(current_item->filename) ; used_item = current_item->next ; free(current_item) ; current_item = used_item ; } free(dirpath) ; return 0 ; } /* ** Now everything is ready so prepare the answer */ if ( ( *filelist = (char *) malloc (lengthtosend) ) == NULL ) { sprintf(logmessage,"Error allocating memory for filelist %s",strerror(errno)) ; *errcode = 35 ; closedir(curdir) ; current_item = first_item ; while ( current_item != NULL ) { free(current_item->filename) ; used_item = current_item->next ; free(current_item) ; current_item = used_item ; } free(dirpath) ; return -1 ; } current_item = first_item ; filepos = *filelist ; while ( current_item != NULL ) { sprintf(filepos,"%s",current_item->filename) ; filepos = filepos + strlen(filepos) + 1 ; sprintf(filepos,"%s",current_item->filechar) ; filepos = filepos + strlen(filepos) + 1 ; current_item = current_item->next ; } *filelistlen = lengthtosend ; closedir(curdir) ; current_item = first_item ; while ( current_item != NULL ) { free(current_item->filename) ; used_item = current_item->next ; free(current_item) ; current_item = used_item ; } free(dirpath) ; return 0 ; } /******************************************************************************* ** bbftp_retrcheckdir : * ** * ** Routine to check a directory * ** * ** OUPUT variable : * ** logmessage : to write the error message in case of error * ** * ** GLOBAL VARIABLE USED : * * ** * ** RETURN: * ** -1 Unrecoverable error * ** 0 OK * ** 1 recoverable error * ** * *******************************************************************************/ int bbftp_retrcheckdir(char *filename,char *logmessage,int *errcode) { #ifdef STANDART_FILE_CALL struct stat statbuf; #else struct stat64 statbuf ; #endif int savederrno ; /* ** Check if it is a rfio creation */ #if defined(WITH_RFIO) || defined(WITH_RFIO64) if ( (transferoption & TROPT_RFIO_O) == TROPT_RFIO_O ) { return bbftp_retrcheckdir_rfio(filename,logmessage,errcode) ; } #endif #ifdef STANDART_FILE_CALL if ( stat(filename,&statbuf) < 0 ) { #else if ( stat64(filename,&statbuf) < 0 ) { #endif /* ** It may be normal to get an error if the dir ** does not exist but some error code must lead ** to the interruption of the transfer: ** EACCES : Search permission denied ** ELOOP : To many symbolic links on path ** ENAMETOOLONG : Path argument too long ** ENOTDIR : A component in path is not a directory */ savederrno = errno ; if ( savederrno == EACCES || savederrno == ELOOP || savederrno == ENAMETOOLONG || savederrno == ENOTDIR ) { sprintf(logmessage,"Error stating file %s : %s",filename,strerror(savederrno)) ; *errcode = 72 ; return -1 ; } else { return 0 ; } } else { /* ** The file exists so check if it is a directory */ if ( (statbuf.st_mode & S_IFDIR) != S_IFDIR) { sprintf(logmessage,"File %s is not a directory",filename) ; *errcode = 76 ; return -1 ; } } return 0 ; } /******************************************************************************* ** bbftp_retrcheckfile : * ** * ** Routine to check a file and set the global parameters * ** * ** OUPUT variable : * ** logmessage : to write the error message in case of error * ** * ** GLOBAL VARIABLE USED : * * ** transferoption NOT MODIFIED * ** filemode MODIFIED * ** lastaccess MODIFIED * ** lastmodif MODIFIED * ** filesize MODIFIED * ** requestedstreamnumber POSSIBLY MODIFIED * ** * ** RETURN: * ** -1 Unrecoverable error * ** 0 OK * ** 1 recoverable error * ** * *******************************************************************************/ int bbftp_retrcheckfile(char *filename,char *logmessage,int *errcode) { #ifdef STANDART_FILE_CALL struct stat statbuf; #else struct stat64 statbuf ; #endif int tmpnbport ; int savederrno ; /* ** Check if it is a rfio creation */ #if defined(WITH_RFIO) || defined(WITH_RFIO64) if ( (transferoption & TROPT_RFIO_O) == TROPT_RFIO_O ) { return bbftp_retrcheckfile_rfio(filename,logmessage,errcode) ; } #endif #ifdef STANDART_FILE_CALL if ( stat(filename,&statbuf) < 0 ) { #else if ( stat64(filename,&statbuf) < 0 ) { #endif /* ** It may be normal to get an error if the file ** does not exist but some error code must lead ** to the interruption of the transfer: ** EACCES : Search permission denied ** ELOOP : To many symbolic links on path ** ENAMETOOLONG : Path argument too long ** ENOENT : The file does not exists ** ENOTDIR : A component in path is not a directory */ savederrno = errno ; sprintf(logmessage,"Error stating file %s : %s ",filename,strerror(savederrno)) ; *errcode = 72 ; if ( savederrno == EACCES || savederrno == ELOOP || savederrno == ENAMETOOLONG || savederrno == ENOENT || savederrno == ENOTDIR ) { return -1 ; } else { return 1 ; } } else { /* ** The file exists so check if it is a directory */ if ( (statbuf.st_mode & S_IFDIR) == S_IFDIR) { sprintf(logmessage,"File %s is a directory",filename) ; *errcode = 73 ; return -1 ; } } if (S_ISREG(statbuf.st_mode)) { filemode = statbuf.st_mode & ~S_IFREG; } else { filemode = statbuf.st_mode; } sprintf(lastaccess,"%08x",statbuf.st_atime) ; sprintf(lastmodif,"%08x",statbuf.st_mtime) ; lastaccess[8] = '\0' ; lastmodif[8] = '\0' ; filesize = statbuf.st_size ; tmpnbport = filesize/(buffersizeperstream*1024) ; if ( tmpnbport == 0 ) { requestedstreamnumber = 1 ; } else if ( tmpnbport < nbport ) { requestedstreamnumber = tmpnbport ; } else { requestedstreamnumber = nbport ; } return 0 ; } /******************************************************************************* ** bbftp_retrtransferfile : * ** * ** Routine to transfer a file * ** * ** INPUT variable : * ** filename : file to send NOT MODIFIED * ** * ** OUTPUT variable : * ** logmessage : to write the error message in case of error * ** * ** GLOBAL VARIABLE USED : * * ** * ** RETURN: * ** -1 transfer failed unrecoverable error * ** 0 Keep the connection open (does not mean that the file has been * ** successfully transfered) * ** >0 Recoverable error but calling has the cleaning to do * ** * *******************************************************************************/ int bbftp_retrtransferfile(char *filename,char *logmessage,int *errcode) { #ifdef STANDART_FILE_CALL off_t nbperchild ; off_t nbtosend; off_t startpoint ; off_t nbread ; off_t numberread ; off_t nbsent ; off_t realnbtosend ; #else off64_t nbperchild ; off64_t nbtosend; off64_t startpoint ; off64_t nbread ; off64_t numberread ; off64_t nbsent ; off64_t realnbtosend ; #endif #ifdef WITH_GZIP uLong buflen ; uLong bufcomplen ; #endif int lentosend ; int retcode ; int *pidfree ; int *socknumber ; int i ; int nfds ; fd_set selectmask ; struct timeval wait_timer; int fd ; struct mess_compress *msg_compress ; struct message *msg ; int compressionon ; int sendsock ; int *portnumber ; extern int simulation_mode ; /* ** Check if it is a rfio transfer */ #if defined(WITH_RFIO) || defined(WITH_RFIO64) if ( (transferoption & TROPT_RFIO_O) == TROPT_RFIO_O ) { return bbftp_retrtransferfile_rfio(filename,logmessage,errcode) ; } #endif if (protocol == 2) { /* Active mode */ socknumber = mysockets ; } else { /* Passive mode */ portnumber = myports ; } nbperchild = filesize/requestedstreamnumber ; pidfree = mychildren ; /* ** Now start all our children */ for (i = 1 ; i <= requestedstreamnumber ; i++) { if ( i == requestedstreamnumber ) { startpoint = (i-1)*nbperchild; nbtosend = filesize-(nbperchild*(requestedstreamnumber-1)) ; } else { startpoint = (i-1)*nbperchild; nbtosend = nbperchild ; } if (protocol == 2) { sendsock = *socknumber ; socknumber++ ; } else { /* Passive mode */ /* ** Now create the socket to send */ sendsock = 0 ; while (sendsock == 0 ) { sendsock = bbftp_createdatasock(*portnumber/*,logmessage*/) ; } if ( sendsock < 0 ) { /* ** We set childendinerror to 1 in order to prevent the father ** to send a BAD message which can desynchronize the client and the ** server (We need only one error message) ** Bug discovered by amlutz on 2000/03/11 */ /* if ( childendinerror == 0 ) { childendinerror = 1 ; reply(MSG_BAD,logmessage) ; } clean_child() ;*/ return 1 ; } portnumber++ ; /* ** Set flagsighup to zero in order to be able in child ** not to wait STARTCHILDTO if signal was sent before ** entering select. (Seen on Linux with one child) */ /*flagsighup = 0 ;*/ } if ( (retcode = fork()) == 0 ) { int ns ; blockallsignals() ; /* ** We are in child */ /* ** In child the first thing to do is to ** close the control socket, and all the ** socket not concerning itself */ close(STDIN_FILENO) ; close(STDOUT_FILENO) ; close(STDERR_FILENO) ; close(incontrolsock) ; close(outcontrolsock) ; if (protocol == 2) { /* Active mode */ int *socktoclose ; socktoclose = mysockets ; for ( i=0 ; i< requestedstreamnumber ; i++ ) { if ( *socktoclose != sendsock) close(*socktoclose) ; socktoclose++ ; } } /* ** And open the file */ #ifdef STANDART_FILE_CALL if ( (fd = open(filename,O_RDONLY|O_BINARY)) < 0 ) { #else if ( (fd = open64(filename,O_RDONLY|O_BINARY)) < 0 ) { #endif /* ** An error on openning the local file is considered ** as fatal. Maybe this need to be improved depending ** on errno */ i = errno ; _exit(i) ; } #ifdef STANDART_FILE_CALL if ( lseek(fd,startpoint,SEEK_SET) < 0 ) { #else if ( lseek64(fd,startpoint,SEEK_SET) < 0 ) { #endif i = errno ; close(fd) ; _exit(i) ; } /* ** We are now just going to select on our ** socket **/ nfds = sysconf(_SC_OPEN_MAX) ; FD_ZERO(&selectmask) ; FD_SET(sendsock,&selectmask) ; /* ** Set the timer for the connection */ wait_timer.tv_sec = CHILDWAITTIME ; wait_timer.tv_usec = 0 ; if (protocol == 2) { retcode = select(FD_SETSIZE,&selectmask,0,0,&wait_timer) ; } else { retcode = select(FD_SETSIZE,0,&selectmask,0,&wait_timer) ; } if ( retcode < 0 ) { /* ** select return in error ** Let us sleep a while in order to let ** the father fork all its children */ i = errno ; close(fd) ; sleep(CHILDWAITTIME) ; _exit(i) ; } if ( retcode == 0 ) { /* ** That is a time out let us exit ** with the time out error */ close(fd) ; _exit(ETIMEDOUT) ; } /* ** At this point as we only set one bit we have ** got a connection */ if (protocol == 2) { /* Active mode */ if ( (ns = accept(sendsock,0,0) ) < 0 ) { i = errno ; close(fd) ; _exit(i) ; } /* ** Close the listening socket */ close(sendsock) ; } else { ns = sendsock ; /*close(sendsock) ;*/ } /* ** Start the sending loop ** In simulation mode, simulate the transfer */ if (!simulation_mode) { nbread = 0 ; while ( nbread < nbtosend ) { if ( (numberread = read ( fd, readbuffer, ( (buffersizeperstream*1024) <= nbtosend - nbread) ? (buffersizeperstream*1024) : nbtosend-nbread) ) > 0 ) { nbread = nbread+numberread ; #ifdef WITH_GZIP if ( (transferoption & TROPT_GZIP ) == TROPT_GZIP ) { /* ** In case of compression we are going to use ** a temporary buffer */ bufcomplen = buffersizeperstream*1024 ; buflen = numberread ; retcode = compress((Bytef *)compbuffer,&bufcomplen,(Bytef *)readbuffer,buflen) ; if ( retcode != 0 ) { msg_compress = ( struct mess_compress *) compbuffer; /* ** Compress error, in this cas we are sending the ** date uncompressed */ msg_compress->code = DATA_NOCOMPRESS ; lentosend = numberread ; #ifndef WORDS_BIGENDIAN msg_compress->datalen = ntohl(lentosend) ; #else msg_compress->datalen = lentosend ; #endif realnbtosend = numberread ; } else { memcpy(readbuffer,compbuffer,buffersizeperstream*1024) ; msg_compress = ( struct mess_compress *) compbuffer; msg_compress->code = DATA_COMPRESS ; lentosend = bufcomplen ; #ifndef WORDS_BIGENDIAN msg_compress->datalen = ntohl(lentosend) ; #else msg_compress->datalen = lentosend ; #endif realnbtosend = bufcomplen ; } /* ** Send the header */ if ( writemessage(ns,compbuffer,COMPMESSLEN,datato,1) < 0 ) { i = ETIMEDOUT ; _exit(i) ; } } else { realnbtosend = numberread ; } #else realnbtosend = numberread ; #endif /* ** Send the data */ nbsent = 0 ; while ( nbsent < realnbtosend ) { lentosend = realnbtosend-nbsent ; nfds = sysconf(_SC_OPEN_MAX) ; FD_ZERO(&selectmask) ; FD_SET(ns,&selectmask) ; wait_timer.tv_sec = datato ; wait_timer.tv_usec = 0 ; if ( (retcode = select(FD_SETSIZE,0,&selectmask,0,&wait_timer) ) == -1 ) { /* ** Select error */ i = errno ; close(fd) ; close(ns) ; _exit(i) ; } else if ( retcode == 0 ) { close(fd) ; i=ETIMEDOUT ; close(ns) ; _exit(i) ; } else { retcode = send(ns,&readbuffer[nbsent],lentosend,0) ; if ( retcode < 0 ) { i = errno ; close(fd) ; close(ns) ; _exit(i) ; } else if ( retcode == 0 ) { i = ECONNRESET ; close(fd) ; close(ns) ; _exit(i) ; } else { nbsent = nbsent+retcode ; } } } } else { i = errno ; close(ns) ; close(fd) ; _exit(i) ; } } close(fd) ; /* ** All data has been sent so wait for the acknoledge */ if ( readmessage(ns,readbuffer,MINMESSLEN,ackto,1) < 0 ) { close(ns) ; _exit(ETIMEDOUT) ; } msg = (struct message *) readbuffer ; if ( msg->code != MSG_ACK) { close(ns) ; _exit(1) ; } } close(ns) ; _exit(0) ; } else { /* ** We are in father */ if ( retcode == -1 ) { /* ** Fork failed ... */ sprintf(logmessage,"Fork failed : %s\n",strerror(errno)) ; *errcode = 36 ; sprintf(logmessage,"fork failed : %s ",strerror(errno)) ; bbftp_clean_child() ; return -1 ; } else { *pidfree++ = retcode ; close(sendsock) ; /*socknumber++ ;*/ } } } return 0 ; }
int sendproto() { char buffer[8] ; struct message *msg ; int remoteprotomin ; int remoteprotomax ; fd_set selectmask ; /* Select mask */ int nfds ; /* Max number of file descriptor */ int code ; int retcode ; int msglen ; if ( debug ) printmessage(stdout,CASE_NORMAL,0,timestamp,"Sending protocol request\n") ; /* ** Now send the control message : First part */ msg = (struct message *)buffer ; msg->code = MSG_PROT ; msg->msglen = 0 ; if ( writemessage(outcontrolsock,buffer,MINMESSLEN,sendcontrolto,0) < 0 ) { /* ** We were not able to send the minimum message so ** we are going to close the control socket and to ** tell the calling program to restart a connection */ printmessage(stderr,CASE_ERROR,64,timestamp,"Error sending %s message\n","MSG_PROT"); return -1 ; /* restart connection */ } if ( debug ) printmessage(stdout,CASE_NORMAL,0,timestamp,"Sent message %x\n", msg->code) ; /* ** Now we are going to wait for the message on the control ** connection */ waitcontrol: nfds = sysconf(_SC_OPEN_MAX) ; FD_ZERO(&selectmask) ; FD_SET(incontrolsock,&selectmask) ; retcode = select(FD_SETSIZE,&selectmask,0,0,0) ; if ( retcode < 0 ) { /* ** Select error */ if ( errno != EINTR ) { /* ** we have got an error so close the connection ** and restart */ printmessage(stderr,CASE_ERROR,66,timestamp,"Error select on control connection : %s\n",strerror(errno)); return -1 ; } else { /* ** Interrupted by a signal */ FD_ZERO(&selectmask) ; FD_SET(incontrolsock,&selectmask) ; goto waitcontrol ; } } else if ( retcode == 0 ) { /* ** Impossible we do not set any timer */ FD_ZERO(&selectmask) ; FD_SET(incontrolsock,&selectmask) ; goto waitcontrol ; } else { /* ** read the message */ if ( readmessage(incontrolsock,buffer,MINMESSLEN,recvcontrolto,0) < 0 ) { printmessage(stderr,CASE_ERROR,61,timestamp,"Error waiting %s message\n","MSG_PROT_ANS"); return -1 ; } msg = (struct message *)buffer ; code = msg->code ; if ( code == MSG_BAD || code == MSG_BAD_NO_RETRY) { /* ** The server does not understand protocol */ printmessage(stderr,CASE_FATAL_ERROR,101,timestamp,"Incompatible deamon and client (remote protocol version (%d,%d), local (%d,%d))\n",1,1,protocolmin,protocolmax); } else if (msg->code == MSG_PROT_ANS ) { /* ** At this stage */ #ifndef WORDS_BIGENDIAN msglen = ntohl(msg->msglen) ; #else msglen = msg->msglen ; #endif if ( msglen != 8 ) { printmessage(stderr,CASE_ERROR,63,timestamp,"Unexpected message length while waiting for %s message\n","MSG_PROT_ANS"); return -1 ; } if ( readmessage(incontrolsock,buffer,msglen,recvcontrolto,0) < 0) { printmessage(stderr,CASE_ERROR,67,timestamp,"Error reading data for %s message\n","MSG_PROT_ANS"); return -1 ; } #ifndef WORDS_BIGENDIAN remoteprotomin = ntohl(msg->code) ; remoteprotomax = ntohl(msg->msglen) ; #else remoteprotomin = msg->code ; remoteprotomax = msg->msglen ; #endif if ( (remoteprotomax < protocolmin) || (remoteprotomin > protocolmax) ) { /* ** Imcompatible version */ msg->code = MSG_BAD_NO_RETRY ; msg->msglen = 0 ; writemessage(outcontrolsock,buffer,MINMESSLEN,recvcontrolto,0); printmessage(stderr,CASE_FATAL_ERROR,101,timestamp,"Incompatible deamon and client (remote protocol version (%d,%d), local (%d,%d))\n",remoteprotomin,remoteprotomax,protocolmin,protocolmax); } else if (remoteprotomax <= protocolmax ) { protocol = remoteprotomax ; } else { protocol = protocolmax ; } msg->code = MSG_PROT_ANS ; #ifndef WORDS_BIGENDIAN msg->msglen = ntohl(4) ; #else msg->msglen = 4 ; #endif if ( writemessage(outcontrolsock,buffer,MINMESSLEN,recvcontrolto,0) < 0 ){ printmessage(stderr,CASE_ERROR,64,timestamp,"Error sending %s message\n","MSG_PROT_ANS"); return -1 ; /* restart connection */ } #ifndef WORDS_BIGENDIAN msg->code = ntohl(protocol) ; #else msg->code = protocol ; #endif if ( writemessage(outcontrolsock,buffer,4,recvcontrolto,0) < 0 ){ printmessage(stderr,CASE_ERROR,64,timestamp,"Error sending %s message\n","MSG_PROT_ANS"); return -1 ; /* restart connection */ } return 0 ; } else { /* ** Receive unkwown message so something is ** going wrong. close the control socket ** and restart */ printmessage(stderr,CASE_ERROR,62,timestamp,"Unknown message while waiting for %s message\n","MSG_PROT_ANS"); return -1 ; } } /* ** Never reach this point but to in order to avoid stupid messages ** from IRIX compiler set a return code to -1 */ return -1 ; }
Response kConnection::receive_response() { Response r; auto s = readmessage(); r.ParseFromString(s); return r; }