]>
git.ipfire.org Git - thirdparty/lldpd.git/blob - src/ctl.c
2 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 #include <sys/types.h>
22 #include <sys/socket.h>
26 ctl_create(char *name
)
29 struct sockaddr_un su
;
32 if ((s
= socket(PF_UNIX
, SOCK_STREAM
, 0)) == -1)
34 su
.sun_family
= AF_UNIX
;
35 strlcpy(su
.sun_path
, name
, UNIX_PATH_MAX
);
36 if (bind(s
, (struct sockaddr
*)&su
, sizeof(struct sockaddr_un
)) == -1) {
37 rc
= errno
; close(s
); errno
= rc
;
40 if (listen(s
, 5) == -1) {
41 rc
= errno
; close(s
); errno
= rc
;
48 ctl_connect(char *name
)
51 struct sockaddr_un su
;
54 if ((s
= socket(PF_UNIX
, SOCK_STREAM
, 0)) == -1)
56 su
.sun_family
= AF_UNIX
;
57 strlcpy(su
.sun_path
, name
, UNIX_PATH_MAX
);
58 if (connect(s
, (struct sockaddr
*)&su
, sizeof(struct sockaddr_un
)) == -1) {
60 LLOG_WARN("unable to connect to socket " LLDPD_CTL_SOCKET
);
61 errno
= rc
; return -1;
67 ctl_accept(struct lldpd
*cfg
, int c
)
70 struct lldpd_client
*lc
;
71 if ((s
= accept(c
, NULL
, NULL
)) == -1) {
72 LLOG_WARN("unable to accept connection from socket");
75 if ((lc
= (struct lldpd_client
*)malloc(sizeof(
76 struct lldpd_client
))) == NULL
) {
77 LLOG_WARN("failed to allocate memory for new client");
82 TAILQ_INSERT_TAIL(&cfg
->g_clients
, lc
, next
);
87 ctl_msg_init(struct hmsg
*t
, enum hmsg_type type
)
91 t
->hdr
.pid
= getpid();
95 ctl_msg_send(int fd
, struct hmsg
*t
)
97 return write(fd
, t
, t
->hdr
.len
+ sizeof(struct hmsg_hdr
));
101 ctl_msg_recv(int fd
, struct hmsg
*t
)
104 if ((n
= read(fd
, t
, MAX_HMSGSIZE
)) == -1) {
107 if (n
< sizeof(struct hmsg_hdr
)) {
108 LLOG_WARNX("message received too short");
112 if (n
!= sizeof(struct hmsg_hdr
) + t
->hdr
.len
) {
113 LLOG_WARNX("message from %d seems to be truncated (or too large)",
122 ctl_close(struct lldpd
*cfg
, int c
)
124 struct lldpd_client
*client
, *client_next
;
125 for (client
= TAILQ_FIRST(&cfg
->g_clients
);
127 client
= client_next
) {
128 client_next
= TAILQ_NEXT(client
, next
);
129 if (client
->fd
== c
) {
131 TAILQ_REMOVE(&cfg
->g_clients
, client
, next
);
141 ctl_cleanup(char *name
)
143 if (unlink(name
) == -1)
144 LLOG_WARN("unable to unlink %s", name
);
147 /* Packing/unpacking */
149 /* This structure is used to track memory allocation when unpacking */
151 TAILQ_ENTRY(gc
) next
;
154 TAILQ_HEAD(gc_l
, gc
);
156 typedef struct { char c
; int16_t x
; } st_int16
;
157 typedef struct { char c
; int32_t x
; } st_int32
;
158 typedef struct { char c
; void *x
; } st_void_p
;
160 #define INT16_ALIGN (sizeof(st_int16) - sizeof(int16_t))
161 #define INT32_ALIGN (sizeof(st_int32) - sizeof(int32_t))
162 #define VOID_P_ALIGN (sizeof(st_void_p) - sizeof(void *))
168 int (*pack
)(struct hmsg
*, void **, void *,
169 const struct formatdef
*);
170 int (*unpack
)(struct hmsg
*, void **, void *,
171 const struct formatdef
*, struct gc_l
*);
174 /* void** is a pointer to a pointer to the end of struct hmsg*. It should be
175 * updated. void* is a pointer to the entity to pack */
178 _ctl_alloc_pointer(struct gc_l
*pointers
, void *pointer
)
181 if (pointers
!= NULL
) {
182 if ((gpointer
= (struct gc
*)calloc(1,
183 sizeof(struct gc
))) == NULL
) {
184 LLOG_WARN("unable to allocate memory for garbage collector");
187 gpointer
->pointer
= pointer
;
188 TAILQ_INSERT_TAIL(pointers
, gpointer
, next
);
194 _ctl_free_pointers(struct gc_l
*pointers
, int listonly
)
196 struct gc
*pointer
, *pointer_next
;
197 for (pointer
= TAILQ_FIRST(pointers
);
199 pointer
= pointer_next
) {
200 pointer_next
= TAILQ_NEXT(pointer
, next
);
201 TAILQ_REMOVE(pointers
, pointer
, next
);
203 free(pointer
->pointer
);
209 pack_copy(struct hmsg
*h
, void **p
, void *s
,
210 const struct formatdef
*ct
)
212 if (h
->hdr
.len
+ ct
->size
> MAX_HMSGSIZE
- sizeof(struct hmsg_hdr
)) {
213 LLOG_WARNX("message became too large");
216 memcpy(*p
, s
, ct
->size
);
218 h
->hdr
.len
+= ct
->size
;
223 unpack_copy(struct hmsg
*h
, void **p
, void *s
,
224 const struct formatdef
*ct
, struct gc_l
*pointers
)
226 memcpy(s
, *p
, ct
->size
);
232 pack_string(struct hmsg
*h
, void **p
, void *s
,
233 const struct formatdef
*ct
)
236 if ((*(char**)s
) == NULL
)
239 len
= strlen(*(char**)s
);
240 if (h
->hdr
.len
+ len
+ sizeof(int) > MAX_HMSGSIZE
-
241 sizeof(struct hmsg_hdr
)) {
242 LLOG_WARNX("message became too large");
245 memcpy(*p
, &len
, sizeof(int));
249 memcpy(*p
, *(char **)s
, len
);
258 unpack_string(struct hmsg
*h
, void **p
, void *s
,
259 const struct formatdef
*ct
, struct gc_l
*pointers
)
267 if ((string
= (char *)calloc(1, len
+ 1)) == NULL
) {
268 LLOG_WARNX("unable to allocate new string");
271 if (_ctl_alloc_pointer(pointers
, string
) == -1) {
275 memcpy(string
, *p
, len
);
278 memcpy(s
, &string
, sizeof(char *));
279 return sizeof(char*);
283 pack_chars(struct hmsg
*h
, void **p
, void *s
,
284 const struct formatdef
*ct
)
288 string
= *(char **)s
;
290 string_len
= *(int *)s
;
292 if (h
->hdr
.len
+ string_len
+ sizeof(int) > MAX_HMSGSIZE
-
293 sizeof(struct hmsg_hdr
)) {
294 LLOG_WARNX("message became too large");
297 memcpy(*p
, &string_len
, sizeof(int));
299 memcpy(*p
, string
, string_len
);
301 h
->hdr
.len
+= sizeof(int) + string_len
;
302 return sizeof(int) + string_len
;
306 unpack_chars(struct hmsg
*h
, void **p
, void *s
,
307 const struct formatdef
*ct
, struct gc_l
*pointers
)
313 } reals
__attribute__ ((__packed__
));
316 if ((string
= (char *)malloc(len
)) == NULL
) {
317 LLOG_WARN("unable to allocate new string");
320 if (_ctl_alloc_pointer(pointers
, string
) == -1) {
324 memcpy(string
, *p
, len
);
326 reals
.string
= string
;
328 memcpy(s
, &reals
, sizeof(reals
));
329 return sizeof(char*);
333 pack_zero(struct hmsg
*h
, void **p
, void *s
,
334 const struct formatdef
*ct
)
336 if (h
->hdr
.len
+ ct
->size
> MAX_HMSGSIZE
- sizeof(struct hmsg_hdr
)) {
337 LLOG_WARNX("message became too large");
340 memset(*p
, 0, ct
->size
);
342 h
->hdr
.len
+= ct
->size
;
346 static struct formatdef conv_table
[] = {
348 pack_copy
, unpack_copy
},
349 {'w', 2, INT16_ALIGN
,
350 pack_copy
, unpack_copy
},
351 {'l', 4, INT32_ALIGN
,
352 pack_copy
, unpack_copy
},
353 /* Null terminated string */
354 {'s', sizeof(void*), VOID_P_ALIGN
,
355 pack_string
, unpack_string
},
356 /* Pointer (is packed with 0) */
357 {'P', sizeof(void*), VOID_P_ALIGN
,
358 pack_zero
, unpack_copy
},
359 /* A list (same as pointer), should be at the beginning */
360 {'L', sizeof(void*)*2, VOID_P_ALIGN
,
361 pack_zero
, unpack_copy
},
362 /* Non null terminated string, followed by an int for the size */
363 {'C', sizeof(void*) + sizeof(int), VOID_P_ALIGN
,
364 pack_chars
, unpack_chars
},
368 /* Lists can be packed only if the "next" member is the first one of the
369 * structure! No check is done for this. */
371 TAILQ_ENTRY(fakelist_m
) next
;
374 TAILQ_HEAD(fakelist_l
, fakelist_m
);
377 ctl_msg_pack_structure(char *format
, void *structure
, unsigned int size
,
378 struct hmsg
*h
, void **p
)
381 struct formatdef
*ce
;
382 unsigned int csize
= 0;
386 for (f
= format
; *f
!= 0; f
++) {
387 for (ce
= conv_table
;
390 if (ce
->format
== *f
)
393 if (ce
->format
!= *f
) {
394 LLOG_WARNX("unknown format char %c in %s", *f
,
398 if (ce
->alignment
!= 0) {
399 maxalign
= (maxalign
>ce
->alignment
)?maxalign
:ce
->alignment
;
400 offset
= (uintptr_t)structure
% ce
->alignment
;
402 structure
= structure
+
403 (ce
->alignment
- offset
);
404 csize
+= ce
->alignment
- offset
;
407 if (ce
->pack(h
, p
, structure
, ce
) == -1) {
408 LLOG_WARNX("error while packing %c in %s", *f
,
412 structure
+= ce
->size
;
417 if ((maxalign
> 0) && (csize
% maxalign
!= 0))
418 csize
= csize
+ maxalign
- (csize
% maxalign
);
420 LLOG_WARNX("size of structure does not match its "
421 "declaration (%d vs %d)", size
, csize
);
428 _ctl_msg_unpack_structure(char *format
, void *structure
, unsigned int size
,
429 struct hmsg
*h
, void **p
, struct gc_l
*pointers
)
432 struct formatdef
*ce
;
433 unsigned int csize
= 0;
437 for (f
= format
; *f
!= 0; f
++) {
438 for (ce
= conv_table
;
441 if (ce
->format
== *f
)
444 if (ce
->format
!= *f
) {
445 LLOG_WARNX("unknown format char %c", *f
);
448 if (ce
->alignment
!= 0) {
449 maxalign
= (maxalign
>ce
->alignment
)?maxalign
:ce
->alignment
;
450 offset
= (uintptr_t)structure
% ce
->alignment
;
452 structure
= structure
+
453 (ce
->alignment
- offset
);
454 csize
+= ce
->alignment
- offset
;
459 LLOG_WARNX("size of structure is too small for given "
460 "format (%d vs %d)", size
, csize
);
464 if (ce
->unpack(h
, p
, structure
, ce
, pointers
) == -1) {
465 LLOG_WARNX("error while unpacking %c", *f
);
468 structure
+= ce
->size
;
472 if ((maxalign
> 0) && (csize
% maxalign
!= 0))
473 csize
= csize
+ maxalign
- (csize
% maxalign
);
475 LLOG_WARNX("size of structure does not match its "
476 "declaration (%d vs %d)", size
, csize
);
483 ctl_msg_unpack_structure(char *format
, void *structure
, unsigned int size
,
484 struct hmsg
*h
, void **p
)
486 struct gc_l pointers
;
488 TAILQ_INIT(&pointers
);
489 if ((rc
= _ctl_msg_unpack_structure(format
, structure
, size
,
490 h
, p
, &pointers
)) == -1) {
491 LLOG_WARNX("unable to unpack structure, freeing");
492 _ctl_free_pointers(&pointers
, 0);
495 _ctl_free_pointers(&pointers
, 1);
500 ctl_msg_pack_list(char *format
, void *list
, unsigned int size
, struct hmsg
*h
, void **p
)
502 struct fakelist_m
*member
;
503 struct fakelist_l
*flist
= (struct fakelist_l
*)list
;
504 TAILQ_FOREACH(member
, flist
, next
) {
505 if (ctl_msg_pack_structure(format
, member
, size
, h
, p
) == -1) {
506 LLOG_WARNX("error while packing list, aborting");
514 ctl_msg_unpack_list(char *format
, void *list
, unsigned int size
, struct hmsg
*h
, void **p
)
516 struct fakelist_m
*member
, *member_next
;
517 struct gc_l pointers
;
518 struct fakelist_l
*flist
= (struct fakelist_l
*)list
;
519 if (format
[0] != 'L') {
520 LLOG_WARNX("to unpack a list, format should start with 'L'");
524 TAILQ_INIT(&pointers
);
525 while (*p
- (void *)h
- sizeof(struct hmsg_hdr
) < h
->hdr
.len
) {
526 if ((member
= calloc(1, size
)) == NULL
) {
527 LLOG_WARN("unable to allocate memory for structure");
530 if (_ctl_msg_unpack_structure(format
, member
, size
,
531 h
, p
, &pointers
) == -1) {
532 LLOG_WARNX("unable to unpack list, aborting");
534 /* Free each list member */
535 for (member
= TAILQ_FIRST(flist
);
537 member
= member_next
) {
538 member_next
= TAILQ_NEXT(member
, next
);
539 TAILQ_REMOVE(flist
, member
, next
);
542 _ctl_free_pointers(&pointers
, 0);
545 TAILQ_INSERT_TAIL(flist
, member
, next
);
547 _ctl_free_pointers(&pointers
, 1);