]>
git.ipfire.org Git - thirdparty/lldpd.git/blob - src/ctl.c
1 /* -*- mode: c; c-file-style: "openbsd" -*- */
3 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 #include <sys/types.h>
23 #include <sys/socket.h>
30 #include "compat/compat.h"
33 * Create a new listening Unix socket for control protocol.
35 * @param name The name of the Unix socket.
36 * @return The socket when successful, -1 otherwise.
39 ctl_create(char *name
)
42 struct sockaddr_un su
;
45 log_debug("control", "create control socket %s", name
);
47 if ((s
= socket(PF_UNIX
, SOCK_STREAM
, 0)) == -1)
49 su
.sun_family
= AF_UNIX
;
50 strlcpy(su
.sun_path
, name
, sizeof(su
.sun_path
));
51 if (bind(s
, (struct sockaddr
*)&su
, sizeof(struct sockaddr_un
)) == -1) {
52 rc
= errno
; close(s
); errno
= rc
;
56 log_debug("control", "listen to control socket %s", name
);
57 if (listen(s
, 5) == -1) {
58 rc
= errno
; close(s
); errno
= rc
;
59 log_debug("control", "cannot listen to control socket %s", name
);
66 * Connect to the control Unix socket.
68 * @param name The name of the Unix socket.
69 * @return The socket when successful, -1 otherwise.
72 ctl_connect(char *name
)
75 struct sockaddr_un su
;
78 log_debug("control", "connect to control socket %s", name
);
80 if ((s
= socket(PF_UNIX
, SOCK_STREAM
, 0)) == -1)
82 su
.sun_family
= AF_UNIX
;
83 strlcpy(su
.sun_path
, name
, sizeof(su
.sun_path
));
84 if (connect(s
, (struct sockaddr
*)&su
, sizeof(struct sockaddr_un
)) == -1) {
86 log_warn("control", "unable to connect to socket %s", name
);
87 errno
= rc
; return -1;
93 * Remove the control Unix socket.
95 * @param name The name of the Unix socket.
98 ctl_cleanup(char *name
)
100 log_debug("control", "cleanup control socket");
101 if (unlink(name
) == -1)
102 log_warn("control", "unable to unlink %s", name
);
106 * Serialize and "send" a structure through the control protocol.
108 * This function does not really send the message but outputs it to a buffer.
110 * @param output_buffer A pointer to a buffer to which the message will be
111 * appended. Can be @c NULL. In this case, the buffer will
113 * @param[in,out] output_len The length of the provided buffer. Will be updated
114 * with the new length
115 * @param type The type of message we want to send.
116 * @param t The structure to be serialized and sent.
117 * @param mi The appropriate marshal structure for serialization.
118 * @return -1 in case of failure, 0 in case of success.
120 * Make sure this function logic matches the server-side one: @c levent_ctl_recv().
123 ctl_msg_send_unserialized(uint8_t **output_buffer
, size_t *output_len
,
125 void *t
, struct marshal_info
*mi
)
127 struct hmsg_header hdr
;
128 size_t len
= 0, newlen
;
131 log_debug("control", "send a message through control socket");
133 len
= marshal_serialize_(mi
, t
, &buffer
, 0, NULL
, 0);
135 log_warnx("control", "unable to serialize data");
140 newlen
= len
+ sizeof(struct hmsg_header
);
142 if (*output_buffer
== NULL
) {
144 if ((*output_buffer
= malloc(newlen
)) == NULL
) {
145 log_warn("control", "no memory available");
150 void *new = realloc(*output_buffer
, *output_len
+ newlen
);
152 log_warn("control", "no memory available");
156 *output_buffer
= new;
158 memset(&hdr
, 0, sizeof(struct hmsg_header
));
161 memcpy(*output_buffer
+ *output_len
, &hdr
, sizeof(struct hmsg_header
));
163 memcpy(*output_buffer
+ *output_len
+ sizeof(struct hmsg_header
), buffer
, len
);
164 *output_len
+= newlen
;
170 * "Receive" and unserialize a structure through the control protocol.
172 * Like @c ctl_msg_send_unserialized(), this function uses buffer to receive the
175 * @param[in,out] input_buffer The buffer with the incoming message. Will be
176 * updated once the message has been unserialized to
177 * point to the remaining of the message or will be
178 * freed if all the buffer has been consumed. Can be
180 * @param[in,out] input_len The length of the provided buffer. Will be updated
181 * to the length of remaining data once the message
182 * has been unserialized.
183 * @param expected_type The expected message type.
184 * @param[out] t Will contain a pointer to the unserialized structure.
185 * Can be @c NULL if we don't want to store the
187 * @param mi The appropriate marshal structure for unserialization.
189 * @return -1 in case of error, 0 in case of success and the number of bytes we
190 * request to complete unserialization.
192 * When requesting a notification, the input buffer is left untouched if we
193 * don't get one and we fail silently.
196 ctl_msg_recv_unserialized(uint8_t **input_buffer
, size_t *input_len
,
197 enum hmsg_type expected_type
,
198 void **t
, struct marshal_info
*mi
)
200 struct hmsg_header hdr
;
203 if (*input_buffer
== NULL
||
204 *input_len
< sizeof(struct hmsg_header
)) {
205 /* Not enough data. */
206 return sizeof(struct hmsg_header
) - *input_len
;
209 log_debug("control", "receive a message through control socket");
210 memcpy(&hdr
, *input_buffer
, sizeof(struct hmsg_header
));
211 if (hdr
.len
> HMSG_MAX_SIZE
) {
212 log_warnx("control", "message received is too large");
213 /* We discard the whole buffer */
215 *input_buffer
= NULL
;
219 if (*input_len
< sizeof(struct hmsg_header
) + hdr
.len
) {
220 /* Not enough data. */
221 return sizeof(struct hmsg_header
) + hdr
.len
- *input_len
;
223 if (hdr
.type
!= expected_type
) {
224 if (expected_type
== NOTIFICATION
) return -1;
225 log_warnx("control", "incorrect received message type (expected: %d, received: %d)",
226 expected_type
, hdr
.type
);
231 log_warnx("control", "no payload available in answer");
235 /* We have data to unserialize. */
236 if (marshal_unserialize_(mi
, *input_buffer
+ sizeof(struct hmsg_header
),
237 hdr
.len
, t
, NULL
, 0, 0) <= 0) {
238 log_warnx("control", "unable to deserialize received data");
245 /* Discard input buffer */
246 *input_len
-= sizeof(struct hmsg_header
) + hdr
.len
;
247 if (*input_len
== 0) {
249 *input_buffer
= NULL
;
251 memmove(*input_buffer
,
252 *input_buffer
+ sizeof(struct hmsg_header
) + hdr
.len
,