Add support for multiple IP/port pairs in swift_sockaddr. Also add the user space...
authorAdrian Bondrescu <adi.bondrescu@gmail.com>
Thu, 10 May 2012 19:36:10 +0000 (22:36 +0300)
committerAdrian Bondrescu <adi.bondrescu@gmail.com>
Thu, 10 May 2012 19:36:10 +0000 (22:36 +0300)
src/kernel/swift.c
src/kernel/swift.h
test/Makefile [new file with mode: 0644]
test/client.c [new file with mode: 0644]
test/server.c [new file with mode: 0644]

index b3aa899..b21c106 100644 (file)
@@ -95,13 +95,7 @@ static int swift_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
 
        swift_addr = (struct sockaddr_swift *) addr;
 
-       if (unlikely(swift_addr->sin_family != AF_INET)) {
-               log_error("Invalid family for sockaddr\n");
-               err = -EINVAL;
-               goto out;
-       }
-
-       port = ntohs(swift_addr->sin_port);
+       port = swift_addr->dests[0].port;
 
        if (unlikely(port == 0 || port >= MAX_SWIFT_PORT)) {
                log_error("Invalid value for sockaddr port (%u)\n", port);
@@ -162,19 +156,21 @@ static int swift_connect(struct socket *sock, struct sockaddr *addr, int addr_le
        if (likely(addr)) {
                struct sockaddr_swift * swift_addr = (struct sockaddr_swift *) addr;
                
-               if (unlikely(addr_len < sizeof(*swift_addr) || swift_addr->sin_family != AF_INET)) {
+        if (unlikely(addr_len < sizeof(*swift_addr) || 
+                     addr_len < swift_addr->count * sizeof(struct swift_dest) || 
+                     swift_addr->count <= 0)) {
                        log_error("Invalid size or address family\n");
                        err = -EINVAL;
                        goto out;
                }
-               ssk->dst = ntohs(swift_addr->sin_port);
+               ssk->dst = swift_addr->dests[0].port;
                if (unlikely(ssk->dst == 0 || ssk->dst >= MAX_SWIFT_PORT)) {
                        log_error("Invalid value for destination port(%u)\n", ssk->dst);
                        err = -EINVAL;
                        goto out;
                }       
        
-               isk->inet_daddr = swift_addr->sin_addr.s_addr;
+               isk->inet_daddr = swift_addr->dests[0].addr;
                log_debug("Received from user space destination port=%u and address=%u\n", ssk->dst, isk->inet_daddr);
        } else {
                log_error("Invalid swift_addr (NULL)\n");
@@ -241,20 +237,22 @@ static int swift_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
        if (msg->msg_name) {
                struct sockaddr_swift * swift_addr = (struct sockaddr_swift *) msg->msg_name;
                
-               if (unlikely(msg->msg_namelen < sizeof(*swift_addr) || swift_addr->sin_family != AF_INET)) {
-                       log_error("Invalid size or address family\n");
+        if (unlikely(msg->msg_namelen < sizeof(*swift_addr) || 
+                     msg->msg_namelen < swift_addr->count * sizeof(struct swift_dest) || 
+                     swift_addr->count <= 0)) {
+                       log_error("Invalid size for msg_name\n");
                        err = -EINVAL;
                        goto out;
                }
                
-               dport = ntohs(swift_addr->sin_port);
+               dport = swift_addr->dests[0].port;
                if (unlikely(dport == 0 || dport >= MAX_SWIFT_PORT)) {
                        log_error("Invalid value for destination port(%u)\n", dport);
                        err = -EINVAL;
                        goto out;
                }       
 
-               daddr = swift_addr->sin_addr.s_addr;
+               daddr = swift_addr->dests[0].addr;
                log_debug("Received from user space destination port=%u and address=%u\n", dport, daddr);
        } else {
                if (unlikely(!ssk->dst || !isk->inet_daddr)) {
@@ -285,8 +283,8 @@ static int swift_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
        log_debug("Reseted transport header\n");
 
        shdr = (struct swifthdr *) skb_transport_header(skb);
-       shdr->dst = ntohs(dport);
-       shdr->src = ntohs(sport);
+       shdr->dst = dport;
+       shdr->src = sport;
        shdr->len = ntohs(len + sizeof(struct swifthdr));
 
        log_debug("payload=%p\n", skb_put(skb, len));
@@ -340,6 +338,8 @@ static int swift_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
        struct sock * sk = sock->sk;
        int err, copied;
 
+    log_debug("Trying to receive sock=%p sk=%p flags=%d\n", sock, sk, flags);
+
        skb = skb_recv_datagram(sk, flags, flags & MSG_DONTWAIT, &err);
        if (unlikely(!skb)) {
                log_error("skb_recv_datagram\n");
@@ -404,8 +404,8 @@ static int swift_rcv(struct sk_buff *skb)
                goto drop;
        }
        
-       src = ntohs(shdr->src);
-       dst = ntohs(shdr->dst);
+       src = shdr->src;
+       dst = shdr->dst;
        if (unlikely(src == 0 || dst == 0 || src >= MAX_SWIFT_PORT || dst >= MAX_SWIFT_PORT)) {
                log_error("Malformed packet (src=%u, dst=%u)\n", shdr->src, shdr->dst);
                goto drop;
@@ -427,11 +427,10 @@ static int swift_rcv(struct sk_buff *skb)
        BUILD_BUG_ON(sizeof(struct sockaddr_swift) > sizeof(skb->cb));
        
        swift_addr = (struct sockaddr_swift *) skb->cb;
-       swift_addr->sin_family = AF_INET;
-       swift_addr->sin_port = shdr->src;
-       swift_addr->sin_addr.s_addr = ip_hdr(skb)->saddr;
+       swift_addr->dests[0].port = shdr->src;
+       swift_addr->dests[0].addr = ip_hdr(skb)->saddr;
 
-       log_debug("Setting sin_port=%u, sin_addr=%u\n", ntohs(shdr->src), swift_addr->sin_addr.s_addr);
+       log_debug("Setting sin_port=%u, sin_addr=%u\n", ntohs(shdr->src), swift_addr->dests[0].addr);
 
        err = ip_queue_rcv_skb((struct sock *) &ssk->sock, skb);
        if (unlikely(err)) {
index 275b322..ab974c9 100644 (file)
@@ -3,10 +3,23 @@
 
 #define IPPROTO_SWIFT 137
 
-#define sockaddr_swift sockaddr_in
 #define MIN_SWIFT_PORT 1
 #define MAX_SWIFT_PORT 256
 
+#ifndef __KERNEL__
+#include <inttypes.h>
+#endif
+
+struct swift_dest {
+    uint32_t addr;
+    uint8_t port;
+};
+
+struct sockaddr_swift {
+    int count;
+    struct swift_dest dests[0];
+};
+
 #ifdef __KERNEL__
 struct swifthdr {
        uint8_t src;
diff --git a/test/Makefile b/test/Makefile
new file mode 100644 (file)
index 0000000..92f7b02
--- /dev/null
@@ -0,0 +1,12 @@
+CC=gcc
+CFLAGS=-g
+
+build: client server
+
+client: client.o
+
+server: server.o
+
+client.o: client.c
+
+server.o: server.c
diff --git a/test/client.c b/test/client.c
new file mode 100644 (file)
index 0000000..ddd6202
--- /dev/null
@@ -0,0 +1,73 @@
+#include "../src/kernel/swift.h"
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+
+int main(int argc, const char *argv[])
+{
+    int sock;
+
+    sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_SWIFT);
+    if (sock < 0) {
+        perror("Failed to create socket");
+        return -1;
+    }
+
+    int size = sizeof(struct sockaddr_swift) + sizeof(struct swift_dest);
+    struct sockaddr_swift *saddr = malloc(size);
+    memset(saddr, 0, size);
+
+    saddr->count = 1;
+    saddr->dests[0].addr = 0x0100007F;
+    saddr->dests[0].port = 50;
+
+    if (bind(sock, (struct sockaddr *) saddr, size) < 0) {
+        perror("Failed to bind socket");
+        close(sock);
+        return -1;
+    }
+
+    char buf[] = "Buffer de test";
+    struct iovec iov[1];
+    struct msghdr msg;
+    struct sockaddr_swift *to = malloc(size);
+
+    memset(&msg, 0, sizeof(msg));
+    memset(&iov, 0, sizeof(iov));
+    memset(to, 0, size);
+
+    iov[0].iov_base = buf;
+    iov[0].iov_len = sizeof(buf);
+
+    to->count = 1;
+    to->dests[0].addr = 0x0100007F;
+    to->dests[0].port = 100;
+
+    msg.msg_iov = iov;
+    msg.msg_iovlen = 1;
+    msg.msg_name = to;
+    msg.msg_namelen = size;
+
+    int ret;
+
+    ret = sendmsg(sock, &msg, sizeof(msg));
+    if (ret < 0) {
+        perror("Failed to send on socket");
+        return -1;
+    }
+
+    printf("Sent %d bytes on socket\n", msg.msg_namelen);
+
+    if (close(sock) < 0) {
+        perror("Failed to close socket");
+        return -1;
+    }
+
+    free(saddr);
+    free(to);
+    return 0;
+}
diff --git a/test/server.c b/test/server.c
new file mode 100644 (file)
index 0000000..b0f1ea8
--- /dev/null
@@ -0,0 +1,71 @@
+#include "../src/kernel/swift.h"
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+
+int main(int argc, const char *argv[])
+{
+    int sock;
+
+    sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_SWIFT);
+    if (sock < 0) {
+        perror("Failed to create socket");
+        return -1;
+    }
+
+    int size = sizeof(struct sockaddr_swift) + sizeof(struct swift_dest);
+    struct sockaddr_swift *saddr = malloc(size);
+    memset(saddr, 0, size);
+
+    saddr->count = 1;
+    saddr->dests[0].addr = 0x0100007F;
+    saddr->dests[0].port = 100;
+
+    if (bind(sock, (struct sockaddr *) saddr, size) < 0) {
+        perror("Failed to bind socket");
+        close(sock);
+        return -1;
+    }
+
+    char buf[256];
+    struct iovec iov[1];
+    struct msghdr msg;
+    struct sockaddr_swift *from = malloc(size);
+
+    memset(&msg, 0, sizeof(msg));
+    memset(&iov, 0, sizeof(iov));
+    memset(from, 0, size);
+
+    iov[0].iov_base = buf;
+    iov[0].iov_len = sizeof(buf);
+
+    msg.msg_iov = iov;
+    msg.msg_iovlen = 1;
+    msg.msg_name = from;
+    msg.msg_namelen = size;
+
+    int ret, fromlen;
+
+    ret = recvmsg(sock, &msg, 0);
+    if (ret < 0) {
+        perror("Failed to recv on socket");
+        return -1;
+    }
+
+    printf("Received %d bytes on socket\n", ret);
+    printf("buf=%s\n", buf);
+
+    if (close(sock) < 0) {
+        perror("Failed to close socket");
+        return -1;
+    }
+
+    free(saddr);
+    free(from);
+
+    return 0;
+}