static void ifconfig_pool_list(const struct ifconfig_pool *pool, struct status_output *out) { if (pool && out) { struct gc_arena gc = gc_new(); int i; for (i = 0; i < pool->size; ++i) { const struct ifconfig_pool_entry *e = &pool->list[i]; if (e->common_name) { const in_addr_t ip = ifconfig_pool_handle_to_ip_base(pool, i); if (pool->ipv6) { struct in6_addr ip6 = ifconfig_pool_handle_to_ipv6_base(pool, i); status_printf(out, "%s,%s,%s", e->common_name, print_in_addr_t(ip, 0, &gc), print_in6_addr(ip6, 0, &gc)); } else { status_printf(out, "%s,%s", e->common_name, print_in_addr_t(ip, 0, &gc)); } } } gc_free(&gc); } }
bool send_push_reply (struct context *c) { struct gc_arena gc = gc_new (); struct buffer buf = alloc_buf_gc (MAX_PUSH_LIST_LEN + 256, &gc); bool ret = false; buf_printf (&buf, "PUSH_REPLY"); if (c->options.push_list && strlen (c->options.push_list->options)) buf_printf (&buf, ",%s", c->options.push_list->options); if (c->c2.push_ifconfig_defined && c->c2.push_ifconfig_local && c->c2.push_ifconfig_remote_netmask) buf_printf (&buf, ",ifconfig %s %s", print_in_addr_t (c->c2.push_ifconfig_local, 0, &gc), print_in_addr_t (c->c2.push_ifconfig_remote_netmask, 0, &gc)); if (strlen (BSTR (&buf)) < MAX_PUSH_LIST_LEN) ret = send_control_channel_string (c, BSTR (&buf), D_PUSH); else msg (M_WARN, "Maximum length of --push buffer (%d) has been exceeded", MAX_PUSH_LIST_LEN); gc_free (&gc); return ret; }
static void pf_addr_test_print(const char *prefix, const char *prefix2, const struct context *src, const struct mroute_addr *dest, const bool allow, const struct ipv4_subnet *rule) { struct gc_arena gc = gc_new(); if (rule) { dmsg(D_PF_DEBUG, "PF: %s/%s %s %s %s rule=[%s/%s %s]", prefix, prefix2, tls_common_name(src->c2.tls_multi, false), mroute_addr_print_ex(dest, MAPF_SHOW_ARP, &gc), drop_accept(allow), print_in_addr_t(rule->network, 0, &gc), print_in_addr_t(rule->netmask, 0, &gc), drop_accept(!rule->exclude)); } else { dmsg(D_PF_DEBUG, "PF: %s/%s %s %s %s", prefix, prefix2, tls_common_name(src->c2.tls_multi, false), mroute_addr_print_ex(dest, MAPF_SHOW_ARP, &gc), drop_accept(allow)); } gc_free(&gc); }
const char * mroute_addr_print_ex (const struct mroute_addr *ma, const unsigned int flags, struct gc_arena *gc) { struct buffer out = alloc_buf_gc (64, gc); if (ma) { struct mroute_addr maddr = *ma; switch (maddr.type & MR_ADDR_MASK) { case MR_ADDR_ETHER: buf_printf (&out, "%s", format_hex_ex (ma->addr, 6, 0, 1, ":", gc)); break; case MR_ADDR_IPV4: { struct buffer buf; in_addr_t addr; int port; bool status; buf_set_read (&buf, maddr.addr, maddr.len); addr = buf_read_u32 (&buf, &status); if (status) { if ((flags & MAPF_SHOW_ARP) && (maddr.type & MR_ARP)) buf_printf (&out, "ARP/"); buf_printf (&out, "%s", print_in_addr_t (addr, (flags & MAPF_IA_EMPTY_IF_UNDEF) ? IA_EMPTY_IF_UNDEF : 0, gc)); if (maddr.type & MR_WITH_NETBITS) { if (flags & MAPF_SUBNET) { const in_addr_t netmask = netbits_to_netmask (maddr.netbits); buf_printf (&out, "/%s", print_in_addr_t (netmask, 0, gc)); } else buf_printf (&out, "/%d", maddr.netbits); } } if (maddr.type & MR_WITH_PORT) { port = buf_read_u16 (&buf); if (port >= 0) buf_printf (&out, ":%d", port); } } break; case MR_ADDR_IPV6: buf_printf (&out, "IPV6"); break; default: buf_printf (&out, "UNKNOWN"); break; } return BSTR (&out); } else return "[NULL]"; }
static void helper_add_route (const in_addr_t network, const in_addr_t netmask, struct options *o) { rol_check_alloc (o); add_route_to_option_list (o->routes, print_in_addr_t (network, 0, &o->gc), print_in_addr_t (netmask, 0, &o->gc), NULL, NULL); }
static void verify_common_subnet (const char *opt, const in_addr_t a, const in_addr_t b, const in_addr_t subnet) { struct gc_arena gc = gc_new (); if ((a & subnet) != (b & subnet)) msg (M_USAGE, "%s IP addresses %s and %s are not in the same %s subnet", opt, print_in_addr_t (a, 0, &gc), print_in_addr_t (b, 0, &gc), print_in_addr_t (subnet, 0, &gc)); gc_free (&gc); }
static const char * print_opt_route (const in_addr_t network, const in_addr_t netmask, struct gc_arena *gc) { struct buffer out = alloc_buf_gc (128, gc); ASSERT (network); if (netmask) buf_printf (&out, "route %s %s", print_in_addr_t (network, 0, gc), print_in_addr_t (netmask, 0, gc)); else buf_printf (&out, "route %s", print_in_addr_t (network, 0, gc)); return BSTR (&out); }
struct ifconfig_pool * ifconfig_pool_init(int type, in_addr_t start, in_addr_t end, const bool duplicate_cn, const bool ipv6_pool, const struct in6_addr ipv6_base, const int ipv6_netbits ) { struct gc_arena gc = gc_new(); struct ifconfig_pool *pool = NULL; ASSERT(start <= end && end - start < IFCONFIG_POOL_MAX); ALLOC_OBJ_CLEAR(pool, struct ifconfig_pool); pool->type = type; pool->duplicate_cn = duplicate_cn; switch (type) { case IFCONFIG_POOL_30NET: pool->base = start & ~3; pool->size = (((end | 3) + 1) - pool->base) >> 2; break; case IFCONFIG_POOL_INDIV: pool->base = start; pool->size = end - start + 1; break; default: ASSERT(0); } /* IPv6 pools are always "INDIV" type */ pool->ipv6 = ipv6_pool; if (pool->ipv6) { pool->base_ipv6 = ipv6_base; pool->size_ipv6 = ipv6_netbits>96 ? ( 1<<(128-ipv6_netbits) ) : IFCONFIG_POOL_MAX; msg( D_IFCONFIG_POOL, "IFCONFIG POOL IPv6: (IPv4) size=%d, size_ipv6=%d, netbits=%d, base_ipv6=%s", pool->size, pool->size_ipv6, ipv6_netbits, print_in6_addr( pool->base_ipv6, 0, &gc )); /* the current code is very simple and assumes that the IPv6 * pool is at least as big as the IPv4 pool, and we don't need * to do separate math etc. for IPv6 */ ASSERT( pool->size < pool->size_ipv6 ); } ALLOC_ARRAY_CLEAR(pool->list, struct ifconfig_pool_entry, pool->size); msg(D_IFCONFIG_POOL, "IFCONFIG POOL: base=%s size=%d, ipv6=%d", print_in_addr_t(pool->base, 0, &gc), pool->size, pool->ipv6 ); gc_free(&gc); return pool; }
static const char * print_opt_route_gateway (const in_addr_t route_gateway, struct gc_arena *gc) { struct buffer out = alloc_buf_gc (128, gc); ASSERT (route_gateway); buf_printf (&out, "route-gateway %s", print_in_addr_t (route_gateway, 0, gc)); return BSTR (&out); }
static const char * print_netmask (int netbits, struct gc_arena *gc) { struct buffer out = alloc_buf_gc (128, gc); const in_addr_t netmask = netbits_to_netmask (netbits); buf_printf (&out, "%s (/%d)", print_in_addr_t (netmask, 0, gc), netbits); return BSTR (&out); }
static void pf_subnet_set_print(const struct pf_subnet_set *s, const int lev) { struct gc_arena gc = gc_new(); if (s) { struct pf_subnet *e; msg(lev, " ----- struct pf_subnet_set -----"); msg(lev, " default_allow=%s", drop_accept(s->default_allow)); for (e = s->list; e != NULL; e = e->next) { msg(lev, " %s/%s %s", print_in_addr_t(e->rule.network, 0, &gc), print_in_addr_t(e->rule.netmask, 0, &gc), drop_accept(!e->rule.exclude)); } } gc_free(&gc); }
void print_client_nat_list(const struct client_nat_option_list *list, int msglevel) { struct gc_arena gc = gc_new(); int i; msg(msglevel, "*** CNAT list"); if (list) { for (i = 0; i < list->n; ++i) { const struct client_nat_entry *e = &list->entries[i]; msg(msglevel, " CNAT[%d] t=%d %s/%s/%s", i, e->type, print_in_addr_t(e->network, IA_NET_ORDER, &gc), print_in_addr_t(e->netmask, IA_NET_ORDER, &gc), print_in_addr_t(e->foreign_network, IA_NET_ORDER, &gc)); } } gc_free(&gc); }
static void print_pkt(struct openvpn_iphdr *iph, const char *prefix, const int direction, const int msglevel) { struct gc_arena gc = gc_new(); char *dirstr = "???"; if (direction == CN_OUTGOING) { dirstr = "OUT"; } else if (direction == CN_INCOMING) { dirstr = "IN"; } msg(msglevel, "** CNAT %s %s %s -> %s", dirstr, prefix, print_in_addr_t(iph->saddr, IA_NET_ORDER, &gc), print_in_addr_t(iph->daddr, IA_NET_ORDER, &gc)); gc_free(&gc); }
/* * Verify start/end range */ bool ifconfig_pool_verify_range(const int msglevel, const in_addr_t start, const in_addr_t end) { struct gc_arena gc = gc_new(); bool ret = true; if (start > end) { msg(msglevel, "--ifconfig-pool start IP [%s] is greater than end IP [%s]", print_in_addr_t(start, 0, &gc), print_in_addr_t(end, 0, &gc)); ret = false; } if (end - start >= IFCONFIG_POOL_MAX) { msg(msglevel, "--ifconfig-pool address range is too large [%s -> %s]. Current maximum is %d addresses, as defined by IFCONFIG_POOL_MAX variable.", print_in_addr_t(start, 0, &gc), print_in_addr_t(end, 0, &gc), IFCONFIG_POOL_MAX); ret = false; } gc_free(&gc); return ret; }
/* * Process server, server-bridge, and client helper * directives after the parameters themselves have been * parsed and placed in struct options. */ void helper_client_server (struct options *o) { struct gc_arena gc = gc_new (); #if P2MP #if P2MP_SERVER /* * Get tun/tap/null device type */ const int dev = dev_type_enum (o->dev, o->dev_type); const int topology = o->topology; /* * * HELPER DIRECTIVE for IPv6 * * server-ipv6 2001:db8::/64 * * EXPANDS TO: * * tun-ipv6 * push "tun-ipv6" * ifconfig-ipv6 2001:db8::1 2001:db8::2 * if !nopool: * ifconfig-ipv6-pool 2001:db8::1:0/64 * */ if ( o->server_ipv6_defined ) { if ( ! o->server_defined ) { msg (M_USAGE, "--server-ipv6 must be used together with --server"); } if ( o->server_flags & SF_NOPOOL ) { msg( M_USAGE, "--server-ipv6 is incompatible with 'nopool' option" ); } if ( o->ifconfig_ipv6_pool_defined ) { msg( M_USAGE, "--server-ipv6 already defines an ifconfig-ipv6-pool, so you can't also specify --ifconfig-pool explicitly"); } /* local ifconfig is "base address + 1" and "+2" */ o->ifconfig_ipv6_local = print_in6_addr( add_in6_addr( o->server_network_ipv6, 1), 0, &o->gc ); o->ifconfig_ipv6_remote = print_in6_addr( add_in6_addr( o->server_network_ipv6, 2), 0, &o->gc ); o->ifconfig_ipv6_netbits = o->server_netbits_ipv6; /* pool starts at "base address + 0x1000" - leave enough room */ ASSERT( o->server_netbits_ipv6 <= 112 ); /* want 16 bits */ o->ifconfig_ipv6_pool_defined = true; o->ifconfig_ipv6_pool_base = add_in6_addr( o->server_network_ipv6, 0x1000 ); o->ifconfig_ipv6_pool_netbits = o->server_netbits_ipv6; o->tun_ipv6 = true; push_option( o, "tun-ipv6", M_USAGE ); } /* * * HELPER DIRECTIVE: * * server 10.8.0.0 255.255.255.0 * * EXPANDS TO: * * mode server * tls-server * push "topology [topology]" * * if tun AND (topology == net30 OR topology == p2p): * ifconfig 10.8.0.1 10.8.0.2 * if !nopool: * ifconfig-pool 10.8.0.4 10.8.0.251 * route 10.8.0.0 255.255.255.0 * if client-to-client: * push "route 10.8.0.0 255.255.255.0" * else if topology == net30: * push "route 10.8.0.1" * * if tap OR (tun AND topology == subnet): * ifconfig 10.8.0.1 255.255.255.0 * if !nopool: * ifconfig-pool 10.8.0.2 10.8.0.254 255.255.255.0 * push "route-gateway 10.8.0.1" * if route-gateway unset: * route-gateway 10.8.0.2 */ if (o->server_defined) { int netbits = -2; bool status = false; if (o->client) msg (M_USAGE, "--server and --client cannot be used together"); if (o->server_bridge_defined || o->server_bridge_proxy_dhcp) msg (M_USAGE, "--server and --server-bridge cannot be used together"); if (o->shared_secret_file) msg (M_USAGE, "--server and --secret cannot be used together (you must use SSL/TLS keys)"); if (!(o->server_flags & SF_NOPOOL) && o->ifconfig_pool_defined) msg (M_USAGE, "--server already defines an ifconfig-pool, so you can't also specify --ifconfig-pool explicitly"); if (!(dev == DEV_TYPE_TAP || dev == DEV_TYPE_TUN)) msg (M_USAGE, "--server directive only makes sense with --dev tun or --dev tap"); status = netmask_to_netbits (o->server_network, o->server_netmask, &netbits); if (!status) msg (M_USAGE, "--server directive network/netmask combination is invalid"); if (netbits < 0) msg (M_USAGE, "--server directive netmask is invalid"); if (netbits < IFCONFIG_POOL_MIN_NETBITS) msg (M_USAGE, "--server directive netmask allows for too many host addresses (subnet must be %s or higher)", print_netmask (IFCONFIG_POOL_MIN_NETBITS, &gc)); if (dev == DEV_TYPE_TUN) { int pool_end_reserve = 4; if (netbits > 29) msg (M_USAGE, "--server directive when used with --dev tun must define a subnet of %s or lower", print_netmask (29, &gc)); if (netbits == 29) pool_end_reserve = 0; o->mode = MODE_SERVER; o->tls_server = true; if (topology == TOP_NET30 || topology == TOP_P2P) { o->ifconfig_local = print_in_addr_t (o->server_network + 1, 0, &o->gc); o->ifconfig_remote_netmask = print_in_addr_t (o->server_network + 2, 0, &o->gc); if (!(o->server_flags & SF_NOPOOL)) { o->ifconfig_pool_defined = true; o->ifconfig_pool_start = o->server_network + 4; o->ifconfig_pool_end = (o->server_network | ~o->server_netmask) - pool_end_reserve; ifconfig_pool_verify_range (M_USAGE, o->ifconfig_pool_start, o->ifconfig_pool_end); } helper_add_route (o->server_network, o->server_netmask, o); if (o->enable_c2c) push_option (o, print_opt_route (o->server_network, o->server_netmask, &o->gc), M_USAGE); else if (topology == TOP_NET30) push_option (o, print_opt_route (o->server_network + 1, 0, &o->gc), M_USAGE); } else if (topology == TOP_SUBNET) { o->ifconfig_local = print_in_addr_t (o->server_network + 1, 0, &o->gc); o->ifconfig_remote_netmask = print_in_addr_t (o->server_netmask, 0, &o->gc); if (!(o->server_flags & SF_NOPOOL)) { o->ifconfig_pool_defined = true; o->ifconfig_pool_start = o->server_network + 2; o->ifconfig_pool_end = (o->server_network | ~o->server_netmask) - 2; ifconfig_pool_verify_range (M_USAGE, o->ifconfig_pool_start, o->ifconfig_pool_end); } o->ifconfig_pool_netmask = o->server_netmask; push_option (o, print_opt_route_gateway (o->server_network + 1, &o->gc), M_USAGE); if (!o->route_default_gateway) o->route_default_gateway = print_in_addr_t (o->server_network + 2, 0, &o->gc); } else ASSERT (0); push_option (o, print_opt_topology (topology, &o->gc), M_USAGE); } else if (dev == DEV_TYPE_TAP) { if (netbits > 30) msg (M_USAGE, "--server directive when used with --dev tap must define a subnet of %s or lower", print_netmask (30, &gc)); o->mode = MODE_SERVER; o->tls_server = true; o->ifconfig_local = print_in_addr_t (o->server_network + 1, 0, &o->gc); o->ifconfig_remote_netmask = print_in_addr_t (o->server_netmask, 0, &o->gc); if (!(o->server_flags & SF_NOPOOL)) { o->ifconfig_pool_defined = true; o->ifconfig_pool_start = o->server_network + 2; o->ifconfig_pool_end = (o->server_network | ~o->server_netmask) - 1; ifconfig_pool_verify_range (M_USAGE, o->ifconfig_pool_start, o->ifconfig_pool_end); } o->ifconfig_pool_netmask = o->server_netmask; push_option (o, print_opt_route_gateway (o->server_network + 1, &o->gc), M_USAGE); } else { ASSERT (0); } /* set push-ifconfig-constraint directive */ if ((dev == DEV_TYPE_TAP || topology == TOP_SUBNET)) { o->push_ifconfig_constraint_defined = true; o->push_ifconfig_constraint_network = o->server_network; o->push_ifconfig_constraint_netmask = o->server_netmask; } } /* * HELPER DIRECTIVE: * * server-bridge 10.8.0.4 255.255.255.0 10.8.0.128 10.8.0.254 * * EXPANDS TO: * * mode server * tls-server * * ifconfig-pool 10.8.0.128 10.8.0.254 255.255.255.0 * push "route-gateway 10.8.0.4" * * OR * * server-bridge * * EXPANDS TO: * * mode server * tls-server * * if !nogw: * push "route-gateway dhcp" */ else if (o->server_bridge_defined | o->server_bridge_proxy_dhcp) { if (o->client) msg (M_USAGE, "--server-bridge and --client cannot be used together"); if (!(o->server_flags & SF_NOPOOL) && o->ifconfig_pool_defined) msg (M_USAGE, "--server-bridge already defines an ifconfig-pool, so you can't also specify --ifconfig-pool explicitly"); if (o->shared_secret_file) msg (M_USAGE, "--server-bridge and --secret cannot be used together (you must use SSL/TLS keys)"); if (dev != DEV_TYPE_TAP) msg (M_USAGE, "--server-bridge directive only makes sense with --dev tap"); if (o->server_bridge_defined) { verify_common_subnet ("--server-bridge", o->server_bridge_ip, o->server_bridge_pool_start, o->server_bridge_netmask); verify_common_subnet ("--server-bridge", o->server_bridge_pool_start, o->server_bridge_pool_end, o->server_bridge_netmask); verify_common_subnet ("--server-bridge", o->server_bridge_ip, o->server_bridge_pool_end, o->server_bridge_netmask); } o->mode = MODE_SERVER; o->tls_server = true; if (o->server_bridge_defined) { o->ifconfig_pool_defined = true; o->ifconfig_pool_start = o->server_bridge_pool_start; o->ifconfig_pool_end = o->server_bridge_pool_end; ifconfig_pool_verify_range (M_USAGE, o->ifconfig_pool_start, o->ifconfig_pool_end); o->ifconfig_pool_netmask = o->server_bridge_netmask; push_option (o, print_opt_route_gateway (o->server_bridge_ip, &o->gc), M_USAGE); } else if (o->server_bridge_proxy_dhcp && !(o->server_flags & SF_NO_PUSH_ROUTE_GATEWAY)) { push_option (o, print_opt_route_gateway_dhcp (&o->gc), M_USAGE); } } else #endif /* P2MP_SERVER */ /* * HELPER DIRECTIVE: * * client * * EXPANDS TO: * * pull * tls-client */ if (o->client) { if (o->key_method != 2) msg (M_USAGE, "--client requires --key-method 2"); o->pull = true; o->tls_client = true; } #endif /* P2MP */ gc_free (&gc); }
void ifconfig_pool_test(in_addr_t start, in_addr_t end) { struct gc_arena gc = gc_new(); struct ifconfig_pool *p = ifconfig_pool_init(IFCONFIG_POOL_30NET, start, end); /*struct ifconfig_pool *p = ifconfig_pool_init (IFCONFIG_POOL_INDIV, start, end);*/ ifconfig_pool_handle array[256]; int i; CLEAR(array); msg(M_INFO | M_NOPREFIX, "************ 1"); for (i = 0; i < (int) SIZE(array); ++i) { char *cn; ifconfig_pool_handle h; in_addr_t local, remote; char buf[256]; openvpn_snprintf(buf, sizeof(buf), "common-name-%d", i); #ifdef DUP_CN cn = NULL; #else cn = buf; #endif h = ifconfig_pool_acquire(p, &local, &remote, NULL, cn); if (h < 0) { break; } msg(M_INFO | M_NOPREFIX, "IFCONFIG_POOL TEST pass 1: l=%s r=%s cn=%s", print_in_addr_t(local, 0, &gc), print_in_addr_t(remote, 0, &gc), cn); array[i] = h; } msg(M_INFO | M_NOPREFIX, "************* 2"); for (i = (int) SIZE(array) / 16; i < (int) SIZE(array) / 8; ++i) { msg(M_INFO, "Attempt to release %d cn=%s", array[i], p->list[i].common_name); if (!ifconfig_pool_release(p, array[i])) { break; } msg(M_INFO, "Succeeded"); } CLEAR(array); msg(M_INFO | M_NOPREFIX, "**************** 3"); for (i = 0; i < (int) SIZE(array); ++i) { char *cn; ifconfig_pool_handle h; in_addr_t local, remote; char buf[256]; snprintf(buf, sizeof(buf), "common-name-%d", i+24); #ifdef DUP_CN cn = NULL; #else cn = buf; #endif h = ifconfig_pool_acquire(p, &local, &remote, NULL, cn); if (h < 0) { break; } msg(M_INFO | M_NOPREFIX, "IFCONFIG_POOL TEST pass 3: l=%s r=%s cn=%s", print_in_addr_t(local, 0, &gc), print_in_addr_t(remote, 0, &gc), cn); array[i] = h; } ifconfig_pool_free(p); gc_free(&gc); }
const char * mroute_addr_print_ex(const struct mroute_addr *ma, const unsigned int flags, struct gc_arena *gc) { struct buffer out = alloc_buf_gc(64, gc); if (ma) { struct mroute_addr maddr = *ma; switch (maddr.type & MR_ADDR_MASK) { case MR_ADDR_ETHER: buf_printf(&out, "%s", format_hex_ex(ma->eth_addr, sizeof(ma->eth_addr), 0, 1, ":", gc)); break; case MR_ADDR_IPV4: { if ((flags & MAPF_SHOW_ARP) && (maddr.type & MR_ARP)) { buf_printf(&out, "ARP/"); } buf_printf(&out, "%s", print_in_addr_t(ntohl(maddr.v4.addr), (flags & MAPF_IA_EMPTY_IF_UNDEF) ? IA_EMPTY_IF_UNDEF : 0, gc)); if (maddr.type & MR_WITH_NETBITS) { if (flags & MAPF_SUBNET) { const in_addr_t netmask = netbits_to_netmask(maddr.netbits); buf_printf(&out, "/%s", print_in_addr_t(netmask, 0, gc)); } else { buf_printf(&out, "/%d", maddr.netbits); } } if (maddr.type & MR_WITH_PORT) { buf_printf(&out, ":%d", ntohs(maddr.v4.port)); } } break; case MR_ADDR_IPV6: { if (IN6_IS_ADDR_V4MAPPED( &maddr.v6.addr ) ) { buf_printf(&out, "%s", print_in_addr_t(maddr.v4mappedv6.addr, IA_NET_ORDER, gc)); /* we only print port numbers for v4mapped v6 as of * today, because "v6addr:port" is too ambiguous */ if (maddr.type & MR_WITH_PORT) { buf_printf(&out, ":%d", ntohs(maddr.v6.port)); } } else { buf_printf(&out, "%s", print_in6_addr(maddr.v6.addr, 0, gc)); } if (maddr.type & MR_WITH_NETBITS) { buf_printf(&out, "/%d", maddr.netbits); } } break; default: buf_printf(&out, "UNKNOWN"); break; } return BSTR(&out); } else { return "[NULL]"; } }
/** * Prepare push options, based on local options and available peer info. * * @param context context structure storing data for VPN tunnel * @param gc gc arena for allocating push options * @param push_list push list to where options are added * * @return true on success, false on failure. */ static bool prepare_push_reply(struct context *c, struct gc_arena *gc, struct push_list *push_list) { const char *optstr = NULL; struct tls_multi *tls_multi = c->c2.tls_multi; const char *const peer_info = tls_multi->peer_info; struct options *o = &c->options; /* ipv6 */ if (c->c2.push_ifconfig_ipv6_defined && !o->push_ifconfig_ipv6_blocked) { push_option_fmt(gc, push_list, M_USAGE, "ifconfig-ipv6 %s/%d %s", print_in6_addr(c->c2.push_ifconfig_ipv6_local, 0, gc), c->c2.push_ifconfig_ipv6_netbits, print_in6_addr(c->c2.push_ifconfig_ipv6_remote, 0, gc)); } /* ipv4 */ if (c->c2.push_ifconfig_defined && c->c2.push_ifconfig_local && c->c2.push_ifconfig_remote_netmask && !o->push_ifconfig_ipv4_blocked) { in_addr_t ifconfig_local = c->c2.push_ifconfig_local; if (c->c2.push_ifconfig_local_alias) { ifconfig_local = c->c2.push_ifconfig_local_alias; } push_option_fmt(gc, push_list, M_USAGE, "ifconfig %s %s", print_in_addr_t(ifconfig_local, 0, gc), print_in_addr_t(c->c2.push_ifconfig_remote_netmask, 0, gc)); } /* Send peer-id if client supports it */ optstr = peer_info ? strstr(peer_info, "IV_PROTO=") : NULL; if (optstr) { int proto = 0; int r = sscanf(optstr, "IV_PROTO=%d", &proto); if ((r == 1) && (proto >= 2)) { push_option_fmt(gc, push_list, M_USAGE, "peer-id %d", tls_multi->peer_id); tls_multi->use_peer_id = true; } } /* Push cipher if client supports Negotiable Crypto Parameters */ if (tls_peer_info_ncp_ver(peer_info) >= 2 && o->ncp_enabled) { /* if we have already created our key, we cannot *change* our own * cipher -> so log the fact and push the "what we have now" cipher * (so the client is always told what we expect it to use) */ const struct tls_session *session = &tls_multi->session[TM_ACTIVE]; if (session->key[KS_PRIMARY].crypto_options.key_ctx_bi.initialized) { msg( M_INFO, "PUSH: client wants to negotiate cipher (NCP), but " "server has already generated data channel keys, " "re-sending previously negotiated cipher '%s'", o->ciphername ); } else { /* Push the first cipher from --ncp-ciphers to the client. * TODO: actual negotiation, instead of server dictatorship. */ char *push_cipher = string_alloc(o->ncp_ciphers, &o->gc); o->ciphername = strtok(push_cipher, ":"); } push_option_fmt(gc, push_list, M_USAGE, "cipher %s", o->ciphername); } else if (o->ncp_enabled) { tls_poor_mans_ncp(o, tls_multi->remote_ciphername); } /* If server uses --auth-gen-token and we have an auth token * to send to the client */ if (false == tls_multi->auth_token_sent && NULL != tls_multi->auth_token) { push_option_fmt(gc, push_list, M_USAGE, "auth-token %s", tls_multi->auth_token); tls_multi->auth_token_sent = true; } return true; }
bool send_push_reply (struct context *c) { struct gc_arena gc = gc_new (); struct buffer buf = alloc_buf_gc (PUSH_BUNDLE_SIZE, &gc); struct push_entry *e = c->options.push_list.head; bool multi_push = false; static char cmd[] = "PUSH_REPLY"; const int extra = 84; /* extra space for possible trailing ifconfig and push-continuation */ const int safe_cap = BCAP (&buf) - extra; bool push_sent = false; msg( M_INFO, "send_push_reply(): safe_cap=%d", safe_cap ); buf_printf (&buf, "%s", cmd); if ( c->c2.push_ifconfig_ipv6_defined ) { /* IPv6 is put into buffer first, could be lengthy */ buf_printf( &buf, ",ifconfig-ipv6 %s/%d %s", print_in6_addr( c->c2.push_ifconfig_ipv6_local, 0, &gc), c->c2.push_ifconfig_ipv6_netbits, print_in6_addr( c->c2.push_ifconfig_ipv6_remote, 0, &gc) ); if (BLEN (&buf) >= safe_cap) { msg (M_WARN, "--push ifconfig-ipv6 option is too long"); goto fail; } } while (e) { if (e->enable) { const int l = strlen (e->option); if (BLEN (&buf) + l >= safe_cap) { buf_printf (&buf, ",push-continuation 2"); { const bool status = send_control_channel_string (c, BSTR (&buf), D_PUSH); if (!status) goto fail; push_sent = true; multi_push = true; buf_reset_len (&buf); buf_printf (&buf, "%s", cmd); } } if (BLEN (&buf) + l >= safe_cap) { msg (M_WARN, "--push option is too long"); goto fail; } buf_printf (&buf, ",%s", e->option); } e = e->next; } if (c->c2.push_ifconfig_defined && c->c2.push_ifconfig_local && c->c2.push_ifconfig_remote_netmask) { in_addr_t ifconfig_local = c->c2.push_ifconfig_local; #ifdef ENABLE_CLIENT_NAT if (c->c2.push_ifconfig_local_alias) ifconfig_local = c->c2.push_ifconfig_local_alias; #endif buf_printf (&buf, ",ifconfig %s %s", print_in_addr_t (ifconfig_local, 0, &gc), print_in_addr_t (c->c2.push_ifconfig_remote_netmask, 0, &gc)); } if (multi_push) buf_printf (&buf, ",push-continuation 1"); if (BLEN (&buf) > sizeof(cmd)-1) { const bool status = send_control_channel_string (c, BSTR (&buf), D_PUSH); if (!status) goto fail; push_sent = true; } /* If nothing have been pushed, send an empty push, * as the client is expecting a response */ if (!push_sent) { bool status = false; buf_reset_len (&buf); buf_printf (&buf, "%s", cmd); status = send_control_channel_string (c, BSTR(&buf), D_PUSH); if (!status) goto fail; } gc_free (&gc); return true; fail: gc_free (&gc); return false; }
const char * mroute_addr_print_ex (const struct mroute_addr *ma, const unsigned int flags, struct gc_arena *gc) { struct buffer out = alloc_buf_gc (64, gc); if (ma) { struct mroute_addr maddr = *ma; switch (maddr.type & MR_ADDR_MASK) { case MR_ADDR_ETHER: buf_printf (&out, "%s", format_hex_ex (ma->addr, 6, 0, 1, ":", gc)); break; case MR_ADDR_IPV4: { struct buffer buf; in_addr_t addr; int port; bool status; buf_set_read (&buf, maddr.addr, maddr.len); addr = buf_read_u32 (&buf, &status); if (status) { if ((flags & MAPF_SHOW_ARP) && (maddr.type & MR_ARP)) buf_printf (&out, "ARP/"); buf_printf (&out, "%s", print_in_addr_t (addr, (flags & MAPF_IA_EMPTY_IF_UNDEF) ? IA_EMPTY_IF_UNDEF : 0, gc)); if (maddr.type & MR_WITH_NETBITS) { if (flags & MAPF_SUBNET) { const in_addr_t netmask = netbits_to_netmask (maddr.netbits); buf_printf (&out, "/%s", print_in_addr_t (netmask, 0, gc)); } else buf_printf (&out, "/%d", maddr.netbits); } } if (maddr.type & MR_WITH_PORT) { port = buf_read_u16 (&buf); if (port >= 0) buf_printf (&out, ":%d", port); } } break; case MR_ADDR_IPV6: #ifdef USE_PF_INET6 { struct buffer buf; struct sockaddr_in6 sin6; int port; char buf6[INET6_ADDRSTRLEN] = ""; CLEAR(sin6); sin6.sin6_family = AF_INET6; buf_set_read (&buf, maddr.addr, maddr.len); if (buf_read(&buf, &sin6.sin6_addr, sizeof (sin6.sin6_addr))) { if (getnameinfo((struct sockaddr *)&sin6, sizeof (struct sockaddr_in6), buf6, sizeof (buf6), NULL, 0, NI_NUMERICHOST) != 0) { buf_printf (&out, "MR_ADDR_IPV6 getnameinfo() err"); break; } buf_puts (&out, buf6); if (maddr.type & MR_WITH_NETBITS) buf_printf (&out, "/%d", maddr.netbits); if (maddr.type & MR_WITH_PORT) { port = buf_read_u16 (&buf); if (port >= 0) buf_printf (&out, ":%d", port); } } } #else /* old, pre USE_PF_INET6 code */ buf_printf (&out, "IPV6"); #endif break; default: buf_printf (&out, "UNKNOWN"); break; } return BSTR (&out); } else return "[NULL]"; }