]>
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
);
88 errno
= rc
; return -1;
94 * Remove the control Unix socket.
96 * @param name The name of the Unix socket.
99 ctl_cleanup(char *name
)
101 log_debug("control", "cleanup control socket");
102 if (unlink(name
) == -1)
103 log_warn("control", "unable to unlink %s", name
);
107 * Serialize and "send" a structure through the control protocol.
109 * This function does not really send the message but outputs it to a buffer.
111 * @param output_buffer A pointer to a buffer to which the message will be
112 * appended. Can be @c NULL. In this case, the buffer will
114 * @param[in,out] output_len The length of the provided buffer. Will be updated
115 * with the new length
116 * @param type The type of message we want to send.
117 * @param t The structure to be serialized and sent.
118 * @param mi The appropriate marshal structure for serialization.
119 * @return -1 in case of failure, 0 in case of success.
121 * Make sure this function logic matches the server-side one: @c levent_ctl_recv().
124 ctl_msg_send_unserialized(uint8_t **output_buffer
, size_t *output_len
,
126 void *t
, struct marshal_info
*mi
)
128 struct hmsg_header hdr
;
129 ssize_t len
= 0, newlen
;
132 log_debug("control", "send a message through control socket");
134 len
= marshal_serialize_(mi
, t
, &buffer
, 0, NULL
, 0);
136 log_warnx("control", "unable to serialize data");
141 newlen
= len
+ sizeof(struct hmsg_header
);
143 if (*output_buffer
== NULL
) {
145 if ((*output_buffer
= malloc(newlen
)) == NULL
) {
146 log_warn("control", "no memory available");
151 void *new = realloc(*output_buffer
, *output_len
+ newlen
);
153 log_warn("control", "no memory available");
157 *output_buffer
= new;
159 memset(&hdr
, 0, sizeof(struct hmsg_header
));
162 memcpy(*output_buffer
+ *output_len
, &hdr
, sizeof(struct hmsg_header
));
164 memcpy(*output_buffer
+ *output_len
+ sizeof(struct hmsg_header
), buffer
, len
);
165 *output_len
+= newlen
;
171 * "Receive" and unserialize a structure through the control protocol.
173 * Like @c ctl_msg_send_unserialized(), this function uses buffer to receive the
176 * @param[in,out] input_buffer The buffer with the incoming message. Will be
177 * updated once the message has been unserialized to
178 * point to the remaining of the message or will be
179 * freed if all the buffer has been consumed. Can be
181 * @param[in,out] input_len The length of the provided buffer. Will be updated
182 * to the length of remaining data once the message
183 * has been unserialized.
184 * @param expected_type The expected message type.
185 * @param[out] t Will contain a pointer to the unserialized structure.
186 * Can be @c NULL if we don't want to store the
188 * @param mi The appropriate marshal structure for unserialization.
190 * @return -1 in case of error, 0 in case of success and the number of bytes we
191 * request to complete unserialization.
193 * When requesting a notification, the input buffer is left untouched if we
194 * don't get one and we fail silently.
197 ctl_msg_recv_unserialized(uint8_t **input_buffer
, size_t *input_len
,
198 enum hmsg_type expected_type
,
199 void **t
, struct marshal_info
*mi
)
201 struct hmsg_header hdr
;
204 if (*input_buffer
== NULL
||
205 *input_len
< sizeof(struct hmsg_header
)) {
206 /* Not enough data. */
207 return sizeof(struct hmsg_header
) - *input_len
;
210 log_debug("control", "receive a message through control socket");
211 memcpy(&hdr
, *input_buffer
, sizeof(struct hmsg_header
));
212 if (hdr
.len
> HMSG_MAX_SIZE
) {
213 log_warnx("control", "message received is too large");
214 /* We discard the whole buffer */
216 *input_buffer
= NULL
;
220 if (*input_len
< sizeof(struct hmsg_header
) + hdr
.len
) {
221 /* Not enough data. */
222 return sizeof(struct hmsg_header
) + hdr
.len
- *input_len
;
224 if (hdr
.type
!= expected_type
) {
225 if (expected_type
== NOTIFICATION
) return -1;
226 log_warnx("control", "incorrect received message type (expected: %d, received: %d)",
227 expected_type
, hdr
.type
);
232 log_warnx("control", "no payload available in answer");
236 /* We have data to unserialize. */
237 if (marshal_unserialize_(mi
, *input_buffer
+ sizeof(struct hmsg_header
),
238 hdr
.len
, t
, NULL
, 0, 0) <= 0) {
239 log_warnx("control", "unable to deserialize received data");
246 /* Discard input buffer */
247 *input_len
-= sizeof(struct hmsg_header
) + hdr
.len
;
248 if (*input_len
== 0) {
250 *input_buffer
= NULL
;
252 memmove(*input_buffer
,
253 *input_buffer
+ sizeof(struct hmsg_header
) + hdr
.len
,