From 663e1ea3a015954519f8fbc07e7cc41f47da4256 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 13 Apr 2021 13:14:01 +0100 Subject: [PATCH] Consolidate the various add_option() functions We have duplicates of these littered all over the place. Make two simple "strndup" vs. "steal" variants and put them in library.c. Signed-off-by: David Woodhouse --- f5.c | 39 +++++------------------------ fortinet.c | 35 ++++---------------------- gpst.c | 41 ++++++------------------------ library.c | 36 ++++++++++++++++++++++++++ oncp.c | 47 ++++++---------------------------- openconnect-internal.h | 2 ++ pulse.c | 57 ++++++++++-------------------------------- 7 files changed, 78 insertions(+), 179 deletions(-) diff --git a/f5.c b/f5.c index d7c0332a..c294d51a 100644 --- a/f5.c +++ b/f5.c @@ -302,31 +302,6 @@ static int xmlnode_bool_or_int_value(struct openconnect_info *vpninfo, xmlNode * return ret; } -/* We behave like CSTP — create a linked list in vpninfo->cstp_options - * with the strings containing the information we got from the server, - * and oc_ip_info contains const copies of those pointers. - * - * (unlike version in oncp.c, val is stolen rather than strdup'ed) */ - -static const char *add_option(struct openconnect_info *vpninfo, const char *opt, char **val) -{ - struct oc_vpn_option *new = malloc(sizeof(*new)); - if (!new) - return NULL; - - new->option = strdup(opt); - if (!new->option) { - free(new); - return NULL; - } - new->value = *val; - *val = NULL; - new->next = vpninfo->cstp_options; - vpninfo->cstp_options = new; - - return new->value; -} - static int parse_options(struct openconnect_info *vpninfo, char *buf, int len, char **session_id, char **ur_z, int *ipv4, int *ipv6, int *hdlc) { @@ -403,14 +378,14 @@ static int parse_options(struct openconnect_info *vpninfo, char *buf, int len, if (s && *s) { vpn_progress(vpninfo, PRG_INFO, _("Got IPv%d DNS server %s\n"), xml_node->name[4]=='_' ? 6 : 4, s); - if (n_dns < 3) vpninfo->ip_info.dns[n_dns++] = add_option(vpninfo, "DNS", &s); + if (n_dns < 3) vpninfo->ip_info.dns[n_dns++] = add_option_steal(vpninfo, "DNS", &s); } } else if (!strncmp((char *)xml_node->name, "WINS", 4) && isdigit(xml_node->name[4])) { free(s); s = (char *)xmlNodeGetContent(xml_node); if (s && *s) { vpn_progress(vpninfo, PRG_INFO, _("Got WINS/NBNS server %s\n"), s); - if (n_nbns < 3) vpninfo->ip_info.dns[n_nbns++] = add_option(vpninfo, "WINS", &s); + if (n_nbns < 3) vpninfo->ip_info.dns[n_nbns++] = add_option_steal(vpninfo, "WINS", &s); } } else if (!strncmp((char *)xml_node->name, "DNSSuffix", 9) && isdigit(xml_node->name[9])) { free(s); @@ -427,7 +402,7 @@ static int parse_options(struct openconnect_info *vpninfo, char *buf, int len, char *word, *next; struct oc_split_include *inc; - for (word = (char *)add_option(vpninfo, "route-list", &s); + for (word = (char *)add_option_steal(vpninfo, "route-list", &s); *word; word = next) { for (next = word; *next && !isspace(*next); next++); if (*next) @@ -452,7 +427,7 @@ static int parse_options(struct openconnect_info *vpninfo, char *buf, int len, vpninfo->ip_info.netmask6 = strdup("::/0"); if (buf_error(domains) == 0 && domains->pos > 0) { domains->data[domains->pos-1] = '\0'; - vpninfo->ip_info.domain = add_option(vpninfo, "search", &domains->data); + vpninfo->ip_info.domain = add_option_steal(vpninfo, "search", &domains->data); } buf_free(domains); @@ -470,21 +445,19 @@ static int parse_options(struct openconnect_info *vpninfo, char *buf, int len, } static int get_ip_address(struct openconnect_info *vpninfo, char *header, char *val) { - char *s = strdup(val); if (!strcasecmp(header, "X-VPN-client-IP")) { vpn_progress(vpninfo, PRG_INFO, _("Got legacy IP address %s\n"), val); - vpninfo->ip_info.addr = add_option(vpninfo, "ipaddr", &s); + vpninfo->ip_info.addr = add_option_dup(vpninfo, "ipaddr", val, -1); } else if (!strcasecmp(header, "X-VPN-client-IPv6")) { vpn_progress(vpninfo, PRG_INFO, _("Got IPv6 address %s\n"), val); /* XX: Should we treat this as a /64 netmask? Or an /128 address? */ - vpninfo->ip_info.addr6 = add_option(vpninfo, "ipaddr6", &s); + vpninfo->ip_info.addr6 = add_option_dup(vpninfo, "ipaddr6", val, -1); } /* XX: The server's IP address(es) X-VPN-server-{IP,IPv6} are also * sent, but the utility of these is unclear. As remarked in oncp.c, * "this is a tunnel; having a gateway is meaningless." */ - free(s); return 0; } diff --git a/fortinet.c b/fortinet.c index 9718230d..c081e885 100644 --- a/fortinet.c +++ b/fortinet.c @@ -249,31 +249,6 @@ int fortinet_obtain_cookie(struct openconnect_info *vpninfo) return ret; } -/* We behave like CSTP — create a linked list in vpninfo->cstp_options - * with the strings containing the information we got from the server, - * and oc_ip_info contains const copies of those pointers. - * - * (unlike version in oncp.c, val is stolen rather than strdup'ed) */ - -static const char *add_option(struct openconnect_info *vpninfo, const char *opt, char **val) -{ - struct oc_vpn_option *new = malloc(sizeof(*new)); - if (!new) - return NULL; - - new->option = strdup(opt); - if (!new->option) { - free(new); - return NULL; - } - new->value = *val; - *val = NULL; - new->next = vpninfo->cstp_options; - vpninfo->cstp_options = new; - - return new->value; -} - /* Parse this: @@ -364,7 +339,7 @@ static int parse_fortinet_xml_config(struct openconnect_info *vpninfo, char *buf for (x = xml_node->children; x; x=x->next) { if (xmlnode_is_named(x, "assigned-addr") && !xmlnode_get_prop(x, "ipv4", &s)) { vpn_progress(vpninfo, PRG_INFO, _("Got legacy IP address %s\n"), s); - vpninfo->ip_info.addr = add_option(vpninfo, "ipaddr", &s); + vpninfo->ip_info.addr = add_option_steal(vpninfo, "ipaddr", &s); } else if (xmlnode_is_named(x, "dns")) { if (!xmlnode_get_prop(x, "domain", &s) && s && *s) { vpn_progress(vpninfo, PRG_INFO, _("Got search domain %s\n"), s); @@ -372,7 +347,7 @@ static int parse_fortinet_xml_config(struct openconnect_info *vpninfo, char *buf } if (!xmlnode_get_prop(x, "ip", &s) && s && *s) { vpn_progress(vpninfo, PRG_INFO, _("Got IPv%d DNS server %s\n"), 4, s); - if (n_dns < 3) vpninfo->ip_info.dns[n_dns++] = add_option(vpninfo, "DNS", &s); + if (n_dns < 3) vpninfo->ip_info.dns[n_dns++] = add_option_steal(vpninfo, "DNS", &s); } } else if (xmlnode_is_named(x, "split-dns")) { int ii; @@ -403,10 +378,10 @@ static int parse_fortinet_xml_config(struct openconnect_info *vpninfo, char *buf } snprintf(route, 32, "%s/%s", s, s2); vpn_progress(vpninfo, PRG_INFO, _("Got IPv%d route %s\n"), 4, route); - inc->route = add_option(vpninfo, "split-include", &route); + inc->route = add_option_steal(vpninfo, "split-include", &route); inc->next = vpninfo->ip_info.split_includes; vpninfo->ip_info.split_includes = inc; - /* XX: static analyzer doesn't realize that add_option will steal route's reference, so... */ + /* XX: static analyzer doesn't realize that add_option_steal will steal route's reference, so... */ free(route); } } @@ -422,7 +397,7 @@ static int parse_fortinet_xml_config(struct openconnect_info *vpninfo, char *buf vpninfo->ip_info.netmask6 = strdup("::/0"); if (buf_error(domains) == 0 && domains->pos > 0) { domains->data[domains->pos-1] = '\0'; - vpninfo->ip_info.domain = add_option(vpninfo, "search", &domains->data); + vpninfo->ip_info.domain = add_option_steal(vpninfo, "search", &domains->data); } buf_free(domains); diff --git a/gpst.c b/gpst.c index 64b24c04..08e9a0d5 100644 --- a/gpst.c +++ b/gpst.c @@ -74,31 +74,6 @@ static const struct pkt dpd_pkt = { { .gpst.hdr = { 0x1a, 0x2b, 0x3c, 0x4d } } }; -/* We behave like CSTP — create a linked list in vpninfo->cstp_options - * with the strings containing the information we got from the server, - * and oc_ip_info contains const copies of those pointers. - * - * (unlike version in oncp.c, val is stolen rather than strdup'ed) */ - -static const char *add_option(struct openconnect_info *vpninfo, const char *opt, char **val) -{ - struct oc_vpn_option *new = malloc(sizeof(*new)); - if (!new) - return NULL; - - new->option = strdup(opt); - if (!new->option) { - free(new); - return NULL; - } - new->value = *val; - *val = NULL; - new->next = vpninfo->cstp_options; - vpninfo->cstp_options = new; - - return new->value; -} - static int filter_opts(struct oc_text_buf *buf, const char *query, const char *incexc, int include) { const char *f, *endf, *eq; @@ -395,7 +370,7 @@ static int gpst_parse_config_xml(struct openconnect_info *vpninfo, xmlNode *xml_ /* Parse config */ for (xml_node = xml_node->children; xml_node; xml_node=xml_node->next) { if (!xmlnode_get_val(xml_node, "ip-address", &s)) - vpninfo->ip_info.addr = add_option(vpninfo, "ipaddr", &s); + vpninfo->ip_info.addr = add_option_steal(vpninfo, "ipaddr", &s); else if (!xmlnode_get_val(xml_node, "netmask", &deferred_netmask)) { /* XX: GlobalProtect servers always (almost always?) send 255.255.255.255 as their netmask * (a /32 host route), and if they want to include an actual default route (0.0.0.0/0) @@ -448,13 +423,13 @@ static int gpst_parse_config_xml(struct openconnect_info *vpninfo, xmlNode *xml_ if (!strcmp(s, vpninfo->ip_info.dns[ii])) break; if (ii==n_dns) - vpninfo->ip_info.dns[n_dns++] = add_option(vpninfo, "DNS", &s); + vpninfo->ip_info.dns[n_dns++] = add_option_steal(vpninfo, "DNS", &s); } } } else if (xmlnode_is_named(xml_node, "wins")) { for (ii=0, member = xml_node->children; member && ii<3; member=member->next) if (!xmlnode_get_val(member, "member", &s)) - vpninfo->ip_info.nbns[ii++] = add_option(vpninfo, "WINS", &s); + vpninfo->ip_info.nbns[ii++] = add_option_steal(vpninfo, "WINS", &s); } else if (xmlnode_is_named(xml_node, "dns-suffix")) { struct oc_text_buf *domains = buf_alloc(); for (member = xml_node->children; member; member=member->next) @@ -462,7 +437,7 @@ static int gpst_parse_config_xml(struct openconnect_info *vpninfo, xmlNode *xml_ buf_append(domains, "%s ", s); if (buf_error(domains) == 0 && domains->pos > 0) { domains->data[domains->pos-1] = '\0'; - vpninfo->ip_info.domain = add_option(vpninfo, "search", &domains->data); + vpninfo->ip_info.domain = add_option_steal(vpninfo, "search", &domains->data); } buf_free(domains); } else if (xmlnode_is_named(xml_node, "access-routes-v6") || xmlnode_is_named(xml_node, "exclude-access-routes-v6")) { @@ -485,11 +460,11 @@ static int gpst_parse_config_xml(struct openconnect_info *vpninfo, xmlNode *xml_ if ((inc = malloc(sizeof(*inc))) == NULL) return -ENOMEM; if (is_inc) { - inc->route = add_option(vpninfo, "split-include", &s); + inc->route = add_option_steal(vpninfo, "split-include", &s); inc->next = vpninfo->ip_info.split_includes; vpninfo->ip_info.split_includes = inc; } else { - inc->route = add_option(vpninfo, "split-exclude", &s); + inc->route = add_option_steal(vpninfo, "split-exclude", &s); inc->next = vpninfo->ip_info.split_excludes; vpninfo->ip_info.split_excludes = inc; } @@ -569,7 +544,7 @@ static int gpst_parse_config_xml(struct openconnect_info *vpninfo, xmlNode *xml_ if ((inc = malloc(sizeof(*inc))) == NULL || asprintf(&s, "%s/%s", inet_ntoa(net_addr), original_netmask) <= 0) return -ENOMEM; - inc->route = add_option(vpninfo, "split-include", &s); + inc->route = add_option_steal(vpninfo, "split-include", &s); inc->next = vpninfo->ip_info.split_includes; vpninfo->ip_info.split_includes = inc; } @@ -577,7 +552,7 @@ static int gpst_parse_config_xml(struct openconnect_info *vpninfo, xmlNode *xml_ free(original_netmask); } if (deferred_netmask) - vpninfo->ip_info.netmask = add_option(vpninfo, "netmask", &deferred_netmask); + vpninfo->ip_info.netmask = add_option_steal(vpninfo, "netmask", &deferred_netmask); /* Set 10-second DPD/keepalive (same as Windows client) unless * overridden with --force-dpd */ diff --git a/library.c b/library.c index e7cf1991..2d1c58c4 100644 --- a/library.c +++ b/library.c @@ -389,6 +389,42 @@ int openconnect_set_version_string(struct openconnect_info *vpninfo, return 0; } +const char *add_option_dup(struct openconnect_info *vpninfo, const char *opt, + const char *val, int val_len) +{ + const char *ret; + char *new_val; + + if (val_len >= 0) + new_val = strndup(val, val_len); + else + new_val = strdup(val); + + ret = add_option_steal(vpninfo, opt, &new_val); + free(new_val); + return ret; +} + +const char *add_option_steal(struct openconnect_info *vpninfo, const char *opt, char **val) +{ + struct oc_vpn_option *new = malloc(sizeof(*new)); + if (!new) + return NULL; + + new->option = strdup(opt); + if (!new->option) { + free(new); + return NULL; + } + new->value = *val; + *val = NULL; + new->next = vpninfo->cstp_options; + vpninfo->cstp_options = new; + + return new->value; +} + + void free_optlist(struct oc_vpn_option *opt) { struct oc_vpn_option *next; diff --git a/oncp.c b/oncp.c index 32798fa5..759327d2 100644 --- a/oncp.c +++ b/oncp.c @@ -61,37 +61,6 @@ static const char authpkt_tail[] = { 0xbb, 0x01, 0x00, 0x00, 0x00, 0x00 }; #define GRP_ATTR(g, a) (((g) << 16) | (a)) -/* We behave like CSTP — create a linked list in vpninfo->cstp_options - * with the strings containing the information we got from the server, - * and oc_ip_info contains const copies of those pointers. */ - -static const char *add_option(struct openconnect_info *vpninfo, const char *opt, - const char *val, int val_len) -{ - struct oc_vpn_option *new = malloc(sizeof(*new)); - if (!new) - return NULL; - - new->option = strdup(opt); - if (!new->option) { - free(new); - return NULL; - } - if (val_len >= 0) - new->value = strndup(val, val_len); - else - new->value = strdup(val); - if (!new->value) { - free(new->option); - free(new); - return NULL; - } - new->next = vpninfo->cstp_options; - vpninfo->cstp_options = new; - - return new->value; -} - static int process_attr(struct openconnect_info *vpninfo, int group, int attr, unsigned char *data, int attrlen) { @@ -122,7 +91,7 @@ static int process_attr(struct openconnect_info *vpninfo, int group, int attr, for (i = 0; i < 3; i++) { if (!vpninfo->ip_info.dns[i]) { - vpninfo->ip_info.dns[i] = add_option(vpninfo, "DNS", buf, -1); + vpninfo->ip_info.dns[i] = add_option_dup(vpninfo, "DNS", buf, -1); break; } } @@ -131,7 +100,7 @@ static int process_attr(struct openconnect_info *vpninfo, int group, int attr, case GRP_ATTR(2, 2): vpn_progress(vpninfo, PRG_DEBUG, _("Received DNS search domain %.*s\n"), attrlen, (char *)data); - vpninfo->ip_info.domain = add_option(vpninfo, "search", (char *)data, attrlen); + vpninfo->ip_info.domain = add_option_dup(vpninfo, "search", (char *)data, attrlen); if (vpninfo->ip_info.domain) { char *p = (char *)vpninfo->ip_info.domain; while ((p = strchr(p, ','))) @@ -145,7 +114,7 @@ static int process_attr(struct openconnect_info *vpninfo, int group, int attr, snprintf(buf, sizeof(buf), "%d.%d.%d.%d", data[0], data[1], data[2], data[3]); vpn_progress(vpninfo, PRG_DEBUG, _("Received internal IP address %s\n"), buf); - vpninfo->ip_info.addr = add_option(vpninfo, "ipaddr", buf, -1); + vpninfo->ip_info.addr = add_option_dup(vpninfo, "ipaddr", buf, -1); break; case GRP_ATTR(1, 2): @@ -154,7 +123,7 @@ static int process_attr(struct openconnect_info *vpninfo, int group, int attr, snprintf(buf, sizeof(buf), "%d.%d.%d.%d", data[0], data[1], data[2], data[3]); vpn_progress(vpninfo, PRG_DEBUG, _("Received netmask %s\n"), buf); - vpninfo->ip_info.netmask = add_option(vpninfo, "netmask", buf, -1); + vpninfo->ip_info.netmask = add_option_dup(vpninfo, "netmask", buf, -1); break; case GRP_ATTR(1, 3): @@ -165,7 +134,7 @@ static int process_attr(struct openconnect_info *vpninfo, int group, int attr, vpn_progress(vpninfo, PRG_DEBUG, _("Received internal gateway address %s\n"), buf); /* Hm, what are we supposed to do with this? It's a tunnel; having a gateway is meaningless. */ - add_option(vpninfo, "ipaddr", buf, -1); + add_option_dup(vpninfo, "ipaddr", buf, -1); break; case GRP_ATTR(3, 3): { @@ -180,7 +149,7 @@ static int process_attr(struct openconnect_info *vpninfo, int group, int attr, break; inc = malloc(sizeof(*inc)); if (inc) { - inc->route = add_option(vpninfo, "split-include", buf, -1); + inc->route = add_option_dup(vpninfo, "split-include", buf, -1); if (inc->route) { inc->next = vpninfo->ip_info.split_includes; vpninfo->ip_info.split_includes = inc; @@ -202,7 +171,7 @@ static int process_attr(struct openconnect_info *vpninfo, int group, int attr, break; exc = malloc(sizeof(*exc)); if (exc) { - exc->route = add_option(vpninfo, "split-exclude", buf, -1); + exc->route = add_option_dup(vpninfo, "split-exclude", buf, -1); if (exc->route) { exc->next = vpninfo->ip_info.split_excludes; vpninfo->ip_info.split_excludes = exc; @@ -221,7 +190,7 @@ static int process_attr(struct openconnect_info *vpninfo, int group, int attr, for (i = 0; i < 3; i++) { if (!vpninfo->ip_info.nbns[i]) { - vpninfo->ip_info.nbns[i] = add_option(vpninfo, "WINS", buf, -1); + vpninfo->ip_info.nbns[i] = add_option_dup(vpninfo, "WINS", buf, -1); break; } } diff --git a/openconnect-internal.h b/openconnect-internal.h index e3a8a758..3ee725f2 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -1280,6 +1280,8 @@ int digest_authorization(struct openconnect_info *vpninfo, int proxy, struct htt /* library.c */ void nuke_opt_values(struct oc_form_opt *opt); +const char *add_option_dup(struct openconnect_info *vpninfo, const char *opt, const char *val, int val_len); +const char *add_option_steal(struct openconnect_info *vpninfo, const char *opt, char **val); void free_optlist(struct oc_vpn_option *opt); int process_auth_form(struct openconnect_info *vpninfo, struct oc_auth_form *form); /* This is private for now since we haven't yet worked out what the API will be */ diff --git a/pulse.c b/pulse.c index c07b21b5..4181896c 100644 --- a/pulse.c +++ b/pulse.c @@ -217,37 +217,6 @@ static int valid_ift_auth_eap_exj1(unsigned char *bytes, int len) return 1; } -/* We behave like CSTP — create a linked list in vpninfo->cstp_options - * with the strings containing the information we got from the server, - * and oc_ip_info contains const copies of those pointers. */ - -static const char *add_option(struct openconnect_info *vpninfo, const char *opt, - const char *val, int val_len) -{ - struct oc_vpn_option *new = malloc(sizeof(*new)); - if (!new) - return NULL; - - new->option = strdup(opt); - if (!new->option) { - free(new); - return NULL; - } - if (val_len >= 0) - new->value = strndup(val, val_len); - else - new->value = strdup(val); - if (!new->value) { - free(new->option); - free(new); - return NULL; - } - new->next = vpninfo->cstp_options; - vpninfo->cstp_options = new; - - return new->value; -} - static int process_attr(struct openconnect_info *vpninfo, uint16_t type, unsigned char *data, int attrlen) { @@ -263,7 +232,7 @@ static int process_attr(struct openconnect_info *vpninfo, uint16_t type, snprintf(buf, sizeof(buf), "%d.%d.%d.%d", data[0], data[1], data[2], data[3]); vpn_progress(vpninfo, PRG_DEBUG, _("Received internal Legacy IP address %s\n"), buf); - vpninfo->ip_info.addr = add_option(vpninfo, "ipaddr", buf, -1); + vpninfo->ip_info.addr = add_option_dup(vpninfo, "ipaddr", buf, -1); break; case 0x0002: @@ -272,7 +241,7 @@ static int process_attr(struct openconnect_info *vpninfo, uint16_t type, snprintf(buf, sizeof(buf), "%d.%d.%d.%d", data[0], data[1], data[2], data[3]); vpn_progress(vpninfo, PRG_DEBUG, _("Received netmask %s\n"), buf); - vpninfo->ip_info.netmask = add_option(vpninfo, "netmask", buf, -1); + vpninfo->ip_info.netmask = add_option_dup(vpninfo, "netmask", buf, -1); break; case 0x0003: @@ -284,7 +253,7 @@ static int process_attr(struct openconnect_info *vpninfo, uint16_t type, for (i = 0; i < 3; i++) { if (!vpninfo->ip_info.dns[i]) { - vpninfo->ip_info.dns[i] = add_option(vpninfo, "DNS", buf, -1); + vpninfo->ip_info.dns[i] = add_option_dup(vpninfo, "DNS", buf, -1); break; } } @@ -299,7 +268,7 @@ static int process_attr(struct openconnect_info *vpninfo, uint16_t type, for (i = 0; i < 3; i++) { if (!vpninfo->ip_info.nbns[i]) { - vpninfo->ip_info.nbns[i] = add_option(vpninfo, "WINS", buf, -1); + vpninfo->ip_info.nbns[i] = add_option_dup(vpninfo, "WINS", buf, -1); break; } } @@ -313,11 +282,11 @@ static int process_attr(struct openconnect_info *vpninfo, uint16_t type, _("Failed to handle IPv6 address\n")); return -EINVAL; } - vpninfo->ip_info.addr6 = add_option(vpninfo, "ip6addr", buf, -1); + vpninfo->ip_info.addr6 = add_option_dup(vpninfo, "ip6addr", buf, -1); i = strlen(buf); snprintf(buf + i, sizeof(buf) - i, "/%d", data[16]); - vpninfo->ip_info.netmask6 = add_option(vpninfo, "ip6netmask", buf, -1); + vpninfo->ip_info.netmask6 = add_option_dup(vpninfo, "ip6netmask", buf, -1); vpn_progress(vpninfo, PRG_DEBUG, _("Received internal IPv6 address %s\n"), buf); break; @@ -333,7 +302,7 @@ static int process_attr(struct openconnect_info *vpninfo, uint16_t type, for (i = 0; i < 3; i++) { if (!vpninfo->ip_info.dns[i]) { - vpninfo->ip_info.dns[i] = add_option(vpninfo, "DNS", buf, -1); + vpninfo->ip_info.dns[i] = add_option_dup(vpninfo, "DNS", buf, -1); break; } } @@ -354,7 +323,7 @@ static int process_attr(struct openconnect_info *vpninfo, uint16_t type, xc = malloc(sizeof(*xc)); if (xc) { - xc->route = add_option(vpninfo, "split-include6", buf, -1); + xc->route = add_option_dup(vpninfo, "split-include6", buf, -1); if (xc->route) { xc->next = vpninfo->ip_info.split_includes; vpninfo->ip_info.split_includes = xc; @@ -377,7 +346,7 @@ static int process_attr(struct openconnect_info *vpninfo, uint16_t type, xc = malloc(sizeof(*xc)); if (xc) { - xc->route = add_option(vpninfo, "split-exclude6", buf, -1); + xc->route = add_option_dup(vpninfo, "split-exclude6", buf, -1); if (xc->route) { xc->next = vpninfo->ip_info.split_excludes; vpninfo->ip_info.split_excludes = xc; @@ -408,7 +377,7 @@ static int process_attr(struct openconnect_info *vpninfo, uint16_t type, attrlen--; vpn_progress(vpninfo, PRG_DEBUG, _("Received DNS search domain %.*s\n"), attrlen, (char *)data); - vpninfo->ip_info.domain = add_option(vpninfo, "search", (char *)data, attrlen); + vpninfo->ip_info.domain = add_option_dup(vpninfo, "search", (char *)data, attrlen); if (vpninfo->ip_info.domain) { char *p = (char *)vpninfo->ip_info.domain; while ((p = strchr(p, ','))) @@ -424,7 +393,7 @@ static int process_attr(struct openconnect_info *vpninfo, uint16_t type, vpn_progress(vpninfo, PRG_DEBUG, _("Received internal gateway address %s\n"), buf); /* Hm, what are we supposed to do with this? It's a tunnel; having a gateway is meaningless. */ - add_option(vpninfo, "ipaddr", buf, -1); + add_option_dup(vpninfo, "ipaddr", buf, -1); break; case 0x4010: { @@ -2334,7 +2303,7 @@ static int handle_main_config_packet(struct openconnect_info *vpninfo, vpn_progress(vpninfo, PRG_DEBUG, _("Received split include route %s\n"), buf); inc = malloc(sizeof(*inc)); if (inc) { - inc->route = add_option(vpninfo, "split-include", buf, -1); + inc->route = add_option_dup(vpninfo, "split-include", buf, -1); if (inc->route) { inc->next = vpninfo->ip_info.split_includes; vpninfo->ip_info.split_includes = inc; @@ -2347,7 +2316,7 @@ static int handle_main_config_packet(struct openconnect_info *vpninfo, vpn_progress(vpninfo, PRG_DEBUG, _("Received split exclude route %s\n"), buf); exc = malloc(sizeof(*exc)); if (exc) { - exc->route = add_option(vpninfo, "split-exclude", buf, -1); + exc->route = add_option_dup(vpninfo, "split-exclude", buf, -1); if (exc->route) { exc->next = vpninfo->ip_info.split_excludes; vpninfo->ip_info.split_excludes = exc; -- 2.51.0