socket-dynamic: Refactor setting source address when sending messages
authorTobias Brunner <tobias@strongswan.org>
Tue, 3 Nov 2015 14:35:16 +0000 (15:35 +0100)
committerTobias Brunner <tobias@strongswan.org>
Mon, 9 Nov 2015 15:44:22 +0000 (16:44 +0100)
Basically the same change as the one for the socket-default plugin.

src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c

index b82a69e..a032134 100644 (file)
@@ -527,6 +527,62 @@ static dynsock_t *find_socket(private_socket_dynamic_socket_t *this,
        return skt;
 }
 
+/**
+ * Generic function to send a message.
+ */
+static ssize_t send_msg_generic(int skt, struct msghdr *msg)
+{
+       return sendmsg(skt, msg, 0);
+}
+
+/**
+ * Send a message with the IPv4 source address set.
+ */
+static ssize_t send_msg_v4(int skt, struct msghdr *msg, host_t *src)
+{
+       char buf[CMSG_SPACE(sizeof(struct in_pktinfo))] = {};
+       struct cmsghdr *cmsg;
+       struct in_addr *addr;
+       struct in_pktinfo *pktinfo;
+       struct sockaddr_in *sin;
+
+       msg->msg_control = buf;
+       msg->msg_controllen = sizeof(buf);
+       cmsg = CMSG_FIRSTHDR(msg);
+       cmsg->cmsg_level = SOL_IP;
+       cmsg->cmsg_type = IP_PKTINFO;
+       cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
+
+       pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
+       addr = &pktinfo->ipi_spec_dst;
+
+       sin = (struct sockaddr_in*)src->get_sockaddr(src);
+       memcpy(addr, &sin->sin_addr, sizeof(struct in_addr));
+       return send_msg_generic(skt, msg);
+}
+
+/**
+ * Send a message with the IPv6 source address set.
+ */
+static ssize_t send_msg_v6(int skt, struct msghdr *msg, host_t *src)
+{
+       char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))] = {};
+       struct cmsghdr *cmsg;
+       struct in6_pktinfo *pktinfo;
+       struct sockaddr_in6 *sin;
+
+       msg->msg_control = buf;
+       msg->msg_controllen = sizeof(buf);
+       cmsg = CMSG_FIRSTHDR(msg);
+       cmsg->cmsg_level = SOL_IPV6;
+       cmsg->cmsg_type = IPV6_PKTINFO;
+       cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
+       pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsg);
+       sin = (struct sockaddr_in6*)src->get_sockaddr(src);
+       memcpy(&pktinfo->ipi6_addr, &sin->sin6_addr, sizeof(struct in6_addr));
+       return send_msg_generic(skt, msg);
+}
+
 METHOD(socket_t, sender, status_t,
        private_socket_dynamic_socket_t *this, packet_t *packet)
 {
@@ -536,7 +592,6 @@ METHOD(socket_t, sender, status_t,
        ssize_t len;
        chunk_t data;
        struct msghdr msg;
-       struct cmsghdr *cmsg;
        struct iovec iov;
 
        src = packet->get_source(packet);
@@ -564,43 +619,18 @@ METHOD(socket_t, sender, status_t,
        {
                if (family == AF_INET)
                {
-                       struct in_addr *addr;
-                       struct sockaddr_in *sin;
-                       char buf[CMSG_SPACE(sizeof(struct in_pktinfo))];
-                       struct in_pktinfo *pktinfo;
-
-                       memset(buf, 0, sizeof(buf));
-                       msg.msg_control = buf;
-                       msg.msg_controllen = sizeof(buf);
-                       cmsg = CMSG_FIRSTHDR(&msg);
-                       cmsg->cmsg_level = SOL_IP;
-                       cmsg->cmsg_type = IP_PKTINFO;
-                       cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
-                       pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
-                       addr = &pktinfo->ipi_spec_dst;
-                       sin = (struct sockaddr_in*)src->get_sockaddr(src);
-                       memcpy(addr, &sin->sin_addr, sizeof(struct in_addr));
+                       len = send_msg_v4(skt->fd, &msg, src);
                }
                else
                {
-                       char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
-                       struct in6_pktinfo *pktinfo;
-                       struct sockaddr_in6 *sin;
-
-                       memset(buf, 0, sizeof(buf));
-                       msg.msg_control = buf;
-                       msg.msg_controllen = sizeof(buf);
-                       cmsg = CMSG_FIRSTHDR(&msg);
-                       cmsg->cmsg_level = SOL_IPV6;
-                       cmsg->cmsg_type = IPV6_PKTINFO;
-                       cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
-                       pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsg);
-                       sin = (struct sockaddr_in6*)src->get_sockaddr(src);
-                       memcpy(&pktinfo->ipi6_addr, &sin->sin6_addr, sizeof(struct in6_addr));
+                       len = send_msg_v6(skt->fd, &msg, src);
                }
        }
+       else
+       {
+               len = send_msg_generic(skt->fd, &msg);
+       }
 
-       len = sendmsg(skt->fd, &msg, 0);
        if (len != data.len)
        {
                DBG1(DBG_NET, "error writing to socket: %s", strerror(errno));