Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(930)

Unified Diff: src/process-manager/tests/test-socket.cc

Issue 867041: support AF_NETLINK in src/process-manager
Patch Set: CreateStack with ScheduledContext Created 13 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/process-manager/simu-fd.cc ('k') | src/process-manager/tests/wscript » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/process-manager/tests/test-socket.cc
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/process-manager/tests/test-socket.cc
@@ -0,0 +1,344 @@
+#define _GNU_SOURCE 1
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <errno.h>
+#include <sys/select.h>
+#include <pthread.h>
+#include "test-macros.h"
+
+
+void test_raw (void)
+{
+ int sock;
+ const char buf[12] = "0123456789\0";
+ struct msghdr msg;
+ struct iovec iov;
+ static struct sockaddr_in dst;
+ int ret;
+
+ // ICMP Raw sock
+ sock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
+ TEST_ASSERT_UNEQUAL (sock, -1);
+
+ // sendmsg
+ memset (&dst, 0, sizeof (dst));
+ dst.sin_family = AF_INET;
+ dst.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+
+ iov.iov_base = (void *) buf;
+ iov.iov_len = sizeof (buf);
+ msg.msg_name = &dst;
+ msg.msg_namelen = sizeof (dst);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+
+ ret = sendmsg (sock, &msg, 0);
+ TEST_ASSERT_EQUAL (ret, sizeof (buf));
+ OUTPUT ("RAW send ret = " << ret);
+
+ // recvmsg with short buf
+ iov.iov_base = (void *) buf;
+ iov.iov_len = sizeof (buf);
+ ret = recvmsg (sock, &msg, 0);
+ TEST_ASSERT_EQUAL (ret, sizeof (buf));
+ OUTPUT ("RAW recv ret = " << ret);
+
+ char buf2[20];
+ iov.iov_base = (void *) buf2;
+ iov.iov_len = sizeof (buf2);
+ ret = recvmsg (sock, &msg, 0);
+ TEST_ASSERT_EQUAL (ret, sizeof (buf2));
+ OUTPUT ("RAW recv ret = " << ret);
+
+ iov.iov_base = (void *) buf;
+ iov.iov_len = sizeof (buf);
+ ret = sendmsg (sock, &msg, 0);
+ TEST_ASSERT_EQUAL (ret, sizeof (buf));
+ OUTPUT ("RAW send ret = " << ret);
+
+ // recvmsg with long buf
+ char recvbuf[512];
+ iov.iov_base = (void *) recvbuf;
+ iov.iov_len = sizeof (recvbuf);
+ ret = recvmsg (sock, &msg, 0);
+ TEST_ASSERT_EQUAL (ret, sizeof (buf) + 20);
+ OUTPUT ("RAW recv ret = " << ret);
+
+ // close
+ close (sock);
+ TEST_ASSERT_UNEQUAL (sock, -1);
+}
+
+void test_udp (void)
+{
+ int sock;
+ const char buf[12] = "0123456789\0";
+ struct msghdr msg;
+ struct iovec iov;
+ static struct sockaddr_in dst;
+ int ret;
+
+ // UDP Sock
+ sock = socket (AF_INET, SOCK_DGRAM, 0);
+ TEST_ASSERT_UNEQUAL (sock, -1);
+
+ memset (&dst, 0, sizeof (dst));
+ dst.sin_family = AF_INET;
+ dst.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+ dst.sin_port = htons (30);
+
+ // bind
+ ret = bind (sock, (struct sockaddr *)&dst, sizeof (dst));
+ TEST_ASSERT_UNEQUAL (ret, -1);
+
+ // sendmsg
+ iov.iov_base = (void *) buf;
+ iov.iov_len = sizeof (buf);
+ msg.msg_name = &dst;
+ msg.msg_namelen = sizeof (dst);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+
+ ret = sendmsg (sock, &msg, 0);
+ TEST_ASSERT_EQUAL (ret, sizeof (buf));
+ OUTPUT ("UDP send ret = " << ret);
+
+ // recvmsg
+ ret = recvmsg (sock, &msg, 0);
+ TEST_ASSERT_EQUAL (ret, sizeof (buf));
+ OUTPUT ("UDP recv ret = " << ret);
+
+ // close
+ close (sock);
+ TEST_ASSERT_UNEQUAL (sock, -1);
+}
+
+static void *
+thread_recv (void *arg)
+{
+ int accept_sock = -1;
+ int sock = *(int *)arg;
+ int ret;
+ char buf[12];
+
+ while (1)
+ {
+ fd_set readfd;
+ struct timeval wait;
+ FD_ZERO (&readfd);
+ if (accept_sock == -1)
+ {
+ FD_SET (sock, &readfd);
+ }
+ else
+ {
+ FD_SET (accept_sock, &readfd);
+ }
+ wait.tv_sec = 1;
+
+ ret = select (FD_SETSIZE, &readfd, NULL, NULL, &wait);
+ TEST_ASSERT_UNEQUAL (ret, 0);
+ if (errno == EINTR || errno == EAGAIN)
+ {
+ continue;
+ }
+ TEST_ASSERT_UNEQUAL (ret, -1);
+
+ // accept
+ if (accept_sock == -1)
+ {
+ accept_sock = accept (sock, NULL, 0);
+ TEST_ASSERT_UNEQUAL (ret, -1);
+ OUTPUT ("TCP accepted ret = " << ret);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ // recv
+ ret = recv (accept_sock, &buf, sizeof (buf), 0);
+ TEST_ASSERT_EQUAL (ret, sizeof (buf));
+ OUTPUT ("TCP recv ret = " << ret);
+
+ pthread_exit (arg);
+ // never reached.
+ TEST_ASSERT (false);
+ return arg;
+}
+
+void test_tcp (void)
+{
+ int sock, tx_sock;
+ const char buf[12] = "0123456789\0";
+ static struct sockaddr_in dst;
+ int ret;
+ pthread_t thread;
+
+ // TCP Sock
+ sock = socket (AF_INET, SOCK_STREAM, 0);
+ TEST_ASSERT_UNEQUAL (sock, -1);
+
+ memset (&dst, 0, sizeof (dst));
+ dst.sin_family = AF_INET;
+ dst.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+ dst.sin_port = htons (30);
+
+ // bind
+ ret = bind (sock, (struct sockaddr *)&dst, sizeof (dst));
+ TEST_ASSERT_UNEQUAL (ret, -1);
+
+ // listen
+ ret = listen (sock, 5);
+ TEST_ASSERT_UNEQUAL (ret, -1);
+
+ // recv thread
+ ret = pthread_create (&thread, NULL,
+ &thread_recv,
+ (void*)&sock);
+
+ // tx sock
+ tx_sock = socket (AF_INET, SOCK_STREAM, 0);
+ TEST_ASSERT_UNEQUAL (tx_sock, -1);
+ // connect
+ ret = connect (tx_sock, (struct sockaddr *)&dst, sizeof (dst));
+ TEST_ASSERT_UNEQUAL (ret, -1);
+
+ // send
+ ret = send (tx_sock, &buf, sizeof (buf), 0);
+ TEST_ASSERT_EQUAL (ret, sizeof (buf));
+ OUTPUT ("TCP send ret = " << ret);
+
+ void *return_value;
+ ret = pthread_join (thread, &return_value);
+
+ // close
+ close (sock);
+ TEST_ASSERT_UNEQUAL (sock, -1);
+ close (tx_sock);
+ TEST_ASSERT_UNEQUAL (tx_sock, -1);
+}
+
+void test_netlink (void)
+{
+ int sock;
+ int ret;
+ struct sockaddr_nl snl;
+ socklen_t namelen;
+ int seq = 0;
+ char buf[4096];
+ struct iovec iov;
+ struct msghdr msg;
+ struct nlmsghdr *h;
+ struct ifaddrmsg *ifa;
+
+ // Netlink sock
+ sock = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ TEST_ASSERT_UNEQUAL (sock, -1);
+
+ // Bind
+ memset (&snl, 0, sizeof snl);
+ snl.nl_family = AF_NETLINK;
+ snl.nl_groups = RTMGRP_LINK|RTMGRP_IPV4_ROUTE|RTMGRP_IPV4_IFADDR;
+ ret = bind (sock, (struct sockaddr *) &snl, sizeof snl);
+ TEST_ASSERT_UNEQUAL (sock, -1);
+
+ // getsockname
+ namelen = sizeof (snl);
+ ret = getsockname (sock, (struct sockaddr *) &snl, &namelen);
+ TEST_ASSERT_UNEQUAL (ret, -1);
+ TEST_ASSERT_EQUAL (namelen, sizeof (snl));
+
+ // sendto
+ struct
+ {
+ struct nlmsghdr nlh;
+ struct rtgenmsg g;
+ } req;
+
+ memset (&snl, 0, sizeof snl);
+ snl.nl_family = AF_NETLINK;
+
+ // Get IPv4 Address
+ req.nlh.nlmsg_len = sizeof (req);
+ req.nlh.nlmsg_type = RTM_GETADDR;
+ req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
+ req.nlh.nlmsg_pid = 0;
+ req.nlh.nlmsg_seq = ++seq;
+ req.g.rtgen_family = AF_INET;
+
+ ret = sendto (sock, (void *) &req, sizeof (req), 0,
+ (struct sockaddr *) &snl, sizeof (snl));
+ TEST_ASSERT_EQUAL (ret, sizeof (req));
+
+ // recvmsg
+ iov.iov_base = (void *) buf;
+ iov.iov_len = sizeof (buf);
+ msg.msg_name = (void *)&snl;
+ msg.msg_namelen = sizeof (snl);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+
+ ret = recvmsg (sock, &msg, 0);
+ TEST_ASSERT_UNEQUAL (ret, -1);
+ TEST_ASSERT_EQUAL (msg.msg_namelen, sizeof (snl));
+
+ // Code from zebra/rt_netlink.c
+ for (h = (struct nlmsghdr *) buf; NLMSG_OK (h, (uint32_t) ret);
+ h = NLMSG_NEXT (h, ret))
+ {
+ if (h->nlmsg_type == NLMSG_DONE)
+ break;
+
+ /* Error handling. */
+ if (h->nlmsg_type == NLMSG_ERROR)
+ {
+ struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA (h);
+ /* If the error field is zero, then this is an ACK */
+ if (err->error == 0)
+ {
+ // ACK
+ /* return if not a multipart message, otherwise continue */
+ if (!(h->nlmsg_flags & NLM_F_MULTI))
+ {
+ break;
+ }
+ continue;
+ }
+
+ TEST_ASSERT (h->nlmsg_len >= NLMSG_LENGTH (sizeof (struct nlmsgerr)));
+ }
+
+ ifa = (struct ifaddrmsg *) NLMSG_DATA (h);
+ TEST_ASSERT (ifa->ifa_family == AF_INET || ifa->ifa_family == AF_INET6);
+ OUTPUT ("NL: family = " << (int)ifa->ifa_family);
+
+ TEST_ASSERT (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR);
+ TEST_ASSERT (h->nlmsg_len - NLMSG_LENGTH(sizeof (struct ifaddrmsg) >= 0));
+
+ // We didn't get into detail to parse attribute
+ }
+
+ close (sock);
+ TEST_ASSERT_UNEQUAL (sock, -1);
+
+}
+
+int main (int argc, char *argv[])
+{
+ test_raw ();
+ test_udp ();
+ test_tcp ();
+ test_netlink ();
+ return 0;
+}
« no previous file with comments | « src/process-manager/simu-fd.cc ('k') | src/process-manager/tests/wscript » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b