Skip to content

Commit

Permalink
Merge pull request #584 from espressif-abhikroy/component/console_cmd…
Browse files Browse the repository at this point in the history
…_ping

feat(console): Added command getaddrinfo, set/get dnsserver to console_cmd_ping
  • Loading branch information
espressif-abhikroy authored Aug 15, 2024
2 parents 5964ead + c41e889 commit f198967
Show file tree
Hide file tree
Showing 10 changed files with 597 additions and 12 deletions.
2 changes: 1 addition & 1 deletion components/console_cmd_ping/.cz.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ commitizen:
bump_message: 'bump(console): $current_version -> $new_version'
pre_bump_hooks: python ../../ci/changelog.py console_cmd_ping
tag_format: console_cmd_ping-v$version
version: 1.0.0
version: 1.1.0
version_files:
- idf_component.yml
6 changes: 6 additions & 0 deletions components/console_cmd_ping/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## [1.1.0](https://github.com/espressif/esp-protocols/commits/console_cmd_ping-v1.1.0)

### Features

- Added command getaddrinfo, set/get dnsserver to console_cmd_ping ([b80c19d7](https://github.com/espressif/esp-protocols/commit/b80c19d7))

## [1.0.0](https://github.com/espressif/esp-protocols/commits/console_cmd_ping-v1.0.0)

### Features
Expand Down
12 changes: 9 additions & 3 deletions components/console_cmd_ping/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
idf_component_register(SRCS "console_ping.c"
idf_component_register(SRCS "console_ping.c" "console_getaddrinfo.c" "console_getsetdnsserver.c"
INCLUDE_DIRS "."
PRIV_REQUIRES esp_netif console
WHOLE_ARCHIVE)
PRIV_REQUIRES esp_netif console)

if(CONFIG_PING_CMD_AUTO_REGISTRATION)
target_link_libraries(${COMPONENT_LIB} "-u console_cmd_ping_register")
target_link_libraries(${COMPONENT_LIB} "-u console_cmd_getaddrinfo_register")
target_link_libraries(${COMPONENT_LIB} "-u console_cmd_setdnsserver_register")
target_link_libraries(${COMPONENT_LIB} "-u console_cmd_getdnsserver_register")
endif()
9 changes: 9 additions & 0 deletions components/console_cmd_ping/Kconfig.projbuild
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
menu "Ping command Configuration"

config PING_CMD_AUTO_REGISTRATION
bool "Enable Console command ping/dns Auto-registration"
default y
help
Enabling this allows for the autoregistration of the ping and dns commands.

endmenu
79 changes: 76 additions & 3 deletions components/console_cmd_ping/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Console command ping
The component provides a console where the 'ping' command can be executed.
# Console command ping and DNS server configuration
The component provides a console where the 'ping' command, 'getaddrinfo', and DNS server configuration commands can be executed.

## API

Expand Down Expand Up @@ -27,15 +27,20 @@ The component provides a console where the 'ping' command can be executed.
// Register all plugin command added to your project
ESP_ERROR_CHECK(console_cmd_all_register());

// To register only ifconfig command skip calling console_cmd_all_register()
// To register only ping/dns command skip calling console_cmd_all_register()
ESP_ERROR_CHECK(console_cmd_ping_register());
ESP_ERROR_CHECK(console_cmd_getaddrinfo_register());
ESP_ERROR_CHECK(console_cmd_setdnsserver_register());
ESP_ERROR_CHECK(console_cmd_getdnsserver_register());

ESP_ERROR_CHECK(console_cmd_start()); // Start console
```

### Adding a plugin command or component:
To add a plugin command or any component from IDF component manager into your project, simply include an entry within the `idf_component.yml` file.

Note: **Auto-registration** of a specific plugin command can be disabled from menuconfig.

For more details refer [IDF Component Manager](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-component-manager.html)


Expand All @@ -52,4 +57,72 @@ ping [-W <t>] [-i <t>] [-s <n>] [-c <n>] [-Q <n>] [-T <n>] <host>
-Q, --tos=<n> Set Type of Service related bits in IP datagrams
-T, --ttl=<n> Set Time to Live related bits in IP datagrams
<host> Host address
getaddrinfo [-f <AF>] [-F <FLAGS>]... [-p <port>] <hostname>
Usage: getaddrinfo [options] <hostname> [service]
-f, --family=<AF> Address family (AF_INET, AF_INET6, AF_UNSPEC).
-F, --flags=<FLAGS> Special flags (AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST, AI_V4MAPPED, AI_ALL).
-p, --port=<port> String containing a numeric port number.
<hostname> Host address
setdnsserver <main> [backup] [fallback]
Usage: setdnsserver <main> [backup] [fallback]
<main> The main DNS server IP address.
backup The secondary DNS server IP address (optional).
fallback The fallback DNS server IP address (optional).
getdnsserver
Usage: getdnsserver
```
These commands allow you to configure and retrieve DNS server settings on your ESP32 device, in addition to the existing ping functionality.

## Usage
### Using the setdnsserver command:
1. To set the main DNS server:
```
setdnsserver 8.8.8.8
```

2. To set the main and backup DNS servers:

```
setdnsserver 8.8.8.8 fe80::b0be:83ff:fe77:dd64
```

3. To set the main, backup, and fallback DNS servers:

```
setdnsserver 8.8.8.8 fe80::b0be:83ff:fe77:dd64 www.xyz.com
```

### Using the getdnsserver command:
To get the current DNS server settings:
```
getdnsserver
```

### Using the getaddrinfo command:
1. To get address information for a hostname:

```
getaddrinfo www.example.com
```

2. To specify additional options:

```
getaddrinfo -f AF_INET -F AI_PASSIVE www.example.com
```

### Using the ping command:
1. To ping a host:

```
ping www.example.com
```

2. To specify additional options, such as timeout, interval, packet size, etc.:

```
ping -W 5 -i 1 -s 64 -c 4 -Q 0x10 -T 64 www.example.com
```
180 changes: 180 additions & 0 deletions components/console_cmd_ping/console_getaddrinfo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <string.h>
#include "sdkconfig.h"
#include "lwip/inet.h"
#include "lwip/netdb.h"
#include "lwip/sockets.h"
#include "esp_console.h"
#include "esp_log.h"
#include "argtable3/argtable3.h"
#include <netdb.h>
#include "console_ping.h"


static const char *TAG = "console_getaddrinfo";

#if CONFIG_PING_CMD_AUTO_REGISTRATION
/**
* @brief Static registration of the getaddrinfo command plugin.
*
* This section registers the plugin description structure and places it into
* the .console_cmd_desc section, as determined by the linker.lf file in the
* 'plugins' component.
*/
static const console_cmd_plugin_desc_t __attribute__((section(".console_cmd_desc"), used)) PLUGIN = {
.name = "console_cmd_getddrinfo",
.plugin_regd_fn = &console_cmd_getaddrinfo_register
};
#endif

/**
* @brief Structure to hold arguments for the getaddrinfo command.
*/
static struct {
struct arg_str *family;
struct arg_str *flags;
struct arg_str *port_nr;
struct arg_str *hostname;
struct arg_end *end;
} getddrinfo_args;

/**
* @brief Executes the getaddrinfo command.
*
* This function parses arguments, sets hints for address resolution, and calls
* getaddrinfo to resolve the hostname. It then prints the resolved IP addresses
* and associated information.
*
* @param argc Argument count
* @param argv Argument vector
*
* @return int Returns 0 on success, 1 on error.
*/
static int do_getddrinfo_cmd(int argc, char **argv)
{
char ip_str[INET6_ADDRSTRLEN];
struct addrinfo hint = {0};
struct addrinfo *res = NULL, *res_tmp = NULL;
const char *port_nr_str = NULL;
int ret = 0;

int nerrors = arg_parse(argc, argv, (void **)&getddrinfo_args);
if (nerrors != 0) {
arg_print_errors(stderr, getddrinfo_args.end, argv[0]);
return 1;
}

/* Set the address family */
if (getddrinfo_args.family->count > 0) {
if (strcmp(getddrinfo_args.family->sval[0], "AF_INET") == 0) {
hint.ai_family = AF_INET;
} else if (strcmp(getddrinfo_args.family->sval[0], "AF_INET6") == 0) {
hint.ai_family = AF_INET6;
} else if (strcmp(getddrinfo_args.family->sval[0], "AF_UNSPEC") == 0) {
hint.ai_family = AF_UNSPEC;
} else {
ESP_LOGE(TAG, "Unknown family");
return 1;
}
}

/* Set the flags */
if (getddrinfo_args.flags->count > 0) {
for (int i = 0; i < getddrinfo_args.flags->count; i++) {
if (strcmp(getddrinfo_args.flags->sval[i], "AI_PASSIVE") == 0) {
hint.ai_flags |= AI_PASSIVE;
} else if (strcmp(getddrinfo_args.flags->sval[i], "AI_CANONNAME") == 0) {
hint.ai_flags |= AI_CANONNAME;
} else if (strcmp(getddrinfo_args.flags->sval[i], "AI_NUMERICHOST") == 0) {
hint.ai_flags |= AI_NUMERICHOST;
} else if (strcmp(getddrinfo_args.flags->sval[i], "AI_V4MAPPED") == 0) {
hint.ai_flags |= AI_V4MAPPED;
} else if (strcmp(getddrinfo_args.flags->sval[i], "AI_ALL") == 0) {
hint.ai_flags |= AI_ALL;
} else {
ESP_LOGE(TAG, "Unknown flag: %s", getddrinfo_args.flags->sval[i]);
return 1;
}
}
}

if (getddrinfo_args.port_nr->count > 0) {
port_nr_str = getddrinfo_args.port_nr->sval[0];
}

/* Convert hostname to IP address */
if (!strcmp(getddrinfo_args.hostname->sval[0], "NULL")) {
ret = getaddrinfo(NULL, port_nr_str, &hint, &res);
} else {
ret = getaddrinfo(getddrinfo_args.hostname->sval[0], port_nr_str, &hint, &res);
}

if (ret != 0) {
printf("getddrinfo: Failure host:%s(ERROR: %d)\n", getddrinfo_args.hostname->sval[0], ret);
ESP_LOGE(TAG, "Failure host");
return 1;
}

/* Iterate through the results from getaddrinfo */
for (res_tmp = res; res_tmp != NULL; res_tmp = res_tmp->ai_next) {

if (res_tmp->ai_family == AF_INET) {
inet_ntop(AF_INET, &((struct sockaddr_in *)res_tmp->ai_addr)->sin_addr, ip_str, INET_ADDRSTRLEN);
printf("\tIP Address: %s\n", ip_str);
printf("\tAddress Family: AF_INET\n");
} else if (res_tmp->ai_family == AF_INET6) {
inet_ntop(AF_INET6, &((struct sockaddr_in6 *)res_tmp->ai_addr)->sin6_addr, ip_str, INET6_ADDRSTRLEN);
printf("\tIP Address: %s\n", ip_str);
printf("\tAddress Family: AF_INET6\n");
} else {
ESP_LOGE(TAG, "ai_family Unknown: %d\n", res_tmp->ai_family);
}

/* Print the protocol used */
printf("\tProtocol: %d\n", res_tmp->ai_protocol);

/* Print the canonical name if available */
if (res_tmp->ai_canonname) {
printf("\tCanonical Name: %s\n", res_tmp->ai_canonname);
}
}

freeaddrinfo(res);

return 0;
}

/**
* @brief Registers the getaddrinfo command.
*
* @return esp_err_t Returns ESP_OK on success, or an error code on failure.
*/
esp_err_t console_cmd_getaddrinfo_register(void)
{
esp_err_t ret;

getddrinfo_args.family = arg_str0("f", "family", "<AF>", "Address family (AF_INET, AF_INET6, AF_UNSPEC).");
getddrinfo_args.flags = arg_strn("F", "flags", "<FLAGS>", 0, 5, "Special flags (AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST, AI_V4MAPPED, AI_ALL).");
getddrinfo_args.port_nr = arg_str0("p", "port", "<port>", "String containing a numeric port number.");
getddrinfo_args.hostname = arg_str1(NULL, NULL, "<hostname>", "Host address");
getddrinfo_args.end = arg_end(1);
const esp_console_cmd_t getddrinfo_cmd = {
.command = "getaddrinfo",
.help = "Usage: getaddrinfo [options] <hostname> [service]",
.hint = NULL,
.func = &do_getddrinfo_cmd,
.argtable = &getddrinfo_args
};

ret = esp_console_cmd_register(&getddrinfo_cmd);
if (ret) {
ESP_LOGE(TAG, "Unable to register getddrinfo");
}

return ret;
}
Loading

0 comments on commit f198967

Please sign in to comment.