
4 changed files with 630 additions and 3 deletions
@ -0,0 +1,613 @@
|
||||
/*
|
||||
* 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(""); |
||||
} |
Loading…
Reference in new issue