3 * Linux Trace Toolkit Netlink Control Library
5 * Controls the ltt-control kernel module through a netlink socket.
7 * Heavily inspired from libipq.c (iptables) made by
8 * James Morris <jmorris@intercode.com.au>
11 * Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
26 #include <ltt/libltt.h>
29 /* Private interface */
50 #define LTTCTL_MAXERR LTTCTL_ERR_PROTOCOL
53 struct lttctl_errmap_t
{
57 { IPQ_ERR_NONE
, "Unknown error" },
58 { IPQ_ERR_IMPL
, "Implementation error" },
59 { IPQ_ERR_HANDLE
, "Unable to create netlink handle" },
60 { IPQ_ERR_SOCKET
, "Unable to create netlink socket" },
61 { IPQ_ERR_BIND
, "Unable to bind netlink socket" },
62 { IPQ_ERR_BUFFER
, "Unable to allocate buffer" },
63 { IPQ_ERR_RECV
, "Failed to receive netlink message" },
64 { IPQ_ERR_NLEOF
, "Received EOF on netlink socket" },
65 { IPQ_ERR_ADDRLEN
, "Invalid peer address length" },
66 { IPQ_ERR_STRUNC
, "Sent message truncated" },
67 { IPQ_ERR_RTRUNC
, "Received message truncated" },
68 { IPQ_ERR_NLRECV
, "Received error from netlink" },
69 { IPQ_ERR_SEND
, "Failed to send netlink message" },
70 { IPQ_ERR_SUPP
, "Operation not supported" },
71 { IPQ_ERR_RECVBUF
, "Receive buffer size invalid" },
72 { IPQ_ERR_TIMEOUT
, "Timeout"},
73 { IPQ_ERR_PROTOCOL
, "Invalid protocol specified" }
76 static int lttctl_errno
= LTTCTL_ERR_NONE
;
79 static ssize_t
lttctl_netlink_sendto(const struct lttctl_handle
*h
,
80 const void *msg
, size_t len
);
82 static ssize_t
lttctl_netlink_recvfrom(const struct lttctl_handle
*h
,
83 unsigned char *buf
, size_t len
,
86 static ssize_t
lttctl_netlink_sendmsg(const struct lttctl_handle
*h
,
87 const struct msghdr
*msg
,
90 static char *lttctl_strerror(int errcode
);
92 static ssize_t
lttctl_netlink_sendto(const struct lttctl_handle
*h
,
93 const void *msg
, size_t len
)
95 int status
= sendto(h
->fd
, msg
, len
, 0,
96 (struct sockaddr
*)&h
->peer
, sizeof(h
->peer
));
98 lttctl_errno
= LTTCTL_ERR_SEND
;
102 static ssize_t
lttctl_netlink_sendmsg(const struct lttctl_handle
*h
,
103 const struct msghdr
*msg
,
106 int status
= sendmsg(h
->fd
, msg
, flags
);
108 lttctl_errno
= LTTCTL_ERR_SEND
;
112 static ssize_t
lttctl_netlink_recvfrom(const struct lttctl_handle
*h
,
113 unsigned char *buf
, size_t len
,
117 struct nlmsghdr
*nlh
;
119 if (len
< sizeof(struct nlmsgerr
)) {
120 lttctl_errno
= LTTCTL_ERR_RECVBUF
;
123 addrlen
= sizeof(h
->peer
);
131 /* non-block non-timeout */
135 tv
.tv_sec
= timeout
/ 1000000;
136 tv
.tv_usec
= timeout
% 1000000;
140 FD_SET(h
->fd
, &read_fds
);
141 ret
= select(h
->fd
+1, &read_fds
, NULL
, NULL
, &tv
);
143 if (errno
== EINTR
) {
146 lttctl_errno
= lttctl_ERR_RECV
;
150 if (!FD_ISSET(h
->fd
, &read_fds
)) {
151 lttctl_errno
= lttctl_ERR_TIMEOUT
;
155 status
= recvfrom(h
->fd
, buf
, len
, 0,
156 (struct sockaddr
*)&h
->peer
, &addrlen
);
158 lttctl_errno
= LTTCTL_ERR_RECV
;
161 if (addrlen
!= sizeof(h
->peer
)) {
162 lttctl_errno
= LTTCTL_ERR_RECV
;
165 if (h
->peer
.nl_pid
!= 0) {
166 lttctl_errno
= LTTCTL_ERR_RECV
;
170 lttctl_errno
= LTTCTL_ERR_NLEOF
;
173 nlh
= (struct nlmsghdr
*)buf
;
174 if (nlh
->nlmsg_flags
& MSG_TRUNC
|| nlh
->nlmsg_len
> status
) {
175 lttctl_errno
= LTTCTL_ERR_RTRUNC
;
182 static char *lttctl_strerror(int errcode
)
184 if (errcode
< 0 || errcode
> LTTCTL_MAXERR
)
185 errcode
= LTTCTL_ERR_IMPL
;
186 return lttctl_errmap
[errcode
].message
;
191 /* public interface */
194 * Create and initialise an lttctl handle.
196 struct lttctl_handle
*lttctl_create_handle(void)
199 struct lttctl_handle
*h
;
201 h
= (struct lttctl_handle
*)malloc(sizeof(struct lttctl_handle
));
203 lttctl_errno
= lttctl_ERR_HANDLE
;
207 memset(h
, 0, sizeof(struct lttctl_handle
));
209 h
->fd
= socket(PF_NETLINK
, SOCK_RAW
, NETLINK_LTT
);
212 lttctl_errno
= LTTCTL_ERR_SOCKET
;
217 memset(&h
->local
, 0, sizeof(struct sockaddr_nl
));
218 h
->local
.nl_family
= AF_NETLINK
;
219 h
->local
.nl_pid
= getpid();
220 h
->local
.nl_groups
= 0;
221 status
= bind(h
->fd
, (struct sockaddr
*)&h
->local
, sizeof(h
->local
));
223 lttctl_errno
= LTTCTL_ERR_BIND
;
228 memset(&h
->peer
, 0, sizeof(struct sockaddr_nl
));
229 h
->peer
.nl_family
= AF_NETLINK
;
231 h
->peer
.nl_groups
= 0;
236 * No error condition is checked here at this stage, but it may happen
237 * if/when reliable messaging is implemented.
239 int lttctl_destroy_handle(struct lttctl_handle
*h
)
249 int lttctl_create_trace(const struct ipq_handle
*h
,
250 char *name
, enum trace_mode mode
)
254 lttctl_peer_msg_t msg
;
257 memset(&req
, 0, sizeof(req
));
258 req
.nlh
.nlmsg_len
= NLMSG_LENGTH(sizeof(req
));
259 req
.nlh
.nlmsg_flags
= NLM_F_REQUEST
;
260 req
.nlh
.nlmsg_type
= LTTCTLM_CONTROL
;
261 req
.nlh
.nlmsg_pid
= h
->local
.nl_pid
;
263 strncpy(req
.msg
.trace_name
, name
, NAME_MAX
);
264 req
.msg
.op
= OP_CREATE
;
265 req
.msg
.args
.mode
= mode
;
267 return lttctl_netlink_sendto(h
, (void *)&req
, req
.nlh
.nlmsg_len
);
270 int lttctl_destroy_trace(const struct ipq_handle
*h
,
275 lttctl_peer_msg_t msg
;
278 memset(&req
, 0, sizeof(req
));
279 req
.nlh
.nlmsg_len
= NLMSG_LENGTH(sizeof(req
));
280 req
.nlh
.nlmsg_flags
= NLM_F_REQUEST
;
281 req
.nlh
.nlmsg_type
= LTTCTLM_CONTROL
;
282 req
.nlh
.nlmsg_pid
= h
->local
.nl_pid
;
284 strncpy(req
.msg
.trace_name
, name
, NAME_MAX
);
285 req
.msg
.op
= OP_DESTROY
;
287 return lttctl_netlink_sendto(h
, (void *)&req
, req
.nlh
.nlmsg_len
);
290 int lttctl_start(const struct ipq_handle
*h
,
295 lttctl_peer_msg_t msg
;
298 memset(&req
, 0, sizeof(req
));
299 req
.nlh
.nlmsg_len
= NLMSG_LENGTH(sizeof(req
));
300 req
.nlh
.nlmsg_flags
= NLM_F_REQUEST
;
301 req
.nlh
.nlmsg_type
= LTTCTLM_CONTROL
;
302 req
.nlh
.nlmsg_pid
= h
->local
.nl_pid
;
304 strncpy(req
.msg
.trace_name
, name
, NAME_MAX
);
305 req
.msg
.op
= OP_START
;
307 return lttctl_netlink_sendto(h
, (void *)&req
, req
.nlh
.nlmsg_len
);
310 int lttctl_stop(const struct ipq_handle
*h
,
315 lttctl_peer_msg_t msg
;
318 memset(&req
, 0, sizeof(req
));
319 req
.nlh
.nlmsg_len
= NLMSG_LENGTH(sizeof(req
));
320 req
.nlh
.nlmsg_flags
= NLM_F_REQUEST
;
321 req
.nlh
.nlmsg_type
= LTTCTLM_CONTROL
;
322 req
.nlh
.nlmsg_pid
= h
->local
.nl_pid
;
324 strncpy(req
.msg
.trace_name
, name
, NAME_MAX
);
325 req
.msg
.op
= OP_STOP
;
327 return lttctl_netlink_sendto(h
, (void *)&req
, req
.nlh
.nlmsg_len
);
This page took 0.146896 seconds and 4 git commands to generate.