test: Add bunch of tests for udp protocol
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Mon, 25 Aug 2014 12:55:53 +0000 (20:55 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Mon, 25 Aug 2014 12:55:53 +0000 (20:55 +0800)
They test various combination of bind(2), connect(2) and sendto(2)
for both unicast and multicast.  Unicast tests work w/ udpecho in
tools/netrate.  Multicast tests work w/ mcastsend.

20 files changed:
test/udp/bindconnfail/Makefile [new file with mode: 0644]
test/udp/bindconnfail/udp_bindconnfail.c [new file with mode: 0644]
test/udp/bindconnsend/Makefile [new file with mode: 0644]
test/udp/bindconnsend/udp_bindconnsend.c [new file with mode: 0644]
test/udp/bindsend/Makefile [new file with mode: 0644]
test/udp/bindsend/udp_bindsend.c [new file with mode: 0644]
test/udp/conn2send/Makefile [new file with mode: 0644]
test/udp/conn2send/udp_conn2send.c [new file with mode: 0644]
test/udp/connsend/Makefile [new file with mode: 0644]
test/udp/connsend/udp_connsend.c [new file with mode: 0644]
test/udp/mcastbind/Makefile [new file with mode: 0644]
test/udp/mcastbind/mcastbind.c [new file with mode: 0644]
test/udp/mcastconn/Makefile [new file with mode: 0644]
test/udp/mcastconn/mcastconn.c [new file with mode: 0644]
test/udp/mcastsend/Makefile [new file with mode: 0644]
test/udp/mcastsend/mcastsend.c [new file with mode: 0644]
test/udp/sendwildcard/Makefile [new file with mode: 0644]
test/udp/sendwildcard/udp_sendwildcard.c [new file with mode: 0644]
test/udp/sockclose/Makefile [new file with mode: 0644]
test/udp/sockclose/udp_sockclose.c [new file with mode: 0644]

diff --git a/test/udp/bindconnfail/Makefile b/test/udp/bindconnfail/Makefile
new file mode 100644 (file)
index 0000000..58f846b
--- /dev/null
@@ -0,0 +1,6 @@
+PROG = udp_bindconnfail
+WARNS = 6
+NOMAN = YES
+BINDIR=        /usr/local/bin
+
+.include <bsd.prog.mk>
diff --git a/test/udp/bindconnfail/udp_bindconnfail.c b/test/udp/bindconnfail/udp_bindconnfail.c
new file mode 100644 (file)
index 0000000..7f42b7e
--- /dev/null
@@ -0,0 +1,106 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void
+usage(const char *cmd)
+{
+       fprintf(stderr, "%s -4 ip4 -p port [-b ip4] -P bind_port\n", cmd);
+       exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+       struct sockaddr_in in, local_in;
+       int s1, s2, opt, n, on = 1;
+       uint8_t buf[18];
+
+       memset(&in, 0, sizeof(in));
+       in.sin_family = AF_INET;
+
+       memset(&local_in, 0, sizeof(local_in));
+       local_in.sin_family = AF_INET;
+
+       while ((opt = getopt(argc, argv, "4:P:b:p:")) != -1) {
+               switch (opt) {
+               case '4':
+                       if (inet_pton(AF_INET, optarg, &in.sin_addr) <= 0)
+                               usage(argv[0]);
+                       break;
+
+               case 'P':
+                       local_in.sin_port = strtol(optarg, NULL, 10);
+                       local_in.sin_port = htons(local_in.sin_port);
+                       break;
+
+               case 'b':
+                       if (inet_pton(AF_INET, optarg, &local_in.sin_addr) <= 0)
+                               usage(argv[0]);
+                       break;
+
+               case 'p':
+                       in.sin_port = strtol(optarg, NULL, 10);
+                       in.sin_port = htons(in.sin_port);
+                       break;
+
+               default:
+                       usage(argv[0]);
+               }
+       }
+
+       if (in.sin_addr.s_addr == INADDR_ANY || in.sin_port == 0 ||
+           local_in.sin_port == 0)
+               usage(argv[0]);
+
+       s1 = socket(AF_INET, SOCK_DGRAM, 0);
+       if (s1 < 0)
+               err(2, "socket 1 failed");
+
+       if (setsockopt(s1, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0)
+               err(2, "setsockopt 1 SO_REUSEPORT failed");
+
+       if (bind(s1, (const struct sockaddr *)&local_in, sizeof(local_in)) < 0)
+               err(2, "bind 1 failed");
+
+       if (connect(s1, (const struct sockaddr *)&in, sizeof(in)) < 0)
+               err(2, "connect 1 failed");
+
+       s2 = socket(AF_INET, SOCK_DGRAM, 0);
+       if (s2 < 0)
+               err(2, "socket 2 failed");
+
+       if (setsockopt(s2, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0)
+               err(2, "setsockopt 2 SO_REUSEPORT failed");
+
+       if (bind(s2, (const struct sockaddr *)&local_in, sizeof(local_in)) < 0)
+               err(2, "bind 2 failed");
+
+       if (connect(s2, (const struct sockaddr *)&in, sizeof(in)) == 0)
+               errx(2, "connect 2 succeeded");
+
+       close(s1);
+
+       n = sendto(s2, buf, sizeof(buf), 0,
+           (const struct sockaddr *)&in, sizeof(in));
+       if (n < 0)
+               err(2, "sendto failed");
+       else if (n != (int)sizeof(buf))
+               errx(2, "sent truncated data %d", n);
+
+       n = read(s2, buf, sizeof(buf));
+       if (n < 0)
+               err(2, "read failed");
+       printf("read %d, done\n", n);
+
+       exit(0);
+}
diff --git a/test/udp/bindconnsend/Makefile b/test/udp/bindconnsend/Makefile
new file mode 100644 (file)
index 0000000..2ea001c
--- /dev/null
@@ -0,0 +1,6 @@
+PROG = udp_bindconnsend
+WARNS = 6
+NOMAN = YES
+BINDIR=        /usr/local/bin
+
+.include <bsd.prog.mk>
diff --git a/test/udp/bindconnsend/udp_bindconnsend.c b/test/udp/bindconnsend/udp_bindconnsend.c
new file mode 100644 (file)
index 0000000..09ef6d2
--- /dev/null
@@ -0,0 +1,87 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void
+usage(const char *cmd)
+{
+       fprintf(stderr, "%s -4 ip4 -p port [-b ip4] -P bind_port\n", cmd);
+       exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+       struct sockaddr_in in, local_in;
+       int s, opt, n;
+       uint8_t buf[18];
+
+       memset(&in, 0, sizeof(in));
+       in.sin_family = AF_INET;
+
+       memset(&local_in, 0, sizeof(local_in));
+       local_in.sin_family = AF_INET;
+
+       while ((opt = getopt(argc, argv, "4:P:b:p:")) != -1) {
+               switch (opt) {
+               case '4':
+                       if (inet_pton(AF_INET, optarg, &in.sin_addr) <= 0)
+                               usage(argv[0]);
+                       break;
+
+               case 'P':
+                       local_in.sin_port = strtol(optarg, NULL, 10);
+                       local_in.sin_port = htons(local_in.sin_port);
+                       break;
+
+               case 'b':
+                       if (inet_pton(AF_INET, optarg, &local_in.sin_addr) <= 0)
+                               usage(argv[0]);
+                       break;
+
+               case 'p':
+                       in.sin_port = strtol(optarg, NULL, 10);
+                       in.sin_port = htons(in.sin_port);
+                       break;
+
+               default:
+                       usage(argv[0]);
+               }
+       }
+
+       if (in.sin_addr.s_addr == INADDR_ANY || in.sin_port == 0 ||
+           local_in.sin_port == 0)
+               usage(argv[0]);
+
+       s = socket(AF_INET, SOCK_DGRAM, 0);
+       if (s < 0)
+               err(2, "socket failed");
+
+       if (bind(s, (const struct sockaddr *)&local_in, sizeof(local_in)) < 0)
+               err(2, "bind failed");
+
+       if (connect(s, (const struct sockaddr *)&in, sizeof(in)) < 0)
+               err(2, "connect failed");
+
+       n = write(s, buf, sizeof(buf));
+       if (n < 0)
+               err(2, "write failed");
+       else if (n != (int)sizeof(buf))
+               errx(2, "written truncated data %d", n);
+
+       n = read(s, buf, sizeof(buf));
+       if (n < 0)
+               err(2, "read failed");
+       printf("read %d, done\n", n);
+
+       exit(0);
+}
diff --git a/test/udp/bindsend/Makefile b/test/udp/bindsend/Makefile
new file mode 100644 (file)
index 0000000..fdf7cbb
--- /dev/null
@@ -0,0 +1,6 @@
+PROG = udp_bindsend
+WARNS = 6
+NOMAN = YES
+BINDIR=        /usr/local/bin
+
+.include <bsd.prog.mk>
diff --git a/test/udp/bindsend/udp_bindsend.c b/test/udp/bindsend/udp_bindsend.c
new file mode 100644 (file)
index 0000000..6c97d5d
--- /dev/null
@@ -0,0 +1,85 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void
+usage(const char *cmd)
+{
+       fprintf(stderr, "%s -4 ip4 -p port [-b ip4] -P bind_port\n", cmd);
+       exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+       struct sockaddr_in in, local_in;
+       int s, opt, n;
+       uint8_t buf[18];
+
+       memset(&in, 0, sizeof(in));
+       in.sin_family = AF_INET;
+
+       memset(&local_in, 0, sizeof(local_in));
+       local_in.sin_family = AF_INET;
+
+       while ((opt = getopt(argc, argv, "4:P:b:p:")) != -1) {
+               switch (opt) {
+               case '4':
+                       if (inet_pton(AF_INET, optarg, &in.sin_addr) <= 0)
+                               usage(argv[0]);
+                       break;
+
+               case 'P':
+                       local_in.sin_port = strtol(optarg, NULL, 10);
+                       local_in.sin_port = htons(local_in.sin_port);
+                       break;
+
+               case 'b':
+                       if (inet_pton(AF_INET, optarg, &local_in.sin_addr) <= 0)
+                               usage(argv[0]);
+                       break;
+
+               case 'p':
+                       in.sin_port = strtol(optarg, NULL, 10);
+                       in.sin_port = htons(in.sin_port);
+                       break;
+
+               default:
+                       usage(argv[0]);
+               }
+       }
+
+       if (in.sin_addr.s_addr == INADDR_ANY || in.sin_port == 0 ||
+           local_in.sin_port == 0)
+               usage(argv[0]);
+
+       s = socket(AF_INET, SOCK_DGRAM, 0);
+       if (s < 0)
+               err(2, "socket failed");
+
+       if (bind(s, (const struct sockaddr *)&local_in, sizeof(local_in)) < 0)
+               err(2, "bind failed");
+
+       n = sendto(s, buf, sizeof(buf), 0,
+           (const struct sockaddr *)&in, sizeof(in));
+       if (n < 0)
+               err(2, "sendto failed");
+       else if (n != (int)sizeof(buf))
+               errx(2, "sent truncated data %d", n);
+
+       n = read(s, buf, sizeof(buf));
+       if (n < 0)
+               err(2, "read failed");
+       printf("read %d, done\n", n);
+
+       exit(0);
+}
diff --git a/test/udp/conn2send/Makefile b/test/udp/conn2send/Makefile
new file mode 100644 (file)
index 0000000..0e37add
--- /dev/null
@@ -0,0 +1,6 @@
+PROG = udp_conn2send
+WARNS = 6
+NOMAN = YES
+BINDIR=        /usr/local/bin
+
+.include <bsd.prog.mk>
diff --git a/test/udp/conn2send/udp_conn2send.c b/test/udp/conn2send/udp_conn2send.c
new file mode 100644 (file)
index 0000000..1073eeb
--- /dev/null
@@ -0,0 +1,81 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void
+usage(const char *cmd)
+{
+       fprintf(stderr, "%s -4 ip4 -p port\n", cmd);
+       exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+       struct sockaddr_in in, in2;
+       int s, opt, n;
+       uint8_t buf[18];
+
+       memset(&in, 0, sizeof(in));
+       in.sin_family = AF_INET;
+
+       while ((opt = getopt(argc, argv, "4:p:")) != -1) {
+               switch (opt) {
+               case '4':
+                       if (inet_pton(AF_INET, optarg, &in.sin_addr) <= 0)
+                               usage(argv[0]);
+                       break;
+
+               case 'p':
+                       in.sin_port = strtol(optarg, NULL, 10);
+                       in.sin_port = htons(in.sin_port);
+                       break;
+
+               default:
+                       usage(argv[0]);
+               }
+       }
+
+       if (in.sin_addr.s_addr == INADDR_ANY || in.sin_port == 0)
+               usage(argv[0]);
+
+       s = socket(AF_INET, SOCK_DGRAM, 0);
+       if (s < 0)
+               err(2, "socket failed");
+
+       if (connect(s, (const struct sockaddr *)&in, sizeof(in)) < 0)
+               err(2, "connect failed");
+
+       memset(&in2, 0, sizeof(in2));
+       in2.sin_family = AF_UNSPEC;
+       if (connect(s, (const struct sockaddr *)&in2, sizeof(in2)) < 0) {
+               int error = errno;
+
+               if (error != EAFNOSUPPORT)
+                       errc(2, error, "di-connect failed");
+       }
+
+       n = sendto(s, buf, sizeof(buf), 0,
+           (const struct sockaddr *)&in, sizeof(in));
+       if (n < 0)
+               err(2, "sendto failed");
+       else if (n != (int)sizeof(buf))
+               errx(2, "sent truncated data %d", n);
+
+       n = read(s, buf, sizeof(buf));
+       if (n < 0)
+               err(2, "read failed");
+       printf("read %d, done\n", n);
+
+       exit(0);
+}
diff --git a/test/udp/connsend/Makefile b/test/udp/connsend/Makefile
new file mode 100644 (file)
index 0000000..e422ed7
--- /dev/null
@@ -0,0 +1,6 @@
+PROG = udp_connsend
+WARNS = 6
+NOMAN = YES
+BINDIR=        /usr/local/bin
+
+.include <bsd.prog.mk>
diff --git a/test/udp/connsend/udp_connsend.c b/test/udp/connsend/udp_connsend.c
new file mode 100644 (file)
index 0000000..053760f
--- /dev/null
@@ -0,0 +1,70 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void
+usage(const char *cmd)
+{
+       fprintf(stderr, "%s -4 ip4 -p port\n", cmd);
+       exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+       struct sockaddr_in in;
+       int s, opt, n;
+       uint8_t buf[18];
+
+       memset(&in, 0, sizeof(in));
+       in.sin_family = AF_INET;
+
+       while ((opt = getopt(argc, argv, "4:p:")) != -1) {
+               switch (opt) {
+               case '4':
+                       if (inet_pton(AF_INET, optarg, &in.sin_addr) <= 0)
+                               usage(argv[0]);
+                       break;
+
+               case 'p':
+                       in.sin_port = strtol(optarg, NULL, 10);
+                       in.sin_port = htons(in.sin_port);
+                       break;
+
+               default:
+                       usage(argv[0]);
+               }
+       }
+
+       if (in.sin_addr.s_addr == INADDR_ANY || in.sin_port == 0)
+               usage(argv[0]);
+
+       s = socket(AF_INET, SOCK_DGRAM, 0);
+       if (s < 0)
+               err(2, "socket failed");
+
+       if (connect(s, (const struct sockaddr *)&in, sizeof(in)) < 0)
+               err(2, "connect failed");
+
+       n = write(s, buf, sizeof(buf));
+       if (n < 0)
+               err(2, "write failed");
+       else if (n != (int)sizeof(buf))
+               errx(2, "written truncated data %d", n);
+
+       n = read(s, buf, sizeof(buf));
+       if (n < 0)
+               err(2, "read failed");
+       printf("read %d, done\n", n);
+
+       exit(0);
+}
diff --git a/test/udp/mcastbind/Makefile b/test/udp/mcastbind/Makefile
new file mode 100644 (file)
index 0000000..a584e17
--- /dev/null
@@ -0,0 +1,6 @@
+PROG = mcastbind
+WARNS = 6
+NOMAN = YES
+BINDIR=        /usr/local/bin
+
+.include <bsd.prog.mk>
diff --git a/test/udp/mcastbind/mcastbind.c b/test/udp/mcastbind/mcastbind.c
new file mode 100644 (file)
index 0000000..ce635b6
--- /dev/null
@@ -0,0 +1,112 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <err.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void
+usage(const char *cmd)
+{
+       fprintf(stderr, "%s -m addr -p port -i addr [-a]\n", cmd);
+       exit(1);
+}
+
+static int
+create_sock(const struct sockaddr_in *in0, const struct in_addr *iface,
+    int bind_any)
+{
+       struct ip_mreq mreq;
+       struct sockaddr_in in;
+       int s, on;
+
+       s = socket(AF_INET, SOCK_DGRAM, 0);
+       if (s < 0)
+               err(2, "socket failed");
+
+       on = 1;
+       if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0)
+               err(2, "setsockopt SO_REUSEPORT failed");
+
+       in = *in0;
+       if (bind_any)
+               in.sin_addr.s_addr = htonl(INADDR_ANY);
+
+       if (bind(s, (const struct sockaddr *)&in, sizeof(in)) < 0)
+               err(2, "bind failed");
+
+       memset(&mreq, 0, sizeof(mreq));
+       mreq.imr_multiaddr = in0->sin_addr;
+       mreq.imr_interface = *iface;
+       if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+           &mreq, sizeof(mreq)) < 0)
+               err(2, "setsockopt IP_ADD_MEMBERSHIP failed");
+
+       return s;
+}
+
+int
+main(int argc, char *argv[])
+{
+       struct sockaddr_in in;
+       struct in_addr iface;
+       int s1, s2, opt, n, bind_any;
+       uint8_t buf[18];
+
+       memset(&in, 0, sizeof(in));
+       in.sin_family = AF_INET;
+
+       memset(&iface, 0, sizeof(iface));
+       bind_any = 0;
+
+       while ((opt = getopt(argc, argv, "ai:m:p:")) != -1) {
+               switch (opt) {
+               case 'a':
+                       bind_any = 1;
+                       break;
+
+               case 'i':
+                       if (inet_pton(AF_INET, optarg, &iface) <= 0)
+                               usage(argv[0]);
+                       break;
+
+               case 'm':
+                       if (inet_pton(AF_INET, optarg, &in.sin_addr) <= 0)
+                               usage(argv[0]);
+                       break;
+
+               case 'p':
+                       in.sin_port = strtol(optarg, NULL, 10);
+                       in.sin_port = htons(in.sin_port);
+                       break;
+
+               default:
+                       usage(argv[0]);
+               }
+       }
+
+       if (in.sin_addr.s_addr == INADDR_ANY || in.sin_port == 0 ||
+           iface.s_addr == INADDR_ANY)
+               usage(argv[0]);
+
+       s1 = create_sock(&in, &iface, bind_any);
+       s2 = create_sock(&in, &iface, bind_any);
+
+       n = read(s1, buf, sizeof(buf));
+       if (n < 0)
+               err(2, "read 1 failed");
+       fprintf(stderr, "read 1 got %d\n", n);
+
+       n = read(s2, buf, sizeof(buf));
+       if (n < 0)
+               err(2, "read 2 failed");
+       fprintf(stderr, "read 2 got %d\n", n);
+
+       exit(0);
+}
diff --git a/test/udp/mcastconn/Makefile b/test/udp/mcastconn/Makefile
new file mode 100644 (file)
index 0000000..7bbfb6b
--- /dev/null
@@ -0,0 +1,6 @@
+PROG = mcastconn
+WARNS = 6
+NOMAN = YES
+BINDIR=        /usr/local/bin
+
+.include <bsd.prog.mk>
diff --git a/test/udp/mcastconn/mcastconn.c b/test/udp/mcastconn/mcastconn.c
new file mode 100644 (file)
index 0000000..ddc1fc2
--- /dev/null
@@ -0,0 +1,122 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <err.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void
+usage(const char *cmd)
+{
+       fprintf(stderr, "%s -m addr -p port -i addr "
+           "-r remote_ip4 -P remote_port\n", cmd);
+       exit(1);
+}
+
+static int
+create_sock(const struct sockaddr_in *in, const struct in_addr *iface)
+{
+       struct ip_mreq mreq;
+       int s, on;
+
+       s = socket(AF_INET, SOCK_DGRAM, 0);
+       if (s < 0)
+               err(2, "socket failed");
+
+       on = 1;
+       if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0)
+               err(2, "setsockopt SO_REUSEPORT failed");
+
+       if (bind(s, (const struct sockaddr *)in, sizeof(*in)) < 0)
+               err(2, "bind failed");
+
+       memset(&mreq, 0, sizeof(mreq));
+       mreq.imr_multiaddr = in->sin_addr;
+       mreq.imr_interface = *iface;
+       if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+           &mreq, sizeof(mreq)) < 0)
+               err(2, "setsockopt IP_ADD_MEMBERSHIP failed");
+
+       return s;
+}
+
+int
+main(int argc, char *argv[])
+{
+       struct sockaddr_in in, remote_in;
+       struct in_addr iface;
+       int s1, s2, opt, n;
+       uint8_t buf[18];
+
+       memset(&in, 0, sizeof(in));
+       in.sin_family = AF_INET;
+
+       memset(&remote_in, 0, sizeof(remote_in));
+       remote_in.sin_family = AF_INET;
+
+       memset(&iface, 0, sizeof(iface));
+
+       while ((opt = getopt(argc, argv, "P:i:m:p:r:")) != -1) {
+               switch (opt) {
+               case 'P':
+                       remote_in.sin_port = strtol(optarg, NULL, 10);
+                       remote_in.sin_port = htons(remote_in.sin_port);
+                       break;
+
+               case 'i':
+                       if (inet_pton(AF_INET, optarg, &iface) <= 0)
+                               usage(argv[0]);
+                       break;
+
+               case 'm':
+                       if (inet_pton(AF_INET, optarg, &in.sin_addr) <= 0)
+                               usage(argv[0]);
+                       break;
+
+               case 'p':
+                       in.sin_port = strtol(optarg, NULL, 10);
+                       in.sin_port = htons(in.sin_port);
+                       break;
+
+               case 'r':
+                       if (inet_pton(AF_INET, optarg,
+                           &remote_in.sin_addr) <= 0)
+                               usage(argv[0]);
+                       break;
+
+               default:
+                       usage(argv[0]);
+               }
+       }
+
+       if (in.sin_addr.s_addr == INADDR_ANY || in.sin_port == 0 ||
+           iface.s_addr == INADDR_ANY ||
+           remote_in.sin_addr.s_addr == INADDR_ANY ||
+           remote_in.sin_port == 0)
+               usage(argv[0]);
+
+       s1 = create_sock(&in, &iface);
+       s2 = create_sock(&in, &iface);
+
+       if (connect(s2, (const struct sockaddr *)&remote_in,
+           sizeof(remote_in)) < 0)
+               err(2, "connect failed");
+
+       n = read(s1, buf, sizeof(buf));
+       if (n < 0)
+               err(2, "read 1 failed");
+       fprintf(stderr, "read 1 got %d\n", n);
+
+       n = read(s2, buf, sizeof(buf));
+       if (n < 0)
+               err(2, "read 2 failed");
+       fprintf(stderr, "read 2 got %d\n", n);
+
+       exit(0);
+}
diff --git a/test/udp/mcastsend/Makefile b/test/udp/mcastsend/Makefile
new file mode 100644 (file)
index 0000000..6ab4d4f
--- /dev/null
@@ -0,0 +1,6 @@
+PROG = mcastsend
+WARNS = 6
+NOMAN = YES
+BINDIR=        /usr/local/bin
+
+.include <bsd.prog.mk>
diff --git a/test/udp/mcastsend/mcastsend.c b/test/udp/mcastsend/mcastsend.c
new file mode 100644 (file)
index 0000000..b15d08c
--- /dev/null
@@ -0,0 +1,95 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <err.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void
+usage(const char *cmd)
+{
+       fprintf(stderr, "%s -p port -d dst -i addr [-P bind_port]\n", cmd);
+       exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+       struct sockaddr_in dst, local_in;
+       struct in_addr iface;
+       int s, opt, n, loop = 0;
+       uint8_t buf[18];
+
+       memset(&dst, 0, sizeof(dst));
+       dst.sin_family = AF_INET;
+
+       memset(&local_in, 0, sizeof(local_in));
+       local_in.sin_family = AF_INET;
+
+       memset(&iface, 0, sizeof(iface));
+
+       while ((opt = getopt(argc, argv, "P:d:i:p:")) != -1) {
+               switch (opt) {
+               case 'P':
+                       local_in.sin_port = strtol(optarg, NULL, 10);
+                       local_in.sin_port = htons(local_in.sin_port);
+                       break;
+
+               case 'd':
+                       if (inet_pton(AF_INET, optarg, &dst.sin_addr) <= 0)
+                               usage(argv[0]);
+                       break;
+
+               case 'i':
+                       if (inet_pton(AF_INET, optarg, &iface) <= 0)
+                               usage(argv[0]);
+                       break;
+
+               case 'p':
+                       dst.sin_port = strtol(optarg, NULL, 10);
+                       dst.sin_port = htons(dst.sin_port);
+                       break;
+
+               default:
+                       usage(argv[0]);
+               }
+       }
+
+       if (iface.s_addr == INADDR_ANY ||
+           dst.sin_addr.s_addr == INADDR_ANY || dst.sin_port == 0)
+               usage(argv[0]);
+
+       s = socket(AF_INET, SOCK_DGRAM, 0);
+       if (s < 0)
+               err(2, "socket failed");
+
+       if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF,
+           &iface, sizeof(iface)) < 0)
+               err(2, "setsockopt IP_MULTICAST_IF failed");
+
+       if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP,
+           &loop, sizeof(loop)) < 0)
+               err(2, "setsockopt IP_MULTICAST_LOOP failed");
+
+       if (local_in.sin_port != 0) {
+               local_in.sin_addr = iface;
+               if (bind(s, (const struct sockaddr *)&local_in,
+                   sizeof(local_in)) < 0)
+                       err(2, "bind failed");
+       }
+
+       n = sendto(s, buf, sizeof(buf), 0,
+           (const struct sockaddr *)&dst, sizeof(dst));
+       if (n < 0)
+               err(2, "sendto failed");
+       else if (n < (int)sizeof(buf))
+               errx(2, "sent truncated data %d", n);
+
+       exit(0);
+}
diff --git a/test/udp/sendwildcard/Makefile b/test/udp/sendwildcard/Makefile
new file mode 100644 (file)
index 0000000..8e24d06
--- /dev/null
@@ -0,0 +1,6 @@
+PROG = udp_sendwildcard
+WARNS = 6
+NOMAN = YES
+BINDIR=        /usr/local/bin
+
+.include <bsd.prog.mk>
diff --git a/test/udp/sendwildcard/udp_sendwildcard.c b/test/udp/sendwildcard/udp_sendwildcard.c
new file mode 100644 (file)
index 0000000..b9a0ea3
--- /dev/null
@@ -0,0 +1,68 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void
+usage(const char *cmd)
+{
+       fprintf(stderr, "%s -4 ip4 -p port\n", cmd);
+       exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+       struct sockaddr_in in;
+       int s, opt, n;
+       uint8_t buf[18];
+
+       memset(&in, 0, sizeof(in));
+       in.sin_family = AF_INET;
+
+       while ((opt = getopt(argc, argv, "4:p:")) != -1) {
+               switch (opt) {
+               case '4':
+                       if (inet_pton(AF_INET, optarg, &in.sin_addr) <= 0)
+                               usage(argv[0]);
+                       break;
+
+               case 'p':
+                       in.sin_port = strtol(optarg, NULL, 10);
+                       in.sin_port = htons(in.sin_port);
+                       break;
+
+               default:
+                       usage(argv[0]);
+               }
+       }
+
+       if (in.sin_addr.s_addr == INADDR_ANY || in.sin_port == 0)
+               usage(argv[0]);
+
+       s = socket(AF_INET, SOCK_DGRAM, 0);
+       if (s < 0)
+               err(2, "socket failed");
+
+       n = sendto(s, buf, sizeof(buf), 0,
+           (const struct sockaddr *)&in, sizeof(in));
+       if (n < 0)
+               err(2, "sendto failed");
+       else if (n != (int)sizeof(buf))
+               errx(2, "sent truncated data %d", n);
+
+       n = read(s, buf, sizeof(buf));
+       if (n < 0)
+               err(2, "read failed");
+       printf("read %d, done\n", n);
+
+       exit(0);
+}
diff --git a/test/udp/sockclose/Makefile b/test/udp/sockclose/Makefile
new file mode 100644 (file)
index 0000000..6b9f3f4
--- /dev/null
@@ -0,0 +1,6 @@
+PROG = udp_sockclose
+WARNS = 6
+NOMAN = YES
+BINDIR=        /usr/local/bin
+
+.include <bsd.prog.mk>
diff --git a/test/udp/sockclose/udp_sockclose.c b/test/udp/sockclose/udp_sockclose.c
new file mode 100644 (file)
index 0000000..d5caffd
--- /dev/null
@@ -0,0 +1,48 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static void
+usage(const char *cmd)
+{
+       fprintf(stderr, "%s -n count\n", cmd);
+       exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+       int i, opt, count;
+
+       count = 0;
+       while ((opt = getopt(argc, argv, "n:")) != -1) {
+               switch (opt) {
+               case 'n':
+                       count = strtol(optarg, NULL, 10);
+                       break;
+
+               default:
+                       usage(argv[0]);
+               }
+       }
+       if (count == 0)
+               usage(argv[0]);
+
+       for (i = 0; i < count; ++i) {
+               int s;
+
+               s = socket(AF_INET, SOCK_DGRAM, 0);
+               if (s < 0)
+                       err(2, "socket failed");
+               close(s);
+       }
+       printf("done\n");
+       exit(0);
+}