1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/sys/shell/commands/sc_netif.c

1220 lines
33 KiB
C
Raw Normal View History

/*
* Copyright (C) 2015 Freie Universität Berlin
*
* 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 sys_shell_commands
* @{
*
* @file
* @brief Shell commands for interacting with network devices
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
2015-03-11 22:54:52 +01:00
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
2016-02-11 22:39:34 +01:00
* @author Oliver Hahm <oliver.hahm@inria.fr>
*/
2015-03-11 22:54:52 +01:00
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "thread.h"
2016-02-11 22:39:34 +01:00
#include "net/netstats.h"
2015-08-10 00:26:36 +02:00
#include "net/ipv6/addr.h"
#include "net/gnrc/ipv6/netif.h"
#include "net/gnrc/netif.h"
#include "net/gnrc/netapi.h"
2015-08-06 15:37:11 +02:00
#include "net/netopt.h"
#include "net/gnrc/pkt.h"
#include "net/gnrc/pktbuf.h"
#include "net/gnrc/netif/hdr.h"
#include "net/gnrc/sixlowpan/netif.h"
/**
* @brief The maximal expected link layer address length in byte
*/
2015-03-11 22:54:52 +01:00
#define MAX_ADDR_LEN (8U)
/**
* @brief The default IPv6 prefix length if not specified.
*/
#define SC_NETIF_IPV6_DEFAULT_PREFIX_LEN (64)
/* utility functions */
2015-03-11 22:54:52 +01:00
static bool _is_number(char *str)
{
for (; *str; str++) {
if (*str < '0' || *str > '9') {
return false;
}
}
return true;
}
static bool _is_iface(kernel_pid_t dev)
{
kernel_pid_t ifs[GNRC_NETIF_NUMOF];
size_t numof = gnrc_netif_get(ifs);
2015-03-11 22:54:52 +01:00
for (size_t i = 0; i < numof && i < GNRC_NETIF_NUMOF; i++) {
2015-03-11 22:54:52 +01:00
if (ifs[i] == dev) {
return true;
}
}
return false;
}
#if defined(MODULE_NETSTATS)
const char *_netstats_module_to_str(uint8_t module)
{
switch (module) {
case NETSTATS_LAYER2:
return "Layer 2";
case NETSTATS_IPV6:
return "IPv6";
case NETSTATS_ALL:
return "all";
default:
return "Unknown";
}
}
static int _netif_stats(kernel_pid_t dev, unsigned module, bool reset)
2016-02-11 22:39:34 +01:00
{
netstats_t *stats;
int res = -ENOTSUP;
if (module == NETSTATS_LAYER2) {
res = gnrc_netapi_get(dev, NETOPT_STATS, 0, &stats, sizeof(&stats));
}
#ifdef MODULE_NETSTATS_IPV6
else if (module == NETSTATS_IPV6) {
stats = gnrc_ipv6_netif_get_stats(dev);
if (stats != NULL) {
res = 1;
}
}
#endif
2016-02-11 22:39:34 +01:00
if (res < 0) {
puts(" Protocol or device doesn't provide statistics.");
}
else if (reset) {
memset(stats, 0, sizeof(netstats_t));
printf("Reset statistics for module %s!\n", _netstats_module_to_str(module));
2016-02-11 22:39:34 +01:00
}
else {
printf(" Statistics for %s\n"
" RX packets %u bytes %u\n"
" TX packets %u (Multicast: %u) bytes %u\n"
" TX succeeded %u errors %u\n",
_netstats_module_to_str(module),
2016-02-11 22:39:34 +01:00
(unsigned) stats->rx_count,
(unsigned) stats->rx_bytes,
(unsigned) (stats->tx_unicast_count + stats->tx_mcast_count),
(unsigned) stats->tx_mcast_count,
(unsigned) stats->tx_bytes,
(unsigned) stats->tx_success,
(unsigned) stats->tx_failed);
res = 0;
2016-02-11 22:39:34 +01:00
}
return res;
}
#endif
2015-03-11 22:54:52 +01:00
static void _set_usage(char *cmd_name)
{
printf("usage: %s <if_id> set <key> <value>\n", cmd_name);
puts(" Sets an hardware specific specific value\n"
" <key> may be one of the following\n"
" * \"addr\" - sets (short) address\n"
" * \"addr_long\" - sets long address\n"
" * \"addr_short\" - alias for \"addr\"\n"
" * \"channel\" - sets the frequency channel\n"
2015-06-01 15:51:50 +02:00
" * \"chan\" - alias for \"channel\"\n"
" * \"csma_retries\" - set max. number of channel access attempts\n"
" * \"cca_threshold\" - set ED threshold during CCA in dBm\n"
2015-03-11 22:54:52 +01:00
" * \"nid\" - sets the network identifier (or the PAN ID)\n"
" * \"page\" - set the channel page (IEEE 802.15.4)\n"
2015-03-11 22:54:52 +01:00
" * \"pan\" - alias for \"nid\"\n"
" * \"pan_id\" - alias for \"nid\"\n"
" * \"power\" - TX power in dBm\n"
" * \"retrans\" - max. number of retransmissions\n"
" * \"src_len\" - sets the source address length in byte\n"
drivers/xbee: encryption support add encryption to drivers fix new line at the end of file add shell command for enable encryption and set encryption key on a given device modify _net_if_set_encrypt_key to support any key length modify _net_if_set_encrypt_key to support any key length of the key modify blank line fix ace before tab in indent fix ace before tab indent fix ace before tab indent an error fix trailing white space drivers/xbee: encryption support add encryption to drivers fix new line at the end of file add shell command for enable encryption and set encryption key on a given device modify _net_if_set_encrypt_key to support any key length modify _net_if_set_encrypt_key to support any key length of the key modify blank line fix ace before tab in indent fix ace before tab indent fix ace before tab indent an error fix trailing white space modify drivers/xbee/xbee.c fix white spaces on xbee.c Update xbee encryption driver white line at end xbee.h fix error fix sc_netif.c fix rebase master interactive drivers/xbee: encryption support add encryption to drivers fix new line at the end of file add shell command for enable encryption and set encryption key on a given device modify _net_if_set_encrypt_key to support any key length modify _net_if_set_encrypt_key to support any key length of the key modify blank line fix ace before tab in indent fix ace before tab indent fix ace before tab indent an error fix trailing white space drivers/xbee: encryption support add encryption to drivers fix new line at the end of file add shell command for enable encryption and set encryption key on a given device modify _net_if_set_encrypt_key to support any key length modify _net_if_set_encrypt_key to support any key length of the key modify blank line fix ace before tab in indent fix ace before tab indent fix ace before tab indent an error fix trailing white space modify drivers/xbee/xbee.c fix white spaces on xbee.c Update xbee encryption driver white line at end xbee.h fix error fix rebase conflict 4 fix same missing in patches changes fix ascii to hex index parser fix syntax rules fix syntax issue 2 add _netopt_strmap NETOPT_ENCRYPTION e NETOPT_ENCRYPTION_KEY fix trailng white spaces
2015-05-14 15:03:52 +02:00
" * \"state\" - set the device state\n"
" * \"encrypt\" - set the encryption on-off\n"
" * \"key\" - set the encryption key in hexadecimal format\n");
2015-03-11 22:54:52 +01:00
}
static void _mtu_usage(char *cmd_name)
{
printf("usage: %s <if_id> mtu <n>\n", cmd_name);
}
static void _hl_usage(char *cmd_name)
{
printf("usage: %s <if_id> hl <n>\n", cmd_name);
}
static void _flag_usage(char *cmd_name)
{
printf("usage: %s <if_id> [-]{promisc|autoack|csma|autocca|cca_threshold|preload|iphc|rtr_adv}\n", cmd_name);
}
static void _add_usage(char *cmd_name)
{
printf("usage: %s <if_id> add [anycast|multicast|unicast] "
"<ipv6_addr>[/prefix_len]\n", cmd_name);
}
static void _del_usage(char *cmd_name)
{
printf("usage: %s <if_id> del <ipv6_addr>\n",
cmd_name);
}
2016-02-11 22:39:34 +01:00
static void _stats_usage(char *cmd_name)
{
printf("usage: %s <if_id> stats [l2|ipv6] [reset]\n", cmd_name);
puts(" reset can be only used if the module is specified.");
2016-02-11 22:39:34 +01:00
}
2015-08-06 15:37:11 +02:00
static void _print_netopt(netopt_t opt)
{
2015-03-11 22:54:52 +01:00
switch (opt) {
2015-08-06 15:37:11 +02:00
case NETOPT_ADDRESS:
2015-03-11 22:54:52 +01:00
printf("(short) address");
break;
2015-08-06 15:37:11 +02:00
case NETOPT_ADDRESS_LONG:
2015-03-11 22:54:52 +01:00
printf("long address");
break;
2015-08-06 15:37:11 +02:00
case NETOPT_SRC_LEN:
2015-03-11 22:54:52 +01:00
printf("source address length");
break;
2015-08-06 15:37:11 +02:00
case NETOPT_CHANNEL:
2015-03-11 22:54:52 +01:00
printf("channel");
break;
case NETOPT_CHANNEL_PAGE:
printf("page");
break;
2015-08-06 15:37:11 +02:00
case NETOPT_NID:
2015-03-11 22:54:52 +01:00
printf("network identifier");
break;
2015-08-06 15:37:11 +02:00
case NETOPT_TX_POWER:
printf("TX power [in dBm]");
break;
case NETOPT_RETRANS:
printf("max. retransmissions");
break;
2015-06-01 15:51:50 +02:00
case NETOPT_CSMA_RETRIES:
printf("CSMA retries");
break;
case NETOPT_CCA_THRESHOLD:
printf("CCA threshold [in dBm]");
break;
drivers/xbee: encryption support add encryption to drivers fix new line at the end of file add shell command for enable encryption and set encryption key on a given device modify _net_if_set_encrypt_key to support any key length modify _net_if_set_encrypt_key to support any key length of the key modify blank line fix ace before tab in indent fix ace before tab indent fix ace before tab indent an error fix trailing white space drivers/xbee: encryption support add encryption to drivers fix new line at the end of file add shell command for enable encryption and set encryption key on a given device modify _net_if_set_encrypt_key to support any key length modify _net_if_set_encrypt_key to support any key length of the key modify blank line fix ace before tab in indent fix ace before tab indent fix ace before tab indent an error fix trailing white space modify drivers/xbee/xbee.c fix white spaces on xbee.c Update xbee encryption driver white line at end xbee.h fix error fix sc_netif.c fix rebase master interactive drivers/xbee: encryption support add encryption to drivers fix new line at the end of file add shell command for enable encryption and set encryption key on a given device modify _net_if_set_encrypt_key to support any key length modify _net_if_set_encrypt_key to support any key length of the key modify blank line fix ace before tab in indent fix ace before tab indent fix ace before tab indent an error fix trailing white space drivers/xbee: encryption support add encryption to drivers fix new line at the end of file add shell command for enable encryption and set encryption key on a given device modify _net_if_set_encrypt_key to support any key length modify _net_if_set_encrypt_key to support any key length of the key modify blank line fix ace before tab in indent fix ace before tab indent fix ace before tab indent an error fix trailing white space modify drivers/xbee/xbee.c fix white spaces on xbee.c Update xbee encryption driver white line at end xbee.h fix error fix rebase conflict 4 fix same missing in patches changes fix ascii to hex index parser fix syntax rules fix syntax issue 2 add _netopt_strmap NETOPT_ENCRYPTION e NETOPT_ENCRYPTION_KEY fix trailng white spaces
2015-05-14 15:03:52 +02:00
case NETOPT_ENCRYPTION:
printf("encryption");
break;
case NETOPT_ENCRYPTION_KEY:
printf("encryption key");
break;
2015-03-11 22:54:52 +01:00
default:
/* we don't serve these options here */
break;
}
}
2015-08-06 15:37:11 +02:00
static void _print_netopt_state(netopt_state_t state)
{
switch (state) {
2015-08-06 15:37:11 +02:00
case NETOPT_STATE_OFF:
printf("OFF");
break;
2015-08-06 15:37:11 +02:00
case NETOPT_STATE_SLEEP:
printf("SLEEP");
break;
2015-08-06 15:37:11 +02:00
case NETOPT_STATE_IDLE:
printf("IDLE");
break;
2015-08-06 15:37:11 +02:00
case NETOPT_STATE_RX:
printf("RX");
break;
2015-08-06 15:37:11 +02:00
case NETOPT_STATE_TX:
printf("TX");
break;
2015-08-06 15:37:11 +02:00
case NETOPT_STATE_RESET:
printf("RESET");
break;
default:
/* nothing to do then */
break;
}
}
static void _netif_list(kernel_pid_t dev)
{
2015-03-11 22:54:52 +01:00
uint8_t hwaddr[MAX_ADDR_LEN];
uint16_t u16;
int16_t i16;
2015-06-01 15:51:50 +02:00
uint8_t u8;
2015-03-11 22:54:52 +01:00
int res;
2015-08-06 15:37:11 +02:00
netopt_state_t state;
netopt_enable_t enable = NETOPT_DISABLE;
bool linebreak = false;
#ifdef MODULE_GNRC_IPV6_NETIF
gnrc_ipv6_netif_t *entry = gnrc_ipv6_netif_get(dev);
2015-08-10 00:26:36 +02:00
char ipv6_addr[IPV6_ADDR_MAX_STR_LEN];
#endif
2015-03-11 22:54:52 +01:00
printf("Iface %2d ", dev);
res = gnrc_netapi_get(dev, NETOPT_ADDRESS, 0, hwaddr, sizeof(hwaddr));
2015-03-11 22:54:52 +01:00
if (res >= 0) {
char hwaddr_str[res * 3];
2015-03-11 22:54:52 +01:00
printf(" HWaddr: ");
printf("%s", gnrc_netif_addr_to_str(hwaddr_str, sizeof(hwaddr_str),
hwaddr, res));
2015-03-11 22:54:52 +01:00
printf(" ");
}
2015-03-11 22:54:52 +01:00
res = gnrc_netapi_get(dev, NETOPT_CHANNEL, 0, &u16, sizeof(u16));
2015-03-11 22:54:52 +01:00
if (res >= 0) {
printf(" Channel: %" PRIu16 " ", u16);
}
2015-03-11 22:54:52 +01:00
res = gnrc_netapi_get(dev, NETOPT_CHANNEL_PAGE, 0, &u16, sizeof(u16));
if (res >= 0) {
printf(" Page: %" PRIu16 " ", u16);
}
res = gnrc_netapi_get(dev, NETOPT_NID, 0, &u16, sizeof(u16));
2015-03-11 22:54:52 +01:00
if (res >= 0) {
printf(" NID: 0x%" PRIx16, u16);
}
2015-03-11 22:54:52 +01:00
2016-02-09 17:57:03 +01:00
printf("\n ");
res = gnrc_netapi_get(dev, NETOPT_ADDRESS_LONG, 0, hwaddr, sizeof(hwaddr));
if (res >= 0) {
char hwaddr_str[res * 3];
printf("Long HWaddr: ");
printf("%s ", gnrc_netif_addr_to_str(hwaddr_str, sizeof(hwaddr_str),
hwaddr, res));
linebreak = true;
}
if (linebreak) {
printf("\n ");
}
res = gnrc_netapi_get(dev, NETOPT_TX_POWER, 0, &i16, sizeof(i16));
if (res >= 0) {
printf(" TX-Power: %" PRIi16 "dBm ", i16);
}
res = gnrc_netapi_get(dev, NETOPT_STATE, 0, &state, sizeof(state));
if (res >= 0) {
printf(" State: ");
_print_netopt_state(state);
printf(" ");
}
res = gnrc_netapi_get(dev, NETOPT_RETRANS, 0, &u8, sizeof(u8));
if (res >= 0) {
printf(" max. Retrans.: %u ", (unsigned)u8);
}
2015-09-11 13:13:55 +02:00
res = gnrc_netapi_get(dev, NETOPT_CSMA_RETRIES, 0, &u8, sizeof(u8));
if (res >= 0) {
res = gnrc_netapi_get(dev, NETOPT_CSMA, 0, &enable, sizeof(enable));
if ((res >= 0) && (enable == NETOPT_ENABLE)) {
printf(" CSMA Retries: %u ", (unsigned)u8);
2015-09-11 13:13:55 +02:00
}
}
printf("\n ");
2015-03-11 22:54:52 +01:00
res = gnrc_netapi_get(dev, NETOPT_PROMISCUOUSMODE, 0, &enable, sizeof(enable));
2015-08-06 15:37:11 +02:00
if ((res >= 0) && (enable == NETOPT_ENABLE)) {
printf("PROMISC ");
linebreak = true;
}
res = gnrc_netapi_get(dev, NETOPT_AUTOACK, 0, &enable, sizeof(enable));
2015-08-06 15:37:11 +02:00
if ((res >= 0) && (enable == NETOPT_ENABLE)) {
printf("AUTOACK ");
linebreak = true;
}
res = gnrc_netapi_get(dev, NETOPT_PRELOADING, 0, &enable, sizeof(enable));
2015-08-06 15:37:11 +02:00
if ((res >= 0) && (enable == NETOPT_ENABLE)) {
printf("PRELOAD ");
linebreak = true;
}
res = gnrc_netapi_get(dev, NETOPT_RAWMODE, 0, &enable, sizeof(enable));
2015-08-06 15:37:11 +02:00
if ((res >= 0) && (enable == NETOPT_ENABLE)) {
printf("RAWMODE ");
linebreak = true;
}
2015-06-01 15:51:50 +02:00
res = gnrc_netapi_get(dev, NETOPT_CSMA, 0, &enable, sizeof(enable));
if ((res >= 0) && (enable == NETOPT_ENABLE)) {
printf("CSMA ");
linebreak = true;
}
res = gnrc_netapi_get(dev, NETOPT_AUTOCCA, 0, &enable, sizeof(enable));
if ((res >= 0) && (enable == NETOPT_ENABLE)) {
printf("AUTOCCA ");
linebreak = true;
}
#ifdef MODULE_GNRC_IPV6_NETIF
if (entry != NULL) {
printf("MTU:%" PRIu16 " ", entry->mtu);
printf("HL:%u ", (unsigned)entry->cur_hl);
if (entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) {
printf("6LO ");
}
if (entry->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER) {
printf("RTR ");
}
if (entry->flags & GNRC_IPV6_NETIF_FLAGS_RTR_ADV) {
printf("RTR_ADV ");
}
linebreak = true;
}
#endif
#if defined(MODULE_GNRC_SIXLOWPAN_NETIF) && defined(MODULE_GNRC_SIXLOWPAN_IPHC)
gnrc_sixlowpan_netif_t *sixlo_entry = gnrc_sixlowpan_netif_get(dev);
if ((sixlo_entry != NULL) && (sixlo_entry->iphc_enabled)) {
printf("IPHC ");
linebreak = true;
}
#endif
if (linebreak) {
printf("\n ");
}
res = gnrc_netapi_get(dev, NETOPT_SRC_LEN, 0, &u16, sizeof(u16));
2015-03-11 22:54:52 +01:00
if (res >= 0) {
2015-05-09 16:13:12 +02:00
printf("Source address length: %" PRIu16 "\n ", u16);
2015-03-11 22:54:52 +01:00
}
#ifdef MODULE_GNRC_IPV6_NETIF
if (entry == NULL) {
puts("");
return;
}
printf("Link type: %s", (entry->flags & GNRC_IPV6_NETIF_FLAGS_IS_WIRED) ?
2015-09-11 13:14:21 +02:00
"wired" : "wireless");
printf("\n ");
for (int i = 0; i < GNRC_IPV6_NETIF_ADDR_NUMOF; i++) {
2015-08-10 00:26:36 +02:00
if (!ipv6_addr_is_unspecified(&entry->addrs[i].addr)) {
printf("inet6 addr: ");
2015-08-10 00:26:36 +02:00
if (ipv6_addr_to_str(ipv6_addr, &entry->addrs[i].addr,
IPV6_ADDR_MAX_STR_LEN)) {
printf("%s/%u scope: ", ipv6_addr, (unsigned)entry->addrs[i].prefix_len);
2015-08-10 00:26:36 +02:00
if ((ipv6_addr_is_link_local(&entry->addrs[i].addr))) {
printf("local");
}
else {
printf("global");
}
if (entry->addrs[i].flags & GNRC_IPV6_NETIF_ADDR_FLAGS_NON_UNICAST) {
2015-08-10 00:26:36 +02:00
if (ipv6_addr_is_multicast(&entry->addrs[i].addr)) {
printf(" [multicast]");
}
else {
printf(" [anycast]");
}
}
}
else {
printf("error in conversion");
}
printf("\n ");
}
}
#endif
2015-03-11 22:54:52 +01:00
2016-02-11 23:06:07 +01:00
#ifdef MODULE_NETSTATS_L2
2016-02-11 22:39:34 +01:00
puts("");
_netif_stats(dev, NETSTATS_LAYER2, false);
#endif
#ifdef MODULE_NETSTATS_IPV6
_netif_stats(dev, NETSTATS_IPV6, false);
2016-02-11 22:39:34 +01:00
#endif
2015-03-11 22:54:52 +01:00
puts("");
}
2015-08-06 15:37:11 +02:00
static int _netif_set_u16(kernel_pid_t dev, netopt_t opt, char *u16_str)
{
2015-03-11 22:54:52 +01:00
unsigned int res;
bool hex = false;
2015-03-11 22:54:52 +01:00
if (_is_number(u16_str)) {
if ((res = strtoul(u16_str, NULL, 10)) == ULONG_MAX) {
puts("error: unable to parse value.\n"
"Must be a 16-bit unsigned integer (dec or hex)\n");
return 1;
2015-03-11 22:54:52 +01:00
}
}
2015-03-11 22:54:52 +01:00
else {
if ((res = strtoul(u16_str, NULL, 16)) == ULONG_MAX) {
puts("error: unable to parse value.\n"
"Must be a 16-bit unsigned integer (dec or hex)\n");
return 1;
2015-03-11 22:54:52 +01:00
}
hex = true;
}
if (res > 0xffff) {
puts("error: unable to parse value.\n"
"Must be a 16-bit unsigned integer (dec or hex)\n");
return 1;
}
2015-03-11 22:54:52 +01:00
if (gnrc_netapi_set(dev, opt, 0, (uint16_t *)&res, sizeof(uint16_t)) < 0) {
2015-03-11 22:54:52 +01:00
printf("error: unable to set ");
_print_netopt(opt);
2015-03-11 22:54:52 +01:00
puts("");
return 1;
2015-03-11 22:54:52 +01:00
}
printf("success: set ");
_print_netopt(opt);
2015-03-11 22:54:52 +01:00
printf(" on interface %" PRIkernel_pid " to ", dev);
if (hex) {
printf("0x%04x\n", res);
}
else {
2015-03-11 22:54:52 +01:00
printf("%u\n", res);
}
return 0;
}
2015-08-06 15:37:11 +02:00
static int _netif_set_i16(kernel_pid_t dev, netopt_t opt, char *i16_str)
{
int16_t val = (int16_t)atoi(i16_str);
if (gnrc_netapi_set(dev, opt, 0, (int16_t *)&val, sizeof(int16_t)) < 0) {
printf("error: unable to set ");
_print_netopt(opt);
puts("");
return 1;
}
printf("success: set ");
_print_netopt(opt);
printf(" on interface %" PRIkernel_pid " to %i\n", dev, val);
return 0;
}
2015-06-01 15:51:50 +02:00
static int _netif_set_u8(kernel_pid_t dev, netopt_t opt, char *u8_str)
{
uint8_t val = (uint8_t)atoi(u8_str);
if (gnrc_netapi_set(dev, opt, 0, (uint8_t *)&val, sizeof(uint8_t)) < 0) {
printf("error: unable to set ");
_print_netopt(opt);
puts("");
return 1;
}
printf("success: set ");
_print_netopt(opt);
printf(" on interface %" PRIkernel_pid " to %i\n", dev, val);
return 0;
}
2015-08-06 15:37:11 +02:00
static int _netif_set_flag(kernel_pid_t dev, netopt_t opt,
netopt_enable_t set)
{
if (gnrc_netapi_set(dev, opt, 0, &set, sizeof(netopt_enable_t)) < 0) {
puts("error: unable to set option");
return 1;
}
printf("success: %sset option\n", (set) ? "" : "un");
return 0;
}
2015-08-06 15:37:11 +02:00
static int _netif_set_addr(kernel_pid_t dev, netopt_t opt, char *addr_str)
{
2015-03-11 22:54:52 +01:00
uint8_t addr[MAX_ADDR_LEN];
size_t addr_len = gnrc_netif_addr_from_str(addr, sizeof(addr), addr_str);
2015-03-11 22:54:52 +01:00
if (addr_len == 0) {
puts("error: unable to parse address.\n"
"Must be of format [0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*\n"
"(hex pairs delimited by colons)");
return 1;
}
2015-03-11 22:54:52 +01:00
if (gnrc_netapi_set(dev, opt, 0, addr, addr_len) < 0) {
2015-03-11 22:54:52 +01:00
printf("error: unable to set ");
_print_netopt(opt);
2015-03-11 22:54:52 +01:00
puts("");
return 1;
}
2015-03-11 22:54:52 +01:00
printf("success: set ");
_print_netopt(opt);
printf(" on interface %" PRIkernel_pid " to %s\n", dev, addr_str);
return 0;
2015-03-11 22:54:52 +01:00
}
static int _netif_set_state(kernel_pid_t dev, char *state_str)
{
2015-08-06 15:37:11 +02:00
netopt_state_t state;
if ((strcmp("off", state_str) == 0) || (strcmp("OFF", state_str) == 0)) {
2015-08-06 15:37:11 +02:00
state = NETOPT_STATE_OFF;
}
else if ((strcmp("sleep", state_str) == 0) ||
(strcmp("SLEEP", state_str) == 0)) {
2015-08-06 15:37:11 +02:00
state = NETOPT_STATE_SLEEP;
}
else if ((strcmp("idle", state_str) == 0) ||
(strcmp("IDLE", state_str) == 0)) {
2015-08-06 15:37:11 +02:00
state = NETOPT_STATE_IDLE;
}
else if ((strcmp("reset", state_str) == 0) ||
(strcmp("RESET", state_str) == 0)) {
2015-08-06 15:37:11 +02:00
state = NETOPT_STATE_RESET;
}
else {
puts("usage: ifconfig <if_id> set state [off|sleep|idle|reset]");
return 1;
}
if (gnrc_netapi_set(dev, NETOPT_STATE, 0,
&state, sizeof(netopt_state_t)) < 0) {
printf("error: unable to set state to ");
_print_netopt_state(state);
puts("");
return 1;
}
printf("success: set state of interface %" PRIkernel_pid " to ", dev);
_print_netopt_state(state);
puts("");
return 0;
}
drivers/xbee: encryption support add encryption to drivers fix new line at the end of file add shell command for enable encryption and set encryption key on a given device modify _net_if_set_encrypt_key to support any key length modify _net_if_set_encrypt_key to support any key length of the key modify blank line fix ace before tab in indent fix ace before tab indent fix ace before tab indent an error fix trailing white space drivers/xbee: encryption support add encryption to drivers fix new line at the end of file add shell command for enable encryption and set encryption key on a given device modify _net_if_set_encrypt_key to support any key length modify _net_if_set_encrypt_key to support any key length of the key modify blank line fix ace before tab in indent fix ace before tab indent fix ace before tab indent an error fix trailing white space modify drivers/xbee/xbee.c fix white spaces on xbee.c Update xbee encryption driver white line at end xbee.h fix error fix sc_netif.c fix rebase master interactive drivers/xbee: encryption support add encryption to drivers fix new line at the end of file add shell command for enable encryption and set encryption key on a given device modify _net_if_set_encrypt_key to support any key length modify _net_if_set_encrypt_key to support any key length of the key modify blank line fix ace before tab in indent fix ace before tab indent fix ace before tab indent an error fix trailing white space drivers/xbee: encryption support add encryption to drivers fix new line at the end of file add shell command for enable encryption and set encryption key on a given device modify _net_if_set_encrypt_key to support any key length modify _net_if_set_encrypt_key to support any key length of the key modify blank line fix ace before tab in indent fix ace before tab indent fix ace before tab indent an error fix trailing white space modify drivers/xbee/xbee.c fix white spaces on xbee.c Update xbee encryption driver white line at end xbee.h fix error fix rebase conflict 4 fix same missing in patches changes fix ascii to hex index parser fix syntax rules fix syntax issue 2 add _netopt_strmap NETOPT_ENCRYPTION e NETOPT_ENCRYPTION_KEY fix trailng white spaces
2015-05-14 15:03:52 +02:00
static int _netif_set_encrypt(kernel_pid_t dev, netopt_t opt, char *encrypt_str)
{
netopt_enable_t set;
size_t size = 1;
if ((strcmp("on", encrypt_str) == 0) || (strcmp("ON", encrypt_str) == 0)) {
set = NETOPT_ENABLE;
}
else if ((strcmp("off", encrypt_str) == 0) || (strcmp("OFF", encrypt_str) == 0)) {
set = NETOPT_DISABLE;
}
else {
puts("usage: ifconfig <if_id> set encryption [on|off]");
return 1;
}
if (gnrc_netapi_set(dev, opt, 0, &set, size) < 0) {
printf("error: unable to set ");
_print_netopt(opt);
puts("");
return 1;
}
printf("success: set ");
_print_netopt(opt);
printf(" on interface %" PRIkernel_pid " to %s\n", dev, encrypt_str);
return 0;
}
static int _hex_to_int(char c) {
if ('0' <= c && c <= '9') {
return c - '0';
}
else if ('a' <= c && c <= 'f') {
return c - 'a';
}
else if ('A' <= c && c <= 'F') {
return c - 'A';
}
else {
return -1;
}
}
static int _netif_set_encrypt_key(kernel_pid_t dev, netopt_t opt, char *key_str)
{
size_t str_len = strlen(key_str);
size_t key_len = str_len / 2;
uint8_t key[key_len];
if (str_len == 14U) {
printf("\nNotice: setting 56 bit key.");
}
else if (str_len == 16U) {
printf("\nNotice: setting 64 bit key.");
}
else if (str_len == 32U) {
printf("\nNotice: setting 128 bit key.");
}
else if (str_len == 48U) {
printf("\nNotice: setting 192 bit key.");
}
else if (str_len == 64U) {
printf("\nNotice: setting 256 bit key.");
}
else if (str_len == 128U) {
printf("\nNotice: setting 512 bit key.");
}
else {
printf("error: invalid key size.\n");
return 1;
}
/* Convert any char from ASCII table in hex format */
for (size_t i = 0; i < str_len; i += 2) {
int i1 = _hex_to_int(key_str[i]);
int i2 = _hex_to_int(key_str[i + 1]);
if (i1 == -1 || i2 == -1) {
puts("error: unable to parse key");
return 1;
}
key[i / 2] = (uint8_t)((i1 << 4) + i2);
}
if (gnrc_netapi_set(dev, opt, 0, key, key_len) < 0) {
printf("error: unable to set ");
_print_netopt(opt);
puts("");
return 1;
}
printf("success: set ");
_print_netopt(opt);
printf(" on interface %" PRIkernel_pid " to \n", dev);
for (size_t i = 0; i < key_len; i++) {
/* print the hex value of the key */
printf("%02x", key[i]);
}
puts("");
return 0;
}
static int _netif_set(char *cmd_name, kernel_pid_t dev, char *key, char *value)
2015-03-11 22:54:52 +01:00
{
if ((strcmp("addr", key) == 0) || (strcmp("addr_short", key) == 0)) {
2015-08-06 15:37:11 +02:00
return _netif_set_addr(dev, NETOPT_ADDRESS, value);
2015-03-11 22:54:52 +01:00
}
else if (strcmp("addr_long", key) == 0) {
2015-08-06 15:37:11 +02:00
return _netif_set_addr(dev, NETOPT_ADDRESS_LONG, value);
2015-03-11 22:54:52 +01:00
}
else if ((strcmp("channel", key) == 0) || (strcmp("chan", key) == 0)) {
2015-08-06 15:37:11 +02:00
return _netif_set_u16(dev, NETOPT_CHANNEL, value);
2015-03-11 22:54:52 +01:00
}
else if (strcmp("page", key) == 0) {
return _netif_set_u16(dev, NETOPT_CHANNEL_PAGE, value);
}
2015-03-11 22:54:52 +01:00
else if ((strcmp("nid", key) == 0) || (strcmp("pan", key) == 0) ||
(strcmp("pan_id", key) == 0)) {
2015-08-06 15:37:11 +02:00
return _netif_set_u16(dev, NETOPT_NID, value);
2015-03-11 22:54:52 +01:00
}
else if (strcmp("power", key) == 0) {
2015-08-06 15:37:11 +02:00
return _netif_set_i16(dev, NETOPT_TX_POWER, value);
}
2015-03-11 22:54:52 +01:00
else if (strcmp("src_len", key) == 0) {
2015-08-06 15:37:11 +02:00
return _netif_set_u16(dev, NETOPT_SRC_LEN, value);
}
else if (strcmp("state", key) == 0) {
return _netif_set_state(dev, value);
}
else if (strcmp("retrans", key) == 0) {
return _netif_set_u8(dev, NETOPT_RETRANS, value);
}
2015-06-01 15:51:50 +02:00
else if (strcmp("csma_retries", key) == 0) {
return _netif_set_u8(dev, NETOPT_CSMA_RETRIES, value);
}
else if (strcmp("cca_threshold", key) == 0) {
return _netif_set_u8(dev, NETOPT_CCA_THRESHOLD, value);
}
drivers/xbee: encryption support add encryption to drivers fix new line at the end of file add shell command for enable encryption and set encryption key on a given device modify _net_if_set_encrypt_key to support any key length modify _net_if_set_encrypt_key to support any key length of the key modify blank line fix ace before tab in indent fix ace before tab indent fix ace before tab indent an error fix trailing white space drivers/xbee: encryption support add encryption to drivers fix new line at the end of file add shell command for enable encryption and set encryption key on a given device modify _net_if_set_encrypt_key to support any key length modify _net_if_set_encrypt_key to support any key length of the key modify blank line fix ace before tab in indent fix ace before tab indent fix ace before tab indent an error fix trailing white space modify drivers/xbee/xbee.c fix white spaces on xbee.c Update xbee encryption driver white line at end xbee.h fix error fix sc_netif.c fix rebase master interactive drivers/xbee: encryption support add encryption to drivers fix new line at the end of file add shell command for enable encryption and set encryption key on a given device modify _net_if_set_encrypt_key to support any key length modify _net_if_set_encrypt_key to support any key length of the key modify blank line fix ace before tab in indent fix ace before tab indent fix ace before tab indent an error fix trailing white space drivers/xbee: encryption support add encryption to drivers fix new line at the end of file add shell command for enable encryption and set encryption key on a given device modify _net_if_set_encrypt_key to support any key length modify _net_if_set_encrypt_key to support any key length of the key modify blank line fix ace before tab in indent fix ace before tab indent fix ace before tab indent an error fix trailing white space modify drivers/xbee/xbee.c fix white spaces on xbee.c Update xbee encryption driver white line at end xbee.h fix error fix rebase conflict 4 fix same missing in patches changes fix ascii to hex index parser fix syntax rules fix syntax issue 2 add _netopt_strmap NETOPT_ENCRYPTION e NETOPT_ENCRYPTION_KEY fix trailng white spaces
2015-05-14 15:03:52 +02:00
else if (strcmp("encrypt", key) == 0) {
return _netif_set_encrypt(dev, NETOPT_ENCRYPTION, value);
}
else if (strcmp("key", key) == 0) {
return _netif_set_encrypt_key(dev, NETOPT_ENCRYPTION_KEY, value);
}
_set_usage(cmd_name);
return 1;
}
static int _netif_flag(char *cmd, kernel_pid_t dev, char *flag)
{
2015-08-06 15:37:11 +02:00
netopt_enable_t set = NETOPT_ENABLE;
if (flag[0] == '-') {
2015-08-06 15:37:11 +02:00
set = NETOPT_DISABLE;
flag++;
}
if (strcmp(flag, "promisc") == 0) {
2015-08-06 15:37:11 +02:00
return _netif_set_flag(dev, NETOPT_PROMISCUOUSMODE, set);
}
else if (strcmp(flag, "preload") == 0) {
2015-08-06 15:37:11 +02:00
return _netif_set_flag(dev, NETOPT_PRELOADING, set);
}
else if (strcmp(flag, "autoack") == 0) {
2015-08-06 15:37:11 +02:00
return _netif_set_flag(dev, NETOPT_AUTOACK, set);
}
else if (strcmp(flag, "raw") == 0) {
2015-08-06 15:37:11 +02:00
return _netif_set_flag(dev, NETOPT_RAWMODE, set);
}
2015-06-01 15:51:50 +02:00
else if (strcmp(flag, "csma") == 0) {
return _netif_set_flag(dev, NETOPT_CSMA, set);
}
else if (strcmp(flag, "autocca") == 0) {
return _netif_set_flag(dev, NETOPT_AUTOCCA, set);
}
else if (strcmp(flag, "iphc") == 0) {
#if defined(MODULE_GNRC_SIXLOWPAN_NETIF) && defined(MODULE_GNRC_SIXLOWPAN_IPHC)
gnrc_sixlowpan_netif_t *entry = gnrc_sixlowpan_netif_get(dev);
if (entry == NULL) {
puts("error: unable to (un)set IPHC");
return 1;
}
if (set) {
entry->iphc_enabled = true;
printf("success: enable IPHC on interface %" PRIkernel_pid "\n", dev);
}
else {
entry->iphc_enabled = false;
printf("success: disable IPHC on interface %" PRIkernel_pid "\n", dev);
}
return 0;
#else
puts("error: unable to (un)set IPHC.");
return 1;
#endif
}
else if (strcmp(flag, "rtr_adv") == 0) {
#if defined(MODULE_GNRC_NDP_ROUTER) || defined(MODULE_GNRC_SIXLOWPAN_ND_ROUTER)
gnrc_ipv6_netif_t *entry = gnrc_ipv6_netif_get(dev);
if (entry == NULL) {
puts("error: unable to (un)set router advertisement flag.");
return 1;
}
if (set) {
gnrc_ipv6_netif_set_rtr_adv(entry, true);
printf("success: enable router advertisements on interface %" PRIkernel_pid "\n", dev);
}
else {
gnrc_ipv6_netif_set_rtr_adv(entry, false);
printf("success: disable router advertisements on interface %" PRIkernel_pid "\n",
dev);
}
return 0;
#else
puts("error: unable to (un)set router advertisement flag.");
return 1;
#endif
}
_flag_usage(cmd);
return 1;
}
#ifdef MODULE_GNRC_IPV6_NETIF
static uint8_t _get_prefix_len(char *addr)
{
int prefix_len = ipv6_addr_split(addr, '/', SC_NETIF_IPV6_DEFAULT_PREFIX_LEN);
if ((prefix_len < 1) || (prefix_len > IPV6_ADDR_BIT_LEN)) {
prefix_len = SC_NETIF_IPV6_DEFAULT_PREFIX_LEN;
}
return prefix_len;
}
#endif
static int _netif_add(char *cmd_name, kernel_pid_t dev, int argc, char **argv)
{
#ifdef MODULE_GNRC_IPV6_NETIF
enum {
_UNICAST = 0,
_MULTICAST, /* multicast value just to check if given addr is mc */
_ANYCAST
} type = _UNICAST;
char *addr_str = argv[0];
2015-08-10 00:26:36 +02:00
ipv6_addr_t addr;
ipv6_addr_t *ifaddr;
uint8_t prefix_len, flags = 0;
if (argc > 1) {
if (strcmp(argv[0], "anycast") == 0) {
type = _ANYCAST;
addr_str = argv[1];
}
else if (strcmp(argv[0], "multicast") == 0) {
type = _MULTICAST;
addr_str = argv[1];
}
else if (strcmp(argv[0], "unicast") == 0) {
/* type already set to unicast */
addr_str = argv[1];
}
else {
_add_usage(cmd_name);
return 1;
}
}
prefix_len = _get_prefix_len(addr_str);
2015-08-10 00:26:36 +02:00
if (ipv6_addr_from_str(&addr, addr_str) == NULL) {
puts("error: unable to parse IPv6 address.");
return 1;
}
2015-08-10 00:26:36 +02:00
if ((argc > 1) && (ipv6_addr_is_multicast(&addr)) && (type != _MULTICAST)) {
puts("error: address was not a multicast address.");
return 1;
}
flags = GNRC_IPV6_NETIF_ADDR_FLAGS_NDP_AUTO;
if (type == _ANYCAST) {
flags |= GNRC_IPV6_NETIF_ADDR_FLAGS_NON_UNICAST;
}
else {
flags |= GNRC_IPV6_NETIF_ADDR_FLAGS_UNICAST;
}
if ((ifaddr = gnrc_ipv6_netif_add_addr(dev, &addr, prefix_len, flags)) == NULL) {
printf("error: unable to add IPv6 address\n");
return 1;
}
/* Address shall be valid infinitely */
gnrc_ipv6_netif_addr_get(ifaddr)->valid = UINT32_MAX;
/* Address shall be preferred infinitely */
gnrc_ipv6_netif_addr_get(ifaddr)->preferred = UINT32_MAX;
printf("success: added %s/%d to interface %" PRIkernel_pid "\n", addr_str,
prefix_len, dev);
return 0;
#else
(void)cmd_name;
(void)dev;
(void)argc;
(void)argv;
puts("error: unable to add IPv6 address.");
return 1;
#endif
}
static int _netif_del(kernel_pid_t dev, char *addr_str)
{
#ifdef MODULE_GNRC_IPV6_NETIF
2015-08-10 00:26:36 +02:00
ipv6_addr_t addr;
2015-08-10 00:26:36 +02:00
if (ipv6_addr_from_str(&addr, addr_str) == NULL) {
puts("error: unable to parse IPv6 address.");
return 1;
}
gnrc_ipv6_netif_remove_addr(dev, &addr);
printf("success: removed %s to interface %" PRIkernel_pid "\n", addr_str,
dev);
return 0;
#else
(void)dev;
(void)addr_str;
puts("error: unable to delete IPv6 address.");
return 1;
#endif
}
static int _netif_mtu(kernel_pid_t dev, char *mtu_str)
{
#ifdef MODULE_GNRC_IPV6_NETIF
int mtu;
gnrc_ipv6_netif_t *entry;
if (((mtu = atoi(mtu_str)) < IPV6_MIN_MTU) || (mtu > UINT16_MAX)) {
printf("error: MTU must be between %" PRIu16 " and %" PRIu16 "\n",
(uint16_t)IPV6_MIN_MTU, (uint16_t)UINT16_MAX);
return 1;
}
if ((entry = gnrc_ipv6_netif_get(dev)) == NULL) {
puts("error: unable to set MTU.");
return 1;
}
2015-11-04 09:15:10 +01:00
entry->mtu = mtu;
printf("success: set MTU %u interface %" PRIkernel_pid "\n", mtu,
dev);
return 0;
#else
(void)dev;
(void)mtu_str;
puts("error: unable to set MTU.");
return 1;
#endif
}
2015-03-11 22:54:52 +01:00
/* shell commands */
int _netif_send(int argc, char **argv)
{
kernel_pid_t dev;
2015-03-11 22:54:52 +01:00
uint8_t addr[MAX_ADDR_LEN];
size_t addr_len;
gnrc_pktsnip_t *pkt, *hdr;
gnrc_netif_hdr_t *nethdr;
uint8_t flags = 0x00;
2015-03-11 22:54:52 +01:00
if (argc < 4) {
printf("usage: %s <if> [<L2 addr>|bcast] <data>\n", argv[0]);
return 1;
}
2015-03-11 22:54:52 +01:00
/* parse interface */
dev = (kernel_pid_t)atoi(argv[1]);
2015-03-11 22:54:52 +01:00
if (!_is_iface(dev)) {
puts("error: invalid interface given");
return 1;
}
2015-03-11 22:54:52 +01:00
/* parse address */
addr_len = gnrc_netif_addr_from_str(addr, sizeof(addr), argv[2]);
2015-03-11 22:54:52 +01:00
if (addr_len == 0) {
if (strcmp(argv[2], "bcast") == 0) {
flags |= GNRC_NETIF_HDR_FLAGS_BROADCAST;
}
else {
puts("error: invalid address given");
return 1;
}
2015-03-11 22:54:52 +01:00
}
/* put packet together */
pkt = gnrc_pktbuf_add(NULL, argv[3], strlen(argv[3]), GNRC_NETTYPE_UNDEF);
if (pkt == NULL) {
puts("error: packet buffer full");
return 1;
}
hdr = gnrc_netif_hdr_build(NULL, 0, addr, addr_len);
if (hdr == NULL) {
puts("error: packet buffer full");
gnrc_pktbuf_release(pkt);
return 1;
}
LL_PREPEND(pkt, hdr);
nethdr = (gnrc_netif_hdr_t *)hdr->data;
nethdr->flags = flags;
2015-03-11 22:54:52 +01:00
/* and send it */
if (gnrc_netapi_send(dev, pkt) < 1) {
puts("error: unable to send");
gnrc_pktbuf_release(pkt);
return 1;
}
return 0;
2015-03-11 22:54:52 +01:00
}
int _netif_config(int argc, char **argv)
2015-03-11 22:54:52 +01:00
{
if (argc < 2) {
kernel_pid_t ifs[GNRC_NETIF_NUMOF];
size_t numof = gnrc_netif_get(ifs);
2015-03-11 22:54:52 +01:00
for (size_t i = 0; i < numof && i < GNRC_NETIF_NUMOF; i++) {
2015-03-11 22:54:52 +01:00
_netif_list(ifs[i]);
}
return 0;
}
2015-03-11 22:54:52 +01:00
else if (_is_number(argv[1])) {
kernel_pid_t dev = (kernel_pid_t)atoi(argv[1]);
if (_is_iface(dev)) {
if (argc < 3) {
_netif_list(dev);
return 0;
2015-03-11 22:54:52 +01:00
}
else if (strcmp(argv[2], "set") == 0) {
if (argc < 5) {
_set_usage(argv[0]);
return 1;
2015-03-11 22:54:52 +01:00
}
return _netif_set(argv[0], dev, argv[3], argv[4]);
2015-03-11 22:54:52 +01:00
}
else if (strcmp(argv[2], "add") == 0) {
if (argc < 4) {
_add_usage(argv[0]);
return 1;
}
2015-03-11 22:54:52 +01:00
return _netif_add(argv[0], (kernel_pid_t)dev, argc - 3, argv + 3);
}
else if (strcmp(argv[2], "del") == 0) {
if (argc < 4) {
_del_usage(argv[0]);
return 1;
}
return _netif_del((kernel_pid_t)dev, argv[3]);
}
else if (strcmp(argv[2], "mtu") == 0) {
if (argc < 4) {
_mtu_usage(argv[0]);
return 1;
}
return _netif_mtu((kernel_pid_t)dev, argv[3]);
}
#ifdef MODULE_NETSTATS
2016-02-11 22:39:34 +01:00
else if (strcmp(argv[2], "stats") == 0) {
uint8_t module;
bool reset = false;
/* check for requested module */
if ((argc == 3) || (strcmp(argv[3], "all") == 0)) {
module = NETSTATS_ALL;
}
else if (strcmp(argv[3], "l2") == 0) {
module = NETSTATS_LAYER2;
}
else if (strcmp(argv[3], "ipv6") == 0) {
module = NETSTATS_IPV6;
}
else {
printf("Module %s doesn't exist or does not provide statistics.\n", argv[3]);
return 0;
}
/* check if reset flag was given */
if ((argc > 4) && (strncmp(argv[4], "reset", 5) == 0)) {
reset = true;
}
if (module & NETSTATS_LAYER2) {
_netif_stats((kernel_pid_t) dev, NETSTATS_LAYER2, reset);
}
if (module & NETSTATS_IPV6) {
_netif_stats((kernel_pid_t) dev, NETSTATS_IPV6, reset);
}
return 1;
2016-02-11 22:39:34 +01:00
}
#endif
#ifdef MODULE_GNRC_IPV6_NETIF
else if (strcmp(argv[2], "hl") == 0) {
if (argc < 4) {
_hl_usage(argv[0]);
return 1;
}
int hl;
gnrc_ipv6_netif_t *entry;
if (((hl = atoi(argv[3])) < 0) || (hl > UINT8_MAX)) {
printf("error: Hop limit must be between %" PRIu16 " and %" PRIu16 "\n",
(uint16_t)0, (uint16_t)UINT16_MAX);
return 1;
}
if ((entry = gnrc_ipv6_netif_get(dev)) == NULL) {
puts("error: unable to set hop limit.");
return 1;
}
entry->cur_hl = hl;
printf("success: set hop limit %u interface %" PRIkernel_pid "\n", hl, dev);
return 0;
}
#endif
else {
return _netif_flag(argv[0], dev, argv[2]);
}
}
else {
2015-03-11 22:54:52 +01:00
puts("error: invalid interface given");
return 1;
}
}
printf("usage: %s [<if_id>]\n", argv[0]);
_set_usage(argv[0]);
_mtu_usage(argv[0]);
_hl_usage(argv[0]);
_flag_usage(argv[0]);
_add_usage(argv[0]);
_del_usage(argv[0]);
2016-02-11 22:39:34 +01:00
_stats_usage(argv[0]);
return 1;
}