Move netpoll_parse_ip_addr() earlier in the file to be reused in other functions, such as local_ip_store(). This avoids duplicate address parsing logic and centralizes validation for both IPv4 and IPv6 string input. No functional changes intended. Signed-off-by: Breno Leitao Reviewed-by: Simon Horman --- drivers/net/netconsole.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index e3722de08ea9f..8d1b93264e0fd 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -300,6 +300,26 @@ static void netconsole_print_banner(struct netpoll *np) np_info(np, "remote ethernet address %pM\n", np->remote_mac); } +static int netpoll_parse_ip_addr(const char *str, union inet_addr *addr) +{ + const char *end; + + if (!strchr(str, ':') && + in4_pton(str, -1, (void *)addr, -1, &end) > 0) { + if (!*end) + return 0; + } + if (in6_pton(str, -1, addr->in6.s6_addr, -1, &end) > 0) { +#if IS_ENABLED(CONFIG_IPV6) + if (!*end) + return 1; +#else + return -1; +#endif + } + return -1; +} + #ifdef CONFIG_NETCONSOLE_DYNAMIC /* @@ -1742,26 +1762,6 @@ static void write_msg(struct console *con, const char *msg, unsigned int len) spin_unlock_irqrestore(&target_list_lock, flags); } -static int netpoll_parse_ip_addr(const char *str, union inet_addr *addr) -{ - const char *end; - - if (!strchr(str, ':') && - in4_pton(str, -1, (void *)addr, -1, &end) > 0) { - if (!*end) - return 0; - } - if (in6_pton(str, -1, addr->in6.s6_addr, -1, &end) > 0) { -#if IS_ENABLED(CONFIG_IPV6) - if (!*end) - return 1; -#else - return -1; -#endif - } - return -1; -} - static int netconsole_parser_cmdline(struct netpoll *np, char *opt) { bool ipversion_set = false; -- 2.47.3 The current IP address parsing logic fails when the input string contains a trailing newline character. This can occur when IP addresses are provided through configfs, which contains newlines in a const buffer. Teach netpoll_parse_ip_addr() how to ignore newlines at the end of the IPs. Also, simplify the code by: * No need to check for separators. Try to parse ipv4, if it fails try ipv6 similarly to ceph_pton() * If ipv6 is not supported, don't call in6_pton() at all. Signed-off-by: Breno Leitao --- drivers/net/netconsole.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 8d1b93264e0fd..2919522d963e2 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -300,23 +300,30 @@ static void netconsole_print_banner(struct netpoll *np) np_info(np, "remote ethernet address %pM\n", np->remote_mac); } +/* Parse the string and populate the `inet_addr` union. Return 0 if IPv4 is + * populated, 1 if IPv6 is populated, and -1 upon failure. + */ static int netpoll_parse_ip_addr(const char *str, union inet_addr *addr) { - const char *end; + const char *end = NULL; + int len; - if (!strchr(str, ':') && - in4_pton(str, -1, (void *)addr, -1, &end) > 0) { - if (!*end) - return 0; - } - if (in6_pton(str, -1, addr->in6.s6_addr, -1, &end) > 0) { -#if IS_ENABLED(CONFIG_IPV6) - if (!*end) - return 1; -#else + len = strlen(str); + if (!len) return -1; -#endif - } + + if (str[len - 1] == '\n') + len -= 1; + + if (in4_pton(str, len, (void *)addr, -1, &end) > 0 && + (!end || *end == 0 || *end == '\n')) + return 0; + + if (IS_ENABLED(CONFIG_IPV6) && + in6_pton(str, len, (void *)addr, -1, &end) > 0 && + (!end || *end == 0 || *end == '\n')) + return 1; + return -1; } -- 2.47.3 Replace manual IP address parsing with a call to netpoll_parse_ip_addr in local_ip_store(), simplifying the code and reducing the chance of errors. Also, remove the pr_err() if the user enters an invalid value in configfs entries. pr_err() is not the best way to alert user that the configuration is invalid. Signed-off-by: Breno Leitao Reviewed-by: Simon Horman --- drivers/net/netconsole.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 2919522d963e2..a9b30b5891d78 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -757,6 +757,7 @@ static ssize_t local_ip_store(struct config_item *item, const char *buf, { struct netconsole_target *nt = to_target(item); ssize_t ret = -EINVAL; + int ipv6; mutex_lock(&dynamic_netconsole_mutex); if (nt->enabled) { @@ -765,23 +766,10 @@ static ssize_t local_ip_store(struct config_item *item, const char *buf, goto out_unlock; } - if (strnchr(buf, count, ':')) { - const char *end; - - if (in6_pton(buf, count, nt->np.local_ip.in6.s6_addr, -1, &end) > 0) { - if (*end && *end != '\n') { - pr_err("invalid IPv6 address at: <%c>\n", *end); - goto out_unlock; - } - nt->np.ipv6 = true; - } else - goto out_unlock; - } else { - if (!nt->np.ipv6) - nt->np.local_ip.ip = in_aton(buf); - else - goto out_unlock; - } + ipv6 = netpoll_parse_ip_addr(buf, &nt->np.local_ip); + if (ipv6 == -1) + goto out_unlock; + nt->np.ipv6 = !!ipv6; ret = strnlen(buf, count); out_unlock: -- 2.47.3 Replace manual IP address parsing with a call to netpoll_parse_ip_addr in remote_ip_store(), simplifying the code and reducing the chance of errors. The error message got removed, since it is not a good practice to pr_err() if used pass a wrong value in configfs. Signed-off-by: Breno Leitao Reviewed-by: Simon Horman --- drivers/net/netconsole.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index a9b30b5891d78..194570443493b 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -782,6 +782,7 @@ static ssize_t remote_ip_store(struct config_item *item, const char *buf, { struct netconsole_target *nt = to_target(item); ssize_t ret = -EINVAL; + int ipv6; mutex_lock(&dynamic_netconsole_mutex); if (nt->enabled) { @@ -790,23 +791,10 @@ static ssize_t remote_ip_store(struct config_item *item, const char *buf, goto out_unlock; } - if (strnchr(buf, count, ':')) { - const char *end; - - if (in6_pton(buf, count, nt->np.remote_ip.in6.s6_addr, -1, &end) > 0) { - if (*end && *end != '\n') { - pr_err("invalid IPv6 address at: <%c>\n", *end); - goto out_unlock; - } - nt->np.ipv6 = true; - } else - goto out_unlock; - } else { - if (!nt->np.ipv6) - nt->np.remote_ip.ip = in_aton(buf); - else - goto out_unlock; - } + ipv6 = netpoll_parse_ip_addr(buf, &nt->np.remote_ip); + if (ipv6 == -1) + goto out_unlock; + nt->np.ipv6 = !!ipv6; ret = strnlen(buf, count); out_unlock: -- 2.47.3