transport.c 3.11 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
/*
 *	BIRD -- The Resource Public Key Infrastructure (RPKI) to Router Protocol
 *
 *	(c) 2015 CZ.NIC
 *	(c) 2015 Pavel Tvrdik <pawel.tvrdik@gmail.com>
 *
 *	This file was a part of RTRlib: http://rpki.realmv6.org/
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 */

#include <sys/socket.h>
#include <netdb.h>

#include "rpki.h"
#include "transport.h"
#include "sysdep/unix/unix.h"

/**
 * rpki_hostname_autoresolv - auto-resolve an IP address from a hostname
 * @host: domain name of host, e.g. "rpki-validator.realmv6.org"
 *
 * This function resolves an IP address from a hostname.
 * Returns &ip_addr structure with IP address or |IPA_NONE|.
 */
static ip_addr
rpki_hostname_autoresolv(const char *host)
{
  struct addrinfo *res;
  struct addrinfo hints = {
      .ai_family = AF_UNSPEC,
      .ai_socktype = SOCK_STREAM,
      .ai_flags = AI_ADDRCONFIG,
  };

  if (!host)
    return IPA_NONE;

  int err_code = getaddrinfo(host, NULL, &hints, &res);
  if (err_code != 0)
  {
    log(L_DEBUG "getaddrinfo failed: %s", gai_strerror(err_code));
    return IPA_NONE;
  }

46
  ip_addr addr = IPA_NONE;
47
  uint unused;
48 49

  sockaddr_read((sockaddr *) res->ai_addr, res->ai_family, &addr, NULL, &unused);
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132

  freeaddrinfo(res);
  return addr;
}

/**
 * rpki_tr_open - prepare and open a socket connection
 * @tr: initialized transport socket
 *
 * Prepare and open a socket connection specified by @tr that must be initialized before.
 * This function ends with a calling the sk_open() function.
 * Returns RPKI_TR_SUCCESS or RPKI_TR_ERROR.
 */
int
rpki_tr_open(struct rpki_tr_sock *tr)
{
  struct rpki_cache *cache = tr->cache;
  struct rpki_config *cf = (void *) cache->p->p.cf;

  ASSERT(tr->sk == NULL);
  tr->sk = sk_new(cache->pool);
  sock *sk = tr->sk;

  /* sk->type -1 is invalid value, a correct value MUST be set in the specific transport layer in open_fp() hook */
  sk->type = -1;

  sk->tx_hook = rpki_connected_hook;
  sk->err_hook = rpki_err_hook;
  sk->data = cache;
  sk->daddr = cf->ip;
  sk->dport = cf->port;
  sk->host = cf->hostname;
  sk->rbsize = RPKI_RX_BUFFER_SIZE;
  sk->tbsize = RPKI_TX_BUFFER_SIZE;
  sk->tos = IP_PREC_INTERNET_CONTROL;

  if (ipa_zero2(sk->daddr) && sk->host)
  {
    sk->daddr = rpki_hostname_autoresolv(sk->host);
    if (ipa_zero(sk->daddr))
    {
      CACHE_TRACE(D_EVENTS, cache, "Cannot resolve the hostname '%s'", sk->host);
      return RPKI_TR_ERROR;
    }
  }

  return tr->open_fp(tr);
}

/**
 * rpki_tr_close - close socket and prepare it for possible next open
 * @tr: successfully opened transport socket
 *
 * Close socket and free resources.
 */
void
rpki_tr_close(struct rpki_tr_sock *tr)
{
  if (tr->ident)
  {
    mb_free((char *) tr->ident);
    tr->ident = NULL;
  }

  if (tr->sk)
  {
    rfree(tr->sk);
    tr->sk = NULL;
  }
}

/**
 * rpki_tr_ident - Returns a string identifier for the rpki transport socket
 * @tr: successfully opened transport socket
 *
 * Returns a \0 terminated string identifier for the socket endpoint, e.g. "<host>:<port>".
 * Memory is allocated inside @tr structure.
 */
inline const char *
rpki_tr_ident(struct rpki_tr_sock *tr)
{
  return tr->ident_fp(tr);
}