Skip to content
Snippets Groups Projects
Commit 4a649598 authored by Martine Lenders's avatar Martine Lenders
Browse files

Add shell commands for interface configuration

parent 848ac70f
No related branches found
No related tags found
No related merge requests found
......@@ -108,3 +108,9 @@ ifneq (,$(filter net_if,$(USEMODULE)))
USEMODULE += transceiver
endif
endif
ifneq (,$(filter shell_commands,$(USEMODULE)))
ifneq (,$(filter net_if,$(USEMODULE)))
USEMODULE += net_help
endif
endif
......@@ -11,6 +11,10 @@ ifneq (,$(filter cc110x,$(USEMODULE)))
SRC += sc_cc1100.c
endif
endif
ifneq (,$(filter net_if,$(USEMODULE)))
INCLUDES += -I$(RIOTBASE)/sys/net/include
SRC += sc_net_if.c
endif
ifneq (,$(filter mci,$(USEMODULE)))
SRC += sc_disk.c
endif
......
/*
* Shell commands for network interfaces
*
* Copyright (C) 2013 Martin Lenders
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @ingroup shell_commands
* @{
* @file sc_net_if.c
* @brief provides shell commands to configure network interfaces
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
* @}
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "destiny/socket.h" /* for AF_INET6 */
#include "inet_pton.h"
#include "inet_ntop.h"
#include "net_help.h"
#include "net_if.h"
#include "transceiver.h"
#define ADDR_REGISTERED_MAX (6)
#define ADDRS_LEN_MAX (16)
static uint8_t addr_registered = 0;
static uint8_t addrs[ADDR_REGISTERED_MAX][ADDRS_LEN_MAX];
void _net_if_ifconfig_add(int if_id, int argc, char **argv);
void _net_if_ifconfig_add_ipv6(int if_id, int argc, char **argv);
void _net_if_ifconfig_set(int if_id, char *key, char *value);
void _net_if_ifconfig_set_srcaddrmode(int if_id, char *mode);
void _net_if_ifconfig_set_eui64(int if_id, char *addr);
void _net_if_ifconfig_set_hwaddr(int if_id, char *addr);
void _net_if_ifconfig_set_pan_id(int if_id, char *pan_id);
void _net_if_ifconfig_set_channel(int if_id, char *channel);
void _net_if_ifconfig_create(char *transceivers_str);
int _net_if_ifconfig_ipv6_addr_convert(net_if_addr_t *addr, char *type,
char *addr_data_str, char *addr_data_len);
void _net_if_ifconfig_list(int if_id);
int isnumber(char *str)
{
for (; *str; str++) {
if (!isdigit((int)*str)) {
return 0;
}
}
return 1;
}
static inline void _eui64_to_str(char *eui64_str, net_if_eui64_t *eui64)
{
sprintf(eui64_str, "%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x",
eui64->uint8[0], eui64->uint8[1], eui64->uint8[2], eui64->uint8[3],
eui64->uint8[4], eui64->uint8[5], eui64->uint8[6], eui64->uint8[7]);
}
char *addr_data_to_str(char *addr_str, const uint8_t *addr, uint8_t addr_len)
{
int i;
for (i = 0; i < addr_len / 8; i++) {
sprintf(addr_str, "%02x", addr[i]);
}
uint8_t r = addr_len % 8;
if (r) {
uint8_t mask = 0x00;
while (r) {
mask |= 0x1 << (8 - (r--));
}
sprintf(addr_str, "%02x", addr[addr_len / 8] & mask);
}
return addr_str;
}
void add_usage(void)
{
puts("Usage: ifconfig <if_id> add ipv6 [multicast|anycast] <addr>");
}
void set_usage(void)
{
printf("Usage: ifconfig <if_id> set <key> <value>\n"
" Sets an transceiver specific value\n"
" <key> may be one of the following\n"
" * \"srcaddrmode\" - sets the source address mode for IEEE\n"
" 802.15.4 transeivers (valid values: \"short\" or \"long\"),\n"
" * \"sam\" - alias for \"srcaddrmode\"\n"
" * \"eui64\" - sets the EUI-64 if supported by transceivers,\n"
" * \"hwaddr\" - sets the 16-bit address (or just the address\n"
" for e.g cc1100) of the transceivers\n"
" * \"pan_id\" - sets the PAN ID of the transceiver\n"
" * \"pan\" - alias for \"pan_id\"\n"
" * \"channel\" - sets the frequency channel of the transceiver\n"
" * \"chan\" - alias for \"channel\"\n");
}
void create_usage(void)
{
puts("Usage: ifconfig create <transceiver_1>[,<transceiver_2>,...]\n"
" <transceiver_n> may be one of the following values:\n"
#ifdef MODULE_AT86RF231
" * at86rv231\n"
#endif
#ifdef MODULE_CC1020
" * cc1020\n"
#endif
#if MODULE_CC110X || MODULE_CC110X_NG
" * cc1100\n"
#endif
#ifdef MODULE_CC2420
" * cc2420\n"
#endif
#ifdef MODULE_MC1322X
" * mc1322x\n"
#endif
#ifdef MODULE_NATIVENET
" * native\n"
#endif
);
}
void _net_if_ifconfig(int argc, char **argv)
{
if (argc < 2) {
int if_id = -1;
while ((if_id = net_if_iter_interfaces(if_id)) >= 0) {
_net_if_ifconfig_list(if_id);
}
return;
}
else if (strcmp(argv[1], "create") == 0) {
_net_if_ifconfig_create(argv[2]);
return;
}
else if (isnumber(argv[1])) {
int if_id = atoi(argv[1]);
if (argc < 3) {
_net_if_ifconfig_list(if_id);
return;
}
else if (strcmp(argv[2], "add") == 0) {
if (argc < 5) {
add_usage();
return;
}
_net_if_ifconfig_add(if_id, argc, argv);
return;
}
else if (strcmp(argv[2], "set") == 0) {
if (argc < 5) {
set_usage();
return;
}
_net_if_ifconfig_set(if_id, argv[3], argv[4]);
return;
}
}
create_usage();
printf("or: ifconfig [<if_id> [add <protocol> <addr>|set <key> <value>]]\n");
}
void _net_if_ifconfig_set_srcaddrmode(int if_id, char *mode)
{
if (mode == NULL) {
set_usage();
return;
}
else if (strcmp(mode, "short") == 0) {
net_if_set_src_address_mode(if_id, NET_IF_TRANS_ADDR_M_SHORT);
}
else if (strcmp(mode, "long") == 0) {
net_if_set_src_address_mode(if_id, NET_IF_TRANS_ADDR_M_LONG);
}
else {
set_usage();
return;
}
}
void _net_if_ifconfig_set_eui64(int if_id, char *eui64_str)
{
net_if_eui64_t eui64;
if (eui64_str == NULL) {
set_usage();
return;
}
net_if_hex_to_eui64(&eui64, eui64_str);
net_if_set_eui64(if_id, &eui64);
}
void _net_if_ifconfig_set_hwaddr(int if_id, char *addr_str)
{
int addr;
if (addr_str == NULL) {
set_usage();
return;
}
if (isnumber(addr_str)) {
if ((addr = atoi(addr_str)) > 0xffff) {
set_usage();
return;
}
}
else {
if ((addr = strtoul(addr_str, NULL, 16)) > 0xffff) {
set_usage();
return;
}
}
net_if_set_hardware_address(if_id, (uint16_t)addr);
}
void _net_if_ifconfig_set_pan_id(int if_id, char *pan_str)
{
int pan_id;
if (pan_str == NULL) {
set_usage();
return;
}
if (isnumber(pan_str)) {
if ((pan_id = atoi(pan_str)) > 0xffff) {
set_usage();
return;
}
}
else {
if ((pan_id = strtoul(pan_str, NULL, 16)) > 0xffff) {
set_usage();
return;
}
}
net_if_set_pan_id(if_id, (uint16_t) pan_id);
}
void _net_if_ifconfig_set_channel(int if_id, char *chan_str)
{
int channel;
if (chan_str == NULL) {
set_usage();
return;
}
if (isnumber(chan_str)) {
if ((channel = atoi(chan_str)) > 0xffff) {
set_usage();
return;
}
}
else {
if ((channel = strtoul(chan_str, NULL, 16)) > 0xffff) {
set_usage();
return;
}
}
net_if_set_channel(if_id, (uint16_t) channel);
}
void _net_if_ifconfig_set(int if_id, char *key, char *value)
{
if (strcmp(key, "sam") == 0 || strcmp(key, "srcaddrmode") == 0) {
_net_if_ifconfig_set_srcaddrmode(if_id, value);
}
else if (strcmp(key, "eui64") == 0) {
_net_if_ifconfig_set_eui64(if_id, value);
}
else if (strcmp(key, "hwaddr") == 0) {
_net_if_ifconfig_set_hwaddr(if_id, value);
}
else if (strcmp(key, "pan") == 0 || strcmp(key, "pan_id") == 0) {
_net_if_ifconfig_set_pan_id(if_id, value);
}
else if (strcmp(key, "chan") == 0 || strcmp(key, "channel") == 0) {
_net_if_ifconfig_set_channel(if_id, value);
}
else {
set_usage();
return;
}
}
void _net_if_ifconfig_add_ipv6(int if_id, int argc, char **argv)
{
char *type;
char *addr_str;
char *addr_data_str;
char *addr_data_len;
net_if_addr_t addr;
if (argc > 5) {
if (strcmp(argv[4], "multicast") == 0 || strcmp(argv[4], "anycast") == 0 || strcmp(argv[4], "unicast") == 0) {
type = argv[4];
addr_str = argv[5];
}
else {
add_usage();
return;
}
}
else {
addr_str = argv[4];
type = NULL;
}
addr_data_str = strtok(addr_str, "/");
addr_data_len = strtok(NULL, "/");
if (!_net_if_ifconfig_ipv6_addr_convert(&addr, type, addr_data_str, addr_data_len)) {
add_usage();
return;
}
if (net_if_add_address(if_id, &addr) < 0) {
add_usage();
return;
}
addr_registered++;
}
void _net_if_ifconfig_add(int if_id, int argc, char **argv)
{
if (strcmp(argv[3], "ipv6") == 0) {
_net_if_ifconfig_add_ipv6(if_id, argc, argv);
}
else {
add_usage();
}
}
void _net_if_ifconfig_create(char *transceivers_str)
{
char *transceiver_str;
transceiver_type_t transceivers = TRANSCEIVER_NONE;
int iface;
transceiver_str = strtok(transceivers_str, ",");
while (transceiver_str) {
if (strcasecmp(transceiver_str, "at86rv231") == 0) {
transceivers |= TRANSCEIVER_AT86RF231;
}
else if (strcasecmp(transceiver_str, "cc1020") == 0) {
transceivers |= TRANSCEIVER_CC1020;
}
else if (strcasecmp(transceiver_str, "cc1100") == 0) {
transceivers |= TRANSCEIVER_CC1100;
}
else if (strcasecmp(transceiver_str, "cc2420") == 0) {
transceivers |= TRANSCEIVER_CC2420;
}
else if (strcasecmp(transceiver_str, "mc1322x") == 0) {
transceivers |= TRANSCEIVER_MC1322X;
}
else if (strcasecmp(transceiver_str, "native") == 0) {
transceivers |= TRANSCEIVER_NATIVE;
}
else {
create_usage();
return;
}
transceiver_str = strtok(NULL, ",");
}
if (!transceivers) {
create_usage();
return;
}
iface = net_if_init_interface(NET_IF_L3P_RAW, transceivers);
if (iface < 0) {
puts("Maximum number of allowed interfaces reached.\n");
}
else {
printf("Initialized interface %d\n", iface);
}
}
static inline int _is_multicast(uint8_t *addr)
{
return *addr == 0xff;
}
static inline int _is_link_local(uint8_t *addr)
{
return (addr[0] == 0xfe && addr[1] == 0x80) ||
(_is_multicast(addr) && (addr[1] & 0x0f) == 2);
}
int _set_protocol_from_type(char *type, net_if_addr_t *addr)
{
if (type != NULL) {
if ((strcmp(type, "multicast") == 0) &&
_is_multicast((uint8_t *)addr->addr_data)) {
addr->addr_protocol |= NET_IF_L3P_IPV6_MULTICAST;
return 1;
}
else if ((strcmp(type, "anycast") == 0) &&
addr->addr_protocol & NET_IF_L3P_IPV6_PREFIX) {
addr->addr_protocol |= NET_IF_L3P_IPV6_ANYCAST;
return 1;
}
return 0;
}
else if (_is_multicast((uint8_t *)addr->addr_data)) {
addr->addr_protocol |= NET_IF_L3P_IPV6_MULTICAST;
return 1;
}
else {
addr->addr_protocol |= NET_IF_L3P_IPV6_UNICAST;
return 1;
}
}
int _net_if_ifconfig_ipv6_addr_convert(net_if_addr_t *addr, char *type,
char *addr_data_str, char *addr_data_len)
{
if (addr_data_len && !isnumber(addr_data_len)) {
return 0;
}
addr->addr_data = (void *)&addrs[addr_registered][0];
if (!inet_pton(AF_INET6, addr_data_str, addr->addr_data)) {
return 0;
}
else if (addr_data_len == NULL) {
addr->addr_len = 128;
addr->addr_protocol = 0;
if (!_set_protocol_from_type(type, addr)) {
return 0;
}
}
else {
addr->addr_len = atoi(addr_data_len);
addr->addr_protocol = NET_IF_L3P_IPV6_PREFIX;
if (addr->addr_len > 128 || !_set_protocol_from_type(type, addr)) {
return 0;
}
}
return 1;
}
void _net_if_ifconfig_list(int if_id)
{
net_if_t *iface = net_if_get_interface(if_id);
transceiver_type_t transceivers;
uint16_t hw_address;
int32_t channel;
int32_t pan_id;
net_if_eui64_t eui64;
char eui64_str[24];
net_if_addr_t *addr_ptr = NULL;
if (!iface) {
return;
}
transceivers = iface->transceivers;
hw_address = net_if_get_hardware_address(if_id);
channel = net_if_get_channel(if_id);
pan_id = net_if_get_pan_id(if_id);
net_if_get_eui64(&eui64, if_id, 0);
_eui64_to_str(eui64_str, &eui64);
printf("Iface %3d HWaddr: 0x%04x", if_id,
hw_address);
if (channel < 0) {
printf(" Channel: not set");
}
else {
printf(" Channel: %d", (uint16_t) channel);
}
if (pan_id < 0) {
printf(" PAN ID: not set");
}
else {
printf(" PAN ID: 0x%04x", (uint16_t)pan_id);
}
printf("\n");
printf(" EUI-64: %s\n", eui64_str);
switch (net_if_get_src_address_mode(if_id)) {
case NET_IF_TRANS_ADDR_M_SHORT:
puts(" Source address mode: short");
break;
case NET_IF_TRANS_ADDR_M_LONG:
puts(" Source address mode: long");
break;
default:
puts(" Source address mode: unknown");
break;
}
puts(" Transceivers:");
if (transceivers & TRANSCEIVER_AT86RF231) {
puts(" * at86rf231");
}
if (transceivers & TRANSCEIVER_CC1020) {
puts(" * cc1020");
}
if (transceivers & TRANSCEIVER_CC1100) {
puts(" * cc1100");
}
if (transceivers & TRANSCEIVER_CC2420) {
puts(" * cc2420");
}
if (transceivers & TRANSCEIVER_MC1322X) {
puts(" * mc1322x");
}
if (transceivers & TRANSCEIVER_NATIVE) {
puts(" * native");
}
while (net_if_iter_addresses(if_id, &addr_ptr)) {
if (addr_ptr->addr_protocol == NET_IF_L3P_RAW) {
char addr_str[addr_ptr->addr_len / 4 + 3];
printf(" Raw L3 addr: 0x");
printf("%s", addr_data_to_str(addr_str, addr_ptr->addr_data,
addr_ptr->addr_len));
puts("\n");
}
if (addr_ptr->addr_protocol & NET_IF_L3P_IPV6) {
char addr_str[50];
printf(" inet6 addr: ");
if (inet_ntop(AF_INET6, addr_ptr->addr_data, addr_str,
addr_ptr->addr_len / 8 + 1)) {
printf("%s/%d", addr_str, addr_ptr->addr_len);
printf(" scope: ");
if (addr_ptr->addr_len > 2 && _is_link_local((uint8_t *)addr_ptr->addr_data)) {
printf("local");
}
else {
printf("local");
}
if (!(addr_ptr->addr_protocol & NET_IF_L3P_IPV6_UNICAST)) {
printf(" ");
if (addr_ptr->addr_protocol & NET_IF_L3P_IPV6_MULTICAST) {
printf("[multicast]");
}
else if (addr_ptr->addr_protocol & NET_IF_L3P_IPV6_ANYCAST) {
printf("[anycast]");
}
}
printf("\n");
}
else {
printf("error in conversion\n");
}
}
}
puts("");
}
......@@ -100,6 +100,10 @@ extern void _transceiver_set_ignore_handler(int argc, char **argv);
#endif
#endif
#ifdef MODULE_NET_IF
extern void _net_if_ifconfig(int argc, char **argv);
#endif
#ifdef MODULE_MCI
extern void _get_sectorsize(int argc, char **argv);
extern void _get_blocksize(int argc, char **argv);
......@@ -137,7 +141,6 @@ const shell_command_t _shell_command_list[] = {
{"cur", "Prints current and average power consumption.", _get_current_handler},
{"rstcur", "Resets coulomb counter.", _reset_current_handler},
#endif
#ifdef MODULE_TRANSCEIVER
#ifdef _TC_ADDR
{"addr", "Gets or sets the address for the transceiver", _transceiver_get_set_address_handler},
......@@ -166,7 +169,9 @@ const shell_command_t _shell_command_list[] = {
{"chan", "Gets or sets the channel for the CC1100 transceiver", _cc110x_get_set_channel_handler},
#endif
#endif
#ifdef MODULE_NET_IF
{"ifconfig", "Configures a network interface", _net_if_ifconfig},
#endif
#ifdef MODULE_MCI
{DISK_READ_SECTOR_CMD, "Reads the specified sector of inserted memory card", _read_sector},
{DISK_READ_BYTES_CMD, "Reads the specified bytes from inserted memory card", _read_bytes},
......@@ -178,6 +183,5 @@ const shell_command_t _shell_command_list[] = {
{ "mersenne_init", "initializes the PRNG", _mersenne_init },
{ "mersenne_get", "returns 32 bit of pseudo randomness", _mersenne_get },
#endif
{NULL, NULL, NULL}
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment