unsigned int
mroute_extract_addr_ipv4 (struct mroute_addr *src,
			  struct mroute_addr *dest,
			  const struct buffer *buf)
{
  unsigned int ret = 0;
  if (BLEN (buf) >= 1)
    {
      switch (OPENVPN_IPH_GET_VER (*BPTR(buf)))
	{
	case 4:
	  if (BLEN (buf) >= (int) sizeof (struct openvpn_iphdr))
	    {
	      const struct openvpn_iphdr *ip = (const struct openvpn_iphdr *) BPTR (buf);

	      mroute_get_in_addr_t (src, ip->saddr, 0);
	      mroute_get_in_addr_t (dest, ip->daddr, 0);

	      /* multicast packet? */
	      if (mroute_is_mcast (ip->daddr))
		ret |= MROUTE_EXTRACT_MCAST;

	      /* IGMP message? */
	      if (ip->protocol == OPENVPN_IPPROTO_IGMP)
		ret |= MROUTE_EXTRACT_IGMP;

	      ret |= MROUTE_EXTRACT_SUCCEEDED;
	    }
	  break;
	case 6:
	  if (BLEN (buf) >= (int) sizeof (struct openvpn_ipv6hdr))
	    {
	      const struct openvpn_ipv6hdr *ipv6 = (const struct openvpn_ipv6hdr *) BPTR (buf);
#if 0				/* very basic debug */
	      struct gc_arena gc = gc_new ();
	      msg( M_INFO, "IPv6 packet! src=%s, dst=%s",
			print_in6_addr( ipv6->saddr, 0, &gc ),
			print_in6_addr( ipv6->daddr, 0, &gc ));
	      gc_free (&gc);
#endif

	      mroute_get_in6_addr (src, ipv6->saddr, 0);
	      mroute_get_in6_addr (dest, ipv6->daddr, 0);

	      if (mroute_is_mcast_ipv6 (ipv6->daddr))
		ret |= MROUTE_EXTRACT_MCAST;

	      ret |= MROUTE_EXTRACT_SUCCEEDED;
	    }
	  break;
	default:
	    msg (M_WARN, "IP packet with unknown IP version=%d seen",
	                 OPENVPN_IPH_GET_VER (*BPTR(buf)));
	}
    }
  return ret;
}
Exemple #2
0
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);
    }
}
Exemple #3
0
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;
}
Exemple #4
0
/*
 * 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);
}
Exemple #5
0
/**
 * 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;
}
Exemple #6
0
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:
	  {
	    buf_printf (&out, "%s",
		  print_in6_addr( *(struct in6_addr*)&maddr.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]";
  }
Exemple #8
0
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]";
    }
}