diff options
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/ublox/mm-modem-helpers-ublox.c | 97 | ||||
-rw-r--r-- | plugins/ublox/mm-modem-helpers-ublox.h | 12 | ||||
-rw-r--r-- | plugins/ublox/tests/test-modem-helpers-ublox.c | 80 |
3 files changed, 189 insertions, 0 deletions
diff --git a/plugins/ublox/mm-modem-helpers-ublox.c b/plugins/ublox/mm-modem-helpers-ublox.c index 857bfe8c..0b0461c9 100644 --- a/plugins/ublox/mm-modem-helpers-ublox.c +++ b/plugins/ublox/mm-modem-helpers-ublox.c @@ -142,3 +142,100 @@ mm_ublox_parse_ubmconf_response (const gchar *response, *out_mode = mode; return TRUE; } + +/*****************************************************************************/ +/* UIPADDR=N response parser */ + +gboolean +mm_ublox_parse_uipaddr_response (const gchar *response, + guint *out_cid, + gchar **out_if_name, + gchar **out_ipv4_address, + gchar **out_ipv4_subnet, + gchar **out_ipv6_global_address, + gchar **out_ipv6_link_local_address, + GError **error) +{ + GRegex *r; + GMatchInfo *match_info; + GError *inner_error = NULL; + guint cid = 0; + gchar *if_name = NULL; + gchar *ipv4_address = NULL; + gchar *ipv4_subnet = NULL; + gchar *ipv6_global_address = NULL; + gchar *ipv6_link_local_address = NULL; + + /* Response may be e.g.: + * +UIPADDR: 1,"ccinet0","5.168.120.13","255.255.255.0","","" + * +UIPADDR: 2,"ccinet1","","","2001::2:200:FF:FE00:0/64","FE80::200:FF:FE00:0/64" + * +UIPADDR: 3,"ccinet2","5.10.100.2","255.255.255.0","2001::1:200:FF:FE00:0/64","FE80::200:FF:FE00:0/64" + * + * We assume only ONE line is returned; because we request +UIPADDR with a specific N CID. + */ + r = g_regex_new ("\\+UIPADDR: (\\d+),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*)(?:\\r\\n)?", 0, 0, NULL); + g_assert (r != NULL); + + g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); + if (inner_error) + goto out; + + if (!g_match_info_matches (match_info)) { + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, "Couldn't match +UIPADDR response"); + goto out; + } + + if (out_cid && !mm_get_uint_from_match_info (match_info, 1, &cid)) { + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Error parsing cid"); + goto out; + } + + if (out_if_name && !(if_name = mm_get_string_unquoted_from_match_info (match_info, 2))) { + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Error parsing interface name"); + goto out; + } + + /* Remaining strings are optional */ + + if (out_ipv4_address) + ipv4_address = mm_get_string_unquoted_from_match_info (match_info, 3); + + if (out_ipv4_subnet) + ipv4_subnet = mm_get_string_unquoted_from_match_info (match_info, 4); + + if (out_ipv6_global_address) + ipv6_global_address = mm_get_string_unquoted_from_match_info (match_info, 5); + + if (out_ipv6_link_local_address) + ipv6_link_local_address = mm_get_string_unquoted_from_match_info (match_info, 6); + +out: + + if (match_info) + g_match_info_free (match_info); + g_regex_unref (r); + + if (inner_error) { + g_free (if_name); + g_free (ipv4_address); + g_free (ipv4_subnet); + g_free (ipv6_global_address); + g_free (ipv6_link_local_address); + g_propagate_error (error, inner_error); + return FALSE; + } + + if (out_cid) + *out_cid = cid; + if (out_if_name) + *out_if_name = if_name; + if (out_ipv4_address) + *out_ipv4_address = ipv4_address; + if (out_ipv4_subnet) + *out_ipv4_subnet = ipv4_subnet; + if (out_ipv6_global_address) + *out_ipv6_global_address = ipv6_global_address; + if (out_ipv6_link_local_address) + *out_ipv6_link_local_address = ipv6_link_local_address; + return TRUE; +} diff --git a/plugins/ublox/mm-modem-helpers-ublox.h b/plugins/ublox/mm-modem-helpers-ublox.h index e8b9f22b..c97724da 100644 --- a/plugins/ublox/mm-modem-helpers-ublox.h +++ b/plugins/ublox/mm-modem-helpers-ublox.h @@ -45,4 +45,16 @@ gboolean mm_ublox_parse_ubmconf_response (const gchar *response, MMUbloxNetworkingMode *out_mode, GError **error); +/*****************************************************************************/ +/* UIPADDR=N response parser */ + +gboolean mm_ublox_parse_uipaddr_response (const gchar *response, + guint *out_cid, + gchar **out_if_name, + gchar **out_ipv4_address, + gchar **out_ipv4_subnet, + gchar **out_ipv6_global_address, + gchar **out_ipv6_link_local_address, + GError **error); + #endif /* MM_MODEM_HELPERS_UBLOX_H */ diff --git a/plugins/ublox/tests/test-modem-helpers-ublox.c b/plugins/ublox/tests/test-modem-helpers-ublox.c index 078d1c1a..d1e5e497 100644 --- a/plugins/ublox/tests/test-modem-helpers-ublox.c +++ b/plugins/ublox/tests/test-modem-helpers-ublox.c @@ -103,6 +103,85 @@ test_ubmconf_response (void) } /*****************************************************************************/ +/* Test UIPADDR=N responses */ + +typedef struct { + const gchar *str; + guint cid; + const gchar *if_name; + const gchar *ipv4_address; + const gchar *ipv4_subnet; + const gchar *ipv6_global_address; + const gchar *ipv6_link_local_address; +} UipaddrResponseTest; + +static const UipaddrResponseTest uipaddr_response_tests[] = { + { + .str = "+UIPADDR: 1,\"ccinet0\",\"5.168.120.13\",\"255.255.255.0\",\"\",\"\"", + .cid = 1, + .if_name = "ccinet0", + .ipv4_address = "5.168.120.13", + .ipv4_subnet = "255.255.255.0", + }, + { + .str = "+UIPADDR: 2,\"ccinet1\",\"\",\"\",\"2001::1:200:FF:FE00:0/64\",\"FE80::200:FF:FE00:0/64\"", + .cid = 2, + .if_name = "ccinet1", + .ipv6_global_address = "2001::1:200:FF:FE00:0/64", + .ipv6_link_local_address = "FE80::200:FF:FE00:0/64", + }, + { + .str = "+UIPADDR: 3,\"ccinet2\",\"5.10.100.2\",\"255.255.255.0\",\"2001::1:200:FF:FE00:0/64\",\"FE80::200:FF:FE00:0/64\"", + .cid = 3, + .if_name = "ccinet2", + .ipv4_address = "5.10.100.2", + .ipv4_subnet = "255.255.255.0", + .ipv6_global_address = "2001::1:200:FF:FE00:0/64", + .ipv6_link_local_address = "FE80::200:FF:FE00:0/64", + }, +}; + +static void +test_uipaddr_response (void) +{ + guint i; + + for (i = 0; i < G_N_ELEMENTS (uipaddr_response_tests); i++) { + GError *error = NULL; + gboolean success; + guint cid = G_MAXUINT; + gchar *if_name = NULL; + gchar *ipv4_address = NULL; + gchar *ipv4_subnet = NULL; + gchar *ipv6_global_address = NULL; + gchar *ipv6_link_local_address = NULL; + + success = mm_ublox_parse_uipaddr_response (uipaddr_response_tests[i].str, + &cid, + &if_name, + &ipv4_address, + &ipv4_subnet, + &ipv6_global_address, + &ipv6_link_local_address, + &error); + g_assert_no_error (error); + g_assert (success); + g_assert_cmpuint (uipaddr_response_tests[i].cid, ==, cid); + g_assert_cmpstr (uipaddr_response_tests[i].if_name, ==, if_name); + g_assert_cmpstr (uipaddr_response_tests[i].ipv4_address, ==, ipv4_address); + g_assert_cmpstr (uipaddr_response_tests[i].ipv4_subnet, ==, ipv4_subnet); + g_assert_cmpstr (uipaddr_response_tests[i].ipv6_global_address, ==, ipv6_global_address); + g_assert_cmpstr (uipaddr_response_tests[i].ipv6_link_local_address, ==, ipv6_link_local_address); + + g_free (if_name); + g_free (ipv4_address); + g_free (ipv4_subnet); + g_free (ipv6_global_address); + g_free (ipv6_link_local_address); + } +} + +/*****************************************************************************/ void _mm_log (const char *loc, @@ -133,6 +212,7 @@ int main (int argc, char **argv) g_test_add_func ("/MM/ublox/uusbconf/response", test_uusbconf_response); g_test_add_func ("/MM/ublox/ubmconf/response", test_ubmconf_response); + g_test_add_func ("/MM/ublox/uipaddr/response", test_uipaddr_response); return g_test_run (); } |