diff options
author | Vadim Yanitskiy <axilirator@gmail.com> | 2018-10-31 19:18:41 +0700 |
---|---|---|
committer | Vadim Yanitskiy <axilirator@gmail.com> | 2018-10-31 19:18:41 +0700 |
commit | 04ac4751701a28b7bec0c812a98d8a7ca1008a69 (patch) | |
tree | 837a4d4cfa318008f68e1004a6a9dee3d14a0e0d | |
parent | 0578d751b1ea0ac10ad2b033f9b73c922f120fdb (diff) |
sock_events.c: also track child file descriptors
In some applications, such as OsmocomBB, a single UNIX socket
can be used by multiple processes (i.e. a server and multiple
clients). Previously this caused a segmentation fault.
Let's modify both sock_ev_accept() and sock_ev_accept4() in order
to handle such connections properly, by using both socket path
and dissector from the parent.
-rw-r--r-- | sock_events.c | 6 | ||||
-rw-r--r-- | utils.c | 26 | ||||
-rw-r--r-- | utils.h | 3 |
3 files changed, 33 insertions, 2 deletions
diff --git a/sock_events.c b/sock_events.c index 9340d7d..a2b4108 100644 --- a/sock_events.c +++ b/sock_events.c @@ -85,7 +85,8 @@ void sock_ev_accept(int fd, int ret, int err, struct sockaddr *addr, { if (ret < 0) return; - udtrace_add_fd(ret); + LOG("accept(fd=%d on parent fd=%d)\n", ret, fd); + udtrace_add_fd_child(fd, ret); } void sock_ev_accept4(int fd, int ret, int err, struct sockaddr *addr, @@ -93,7 +94,8 @@ void sock_ev_accept4(int fd, int ret, int err, struct sockaddr *addr, { if (ret < 0) return; - udtrace_add_fd(ret); + LOG("accept(fd=%d on parent fd=%d)\n", ret, fd); + udtrace_add_fd_child(fd, ret); } void sock_ev_send(int fd, int ret, int err, const void *buf, size_t bytes, @@ -85,6 +85,32 @@ void udtrace_add_fd(int fd) ss->fd = fd; } +/* add a file descriptor from the list of to-be-traced ones */ +void udtrace_add_fd_child(int pfd, int cfd) +{ + struct sock_state *pss, *css; + + /* Find the parent socket state first */ + pss = udtrace_sstate_by_fd(pfd); + if (!pss) { + LOG("Couldn't find parent UNIX FD %d for %d\n", pfd, cfd); + return; + } + + /* Find an unused state in unix_fds */ + css = udtrace_sstate_by_fd(-1); + if (!css) { + LOG("Couldn't add UNIX FD %d (no space in unix_fds)\n", cfd); + return; + } + + LOG("Adding FD %d as a child of %d\n", cfd, pfd); + + css->dissector = pss->dissector; + css->path = strdup(pss->path); + css->fd = cfd; +} + /* delete a file descriptor from the list of to-be-traced ones */ void udtrace_del_fd(int fd) { @@ -21,6 +21,9 @@ struct sock_state *udtrace_sstate_by_fd(int fd); /* add a file descriptor from the list of to-be-traced ones */ void udtrace_add_fd(int fd); +/* add a file descriptor from the list of to-be-traced ones */ +void udtrace_add_fd_child(int pfd, int cfd); + /* delete a file descriptor from the list of to-be-traced ones */ void udtrace_del_fd(int fd); |