Skip to content

Commit

Permalink
Support TFTP options sent with read requests, write requests are not …
Browse files Browse the repository at this point in the history
…finished yet and most of this code is not ready.

- Support "blksize" and "tsize" TFTP options as per RFC 2347, RFC 2348, and RFC 2349, "timeout" is still missing
- Once again rewrote the way packets are parsed in ProcessPacket, this is MUCH simpler to understand now.
- Modified much of the core to use a dynamic block size instead of 512 bytes as to support "blksize"
- Remove OACK packet handling from ProcessPacket, a client will never send that packet and we would ignore it anyway.
  • Loading branch information
Justin Crawford authored and Justin Crawford committed Jan 9, 2015
1 parent 05761d6 commit 6e74dcd
Show file tree
Hide file tree
Showing 12 changed files with 202 additions and 143 deletions.
5 changes: 5 additions & 0 deletions include/client.h
Expand Up @@ -54,6 +54,11 @@ typedef struct client_s
// The client's Transfer ID, just the udp port // The client's Transfer ID, just the udp port
tid_t tid; tid_t tid;


// The block transfer size.
uint32_t blksize;
// An actual data block.
void *blk;

} client_t; } client_t;


typedef vec_t(client_t*) client_vec_t; typedef vec_t(client_t*) client_vec_t;
Expand Down
1 change: 0 additions & 1 deletion include/misc.h
Expand Up @@ -40,5 +40,4 @@ extern int SwitchUserAndGroup(const char *user, const char *group);
extern void Daemonize(void); extern void Daemonize(void);
extern int vasprintf(char **str, const char *fmt, va_list args); extern int vasprintf(char **str, const char *fmt, va_list args);
extern char *SizeReduce(size_t size); extern char *SizeReduce(size_t size);
extern char *GetBlockSize(size_t blocks);
extern char *stringify(const char *str, ...); extern char *stringify(const char *str, ...);
1 change: 1 addition & 0 deletions include/packets.h
Expand Up @@ -89,3 +89,4 @@ __attribute__((format(printf, 3, 4)))
extern void Error(client_t *client, const uint16_t errnum, const char *str, ...); extern void Error(client_t *client, const uint16_t errnum, const char *str, ...);
extern void Acknowledge(client_t *client, uint16_t blockno); extern void Acknowledge(client_t *client, uint16_t blockno);
extern void SendData(client_t *client, void *data, size_t len); extern void SendData(client_t *client, void *data, size_t len);
extern void OptionAcknowledge(client_t *c, const char *option, const char *param);
7 changes: 7 additions & 0 deletions src/client.c
Expand Up @@ -41,6 +41,7 @@ void AddClient(client_t *c)


// The transfer ID is given as the port. // The transfer ID is given as the port.
c->tid = -GetPort(c->s); c->tid = -GetPort(c->s);
c->blksize = 512;
} }


client_t *FindOrAllocateClient(socket_t cs) client_t *FindOrAllocateClient(socket_t cs)
Expand Down Expand Up @@ -96,6 +97,12 @@ void RemoveClient(client_t *c)
if (c->lastpacket.allocated) if (c->lastpacket.allocated)
free(c->lastpacket.p); free(c->lastpacket.p);


// Remove the client's block buffer.
if (c->blk)
free(c->blk);

printf("Removing client\n");

// Delete the client // Delete the client
free(c); free(c);
} }
Expand Down
9 changes: 2 additions & 7 deletions src/misc.c
Expand Up @@ -161,7 +161,7 @@ int SwitchUserAndGroup(const char *user, const char *group)
return 1; return 1;
} }
} }

// Check our directory permissions // Check our directory permissions
int r = access(config->directory, R_OK) + 1, w = access(config->directory, W_OK) + 1; int r = access(config->directory, R_OK) + 1, w = access(config->directory, W_OK) + 1;
if (!r && !w) if (!r && !w)
Expand Down Expand Up @@ -235,11 +235,6 @@ char *SizeReduce(size_t size)
return str; return str;
} }


char *GetBlockSize(size_t blocks)
{
return SizeReduce(blocks * 512);
}

char *stringify(const char *str, ...) char *stringify(const char *str, ...)
{ {
char *ret = NULL; char *ret = NULL;
Expand All @@ -248,4 +243,4 @@ char *stringify(const char *str, ...)
vasprintf(&ret, str, ap); vasprintf(&ret, str, ap);
va_end(ap); va_end(ap);
return ret; return ret;
} }
12 changes: 6 additions & 6 deletions src/multiplexers/multiplexer_epoll.c
Expand Up @@ -166,17 +166,17 @@ void ProcessSockets(void)
continue; continue;
} }


// process socket read events. // Process socket write events
if (ev->events & EPOLLIN && ReceivePackets(s) == -1) if (ev->events & EPOLLOUT && SendPackets(s) == -1)
{ {
bprintf("Destorying socket due to receive failure!\n"); bprintf("Destorying socket due to send failure!\n");
DestroySocket(s, 1); DestroySocket(s, 1);
} }


// Process socket write events // process socket read events.
if (ev->events & EPOLLOUT && SendPackets(s) == -1) if (ev->events & EPOLLIN && ReceivePackets(s) == -1)
{ {
bprintf("Destorying socket due to send failure!\n"); bprintf("Destorying socket due to receive failure!\n");
DestroySocket(s, 1); DestroySocket(s, 1);
} }
} }
Expand Down
12 changes: 6 additions & 6 deletions src/multiplexers/multiplexer_kqueue.c
Expand Up @@ -188,17 +188,17 @@ void ProcessSockets(void)
continue; continue;
} }


// process socket read events. // Process socket write events
if (ev->filter & EVFILT_READ && ReceivePackets(s) == -1) if (ev->filter & EVFILT_WRITE && SendPackets(s) == -1)
{ {
bprintf("Destorying socket due to receive failure!\n"); bprintf("Destorying socket due to send failure!\n");
DestroySocket(s, 1); DestroySocket(s, 1);
} }


// Process socket write events // process socket read events.
if (ev->filter & EVFILT_WRITE && SendPackets(s) == -1) if (ev->filter & EVFILT_READ && ReceivePackets(s) == -1)
{ {
bprintf("Destorying socket due to send failure!\n"); bprintf("Destorying socket due to receive failure!\n");
DestroySocket(s, 1); DestroySocket(s, 1);
} }
} }
Expand Down
8 changes: 4 additions & 4 deletions src/multiplexers/multiplexer_poll.c
Expand Up @@ -150,15 +150,15 @@ void ProcessSockets(void)
continue; continue;
} }


if (ev->revents & POLLIN && ReceivePackets(s) == -1) if (ev->revents & POLLOUT && SendPackets(s) == -1)
{ {
bprintf("Destorying socket due to receive failure!\n"); bprintf("Destorying socket due to send failure!\n");
DestroySocket(s, 1); DestroySocket(s, 1);
} }


if (ev->revents & POLLOUT && SendPackets(s) == -1) if (ev->revents & POLLIN && ReceivePackets(s) == -1)
{ {
bprintf("Destorying socket due to send failure!\n"); bprintf("Destorying socket due to receive failure!\n");
DestroySocket(s, 1); DestroySocket(s, 1);
} }
} }
Expand Down
8 changes: 4 additions & 4 deletions src/multiplexers/multiplexer_select.c
Expand Up @@ -126,15 +126,15 @@ void ProcessSockets(void)
continue; continue;
} }


if (has_read && ReceivePackets(s) == -1) if (has_write && SendPackets(s) == -1)
{ {
bprintf("Destorying socket due to receive failure!\n"); bprintf("Destorying socket due to send failure!\n");
DestroySocket(s, 1); DestroySocket(s, 1);
} }


if (has_write && SendPackets(s) == -1) if (has_read && ReceivePackets(s) == -1)
{ {
bprintf("Destorying socket due to send failure!\n"); bprintf("Destorying socket due to receive failure!\n");
DestroySocket(s, 1); DestroySocket(s, 1);
} }
} }
Expand Down
51 changes: 39 additions & 12 deletions src/packet.c
Expand Up @@ -32,15 +32,17 @@


void SendData(client_t *c, void *data, size_t len) void SendData(client_t *c, void *data, size_t len)
{ {
// Make sure the packet size does not exceed the max packet length. // Previously we would make sure the data packets do not exceed a certain length
assert((len + sizeof(packet_t) <= MAX_PACKET_SIZE)); // but that would violate the blksize extension and therefore we trust that
assert(c && data); // we are given the proper size.

// assert((len + sizeof(packet_t) <= MAX_PACKET_SIZE));
assert(c && data);

// Allocate a packet that is as big as the data + len // Allocate a packet that is as big as the data + len
packet_t *p = nmalloc(len + sizeof(packet_t)); packet_t *p = nmalloc(len + sizeof(packet_t));
p->opcode = htons(PACKET_DATA); p->opcode = htons(PACKET_DATA);
p->blockno = htons(c->currentblockno); p->blockno = htons(c->currentblockno);

// Cast the pointer, move to the end of the struct, // Cast the pointer, move to the end of the struct,
// then copy our data, this will mean we have a full // then copy our data, this will mean we have a full
// packet struct. // packet struct.
Expand All @@ -52,7 +54,7 @@ void SendData(client_t *c, void *data, size_t len)
// //
uint8_t *pptr = ((uint8_t*)p) + sizeof(packet_t); uint8_t *pptr = ((uint8_t*)p) + sizeof(packet_t);
memcpy(pptr, data, len); memcpy(pptr, data, len);

// Queue our packet for sending when EPoll comes around to send. // Queue our packet for sending when EPoll comes around to send.
QueuePacket(c, p, len + sizeof(packet_t), 1); QueuePacket(c, p, len + sizeof(packet_t), 1);
} }
Expand All @@ -69,7 +71,7 @@ void Acknowledge(client_t *c, uint16_t blockno)
packet_t *p = nmalloc(sizeof(packet_t)); packet_t *p = nmalloc(sizeof(packet_t));
p->opcode = htons(PACKET_ACK); p->opcode = htons(PACKET_ACK);
p->blockno = htons(blockno); p->blockno = htons(blockno);

QueuePacket(c, p, sizeof(packet_t), 1); QueuePacket(c, p, sizeof(packet_t), 1);
} }


Expand All @@ -90,13 +92,15 @@ void Error(client_t *c, const uint16_t errnum, const char *str, ...)
va_start(ap, str); va_start(ap, str);
size_t len = vasprintf(&buf, str, ap); size_t len = vasprintf(&buf, str, ap);
va_end(ap); va_end(ap);

if (len == -1) if (len == -1)
{ {
fprintf(stderr, "ERROR: cannot format error string: %s\n", strerror(errno)); fprintf(stderr, "ERROR: cannot format error string: %s\n", strerror(errno));
return; return;
} }


bprintf("Error Packet: %s\n", buf);

// If your message is seriously bigger than 512 characters // If your message is seriously bigger than 512 characters
// then you need to rethink what is going on. // then you need to rethink what is going on.
// The end user doesn't need a god damn book because a file // The end user doesn't need a god damn book because a file
Expand All @@ -106,17 +110,40 @@ void Error(client_t *c, const uint16_t errnum, const char *str, ...)
packet_t *p = nmalloc(len + sizeof(packet_t) + 1); packet_t *p = nmalloc(len + sizeof(packet_t) + 1);
p->opcode = htons(PACKET_ERROR); p->opcode = htons(PACKET_ERROR);
p->blockno = htons(errnum); p->blockno = htons(errnum);

// Fancy casting magic! // Fancy casting magic!
uint8_t *pptr = ((uint8_t*)p) + sizeof(packet_t); uint8_t *pptr = ((uint8_t*)p) + sizeof(packet_t);
strncpy((char*)pptr, buf, len); strncpy((char*)pptr, buf, len);
// guaranteed null-termination. // guaranteed null-termination.
pptr[len] = 0; pptr[len] = 0;

QueuePacket(c, p, len + sizeof(packet_t) + 1, 1); QueuePacket(c, p, len + sizeof(packet_t) + 1, 1);

// We don't care what they say now, destroy the client. // We don't care what they say now, destroy the client.
c->destroy = 1; c->destroy = 1;


free(buf); free(buf);
}

void OptionAcknowledge(client_t *c, const char *option, const char *param)
{
//
// 2 bytes string 1 byte string 1 byte string 1 byte string 1 byte
// +----------+---~~---+---------+---~~---+---------+---~~---+-----------+---~~---+---+
// | Opcode | opt1 | 0 | value1 | 0 | optN | 0 | valueN | 0 |
// +----------+---~~---+---------+---~~---+---------+---~~---+-----------+---~~---+---+
//

assert(c && option && param);
packet_t *p = nmalloc(sizeof(packet_t) + strlen(option) + strlen(param) + 2);
p->opcode = htons(PACKET_OACK);

uint8_t *pptr = ((uint8_t*)p) + sizeof(uint16_t);
strcpy((char*)pptr, option);
pptr += strlen(option);
*pptr++ = '\0';
strcpy((char*)pptr, param);
*pptr = '\0';

QueuePacket(c, p, sizeof(packet_t) + strlen(option) + strlen(param) + 2, 1);
} }

0 comments on commit 6e74dcd

Please sign in to comment.