-
Notifications
You must be signed in to change notification settings - Fork 327
plugins types BUGFIX print same IPv6 format as stored #2509
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ | |
|
|
||
| #define _GNU_SOURCE /* strndup */ | ||
|
|
||
| #include "ipv6_common.h" | ||
| #include "plugins_internal.h" | ||
| #include "plugins_types.h" | ||
|
|
||
|
|
@@ -60,12 +61,13 @@ static void lyplg_type_free_ipv6_address(const struct ly_ctx *ctx, struct lyd_va | |
| * @param[in] ctx libyang context with dictionary. | ||
| * @param[in,out] addr Allocated value for the address. | ||
| * @param[out] zone Ipv6 address zone in dictionary. | ||
| * @param[out] dual stack format. | ||
| * @param[out] err Error information on error. | ||
| * @return LY_ERR value. | ||
| */ | ||
| static LY_ERR | ||
| ipv6address_str2ip(const char *value, uint32_t value_len, uint32_t options, const struct ly_ctx *ctx, | ||
| struct in6_addr *addr, const char **zone, struct ly_err_item **err) | ||
| struct in6_addr *addr, const char **zone, uint8_t *dual_stack_format, struct ly_err_item **err) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should use |
||
| { | ||
| LY_ERR ret = LY_SUCCESS; | ||
| const char *addr_no_zone; | ||
|
|
@@ -107,6 +109,9 @@ ipv6address_str2ip(const char *value, uint32_t value_len, uint32_t options, cons | |
| goto cleanup; | ||
| } | ||
|
|
||
| /* store dual stack IPv6 format or compressed format */ | ||
| *dual_stack_format = ly_strnchr(value, '.', value_len) != NULL; | ||
|
|
||
| /* restore the value */ | ||
| if ((options & LYPLG_TYPE_STORE_DYNAMIC) && zone_ptr) { | ||
| *zone_ptr = '%'; | ||
|
|
@@ -174,7 +179,8 @@ lyplg_type_store_ipv6_address(const struct ly_ctx *ctx, const struct lysc_type * | |
| LY_CHECK_GOTO(ret, cleanup); | ||
|
|
||
| /* get the network-byte order address */ | ||
| ret = ipv6address_str2ip(value, value_size, options, ctx, &val->addr, &val->zone, err); | ||
| ret = ipv6address_str2ip(value, value_size, options, ctx, &val->addr, &val->zone, | ||
| &val->dual_stack_format, err); | ||
| LY_CHECK_GOTO(ret, cleanup); | ||
|
|
||
| if (format == LY_VALUE_CANON) { | ||
|
|
@@ -258,6 +264,7 @@ lyplg_type_print_ipv6_address(const struct ly_ctx *ctx, const struct lyd_value * | |
| struct lyd_value_ipv6_address *val; | ||
| uint32_t zone_len; | ||
| char *ret; | ||
| LY_ERR rc; | ||
|
|
||
| LYD_VALUE_GET(value, val); | ||
|
|
||
|
|
@@ -290,15 +297,10 @@ lyplg_type_print_ipv6_address(const struct ly_ctx *ctx, const struct lyd_value * | |
| if (!value->_canonical) { | ||
| /* '%' + zone */ | ||
| zone_len = val->zone ? strlen(val->zone) + 1 : 0; | ||
| ret = malloc(INET6_ADDRSTRLEN + zone_len); | ||
| LY_CHECK_RET(!ret, NULL); | ||
|
|
||
| /* get the address in string */ | ||
| if (!inet_ntop(AF_INET6, &val->addr, ret, INET6_ADDRSTRLEN)) { | ||
| free(ret); | ||
| LOGERR(ctx, LY_ESYS, "Failed to get IPv6 address in string (%s).", strerror(errno)); | ||
| return NULL; | ||
| } | ||
| rc = ipv6address_ip2str(&val->addr, val->dual_stack_format, | ||
| &ret, INET6_ADDRSTRLEN + zone_len); | ||
| LY_CHECK_RET(!ret || rc != LY_SUCCESS, NULL); | ||
|
|
||
| /* add zone */ | ||
| if (zone_len) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| /* | ||
| * Copyright 2026 6WIND S.A. | ||
| */ | ||
|
|
||
| #include <stdint.h> | ||
| #include <stdio.h> | ||
| #include <stdlib.h> | ||
| #include <string.h> | ||
|
|
||
| #include "compat.h" | ||
| #include "ipv6_common.h" | ||
| #include "ly_common.h" | ||
|
|
||
| static int | ||
| ipv6_dual_to_compressed(char *ipv6_str) | ||
| { | ||
| char *ipv4_str = NULL; | ||
| uint16_t parts[2]; | ||
| uint8_t bytes[4]; | ||
|
|
||
| ipv4_str = strrchr(ipv6_str, ':'); | ||
| if (ipv4_str == NULL) { | ||
| return -1; | ||
| } | ||
|
|
||
| /* Parse the IPv4 part */ | ||
| if (sscanf(ipv4_str + 1, "%hhu.%hhu.%hhu.%hhu", | ||
| &bytes[0], &bytes[1], &bytes[2], &bytes[3]) != 4) { | ||
| return -1; | ||
| } | ||
|
|
||
| parts[0] = (bytes[0] << 8) | bytes[1]; | ||
| parts[1] = (bytes[2] << 8) | bytes[3]; | ||
|
|
||
| sprintf(ipv4_str + 1, "%x:%x", parts[0], parts[1]); | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| LY_ERR | ||
| ipv6address_ip2str(struct in6_addr *addr, uint8_t dual_stack_format, | ||
| char **str_addr, int str_addr_len) | ||
| { | ||
| *str_addr = malloc(str_addr_len); | ||
| if (!*str_addr) { | ||
| return LY_EMEM; | ||
| } | ||
|
|
||
| /* convert back to string */ | ||
| if (!inet_ntop(AF_INET6, addr, *str_addr, INET6_ADDRSTRLEN)) { | ||
| free(*str_addr); | ||
| return LY_EINVAL; | ||
| } | ||
|
|
||
| /* if compress format is expected convert from dual to compress format */ | ||
| if (!dual_stack_format && strchr(*str_addr, '.')) { | ||
| if (ipv6_dual_to_compressed(*str_addr)) { | ||
| free(*str_addr); | ||
| return LY_EINVAL; | ||
| } | ||
| } | ||
|
|
||
| return LY_SUCCESS; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| /* | ||
| * Copyright 2026 6WIND S.A. | ||
| */ | ||
|
|
||
| #ifdef _WIN32 | ||
| # include <winsock2.h> | ||
| # include <ws2tcpip.h> | ||
| #else | ||
| # include <arpa/inet.h> | ||
| # if defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) | ||
| # include <netinet/in.h> | ||
| # include <sys/socket.h> | ||
| # endif | ||
| #endif | ||
|
|
||
| #include "libyang.h" | ||
|
|
||
| /** | ||
| * @brief convert dual format ipv6 address inside to compressed ipv6 address | ||
| */ | ||
| LY_ERR ipv6address_ip2str(struct in6_addr *addr, uint8_t dual_stack_format, | ||
| char **str_addr, int str_addr_len); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -635,14 +635,16 @@ struct lyd_value_ipv4_prefix { | |
| */ | ||
| struct lyd_value_ipv6_address_no_zone { | ||
| struct in6_addr addr; /**< IPv6 address in binary */ | ||
| uint8_t dual_stack_format; /**< Dual stack IPv6 format or compressed format */ | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a problematic change. The header is public meaning this is an NBC change. I have just made the new release and it caused enough annoyance so too bad you have not made this change before it. Now it cannot be merged and we have not planned a new major SO version bump anytime soon. |
||
| }; | ||
|
|
||
| /** | ||
| * @brief Special lyd_value structure for ietf-inet-types ipv6-address values. | ||
| */ | ||
| struct lyd_value_ipv6_address { | ||
| struct in6_addr addr; /**< IPv6 address in binary */ | ||
| const char *zone; /**< Optional address zone */ | ||
| struct in6_addr addr; /**< IPv6 address in binary */ | ||
| const char *zone; /**< Optional address zone */ | ||
| uint8_t dual_stack_format; /**< Dual stack IPv6 format or compressed format */ | ||
| }; | ||
|
|
||
| /** | ||
|
|
@@ -651,6 +653,7 @@ struct lyd_value_ipv6_address { | |
| struct lyd_value_ipv6_prefix { | ||
| struct in6_addr addr; /**< IPv6 host address in binary */ | ||
| uint8_t prefix; /**< prefix length (0 - 128) */ | ||
| uint8_t dual_stack_format; /**< Dual stack IPv6 format or compressed format */ | ||
| }; | ||
|
|
||
| /** | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No description of the param.