]>
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(const 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 if (fcntl(s
, F_SETFD
, FD_CLOEXEC
) == -1) {
53 su
.sun_family
= AF_UNIX
;
54 strlcpy(su
.sun_path
, name
, sizeof(su
.sun_path
));
55 if (bind(s
, (struct sockaddr
*)&su
, sizeof(struct sockaddr_un
)) == -1) {
56 rc
= errno
; close(s
); errno
= rc
;
60 log_debug("control", "listen to control socket %s", name
);
61 if (listen(s
, 5) == -1) {
62 rc
= errno
; close(s
); errno
= rc
;
63 log_debug("control", "cannot listen to control socket %s", name
);
70 * Connect to the control Unix socket.
72 * @param name The name of the Unix socket.
73 * @return The socket when successful, -1 otherwise.
76 ctl_connect(const char *name
)
79 struct sockaddr_un su
;
82 log_debug("control", "connect to control socket %s", name
);
84 if ((s
= socket(PF_UNIX
, SOCK_STREAM
, 0)) == -1)
86 su
.sun_family
= AF_UNIX
;
87 strlcpy(su
.sun_path
, name
, sizeof(su
.sun_path
));
88 if (connect(s
, (struct sockaddr
*)&su
, sizeof(struct sockaddr_un
)) == -1) {
90 log_warn("control", "unable to connect to socket %s", name
);
92 errno
= rc
; return -1;
98 * Remove the control Unix socket.
100 * @param name The name of the Unix socket.
103 ctl_cleanup(const char *name
)
105 log_debug("control", "cleanup control socket");
106 if (unlink(name
) == -1)
107 log_warn("control", "unable to unlink %s", name
);
111 * Serialize and "send" a structure through the control protocol.
113 * This function does not really send the message but outputs it to a buffer.
115 * @param output_buffer A pointer to a buffer to which the message will be
116 * appended. Can be @c NULL. In this case, the buffer will
118 * @param[in,out] output_len The length of the provided buffer. Will be updated
119 * with the new length
120 * @param type The type of message we want to send.
121 * @param t The structure to be serialized and sent.
122 * @param mi The appropriate marshal structure for serialization.
123 * @return -1 in case of failure, 0 in case of success.
125 * Make sure this function logic matches the server-side one: @c levent_ctl_recv().
128 ctl_msg_send_unserialized(uint8_t **output_buffer
, size_t *output_len
,
130 void *t
, struct marshal_info
*mi
)
132 ssize_t len
= 0, newlen
;
135 log_debug("control", "send a message through control socket");
137 len
= marshal_serialize_(mi
, t
, &buffer
, 0, NULL
, 0);
139 log_warnx("control", "unable to serialize data");
144 newlen
= len
+ sizeof(struct hmsg_header
);
146 if (*output_buffer
== NULL
) {
148 if ((*output_buffer
= malloc(newlen
)) == NULL
) {
149 log_warn("control", "no memory available");
154 void *new = realloc(*output_buffer
, *output_len
+ newlen
);
156 log_warn("control", "no memory available");
160 *output_buffer
= new;
163 struct hmsg_header hdr
;
164 memset(&hdr
, 0, sizeof(struct hmsg_header
));
167 memcpy(*output_buffer
+ *output_len
, &hdr
, sizeof(struct hmsg_header
));
169 memcpy(*output_buffer
+ *output_len
+ sizeof(struct hmsg_header
), buffer
, len
);
170 *output_len
+= newlen
;
176 * "Receive" and unserialize a structure through the control protocol.
178 * Like @c ctl_msg_send_unserialized(), this function uses buffer to receive the
181 * @param[in,out] input_buffer The buffer with the incoming message. Will be
182 * updated once the message has been unserialized to
183 * point to the remaining of the message or will be
184 * freed if all the buffer has been consumed. Can be
186 * @param[in,out] input_len The length of the provided buffer. Will be updated
187 * to the length of remaining data once the message
188 * has been unserialized.
189 * @param expected_type The expected message type.
190 * @param[out] t Will contain a pointer to the unserialized structure.
191 * Can be @c NULL if we don't want to store the
193 * @param mi The appropriate marshal structure for unserialization.
195 * @return -1 in case of error, 0 in case of success and the number of bytes we
196 * request to complete unserialization.
198 * When requesting a notification, the input buffer is left untouched if we
199 * don't get one and we fail silently.
202 ctl_msg_recv_unserialized(uint8_t **input_buffer
, size_t *input_len
,
203 enum hmsg_type expected_type
,
204 void **t
, struct marshal_info
*mi
)
206 struct hmsg_header hdr
;
209 if (*input_buffer
== NULL
||
210 *input_len
< sizeof(struct hmsg_header
)) {
211 /* Not enough data. */
212 return sizeof(struct hmsg_header
) - *input_len
;
215 log_debug("control", "receive a message through control socket");
216 memcpy(&hdr
, *input_buffer
, sizeof(struct hmsg_header
));
217 if (hdr
.len
> HMSG_MAX_SIZE
) {
218 log_warnx("control", "message received is too large");
219 /* We discard the whole buffer */
221 *input_buffer
= NULL
;
225 if (*input_len
< sizeof(struct hmsg_header
) + hdr
.len
) {
226 /* Not enough data. */
227 return sizeof(struct hmsg_header
) + hdr
.len
- *input_len
;
229 if (hdr
.type
!= expected_type
) {
230 if (expected_type
== NOTIFICATION
) return -1;
231 log_warnx("control", "incorrect received message type (expected: %d, received: %d)",
232 expected_type
, hdr
.type
);
237 log_warnx("control", "no payload available in answer");
241 /* We have data to unserialize. */
242 if (marshal_unserialize_(mi
, *input_buffer
+ sizeof(struct hmsg_header
),
243 hdr
.len
, t
, NULL
, 0, 0) <= 0) {
244 log_warnx("control", "unable to deserialize received data");
251 /* Discard input buffer */
252 *input_len
-= sizeof(struct hmsg_header
) + hdr
.len
;
253 if (*input_len
== 0) {
255 *input_buffer
= NULL
;
257 memmove(*input_buffer
,
258 *input_buffer
+ sizeof(struct hmsg_header
) + hdr
.len
,