1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
#include <errno.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include "uftrace.h"
#include "utils/socket.h"
#include "utils/utils.h"
/* Unlink socket file if it exists */
void socket_unlink(struct sockaddr_un *addr)
{
if (unlink(addr->sun_path) == -1) {
if (errno != ENOENT)
pr_dbg("cannot unlink socket '%s'\n", addr->sun_path);
}
}
/* Create socket for communication between the client and the agent */
int agent_socket_create(struct sockaddr_un *addr, pid_t pid)
{
int fd;
char *channel = NULL;
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd == -1) {
pr_warn("socket creation failed: %s\n", strerror(errno));
return fd;
}
memset(addr, 0, sizeof(struct sockaddr_un));
xasprintf(&channel, "%s/%d.socket", MCOUNT_AGENT_SOCKET_DIR, pid);
addr->sun_family = AF_UNIX;
strncpy(addr->sun_path, channel, sizeof(addr->sun_path) - 1);
free(channel);
return fd;
}
/* Setup socket on agent side so it can accept client connection */
int agent_listen(int fd, struct sockaddr_un *addr)
{
if (bind(fd, (struct sockaddr *)addr, sizeof(struct sockaddr_un)) == -1) {
pr_warn("cannot bind to socket '%s': %s\n", addr->sun_path, strerror(errno));
return -1;
}
if (listen(fd, 1) == -1) {
pr_warn("cannot listen to socket '%s': %s\n", addr->sun_path, strerror(errno));
return -1;
}
return 0;
}
/* Client side: connect to an agent socket */
int agent_connect(int fd, struct sockaddr_un *addr)
{
if (connect(fd, (struct sockaddr *)addr, sizeof(struct sockaddr_un)) == -1) {
pr_warn("cannot connect to socket '%s': %s\n", addr->sun_path, strerror(errno));
return -1;
}
return 0;
}
/* Agent side: accept incoming client connection */
int agent_accept(int fd)
{
return accept(fd, NULL, NULL);
}
/**
* agent_message_send - send a message through the agent socket
* @fd - socket file descriptor
* @type - type of message to send
* @data - data load
* @size - size of @data
* @return - status code, negative for error
*/
int agent_message_send(int fd, int type, void *data, size_t size)
{
struct uftrace_msg msg = {
.magic = UFTRACE_MSG_MAGIC,
.type = type,
.len = size,
};
struct iovec iov[2] = {
{
.iov_base = &msg,
.iov_len = sizeof(msg),
},
{
.iov_base = data,
.iov_len = size,
},
};
pr_dbg4("send agent message [%d] (size=%d)\n", type, size);
if (writev_all(fd, iov, ARRAY_SIZE(iov)) < 0) {
pr_dbg3("error writing message to agent socket\n");
return -1;
}
return 0;
}
/**
* agent_message_read_head - read message header from the agent socket
*
* Fetch the message type and size so the data load can be read somewhere else.
*
* @fd - socket file descriptor
* @msg - received message head
* @return - status code, negative for error
*/
int agent_message_read_head(int fd, struct uftrace_msg *msg)
{
if (read_all(fd, msg, sizeof(*msg)) < 0) {
pr_dbg4("error reading agent message header\n");
return -1;
}
if (msg->magic != UFTRACE_MSG_MAGIC) {
pr_dbg4("invalid agent message received\n");
return -1;
}
return 0;
}
/**
* agent_message_read_response - read agent ack
* @fd - socket file descriptor
* @response - ack from agent
* @return - status: data or error code, negative on error
*/
int agent_message_read_response(int fd, struct uftrace_msg *response)
{
int status = 0;
if (agent_message_read_head(fd, response) < 0)
return -1;
if (response->len > sizeof(status))
return -1;
if (read_all(fd, &status, response->len) < 0) {
pr_dbg3("error reading agent socket\n");
return -1;
}
pr_dbg4("read agent response [%d] (size=%d)\n", response->type, response->len);
return status;
}
|