Пример #1
0
/* send request, expect first block (or error) */
static int
tftp_makereq(struct tftp_handle *h)
{
	struct {
		u_char header[HEADER_SIZE];
		struct tftphdr  t;
		u_char space[FNAME_SIZE + 6];
	} __packed __aligned(4) wbuf;
	char           *wtail;
	int             l;
	ssize_t         res;
	struct tftphdr *t;
	char *tftp_blksize = NULL;
	int blksize_l;
	unsigned short rtype = 0;

	/*
	 * Allow overriding default TFTP block size by setting
	 * a tftp.blksize environment variable.
	 */
	if ((tftp_blksize = getenv("tftp.blksize")) != NULL) {
		tftp_set_blksize(h, tftp_blksize);
	}

	wbuf.t.th_opcode = htons((u_short) RRQ);
	wtail = wbuf.t.th_stuff;
	l = strlen(h->path);
#ifdef TFTP_PREPEND_PATH
	if (l > FNAME_SIZE - (sizeof(TFTP_PREPEND_PATH) - 1))
		return (ENAMETOOLONG);
	bcopy(TFTP_PREPEND_PATH, wtail, sizeof(TFTP_PREPEND_PATH) - 1);
	wtail += sizeof(TFTP_PREPEND_PATH) - 1;
#else
	if (l > FNAME_SIZE)
		return (ENAMETOOLONG);
#endif
	bcopy(h->path, wtail, l + 1);
	wtail += l + 1;
	bcopy("octet", wtail, 6);
	wtail += 6;
	bcopy("blksize", wtail, 8);
	wtail += 8;
	blksize_l = sprintf(wtail, "%d", h->tftp_blksize);
	wtail += blksize_l + 1;
	bcopy("tsize", wtail, 6);
	wtail += 6;
	bcopy("0", wtail, 2);
	wtail += 2;

	t = &h->lastdata.t;

	/* h->iodesc->myport = htons(--tftpport); */
	h->iodesc->myport = htons(tftpport + (getsecs() & 0x3ff));
	h->iodesc->destport = htons(IPPORT_TFTP);
	h->iodesc->xid = 1;	/* expected block */

	h->currblock = 0;
	h->islastblock = 0;
	h->validsize = 0;

	res = sendrecv_tftp(h, &sendudp, &wbuf.t, wtail - (char *) &wbuf.t,
		       &recvtftp, t, sizeof(*t) + h->tftp_blksize, &rtype);

	if (rtype == OACK)
		return (tftp_getnextblock(h));

	/* Server ignored our blksize request, revert to TFTP default. */
	h->tftp_blksize = SEGSIZE;

	switch (rtype) {
		case DATA: {
			h->currblock = 1;
			h->validsize = res;
			h->islastblock = 0;
			if (res < h->tftp_blksize) {
				h->islastblock = 1;	/* very short file */
				tftp_sendack(h);
			}
			return (0);
		}
		case ERROR:
		default:
			return (errno);
	}

}
Пример #2
0
static int
tftp_read(struct open_file *f, void *addr, size_t size,
    size_t *resid /* out */)
{
	struct tftp_handle *tftpfile;
	static int      tc = 0;
	tftpfile = (struct tftp_handle *) f->f_fsdata;

	while (size > 0) {
		int needblock, count;

		if (!(tc++ % 16))
			twiddle();

		needblock = tftpfile->off / tftpfile->tftp_blksize + 1;

		if (tftpfile->currblock > needblock) {	/* seek backwards */
			tftp_senderr(tftpfile, 0, "No error: read aborted");
			tftp_makereq(tftpfile);	/* no error check, it worked
						 * for open */
		}

		while (tftpfile->currblock < needblock) {
			int res;

			res = tftp_getnextblock(tftpfile);
			if (res) {	/* no answer */
#ifdef TFTP_DEBUG
				printf("tftp: read error\n");
#endif
				return (res);
			}
			if (tftpfile->islastblock)
				break;
		}

		if (tftpfile->currblock == needblock) {
			int offinblock, inbuffer;

			offinblock = tftpfile->off % tftpfile->tftp_blksize;

			inbuffer = tftpfile->validsize - offinblock;
			if (inbuffer < 0) {
#ifdef TFTP_DEBUG
				printf("tftp: invalid offset %d\n",
				    tftpfile->off);
#endif
				return (EINVAL);
			}
			count = (size < inbuffer ? size : inbuffer);
			bcopy(tftpfile->lastdata.t.th_data + offinblock,
			    addr, count);

			addr = (char *)addr + count;
			tftpfile->off += count;
			size -= count;

			if ((tftpfile->islastblock) && (count == inbuffer))
				break;	/* EOF */
		} else {
#ifdef TFTP_DEBUG
			printf("tftp: block %d not found\n", needblock);
#endif
			return (EINVAL);
		}

	}

	if (resid)
		*resid = size;
	return (0);
}
Пример #3
0
int
tftp_read(struct open_file *f, void *addr, size_t size, size_t *resid)
{
	struct tftp_handle *tftpfile;
#if !defined(LIBSA_NO_TWIDDLE)
	static int tc = 0;
#endif
	tftpfile = (struct tftp_handle *) f->f_fsdata;

	while (size > 0) {
		int needblock;
		size_t count;

		needblock = tftpfile->off / SEGSIZE + 1;

		if (tftpfile->currblock > needblock) {	/* seek backwards */
#ifndef TFTP_NOTERMINATE
			tftp_terminate(tftpfile);
#endif
			/* Don't bother to check retval: it worked for open() */
			tftp_makereq(tftpfile);
		}

		while (tftpfile->currblock < needblock) {
			int res;

#if !defined(LIBSA_NO_TWIDDLE)
			if ((tc++ % 16) == 0)
				twiddle();
#endif
			res = tftp_getnextblock(tftpfile);
			if (res) {	/* no answer */
#ifdef DEBUG
				printf("tftp: read error (block %d->%d)\n",
				    tftpfile->currblock, needblock);
#endif
				return res;
			}
			if (tftpfile->islastblock)
				break;
		}

		if (tftpfile->currblock == needblock) {
			size_t offinblock, inbuffer;

			offinblock = tftpfile->off % SEGSIZE;

			inbuffer = tftpfile->validsize - offinblock;
			if (inbuffer < 0) {
#ifdef DEBUG
				printf("tftp: invalid offset %d\n",
				    tftpfile->off);
#endif
				return EINVAL;
			}
			count = (size < inbuffer ? size : inbuffer);
			bcopy(tftpfile->lastdata.t.th_data + offinblock,
			    addr, count);

			addr = (caddr_t)addr + count;
			tftpfile->off += count;
			size -= count;

			if ((tftpfile->islastblock) && (count == inbuffer))
				break;	/* EOF */
		} else {
#ifdef DEBUG
			printf("tftp: block %d not found\n", needblock);
#endif
			return EINVAL;
		}

	}

	if (resid != NULL)
		*resid = size;
	return 0;
}