diff options
author | Loic Poulain <loic.poulain@linaro.org> | 2020-11-10 15:32:24 +0100 |
---|---|---|
committer | Loic Poulain <loic.poulain@linaro.org> | 2020-11-10 15:32:24 +0100 |
commit | 0995aa02e1a6c3ffb335c9bac6f2bb9be9599479 (patch) | |
tree | 3daa689991b854f1ebcfd2765d97880a2455a9bb | |
parent | 88fe7e3cc99438c1760f3e0f2da061fdaab4a924 (diff) |
Add builtin DNS config support
Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
-rw-r--r-- | 42-mhi.rules | 6 | ||||
-rw-r--r-- | mhi-qmi-connect.c | 145 | ||||
-rw-r--r-- | mhi-qmi-connect.conf | 2 |
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 |