⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tftpd.c

📁 THIS IS HTTP CURL Example
💻 C
📖 第 1 页 / 共 2 页
字号:
      (sock, SOL_SOCKET, SO_REUSEADDR, (const void *) &flag,       sizeof(int)) < 0) {    perror("setsockopt(SO_REUSEADDR)");  }#ifdef ENABLE_IPV6  if(!use_ipv6) {#endif    me.sin_family = AF_INET;    me.sin_addr.s_addr = INADDR_ANY;    me.sin_port = htons(port);    rc = bind(sock, (struct sockaddr *) &me, sizeof(me));#ifdef ENABLE_IPV6  }  else {    memset(&me6, 0, sizeof(struct sockaddr_in6));    me6.sin6_family = AF_INET6;    me6.sin6_addr = in6addr_any;    me6.sin6_port = htons(port);    rc = bind(sock, (struct sockaddr *) &me6, sizeof(me6));  }#endif /* ENABLE_IPV6 */  if(rc < 0) {    perror("binding stream socket");    logmsg("Error binding socket");    return 1;  }  pidfile = fopen(pidname, "w");  if(pidfile) {    fprintf(pidfile, "%d\n", (int)getpid());    fclose(pidfile);  }  else {    error = ERRNO;    logmsg("fopen() failed with error: %d %s", error, strerror(error));    logmsg("Error opening file: %s", pidname);    logmsg("Couldn't write pid file");  }  logmsg("Running IPv%d version on port UDP/%d",#ifdef ENABLE_IPV6         (use_ipv6?6:4)#else         4#endif         , port );  do {    fromlen = sizeof(from);    n = recvfrom(sock, buf, sizeof (buf), 0,                 (struct sockaddr *)&from, &fromlen);    if (n < 0) {      logmsg("recvfrom:\n");      return 3;    }    from.sin_family = AF_INET;    peer = socket(AF_INET, SOCK_DGRAM, 0);    if (peer < 0) {      logmsg("socket:\n");      return 2;    }    if (connect(peer, (struct sockaddr *)&from, sizeof(from)) < 0) {      logmsg("connect: fail\n");      return 1;    }    maxtimeout = 5*TIMEOUT;    tp = (struct tftphdr *)buf;    tp->th_opcode = ntohs(tp->th_opcode);    if (tp->th_opcode == RRQ || tp->th_opcode == WRQ) {      memset(&test, 0, sizeof(test));      if (tftp(&test, tp, n) < 0)        break;      if(test.buffer)        free(test.buffer);    }    sclose(peer);  } while(1);  return 0;}struct formats {  const char *f_mode;  int f_convert;} formats[] = {  { "netascii",   1 },  { "octet",      0 },  { NULL,         0 }};/* * Handle initial connection protocol. */static int tftp(struct testcase *test, struct tftphdr *tp, int size){  char *cp;  int first = 1, ecode;  struct formats *pf;  char *filename, *mode = NULL;  int error;  FILE *server;  /* Open request dump file. */  server = fopen(REQUEST_DUMP, "ab");  if(!server) {    error = ERRNO;    logmsg("fopen() failed with error: %d %s", error, strerror(error));    logmsg("Error opening file: %s", REQUEST_DUMP);    return -1;  }  /* store input protocol */  fprintf(server, "opcode: %x\n", tp->th_opcode);  cp = (char *)&tp->th_stuff;  filename = cp;again:  while (cp < buf + size) {    if (*cp == '\0')      break;    cp++;  }  if (*cp) {    nak(EBADOP);    fclose(server);    return 3;  }  if (first) {    mode = ++cp;    first = 0;    goto again;  }  /* store input protocol */  fprintf(server, "filename: %s\n", filename);  for (cp = mode; *cp; cp++)    if(ISUPPER(*cp))      *cp = (char)tolower((int)*cp);  /* store input protocol */  fprintf(server, "mode: %s\n", mode);  fclose(server);  for (pf = formats; pf->f_mode; pf++)    if (strcmp(pf->f_mode, mode) == 0)      break;  if (!pf->f_mode) {    nak(EBADOP);    return 2;  }  ecode = validate_access(test, filename, tp->th_opcode);  if (ecode) {    nak(ecode);    return 1;  }  if (tp->th_opcode == WRQ)    recvtftp(test, pf);  else    sendtftp(test, pf);  return 0;}/* * Validate file access. */static int validate_access(struct testcase *test,                           const char *filename, int mode){  char *ptr;  long testno, partno;  int error;  char partbuf[80]="data";  logmsg("trying to get file: %s mode %x", filename, mode);  if(!strncmp("verifiedserver", filename, 15)) {    char weare[128];    size_t count = sprintf(weare, "WE ROOLZ: %d\r\n", (int)getpid());    logmsg("Are-we-friendly question received");    test->buffer = strdup(weare);    test->rptr = test->buffer; /* set read pointer */    test->bufsize = count;    /* set total count */    test->rcount = count;     /* set data left to read */    return 0; /* fine */  }  /* find the last slash */  ptr = strrchr(filename, '/');  if(ptr) {    char *file;    ptr++; /* skip the slash */    /* skip all non-numericals following the slash */    while(*ptr && !ISDIGIT(*ptr))      ptr++;    /* get the number */    testno = strtol(ptr, &ptr, 10);    if(testno > 10000) {      partno = testno % 10000;      testno /= 10000;    }    else      partno = 0;    logmsg("requested test number %ld part %ld", testno, partno);    test->num = testno;    file = test2file(testno);    if(0 != partno)      sprintf(partbuf, "data%ld", partno);    if(file) {      FILE *stream=fopen(file, "rb");      if(!stream) {        error = ERRNO;        logmsg("fopen() failed with error: %d %s", error, strerror(error));        logmsg("Error opening file: %s", file);        logmsg("Couldn't open test file: %s", file);        return EACCESS;      }      else {        size_t count;        test->buffer = (char *)spitout(stream, "reply", partbuf, &count);        fclose(stream);        if(test->buffer) {          test->rptr = test->buffer; /* set read pointer */          test->bufsize = count;    /* set total count */          test->rcount = count;     /* set data left to read */        }        else          return EACCESS;      }    }    else      return EACCESS;  }  else {    logmsg("no slash found in path");    return EACCESS; /* failure */  }  return 0;}int timeout;#ifdef HAVE_SIGSETJMPsigjmp_buf timeoutbuf;#endifstatic void timer(int signum){  (void)signum;  logmsg("alarm!");  timeout += rexmtval;  if (timeout >= maxtimeout)    exit(1);#ifdef HAVE_SIGSETJMP  siglongjmp(timeoutbuf, 1);#endif}/* * Send the requested file. */static void sendtftp(struct testcase *test, struct formats *pf){  struct tftphdr *dp;  struct tftphdr *ap;    /* ack packet */  unsigned short block = 1;  int size;  ssize_t n;#if defined(HAVE_ALARM) && defined(SIGALRM)  mysignal(SIGALRM, timer);#endif  dp = r_init();  ap = (struct tftphdr *)ackbuf;  do {    size = readit(test, &dp, pf->f_convert);    if (size < 0) {      nak(ERRNO + 100);      return;    }    dp->th_opcode = htons((u_short)DATA);    dp->th_block = htons((u_short)block);    timeout = 0;#ifdef HAVE_SIGSETJMP    (void) sigsetjmp(timeoutbuf, 1);#endif    send_data:    if (swrite(peer, dp, size + 4) != size + 4) {      logmsg("write\n");      return;    }    read_ahead(test, pf->f_convert);    for ( ; ; ) {#ifdef HAVE_ALARM      alarm(rexmtval);        /* read the ack */#endif      n = sread(peer, ackbuf, sizeof (ackbuf));#ifdef HAVE_ALARM      alarm(0);#endif      if (n < 0) {        logmsg("read: fail\n");        return;      }      ap->th_opcode = ntohs((u_short)ap->th_opcode);      ap->th_block = ntohs((u_short)ap->th_block);      if (ap->th_opcode == ERROR) {        logmsg("got ERROR");        return;      }      if (ap->th_opcode == ACK) {        if (ap->th_block == block) {          break;        }        /* Re-synchronize with the other side */        (void) synchnet(peer);        if (ap->th_block == (block -1)) {          goto send_data;        }      }    }    block++;  } while (size == SEGSIZE);}static void justtimeout(int signum){  (void)signum;}/* * Receive a file. */static void recvtftp(struct testcase *test, struct formats *pf){  struct tftphdr *dp;  struct tftphdr *ap;    /* ack buffer */  unsigned short block = 0;  ssize_t n, size;#if defined(HAVE_ALARM) && defined(SIGALRM)  mysignal(SIGALRM, timer);#endif  dp = w_init();  ap = (struct tftphdr *)ackbuf;  do {    timeout = 0;    ap->th_opcode = htons((u_short)ACK);    ap->th_block = htons((u_short)block);    block++;#ifdef HAVE_SIGSETJMP    (void) sigsetjmp(timeoutbuf, 1);#endifsend_ack:    if (swrite(peer, ackbuf, 4) != 4) {      logmsg("write: fail\n");      goto abort;    }    write_behind(test, pf->f_convert);    for ( ; ; ) {#ifdef HAVE_ALARM      alarm(rexmtval);#endif      n = sread(peer, dp, PKTSIZE);#ifdef HAVE_ALARM      alarm(0);#endif      if (n < 0) {                       /* really? */        logmsg("read: fail\n");        goto abort;      }      dp->th_opcode = ntohs((u_short)dp->th_opcode);      dp->th_block = ntohs((u_short)dp->th_block);      if (dp->th_opcode == ERROR)        goto abort;      if (dp->th_opcode == DATA) {        if (dp->th_block == block) {          break;                         /* normal */        }        /* Re-synchronize with the other side */        (void) synchnet(peer);        if (dp->th_block == (block-1))          goto send_ack;                 /* rexmit */      }    }    size = writeit(test, &dp, (int)(n - 4), pf->f_convert);    if (size != (n-4)) {                 /* ahem */      if (size < 0)        nak(ERRNO + 100);      else        nak(ENOSPACE);      goto abort;    }  } while (size == SEGSIZE);  write_behind(test, pf->f_convert);  ap->th_opcode = htons((u_short)ACK);   /* send the "final" ack */  ap->th_block = htons((u_short)(block));  (void) swrite(peer, ackbuf, 4);#if defined(HAVE_ALARM) && defined(SIGALRM)  mysignal(SIGALRM, justtimeout);        /* just abort read on timeout */  alarm(rexmtval);#endif  n = sread(peer, buf, sizeof(buf));     /* normally times out and quits */#ifdef HAVE_ALARM  alarm(0);#endif  if (n >= 4 &&                          /* if read some data */      dp->th_opcode == DATA &&           /* and got a data block */      block == dp->th_block) {           /* then my last ack was lost */    (void) swrite(peer, ackbuf, 4);      /* resend final ack */  }abort:  return;}struct errmsg {  int e_code;  const char *e_msg;} errmsgs[] = {  { EUNDEF,       "Undefined error code" },  { ENOTFOUND,    "File not found" },  { EACCESS,      "Access violation" },  { ENOSPACE,     "Disk full or allocation exceeded" },  { EBADOP,       "Illegal TFTP operation" },  { EBADID,       "Unknown transfer ID" },  { EEXISTS,      "File already exists" },  { ENOUSER,      "No such user" },  { -1,           0 }};/* * Send a nak packet (error message).  Error code passed in is one of the * standard TFTP codes, or a UNIX errno offset by 100. */static void nak(int error){  struct tftphdr *tp;  int length;  struct errmsg *pe;  tp = (struct tftphdr *)buf;  tp->th_opcode = htons((u_short)ERROR);  tp->th_code = htons((u_short)error);  for (pe = errmsgs; pe->e_code >= 0; pe++)    if (pe->e_code == error)      break;  if (pe->e_code < 0) {    pe->e_msg = strerror(error - 100);    tp->th_code = EUNDEF;   /* set 'undef' errorcode */  }  strcpy(tp->th_msg, pe->e_msg);  length = (int)strlen(pe->e_msg);  tp->th_msg[length] = '\0';  length += 5;  if (swrite(peer, buf, length) != length)    logmsg("nak: fail\n");}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -