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)
{
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);
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)
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);
}
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;
}
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:
<?xml version="1.0" encoding="utf-8"?>
<sslvpn-tunnel ver="2" dtls="1" patch="1">
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);
}
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;
}
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);
}
}
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);
{ .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;
/* 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)
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)
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")) {
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;
}
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;
}
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 */
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;
#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)
{
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;
}
}
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, ',')))
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):
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):
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): {
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;
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;
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;
}
}
/* 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 */
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)
{
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:
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:
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;
}
}
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;
}
}
_("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;
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;
}
}
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;
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;
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, ',')))
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: {
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;
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;