summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2018-12-14 16:00:40 +0100
committerGitHub <noreply@github.com>2018-12-14 16:00:40 +0100
commitfcef0e01ff656f0d87dc451604d35c253721d567 (patch)
tree837a4d4cfa318008f68e1004a6a9dee3d14a0e0d
parente041c4f4a9a8683699879df696cfcbd1e60cccdb (diff)
parent04ac4751701a28b7bec0c812a98d8a7ca1008a69 (diff)
Merge pull request #1 from axilirator/fixeria/parent_fd
Properly handle multiple child connections
-rw-r--r--sock_events.c6
-rw-r--r--utils.c93
-rw-r--r--utils.h15
3 files changed, 78 insertions, 36 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,
diff --git a/utils.c b/utils.c
index 4b653f2..e1b0d7d 100644
--- a/utils.c
+++ b/utils.c
@@ -47,19 +47,11 @@ static char *hexdump(const unsigned char *buf, int len, char *delim)
return hexd_buff;
}
-typedef void (*udtrace_dissector)(int fd, bool is_out, const char *fn, const uint8_t *data, unsigned int len);
-
static void default_dissector(int fd, bool is_out, const char *fn, const uint8_t *data, unsigned int len)
{
fprintf(stderr, "%d %s %c %s\n", fd, fn, is_out ? 'W' : 'R', hexdump(data, len, ""));
}
-struct sock_state {
- int fd;
- const char *path;
- udtrace_dissector dissector;
-};
-
static struct sock_state unix_fds[MAX_UNIX_FDS];
__attribute__ ((constructor)) static void udtrace_init(void)
@@ -80,30 +72,60 @@ __attribute__ ((constructor)) static void udtrace_init(void)
/* add a file descriptor from the list of to-be-traced ones */
void udtrace_add_fd(int fd)
{
- int i;
- for (i = 0; i < ARRAY_SIZE(unix_fds); i++) {
- if (unix_fds[i].fd == -1) {
- LOG("Adding FD %d\n", fd);
- unix_fds[i].fd = fd;
- return;
- }
+ struct sock_state *ss;
+
+ /* Find an unused state in unix_fds */
+ ss = udtrace_sstate_by_fd(-1);
+ if (!ss) {
+ LOG("Couldn't add UNIX FD %d (no space in unix_fds)\n", fd);
+ return;
+ }
+
+ LOG("Adding FD %d\n", 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("Couldn't add UNIX FD %d (no space in unix_fds)\n", fd);
+
+ 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)
{
- int i;
- for (i = 0; i < ARRAY_SIZE(unix_fds); i++) {
- if (unix_fds[i].fd == fd) {
- LOG("Removing FD %d\n", fd);
- free((void *) unix_fds[i].path);
- unix_fds[i] = (struct sock_state) { -1, NULL, NULL };
- return;
- }
+ struct sock_state *ss;
+
+ /* Find the corresponding state in unix_fds */
+ ss = udtrace_sstate_by_fd(fd);
+ if (!ss) {
+ LOG("Couldn't delete UNIX FD %d (no such FD in unix_fds)\n", fd);
+ return;
}
- LOG("Couldn't delete UNIX FD %d (no such FD)\n", fd);
+
+ LOG("Removing FD %d\n", fd);
+ free((void *) ss->path);
+ *ss = (struct sock_state) { -1, NULL, NULL };
}
static void udtrace_resolve_dissector(struct sock_state *ss)
@@ -123,17 +145,20 @@ static void udtrace_resolve_dissector(struct sock_state *ss)
/* set the path of a given fd */
void udtrace_fd_set_path(int fd, const char *path)
{
- int i;
- for (i = 0; i < ARRAY_SIZE(unix_fds); i++) {
- if (unix_fds[i].fd == fd) {
- unix_fds[i].path = strdup(path);
- udtrace_resolve_dissector(&unix_fds[i]);
- return;
- }
+ struct sock_state *ss;
+
+ /* Find the corresponding state in unix_fds */
+ ss = udtrace_sstate_by_fd(fd);
+ if (!ss) {
+ LOG("Couldn't set path for UNIX FD %d (no such FD in unix_fds)\n", fd);
+ return;
}
+
+ ss->path = strdup(path);
+ udtrace_resolve_dissector(ss);
}
-const struct sock_state *udtrace_sstate_by_fd(int fd)
+struct sock_state *udtrace_sstate_by_fd(int fd)
{
int i;
for (i = 0; i < ARRAY_SIZE(unix_fds); i++) {
@@ -154,7 +179,7 @@ bool is_unix_socket(int fd)
void udtrace_data(int fd, bool is_out, const char *fn, const uint8_t *data, unsigned int len)
{
- const struct sock_state *ss = udtrace_sstate_by_fd(fd);
+ struct sock_state *ss = udtrace_sstate_by_fd(fd);
if (!data || !len || !ss)
return;
ss->dissector(fd, is_out, fn, data, len);
diff --git a/utils.h b/utils.h
index f1f52f4..6829ffe 100644
--- a/utils.h
+++ b/utils.h
@@ -6,9 +6,24 @@
#define LOG(fmt, args ...) \
fprintf(stderr, ">>> UDTRACE: " fmt, ## args)
+typedef void (*udtrace_dissector)(int fd, bool is_out, const char *fn,
+ const uint8_t *data, unsigned int len);
+
+struct sock_state {
+ int fd;
+ const char *path;
+ udtrace_dissector dissector;
+};
+
+/* find the state corresponding to a given file descriptor */
+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);
personal git repositories of Harald Welte. Your mileage may vary