gnrc_tftp: remove module
Has been deprecated for awhile (01fc3d8f0bc09fe95cb2b5a9c6bdecb4).
This commit is contained in:
parent
ea3296df62
commit
0e2a620788
@ -143,11 +143,6 @@ ifneq (,$(filter netdev_tap,$(USEMODULE)))
|
|||||||
USEMODULE += iolist
|
USEMODULE += iolist
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq (,$(filter gnrc_tftp,$(USEMODULE)))
|
|
||||||
USEMODULE += gnrc_udp
|
|
||||||
USEMODULE += xtimer
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifneq (,$(filter gnrc_rpl_p2p,$(USEMODULE)))
|
ifneq (,$(filter gnrc_rpl_p2p,$(USEMODULE)))
|
||||||
USEMODULE += gnrc_rpl
|
USEMODULE += gnrc_rpl
|
||||||
endif
|
endif
|
||||||
|
|||||||
@ -1,40 +0,0 @@
|
|||||||
# name of your application
|
|
||||||
APPLICATION = gnrc_tftp_example
|
|
||||||
|
|
||||||
# If no BOARD is found in the environment, use this default:
|
|
||||||
BOARD ?= native
|
|
||||||
|
|
||||||
# This has to be the absolute path to the RIOT base directory:
|
|
||||||
RIOTBASE ?= $(CURDIR)/../..
|
|
||||||
|
|
||||||
# Include packages that pull up and auto-init the link layer.
|
|
||||||
# NOTE: 6LoWPAN will be included if IEEE802.15.4 devices are present
|
|
||||||
USEMODULE += gnrc_netdev_default
|
|
||||||
USEMODULE += auto_init_gnrc_netif
|
|
||||||
# Specify the mandatory networking modules for IPv6 and UDP
|
|
||||||
USEMODULE += gnrc_ipv6_router_default
|
|
||||||
USEMODULE += gnrc_udp
|
|
||||||
# Add a routing protocol
|
|
||||||
USEMODULE += gnrc_rpl
|
|
||||||
# This application dumps received packets to STDIO using the pktdump module
|
|
||||||
USEMODULE += gnrc_pktdump
|
|
||||||
# Additional networking modules that can be dropped if not needed
|
|
||||||
USEMODULE += gnrc_icmpv6_echo
|
|
||||||
USEMODULE += gnrc_tftp
|
|
||||||
# Add also the shell, some shell commands
|
|
||||||
USEMODULE += shell
|
|
||||||
USEMODULE += shell_commands
|
|
||||||
USEMODULE += ps
|
|
||||||
|
|
||||||
# Comment this out to disable code in RIOT that does safety checking
|
|
||||||
# which is not needed in a production environment but helps in the
|
|
||||||
# development process:
|
|
||||||
DEVELHELP ?= 1
|
|
||||||
|
|
||||||
# Change this to 0 show compiler invocation lines by default:
|
|
||||||
QUIET ?= 1
|
|
||||||
|
|
||||||
include $(RIOTBASE)/Makefile.include
|
|
||||||
|
|
||||||
# Set a custom channel if needed
|
|
||||||
include $(RIOTMAKE)/default-radio-settings.inc.mk
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
BOARD_INSUFFICIENT_MEMORY := \
|
|
||||||
airfy-beacon \
|
|
||||||
arduino-duemilanove \
|
|
||||||
arduino-leonardo \
|
|
||||||
arduino-mega2560 \
|
|
||||||
arduino-nano \
|
|
||||||
arduino-uno \
|
|
||||||
atmega1284p \
|
|
||||||
atmega328p \
|
|
||||||
b-l072z-lrwan1 \
|
|
||||||
blackpill \
|
|
||||||
bluepill \
|
|
||||||
calliope-mini \
|
|
||||||
chronos \
|
|
||||||
derfmega128 \
|
|
||||||
hifive1 \
|
|
||||||
hifive1b \
|
|
||||||
i-nucleo-lrwan1 \
|
|
||||||
mega-xplained \
|
|
||||||
microbit \
|
|
||||||
microduino-corerf \
|
|
||||||
msb-430 \
|
|
||||||
msb-430h \
|
|
||||||
nrf51dk \
|
|
||||||
nrf51dongle \
|
|
||||||
nrf6310 \
|
|
||||||
nucleo-f030r8 \
|
|
||||||
nucleo-f031k6 \
|
|
||||||
nucleo-f042k6 \
|
|
||||||
nucleo-f070rb \
|
|
||||||
nucleo-f072rb \
|
|
||||||
nucleo-f103rb \
|
|
||||||
nucleo-f302r8 \
|
|
||||||
nucleo-f303k8 \
|
|
||||||
nucleo-f334r8 \
|
|
||||||
nucleo-l031k6 \
|
|
||||||
nucleo-l053r8 \
|
|
||||||
saml10-xpro \
|
|
||||||
saml11-xpro \
|
|
||||||
spark-core \
|
|
||||||
stm32f030f4-demo \
|
|
||||||
stm32f0discovery \
|
|
||||||
stm32l0538-disco \
|
|
||||||
telosb \
|
|
||||||
waspmote-pro \
|
|
||||||
wsn430-v1_3b \
|
|
||||||
wsn430-v1_4 \
|
|
||||||
yunjia-nrf51822 \
|
|
||||||
z1 \
|
|
||||||
#
|
|
||||||
@ -1,86 +0,0 @@
|
|||||||
# gnrc_tftp example
|
|
||||||
|
|
||||||
## Connecting RIOT native and the Linux host
|
|
||||||
|
|
||||||
> **Note:** RIOT does not support IPv4, so you need to stick to IPv6 anytime. To establish a connection between RIOT and the Linux host,
|
|
||||||
you will need `tftp` (with IPv6 support). On Ubuntu and Debian you would need the package `tftp-hpa` for TFTP client and `tftpd-hpa` for TFTP server.
|
|
||||||
Be aware that many programs require you to add an option such as -6 to tell them to use IPv6, otherwise they
|
|
||||||
will fail. If you're using a _Raspberry Pi_, run `sudo modprobe ipv6` before trying this example, because raspbian does not load the
|
|
||||||
IPv6 module automatically.
|
|
||||||
On some systems (openSUSE for example), the _firewall_ may interfere, and prevent some packets to arrive at the application (they will
|
|
||||||
however show up in Wireshark, which can be confusing). So be sure to adjust your firewall rules, or turn it off (who needs security anyway).
|
|
||||||
|
|
||||||
First, create a tap interface (to which RIOT will connect) and a bridge (to which Linux will connect) from the RIOT main directory run:
|
|
||||||
|
|
||||||
sudo ./dist/tools/tapsetup/tapsetup -c 1
|
|
||||||
|
|
||||||
Now you can start the `gnrc_tftp` example by invoking `make term`. This should automatically connect to the `tap0` interface. If
|
|
||||||
this doesn't work for some reason, run `make` without any arguments, and then run the binary manually like so (assuming you are in the `examples/gnrc_tftp` directory):
|
|
||||||
|
|
||||||
To verify that there is connectivity between RIOT and Linux, go to the RIOT console and run `ifconfig`:
|
|
||||||
|
|
||||||
> ifconfig
|
|
||||||
Iface 6 HWaddr: 7e:ed:d2:ee:e1:07
|
|
||||||
MTU:1280
|
|
||||||
Source address length: 6
|
|
||||||
Link type: wired
|
|
||||||
inet6 addr: ff02::1/128 scope: local [multicast]
|
|
||||||
inet6 addr: fe80::7ced:d2ff:feee:e107/64 scope: local
|
|
||||||
inet6 addr: ff02::1:ffee:e107/128 scope: local [multicast]
|
|
||||||
|
|
||||||
|
|
||||||
Copy the [link-local address](https://en.wikipedia.org/wiki/Link-local_address) of the RIOT node (prefixed with `fe80`) and try to ping it **from the Linux node**:
|
|
||||||
|
|
||||||
ping6 fe80::7ced:d2ff:feee:e107%tapbr0
|
|
||||||
|
|
||||||
Note that the interface on which to send the ping needs to be appended to the IPv6 address, `%tapbr0` in the above example. When talking to the RIOT node, you always want to send to/receive from the `tapbr0` interface.
|
|
||||||
|
|
||||||
If the pings succeed you can go on to send UDP packets. To do that, first start a UDP server on the RIOT node:
|
|
||||||
|
|
||||||
> tftps start
|
|
||||||
tftp_server: Starting TFTP service at port 69
|
|
||||||
|
|
||||||
Now, on the Linux host, you can run tftp to connect with RIOT's TFTP server:
|
|
||||||
|
|
||||||
$ tftp -v -6 fe80::7ced:d2ff:feee:e107%tapbr0 -c get welcome.txt
|
|
||||||
|
|
||||||
The output will be something like:
|
|
||||||
|
|
||||||
Connected to fe80::7ced:d2ff:feee:e107%tapbr0 (fe80::7ced:d2ff:feee:e107), port 69
|
|
||||||
getting from fe80::7ced:d2ff:feee:e107%tapbr0:welcome.txt to welcome.txt [netascii]
|
|
||||||
Received 94 bytes in 0.0 seconds [113425 bit/s]
|
|
||||||
|
|
||||||
The `-6` option is necessary to tell tftp to use IPv6 only and the `-v` is to tell the tftp client to be verbose.
|
|
||||||
|
|
||||||
You should now see that the TFTP messages are received on the RIOT side. Opening a TFTP server on the Linux side is also possible. To do that, write down the IP address of the host (run on Linux):
|
|
||||||
|
|
||||||
ifconfig tapbr0
|
|
||||||
tapbr0 Link encap:Ethernet HWaddr 0e:bc:0f:49:7f:e4
|
|
||||||
inet6 addr: fe80::cbc:fff:fe49:7fe4/64 Scope:Link
|
|
||||||
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
|
|
||||||
RX packets:22 errors:0 dropped:0 overruns:0 frame:0
|
|
||||||
TX packets:53 errors:0 dropped:0 overruns:0 carrier:0
|
|
||||||
collisions:0 txqueuelen:0
|
|
||||||
RX bytes:1928 (1.9 KB) TX bytes:6217 (6.2 KB)
|
|
||||||
|
|
||||||
And start the tftp server on Linux:
|
|
||||||
|
|
||||||
$ sudo /etc/init.d/tftpd-hpa stop && mkdir -p tftpserv && echo "hello world" > tftpserv/welcome.txt && sudo in.tftpd -vvv -L -6 -c -s -u ${USER} ./tftpserv
|
|
||||||
|
|
||||||
Now, on the RIOT side, send a UDP packet using:
|
|
||||||
|
|
||||||
tftpc get welcome.txt octet 1 fe80::cbc:fff:fe49:7fe4
|
|
||||||
|
|
||||||
You will get output that looks like this:
|
|
||||||
|
|
||||||
tftp_client: bin read welcome.txt:12
|
|
||||||
|
|
||||||
-- CLIENT DATA --
|
|
||||||
hello worl
|
|
||||||
-- CLIENT DATA --
|
|
||||||
|
|
||||||
-- CLIENT DATA --
|
|
||||||
d
|
|
||||||
|
|
||||||
-- CLIENT DATA --
|
|
||||||
tftp_client: SUCCESS: (null)
|
|
||||||
@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2015 Engineering-Spirit
|
|
||||||
*
|
|
||||||
* This file is subject to the terms and conditions of the GNU Lesser
|
|
||||||
* General Public License v2.1. See the file LICENSE in the top level
|
|
||||||
* directory for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ingroup examples
|
|
||||||
* @{
|
|
||||||
*
|
|
||||||
* @file
|
|
||||||
* @brief Example application for demonstrating the RIOT TFTP stack
|
|
||||||
*
|
|
||||||
* @author Nick van IJzendoorn <nijzendoorn@engineering-spirit.nl>
|
|
||||||
*
|
|
||||||
* @}
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "shell.h"
|
|
||||||
#include "msg.h"
|
|
||||||
|
|
||||||
extern int tftp_client_cmd(int argc, char * *argv);
|
|
||||||
extern int tftp_server_cmd(int argc, char * *argv);
|
|
||||||
|
|
||||||
#define MAIN_QUEUE_SIZE (4)
|
|
||||||
static msg_t _main_msg_queue[MAIN_QUEUE_SIZE];
|
|
||||||
|
|
||||||
static const shell_command_t shell_commands[] = {
|
|
||||||
{ "tftpc", "get/put data to a TFTP server", tftp_client_cmd },
|
|
||||||
{ "tftps", "start and stop the TFTP server", tftp_server_cmd },
|
|
||||||
{ NULL, NULL, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
/* we need a message queue for the thread running the shell in order to
|
|
||||||
* receive potentially fast incoming networking packets */
|
|
||||||
msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE);
|
|
||||||
puts("RIOT TFTP stack example application");
|
|
||||||
|
|
||||||
/* start shell */
|
|
||||||
puts("All up, running the shell now");
|
|
||||||
char line_buf[SHELL_DEFAULT_BUFSIZE];
|
|
||||||
|
|
||||||
shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);
|
|
||||||
|
|
||||||
/* should be never reached */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,220 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2015 Engineering-Spirit
|
|
||||||
*
|
|
||||||
* This file is subject to the terms and conditions of the GNU Lesser
|
|
||||||
* General Public License v2.1. See the file LICENSE in the top level
|
|
||||||
* directory for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ingroup examples
|
|
||||||
* @{
|
|
||||||
*
|
|
||||||
* @file
|
|
||||||
* @brief Demonstrating the sending and receiving of data via the TFTP client
|
|
||||||
*
|
|
||||||
* @author Nick van IJzendoorn <nijzendoorn@engineering-spirit.nl>
|
|
||||||
*
|
|
||||||
* @}
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#include "net/gnrc/tftp.h"
|
|
||||||
|
|
||||||
static const char *_tftp_default_host = "::1";
|
|
||||||
|
|
||||||
/* default server text which can be received */
|
|
||||||
static const char _tftp_client_hello[] = "Hello,\n"
|
|
||||||
"\n"
|
|
||||||
"Client text would also need to exist to be able to put data.\n"
|
|
||||||
"\n"
|
|
||||||
"Enjoy the RIOT-OS\n";
|
|
||||||
|
|
||||||
static tftp_action_t _tftp_action;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief called at every transaction start
|
|
||||||
*/
|
|
||||||
static bool _tftp_client_start_cb(tftp_action_t action, tftp_mode_t mode,
|
|
||||||
const char *file_name, size_t *len)
|
|
||||||
{
|
|
||||||
/* translate the mode */
|
|
||||||
const char *str_mode = "ascii";
|
|
||||||
|
|
||||||
if (mode == TTM_OCTET) {
|
|
||||||
str_mode = "bin";
|
|
||||||
}
|
|
||||||
else if (mode == TTM_MAIL) {
|
|
||||||
str_mode = "mail";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* translate the action */
|
|
||||||
const char *str_action = "read";
|
|
||||||
if (action == TFTP_WRITE) {
|
|
||||||
str_action = "write";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* display the action being performed */
|
|
||||||
printf("tftp_client: %s %s %s:%lu\n", str_mode, str_action, file_name, (unsigned long)*len);
|
|
||||||
|
|
||||||
/* return the length of the text, if this is an read action */
|
|
||||||
if (action == TFTP_READ) {
|
|
||||||
*len = sizeof(_tftp_client_hello);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* remember the action of the current transfer */
|
|
||||||
_tftp_action = action;
|
|
||||||
|
|
||||||
/* we accept the transfer to take place so we return true */
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief called to get or put data, depending on the mode received by `_tftp_start_cb(action, ...)`
|
|
||||||
*/
|
|
||||||
static int _tftp_client_data_cb(uint32_t offset, void *data, size_t data_len)
|
|
||||||
{
|
|
||||||
char *c = (char *) data;
|
|
||||||
|
|
||||||
/* if we are reading return the part of the data that is being requested */
|
|
||||||
if (_tftp_action == TFTP_WRITE) {
|
|
||||||
/* calculate the length of the data block to transfer */
|
|
||||||
if (offset + data_len > sizeof(_tftp_client_hello)) {
|
|
||||||
data_len -= (offset + data_len) - sizeof(_tftp_client_hello);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copy the block to the output buffer */
|
|
||||||
memcpy(data, _tftp_client_hello + offset, data_len);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* we received a data block which we output to the console */
|
|
||||||
printf("\n -- CLIENT DATA --\n%.*s\n -- CLIENT DATA --\n", (int)data_len, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* return the length of the data block */
|
|
||||||
return data_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief the transfer has stopped, see the event argument to determined if it was successful
|
|
||||||
* or not.
|
|
||||||
*/
|
|
||||||
static void _tftp_client_stop_cb(tftp_event_t event, const char *msg)
|
|
||||||
{
|
|
||||||
/* decode the stop event received */
|
|
||||||
const char *cause = "UNKNOWN";
|
|
||||||
|
|
||||||
if (event == TFTP_SUCCESS) {
|
|
||||||
cause = "SUCCESS";
|
|
||||||
}
|
|
||||||
else if (event == TFTP_PEER_ERROR) {
|
|
||||||
cause = "ERROR From Client";
|
|
||||||
}
|
|
||||||
else if (event == TFTP_INTERN_ERROR) {
|
|
||||||
cause = "ERROR Internal Server Error";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* print the transfer result to the console */
|
|
||||||
if (msg != NULL) {
|
|
||||||
printf("tftp_client: %s: %s\n", cause, msg);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
printf("tftp_client: %s\n", cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _tftp_client_cmd(int argc, char * *argv)
|
|
||||||
{
|
|
||||||
ipv6_addr_t ip;
|
|
||||||
const char *file_name = argv[2];
|
|
||||||
tftp_mode_t mode = TTM_OCTET;
|
|
||||||
bool use_options = true;
|
|
||||||
|
|
||||||
ipv6_addr_from_str(&ip, _tftp_default_host);
|
|
||||||
|
|
||||||
if (argc >= 3 && argc <= 6) {
|
|
||||||
/* decode the action */
|
|
||||||
if (strcmp(argv[1], "get") == 0) {
|
|
||||||
_tftp_action = TFTP_READ;
|
|
||||||
}
|
|
||||||
else if (strcmp(argv[1], "put") == 0) {
|
|
||||||
_tftp_action = TFTP_WRITE;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get the transfer mode */
|
|
||||||
if (argc >= 4) {
|
|
||||||
if (strcmp(argv[3], "octet") == 0) {
|
|
||||||
mode = TTM_OCTET;
|
|
||||||
}
|
|
||||||
else if (strcmp(argv[3], "ascii") == 0) {
|
|
||||||
mode = TTM_ASCII;
|
|
||||||
}
|
|
||||||
else if (strcmp(argv[3], "mail") == 0) {
|
|
||||||
mode = TTM_MAIL;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
puts("tftp: couldn't parse the TFTP transfer mode");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* decode if we must use the TFTP option extension or not */
|
|
||||||
if (argc >= 5) {
|
|
||||||
if (strcmp(argv[4], "0") == 0) {
|
|
||||||
use_options = false;
|
|
||||||
}
|
|
||||||
else if (strcmp(argv[4], "1") == 0) {
|
|
||||||
use_options = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
puts("tftp: invalid options choose 0 or 1");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* decode the address */
|
|
||||||
if (argc >= 6) {
|
|
||||||
if (!ipv6_addr_from_str(&ip, argv[5])) {
|
|
||||||
puts("tftp: invalid IP address");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_tftp_action == TFTP_READ) {
|
|
||||||
puts("tftp: starting read request");
|
|
||||||
|
|
||||||
gnrc_tftp_client_read(&ip, file_name, mode, _tftp_client_data_cb,
|
|
||||||
_tftp_client_start_cb, _tftp_client_stop_cb, use_options);
|
|
||||||
}
|
|
||||||
else if (_tftp_action == TFTP_WRITE) {
|
|
||||||
puts("tftp: starting write request");
|
|
||||||
|
|
||||||
gnrc_tftp_client_write(&ip, file_name, mode, _tftp_client_data_cb,
|
|
||||||
sizeof(_tftp_client_hello), _tftp_client_stop_cb, use_options);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief start the TFTP server by creating a thread
|
|
||||||
*/
|
|
||||||
int tftp_client_cmd(int argc, char * *argv)
|
|
||||||
{
|
|
||||||
if (_tftp_client_cmd(argc, argv) < 0) {
|
|
||||||
printf("usage: %s <action[get|put]> <file_name> <mode[ascii | octet(default) | mail]>\n"
|
|
||||||
"\t<use_options[1 (default) | 0]> <addr(default: ::1)>\n", argv[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,191 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2015 Engineering-Spirit
|
|
||||||
*
|
|
||||||
* This file is subject to the terms and conditions of the GNU Lesser
|
|
||||||
* General Public License v2.1. See the file LICENSE in the top level
|
|
||||||
* directory for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ingroup examples
|
|
||||||
* @{
|
|
||||||
*
|
|
||||||
* @file
|
|
||||||
* @brief Demonstrating the sending and receiving of data via the TFTP server
|
|
||||||
*
|
|
||||||
* @author Nick van IJzendoorn <nijzendoorn@engineering-spirit.nl>
|
|
||||||
*
|
|
||||||
* @}
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#include "thread.h"
|
|
||||||
#include "net/gnrc/tftp.h"
|
|
||||||
|
|
||||||
/* the message queues */
|
|
||||||
#define TFTP_QUEUE_SIZE (4)
|
|
||||||
static msg_t _tftp_msg_queue[TFTP_QUEUE_SIZE];
|
|
||||||
|
|
||||||
/* allocate the stack */
|
|
||||||
char _tftp_stack[THREAD_STACKSIZE_MAIN + THREAD_EXTRA_STACKSIZE_PRINTF];
|
|
||||||
|
|
||||||
/* default server text which can be received */
|
|
||||||
static const char _tftp_server_hello[] = "Hello world,\n"
|
|
||||||
"\n"
|
|
||||||
"Welcome to the wonderful world of IoT and embedded systems.\n"
|
|
||||||
"\n"
|
|
||||||
"Enjoy the RIOT-OS\n";
|
|
||||||
|
|
||||||
static tftp_action_t _tftp_action;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief called at every transcation start
|
|
||||||
*/
|
|
||||||
static bool _tftp_server_start_cb(tftp_action_t action, tftp_mode_t mode,
|
|
||||||
const char *file_name, size_t *len)
|
|
||||||
{
|
|
||||||
/* translate the mode */
|
|
||||||
const char *str_mode = "ascii";
|
|
||||||
|
|
||||||
if (mode == TTM_OCTET) {
|
|
||||||
str_mode = "bin";
|
|
||||||
}
|
|
||||||
else if (mode == TTM_MAIL) {
|
|
||||||
str_mode = "mail";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* translate the action */
|
|
||||||
const char *str_action = "read";
|
|
||||||
if (action == TFTP_WRITE) {
|
|
||||||
str_action = "write";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* display the action being performed */
|
|
||||||
printf("tftp_server: %s %s %s:%lu\n", str_mode, str_action, file_name, (unsigned long)*len);
|
|
||||||
|
|
||||||
/* return the length of the text, if this is an read action */
|
|
||||||
if (action == TFTP_READ) {
|
|
||||||
*len = sizeof(_tftp_server_hello);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* remember the action of the current transfer */
|
|
||||||
_tftp_action = action;
|
|
||||||
|
|
||||||
/* we accept the transfer to take place so we return true */
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief called to get or put data, depending on the mode received by `_tftp_start_cb(action, ...)`
|
|
||||||
*/
|
|
||||||
static int _tftp_server_data_cb(uint32_t offset, void *data, size_t data_len)
|
|
||||||
{
|
|
||||||
char *c = (char *) data;
|
|
||||||
|
|
||||||
/* if we are reading return the part of the data that is being requested */
|
|
||||||
if (_tftp_action == TFTP_READ) {
|
|
||||||
/* calculate the length of the data block to transfer */
|
|
||||||
if (offset + data_len > sizeof(_tftp_server_hello)) {
|
|
||||||
data_len -= (offset + data_len) - sizeof(_tftp_server_hello);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copy the block to the output buffer */
|
|
||||||
memcpy(data, _tftp_server_hello + offset, data_len);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* we received a data block which we output to the console */
|
|
||||||
printf("\n -- SERVER DATA --\n%.*s\n -- SERVER DATA --\n", (int)data_len, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* return the length of the data block */
|
|
||||||
return data_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief the transfer has stopped, see the event argument to determined if it was successful
|
|
||||||
* or not.
|
|
||||||
*/
|
|
||||||
static void _tftp_server_stop_cb(tftp_event_t event, const char *msg)
|
|
||||||
{
|
|
||||||
/* decode the stop event received */
|
|
||||||
const char *cause = "UNKNOWN";
|
|
||||||
|
|
||||||
if (event == TFTP_SUCCESS) {
|
|
||||||
cause = "SUCCESS";
|
|
||||||
}
|
|
||||||
else if (event == TFTP_PEER_ERROR) {
|
|
||||||
cause = "ERROR From Client";
|
|
||||||
}
|
|
||||||
else if (event == TFTP_INTERN_ERROR) {
|
|
||||||
cause = "ERROR Internal Server Error";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* print the transfer result to the console */
|
|
||||||
printf("tftp_server: %s: %s\n", cause, (msg == NULL) ? "NULL" : msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief the TFTP server thread
|
|
||||||
*/
|
|
||||||
void *tftp_server_wrapper(void *arg)
|
|
||||||
{
|
|
||||||
(void)arg;
|
|
||||||
|
|
||||||
/* A message queue is needed to register for incoming packets */
|
|
||||||
msg_init_queue(_tftp_msg_queue, TFTP_QUEUE_SIZE);
|
|
||||||
|
|
||||||
/* inform the user */
|
|
||||||
puts("tftp_server: Starting TFTP service at port 69");
|
|
||||||
|
|
||||||
/* run the TFTP server */
|
|
||||||
gnrc_tftp_server(_tftp_server_data_cb, _tftp_server_start_cb, _tftp_server_stop_cb, true);
|
|
||||||
|
|
||||||
/* the TFTP server has been stopped */
|
|
||||||
puts("tftp_server: Stopped TFTP service");
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief start the TFTP server by creating a thread
|
|
||||||
*/
|
|
||||||
void tftp_server_start(void)
|
|
||||||
{
|
|
||||||
thread_create(_tftp_stack, sizeof(_tftp_stack),
|
|
||||||
1, THREAD_CREATE_WOUT_YIELD | THREAD_CREATE_STACKTEST,
|
|
||||||
tftp_server_wrapper, NULL, "TFTP Server");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief stop the TFTP server by sending a message to the thread
|
|
||||||
*/
|
|
||||||
void tftp_server_stop(void)
|
|
||||||
{
|
|
||||||
gnrc_tftp_server_stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
int tftp_server_cmd(int argc, char * *argv)
|
|
||||||
{
|
|
||||||
switch (argc) {
|
|
||||||
case 2:
|
|
||||||
if (strcmp(argv[1], "start") == 0) {
|
|
||||||
tftp_server_start();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (strcmp(argv[1], "stop") == 0) {
|
|
||||||
tftp_server_stop();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* falls through */
|
|
||||||
|
|
||||||
default:
|
|
||||||
printf("usage: %s [start|stop]\n", argv[0]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
@ -1,217 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2015 Nick van IJzendoorn <nijzendoorn@engineering-spirit.nl>
|
|
||||||
*
|
|
||||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
|
||||||
* Public License v2.1. See the file LICENSE in the top level directory for
|
|
||||||
* more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @defgroup net_gnrc_tftp TFTP Support Library
|
|
||||||
* @ingroup net_gnrc
|
|
||||||
* @brief Add's support for TFTP protocol parsing
|
|
||||||
*
|
|
||||||
* @deprecated This module has serious quality defects and is not in a
|
|
||||||
* maintainable state. It will be removed after the 2020.04 release
|
|
||||||
* at the latest.
|
|
||||||
* @{
|
|
||||||
*
|
|
||||||
* @file
|
|
||||||
* @brief TFTP support library
|
|
||||||
*
|
|
||||||
* @warning Currently only runs with link-local addresses when there is only
|
|
||||||
* one interface
|
|
||||||
*
|
|
||||||
* The TFTP module add's support for the TFTP protocol.
|
|
||||||
* It implements the following RFC's:
|
|
||||||
* - https://tools.ietf.org/html/rfc1350
|
|
||||||
* (RFC1350 The TFTP Protocol (Revision 2)
|
|
||||||
*
|
|
||||||
* - https://tools.ietf.org/html/rfc2347
|
|
||||||
* (RFC2347 TFTP Option Extension)
|
|
||||||
*
|
|
||||||
* - https://tools.ietf.org/html/rfc2348
|
|
||||||
* (RFC2348 TFTP Blocksize Option)
|
|
||||||
*
|
|
||||||
* - https://tools.ietf.org/html/rfc2349
|
|
||||||
* (RFC2349 TFTP Timeout Interval and Transfer Size Options)
|
|
||||||
*
|
|
||||||
* @author Nick van IJzendoorn <nijzendoorn@engineering-spirit.nl>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef NET_GNRC_TFTP_H
|
|
||||||
#define NET_GNRC_TFTP_H
|
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#include "byteorder.h"
|
|
||||||
#include "kernel_types.h"
|
|
||||||
#include "net/ipv6/addr.h"
|
|
||||||
#include "net/gnrc/nettype.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The maximum allowed length of the transfer filename
|
|
||||||
*/
|
|
||||||
#ifndef GNRC_TFTP_MAX_FILENAME_LEN
|
|
||||||
#define GNRC_TFTP_MAX_FILENAME_LEN (64)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The base source port to be used by TFTP
|
|
||||||
*/
|
|
||||||
#ifndef GNRC_TFTP_DEFAULT_SRC_PORT
|
|
||||||
#define GNRC_TFTP_DEFAULT_SRC_PORT (10690)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The default destination port of the TFTP server
|
|
||||||
*/
|
|
||||||
#ifndef GNRC_TFTP_DEFAULT_DST_PORT
|
|
||||||
#define GNRC_TFTP_DEFAULT_DST_PORT (69)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The maximum allowed data bytes in the data packet
|
|
||||||
*/
|
|
||||||
#ifndef GNRC_TFTP_MAX_TRANSFER_UNIT
|
|
||||||
#define GNRC_TFTP_MAX_TRANSFER_UNIT (512)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The number of retries that must be made before stopping a transfer
|
|
||||||
*/
|
|
||||||
#ifndef GNRC_TFTP_MAX_RETRIES
|
|
||||||
#define GNRC_TFTP_MAX_RETRIES (5)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The default timeout of a data packet
|
|
||||||
*/
|
|
||||||
#ifndef GNRC_TFTP_DEFAULT_TIMEOUT
|
|
||||||
#define GNRC_TFTP_DEFAULT_TIMEOUT (1 * US_PER_SEC)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief TFTP action to perform
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
TFTP_READ,
|
|
||||||
TFTP_WRITE
|
|
||||||
} tftp_action_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief TFTP Transfer modes
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
TTM_ASCII,
|
|
||||||
TTM_OCTET,
|
|
||||||
TTM_MAIL
|
|
||||||
} tftp_mode_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief TFTP stop / finish events
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
TFTP_SUCCESS, /**< The transfer was successful */
|
|
||||||
TFTP_PEER_ERROR, /**< The peer send the given error */
|
|
||||||
TFTP_INTERN_ERROR /**< There was an internal error */
|
|
||||||
} tftp_event_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief callback define which is called when a new server request is placed
|
|
||||||
* or when an client read request is made and the data length option is received
|
|
||||||
*
|
|
||||||
* @param [in] action The action the transfer want to perform
|
|
||||||
* @param [in] mode The data mode of the transfer
|
|
||||||
* @param [in] file_name The filename of the file being transferred
|
|
||||||
* @param [in/out] data_len When a read action is performed, the application must give
|
|
||||||
* the total transfer size of the data. When a write action
|
|
||||||
* is performed the total transfer size will be given.
|
|
||||||
*/
|
|
||||||
typedef bool (*tftp_start_cb_t)(tftp_action_t action, tftp_mode_t mode,
|
|
||||||
const char *file_name, size_t *data_len);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief callback define which is called to get or set data from/to the user application
|
|
||||||
*/
|
|
||||||
typedef int (*tftp_data_cb_t)(uint32_t offset, void *data, size_t data_len);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief callback define which is called when an transfer is stopped
|
|
||||||
*/
|
|
||||||
typedef void (*tftp_stop_cb_t)(tftp_event_t event, const char *msg);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Start the TFTP server
|
|
||||||
*
|
|
||||||
* @param [in] data_cb called for each read data block
|
|
||||||
* @param [in] start_cb called if a new client connection is requested
|
|
||||||
* @param [in] stop_cb called if the transfer has finished
|
|
||||||
* @param [in] use_options when set the client uses the option extensions
|
|
||||||
*
|
|
||||||
* @return 1 on success
|
|
||||||
* @return -1 on failure
|
|
||||||
*/
|
|
||||||
int gnrc_tftp_server(tftp_data_cb_t data_cb, tftp_start_cb_t start_cb, tftp_stop_cb_t stop_cb, bool use_options);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Stop the TFTP server
|
|
||||||
*
|
|
||||||
* @return 1 on success
|
|
||||||
* @return -1 on failure
|
|
||||||
*/
|
|
||||||
int gnrc_tftp_server_stop(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Start an TFTP client read action from the given destination
|
|
||||||
*
|
|
||||||
* @pre `(GNRC_NETIF_NUMOF == 1) || !ipv6_addr_is_link_local(addr)`
|
|
||||||
*
|
|
||||||
* @param [in] addr the address of the server
|
|
||||||
* @param [in] file_name the filename of the file to get
|
|
||||||
* @param [in] mode the transfer mode
|
|
||||||
* @param [in] data_cb called for each read data block
|
|
||||||
* @param [in] start_cb called if the server returns the transfer_size option
|
|
||||||
* @param [in] stop_cb called if the transfer has finished
|
|
||||||
* @param [in] use_option when set the client uses the option extensions
|
|
||||||
*
|
|
||||||
* @return 1 on success
|
|
||||||
* @return -1 on failure
|
|
||||||
*/
|
|
||||||
int gnrc_tftp_client_read(ipv6_addr_t *addr, const char *file_name, tftp_mode_t mode,
|
|
||||||
tftp_data_cb_t data_cb, tftp_start_cb_t start_cb, tftp_stop_cb_t stop_cb,
|
|
||||||
bool use_option);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Start an TFTP client write action to the given destination
|
|
||||||
*
|
|
||||||
* @pre `(GNRC_NETIF_NUMOF == 1) || !ipv6_addr_is_link_local(addr)`
|
|
||||||
*
|
|
||||||
* @param [in] addr the address of the server
|
|
||||||
* @param [in] file_name the filename of the file to write
|
|
||||||
* @param [in] mode the transfer mode
|
|
||||||
* @param [in] data_cb called to store the received block
|
|
||||||
* @param [in] total_size the total size of the transfer
|
|
||||||
* @param [in] stop_cb called if the server returns the transfer_size option
|
|
||||||
* @param [in] use_option when set the client uses the option extensions
|
|
||||||
*
|
|
||||||
* @return 1 on success
|
|
||||||
* @return -1 on failure
|
|
||||||
*/
|
|
||||||
int gnrc_tftp_client_write(ipv6_addr_t *addr, const char *file_name, tftp_mode_t mode,
|
|
||||||
tftp_data_cb_t data_cb, size_t total_size, tftp_stop_cb_t stop_cb,
|
|
||||||
bool use_option);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* NET_GNRC_TFTP_H */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @}
|
|
||||||
*/
|
|
||||||
@ -130,8 +130,5 @@ endif
|
|||||||
ifneq (,$(filter gnrc_tcp,$(USEMODULE)))
|
ifneq (,$(filter gnrc_tcp,$(USEMODULE)))
|
||||||
DIRS += transport_layer/tcp
|
DIRS += transport_layer/tcp
|
||||||
endif
|
endif
|
||||||
ifneq (,$(filter gnrc_tftp,$(USEMODULE)))
|
|
||||||
DIRS += application_layer/tftp
|
|
||||||
endif
|
|
||||||
|
|
||||||
include $(RIOTBASE)/Makefile.base
|
include $(RIOTBASE)/Makefile.base
|
||||||
|
|||||||
@ -1,3 +0,0 @@
|
|||||||
MODULE = gnrc_tftp
|
|
||||||
|
|
||||||
include $(RIOTBASE)/Makefile.base
|
|
||||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user