Commit 05476c4d authored by Ondrej Zajicek's avatar Ondrej Zajicek
Browse files

IPv4/IPv6 integrated socket code.

parent 1149aa97
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@
#include "lib/resource.h"
#include "lib/string.h"
#include "client/client.h"
#include "sysdep/unix/unix.h"

static int input_hidden_end;
static int prompt_active;
+10 −0
Original line number Diff line number Diff line
@@ -221,6 +221,16 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
			continue;

		case 'm':
			if (flags & SPECIAL) {
				if (!errno)
					continue;
				if (size < 2)
					return -1;
				*str++ = ':';
				*str++ = ' ';
				start += 2;
				size -= 2;
			}
			s = strerror(errno);
			goto str;
		case 'M':
+30 −23
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
#define _BIRD_SOCKET_H_

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

#include "lib/resource.h"

@@ -43,17 +44,21 @@ typedef struct birdsock {
  unsigned lifindex;			/* local interface that received the datagram */
  /* laddr and lifindex are valid only if SKF_LADDR_RX flag is set to request it */

  int af;				/* Address family (AF_INET, AF_INET6 or 0 for non-IP) of fd */
  int fd;				/* System-dependent data */
  int index;				/* Index in poll buffer */
  int rcv_ttl;				/* TTL of last received datagram */
  node n;
  void *rbuf_alloc, *tbuf_alloc;
  char *password;			/* Password for MD5 authentication */
  char *err;				/* Error message */
} sock;

sock *sock_new(pool *);			/* Allocate new socket */
#define sk_new(X) sock_new(X)		/* Wrapper to avoid name collision with OpenSSL */

int sk_open(sock *);			/* Open socket */
int sk_rx_ready(sock *s);
int sk_send(sock *, unsigned len);	/* Send data, <0=err, >0=ok, 0=sleep */
int sk_send_to(sock *, unsigned len, ip_addr to, unsigned port); /* sk_send to given destination */
void sk_reallocate(sock *);		/* Free and allocate tbuf & rbuf */
@@ -61,39 +66,41 @@ void sk_set_rbsize(sock *s, uint val); /* Resize RX buffer */
void sk_set_tbsize(sock *s, uint val);	/* Resize TX buffer, keeping content */
void sk_set_tbuf(sock *s, void *tbuf);	/* Switch TX buffer, NULL-> return to internal */
void sk_dump_all(void);
int sk_set_ttl(sock *s, int ttl);	/* Set transmit TTL for given socket */
int sk_set_min_ttl(sock *s, int ttl);	/* Set minimal accepted TTL for given socket */

/* Add or remove security associations for given passive socket */
int sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd);
int sk_rx_ready(sock *s);
static inline int sk_send_buffer_empty(sock *sk)
{ return sk->tbuf == sk->tpos; }

/* Prepare UDP or IP socket to multicasting. s->iface and s->ttl must be set */
int sk_setup_multicast(sock *s);	
int sk_join_group(sock *s, ip_addr maddr);
int sk_leave_group(sock *s, ip_addr maddr);

#ifdef IPV6
int sk_set_ipv6_checksum(sock *s, int offset);
int sk_set_icmp_filter(sock *s, int p1, int p2);
#define sk_is_ipv4(X) 0
#define sk_is_ipv6(X) 1
#else
#define sk_is_ipv4(X) 1
#define sk_is_ipv6(X) 0
#endif

int sk_set_broadcast(sock *s, int enable);

static inline int
sk_send_buffer_empty(sock *sk)
{
	return sk->tbuf == sk->tpos;
}
int sk_setup_multicast(sock *s);	/* Prepare UDP or IP socket for multicasting */
int sk_join_group(sock *s, ip_addr maddr);	/* Join multicast group on sk iface */
int sk_leave_group(sock *s, ip_addr maddr);	/* Leave multicast group on sk iface */
int sk_setup_broadcast(sock *s);
int sk_set_ttl(sock *s, int ttl);	/* Set transmit TTL for given socket */
int sk_set_min_ttl(sock *s, int ttl);	/* Set minimal accepted TTL for given socket */
int sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd);
int sk_set_ipv6_checksum(sock *s, int offset);
int sk_set_icmp6_filter(sock *s, int p1, int p2);
void sk_log_error(sock *s, const char *p);

extern int sk_priority_control;		/* Suggested priority for control traffic, should be sysdep define */


/* Socket flags */

#define SKF_V6ONLY	1	/* Use IPV6_V6ONLY socket option */
#define SKF_LADDR_RX	2	/* Report local address for RX packets */
#define SKF_TTL_RX	4	/* Report TTL / Hop Limit for RX packets */
#define SKF_BIND	8	/* Bind datagram socket to given source address */
#define SKF_V4ONLY	0x01	/* Use IPv4 for IP sockets */
#define SKF_V6ONLY	0x02	/* Use IPV6_V6ONLY socket option */
#define SKF_LADDR_RX	0x04	/* Report local address for RX packets */
#define SKF_TTL_RX	0x08	/* Report TTL / Hop Limit for RX packets */
#define SKF_BIND	0x10	/* Bind datagram socket to given source address */

#define SKF_THREAD	0x100	/* Socked used in thread, Do not add to main loop */
#define SKF_TRUNCATED	0x200	/* Received packet was truncated, set by IO layer */
+4 −2
Original line number Diff line number Diff line
@@ -101,8 +101,8 @@ bfd_rx_hook(sock *sk, int len)
  uint err_val = 0;
  char fb[8];

  if ((sk->sport == BFD_CONTROL_PORT) && (sk->ttl < 255))
    DROP("wrong TTL", sk->ttl);
  if ((sk->sport == BFD_CONTROL_PORT) && (sk->rcv_ttl < 255))
    DROP("wrong TTL", sk->rcv_ttl);

  if (len < BFD_BASE_LEN)
    DROP("too short", len);
@@ -209,6 +209,7 @@ bfd_open_rx_sk(struct bfd_proto *p, int multihop)
  return sk;

 err:
  sk_log_error(sk, p->p.name);
  rfree(sk);
  return NULL;
}
@@ -243,6 +244,7 @@ bfd_open_tx_sk(struct bfd_proto *p, ip_addr local, struct iface *ifa)
  return sk;

 err:
  sk_log_error(sk, p->p.name);
  rfree(sk);
  return NULL;
}
+39 −42
Original line number Diff line number Diff line
@@ -106,14 +106,11 @@ bgp_open(struct bgp_proto *p)
  struct config *cfg = p->cf->c.global;
  int errcode;

  bgp_counter++;

  if (!bgp_listen_sk)
    bgp_listen_sk = bgp_setup_listen_sk(cfg->listen_bgp_addr, cfg->listen_bgp_port, cfg->listen_bgp_flags);

  if (!bgp_listen_sk)
    {
      bgp_counter--;
      errcode = BEM_NO_SOCKET;
      goto err;
    }
@@ -121,16 +118,16 @@ bgp_open(struct bgp_proto *p)
  if (!bgp_linpool)
    bgp_linpool = lp_new(&root_pool, 4080);

  bgp_counter++;

  if (p->cf->password)
    if (sk_set_md5_auth(bgp_listen_sk, p->cf->remote_ip, p->cf->iface, p->cf->password) < 0)
      {
      int rv = sk_set_md5_auth(bgp_listen_sk, p->cf->remote_ip, p->cf->iface, p->cf->password);
      if (rv < 0)
	{
	sk_log_error(bgp_listen_sk, p->p.name);
	bgp_close(p, 0);
	errcode = BEM_INVALID_MD5;
	goto err;
      }
    }

  return 0;

@@ -194,7 +191,8 @@ bgp_close(struct bgp_proto *p, int apply_md5)
  bgp_counter--;

  if (p->cf->password && apply_md5)
    sk_set_md5_auth(bgp_listen_sk, p->cf->remote_ip, p->cf->iface, NULL);
    if (sk_set_md5_auth(bgp_listen_sk, p->cf->remote_ip, p->cf->iface, NULL) < 0)
      sk_log_error(bgp_listen_sk, p->p.name);

  if (!bgp_counter)
    {
@@ -697,25 +695,21 @@ bgp_connect(struct bgp_proto *p) /* Enter Connect state and start establishing c
  bgp_conn_set_state(conn, BS_CONNECT);

  if (sk_open(s) < 0)
    {
      bgp_sock_err(s, 0);
      return;
    }
    goto err;

  /* Set minimal receive TTL if needed */
  if (p->cf->ttl_security)
  {
    DBG("Setting minimum received TTL to %d", 256 - hops);
    if (sk_set_min_ttl(s, 256 - hops) < 0)
    {
      log(L_ERR "TTL security configuration failed, closing session");
      bgp_sock_err(s, 0);
      return;
    }
  }
      goto err;

  DBG("BGP: Waiting for connect success\n");
  bgp_start_timer(conn->connect_retry_timer, p->cf->connect_retry_time);
  return;

 err:
  sk_log_error(s, p->p.name);
  bgp_sock_err(s, 0);
  return;
}

/**
@@ -760,32 +754,33 @@ bgp_incoming_connection(sock *sk, int dummy UNUSED)
		      sk->dport, acc ? "accepted" : "rejected");

	    if (!acc)
	      goto err;
	      goto reject;

	    int hops = p->cf->multihop ? : 1;

	    if (sk_set_ttl(sk, p->cf->ttl_security ? 255 : hops) < 0)
	      goto err;

	    if (p->cf->ttl_security)
	    {
	      /* TTL security support */
	      if ((sk_set_ttl(sk, 255) < 0) ||
		  (sk_set_min_ttl(sk, 256 - hops) < 0))
	      {
		log(L_ERR "TTL security configuration failed, closing session");
	      if (sk_set_min_ttl(sk, 256 - hops) < 0)
		goto err;
	      }
	    }
	    else
	      sk_set_ttl(sk, hops);

	    bgp_setup_conn(p, &p->incoming_conn);
	    bgp_setup_sk(&p->incoming_conn, sk);
	    bgp_send_open(&p->incoming_conn);
	    return 0;

	  err:
	    sk_log_error(sk, p->p.name);
	    log(L_ERR "%s: Incoming connection aborted", p->p.name);
	    rfree(sk);
	    return 0;
	  }
      }

  log(L_WARN "BGP: Unexpected connect from unknown address %I%J (port %d)",
      sk->daddr, ipa_has_link_scope(sk->daddr) ? sk->iface : NULL, sk->dport);
 err:
 reject:
  rfree(sk);
  return 0;
}
@@ -816,13 +811,15 @@ bgp_setup_listen_sk(ip_addr addr, unsigned port, u32 flags)
  s->err_hook = bgp_listen_sock_err;

  if (sk_open(s) < 0)
    {
      log(L_ERR "BGP: Unable to open listening socket");
      rfree(s);
      return NULL;
    }
    goto err;

  return s;

 err:
  sk_log_error(s, "BGP");
  log(L_ERR "BGP: Cannot open listening socket");
  rfree(s);
  return NULL;
}

static void
Loading