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.
30 #include <liblttctl/lttctl.h>
35 #include <sys/types.h>
41 /* Private interface */
62 #define LTTCTL_MAXERR LTTCTL_ERR_PROTOCOL
65 struct lttctl_errmap_t
{
69 { LTTCTL_ERR_NONE
, "Unknown error" },
70 { LTTCTL_ERR_IMPL
, "Implementation error" },
71 { LTTCTL_ERR_HANDLE
, "Unable to create netlink handle" },
72 { LTTCTL_ERR_SOCKET
, "Unable to create netlink socket" },
73 { LTTCTL_ERR_BIND
, "Unable to bind netlink socket" },
74 { LTTCTL_ERR_BUFFER
, "Unable to allocate buffer" },
75 { LTTCTL_ERR_RECV
, "Failed to receive netlink message" },
76 { LTTCTL_ERR_NLEOF
, "Received EOF on netlink socket" },
77 { LTTCTL_ERR_ADDRLEN
, "Invalid peer address length" },
78 { LTTCTL_ERR_STRUNC
, "Sent message truncated" },
79 { LTTCTL_ERR_RTRUNC
, "Received message truncated" },
80 { LTTCTL_ERR_NLRECV
, "Received error from netlink" },
81 { LTTCTL_ERR_SEND
, "Failed to send netlink message" },
82 { LTTCTL_ERR_SUPP
, "Operation not supported" },
83 { LTTCTL_ERR_RECVBUF
, "Receive buffer size invalid" },
84 { LTTCTL_ERR_TIMEOUT
, "Timeout"},
85 { LTTCTL_ERR_PROTOCOL
, "Invalid protocol specified" }
88 static int lttctl_errno
= LTTCTL_ERR_NONE
;
91 static ssize_t
lttctl_netlink_sendto(const struct lttctl_handle
*h
,
92 const void *msg
, size_t len
);
94 static ssize_t
lttctl_netlink_recvfrom(const struct lttctl_handle
*h
,
95 unsigned char *buf
, size_t len
,
98 static ssize_t
lttctl_netlink_sendmsg(const struct lttctl_handle
*h
,
99 const struct msghdr
*msg
,
102 static char *lttctl_strerror(int errcode
);
104 void lttctl_perror(const char *s
);
106 static ssize_t
lttctl_netlink_sendto(const struct lttctl_handle
*h
,
107 const void *msg
, size_t len
)
109 int status
= sendto(h
->fd
, msg
, len
, 0,
110 (struct sockaddr
*)&h
->peer
, sizeof(h
->peer
));
112 lttctl_errno
= LTTCTL_ERR_SEND
;
117 static ssize_t
lttctl_netlink_sendmsg(const struct lttctl_handle
*h
,
118 const struct msghdr
*msg
,
121 int status
= sendmsg(h
->fd
, msg
, flags
);
123 lttctl_errno
= LTTCTL_ERR_SEND
;
127 static ssize_t
lttctl_netlink_recvfrom(const struct lttctl_handle
*h
,
128 unsigned char *buf
, size_t len
,
132 struct nlmsghdr
*nlh
;
134 if (len
< sizeof(struct nlmsghdr
)) {
135 lttctl_errno
= LTTCTL_ERR_RECVBUF
;
136 lttctl_perror("Netlink recvfrom");
139 addrlen
= sizeof(h
->peer
);
147 /* non-block non-timeout */
151 tv
.tv_sec
= timeout
/ 1000000;
152 tv
.tv_usec
= timeout
% 1000000;
156 FD_SET(h
->fd
, &read_fds
);
157 ret
= select(h
->fd
+1, &read_fds
, NULL
, NULL
, &tv
);
159 if (errno
== EINTR
) {
163 lttctl_errno
= LTTCTL_ERR_RECV
;
164 lttctl_perror("Netlink recvfrom");
168 if (!FD_ISSET(h
->fd
, &read_fds
)) {
169 lttctl_errno
= LTTCTL_ERR_TIMEOUT
;
174 status
= recvfrom(h
->fd
, buf
, len
, 0,
175 (struct sockaddr
*)&h
->peer
, &addrlen
);
178 lttctl_errno
= LTTCTL_ERR_RECV
;
179 lttctl_perror("Netlink recvfrom");
182 if (addrlen
!= sizeof(h
->peer
)) {
183 lttctl_errno
= LTTCTL_ERR_RECV
;
184 lttctl_perror("Netlink recvfrom");
187 if (h
->peer
.nl_pid
!= 0) {
188 lttctl_errno
= LTTCTL_ERR_RECV
;
189 lttctl_perror("Netlink recvfrom");
193 lttctl_errno
= LTTCTL_ERR_NLEOF
;
194 lttctl_perror("Netlink recvfrom");
197 nlh
= (struct nlmsghdr
*)buf
;
198 if (nlh
->nlmsg_flags
& MSG_TRUNC
|| nlh
->nlmsg_len
> status
) {
199 lttctl_errno
= LTTCTL_ERR_RTRUNC
;
200 lttctl_perror("Netlink recvfrom");
209 static char *lttctl_strerror(int errcode
)
211 if (errcode
< 0 || errcode
> LTTCTL_MAXERR
)
212 errcode
= LTTCTL_ERR_IMPL
;
213 return lttctl_errmap
[errcode
].message
;
217 char *lttctl_errstr(void)
219 return lttctl_strerror(lttctl_errno
);
222 void lttctl_perror(const char *s
)
227 fputs("ERROR", stderr
);
229 fprintf(stderr
, ": %s", lttctl_errstr());
231 fprintf(stderr
, ": %s", strerror(errno
));
235 /* public interface */
238 * Create and initialise an lttctl handle.
240 struct lttctl_handle
*lttctl_create_handle(void)
243 struct lttctl_handle
*h
;
245 h
= (struct lttctl_handle
*)malloc(sizeof(struct lttctl_handle
));
247 lttctl_errno
= LTTCTL_ERR_HANDLE
;
248 lttctl_perror("Create handle");
252 memset(h
, 0, sizeof(struct lttctl_handle
));
254 h
->fd
= socket(PF_NETLINK
, SOCK_RAW
, NETLINK_LTT
);
257 lttctl_errno
= LTTCTL_ERR_SOCKET
;
258 lttctl_perror("Create handle");
261 memset(&h
->local
, 0, sizeof(struct sockaddr_nl
));
262 h
->local
.nl_family
= AF_NETLINK
;
263 h
->local
.nl_pid
= getpid();
264 h
->local
.nl_groups
= 0;
265 status
= bind(h
->fd
, (struct sockaddr
*)&h
->local
, sizeof(h
->local
));
267 lttctl_errno
= LTTCTL_ERR_BIND
;
268 lttctl_perror("Create handle");
271 memset(&h
->peer
, 0, sizeof(struct sockaddr_nl
));
272 h
->peer
.nl_family
= AF_NETLINK
;
274 h
->peer
.nl_groups
= 0;
277 /* Error condition */
287 * No error condition is checked here at this stage, but it may happen
288 * if/when reliable messaging is implemented.
290 int lttctl_destroy_handle(struct lttctl_handle
*h
)
300 int lttctl_create_trace(const struct lttctl_handle
*h
,
301 char *name
, enum trace_mode mode
, char *trace_type
,
302 unsigned subbuf_size_low
, unsigned n_subbufs_low
,
303 unsigned subbuf_size_med
, unsigned n_subbufs_med
,
304 unsigned subbuf_size_high
, unsigned n_subbufs_high
)
310 lttctl_peer_msg_t msg
;
314 struct nlmsgerr nlerr
;
315 lttctl_peer_msg_t msg
;
318 memset(&req
, 0, sizeof(req
));
319 req
.nlh
.nlmsg_len
= NLMSG_LENGTH(sizeof(lttctl_peer_msg_t
));
320 req
.nlh
.nlmsg_flags
= NLM_F_REQUEST
|NLM_F_ACK
;
321 req
.nlh
.nlmsg_type
= LTTCTLM_CONTROL
;
322 req
.nlh
.nlmsg_pid
= h
->local
.nl_pid
;
323 req
.nlh
.nlmsg_seq
= 0;
325 strncpy(req
.msg
.trace_name
, name
, NAME_MAX
);
326 strncpy(req
.msg
.trace_type
, trace_type
, NAME_MAX
);
327 req
.msg
.op
= OP_CREATE
;
328 req
.msg
.args
.new_trace
.mode
= mode
;
329 req
.msg
.args
.new_trace
.subbuf_size_low
= subbuf_size_low
;
330 req
.msg
.args
.new_trace
.n_subbufs_low
= n_subbufs_low
;
331 req
.msg
.args
.new_trace
.subbuf_size_med
= subbuf_size_med
;
332 req
.msg
.args
.new_trace
.n_subbufs_med
= n_subbufs_med
;
333 req
.msg
.args
.new_trace
.subbuf_size_high
= subbuf_size_high
;
334 req
.msg
.args
.new_trace
.n_subbufs_high
= n_subbufs_high
;
336 err
= lttctl_netlink_sendto(h
, (void *)&req
, req
.nlh
.nlmsg_len
);
337 if(err
< 0) goto senderr
;
339 err
= lttctl_netlink_recvfrom(h
, (void*)&ack
, sizeof(ack
), 0);
340 if(err
< 0) goto senderr
;
342 err
= ack
.nlerr
.error
;
345 lttctl_perror("Create Trace Error");
352 lttctl_perror("Create Trace Error");
357 int lttctl_destroy_trace(const struct lttctl_handle
*h
,
362 lttctl_peer_msg_t msg
;
366 struct nlmsgerr nlerr
;
367 lttctl_peer_msg_t msg
;
371 memset(&req
, 0, sizeof(req
));
372 req
.nlh
.nlmsg_len
= NLMSG_LENGTH(sizeof(lttctl_peer_msg_t
));
373 req
.nlh
.nlmsg_flags
= NLM_F_REQUEST
;
374 req
.nlh
.nlmsg_type
= LTTCTLM_CONTROL
;
375 req
.nlh
.nlmsg_pid
= h
->local
.nl_pid
;
377 strncpy(req
.msg
.trace_name
, name
, NAME_MAX
);
378 req
.msg
.op
= OP_DESTROY
;
380 err
= lttctl_netlink_sendto(h
, (void *)&req
, req
.nlh
.nlmsg_len
);
381 if(err
< 0) goto senderr
;
383 err
= lttctl_netlink_recvfrom(h
, (void*)&ack
, sizeof(ack
), 0);
384 if(err
< 0) goto senderr
;
386 err
= ack
.nlerr
.error
;
389 lttctl_perror("Destroy Trace Channels Error");
396 lttctl_perror("Destroy Trace Channels Error");
402 int lttctl_start(const struct lttctl_handle
*h
,
407 lttctl_peer_msg_t msg
;
411 struct nlmsgerr nlerr
;
412 lttctl_peer_msg_t msg
;
417 memset(&req
, 0, sizeof(req
));
418 req
.nlh
.nlmsg_len
= NLMSG_LENGTH(sizeof(lttctl_peer_msg_t
));
419 req
.nlh
.nlmsg_flags
= NLM_F_REQUEST
;
420 req
.nlh
.nlmsg_type
= LTTCTLM_CONTROL
;
421 req
.nlh
.nlmsg_pid
= h
->local
.nl_pid
;
423 strncpy(req
.msg
.trace_name
, name
, NAME_MAX
);
424 req
.msg
.op
= OP_START
;
426 err
= lttctl_netlink_sendto(h
, (void *)&req
, req
.nlh
.nlmsg_len
);
427 if(err
< 0) goto senderr
;
429 err
= lttctl_netlink_recvfrom(h
, (void*)&ack
, sizeof(ack
), 0);
430 if(err
< 0) goto senderr
;
432 err
= ack
.nlerr
.error
;
435 lttctl_perror("Start Trace Error");
443 lttctl_perror("Start Trace Error");
448 int lttctl_stop(const struct lttctl_handle
*h
,
453 lttctl_peer_msg_t msg
;
457 struct nlmsgerr nlerr
;
458 lttctl_peer_msg_t msg
;
462 memset(&req
, 0, sizeof(req
));
463 req
.nlh
.nlmsg_len
= NLMSG_LENGTH(sizeof(lttctl_peer_msg_t
));
464 req
.nlh
.nlmsg_flags
= NLM_F_REQUEST
;
465 req
.nlh
.nlmsg_type
= LTTCTLM_CONTROL
;
466 req
.nlh
.nlmsg_pid
= h
->local
.nl_pid
;
468 strncpy(req
.msg
.trace_name
, name
, NAME_MAX
);
469 req
.msg
.op
= OP_STOP
;
471 err
= lttctl_netlink_sendto(h
, (void *)&req
, req
.nlh
.nlmsg_len
);
472 if(err
< 0) goto senderr
;
474 err
= lttctl_netlink_recvfrom(h
, (void*)&ack
, sizeof(ack
), 0);
475 if(err
< 0) goto senderr
;
477 err
= ack
.nlerr
.error
;
480 lttctl_perror("Stop Trace Error");
488 lttctl_perror("Stop Trace Error");
This page took 0.040301 seconds and 4 git commands to generate.