aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoic Poulain <loic.poulain@linaro.org>2020-11-10 15:32:24 +0100
committerLoic Poulain <loic.poulain@linaro.org>2020-11-10 15:32:24 +0100
commit0995aa02e1a6c3ffb335c9bac6f2bb9be9599479 (patch)
tree3daa689991b854f1ebcfd2765d97880a2455a9bb
parent88fe7e3cc99438c1760f3e0f2da061fdaab4a924 (diff)
Add builtin DNS config support
Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
-rw-r--r--42-mhi.rules6
-rw-r--r--mhi-qmi-connect.c145
-rw-r--r--mhi-qmi-connect.conf2
3 files changed, 107 insertions, 46 deletions
diff --git a/42-mhi.rules b/42-mhi.rules
index 0807756..e58de03 100644
--- a/42-mhi.rules
+++ b/42-mhi.rules
@@ -1,6 +1,3 @@
-# TODO build tool path
-#ACTION=="add", SUBSYSTEM=="mhi_uci", KERNEL=="mhi_0000:02:00.0_QMI", RUN+="/bin/mhi-qmi-connect --udev"
-
# There are two paths for submitting QMI commands, the legacy path using MHI UCI /dev/mhi_xxx_QMI
# and QRTR path. Today, QMI over QRTR is recommended because it's bus agnostic and can be
# used in embedded or PCIe case. (QRTR over smem, QRTR over MHI....).
@@ -8,6 +5,7 @@
# data path to PCIe endpoint. This dummy rule is only here to keep the QMI channel open and let
# the modem know that we want to use PCIe.
-# QCOM SDX55 PCIe MHI QMI
+# QCOM SDX55 PCIe MHI QMI device (Legacy)
ACTION=="add", SUBSYSTEM=="mhi_uci", ATTRS{vendor}=="0x17cb", ATTRS{device}=="0x0306", KERNEL=="mhi*QMI", RUN+="/bin/cat $env{DEVNAME}"
+#ACTION=="add", SUBSYSTEM=="mhi_uci", ATTRS{vendor}=="0x17cb", ATTRS{device}=="0x0306", KERNEL=="mhi*QMI", RUN+="/bin/mhi-qmi-connect --udev --kmsg"
diff --git a/mhi-qmi-connect.c b/mhi-qmi-connect.c
index fc0f8f1..bb968cf 100644
--- a/mhi-qmi-connect.c
+++ b/mhi-qmi-connect.c
@@ -15,6 +15,8 @@
#define MUX_ID 1
#define WWAN_IFACE "mhi_hwip0"
+#define MHI_CONFIG_DEFAULT "/etc/mhi-qmi-connect.conf"
+
static GMainLoop *loop;
static GCancellable *cancellable;
@@ -38,6 +40,7 @@ static gboolean set_ip;
static guint32 mux_id = 1;
static gchar *qmi_dev;
static gboolean udev;
+static gboolean kmsg;
static gchar *config;
static gchar ip4_addr[INET_ADDRSTRLEN];
@@ -86,14 +89,20 @@ static void stop_rmnet(void)
{
GError *error = NULL;
gchar cmdline[1000] = {0};
+ gchar *iptool = "ip";
+ gchar *iptool_alt = "/sbin/ip";
if (!rmnet_setup_done)
return;
- g_print("[%s] stopping rmnet\n", qmi_device_get_path_display(device));
+ g_print("[%s] [RMNET] stopping rmnet\n", qmi_device_get_path_display(device));
+
+ /* TODO: proper solution */
+ if (udev)
+ iptool = iptool_alt;
/* Set RMNET interface down */
- g_snprintf(cmdline, sizeof(cmdline), "ip link set rmnet_data%u down", mux_id);
+ g_snprintf(cmdline, sizeof(cmdline), "%s link set rmnet_data%u down", iptool, mux_id);
if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &error)) {
g_printerr("%s: %s\n", cmdline, error->message);
g_error_free(error);
@@ -101,7 +110,7 @@ static void stop_rmnet(void)
}
/* Set WWAN interface down */
- g_snprintf(cmdline, sizeof(cmdline), "ip link set %s down", WWAN_IFACE);
+ g_snprintf(cmdline, sizeof(cmdline), "%s link set %s down", iptool, WWAN_IFACE);
if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &error)) {
g_printerr("%s: %s\n", cmdline, error->message);
g_error_free(error);
@@ -109,7 +118,7 @@ static void stop_rmnet(void)
}
/* del RMNET interface */
- g_snprintf(cmdline, sizeof(cmdline), "ip link delete rmnet_data%u", mux_id);
+ g_snprintf(cmdline, sizeof(cmdline), "%s link delete rmnet_data%u", iptool, mux_id);
if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &error)) {
g_printerr("%s: %s\n", cmdline, error->message);
g_error_free(error);
@@ -119,7 +128,7 @@ static void stop_rmnet(void)
if (!default_route)
return;
- g_snprintf(cmdline, sizeof(cmdline), "ip route del default");
+ g_snprintf(cmdline, sizeof(cmdline), "%s route del default",iptool);
if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &error)) {
g_printerr("%s: %s\n", cmdline, error->message);
g_error_free(error);
@@ -151,7 +160,7 @@ static void stop_network_ready(QmiClientWds *client, GAsyncResult *res)
}
qmi_message_wds_stop_network_output_unref(output);
- g_print("[%s] Network stopped\n", qmi_device_get_path_display(device));
+ g_print("[%s] [WDS] Network stopped\n", qmi_device_get_path_display(device));
/* TODO ? reconnect automatically ? */
exit(EXIT_SUCCESS);
@@ -199,14 +208,14 @@ static void get_packet_service_status_ready(QmiClientWds *client, GAsyncResult *
qmi_message_wds_get_packet_service_status_output_unref(output);
if (connection_status != QMI_WDS_CONNECTION_STATUS_CONNECTED) {
- g_print("[%s] Connection status: '%s'\n", qmi_device_get_path_display(device),
+ g_print("[%s] [WDS] Connection status: '%s'\n", qmi_device_get_path_display(device),
qmi_wds_connection_status_get_string(connection_status));
op_shutdown(SHUTDOWN_DISCONNECTED);
return;
}
if (!ping) {
- g_print("\r[%s] Connected!\n", qmi_device_get_path_display(device));
+ g_print("\r[%s] [WDS] Connected!\n", qmi_device_get_path_display(device));
ping = !ping;
}
}
@@ -224,16 +233,55 @@ static gboolean start_network_status(gpointer user_data)
}
/* 14 - Configure interfaces TODO: move that part out of this tool */
+static void setup_dns(void)
+{
+ gchar content[1000] = {0};
+ GError *error = NULL;
+
+ if (ip4_dns[0] == 0) {
+ g_print("[%s] [DNS] no DNS found from bearer\n", qmi_device_get_path_display(device));
+ return;
+ }
+
+ GFile *mhi_resolv_file = g_file_new_for_path("/run/mhi-qmi-resolv.conf");
+ GFile *resolv_file = g_file_new_for_path("/etc/resolv.conf");
+
+ g_snprintf(content, sizeof(content), "nameserver %s\n", ip4_dns);
+ g_file_replace_contents(mhi_resolv_file, content, strlen(content), NULL, FALSE, 0, NULL, cancellable, &error);
+ g_object_unref(mhi_resolv_file);
+
+ if (g_file_query_exists(resolv_file, cancellable))
+ g_file_delete(resolv_file, NULL, NULL);
+
+ if (!g_file_make_symbolic_link(resolv_file, "/run/mhi-qmi-resolv.conf", cancellable, &error)) {
+ g_printerr("Error creating /etc/resolv.conf symlink: %s\n", error->message);
+ g_error_free(error);
+ g_object_unref(resolv_file);
+ op_shutdown(SHUTDOWN_ERROR);
+ return;
+ }
+
+ g_print("[%s] [DNS] Created /etc/resolv.conf symlink\n", qmi_device_get_path_display(device));
+
+ g_object_unref(resolv_file);
+
+}
+
static void setup_rmnet(void)
{
GError *error = NULL;
gchar cmdline[1000] = {0};
+ gchar *iptool = "ip";
+ gchar *iptool_alt = "/sbin/ip";
- /* Clean-up */
- g_print("[%s] starting rmnet\n", qmi_device_get_path_display(device));
+ /* TODO: proper solution */
+ if (udev)
+ iptool = iptool_alt;
+
+ g_print("[%s] [RMNET] starting rmnet using: %s\n", qmi_device_get_path_display(device), iptool);
/* Set wwan MTU */
- g_snprintf(cmdline, sizeof(cmdline), "ip link set %s mtu %u", WWAN_IFACE,
+ g_snprintf(cmdline, sizeof(cmdline), "%s link set %s mtu %u", iptool, WWAN_IFACE,
MAX_QMAP_DATAGRAM_SIZE);
if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &error)) {
g_printerr("%s: %s\n", cmdline, error->message);
@@ -243,35 +291,33 @@ static void setup_rmnet(void)
}
/* Add link */
- g_snprintf(cmdline, sizeof(cmdline), "ip link add link %s name rmnet_data%u type rmnet mux_id %u",
- WWAN_IFACE, mux_id, mux_id);
+ g_snprintf(cmdline, sizeof(cmdline), "%s link add link %s name rmnet_data%u type rmnet mux_id %u",
+ iptool, WWAN_IFACE, mux_id, mux_id);
if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &error)) {
g_printerr("%s: %s\n", cmdline, error->message);
g_error_free(error);
op_shutdown(SHUTDOWN_ERROR);
return;
}
- g_print("[%s] <rmnet_data%u> interface created\n", qmi_device_get_path_display(device), mux_id);
+ g_print("[%s] [RMNET] <rmnet_data%u> interface created\n", qmi_device_get_path_display(device), mux_id);
if (set_ip) {
- g_print("[%s] starting rmnet\n", qmi_device_get_path_display(device));
-
/* Set RMNET IP address */
- g_snprintf(cmdline, sizeof(cmdline), "ip addr add %s/27 dev rmnet_data%u",
- ip4_addr, mux_id);
+ g_snprintf(cmdline, sizeof(cmdline), "%s addr add %s/27 dev rmnet_data%u",
+ iptool, ip4_addr, mux_id);
if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &error)) {
g_printerr("%s: %s\n", cmdline, error->message);
g_error_free(error);
op_shutdown(SHUTDOWN_ERROR);
return;
}
- g_print("[%s] <rmnet_data%u> interface IP is %s\n",
+ g_print("[%s] [RMNET] <rmnet_data%u> address set to %s\n",
qmi_device_get_path_display(device), mux_id, ip4_addr);
}
/* Set RMNET MTU */
- g_snprintf(cmdline, sizeof(cmdline), "ip link set rmnet_data%u mtu %u",
- mux_id, MAX_QMAP_DATAGRAM_SIZE);
+ g_snprintf(cmdline, sizeof(cmdline), "%s link set rmnet_data%u mtu %u",
+ iptool, mux_id, MAX_QMAP_DATAGRAM_SIZE);
if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &error)) {
g_printerr("%s: %s\n", cmdline, error->message);
g_error_free(error);
@@ -280,7 +326,7 @@ static void setup_rmnet(void)
}
/* Set WWAN interface up */
- g_snprintf(cmdline, sizeof(cmdline), "ip link set %s up", WWAN_IFACE);
+ g_snprintf(cmdline, sizeof(cmdline), "%s link set %s up", iptool, WWAN_IFACE);
if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &error)) {
g_printerr("%s: %s\n", cmdline, error->message);
g_error_free(error);
@@ -289,7 +335,7 @@ static void setup_rmnet(void)
}
/* Set RMNET interface up */
- g_snprintf(cmdline, sizeof(cmdline), "ip link set rmnet_data%u up", mux_id);
+ g_snprintf(cmdline, sizeof(cmdline), "%s link set rmnet_data%u up", iptool, mux_id);
if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &error)) {
g_printerr("%s: %s\n", cmdline, error->message);
g_error_free(error);
@@ -299,11 +345,14 @@ static void setup_rmnet(void)
rmnet_setup_done = TRUE;
- if (!default_route || !set_ip)
+ if (!default_route)
return;
+ g_print("[%s] [RMNET] <rmnet_data%u> as default route\n",
+ qmi_device_get_path_display(device), mux_id);
+
/* Save routing */
- g_snprintf(cmdline, sizeof(cmdline), "ip route save");
+ g_snprintf(cmdline, sizeof(cmdline), "%s route save", iptool);
if (!g_spawn_command_line_sync(cmdline, &ip_route_dump, NULL, NULL, &error)) {
g_printerr("%s: %s\n", cmdline, error->message);
g_error_free(error);
@@ -312,7 +361,7 @@ static void setup_rmnet(void)
}
/* Set RMNET as default route */
- g_snprintf(cmdline, sizeof(cmdline), "ip route replace default via %s", ip4_addr);
+ g_snprintf(cmdline, sizeof(cmdline), "%s route replace default via %s", iptool, ip4_addr);
if (!g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, &error)) {
g_printerr("%s: %s\n", cmdline, error->message);
g_error_free(error);
@@ -320,7 +369,7 @@ static void setup_rmnet(void)
return;
}
- /* TODO: DNS */
+ setup_dns();
}
/* 13 - Network settings retrieved */
@@ -349,7 +398,7 @@ static void get_current_settings_ready(QmiClientWds *client, GAsyncResult *res)
}
if (qmi_message_wds_get_current_settings_output_get_ip_family(output, &ip_family, NULL))
- g_print("[%s] IP Family: %s\n", qmi_device_get_path_display(device),
+ g_print("[%s] [WDS] IP family: %s\n", qmi_device_get_path_display(device),
((ip_family == QMI_WDS_IP_FAMILY_IPV4) ? "IPv4" :
((ip_family == QMI_WDS_IP_FAMILY_IPV6) ? "IPv6" :
"unknown")));
@@ -365,16 +414,16 @@ static void get_current_settings_ready(QmiClientWds *client, GAsyncResult *res)
in_addr_val.s_addr = GUINT32_TO_BE(addr);
memset (ip4_addr, 0, sizeof(ip4_addr));
inet_ntop (AF_INET, &in_addr_val, ip4_addr, sizeof(ip4_addr));
- g_print("[%s] IPv4 address: %s\n", qmi_device_get_path_display(device), ip4_addr);
+ g_print("[%s] [WDS] IPv4 address: %s\n", qmi_device_get_path_display(device), ip4_addr);
}
if (qmi_message_wds_get_current_settings_output_get_primary_ipv4_dns_address(output, &addr, NULL)) {
in_addr_val.s_addr = GUINT32_TO_BE(addr);
memset(ip4_dns, 0, sizeof(ip4_dns));
inet_ntop(AF_INET, &in_addr_val, ip4_dns, sizeof(ip4_dns));
- g_print("[%s] IPv4 primary DNS: %s\n", qmi_device_get_path_display(device), ip4_dns);
+ g_print("[%s] [WDS] IPv4 primary DNS: %s\n", qmi_device_get_path_display(device), ip4_dns);
}
-
+
qmi_message_wds_get_current_settings_output_unref(output);
setup_rmnet();
@@ -414,7 +463,7 @@ static void start_network_ready(QmiClientWds *client, GAsyncResult *res)
qmi_message_wds_start_network_output_get_packet_data_handle(output, &packet_data_handle, NULL);
qmi_message_wds_start_network_output_unref(output);
- g_print("[%s] Network Started!\n", qmi_device_get_path_display(device));
+ g_print("[%s] [WDS] Network Started!\n", qmi_device_get_path_display(device));
input = qmi_message_wds_get_current_settings_input_new();
qmi_message_wds_get_current_settings_input_set_requested_settings(input,
@@ -441,7 +490,7 @@ static gboolean start_network(gpointer user_data)
{
QmiMessageWdsStartNetworkInput *input;
- g_print("[%s] Starting Network...\n", qmi_device_get_path_display(device));
+ g_print("[%s] [WDS] Starting Network...\n", qmi_device_get_path_display(device));
input = qmi_message_wds_start_network_input_new();
@@ -600,7 +649,7 @@ static void verify_pin_ready(QmiClientUim *client, GAsyncResult *res)
if (qmi_message_uim_verify_pin_output_get_retries_remaining(
output, &verify_retries_left, &unblock_retries_left, NULL)) {
- g_printerr("[%s] Retries left:\n"
+ g_printerr("[%s] [UIM] Retries left:\n"
"\tVerify: %u\n"
"\tUnblock: %u\n",
qmi_device_get_path_display(device),
@@ -613,7 +662,7 @@ static void verify_pin_ready(QmiClientUim *client, GAsyncResult *res)
return;
}
- g_print("[%s] PIN verified successfully\n", qmi_device_get_path_display(device));
+ g_print("[%s] [UIM] PIN verified successfully\n", qmi_device_get_path_display(device));
qmi_message_uim_verify_pin_output_unref(output);
@@ -648,7 +697,7 @@ static void power_on_sim_ready(QmiClientUim *client, GAsyncResult *res)
qmi_message_uim_power_on_sim_output_unref(output);
- g_print("[%s] Verifying SIM1 PIN...\n", qmi_device_get_path_display(device));
+ g_print("[%s] [UIM] Verifying SIM1 PIN...\n", qmi_device_get_path_display(device));
input = qmi_message_uim_verify_pin_input_new();
@@ -681,7 +730,7 @@ static void allocate_uim_client_ready(QmiDevice *dev, GAsyncResult *res)
return;
}
- g_print("[%s] Powering SIM1...\n", qmi_device_get_path_display(device));
+ g_print("[%s] [UIM] Powering SIM1...\n", qmi_device_get_path_display(device));
input = qmi_message_uim_power_on_sim_input_new();
@@ -721,12 +770,12 @@ static void get_operating_mode_ready(QmiClientDms *client, GAsyncResult *res)
if (mode != QMI_DMS_OPERATING_MODE_ONLINE) {
/* TODO put it online */
- g_print("[%s] Modem is offline\n", qmi_device_get_path_display(device));
+ g_print("[%s] [DMS] Modem is offline\n", qmi_device_get_path_display(device));
op_shutdown(SHUTDOWN_ERROR);
return;
}
- g_print("[%s] Modem is online\n", qmi_device_get_path_display(device));
+ g_print("[%s] [DMS] Modem is online\n", qmi_device_get_path_display(device));
if (sim1_pin_str) {
qmi_device_allocate_client(device, service_uim, QMI_CID_NONE, 10, cancellable,
@@ -747,7 +796,7 @@ static void allocate_dms_client_ready(QmiDevice *dev, GAsyncResult *res)
g_printerr("error: couldn't create client for the '%s' service: %s\n",
"DMS", error->message);
g_error_free(error);
- op_shutdown(SHUTDOWN_ERROR);
+ op_shutdown(SHUTDOWN_DISCONNECTED);
return;
}
@@ -878,6 +927,9 @@ static GOptionEntry main_entries[] = {
{ "udev", 0, 0, G_OPTION_ARG_NONE, &udev,
"When executed from udev rule", NULL
},
+ { "kmsg", 0, 0, G_OPTION_ARG_NONE, &kmsg,
+ "Redirect output to kernel log", NULL
+ },
{ NULL }
};
@@ -961,8 +1013,7 @@ int main(int argc, char **argv)
if (udev) {
qmi_dev = g_strdup(g_getenv("DEVNAME"));
- g_printerr("QMIdev=%s\n", qmi_dev);
- config = "/etc/mhi-qmi-connect.conf";
+ config = MHI_CONFIG_DEFAULT;
// todo g_free()
}
@@ -980,6 +1031,14 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE);
}
+ if (kmsg) {
+ /*/ Wait for the modem to be ready */
+ fclose(stdout);
+ stdout = fopen("/dev/kmsg", "w");
+ fclose(stderr);
+ stderr = stdout;
+ }
+
while (1) {
/* TODO try to reconnect on disconnect event */
ret = mainloop();
@@ -987,6 +1046,8 @@ int main(int argc, char **argv)
case SHUTDOWN_ERROR:
exit(EXIT_SUCCESS);
case SHUTDOWN_DISCONNECTED:
+ sleep(5);
+ continue;
case SHUTDOWN_KILLED:
exit(EXIT_FAILURE);
default:
diff --git a/mhi-qmi-connect.conf b/mhi-qmi-connect.conf
index d64aaee..a72de2e 100644
--- a/mhi-qmi-connect.conf
+++ b/mhi-qmi-connect.conf
@@ -5,6 +5,8 @@ name=free
#pin=1234
[RMNET]
+# Retrieve network IP/DNS from bearer (no dhcp)
ip_from_bearer=true
+# Network as default route
default_route=true