]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
IO: Minor changes in socket AF handing
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Tue, 17 May 2016 13:21:49 +0000 (15:21 +0200)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Tue, 17 May 2016 13:21:49 +0000 (15:21 +0200)
AF can be specified implicitly by saddr or daddr, flags SKF_V4ONLY and
SKF_V6ONLY are to be removed.

lib/socket.h
proto/bfd/bfd.c
proto/bfd/packets.c
proto/ospf/iface.c
proto/radv/packets.c
proto/rip/config.Y
proto/rip/packets.c
sysdep/linux/sysio.h
sysdep/unix/io.c
sysdep/unix/unix.h

index d12ea3c5e6825687cc118e6729cf1dc92fe4674c..7d1aa7efc0070baca2702a8d4fe5ce89d1f454ff 100644 (file)
@@ -17,6 +17,7 @@ typedef struct birdsock {
   resource r;
   pool *pool;                          /* Pool where incoming connections should be allocated (for SK_xxx_PASSIVE) */
   int type;                            /* Socket type */
+  int subtype;                         /* Socket subtype */
   void *data;                          /* User data */
   ip_addr saddr, daddr;                        /* IPA_NONE = unspecified */
   uint sport, dport;                   /* 0 = unspecified (for IP: protocol type) */
@@ -44,7 +45,7 @@ typedef struct birdsock {
   uint lifindex;                       /* local interface that received the datagram */
   /* laddr and lifindex are valid only if SKF_LADDR_RX flag is set to request it */
 
-  int fam;                             /* Address family (SK_FAM_* or 0 for non-IP) of fd */
+  int af;                              /* System-dependend adress family (e.g. AF_INET) */
   int fd;                              /* System-dependent data */
   int index;                           /* Index in poll buffer */
   int rcv_ttl;                         /* TTL of last received datagram */
@@ -91,7 +92,6 @@ extern int sk_priority_control;               /* Suggested priority for control traffic, shou
 
 /* Socket flags */
 
-#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 */
@@ -116,31 +116,35 @@ extern int sk_priority_control;           /* Suggested priority for control traffic, shou
 #define SK_UNIX_PASSIVE        8
 #define SK_UNIX                9
 
-/* Socket families */
+/*
+ *     Socket subtypes
+ */
 
-#define SK_FAM_NONE    0
-#define SK_FAM_IPV4    4
-#define SK_FAM_IPV6    6
+#define SK_IPV4                1
+#define SK_IPV6                2
 
 /*
- *  For SK_UDP or SK_IP sockets setting DA/DP allows to use sk_send(),
- *  otherwise sk_send_to() must be used.
+ * For TCP/IP sockets, Address family (IPv4 or IPv6) can be specified either
+ * explicitly (SK_IPV4 or SK_IPV6) or implicitly (based on saddr, daddr). But
+ * these specifications must be consistent.
+ *
+ * For SK_UDP or SK_IP sockets setting DA/DP allows to use sk_send(), otherwise
+ * sk_send_to() must be used.
  *
- *  For SK_IP sockets setting DP specifies protocol number, which is used
- *  for both receiving and sending.
+ * For SK_IP sockets setting DP specifies protocol number, which is used for
+ * both receiving and sending.
  *
- *  For multicast on SK_UDP or SK_IP sockets set IF and TTL,
- *  call sk_setup_multicast() to enable multicast on that socket,
- *  and then use sk_join_group() and sk_leave_group() to manage
- *  a set of received multicast groups.
+ * For multicast on SK_UDP or SK_IP sockets set IF and TTL, call
+ * sk_setup_multicast() to enable multicast on that socket, and then use
+ * sk_join_group() and sk_leave_group() to manage a set of received multicast
+ * groups.
  *
- *  For datagram (SK_UDP, SK_IP) sockets, there are two ways to handle
- *  source address. The socket could be bound to it using bind()
- *  syscall, but that also forbids the reception of multicast packets,
- *  or the address could be set on per-packet basis using platform
- *  dependent options (but these are not available in some corner
- *  cases). The first way is used when SKF_BIND is specified, the
- *  second way is used otherwise.
+ * For datagram (SK_UDP, SK_IP) sockets, there are two ways to handle source
+ * address. The socket could be bound to it using bind() syscall, but that also
+ * forbids the reception of multicast packets, or the address could be set on
+ * per-packet basis using platform dependent options (but these are not
+ * available in some corner cases). The first way is used when SKF_BIND is
+ * specified, the second way is used otherwise.
  */
 
 #endif
index f966161c11c73281a1f2a8698678fdae0a67768e..d33424b037fb2a31da2ee883a0591e977a3c8225 100644 (file)
@@ -981,10 +981,10 @@ bfd_start(struct proto *P)
   add_tail(&bfd_proto_list, &p->bfd_node);
 
   birdloop_enter(p->loop);
-  p->rx4_1 = bfd_open_rx_sk(p, 0, 4);
-  p->rx4_m = bfd_open_rx_sk(p, 1, 4);
-  p->rx6_1 = bfd_open_rx_sk(p, 0, 6);
-  p->rx6_m = bfd_open_rx_sk(p, 1, 6);
+  p->rx4_1 = bfd_open_rx_sk(p, 0, SK_IPV4);
+  p->rx4_m = bfd_open_rx_sk(p, 1, SK_IPV4);
+  p->rx6_1 = bfd_open_rx_sk(p, 0, SK_IPV6);
+  p->rx6_m = bfd_open_rx_sk(p, 1, SK_IPV6);
   birdloop_leave(p->loop);
 
   bfd_take_requests(p);
index b7a057f1d20a7eaec76f174803e02526e1ce2149..579064c6ffdafefd98b61bfb2fb274a51b6a16e4 100644 (file)
@@ -186,10 +186,11 @@ bfd_err_hook(sock *sk, int err)
 }
 
 sock *
-bfd_open_rx_sk(struct bfd_proto *p, int multihop, int inet_version)
+bfd_open_rx_sk(struct bfd_proto *p, int multihop, int af)
 {
   sock *sk = sk_new(p->tpool);
   sk->type = SK_UDP;
+  sk->subtype = af;
   sk->sport = !multihop ? BFD_CONTROL_PORT : BFD_MULTI_CTL_PORT;
   sk->data = p;
 
@@ -202,19 +203,6 @@ bfd_open_rx_sk(struct bfd_proto *p, int multihop, int inet_version)
   sk->priority = sk_priority_control;
   sk->flags = SKF_THREAD | SKF_LADDR_RX | (!multihop ? SKF_TTL_RX : 0);
 
-  switch (inet_version) {
-    case 4:
-      sk->fam = SK_FAM_IPV4;
-      sk->flags |= SKF_V4ONLY;
-      break;
-    case 6:
-      sk->fam = SK_FAM_IPV6;
-      sk->flags |= SKF_V6ONLY;
-      break;
-    default:
-      ASSERT(0);
-  }
-
   if (sk_open(sk) < 0)
     goto err;
 
@@ -246,14 +234,6 @@ bfd_open_tx_sk(struct bfd_proto *p, ip_addr local, struct iface *ifa)
   sk->ttl = ifa ? 255 : -1;
   sk->flags = SKF_THREAD | SKF_BIND | SKF_HIGH_PORT;
 
-  if (ipa_is_ip4(local)) {
-    sk->fam = SK_FAM_IPV4;
-    sk->flags |= SKF_V4ONLY;
-  } else {
-    sk->fam = SK_FAM_IPV6;
-    sk->flags |= SKF_V6ONLY;
-  }
-
   if (sk_open(sk) < 0)
     goto err;
 
index 4548f6dafa4da5d772b2a3b71b8c8124ea0607d9..6ef24ffe5bfb2a9214cc4fd108cbe8f3a5c12b20 100644 (file)
@@ -108,10 +108,10 @@ ospf_sk_open(struct ospf_iface *ifa)
 
   sock *sk = sk_new(ifa->pool);
   sk->type = SK_IP;
+  sk->subtype = ospf_is_v2(p) ? SK_IPV4 : SK_IPV6;
   sk->dport = OSPF_PROTO;
   sk->saddr = ifa->addr->ip;
   sk->iface = ifa->iface;
-  sk->fam = ospf_is_v2(p) ? SK_FAM_IPV4 : SK_FAM_IPV6;
 
   sk->tos = ifa->cf->tx_tos;
   sk->priority = ifa->cf->tx_priority;
@@ -193,8 +193,8 @@ ospf_open_vlink_sk(struct ospf_proto *p)
 {
   sock *sk = sk_new(p->p.pool);
   sk->type = SK_IP;
+  sk->subtype = ospf_is_v2(p) ? SK_IPV4 : SK_IPV6;
   sk->dport = OSPF_PROTO;
-  sk->fam = ospf_is_v2(p) ? SK_FAM_IPV4 : SK_FAM_IPV6;
 
   /* FIXME: configurable tos/priority ? */
   sk->tos = IP_PREC_INTERNET_CONTROL;
index 8f6a1913e550ac1a38a52b2f19fccb1012fbe121..915b412ff025252a12a103be2145f166b12bbc0a 100644 (file)
@@ -410,9 +410,9 @@ radv_sk_open(struct radv_iface *ifa)
 {
   sock *sk = sk_new(ifa->ra->p.pool);
   sk->type = SK_IP;
+  sk->subtype = SK_IPV6;
   sk->dport = ICMPV6_PROTO;
   sk->saddr = ifa->addr->ip;
-  sk->fam = SK_FAM_IPV6;
 
   sk->ttl = 255; /* Mandatory for Neighbor Discovery packets */
   sk->rx_hook = radv_rx_hook;
index 3c8cd0f22bb2b7e4c6469e5edb4961dfd693da5f..61a2a1019083d7668e9125dc256ac6f23972bd79 100644 (file)
@@ -123,7 +123,7 @@ rip_iface_item:
  | MODE MULTICAST      { RIP_IFACE->mode = RIP_IM_MULTICAST; }
  | MODE BROADCAST      { RIP_IFACE->mode = RIP_IM_BROADCAST; if (rip_cfg_is_ng()) cf_error("Broadcast not supported in RIPng"); }
  | PASSIVE bool                { RIP_IFACE->passive = $2; }
- | ADDRESS ipa         { RIP_IFACE->address = $2; }
+ | ADDRESS ipa         { RIP_IFACE->address = $2; if (ipa_is_ip4($2) != rip_cfg_is_v2()) cf_error("IP address version mismatch"); }
  | PORT expr           { RIP_IFACE->port = $2; if (($2<1) || ($2>65535)) cf_error("Invalid port number"); }
  | VERSION expr                { RIP_IFACE->version = $2;
                          if (rip_cfg_is_ng()) cf_error("Version not supported in RIPng");
index 488ac9df1846399d7102e2619b58d285d2a0804f..f89bb1783942787f17915ef40208323cc5937b8a 100644 (file)
@@ -715,7 +715,7 @@ rip_open_socket(struct rip_iface *ifa)
 
   sock *sk = sk_new(p->p.pool);
   sk->type = SK_UDP;
-  sk->fam = rip_is_v2(p) ? SK_FAM_IPV4 : SK_FAM_IPV6;
+  sk->subtype = rip_is_v2(p) ? SK_IPV4 : SK_IPV6;
   sk->sport = ifa->cf->port;
   sk->dport = ifa->cf->port;
   sk->iface = ifa->iface;
@@ -736,8 +736,7 @@ rip_open_socket(struct rip_iface *ifa)
   sk->tos = ifa->cf->tx_tos;
   sk->priority = ifa->cf->tx_priority;
   sk->ttl = ifa->cf->ttl_security ? 255 : 1;
-  sk->flags = SKF_LADDR_RX | (rip_is_ng(p) ? SKF_V6ONLY : 0) |
-    ((ifa->cf->ttl_security == 1) ? SKF_TTL_RX : 0);
+  sk->flags = SKF_LADDR_RX | ((ifa->cf->ttl_security == 1) ? SKF_TTL_RX : 0);
 
   /* sk->rbsize and sk->tbsize are handled in rip_iface_update_buffers() */
 
index 3c07a3e7904a5c4f1c106982904d908c239d01c9..58644417f9cffda0ea6154f76e0ea94b87f31b4d 100644 (file)
@@ -184,7 +184,7 @@ sk_set_md5_auth(sock *s, ip_addr local UNUSED, ip_addr remote, struct iface *ifa
   struct tcp_md5sig md5;
 
   memset(&md5, 0, sizeof(md5));
-  sockaddr_fill((sockaddr *) &md5.tcpm_addr, fam_to_af[s->fam], remote, ifa, 0);
+  sockaddr_fill((sockaddr *) &md5.tcpm_addr, s->af, remote, ifa, 0);
 
   if (passwd)
   {
index 69c17d60abfcf873e3db451ceb08cc038a4d7035..48f368a4c4e0a81c02c6650dc2a85f6a3c233156 100644 (file)
@@ -587,7 +587,6 @@ sockaddr_read(sockaddr *sa, int af, ip_addr *a, struct iface **ifa, uint *port)
   return -1;
 }
 
-const int fam_to_af[] = { [SK_FAM_IPV4] = AF_INET, [SK_FAM_IPV6] = AF_INET6 };
 
 /*
  *     IPv6 multicast syscalls
@@ -1194,7 +1193,7 @@ sk_setup(sock *s)
   if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
     ERR("O_NONBLOCK");
 
-  if (!s->fam)
+  if (!s->af)
     return 0;
 
   if (ipa_nonzero(s->saddr) && !(s->flags & SKF_BIND))
@@ -1254,9 +1253,8 @@ sk_setup(sock *s)
 
   if (sk_is_ipv6(s))
   {
-    if (s->flags & SKF_V6ONLY)
-      if (setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, &y, sizeof(y)) < 0)
-       ERR("IPV6_V6ONLY");
+    if (setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, &y, sizeof(y)) < 0)
+      ERR("IPV6_V6ONLY");
 
     if (s->flags & SKF_LADDR_RX)
       if (sk_request_cmsg6_pktinfo(s) < 0)
@@ -1295,7 +1293,7 @@ sk_tcp_connected(sock *s)
   int sa_len = sizeof(sa);
 
   if ((getsockname(s->fd, &sa.sa, &sa_len) < 0) ||
-      (sockaddr_read(&sa, fam_to_af[s->fam], &s->saddr, &s->iface, &s->sport) < 0))
+      (sockaddr_read(&sa, s->af, &s->saddr, &s->iface, &s->sport) < 0))
     log(L_WARN "SOCK: Cannot get local IP address for TCP>");
 
   s->type = SK_TCP;
@@ -1320,7 +1318,7 @@ sk_passive_connected(sock *s, int type)
 
   sock *t = sk_new(s->pool);
   t->type = type;
-  t->fam = s->fam;
+  t->af = s->af;
   t->fd = fd;
   t->ttl = s->ttl;
   t->tos = s->tos;
@@ -1330,10 +1328,10 @@ sk_passive_connected(sock *s, int type)
   if (type == SK_TCP)
   {
     if ((getsockname(fd, &loc_sa.sa, &loc_sa_len) < 0) ||
-       (sockaddr_read(&loc_sa, fam_to_af[s->fam], &t->saddr, &t->iface, &t->sport) < 0))
+       (sockaddr_read(&loc_sa, s->af, &t->saddr, &t->iface, &t->sport) < 0))
       log(L_WARN "SOCK: Cannot get local IP address for TCP<");
 
-    if (sockaddr_read(&rem_sa, fam_to_af[s->fam], &t->daddr, &t->iface, &t->dport) < 0)
+    if (sockaddr_read(&rem_sa, s->af, &t->daddr, &t->iface, &t->dport) < 0)
       log(L_WARN "SOCK: Cannot get remote IP address for TCP<");
   }
 
@@ -1368,40 +1366,74 @@ sk_passive_connected(sock *s, int type)
 int
 sk_open(sock *s)
 {
+  int af = AF_UNSPEC;
   int fd = -1;
   int do_bind = 0;
   int bind_port = 0;
   ip_addr bind_addr = IPA_NONE;
   sockaddr sa;
 
+  if (s->type <= SK_IP)
+  {
+    /*
+     * For TCP/IP sockets, Address family (IPv4 or IPv6) can be specified either
+     * explicitly (SK_IPV4 or SK_IPV6) or implicitly (based on saddr, daddr).
+     * But the specifications have to be consistent.
+     */
+
+    switch (s->subtype)
+    {
+    case 0:
+      ASSERT(ipa_zero(s->saddr) || ipa_zero(s->daddr) ||
+            (ipa_is_ip4(s->saddr) == ipa_is_ip4(s->daddr)));
+      af = (ipa_is_ip4(s->saddr) || ipa_is_ip4(s->daddr)) ? AF_INET : AF_INET6;
+      break;
+
+    case SK_IPV4:
+      ASSERT(ipa_zero(s->saddr) || ipa_is_ip4(s->saddr));
+      ASSERT(ipa_zero(s->daddr) || ipa_is_ip4(s->daddr));
+      af = AF_INET;
+      break;
+
+    case SK_IPV6:
+      ASSERT(ipa_zero(s->saddr) || !ipa_is_ip4(s->saddr));
+      ASSERT(ipa_zero(s->daddr) || !ipa_is_ip4(s->daddr));
+      af = AF_INET6;
+      break;
+
+    default:
+      bug("Invalid subtype %d", s->subtype);
+    }
+  }
+
   switch (s->type)
   {
   case SK_TCP_ACTIVE:
     s->ttx = "";                       /* Force s->ttx != s->tpos */
     /* Fall thru */
   case SK_TCP_PASSIVE:
-    fd = socket(fam_to_af[s->fam], SOCK_STREAM, IPPROTO_TCP);
+    fd = socket(af, SOCK_STREAM, IPPROTO_TCP);
     bind_port = s->sport;
     bind_addr = s->saddr;
     do_bind = bind_port || ipa_nonzero(bind_addr);
     break;
 
   case SK_UDP:
-    fd = socket(fam_to_af[s->fam], SOCK_DGRAM, IPPROTO_UDP);
+    fd = socket(af, SOCK_DGRAM, IPPROTO_UDP);
     bind_port = s->sport;
     bind_addr = (s->flags & SKF_BIND) ? s->saddr : IPA_NONE;
     do_bind = 1;
     break;
 
   case SK_IP:
-    fd = socket(fam_to_af[s->fam], SOCK_RAW, s->dport);
+    fd = socket(af, SOCK_RAW, s->dport);
     bind_port = 0;
     bind_addr = (s->flags & SKF_BIND) ? s->saddr : IPA_NONE;
     do_bind = ipa_nonzero(bind_addr);
     break;
 
   case SK_MAGIC:
-    s->fam = SK_FAM_NONE;
+    af = 0;
     fd = s->fd;
     break;
 
@@ -1412,6 +1444,7 @@ sk_open(sock *s)
   if (fd < 0)
     ERR("socket");
 
+  s->af = af;
   s->fd = fd;
 
   if (sk_setup(s) < 0)
@@ -1440,7 +1473,7 @@ sk_open(sock *s)
        if (sk_set_high_port(s) < 0)
          log(L_WARN "Socket error: %s%#m", s->err);
 
-    sockaddr_fill(&sa, fam_to_af[s->fam], bind_addr, s->iface, bind_port);
+    sockaddr_fill(&sa, s->af, bind_addr, s->iface, bind_port);
     if (bind(fd, &sa.sa, SA_LEN(sa)) < 0)
       ERR2("bind");
   }
@@ -1452,7 +1485,7 @@ sk_open(sock *s)
   switch (s->type)
   {
   case SK_TCP_ACTIVE:
-    sockaddr_fill(&sa, fam_to_af[s->fam], s->daddr, s->iface, s->dport);
+    sockaddr_fill(&sa, s->af, s->daddr, s->iface, s->dport);
     if (connect(fd, &sa.sa, SA_LEN(sa)) >= 0)
       sk_tcp_connected(s);
     else if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS &&
@@ -1559,7 +1592,7 @@ sk_sendmsg(sock *s)
   byte cmsg_buf[CMSG_TX_SPACE];
   sockaddr dst;
 
-  sockaddr_fill(&dst, fam_to_af[s->fam], s->daddr, s->iface, s->dport);
+  sockaddr_fill(&dst, s->af, s->daddr, s->iface, s->dport);
 
   struct msghdr msg = {
     .msg_name = &dst.sa,
@@ -1612,7 +1645,7 @@ sk_recvmsg(sock *s)
   //    rv = ipv4_skip_header(pbuf, rv);
   //endif
 
-  sockaddr_read(&src, fam_to_af[s->fam], &s->faddr, NULL, &s->fport);
+  sockaddr_read(&src, s->af, &s->faddr, NULL, &s->fport);
   sk_process_cmsgs(s, &msg);
 
   if (msg.msg_flags & MSG_TRUNC)
@@ -1832,7 +1865,7 @@ sk_write(sock *s)
   case SK_TCP_ACTIVE:
     {
       sockaddr sa;
-      sockaddr_fill(&sa, fam_to_af[s->fam], s->daddr, s->iface, s->dport);
+      sockaddr_fill(&sa, s->af, s->daddr, s->iface, s->dport);
 
       if (connect(s->fd, &sa.sa, SA_LEN(sa)) >= 0 || errno == EISCONN)
        sk_tcp_connected(s);
@@ -1853,10 +1886,10 @@ sk_write(sock *s)
 }
 
 int sk_is_ipv4(sock *s)
-{ return s->fam == SK_FAM_IPV4; }
+{ return s->af == AF_INET; }
 
 int sk_is_ipv6(sock *s)
-{ return s->fam == SK_FAM_IPV6; }
+{ return s->af == AF_INET6; }
 
 void
 sk_dump_all(void)
index 80c993504fed8ab55c3d97988248cb56665d27d8..dcaab72973612e3bbcceb16f2f687ce41338990c 100644 (file)
@@ -102,8 +102,6 @@ int sk_open_unix(struct birdsock *s, char *name);
 void *tracked_fopen(struct pool *, char *name, char *mode);
 void test_old_bird(char *path);
 
-extern const int fam_to_af[];
-
 /* krt.c bits */
 
 void krt_io_init(void);