tests: add a test for -yy option
* tests/net-yy.test: New test. * tests/inet-accept-connect-send-recv.c: New file. * tests/netlink_inet_diag.c: Likewise. * tests/net-yy-accept.awk: Likewise. * tests/net-yy-connect.awk: Likewise. * tests/.gitignore: Add inet-accept-connect-send-recv, netlink_inet_diag, *.tmp-*, and *.tmp.*. * tests/Makefile.am (check_PROGRAMS): Add inet-accept-connect-send-recv and netlink_inet_diag. (TESTS): Add net-yy.test. (EXTRA_DIST): Add net-yy-accept.awk and net-yy-connect.awk.
This commit is contained in:
parent
9a0dd74ae0
commit
fdfa72276a
6
tests/.gitignore
vendored
6
tests/.gitignore
vendored
@ -1,4 +1,6 @@
|
||||
inet-accept-connect-send-recv
|
||||
net-accept-connect
|
||||
netlink_inet_diag
|
||||
scm_rights
|
||||
set_ptracer_any
|
||||
sigaction
|
||||
@ -8,5 +10,7 @@ uio
|
||||
*.log
|
||||
*.log.*
|
||||
*.o
|
||||
*.trs
|
||||
*.tmp
|
||||
*.tmp-*
|
||||
*.tmp.*
|
||||
*.trs
|
||||
|
@ -3,7 +3,9 @@
|
||||
AM_CFLAGS = $(WARN_CFLAGS)
|
||||
|
||||
check_PROGRAMS = \
|
||||
inet-accept-connect-send-recv \
|
||||
net-accept-connect \
|
||||
netlink_inet_diag \
|
||||
scm_rights \
|
||||
set_ptracer_any \
|
||||
sigaction \
|
||||
@ -27,6 +29,7 @@ TESTS = \
|
||||
statfs.test \
|
||||
net.test \
|
||||
net-fd.test \
|
||||
net-yy.test \
|
||||
uio.test \
|
||||
count.test \
|
||||
detach-sleeping.test \
|
||||
@ -38,6 +41,11 @@ net-fd.log: net.log
|
||||
|
||||
TEST_LOG_COMPILER = $(srcdir)/run.sh
|
||||
|
||||
EXTRA_DIST = init.sh run.sh getdents.awk sigaction.awk $(TESTS)
|
||||
EXTRA_DIST = init.sh run.sh \
|
||||
getdents.awk \
|
||||
net-yy-accept.awk \
|
||||
net-yy-connect.awk \
|
||||
sigaction.awk \
|
||||
$(TESTS)
|
||||
|
||||
CLEANFILES = $(TESTS:=.tmp)
|
||||
|
53
tests/inet-accept-connect-send-recv.c
Normal file
53
tests/inet-accept-connect-send-recv.c
Normal file
@ -0,0 +1,53 @@
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
static const char data[] = "data";
|
||||
const size_t size = sizeof(data) - 1;
|
||||
struct sockaddr_in addr;
|
||||
socklen_t len = sizeof(addr);
|
||||
pid_t pid;
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
|
||||
close(0);
|
||||
close(1);
|
||||
|
||||
assert(socket(PF_INET, SOCK_STREAM, 0) == 0);
|
||||
assert(bind(0, (struct sockaddr *) &addr, len) == 0);
|
||||
assert(listen(0, 5) == 0);
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
assert(getsockname(0, (struct sockaddr *) &addr, &len) == 0);
|
||||
|
||||
assert((pid = fork()) >= 0);
|
||||
|
||||
if (pid) {
|
||||
char buf[sizeof(data)];
|
||||
int status;
|
||||
|
||||
assert(accept(0, (struct sockaddr *) &addr, &len) == 1);
|
||||
assert(close(0) == 0);
|
||||
assert(recv(1, buf, sizeof(buf), MSG_WAITALL) == (int) size);
|
||||
assert(waitpid(pid, &status, 0) == pid);
|
||||
assert(status == 0);
|
||||
assert(close(1) == 0);
|
||||
} else {
|
||||
assert(close(0) == 0);
|
||||
assert(socket(PF_INET, SOCK_STREAM, 0) == 0);
|
||||
assert(connect(0, (struct sockaddr *) &addr, len) == 0);
|
||||
assert(send(0, data, size, MSG_DONTROUTE) == (int) size);
|
||||
assert(close(0) == 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
76
tests/net-yy-accept.awk
Normal file
76
tests/net-yy-accept.awk
Normal file
@ -0,0 +1,76 @@
|
||||
BEGIN {
|
||||
lines = 9
|
||||
fail = 0
|
||||
|
||||
inode = "?"
|
||||
port_l = "?"
|
||||
port_r = "?"
|
||||
|
||||
r_i = "[1-9][0-9]*"
|
||||
r_port = "[1-9][0-9][0-9][0-9]+"
|
||||
r_localhost = "127\\.0\\.0\\.1"
|
||||
r_bind = "^bind\\(0<socket:\\[(" r_i ")\\]>, {sa_family=AF_INET, sin_port=htons\\(0\\), sin_addr=inet_addr\\(\"" r_localhost "\"\\)}, " r_i "\\) += 0$"
|
||||
r_listen = "^/$"
|
||||
r_getsockname = "^getsockname\\(0<" r_localhost ":(" r_port ")>, {sa_family=AF_INET, sin_port=htons\\((" r_port ")\\), sin_addr=inet_addr\\(\"" r_localhost "\"\\)}, \\[" r_i "\\]\\) += 0$"
|
||||
r_accept = "^/$"
|
||||
r_close0 = "^/$"
|
||||
r_recv = "^/$"
|
||||
r_recvfrom = "^/$"
|
||||
r_close1 = "^/$"
|
||||
}
|
||||
|
||||
NR == 1 && /^socket\(PF_INET, SOCK_STREAM, IPPROTO_IP\) += 0$/ {next}
|
||||
|
||||
NR == 2 {
|
||||
if (match($0, r_bind, a)) {
|
||||
inode = a[1]
|
||||
r_listen = "^listen\\(0<socket:\\[" inode "\\]>, 5\\) += 0$"
|
||||
next
|
||||
}
|
||||
}
|
||||
|
||||
NR == 3 {if (match($0, r_listen)) next}
|
||||
|
||||
NR == 4 {
|
||||
if (match($0, r_getsockname, a) && a[1] == a[2]) {
|
||||
port_l = a[1]
|
||||
r_accept = "^accept\\(0<" r_localhost ":" port_l ">, {sa_family=AF_INET, sin_port=htons\\((" r_port ")\\), sin_addr=inet_addr\\(\"" r_localhost "\"\\)}, \\[" r_i "\\]\\) += 1<" r_localhost ":" port_l "->" r_localhost ":(" r_port ")>$"
|
||||
r_close0 = "^close\\(0<" r_localhost ":" port_l ">) += 0$"
|
||||
next
|
||||
}
|
||||
}
|
||||
|
||||
NR == 5 {
|
||||
if (match($0, r_accept, a) && a[1] == a[2]) {
|
||||
port_r = a[1]
|
||||
r_recv = "^recv\\(1<" r_localhost ":" port_l "->" r_localhost ":" port_r ">, \"data\", 5, MSG_WAITALL\\) += 4$"
|
||||
r_recvfrom = "^recvfrom\\(1<" r_localhost ":" port_l "->" r_localhost ":" port_r ">, \"data\", 5, MSG_WAITALL, NULL, NULL\\) += 4$"
|
||||
r_close1 = "^close\\(1<" r_localhost ":" port_l "->" r_localhost ":" port_r ">) += 0$"
|
||||
next
|
||||
}
|
||||
}
|
||||
|
||||
NR == 6 {if (match($0, r_close0)) next}
|
||||
|
||||
NR == 7 {if (match($0, r_recv) || match($0, r_recvfrom)) next}
|
||||
|
||||
NR == 8 {if (match($0, r_close1)) next}
|
||||
|
||||
NR == lines && /^\+\+\+ exited with 0 \+\+\+$/ {next}
|
||||
|
||||
{
|
||||
print "Line " NR " does not match: " $0
|
||||
fail=1
|
||||
}
|
||||
|
||||
END {
|
||||
if (NR != lines) {
|
||||
print "Expected " lines " lines, found " NR " line(s)."
|
||||
print ""
|
||||
exit 1
|
||||
}
|
||||
if (fail) {
|
||||
print ""
|
||||
exit 1
|
||||
}
|
||||
}
|
55
tests/net-yy-connect.awk
Normal file
55
tests/net-yy-connect.awk
Normal file
@ -0,0 +1,55 @@
|
||||
BEGIN {
|
||||
lines = 5
|
||||
fail = 0
|
||||
|
||||
port_l = "?"
|
||||
port_r = "?"
|
||||
|
||||
r_i = "[1-9][0-9]*"
|
||||
r_port = "[1-9][0-9][0-9][0-9]+"
|
||||
r_localhost = "127\\.0\\.0\\.1"
|
||||
r_connect = "^connect\\(0<socket:\\[" r_i "\\]>, {sa_family=AF_INET, sin_port=htons\\((" r_port ")\\), sin_addr=inet_addr\\(\"" r_localhost "\"\\)}, " r_i ") += 0$"
|
||||
r_send = "^/$"
|
||||
r_sendto = "^/$"
|
||||
r_close = "^/$"
|
||||
}
|
||||
|
||||
NR == 1 && /^socket\(PF_INET, SOCK_STREAM, IPPROTO_IP\) += 0$/ {next}
|
||||
|
||||
NR == 2 {
|
||||
if (match($0, r_connect, a)) {
|
||||
port_r = a[1]
|
||||
r_send = "^send\\(0<" r_localhost ":(" r_port ")->" r_localhost ":" port_r ">, \"data\", 4, MSG_DONTROUTE\\) += 4$"
|
||||
r_sendto = "^sendto\\(0<" r_localhost ":(" r_port ")->" r_localhost ":" port_r ">, \"data\", 4, MSG_DONTROUTE, NULL, 0\\) += 4$"
|
||||
next
|
||||
}
|
||||
}
|
||||
|
||||
NR == 3 {
|
||||
if (match($0, r_send, a) || match($0, r_sendto, a)) {
|
||||
port_l = a[1]
|
||||
r_close = "^close\\(0<" r_localhost ":" port_l "->" r_localhost ":" port_r ">\\) += 0$"
|
||||
next
|
||||
}
|
||||
}
|
||||
|
||||
NR == 4 {if (match($0, r_close)) next}
|
||||
|
||||
NR == lines && /^\+\+\+ exited with 0 \+\+\+$/ {next}
|
||||
|
||||
{
|
||||
print "Line " NR " does not match: " $0
|
||||
fail=1
|
||||
}
|
||||
|
||||
END {
|
||||
if (NR != lines) {
|
||||
print "Expected " lines " lines, found " NR " line(s)."
|
||||
print ""
|
||||
exit 1
|
||||
}
|
||||
if (fail) {
|
||||
print ""
|
||||
exit 1
|
||||
}
|
||||
}
|
59
tests/net-yy.test
Executable file
59
tests/net-yy.test
Executable file
@ -0,0 +1,59 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Check decoding of ip:port pairs associated with socket descriptors
|
||||
|
||||
. "${srcdir=.}/init.sh"
|
||||
|
||||
# strace -yy is implemented using /proc/self/fd
|
||||
[ -d /proc/self/fd/ ] ||
|
||||
framework_skip_ '/proc/self/fd/ is not available'
|
||||
|
||||
check_prog sed
|
||||
check_prog awk
|
||||
|
||||
rm -f $LOG.* $LOG-*
|
||||
|
||||
./inet-accept-connect-send-recv ||
|
||||
fail_ 'inet-accept-connect-send-recv failed'
|
||||
|
||||
./netlink_inet_diag || {
|
||||
if [ $? -eq 77 ]; then
|
||||
framework_skip_ 'NETLINK_INET_DIAG is not available'
|
||||
else
|
||||
fail_ 'netlink_inet_diag failed'
|
||||
fi
|
||||
}
|
||||
|
||||
args="-tt -ff -yy -o $LOG -eclose,network ./inet-accept-connect-send-recv"
|
||||
$STRACE $args ||
|
||||
fail_ "strace $args failed"
|
||||
|
||||
"$srcdir"/../strace-log-merge $LOG > $LOG || {
|
||||
cat $LOG
|
||||
fail_ 'strace-log-merge failed'
|
||||
}
|
||||
rm -f $LOG.*
|
||||
|
||||
child="$(sed -rn '/SIGCHLD/ s/^.*, si_pid=([1-9][0-9]*), .*/\1/p' $LOG)"
|
||||
[ -n "$child" ] || {
|
||||
cat $LOG
|
||||
fail_ 'failed to find pid of child process'
|
||||
}
|
||||
|
||||
sed -rn "/^$child"' /!d; / socket\(/,$ s/^[0-9]+ +[^ ]+ (.+)/\1/p' $LOG > $LOG-connect &&
|
||||
sed -rn "/^$child"' /d; /SIGCHLD/d; / socket\(/,$ s/^[0-9]+ +[^ ]+ (.+)/\1/p' $LOG > $LOG-accept || {
|
||||
cat $LOG
|
||||
fail_ 'failed to separate logs'
|
||||
}
|
||||
|
||||
awk -f "$srcdir"/net-yy-connect.awk $LOG-connect || {
|
||||
cat $LOG-connect
|
||||
fail_ "strace $args failed to decode socket descriptors properly"
|
||||
}
|
||||
|
||||
awk -f "$srcdir"/net-yy-accept.awk $LOG-accept || {
|
||||
cat $LOG-accept
|
||||
fail_ "strace $args failed to decode socket descriptors properly"
|
||||
}
|
||||
|
||||
exit 0
|
96
tests/netlink_inet_diag.c
Normal file
96
tests/netlink_inet_diag.c
Normal file
@ -0,0 +1,96 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/sock_diag.h>
|
||||
#include <linux/inet_diag.h>
|
||||
|
||||
static int
|
||||
send_query(const int fd, const int family, const int proto)
|
||||
{
|
||||
struct sockaddr_nl nladdr;
|
||||
struct {
|
||||
struct nlmsghdr nlh;
|
||||
struct inet_diag_req_v2 idr;
|
||||
} req;
|
||||
struct iovec iov = {
|
||||
.iov_base = &req,
|
||||
.iov_len = sizeof(req)
|
||||
};
|
||||
struct msghdr msg = {
|
||||
.msg_name = (void*)&nladdr,
|
||||
.msg_namelen = sizeof(nladdr),
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1
|
||||
};
|
||||
|
||||
memset(&nladdr, 0, sizeof(nladdr));
|
||||
nladdr.nl_family = AF_NETLINK;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.nlh.nlmsg_len = sizeof(req);
|
||||
req.nlh.nlmsg_type = SOCK_DIAG_BY_FAMILY;
|
||||
req.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
|
||||
req.idr.sdiag_family = family;
|
||||
req.idr.sdiag_protocol = proto;
|
||||
req.idr.idiag_states = -1;
|
||||
|
||||
return sendmsg(fd, &msg, 0) > 0;
|
||||
}
|
||||
|
||||
static int
|
||||
check_responses(const int fd)
|
||||
{
|
||||
static char buf[8192];
|
||||
struct sockaddr_nl nladdr;
|
||||
struct iovec iov = {
|
||||
.iov_base = buf,
|
||||
.iov_len = sizeof(buf)
|
||||
};
|
||||
|
||||
memset(&nladdr, 0, sizeof(nladdr));
|
||||
nladdr.nl_family = AF_NETLINK;
|
||||
|
||||
struct msghdr msg = {
|
||||
.msg_name = (void*)&nladdr,
|
||||
.msg_namelen = sizeof(nladdr),
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
.msg_control = NULL,
|
||||
.msg_controllen = 0,
|
||||
.msg_flags = 0
|
||||
};
|
||||
|
||||
ssize_t ret = recvmsg(fd, &msg, 0);
|
||||
if (ret <= 0)
|
||||
return 0;
|
||||
|
||||
struct nlmsghdr *h = (struct nlmsghdr*)buf;
|
||||
return (NLMSG_OK(h, ret) &&
|
||||
h->nlmsg_type != NLMSG_ERROR &&
|
||||
h->nlmsg_type != NLMSG_DONE) ? 1 : 0;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
socklen_t len = sizeof(addr);
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
|
||||
close(0);
|
||||
close(1);
|
||||
|
||||
assert(socket(PF_INET, SOCK_STREAM, 0) == 0);
|
||||
assert(bind(0, (struct sockaddr *) &addr, len) == 0);
|
||||
assert(listen(0, 5) == 0);
|
||||
|
||||
if (socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG) != 1)
|
||||
return 77;
|
||||
|
||||
return (send_query(1, AF_INET, IPPROTO_TCP) &&
|
||||
check_responses(1)) ? 0 : 77;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user