#define _BSD_SOURCE
#include <string.h>
#include <unistd.h>
+#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#define TFTP_PKT_SIZE 516
-static const char *opcode_names[] = {
+static const char *opcode_names[] = {
"RRQ", "WRQ", "DATA", "ACK", "ERR"
};
ERR = 5
};
+static char *x_basename(const char *path)
+{
+ char *slash, *bslash;
+
+ slash = rindex(path, '/');
+ bslash = rindex(path, '\\');
+
+ if (slash && bslash) {
+ path = 1 + (slash > bslash ? slash : bslash);
+ } else if (slash) {
+ path = 1 + slash;
+ } else if (bslash) {
+ path = 1 + bslash;
+ }
+
+ return strdup(path);
+}
+
+static const char *sanitize_netascii(char *str)
+{
+ char *p = str;
+
+ for (; *p; ++p) {
+ if (*p < 0x20 || *p > 0x7f) {
+ *p = '_';
+ }
+ }
+
+ return str;
+}
+
static inline void pkt_mknum(char *pkt, uint16_t n)
{
*(uint16_t*)pkt = htons(n);
return len;
}
-static ssize_t tftp_sendto(int sock, char *pkt, size_t len,
+static ssize_t tftp_sendto(int sock, char *pkt, size_t len,
struct sockaddr_in *dst)
{
ssize_t sent;
int tftp_put(struct nmrpd_args *args)
{
struct sockaddr_in addr;
+ char *filename;
uint16_t block;
ssize_t len;
int fd, sock, err, timeout, last_len;
char rx[TFTP_PKT_SIZE], tx[TFTP_PKT_SIZE];
sock = -1;
+ filename = NULL;
fd = open(args->filename, O_RDONLY);
if (fd < 0) {
addr.sin_family = AF_INET;
addr.sin_port = htons(args->port);
- pkt_mkwrq(tx, args->filename, "octet");
+ filename = x_basename(args->filename);
+ if (!filename) {
+ perror("x_basename");
+ goto cleanup;
+ } else if (strlen(filename) > 256) {
+ fprintf(stderr, "Filename exceeds maximum of 256 characters.\n");
+ goto cleanup;
+ }
+
+ sanitize_netascii(filename);
+ if (verbosity > 1) {
+ printf("%s -> %s\n", args->filename, filename);
+ }
+
+ pkt_mkwrq(tx, filename, "octet");
len = tftp_sendto(sock, tx, 0, &addr);
if (len < 0) {
err = 0;
cleanup:
+ free(filename);
+
if (fd >= 0) {
close(fd);
}