]>
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"
32 #define UNIX_PATH_MAX 108
35 * Create a new listening Unix socket for control protocol.
37 * @param name The name of the Unix socket.
38 * @return The socket when successful, -1 otherwise.
41 ctl_create(char *name
)
44 struct sockaddr_un su
;
47 log_debug("control", "create control socket %s", name
);
49 if ((s
= socket(PF_UNIX
, SOCK_STREAM
, 0)) == -1)
51 su
.sun_family
= AF_UNIX
;
52 strlcpy(su
.sun_path
, name
, UNIX_PATH_MAX
);
53 if (bind(s
, (struct sockaddr
*)&su
, sizeof(struct sockaddr_un
)) == -1) {
54 rc
= errno
; close(s
); errno
= rc
;
58 log_debug("control", "listen to control socket %s", name
);
59 if (listen(s
, 5) == -1) {
60 rc
= errno
; close(s
); errno
= rc
;
61 log_debug("control", "cannot listen to control socket %s", name
);
68 * Connect to the control Unix socket.
70 * @param name The name of the Unix socket.
71 * @return The socket when successful, -1 otherwise.
74 ctl_connect(char *name
)
77 struct sockaddr_un su
;
80 log_debug("control", "connect to control socket %s", name
);
82 if ((s
= socket(PF_UNIX
, SOCK_STREAM
, 0)) == -1)
84 su
.sun_family
= AF_UNIX
;
85 strlcpy(su
.sun_path
, name
, UNIX_PATH_MAX
);
86 if (connect(s
, (struct sockaddr
*)&su
, sizeof(struct sockaddr_un
)) == -1) {
88 log_warn("control", "unable to connect to socket %s", name
);
89 errno
= rc
; return -1;
95 * Remove the control Unix socket.
97 * @param name The name of the Unix socket.
100 ctl_cleanup(char *name
)
102 log_debug("control", "cleanup control socket");
103 if (unlink(name
) == -1)
104 log_warn("control", "unable to unlink %s", name
);
108 * Serialize and "send" a structure through the control protocol.
110 * This function does not really send the message but outputs it to a buffer.
112 * @param output_buffer A pointer to a buffer to which the message will be
113 * appended. Can be @c NULL. In this case, the buffer will
115 * @param[in,out] output_len The length of the provided buffer. Will be updated
116 * with the new length
117 * @param type The type of message we want to send.
118 * @param t The structure to be serialized and sent.
119 * @param mi The appropriate marshal structure for serialization.
120 * @return -1 in case of failure, 0 in case of success.
122 * Make sure this function logic matches the server-side one: @c levent_ctl_recv().
125 ctl_msg_send_unserialized(uint8_t **output_buffer
, size_t *output_len
,
127 void *t
, struct marshal_info
*mi
)
129 struct hmsg_header hdr
;
130 size_t len
= 0, newlen
;
133 log_debug("control", "send a message through control socket");
135 len
= marshal_serialize_(mi
, t
, &buffer
, 0, NULL
, 0);
137 log_warnx("control", "unable to serialize data");
142 newlen
= len
+ sizeof(struct hmsg_header
);
144 if (*output_buffer
== NULL
) {
146 if ((*output_buffer
= malloc(newlen
)) == NULL
) {
147 log_warn("control", "no memory available");
152 void *new = realloc(*output_buffer
, *output_len
+ newlen
);
154 log_warn("control", "no memory available");
158 *output_buffer
= new;
160 memset(&hdr
, 0, sizeof(struct hmsg_header
));
163 memcpy(*output_buffer
+ *output_len
, &hdr
, sizeof(struct hmsg_header
));
165 memcpy(*output_buffer
+ *output_len
+ sizeof(struct hmsg_header
), buffer
, len
);
166 *output_len
+= newlen
;
172 * "Receive" and unserialize a structure through the control protocol.
174 * Like @c ctl_msg_send_unserialized(), this function uses buffer to receive the
177 * @param[in,out] input_buffer The buffer with the incoming message. Will be
178 * updated once the message has been unserialized to
179 * point to the remaining of the message or will be
180 * freed if all the buffer has been consumed. Can be
182 * @param[in,out] input_len The length of the provided buffer. Will be updated
183 * to the length of remaining data once the message
184 * has been unserialized.
185 * @param expected_type The expected message type.
186 * @param[out] t Will contain a pointer to the unserialized structure.
187 * Can be @c NULL if we don't want to store the
189 * @param mi The appropriate marshal structure for unserialization.
191 * @return -1 in case of error, 0 in case of success and the number of bytes we
192 * request to complete unserialization.
194 * When requesting a notification, the input buffer is left untouched if we
195 * don't get one and we fail silently.
198 ctl_msg_recv_unserialized(uint8_t **input_buffer
, size_t *input_len
,
199 enum hmsg_type expected_type
,
200 void **t
, struct marshal_info
*mi
)
202 struct hmsg_header hdr
;
205 if (*input_buffer
== NULL
||
206 *input_len
< sizeof(struct hmsg_header
)) {
207 /* Not enough data. */
208 return sizeof(struct hmsg_header
) - *input_len
;
211 log_debug("control", "receive a message through control socket");
212 memcpy(&hdr
, *input_buffer
, sizeof(struct hmsg_header
));
213 if (hdr
.len
> HMSG_MAX_SIZE
) {
214 log_warnx("control", "message received is too large");
215 /* We discard the whole buffer */
217 *input_buffer
= NULL
;
221 if (*input_len
< sizeof(struct hmsg_header
) + hdr
.len
) {
222 /* Not enough data. */
223 return sizeof(struct hmsg_header
) + hdr
.len
- *input_len
;
225 if (hdr
.type
!= expected_type
) {
226 if (expected_type
== NOTIFICATION
) return -1;
227 log_warnx("control", "incorrect received message type (expected: %d, received: %d)",
228 expected_type
, hdr
.type
);
233 log_warnx("control", "no payload available in answer");
237 /* We have data to unserialize. */
238 if (marshal_unserialize_(mi
, *input_buffer
+ sizeof(struct hmsg_header
),
239 hdr
.len
, t
, NULL
, 0, 0) <= 0) {
240 log_warnx("control", "unable to deserialize received data");
247 /* Discard input buffer */
248 *input_len
-= sizeof(struct hmsg_header
) + hdr
.len
;
249 if (*input_len
== 0) {
251 *input_buffer
= NULL
;
253 memmove(*input_buffer
,
254 *input_buffer
+ sizeof(struct hmsg_header
) + hdr
.len
,