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 <libltt/libltt.h>
35 /* Private interface */
56 #define LTTCTL_MAXERR LTTCTL_ERR_PROTOCOL
59 struct lttctl_errmap_t
{
63 { LTTCTL_ERR_NONE
, "Unknown error" },
64 { LTTCTL_ERR_IMPL
, "Implementation error" },
65 { LTTCTL_ERR_HANDLE
, "Unable to create netlink handle" },
66 { LTTCTL_ERR_SOCKET
, "Unable to create netlink socket" },
67 { LTTCTL_ERR_BIND
, "Unable to bind netlink socket" },
68 { LTTCTL_ERR_BUFFER
, "Unable to allocate buffer" },
69 { LTTCTL_ERR_RECV
, "Failed to receive netlink message" },
70 { LTTCTL_ERR_NLEOF
, "Received EOF on netlink socket" },
71 { LTTCTL_ERR_ADDRLEN
, "Invalid peer address length" },
72 { LTTCTL_ERR_STRUNC
, "Sent message truncated" },
73 { LTTCTL_ERR_RTRUNC
, "Received message truncated" },
74 { LTTCTL_ERR_NLRECV
, "Received error from netlink" },
75 { LTTCTL_ERR_SEND
, "Failed to send netlink message" },
76 { LTTCTL_ERR_SUPP
, "Operation not supported" },
77 { LTTCTL_ERR_RECVBUF
, "Receive buffer size invalid" },
78 { LTTCTL_ERR_TIMEOUT
, "Timeout"},
79 { LTTCTL_ERR_PROTOCOL
, "Invalid protocol specified" }
82 static int lttctl_errno
= LTTCTL_ERR_NONE
;
85 static ssize_t
lttctl_netlink_sendto(const struct lttctl_handle
*h
,
86 const void *msg
, size_t len
);
88 static ssize_t
lttctl_netlink_recvfrom(const struct lttctl_handle
*h
,
89 unsigned char *buf
, size_t len
,
92 static ssize_t
lttctl_netlink_sendmsg(const struct lttctl_handle
*h
,
93 const struct msghdr
*msg
,
96 static char *lttctl_strerror(int errcode
);
98 void lttctl_perror(const char *s
);
100 static ssize_t
lttctl_netlink_sendto(const struct lttctl_handle
*h
,
101 const void *msg
, size_t len
)
103 int status
= sendto(h
->fd
, msg
, len
, 0,
104 (struct sockaddr
*)&h
->peer
, sizeof(h
->peer
));
106 lttctl_errno
= LTTCTL_ERR_SEND
;
111 static ssize_t
lttctl_netlink_sendmsg(const struct lttctl_handle
*h
,
112 const struct msghdr
*msg
,
115 int status
= sendmsg(h
->fd
, msg
, flags
);
117 lttctl_errno
= LTTCTL_ERR_SEND
;
121 static ssize_t
lttctl_netlink_recvfrom(const struct lttctl_handle
*h
,
122 unsigned char *buf
, size_t len
,
126 struct nlmsghdr
*nlh
;
128 if (len
< sizeof(struct nlmsghdr
)) {
129 lttctl_errno
= LTTCTL_ERR_RECVBUF
;
130 lttctl_perror("Netlink recvfrom");
133 addrlen
= sizeof(h
->peer
);
141 /* non-block non-timeout */
145 tv
.tv_sec
= timeout
/ 1000000;
146 tv
.tv_usec
= timeout
% 1000000;
150 FD_SET(h
->fd
, &read_fds
);
151 ret
= select(h
->fd
+1, &read_fds
, NULL
, NULL
, &tv
);
153 if (errno
== EINTR
) {
157 lttctl_errno
= LTTCTL_ERR_RECV
;
158 lttctl_perror("Netlink recvfrom");
162 if (!FD_ISSET(h
->fd
, &read_fds
)) {
163 lttctl_errno
= LTTCTL_ERR_TIMEOUT
;
168 status
= recvfrom(h
->fd
, buf
, len
, 0,
169 (struct sockaddr
*)&h
->peer
, &addrlen
);
172 lttctl_errno
= LTTCTL_ERR_RECV
;
173 lttctl_perror("Netlink recvfrom");
176 if (addrlen
!= sizeof(h
->peer
)) {
177 lttctl_errno
= LTTCTL_ERR_RECV
;
178 lttctl_perror("Netlink recvfrom");
181 if (h
->peer
.nl_pid
!= 0) {
182 lttctl_errno
= LTTCTL_ERR_RECV
;
183 lttctl_perror("Netlink recvfrom");
187 lttctl_errno
= LTTCTL_ERR_NLEOF
;
188 lttctl_perror("Netlink recvfrom");
191 nlh
= (struct nlmsghdr
*)buf
;
192 if (nlh
->nlmsg_flags
& MSG_TRUNC
|| nlh
->nlmsg_len
> status
) {
193 lttctl_errno
= LTTCTL_ERR_RTRUNC
;
194 lttctl_perror("Netlink recvfrom");
203 static char *lttctl_strerror(int errcode
)
205 if (errcode
< 0 || errcode
> LTTCTL_MAXERR
)
206 errcode
= LTTCTL_ERR_IMPL
;
207 return lttctl_errmap
[errcode
].message
;
211 char *lttctl_errstr(void)
213 return lttctl_strerror(lttctl_errno
);
216 void lttctl_perror(const char *s
)
221 fputs("ERROR", stderr
);
223 fprintf(stderr
, ": %s", lttctl_errstr());
225 fprintf(stderr
, ": %s", strerror(errno
));
229 /* public interface */
232 * Create and initialise an lttctl handle.
234 struct lttctl_handle
*lttctl_create_handle(void)
237 struct lttctl_handle
*h
;
239 h
= (struct lttctl_handle
*)malloc(sizeof(struct lttctl_handle
));
241 lttctl_errno
= LTTCTL_ERR_HANDLE
;
242 lttctl_perror("Create handle");
246 memset(h
, 0, sizeof(struct lttctl_handle
));
248 h
->fd
= socket(PF_NETLINK
, SOCK_RAW
, NETLINK_LTT
);
251 lttctl_errno
= LTTCTL_ERR_SOCKET
;
252 lttctl_perror("Create handle");
255 memset(&h
->local
, 0, sizeof(struct sockaddr_nl
));
256 h
->local
.nl_family
= AF_NETLINK
;
257 h
->local
.nl_pid
= getpid();
258 h
->local
.nl_groups
= 0;
259 status
= bind(h
->fd
, (struct sockaddr
*)&h
->local
, sizeof(h
->local
));
261 lttctl_errno
= LTTCTL_ERR_BIND
;
262 lttctl_perror("Create handle");
265 memset(&h
->peer
, 0, sizeof(struct sockaddr_nl
));
266 h
->peer
.nl_family
= AF_NETLINK
;
268 h
->peer
.nl_groups
= 0;
271 /* Error condition */
281 * No error condition is checked here at this stage, but it may happen
282 * if/when reliable messaging is implemented.
284 int lttctl_destroy_handle(struct lttctl_handle
*h
)
294 int lttctl_create_trace(const struct lttctl_handle
*h
,
295 char *name
, enum trace_mode mode
, unsigned subbuf_size
, unsigned n_subbufs
)
301 lttctl_peer_msg_t msg
;
305 struct nlmsgerr nlerr
;
306 lttctl_peer_msg_t msg
;
309 memset(&req
, 0, sizeof(req
));
310 req
.nlh
.nlmsg_len
= NLMSG_LENGTH(sizeof(lttctl_peer_msg_t
));
311 req
.nlh
.nlmsg_flags
= NLM_F_REQUEST
|NLM_F_ACK
;
312 req
.nlh
.nlmsg_type
= LTTCTLM_CONTROL
;
313 req
.nlh
.nlmsg_pid
= h
->local
.nl_pid
;
314 req
.nlh
.nlmsg_seq
= 0;
316 strncpy(req
.msg
.trace_name
, name
, NAME_MAX
);
317 req
.msg
.op
= OP_CREATE
;
318 req
.msg
.args
.new_trace
.mode
= mode
;
319 req
.msg
.args
.new_trace
.subbuf_size
= subbuf_size
;
320 req
.msg
.args
.new_trace
.n_subbufs
= n_subbufs
;
322 err
= lttctl_netlink_sendto(h
, (void *)&req
, req
.nlh
.nlmsg_len
);
323 if(err
< 0) goto senderr
;
325 err
= lttctl_netlink_recvfrom(h
, (void*)&ack
, sizeof(ack
), 0);
326 if(err
< 0) goto senderr
;
328 err
= ack
.nlerr
.error
;
331 lttctl_perror("Create Trace Error");
338 lttctl_perror("Create Trace Error");
342 int lttctl_destroy_trace(const struct lttctl_handle
*h
,
347 lttctl_peer_msg_t msg
;
351 struct nlmsgerr nlerr
;
352 lttctl_peer_msg_t msg
;
356 memset(&req
, 0, sizeof(req
));
357 req
.nlh
.nlmsg_len
= NLMSG_LENGTH(sizeof(lttctl_peer_msg_t
));
358 req
.nlh
.nlmsg_flags
= NLM_F_REQUEST
;
359 req
.nlh
.nlmsg_type
= LTTCTLM_CONTROL
;
360 req
.nlh
.nlmsg_pid
= h
->local
.nl_pid
;
362 strncpy(req
.msg
.trace_name
, name
, NAME_MAX
);
363 req
.msg
.op
= OP_DESTROY
;
365 err
= lttctl_netlink_sendto(h
, (void *)&req
, req
.nlh
.nlmsg_len
);
366 if(err
< 0) goto senderr
;
368 err
= lttctl_netlink_recvfrom(h
, (void*)&ack
, sizeof(ack
), 0);
369 if(err
< 0) goto senderr
;
371 err
= ack
.nlerr
.error
;
374 lttctl_perror("Destroy Trace Channels Error");
381 lttctl_perror("Destroy Trace Channels Error");
386 int lttctl_start(const struct lttctl_handle
*h
,
391 lttctl_peer_msg_t msg
;
395 struct nlmsgerr nlerr
;
396 lttctl_peer_msg_t msg
;
401 memset(&req
, 0, sizeof(req
));
402 req
.nlh
.nlmsg_len
= NLMSG_LENGTH(sizeof(lttctl_peer_msg_t
));
403 req
.nlh
.nlmsg_flags
= NLM_F_REQUEST
;
404 req
.nlh
.nlmsg_type
= LTTCTLM_CONTROL
;
405 req
.nlh
.nlmsg_pid
= h
->local
.nl_pid
;
407 strncpy(req
.msg
.trace_name
, name
, NAME_MAX
);
408 req
.msg
.op
= OP_START
;
410 err
= lttctl_netlink_sendto(h
, (void *)&req
, req
.nlh
.nlmsg_len
);
411 if(err
< 0) goto senderr
;
413 err
= lttctl_netlink_recvfrom(h
, (void*)&ack
, sizeof(ack
), 0);
414 if(err
< 0) goto senderr
;
416 err
= ack
.nlerr
.error
;
419 lttctl_perror("Start Trace Error");
426 lttctl_perror("Start Trace Error");
431 int lttctl_stop(const struct lttctl_handle
*h
,
436 lttctl_peer_msg_t msg
;
440 struct nlmsgerr nlerr
;
441 lttctl_peer_msg_t msg
;
445 memset(&req
, 0, sizeof(req
));
446 req
.nlh
.nlmsg_len
= NLMSG_LENGTH(sizeof(lttctl_peer_msg_t
));
447 req
.nlh
.nlmsg_flags
= NLM_F_REQUEST
;
448 req
.nlh
.nlmsg_type
= LTTCTLM_CONTROL
;
449 req
.nlh
.nlmsg_pid
= h
->local
.nl_pid
;
451 strncpy(req
.msg
.trace_name
, name
, NAME_MAX
);
452 req
.msg
.op
= OP_STOP
;
454 err
= lttctl_netlink_sendto(h
, (void *)&req
, req
.nlh
.nlmsg_len
);
455 if(err
< 0) goto senderr
;
457 err
= lttctl_netlink_recvfrom(h
, (void*)&ack
, sizeof(ack
), 0);
458 if(err
< 0) goto senderr
;
460 err
= ack
.nlerr
.error
;
463 lttctl_perror("Stop Trace Error");
470 lttctl_perror("Stop Trace Error");
475 int lttctl_align(const struct lttctl_handle
*h
,
476 char *name
, unsigned alignment
)
480 lttctl_peer_msg_t msg
;
484 struct nlmsgerr nlerr
;
485 lttctl_peer_msg_t msg
;
489 memset(&req
, 0, sizeof(req
));
490 req
.nlh
.nlmsg_len
= NLMSG_LENGTH(sizeof(lttctl_peer_msg_t
));
491 req
.nlh
.nlmsg_flags
= NLM_F_REQUEST
;
492 req
.nlh
.nlmsg_type
= LTTCTLM_CONTROL
;
493 req
.nlh
.nlmsg_pid
= h
->local
.nl_pid
;
495 strncpy(req
.msg
.trace_name
, name
, NAME_MAX
);
496 req
.msg
.op
= OP_ALIGN
;
497 req
.msg
.args
.alignment
= alignment
;
499 err
= lttctl_netlink_sendto(h
, (void *)&req
, req
.nlh
.nlmsg_len
);
500 if(err
< 0) goto senderr
;
502 err
= lttctl_netlink_recvfrom(h
, (void*)&ack
, sizeof(ack
), 0);
503 if(err
< 0) goto senderr
;
505 err
= ack
.nlerr
.error
;
508 lttctl_perror("Align Trace Error");
515 lttctl_perror("Align Trace Error");
This page took 0.047342 seconds and 4 git commands to generate.