Пример #1
0
/*
 * Receive a file.
 */
static void recvtftp(struct testcase *test, struct formats *pf)
{
  ssize_t n, size;
  recvblock = 0;
#if defined(HAVE_ALARM) && defined(SIGALRM)
  mysignal(SIGALRM, timer);
#endif
  rdp = w_init();
  rap = (struct tftphdr *)ackbuf;
  do {
    timeout = 0;
    rap->th_opcode = htons((u_short)opcode_ACK);
    rap->th_block = htons((u_short)recvblock);
    recvblock++;
#ifdef HAVE_SIGSETJMP
    (void) sigsetjmp(timeoutbuf, 1);
#endif
send_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, rdp, PKTSIZE);
#ifdef HAVE_ALARM
      alarm(0);
#endif
      if (n < 0) {                       /* really? */
        logmsg("read: fail\n");
        goto abort;
      }
      rdp->th_opcode = ntohs((u_short)rdp->th_opcode);
      rdp->th_block = ntohs((u_short)rdp->th_block);
      if (rdp->th_opcode == opcode_ERROR)
        goto abort;
      if (rdp->th_opcode == opcode_DATA) {
        if (rdp->th_block == recvblock) {
          break;                         /* normal */
        }
        /* Re-synchronize with the other side */
        (void) synchnet(peer);
        if (rdp->th_block == (recvblock-1))
          goto send_ack;                 /* rexmit */
      }
    }

    size = writeit(test, &rdp, (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);

  rap->th_opcode = htons((u_short)opcode_ACK);  /* send the "final" ack */
  rap->th_block = htons((u_short)recvblock);
  (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 */
      rdp->th_opcode == opcode_DATA &&   /* and got a data block */
      recvblock == rdp->th_block) {      /* then my last ack was lost */
    (void) swrite(peer, ackbuf, 4);      /* resend final ack */
  }
abort:
  return;
}
Пример #2
0
/*
 * Receive a file.
 */
static void recvtftp(struct testcase *test, struct formats *pf)
{
  struct tftphdr *dp;
  struct tftphdr *ap;    /* ack buffer */
  unsigned short block = 0;
  int 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);
#endif
send_ack:
    if (send(peer, ackbuf, 4, 0) != 4) {
      logmsg("write: fail\n");
      goto abort;
    }
    write_behind(test, pf->f_convert);
    for ( ; ; ) {
#ifdef HAVE_ALARM
      alarm(rexmtval);
#endif
      n = recv(peer, dp, PKTSIZE, 0);
#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, 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) send(peer, ackbuf, 4, 0);
#if defined(HAVE_ALARM) && defined(SIGALRM)
  mysignal(SIGALRM, justquit);           /* just quit on timeout */
  alarm(rexmtval);
#endif
  n = recv(peer, buf, sizeof (buf), 0);  /* 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) send(peer, ackbuf, 4, 0);     /* resend final ack */
  }
abort:
  return;
}
Пример #3
0
/*
 * Send the requested file.
 */
static void sendtftp(struct testcase *test, struct formats *pf)
{
  int size;
  ssize_t n;
  sendblock = 1;
#if defined(HAVE_ALARM) && defined(SIGALRM)
  mysignal(SIGALRM, timer);
#endif
  sdp = r_init();
  sap = (struct tftphdr *)ackbuf;
  do {
    size = readit(test, &sdp, pf->f_convert);
    if (size < 0) {
      nak(ERRNO + 100);
      return;
    }
    sdp->th_opcode = htons((u_short)opcode_DATA);
    sdp->th_block = htons((u_short)sendblock);
    timeout = 0;
#ifdef HAVE_SIGSETJMP
    (void) sigsetjmp(timeoutbuf, 1);
#endif
    send_data:
    if (swrite(peer, sdp, size + 4) != size + 4) {
      logmsg("write");
      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");
        return;
      }
      sap->th_opcode = ntohs((u_short)sap->th_opcode);
      sap->th_block = ntohs((u_short)sap->th_block);

      if (sap->th_opcode == opcode_ERROR) {
        logmsg("got ERROR");
        return;
      }

      if (sap->th_opcode == opcode_ACK) {
        if (sap->th_block == sendblock) {
          break;
        }
        /* Re-synchronize with the other side */
        (void) synchnet(peer);
        if (sap->th_block == (sendblock-1)) {
          goto send_data;
        }
      }

    }
    sendblock++;
  } while (size == SEGSIZE);
}
Пример #4
0
/*
 * Send the requested file.
 */
static void sendtftp(struct testcase *test, struct formats *pf)
{
  int size;
  ssize_t n;
  /* These are volatile to live through a siglongjmp */
  volatile unsigned short sendblock; /* block count */
  struct tftphdr * volatile sdp = r_init(); /* data buffer */
  struct tftphdr * const sap = &ackbuf.hdr; /* ack buffer */

  sendblock = 1;
#if defined(HAVE_ALARM) && defined(SIGALRM)
  mysignal(SIGALRM, timer);
#endif
  do {
    size = readit(test, (struct tftphdr **)&sdp, pf->f_convert);
    if(size < 0) {
      nak(errno + 100);
      return;
    }
    sdp->th_opcode = htons((unsigned short)opcode_DATA);
    sdp->th_block = htons(sendblock);
    timeout = 0;
#ifdef HAVE_SIGSETJMP
    (void) sigsetjmp(timeoutbuf, 1);
#endif
    if(test->writedelay) {
      logmsg("Pausing %d seconds before %d bytes", test->writedelay,
             size);
      wait_ms(1000*test->writedelay);
    }

    send_data:
    if(swrite(peer, sdp, size + 4) != size + 4) {
      logmsg("write");
      return;
    }
    read_ahead(test, pf->f_convert);
    for(;;) {
#ifdef HAVE_ALARM
      alarm(rexmtval);        /* read the ack */
#endif
      n = sread(peer, &ackbuf.storage[0], sizeof(ackbuf.storage));
#ifdef HAVE_ALARM
      alarm(0);
#endif
      if(got_exit_signal)
        return;
      if(n < 0) {
        logmsg("read: fail");
        return;
      }
      sap->th_opcode = ntohs((unsigned short)sap->th_opcode);
      sap->th_block = ntohs(sap->th_block);

      if(sap->th_opcode == opcode_ERROR) {
        logmsg("got ERROR");
        return;
      }

      if(sap->th_opcode == opcode_ACK) {
        if(sap->th_block == sendblock) {
          break;
        }
        /* Re-synchronize with the other side */
        (void) synchnet(peer);
        if(sap->th_block == (sendblock-1)) {
          goto send_data;
        }
      }

    }
    sendblock++;
  } while(size == SEGSIZE);
}
Пример #5
0
/*
 * 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, 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 (send(peer, dp, size + 4, 0) != size + 4) {
      logmsg("write\n");
      return;
    }
    read_ahead(test, pf->f_convert);
    for ( ; ; ) {
#ifdef HAVE_ALARM
      alarm(rexmtval);        /* read the ack */
#endif
      n = recv(peer, ackbuf, sizeof (ackbuf), 0);
#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);
}
Пример #6
0
/*
 * Send the requested file.
 */
int tftp_sendfile(int f, union sock_addr *peeraddr,
		   int fd, const char *name, const char *mode)
{
    struct tftphdr *ap;         /* data and ack packets */
    struct tftphdr *dp;
    int n;
    volatile int is_request;
    volatile u_short block;
    volatile int size, convert;
    volatile off_t amount;
    union sock_addr from;
    socklen_t fromlen;
    FILE *file;
    u_short ap_opcode, ap_block;

    startclock();               /* start stat's clock */
    dp = r_init();              /* reset fillbuf/read-ahead code */
    ap = (struct tftphdr *)ackbuf;
    convert = !strcmp(mode, "netascii");
    file = fdopen(fd, convert ? "rt" : "rb");
    block = 0;
    is_request = 1;             /* First packet is the actual WRQ */
    amount = 0;

    bsd_signal(SIGALRM, timer);
    do {
        if (is_request) {
            size = makerequest(WRQ, name, dp, mode) - 4;
        } else {
            /*      size = read(fd, dp->th_data, SEGSIZE);   */
            size = readit(file, &dp, convert);
            if (size < 0) {
                nak(f, peeraddr, errno + 100, NULL);
                break;
            }
            dp->th_opcode = htons((u_short) DATA);
            dp->th_block = htons((u_short) block);
        }
        timeout = 0;
        (void)sigsetjmp(timeoutbuf, 1);

        if (trace)
            tpacket("sent", dp, size + 4);
        n = sendto(f, dp, size + 4, 0,
                   &(peeraddr->sa), SOCKLEN(peeraddr));
        if (n != size + 4) {
            perror("tftp: sendto");
            goto abort;
        }
        read_ahead(file, convert);
        for (;;) {
            alarm(rexmtval);
            do {
                fromlen = sizeof(from);
                n = recvfrom(f, ackbuf, sizeof(ackbuf), 0,
                             &from.sa, &fromlen);
            } while (n <= 0);
            alarm(0);
            if (n < 0) {
                perror("tftp: recvfrom");
                goto abort;
            }
            sa_set_port(peeraddr, SOCKPORT(&from));  /* added */
            if (trace)
                tpacket("received", ap, n);
            /* should verify packet came from server */
            ap_opcode = ntohs((u_short) ap->th_opcode);
            ap_block = ntohs((u_short) ap->th_block);
            if (ap_opcode == ERROR) {
                printf("Error code %d: %s\n", ap_block, ap->th_msg);
                goto abort;
            }
            if (ap_opcode == ACK) {
                int j;

                if (ap_block == block) {
                    break;
                }
                /* On an error, try to synchronize
                 * both sides.
                 */
                j = synchnet(f);
                if (j && trace) {
                    printf("discarded %d packets\n", j);
                }
                /*
                 * RFC1129/RFC1350: We MUST NOT re-send the DATA
                 * packet in response to an invalid ACK.  Doing so
                 * would cause the Sorcerer's Apprentice bug.
                 */
            }
        }
        if (!is_request)
            amount += size;
        is_request = 0;
        block++;
    } while (size == SEGSIZE || block == 1);
  abort:
    fclose(file);
    stopclock();
    //if (amount > 0)
    //    printstats("Sent", amount);
    return amount;
}
Пример #7
0
/*
 * Send a file via the TFTP data session.
 */
void
tftp_send(int peer, uint16_t *block, struct tftp_stats *ts)
{
	struct tftphdr *rp;
	int size, n_data, n_ack, try;
	uint16_t oldblock;
	char sendbuffer[MAXPKTSIZE];
	char recvbuffer[MAXPKTSIZE];

	rp = (struct tftphdr *)recvbuffer;
	*block = 1;
	ts->amount = 0;
	do {
		if (debug&DEBUG_SIMPLE)
			tftp_log(LOG_DEBUG, "Sending block %d", *block);

		size = read_file(sendbuffer, segsize);
		if (size < 0) {
			tftp_log(LOG_ERR, "read_file returned %d", size);
			send_error(peer, errno + 100);
			goto abort;
		}

		for (try = 0; ; try++) {
			n_data = send_data(peer, *block, sendbuffer, size);
			if (n_data > 0) {
				if (try == maxtimeouts) {
					tftp_log(LOG_ERR,
					    "Cannot send DATA packet #%d, "
					    "giving up", *block);
					return;
				}
				tftp_log(LOG_ERR,
				    "Cannot send DATA packet #%d, trying again",
				    *block);
				continue;
			}

			n_ack = receive_packet(peer, recvbuffer,
			    MAXPKTSIZE, NULL, timeoutpacket);
			if (n_ack < 0) {
				if (n_ack == RP_TIMEOUT) {
					if (try == maxtimeouts) {
						tftp_log(LOG_ERR,
						    "Timeout #%d send ACK %d "
						    "giving up", try, *block);
						return;
					}
					tftp_log(LOG_WARNING,
					    "Timeout #%d on ACK %d",
					    try, *block);
					continue;
				}

				/* Either read failure or ERROR packet */
				if (debug&DEBUG_SIMPLE)
					tftp_log(LOG_ERR, "Aborting: %s",
					    rp_strerror(n_ack));
				goto abort;
			}
			if (rp->th_opcode == ACK) {
				ts->blocks++;
				if (rp->th_block == *block) {
					ts->amount += size;
					break;
				}

				/* Re-synchronize with the other side */
				(void) synchnet(peer);
				if (rp->th_block == (*block - 1)) {
					ts->retries++;
					continue;
				}
			}

		}
		oldblock = *block;
		(*block)++;
		if (oldblock > *block) {
			if (options[OPT_ROLLOVER].o_request == NULL) {
				/*
				 * "rollover" option not specified in
				 * tftp client.  Default to rolling block
				 * counter to 0.
				 */
				*block = 0;
			} else {
				*block = atoi(options[OPT_ROLLOVER].o_request);
			}

			ts->rollovers++;
		}
		gettimeofday(&(ts->tstop), NULL);
	} while (size == segsize);
abort:
	return;
}

/*
 * Receive a file via the TFTP data session.
 *
 * - It could be that the first block has already arrived while
 *   trying to figure out if we were receiving options or not. In
 *   that case it is passed to this function.
 */
void
tftp_receive(int peer, uint16_t *block, struct tftp_stats *ts,
    struct tftphdr *firstblock, size_t fb_size)
{
	struct tftphdr *rp;
	uint16_t oldblock;
	int n_data, n_ack, writesize, i, retry;
	char recvbuffer[MAXPKTSIZE];

	ts->amount = 0;

	if (firstblock != NULL) {
		writesize = write_file(firstblock->th_data, fb_size);
		ts->amount += writesize;
		for (i = 0; ; i++) {
			n_ack = send_ack(peer, *block);
			if (n_ack > 0) {
				if (i == maxtimeouts) {
					tftp_log(LOG_ERR,
					    "Cannot send ACK packet #%d, "
					    "giving up", *block);
					return;
				}
				tftp_log(LOG_ERR,
				    "Cannot send ACK packet #%d, trying again",
				    *block);
				continue;
			}

			break;
		}

		if (fb_size != segsize) {
			gettimeofday(&(ts->tstop), NULL);
			return;
		}
	}

	rp = (struct tftphdr *)recvbuffer;
	do {
		oldblock = *block;
		(*block)++;
		if (oldblock > *block) {
			if (options[OPT_ROLLOVER].o_request == NULL) {
				/*
				 * "rollover" option not specified in
				 * tftp client.  Default to rolling block
				 * counter to 0.
				 */
				*block = 0;
			} else {
				*block = atoi(options[OPT_ROLLOVER].o_request);
			}

			ts->rollovers++;
		}

		for (retry = 0; ; retry++) {
			if (debug&DEBUG_SIMPLE)
				tftp_log(LOG_DEBUG,
				    "Receiving DATA block %d", *block);

			n_data = receive_packet(peer, recvbuffer,
			    MAXPKTSIZE, NULL, timeoutpacket);
			if (n_data < 0) {
				if (retry == maxtimeouts) {
					tftp_log(LOG_ERR,
					    "Timeout #%d on DATA block %d, "
					    "giving up", retry, *block);
					return;
				}
				if (n_data == RP_TIMEOUT) {
					tftp_log(LOG_WARNING,
					    "Timeout #%d on DATA block %d",
					    retry, *block);
					send_ack(peer, oldblock);
					continue;
				}

				/* Either read failure or ERROR packet */
				if (debug&DEBUG_SIMPLE)
					tftp_log(LOG_DEBUG, "Aborting: %s",
					    rp_strerror(n_data));
				goto abort;
			}
			if (rp->th_opcode == DATA) {
				ts->blocks++;

				if (rp->th_block == *block)
					break;

				tftp_log(LOG_WARNING,
				    "Expected DATA block %d, got block %d",
				    *block, rp->th_block);

				/* Re-synchronize with the other side */
				(void) synchnet(peer);
				if (rp->th_block == (*block-1)) {
					tftp_log(LOG_INFO, "Trying to sync");
					*block = oldblock;
					ts->retries++;
					goto send_ack;	/* rexmit */
				}

			} else {
				tftp_log(LOG_WARNING,
				    "Expected DATA block, got %s block",
				    packettype(rp->th_opcode));
			}
		}

		if (n_data > 0) {
			writesize = write_file(rp->th_data, n_data);
			ts->amount += writesize;
			if (writesize <= 0) {
				tftp_log(LOG_ERR,
				    "write_file returned %d", writesize);
				if (writesize < 0)
					send_error(peer, errno + 100);
				else
					send_error(peer, ENOSPACE);
				goto abort;
			}
		}

send_ack:
		for (i = 0; ; i++) {
			n_ack = send_ack(peer, *block);
			if (n_ack > 0) {

				if (i == maxtimeouts) {
					tftp_log(LOG_ERR,
					    "Cannot send ACK packet #%d, "
					    "giving up", *block);
					return;
				}

				tftp_log(LOG_ERR,
				    "Cannot send ACK packet #%d, trying again",
				    *block);
				continue;
			}

			break;
		}
		gettimeofday(&(ts->tstop), NULL);
	} while (n_data == segsize);

	/* Don't do late packet management for the client implementation */
	if (acting_as_client)
		return;

	for (i = 0; ; i++) {
		n_data = receive_packet(peer, (char *)rp, pktsize,
		    NULL, timeoutpacket);
		if (n_data <= 0)
			break;
		if (n_data > 0 &&
		    rp->th_opcode == DATA &&	/* and got a data block */
		    *block == rp->th_block)	/* then my last ack was lost */
			send_ack(peer, *block);	/* resend final ack */
	}

abort:
	return;
}
Пример #8
0
/*
 * Receive a file.
 */
int tftp_recvfile(int f, union sock_addr *peeraddr,
		   int fd, const char *name, const char *mode)
{
    struct tftphdr *ap;
    struct tftphdr *dp;
    int n;
    volatile u_short block;
    volatile int size, firsttrip;
    volatile unsigned long amount;
    union sock_addr from;
    socklen_t fromlen;
    FILE *file;
    volatile int convert;       /* true if converting crlf -> lf */
    u_short dp_opcode, dp_block;

    startclock();
    dp = w_init();
    ap = (struct tftphdr *)ackbuf;
    convert = !strcmp(mode, "netascii");
    file = fdopen(fd, convert ? "wt" : "wb");
    block = 1;
    firsttrip = 1;
    amount = 0;

    bsd_signal(SIGALRM, timer);
    do {
        if (firsttrip) {
            size = makerequest(RRQ, name, ap, mode);
            firsttrip = 0;
        } else {
            ap->th_opcode = htons((u_short) ACK);
            ap->th_block = htons((u_short) block);
            size = 4;
            block++;
        }
        timeout = 0;
        (void)sigsetjmp(timeoutbuf, 1);
      send_ack:
        if (trace)
            tpacket("sent", ap, size);
        if (sendto(f, ackbuf, size, 0, &(peeraddr->sa),
                   SOCKLEN(peeraddr)) != size) {
            alarm(0);
            perror("tftp: sendto");
            goto abort;
        }
        write_behind(file, convert);
        for (;;) {
            alarm(rexmtval);
            do {
                fromlen = sizeof(from);
                n = recvfrom(f, dp, PKTSIZE, 0,
                             &from.sa, &fromlen);
            } while (n <= 0);
            alarm(0);
            if (n < 0) {
                perror("tftp: recvfrom");
                goto abort;
            }
            sa_set_port(peeraddr, SOCKPORT(&from));  /* added */
            if (trace)
                tpacket("received", dp, n);
            /* should verify client address */
            dp_opcode = ntohs((u_short) dp->th_opcode);
            dp_block = ntohs((u_short) dp->th_block);
            if (dp_opcode == ERROR) {
                printf("Error code %d: %s\n", dp_block, dp->th_msg);
                goto abort;
            }
            if (dp_opcode == DATA) {
                int j;

                if (dp_block == block) {
                    break;      /* have next packet */
                }
                /* On an error, try to synchronize
                 * both sides.
                 */
                j = synchnet(f);
                if (j && trace) {
                    printf("discarded %d packets\n", j);
                }
                if (dp_block == (block - 1)) {
                    goto send_ack;      /* resend ack */
                }
            }
        }
        /*      size = write(fd, dp->th_data, n - 4); */
        size = writeit(file, &dp, n - 4, convert);
        if (size < 0) {
            nak(f, peeraddr, errno + 100, NULL);
            break;
        }
        amount += size;
    } while (size == SEGSIZE);
  abort:                       /* ok to ack, since user */
    ap->th_opcode = htons((u_short) ACK);       /* has seen err msg */
    ap->th_block = htons((u_short) block);
    (void)sendto(f, ackbuf, 4, 0, (struct sockaddr *)peeraddr,
                 SOCKLEN(peeraddr));
    write_behind(file, convert);        /* flush last buffer */
    fclose(file);
    stopclock();
    //if (amount > 0)
    //    printstats("Received", amount);
    return amount;
}
Пример #9
0
/*
 * Send the requested file.
 */
void
sendfile(int fd, char *name, char *mode)
{
	register struct tftphdr *ap;       /* data and ack packets */
	struct tftphdr *dp;
	volatile int block = 0, size = 0;
	int n;
	volatile unsigned long amount = 0;
	struct sockaddr_in from;
	socklen_t fromlen;
	volatile int convert;            /* true if doing nl->crlf conversion */
	FILE *file;

	startclock();           /* start stat's clock */
	dp = r_init();          /* reset fillbuf/read-ahead code */
	ap = (struct tftphdr *)ackbuf;
	file = fdopen(fd, "r");
	convert = !strcmp(mode, "netascii");

	signal(SIGALRM, timer);
	do {
		if (block == 0)
			size = makerequest(WRQ, name, dp, mode) - 4;
		else {
		/*      size = read(fd, dp->th_data, SEGSIZE);   */
			size = readit(file, &dp, convert);
			if (size < 0) {
				nak(errno + 100);
				break;
			}
			dp->th_opcode = htons((u_short)DATA);
			dp->th_block = htons((u_short)block);
		}
		timeout = 0;
		(void) sigsetjmp(timeoutbuf, 1);
send_data:
		if (trace)
			tpacket("sent", dp, size + 4);
		n = sendto(f, dp, size + 4, 0,
		    (struct sockaddr *)&s_inn, sizeof(s_inn));
		if (n != size + 4) {
			perror("tftp: sendto");
			goto abort;
		}
		read_ahead(file, convert);
		for ( ; ; ) {
			alarm(rexmtval);
			do {
				fromlen = sizeof (from);
				n = recvfrom(f, ackbuf, sizeof (ackbuf), 0,
				    (struct sockaddr *)&from, &fromlen);
			} while (n <= 0);
			alarm(0);
			if (n < 0) {
				perror("tftp: recvfrom");
				goto abort;
			}
			s_inn.sin_port = from.sin_port;   /* added */
			if (trace)
				tpacket("received", ap, n);
			/* should verify packet came from server */
			ap->th_opcode = ntohs(ap->th_opcode);
			ap->th_block = ntohs(ap->th_block);
			if (ap->th_opcode == ERROR) {
				printf("Error code %d: %s\n", ap->th_code,
					ap->th_msg);
				goto abort;
			}
			if (ap->th_opcode == ACK) {
				volatile int j = 0;

				if (ap->th_block == block) {
					break;
				}
				/* On an error, try to synchronize
				 * both sides.
				 */
				j = synchnet(f);
				if (j && trace) {
					printf("discarded %d packets\n",
							j);
				}
				if (ap->th_block == (block-1)) {
					goto send_data;
				}
			}
		}
		if (block > 0)
			amount += size;
		block++;
	} while (size == SEGSIZE || block == 1);
abort:
	fclose(file);
	stopclock();
	if (amount > 0)
		printstats("Sent", amount);
}
Пример #10
0
/*
 * Receive a file.
 */
void
recvfile(struct formats *pf)
{
	struct tftphdr *dp;
	struct tftphdr *ap;    /* ack buffer */
	int n, size;
	volatile unsigned short block;

	signal(SIGALRM, timer);
	dp = w_init();
	ap = (struct tftphdr *)ackbuf;
	block = 0;
	do {
		timeouts = 0;
		ap->th_opcode = htons((u_short)ACK);
		ap->th_block = htons((u_short)block);
		block++;
		(void) setjmp(timeoutbuf);
send_ack:
		if (send(peer, ackbuf, 4, 0) != 4) {
			syslog(LOG_ERR, "write: %m");
			goto abort;
		}
		write_behind(file, pf->f_convert);
		for ( ; ; ) {
			alarm(rexmtval);
			n = recv(peer, dp, PKTSIZE, 0);
			alarm(0);
			if (n < 0) {            /* really? */
				syslog(LOG_ERR, "read: %m");
				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 = write(file, dp->th_data, n - 4); */
		size = writeit(file, &dp, 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(file, pf->f_convert);
	(void) fclose(file);            /* close data file */

	ap->th_opcode = htons((u_short)ACK);    /* send the "final" ack */
	ap->th_block = htons((u_short)(block));
	(void) send(peer, ackbuf, 4, 0);

	signal(SIGALRM, justquit);      /* just quit on timeout */
	alarm(rexmtval);
	n = recv(peer, buf, sizeof (buf), 0); /* normally times out and quits */
	alarm(0);
	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) send(peer, ackbuf, 4, 0);     /* resend final ack */
	}
abort:
	return;
}
Пример #11
0
/*
 * Send the requested file.
 */
void
xmitfile(struct formats *pf)
{
	struct tftphdr *dp;
	struct tftphdr *ap;    /* ack packet */
	int size, n;
	volatile unsigned short block;

	signal(SIGALRM, timer);
	dp = r_init();
	ap = (struct tftphdr *)ackbuf;
	block = 1;
	do {
		size = readit(file, &dp, pf->f_convert);
		if (size < 0) {
			nak(errno + 100);
			goto abort;
		}
		dp->th_opcode = htons((u_short)DATA);
		dp->th_block = htons((u_short)block);
		timeouts = 0;
		(void)setjmp(timeoutbuf);

send_data:
		{
			int i, t = 1;
			for (i = 0; ; i++){
				if (send(peer, dp, size + 4, 0) != size + 4) {
					sleep(t);
					t = (t < 32) ? t<< 1 : t;
					if (i >= 12) {
						syslog(LOG_ERR, "write: %m");
						goto abort;
					}
				}
				break;
			}
		}
		read_ahead(file, pf->f_convert);
		for ( ; ; ) {
			alarm(rexmtval);        /* read the ack */
			n = recv(peer, ackbuf, sizeof (ackbuf), 0);
			alarm(0);
			if (n < 0) {
				syslog(LOG_ERR, "read: %m");
				goto abort;
			}
			ap->th_opcode = ntohs((u_short)ap->th_opcode);
			ap->th_block = ntohs((u_short)ap->th_block);

			if (ap->th_opcode == ERROR)
				goto abort;

			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);
abort:
	(void) fclose(file);
}
Пример #12
0
/*
 * Send the requested file.
 */
void send_file (struct formats *pf)
{
    struct tftphdr *dp, *r_init ();

    register struct tftphdr *ap;    /* ack packet */

    register int size, n;

    volatile int block;

    signal (SIGALRM, timer);
    dp = r_init ();
    ap = (struct tftphdr *) ackbuf;
    block = 1;
    do
    {
        size = readit (file, &dp, pf->f_convert);
        if (size < 0)
        {
            nak (errno + 100);
            goto abort;
        }
        dp->th_opcode = htons ((u_short) DATA);
        dp->th_block = htons ((u_short) block);
        timeout = 0;
        setjmp (timeoutbuf);

      send_data:
        if (send (peer, (const char *) dp, size + 4, 0) != size + 4)
        {
            syslog (LOG_ERR, "tftpd: write: %m\n");
            goto abort;
        }
        read_ahead (file, pf->f_convert);
        for (;;)
        {
            alarm (rexmtval);    /* read the ack */
            n = recv (peer, ackbuf, sizeof (ackbuf), 0);
            alarm (0);
            if (n < 0)
            {
                syslog (LOG_ERR, "tftpd: read: %m\n");
                goto abort;
            }
            ap->th_opcode = ntohs ((u_short) ap->th_opcode);
            ap->th_block = ntohs ((u_short) ap->th_block);

            if (ap->th_opcode == ERROR)
                goto abort;

            if (ap->th_opcode == ACK)
            {
                if ((u_short) ap->th_block == (u_short) block)
                    break;
                /* Re-synchronize with the other side */
                synchnet (peer);
                if ((u_short) ap->th_block == (u_short) (block - 1))
                    goto send_data;
            }

        }
        block++;
    }
    while (size == SEGSIZE);
  abort:
    fclose (file);
}