diff options
| author | HubretXie <[email protected]> | 2019-08-16 21:28:29 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2019-08-16 21:28:29 +0800 |
| commit | 9662e18c3688681cd95ebd65242773dbe7c1366b (patch) | |
| tree | eb5b5326efc603b359d8758ee6cd17eebfb1fa75 /components/net/netdev/src | |
| parent | 56a65431dc830d6234a8a3286fea35664a65aeb1 (diff) | |
| parent | 3b252d5b9721bb7cc649dad832507937efc1e96c (diff) | |
Merge pull request #7 from RT-Thread/master
sync
Diffstat (limited to 'components/net/netdev/src')
| -rw-r--r-- | components/net/netdev/src/netdev.c | 115 | ||||
| -rw-r--r-- | components/net/netdev/src/netdev_ipaddr.c | 357 |
2 files changed, 438 insertions, 34 deletions
diff --git a/components/net/netdev/src/netdev.c b/components/net/netdev/src/netdev.c index 5f49a46f17..451cc81025 100644 --- a/components/net/netdev/src/netdev.c +++ b/components/net/netdev/src/netdev.c @@ -58,9 +58,21 @@ int netdev_register(struct netdev *netdev, const char *name, void *user_data) ip_addr_set_zero(&(netdev->ip_addr)); ip_addr_set_zero(&(netdev->netmask)); ip_addr_set_zero(&(netdev->gw)); + + IP_SET_TYPE_VAL(netdev->ip_addr, IPADDR_TYPE_V4); + IP_SET_TYPE_VAL(netdev->netmask, IPADDR_TYPE_V4); + IP_SET_TYPE_VAL(netdev->gw, IPADDR_TYPE_V4); +#if NETDEV_IPV6 + for (index = 0; index < NETDEV_IPV6_NUM_ADDRESSES; index++) + { + ip_addr_set_zero(&(netdev->ip6_addr[index])); + IP_SET_TYPE_VAL(netdev->ip_addr, IPADDR_TYPE_V6); + } +#endif /* NETDEV_IPV6 */ for (index = 0; index < NETDEV_DNS_SERVERS_NUM; index++) { ip_addr_set_zero(&(netdev->dns_servers[index])); + IP_SET_TYPE_VAL(netdev->ip_addr, IPADDR_TYPE_V4); } netdev->status_callback = RT_NULL; netdev->addr_callback = RT_NULL; @@ -87,7 +99,7 @@ int netdev_register(struct netdev *netdev, const char *name, void *user_data) rt_hw_interrupt_enable(level); - return RT_EOK; + return RT_EOK; } /** @@ -106,7 +118,7 @@ int netdev_unregister(struct netdev *netdev) struct netdev *cur_netdev = RT_NULL; RT_ASSERT(netdev); - + if (netdev_list == RT_NULL) { return -RT_ERROR; @@ -117,18 +129,35 @@ int netdev_unregister(struct netdev *netdev) for (node = &(netdev_list->list); node; node = rt_slist_next(node)) { cur_netdev = rt_slist_entry(node, struct netdev, list); - if (cur_netdev && (rt_memcpy(cur_netdev, netdev, sizeof(struct netdev)) == 0)) + if (cur_netdev == netdev) { - rt_slist_remove(&(netdev_list->list), &(cur_netdev->list)); - rt_hw_interrupt_enable(level); - - return RT_EOK; + /* find this network interface device in network interface device list */ + if (netdev_list == netdev && rt_slist_next(&netdev_list->list) == RT_NULL) + { + netdev_list = RT_NULL; + } + else + { + rt_slist_remove(&(netdev_list->list), &(cur_netdev->list)); + } + if (netdev_default == netdev) + { + netdev_default = netdev_list; + } + break; } } - rt_hw_interrupt_enable(level); - /* not find this network interface device in network interface device list */ + if (cur_netdev == netdev) + { +#ifdef RT_USING_SAL + extern int sal_netdev_cleanup(struct netdev *netdev); + sal_netdev_cleanup(netdev); +#endif + rt_memset(netdev, 0, sizeof(*netdev)); + } + return -RT_ERROR; } @@ -666,6 +695,10 @@ void netdev_low_level_set_dns_server(struct netdev *netdev, uint8_t dns_num, con RT_ASSERT(dns_server); + if (netdev == RT_NULL) + { + return; + } /* check DNS servers is exist */ for (index = 0; index < NETDEV_DNS_SERVERS_NUM; index++) { @@ -675,7 +708,7 @@ void netdev_low_level_set_dns_server(struct netdev *netdev, uint8_t dns_num, con } } - if (netdev && dns_num < NETDEV_DNS_SERVERS_NUM) + if (dns_num < NETDEV_DNS_SERVERS_NUM) { ip_addr_copy(netdev->dns_servers[dns_num], *dns_server); @@ -809,7 +842,7 @@ void netdev_low_level_set_dhcp_status(struct netdev *netdev, rt_bool_t is_enable } } -#ifdef FINSH_USING_MSH +#ifdef RT_USING_FINSH #include <finsh.h> @@ -820,7 +853,6 @@ static void netdev_list_if(void) #define NETDEV_IFCONFIG_IEMI_MAX_LEN 8 rt_ubase_t index; - rt_base_t level; rt_slist_t *node = RT_NULL; struct netdev *netdev = RT_NULL; struct netdev *cur_netdev_list = netdev_list; @@ -831,15 +863,13 @@ static void netdev_list_if(void) return; } - level = rt_hw_interrupt_disable(); - for (node = &(cur_netdev_list->list); node; node = rt_slist_next(node)) { netdev = rt_list_entry(node, struct netdev, list); - rt_kprintf("network interface device: %s%s\n", - netdev->name, - (netdev == netdev_default)?" (Default)":""); + rt_kprintf("network interface device: %.*s%s\n", + RT_NAME_MAX, netdev->name, + (netdev == netdev_default) ? " (Default)" : ""); rt_kprintf("MTU: %d\n", netdev->mtu); /* 6 - MAC address, 8 - IEMI */ @@ -881,6 +911,28 @@ static void netdev_list_if(void) rt_kprintf("gw address: %s\n", inet_ntoa(netdev->gw)); rt_kprintf("net mask : %s\n", inet_ntoa(netdev->netmask)); +#if NETDEV_IPV6 + { + ip_addr_t *addr; + int i; + + addr = &netdev->ip6_addr[0]; + + if (!ip_addr_isany(addr)) + { + rt_kprintf("ipv6 link-local: %s %s\n", inet_ntoa(*addr), + !ip_addr_isany(addr) ? "VALID" : "INVALID"); + + for (i = 1; i < NETDEV_IPV6_NUM_ADDRESSES; i++) + { + addr = &netdev->ip6_addr[i]; + rt_kprintf("ipv6[%d] address: %s %s\n", i, inet_ntoa(*addr), + !ip_addr_isany(addr) ? "VALID" : "INVALID"); + } + } + } +#endif /* NETDEV_IPV6 */ + for (index = 0; index < NETDEV_DNS_SERVERS_NUM; index++) { rt_kprintf("dns server #%d: %s\n", index, inet_ntoa(netdev->dns_servers[index])); @@ -891,8 +943,6 @@ static void netdev_list_if(void) rt_kprintf("\n"); } } - - rt_hw_interrupt_enable(level); } static void netdev_set_if(char* netdev_name, char* ip_addr, char* gw_addr, char* nm_addr) @@ -951,7 +1001,7 @@ FINSH_FUNCTION_EXPORT_ALIAS(netdev_ifconfig, __cmd_ifconfig, list the informatio #endif /* NETDEV_USING_IFCONFIG */ #ifdef NETDEV_USING_PING -static int netdev_cmd_ping(char* target_name, rt_uint32_t times, rt_size_t size) +int netdev_cmd_ping(char* target_name, rt_uint32_t times, rt_size_t size) { #define NETDEV_PING_DATA_SIZE 32 /** ping receive timeout - in milliseconds */ @@ -1041,19 +1091,16 @@ FINSH_FUNCTION_EXPORT_ALIAS(netdev_ping, __cmd_ping, ping network host); static void netdev_list_dns(void) { - rt_base_t level; int index = 0; struct netdev *netdev = RT_NULL; rt_slist_t *node = RT_NULL; - level = rt_hw_interrupt_disable(); - for (node = &(netdev_list->list); node; node = rt_slist_next(node)) { netdev = rt_list_entry(node, struct netdev, list); - rt_kprintf("network interface device: %s%s\n", - netdev->name, + rt_kprintf("network interface device: %.*s%s\n", + RT_NAME_MAX, netdev->name, (netdev == netdev_default)?" (Default)":""); for(index = 0; index < NETDEV_DNS_SERVERS_NUM; index++) @@ -1066,8 +1113,6 @@ static void netdev_list_dns(void) rt_kprintf("\n"); } } - - rt_hw_interrupt_enable(level); } static void netdev_set_dns(char *netdev_name, uint8_t dns_num, char *dns_server) @@ -1115,7 +1160,6 @@ FINSH_FUNCTION_EXPORT_ALIAS(netdev_dns, __cmd_dns, list and set the information #ifdef NETDEV_USING_NETSTAT static void netdev_cmd_netstat(void) { - rt_base_t level; rt_slist_t *node = RT_NULL; struct netdev *netdev = RT_NULL; struct netdev *cur_netdev_list = netdev_list; @@ -1126,8 +1170,6 @@ static void netdev_cmd_netstat(void) return; } - level = rt_hw_interrupt_disable(); - for (node = &(cur_netdev_list->list); node; node = rt_slist_next(node)) { netdev = rt_list_entry(node, struct netdev, list); @@ -1138,9 +1180,14 @@ static void netdev_cmd_netstat(void) } } - rt_hw_interrupt_enable(level); - - netdev->ops->netstat(netdev); + if (netdev->ops->netstat != RT_NULL) + { + netdev->ops->netstat(netdev); + } + else + { + rt_kprintf("netstat: this command is not supported!\n"); + } } int netdev_netstat(int argc, char **argv) @@ -1159,4 +1206,4 @@ int netdev_netstat(int argc, char **argv) FINSH_FUNCTION_EXPORT_ALIAS(netdev_netstat, __cmd_netstat, list the information of TCP / IP); #endif /* NETDEV_USING_NETSTAT */ -#endif /* FINSH_USING_MSH */ +#endif /* RT_USING_FINSH */ diff --git a/components/net/netdev/src/netdev_ipaddr.c b/components/net/netdev/src/netdev_ipaddr.c index 988bd50eb7..8d83937da9 100644 --- a/components/net/netdev/src/netdev_ipaddr.c +++ b/components/net/netdev/src/netdev_ipaddr.c @@ -19,8 +19,10 @@ #define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) #define islower(c) in_range(c, 'a', 'z') #define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') +#define xchar(i) ((i) < 10 ? '0' + (i) : 'A' + (i) - 10) #endif +#if NETDEV_IPV4 /** * Check whether "cp" is a valid ascii representation @@ -255,3 +257,358 @@ in_addr_t netdev_ipaddr_addr(const char *cp) } return (IPADDR_NONE); } + +#endif /* NETDEV_IPV4 */ + + +#if NETDEV_IPV6 + +RT_WEAK const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; + +/** + * Check whether "cp" is a valid ascii representation + * of an IPv6 address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * + * @param cp IPv6 address in ascii representation (e.g. "FF01::1") + * @param addr pointer to which to save the ip address in network order + * @return 1 if cp could be converted to addr, 0 on failure + */ +int +netdev_ip6addr_aton(const char *cp, ip6_addr_t *addr) +{ + uint32_t addr_index, zero_blocks, current_block_index, current_block_value; + const char *s; + + /* Count the number of colons, to count the number of blocks in a "::" sequence + zero_blocks may be 1 even if there are no :: sequences */ + zero_blocks = 8; + for (s = cp; *s != 0; s++) + { + if (*s == ':') + { + zero_blocks--; + } + else if (!isxdigit(*s)) + { + break; + } + } + + /* parse each block */ + addr_index = 0; + current_block_index = 0; + current_block_value = 0; + for (s = cp; *s != 0; s++) + { + if (*s == ':') + { + if (addr) + { + if (current_block_index & 0x1) + { + addr->addr[addr_index++] |= current_block_value; + } + else + { + addr->addr[addr_index] = current_block_value << 16; + } + } + current_block_index++; + current_block_value = 0; + if (current_block_index > 7) + { + /* address too long! */ + return 0; + } + if (s[1] == ':') + { + if (s[2] == ':') + { + /* invalid format: three successive colons */ + return 0; + } + s++; + /* "::" found, set zeros */ + while (zero_blocks > 0) + { + zero_blocks--; + if (current_block_index & 0x1) + { + addr_index++; + } + else + { + if (addr) + { + addr->addr[addr_index] = 0; + } + } + current_block_index++; + if (current_block_index > 7) + { + /* address too long! */ + return 0; + } + } + } + } + else if (isxdigit(*s)) + { + /* add current digit */ + current_block_value = (current_block_value << 4) + + (isdigit(*s) ? (uint32_t)(*s - '0') : (uint32_t)(10 + (islower(*s) ? *s - 'a' : *s - 'A'))); + } + else + { + /* unexpected digit, space? CRLF? */ + break; + } + } + + if (addr) + { + if (current_block_index & 0x1) + { + addr->addr[addr_index++] |= current_block_value; + } + else + { + addr->addr[addr_index] = current_block_value << 16; + } + } + + /* convert to network byte order. */ + if (addr) + { + for (addr_index = 0; addr_index < 4; addr_index++) + { + addr->addr[addr_index] = htonl(addr->addr[addr_index]); + } + } + + if (current_block_index != 7) + { + return 0; + } + + return 1; +} + +/** + * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used. + * + * @param addr ip6 address in network order to convert + * @param buf target buffer where the string is stored + * @param buflen length of buf + * @return either pointer to buf which now holds the ASCII + * representation of addr or NULL if buf was too small + */ +char * +netdev_ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen) +{ + uint32_t current_block_index, current_block_value, next_block_value; + int32_t i; + uint8_t zero_flag, empty_block_flag; + + i = 0; + empty_block_flag = 0; /* used to indicate a zero chain for "::' */ + + for (current_block_index = 0; current_block_index < 8; current_block_index++) + { + /* get the current 16-bit block */ + current_block_value = htonl(addr->addr[current_block_index >> 1]); + if ((current_block_index & 0x1) == 0) + { + current_block_value = current_block_value >> 16; + } + current_block_value &= 0xffff; + + /* Check for empty block. */ + if (current_block_value == 0) + { + if (current_block_index == 7 && empty_block_flag == 1) + { + /* special case, we must render a ':' for the last block. */ + buf[i++] = ':'; + if (i >= buflen) + { + return NULL; + } + break; + } + if (empty_block_flag == 0) + { + /* generate empty block "::", but only if more than one contiguous zero block, + * according to current formatting suggestions RFC 5952. */ + next_block_value = htonl(addr->addr[(current_block_index + 1) >> 1]); + if ((current_block_index & 0x1) == 0x01) + { + next_block_value = next_block_value >> 16; + } + next_block_value &= 0xffff; + if (next_block_value == 0) + { + empty_block_flag = 1; + buf[i++] = ':'; + if (i >= buflen) + { + return NULL; + } + continue; /* move on to next block. */ + } + } + else if (empty_block_flag == 1) + { + /* move on to next block. */ + continue; + } + } + else if (empty_block_flag == 1) + { + /* Set this flag value so we don't produce multiple empty blocks. */ + empty_block_flag = 2; + } + + if (current_block_index > 0) + { + buf[i++] = ':'; + if (i >= buflen) + { + return NULL; + } + } + + if ((current_block_value & 0xf000) == 0) + { + zero_flag = 1; + } + else + { + buf[i++] = xchar(((current_block_value & 0xf000) >> 12)); + zero_flag = 0; + if (i >= buflen) + { + return NULL; + } + } + + if (((current_block_value & 0xf00) == 0) && (zero_flag)) + { + /* do nothing */ + } + else + { + buf[i++] = xchar(((current_block_value & 0xf00) >> 8)); + zero_flag = 0; + if (i >= buflen) + { + return NULL; + } + } + + if (((current_block_value & 0xf0) == 0) && (zero_flag)) + { + /* do nothing */ + } + else + { + buf[i++] = xchar(((current_block_value & 0xf0) >> 4)); + zero_flag = 0; + if (i >= buflen) + { + return NULL; + } + } + + buf[i++] = xchar((current_block_value & 0xf)); + if (i >= buflen) + { + return NULL; + } + } + + buf[i] = 0; + + return buf; +} + +/** + * Convert numeric IPv6 address into ASCII representation. + * returns ptr to static buffer; not reentrant! + * + * @param addr ip6 address in network order to convert + * @return pointer to a global static (!) buffer that holds the ASCII + * representation of addr + */ +char * +netdev_ip6addr_ntoa(const ip6_addr_t *addr) +{ + static char str[40]; + return netdev_ip6addr_ntoa_r(addr, str, 40); +} + +#endif /* NETDEV_IPV6 */ + +const char * +netdev_inet_ntop(int af, const void *src, char *dst, int32_t size) +{ +#define AF_INET 2 +#define AF_INET6 10 + + const char *ret = NULL; + int size_int = (int)size; + if (size_int < 0) + { + return NULL; + } + switch (af) + { +#if NTEDEV_IPV4 + case AF_INET: + return netdev_ip4addr_ntoa_r((const ip4_addr_t *)src, dst, size_int); +#endif +#if NETDEV_IPV6 + case AF_INET6: + return netdev_ip6addr_ntoa_r((const ip6_addr_t *)src, dst, size_int); +#endif + default: + break; + } + return ret; +} + +int +netdev_inet_pton(int af, const char *src, void *dst) +{ +#define AF_INET 2 +#define AF_INET6 10 + + int err; + switch (af) + { +#if NETDEV_IPV4 + case AF_INET: + err = netdev_ip4addr_aton(src, (ip4_addr_t *)dst); + break; +#endif +#if NETDEV_IPV6 + case AF_INET6: + { + /* convert into temporary variable since ip6_addr_t might be larger + than in6_addr when scopes are enabled */ + ip6_addr_t addr; + err = netdev_ip6addr_aton(src, &addr); + if (err) + { + rt_memcpy(dst, &addr.addr, sizeof(addr.addr)); + } + break; + } +#endif + default: + err = -1; + break; + } + return err; +} |
