socket-default: Refactor retrieval of destination address of received packets
authorTobias Brunner <tobias@strongswan.org>
Mon, 2 Nov 2015 15:16:56 +0000 (16:16 +0100)
committerTobias Brunner <tobias@strongswan.org>
Mon, 9 Nov 2015 15:42:20 +0000 (16:42 +0100)
This makes the code a bit clearer than with the interleaved ifdefs.

src/libcharon/plugins/socket_default/socket_default_socket.c

index dbfddbb..421593c 100644 (file)
@@ -148,6 +148,91 @@ struct private_socket_default_socket_t {
        u_int rr_counter;
 };
 
+/**
+ * Get the destination IPv4 address of a received packet, depending on the
+ * available mechanism.
+ */
+#ifdef IP_PKTINFO
+
+static host_t *get_dst_v4(struct cmsghdr *cmsgptr, u_int16_t port)
+{
+       struct sockaddr_in dst = {
+               .sin_family = AF_INET,
+               .sin_port = htons(port),
+       };
+       struct in_pktinfo *pktinfo;
+       struct in_addr *addr;
+
+       if (cmsgptr->cmsg_type == IP_PKTINFO)
+       {
+               pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsgptr);
+               addr = &pktinfo->ipi_addr;
+               memcpy(&dst.sin_addr, addr, sizeof(dst.sin_addr));
+               return host_create_from_sockaddr((sockaddr_t*)&dst);
+       }
+       return NULL;
+}
+
+#elif defined(IP_RECVDSTADDR)
+
+static host_t *get_dst_v4(struct cmsghdr *cmsgptr, u_int16_t port)
+{
+       struct sockaddr_in dst = {
+               .sin_family = AF_INET,
+               .sin_port = htons(port),
+       };
+       struct in_addr *addr;
+
+       if (cmsgptr->cmsg_type == IP_RECVDSTADDR)
+       {
+               addr = (struct in_addr*)CMSG_DATA(cmsgptr);
+               memcpy(&dst.sin_addr, addr, sizeof(dst.sin_addr));
+               return host_create_from_sockaddr((sockaddr_t*)&dst);
+       }
+       return NULL;
+}
+
+#else /* IP_PKTINFO || IP_RECVDSTADDR */
+
+static host_t *get_dst_v4(struct cmsghdr *cmsgptr, u_int16_t port)
+{
+       return NULL;
+}
+
+#endif /* IP_PKTINFO || IP_RECVDSTADDR */
+
+/**
+ * Get the destination IPv6 address of a received packet, depending on the
+ * available mechanism.
+ */
+#ifdef HAVE_IN6_PKTINFO
+
+static host_t *get_dst_v6(struct cmsghdr *cmsgptr, u_int16_t port)
+{
+       struct in6_pktinfo *pktinfo;
+       struct sockaddr_in6 dst = {
+               .sin6_family = AF_INET6,
+               .sin6_port = htons(port),
+       };
+
+       if (cmsgptr->cmsg_type == IPV6_PKTINFO)
+       {
+               pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsgptr);
+               memcpy(&dst.sin6_addr, &pktinfo->ipi6_addr, sizeof(dst.sin6_addr));
+               return host_create_from_sockaddr((sockaddr_t*)&dst);
+       }
+       return NULL;
+}
+
+#else /* HAVE_IN6_PKTINFO */
+
+static host_t *get_dst_v6(struct cmsghdr *cmsgptr, u_int16_t port)
+{
+       return NULL;
+}
+
+#endif /* HAVE_IN6_PKTINFO */
+
 METHOD(socket_t, receiver, status_t,
        private_socket_default_socket_t *this, packet_t **packet)
 {
@@ -233,48 +318,13 @@ METHOD(socket_t, receiver, status_t,
                                DBG1(DBG_NET, "error reading ancillary data");
                                return FAILED;
                        }
-
-#ifdef HAVE_IN6_PKTINFO
-                       if (cmsgptr->cmsg_level == SOL_IPV6 &&
-                               cmsgptr->cmsg_type == IPV6_PKTINFO)
+                       if (cmsgptr->cmsg_level == SOL_IP)
                        {
-                               struct in6_pktinfo *pktinfo;
-                               pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsgptr);
-                               struct sockaddr_in6 dst;
-
-                               memset(&dst, 0, sizeof(dst));
-                               memcpy(&dst.sin6_addr, &pktinfo->ipi6_addr, sizeof(dst.sin6_addr));
-                               dst.sin6_family = AF_INET6;
-                               dst.sin6_port = htons(port);
-                               dest = host_create_from_sockaddr((sockaddr_t*)&dst);
+                               dest = get_dst_v4(cmsgptr, port);
                        }
-#endif /* HAVE_IN6_PKTINFO */
-                       if (cmsgptr->cmsg_level == SOL_IP &&
-#ifdef IP_PKTINFO
-                               cmsgptr->cmsg_type == IP_PKTINFO
-#elif defined(IP_RECVDSTADDR)
-                               cmsgptr->cmsg_type == IP_RECVDSTADDR
-#else
-                               FALSE
-#endif
-                               )
+                       else if (cmsgptr->cmsg_level == SOL_IPV6)
                        {
-                               struct in_addr *addr;
-                               struct sockaddr_in dst;
-
-#ifdef IP_PKTINFO
-                               struct in_pktinfo *pktinfo;
-                               pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsgptr);
-                               addr = &pktinfo->ipi_addr;
-#elif defined(IP_RECVDSTADDR)
-                               addr = (struct in_addr*)CMSG_DATA(cmsgptr);
-#endif
-                               memset(&dst, 0, sizeof(dst));
-                               memcpy(&dst.sin_addr, addr, sizeof(dst.sin_addr));
-
-                               dst.sin_family = AF_INET;
-                               dst.sin_port = htons(port);
-                               dest = host_create_from_sockaddr((sockaddr_t*)&dst);
+                               dest = get_dst_v6(cmsgptr, port);
                        }
                        if (dest)
                        {