lldpd_LDADD = liblldpd.la
## lldpctl
-lldpctl_SOURCES = lldpctl.c display.c writer.h text_writer.c kv_writer.c
+lldpctl_SOURCES = lldpctl.h lldpctl.c display.c writer.h text_writer.c kv_writer.c
lldpctl_LDADD = libcommon.la
## With SNMP...
#include "lldpd.h"
-static struct client_handle client_handles[] = {
- { HMSG_NONE, client_handle_none },
- { HMSG_GET_INTERFACES, client_handle_get_interfaces },
- { HMSG_GET_NB_PORTS, client_handle_port_related },
- { HMSG_GET_PORT, client_handle_port_related },
- { HMSG_GET_CHASSIS, client_handle_port_related },
-#ifdef ENABLE_LLDPMED
- { HMSG_SET_LOCATION, client_handle_port_related },
- { HMSG_SET_POLICY, client_handle_port_related },
- { HMSG_SET_POWER, client_handle_port_related },
-#endif
-#ifdef ENABLE_DOT3
- { HMSG_SET_DOT3_POWER, client_handle_port_related },
-#endif
-#ifdef ENABLE_DOT1
- { HMSG_GET_VLANS, client_handle_port_related },
- { HMSG_GET_PPVIDS, client_handle_port_related },
- { HMSG_GET_PIDS, client_handle_port_related },
-#endif
- { HMSG_SHUTDOWN, client_handle_shutdown },
- { 0, NULL } };
-
-void
-client_handle_client(struct lldpd *cfg, struct lldpd_callback *callback,
- char *buffer, int n)
+static int
+client_handle_none(struct lldpd *cfg, enum hmsg_type *type,
+ void *input, int input_len, void **output)
{
- struct hmsg *h; /* Reception */
- struct hmsg *t; /* Sending */
- struct client_handle *ch;
-
- if (n < sizeof(struct hmsg_hdr)) {
- LLOG_WARNX("too short message request received");
- return;
- }
- h = (struct hmsg *)buffer;
- n -= sizeof(struct hmsg_hdr);
- if (n != h->hdr.len) {
- LLOG_WARNX("incorrect message size received from %d",
- h->hdr.pid);
- return;
- }
-
- if ((t = (struct hmsg*)malloc(MAX_HMSGSIZE)) == NULL) {
- LLOG_WARNX("unable to allocate memory to answer to %d",
- h->hdr.pid);
- return;
- }
- ctl_msg_init(t, h->hdr.type);
- for (ch = client_handles; ch->handle != NULL; ch++) {
- if (ch->type == h->hdr.type) {
- ch->handle(cfg, h, t);
- if (t->hdr.len == -1) {
- t->hdr.len = 0;
- t->hdr.type = HMSG_NONE;
- }
- if (ctl_msg_send(callback->fd, t) == -1)
- LLOG_WARN("unable to send answer to client %d",
- h->hdr.pid);
- free(t);
- return;
- }
- }
-
- LLOG_WARNX("unknown message request (%d) received from %d",
- h->hdr.type, h->hdr.pid);
- free(t);
- return;
+ LLOG_INFO("received noop request from client");
+ *type = NONE;
+ return 0;
}
-void
-client_handle_shutdown(struct lldpd *cfg, struct hmsg *r, struct hmsg *s)
-{
- LLOG_INFO("received shutdown request from client %d",
- r->hdr.pid);
- exit(0);
-}
-
-void
-client_handle_none(struct lldpd *cfg, struct hmsg *r, struct hmsg *s)
-{
- LLOG_INFO("received noop request from client %d",
- r->hdr.pid);
- s->hdr.len = -1;
-}
-
-void
-client_handle_get_interfaces(struct lldpd *cfg, struct hmsg *r, struct hmsg *s)
+/* Return the list of interfaces.
+ Input: nothing.
+ Output: list of interface names (lldpd_interface_list)
+*/
+static int
+client_handle_get_interfaces(struct lldpd *cfg, enum hmsg_type *type,
+ void *input, int input_len, void **output)
{
struct lldpd_interface *iff, *iff_next;
struct lldpd_hardware *hardware;
- void *p;
/* Build the list of interfaces */
- TAILQ_HEAD(, lldpd_interface) ifs;
+ struct lldpd_interface_list ifs;
TAILQ_INIT(&ifs);
TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
if ((iff = (struct lldpd_interface*)malloc(sizeof(
TAILQ_INSERT_TAIL(&ifs, iff, next);
}
- p = &s->data;
- if (ctl_msg_pack_list(STRUCT_LLDPD_INTERFACE, &ifs,
- sizeof(struct lldpd_interface), s, &p) == -1) {
- LLOG_WARNX("unable to pack list of interfaces");
- s->hdr.len = -1;
+ int output_len = marshal_serialize(lldpd_interface_list, &ifs, output);
+ if (output_len <= 0) {
+ output_len = 0;
+ *type = NONE;
}
/* Free the temporary list */
TAILQ_REMOVE(&ifs, iff, next);
free(iff);
}
+
+ return output_len;
}
-void
-client_handle_port_related(struct lldpd *cfg, struct hmsg *r, struct hmsg *s)
+/* Return all available information related to an interface
+ Input: name of the interface (serialized)
+ Output: Information about the interface (lldpd_hardware)
+*/
+static int
+client_handle_get_interface(struct lldpd *cfg, enum hmsg_type *type,
+ void *input, int input_len, void **output)
{
- char *ifname;
+ /* Get name of the interface */
+ char *name;
+ if (marshal_unserialize(string, input, input_len, &name) <= 0) {
+ *type = NONE;
+ return 0;
+ }
+
+ /* Search appropriate hardware */
struct lldpd_hardware *hardware;
- struct lldpd_port *port;
- void *p;
- int i;
+ TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries)
+ if (!strcmp(hardware->h_ifname, name)) {
+ int output_len = marshal_serialize(lldpd_hardware, hardware, output);
+ free(name);
+ if (output_len <= 0) {
+ *type = NONE;
+ free(name);
+ return 0;
+ }
+ return output_len;
+ }
+
+ free(name);
+ LLOG_WARNX("no interface %s found", name);
+ *type = NONE;
+ return 0;
+}
+
+/* Set some port related settings (policy, location, power)
+ Input: name of the interface, policy/location/power setting to be modified
+ Output: nothing
+*/
+static int
+client_handle_set_port(struct lldpd *cfg, enum hmsg_type *type,
+ void *input, int input_len, void **output)
+{
+ int ret = 0;
+ struct lldpd_port_set *set;
- ifname = (char*)(&r->data);
- if ((r->hdr.len < IFNAMSIZ) || (ifname[IFNAMSIZ - 1] != 0)) {
- LLOG_WARNX("bad message format for get port related message (%d)",
- r->hdr.type);
- s->hdr.len = -1;
- return;
+ if (marshal_unserialize(lldpd_port_set, input, input_len, &set) <= 0) {
+ *type = NONE;
+ return 0;
}
- TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
- if (strncmp(ifname, hardware->h_ifname, IFNAMSIZ) == 0) {
- switch (r->hdr.type) {
+ if (!set->ifname) {
+ LLOG_WARNX("no interface provided");
+ goto set_port_finished;
+ }
+
+ /* Search the appropriate hardware */
+ struct lldpd_hardware *hardware;
+ TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries)
+ if (!strcmp(hardware->h_ifname, set->ifname)) {
+ struct lldpd_port *port = &hardware->h_lport;
#ifdef ENABLE_LLDPMED
- case HMSG_SET_LOCATION:
- p = (char*)&r->data + IFNAMSIZ;
- for (i=0; i < LLDPMED_LOCFORMAT_LAST; i++) {
- free(hardware->h_lport.p_med_location[i].data);
- hardware->h_lport.p_med_location[i].data = NULL;
- hardware->h_lport.p_med_location[i].format = 0;
- }
- if (ctl_msg_unpack_structure(STRUCT_LLDPD_MED_LOC
- STRUCT_LLDPD_MED_LOC STRUCT_LLDPD_MED_LOC,
- hardware->h_lport.p_med_location,
- 3*sizeof(struct lldpd_med_loc), r, &p) == -1) {
- LLOG_WARNX("unable to set location for %s", ifname);
- s->hdr.len = -1;
- return;
- }
- hardware->h_lport.p_med_cap_enabled |= LLDPMED_CAP_LOCATION;
- break;
- case HMSG_SET_POLICY:
- p = (char*)&r->data + IFNAMSIZ;
- for (i=0; i < LLDPMED_APPTYPE_LAST; i++) {
- hardware->h_lport.p_med_policy[i].type = 0;
- hardware->h_lport.p_med_policy[i].unknown = 0;
- hardware->h_lport.p_med_policy[i].tagged = 0;
- hardware->h_lport.p_med_policy[i].vid = 0;
- hardware->h_lport.p_med_policy[i].priority = 0;
- hardware->h_lport.p_med_policy[i].dscp = 0;
- }
- if (ctl_msg_unpack_structure(
- STRUCT_LLDPD_MED_POLICY
- STRUCT_LLDPD_MED_POLICY
- STRUCT_LLDPD_MED_POLICY
- STRUCT_LLDPD_MED_POLICY
- STRUCT_LLDPD_MED_POLICY
- STRUCT_LLDPD_MED_POLICY
- STRUCT_LLDPD_MED_POLICY
- STRUCT_LLDPD_MED_POLICY,
- hardware->h_lport.p_med_policy,
- 8*sizeof(struct lldpd_med_policy),
- r, &p) == -1) {
- LLOG_WARNX("unable to set network policy for %s", ifname);
- s->hdr.len = -1;
- return;
- }
- hardware->h_lport.p_med_cap_enabled |=
- LLDPMED_CAP_POLICY;
- break;
- case HMSG_SET_POWER:
- p = (char*)&r->data + IFNAMSIZ;
- memset(&hardware->h_lport.p_med_power, 0,
- sizeof(struct lldpd_med_power));
- if (ctl_msg_unpack_structure(STRUCT_LLDPD_MED_POWER,
- &hardware->h_lport.p_med_power,
- sizeof(struct lldpd_med_power),
- r, &p) == -1) {
- LLOG_WARNX("unable to set POE-MDI for %s",
- ifname);
- s->hdr.len = -1;
- return;
- }
- hardware->h_lport.p_med_cap_enabled &= ~(
- LLDPMED_CAP_MDI_PD | LLDPMED_CAP_MDI_PSE);
- switch (hardware->h_lport.p_med_power.devicetype)
- {
- case LLDPMED_POW_TYPE_PSE:
- hardware->h_lport.p_med_cap_enabled |=
- LLDPMED_CAP_MDI_PSE;
- break;
- case LLDPMED_POW_TYPE_PD:
- hardware->h_lport.p_med_cap_enabled |=
- LLDPMED_CAP_MDI_PD;
- break;
- }
- break;
+ if (set->med_policy && set->med_policy->type > 0) {
+ if (set->med_policy->type > LLDPMED_APPTYPE_LAST) {
+ LLOG_WARNX("invalid policy provided: %d",
+ set->med_policy->type);
+ goto set_port_finished;
+ }
+ memcpy(&port->p_med_policy[set->med_policy->type - 1],
+ set->med_policy, sizeof(struct lldpd_med_policy));
+ port->p_med_cap_enabled |= LLDPMED_CAP_POLICY;
+ }
+ if (set->med_location && set->med_location->format > 0) {
+ if (set->med_location->format > LLDPMED_LOCFORMAT_LAST) {
+ LLOG_WARNX("invalid location format provided: %d",
+ set->med_location->format);
+ goto set_port_finished;
+ }
+ struct lldpd_med_loc *loc = \
+ &port->p_med_location[set->med_location->format - 1];
+ free(loc->data);
+ memcpy(loc, set->med_location, sizeof(struct lldpd_med_loc));
+ if (!loc->data || !(loc->data = strdup(loc->data))) loc->data_len = 0;
+ port->p_med_cap_enabled |= LLDPMED_CAP_LOCATION;
+ }
+ if (set->med_power) {
+ memcpy(&port->p_med_power, set->med_power,
+ sizeof(struct lldpd_med_power));
+ switch (set->med_power->devicetype) {
+ case LLDPMED_POW_TYPE_PD:
+ port->p_med_cap_enabled |= LLDPMED_CAP_MDI_PD;
+ port->p_med_cap_enabled &= ~LLDPMED_CAP_MDI_PSE;
+ break;
+ case LLDPMED_POW_TYPE_PSE:
+ port->p_med_cap_enabled |= LLDPMED_CAP_MDI_PSE;
+ port->p_med_cap_enabled &= ~LLDPMED_CAP_MDI_PD;
+ break;
+ }
+ }
#endif
#ifdef ENABLE_DOT3
- case HMSG_SET_DOT3_POWER:
- p = (char*)&r->data + IFNAMSIZ;
- memset(&hardware->h_lport.p_power, 0,
- sizeof(struct lldpd_dot3_power));
- if (ctl_msg_unpack_structure(STRUCT_LLDPD_DOT3_POWER,
- &hardware->h_lport.p_power,
- sizeof(struct lldpd_dot3_power),
- r, &p) == -1) {
- LLOG_WARNX("unable to set POE-MDI for %s",
- ifname);
- s->hdr.len = -1;
- return;
- }
- break;
+ if (set->dot3_power)
+ memcpy(&port->p_power, set->dot3_power,
+ sizeof(struct lldpd_dot3_power));
#endif
- case HMSG_GET_NB_PORTS:
- p = &s->data;
- i = 0;
- TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
- if (SMART_HIDDEN(port)) continue;
- i++;
- }
- memcpy(p, &i, sizeof(int));
- s->hdr.len = sizeof(int);
- break;
- case HMSG_GET_VLANS:
- case HMSG_GET_PPVIDS:
- case HMSG_GET_PIDS:
- case HMSG_GET_PORT:
- case HMSG_GET_CHASSIS:
- /* We read the index which is right after the interface name */
- if (r->hdr.len < IFNAMSIZ + sizeof(int)) {
- LLOG_WARNX("too short message format for get "
- "port related message (%d)", r->hdr.type);
- s->hdr.len = -1;
- return;
- }
- p = (char*)&r->data + IFNAMSIZ;
- memcpy(&i, p, sizeof(int));
- p = &s->data;
- TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
- if (SMART_HIDDEN(port)) continue;
- if (i-- == 0) break;
- }
- if (!port) {
- LLOG_INFO("out of range index requested for port "
- "related information on interface %s for %d",
- ifname, r->hdr.pid);
- s->hdr.len = -1;
- return;
- }
- p = (char*)&s->data;
- switch (r->hdr.type) {
-#ifdef ENABLE_DOT1
- case HMSG_GET_VLANS:
- if (ctl_msg_pack_list(STRUCT_LLDPD_VLAN,
- &port->p_vlans,
- sizeof(struct lldpd_vlan), s, &p) == -1) {
- LLOG_WARNX("unable to send vlans information for "
- "interface %s for %d", ifname, r->hdr.pid);
- s->hdr.len = -1;
- return;
- }
- break;
- case HMSG_GET_PPVIDS:
- if (ctl_msg_pack_list(
- STRUCT_LLDPD_PPVID,
- &port->p_ppvids,
- sizeof(struct lldpd_ppvid), s, &p) == -1) {
- LLOG_WARNX("unable to send ppvids information for "
- "interface %s for %d", ifname, r->hdr.pid);
- s->hdr.len = -1;
- return;
- }
- break;
- case HMSG_GET_PIDS:
- if (ctl_msg_pack_list(
- STRUCT_LLDPD_PI,
- &port->p_pids,
- sizeof(struct lldpd_pi), s, &p) == -1) {
- LLOG_WARNX("unable to send PI's information for "
- "interface %s for %d", ifname, r->hdr.pid);
- s->hdr.len = -1;
- return;
- }
- break;
+ ret = 1;
+ break;
+ }
+
+ if (ret == 0)
+ LLOG_WARN("no interface %s found", set->ifname);
+
+set_port_finished:
+ if (!ret) *type = NONE;
+ free(set->ifname);
+#ifdef ENABLE_LLDPMED
+ free(set->med_policy);
+ if (set->med_location) free(set->med_location->data);
+ free(set->med_location);
+ free(set->med_power);
#endif
- case HMSG_GET_PORT:
- if (ctl_msg_pack_structure(STRUCT_LLDPD_PORT,
- port,
- sizeof(struct lldpd_port), s, &p) == -1) {
- LLOG_WARNX("unable to send port information for "
- "interface %s for %d", ifname, r->hdr.pid);
- s->hdr.len = -1;
- return;
- }
- break;
- case HMSG_GET_CHASSIS:
- if (ctl_msg_pack_structure(STRUCT_LLDPD_CHASSIS,
- port->p_chassis,
- sizeof(struct lldpd_chassis), s, &p) == -1) {
- LLOG_WARNX("unable to send chassis information "
- "for interface %s for %d",
- ifname, r->hdr.pid);
- s->hdr.len = -1;
- return;
- }
- break;
- default:
- LLOG_WARNX("don't know what to do");
- s->hdr.len = -1;
- return;
- }
- break;
- default:
- LLOG_WARNX("don't know what to do");
- s->hdr.len = -1;
- return;
- }
- return;
+#ifdef ENABLE_DOT3
+ free(set->dot3_power);
+#endif
+ return 0;
+}
+
+static struct client_handle client_handles[] = {
+ { NONE, client_handle_none },
+ { GET_INTERFACES, client_handle_get_interfaces },
+ { GET_INTERFACE, client_handle_get_interface },
+ { SET_PORT, client_handle_set_port },
+ { 0, NULL } };
+
+int
+client_handle_client(struct lldpd *cfg, struct lldpd_callback *callback,
+ enum hmsg_type type, void *buffer, int n)
+{
+ struct client_handle *ch;
+ void *answer; int len, sent;
+ for (ch = client_handles; ch->handle != NULL; ch++) {
+ if (ch->type == type) {
+ answer = NULL; len = 0;
+ len = ch->handle(cfg, &type, buffer, n, &answer);
+ if ((sent = ctl_msg_send(callback->fd, type, answer, len)) == -1)
+ LLOG_WARN("unable to send answer to client");
+ free(answer);
+ return sent;
}
}
- LLOG_WARNX("requested interface %s by %d was not found",
- ifname, r->hdr.pid);
- s->hdr.len = -1;
- return;
+
+ LLOG_WARNX("unknown message request (%d) received",
+ type);
+ return -1;
}
static void
ctl_callback(struct lldpd *cfg, struct lldpd_callback *callback)
{
- char *buffer;
- int n;
+ enum hmsg_type type;
+ void *buffer = NULL;
+ int n;
- if ((buffer = (char *)malloc(MAX_HMSGSIZE)) ==
- NULL) {
- LLOG_WARN("failed to alloc reception buffer");
- return;
- }
- if ((n = recv(callback->fd, buffer,
- MAX_HMSGSIZE, 0)) == -1) {
- LLOG_WARN("error while receiving message");
- free(buffer);
- return;
- }
- if (n > 0)
- client_handle_client(cfg, callback, buffer, n);
- else {
+ if ((n = ctl_msg_recv(callback->fd, &type, &buffer)) == -1 ||
+ client_handle_client(cfg, callback, type, buffer, n) == -1) {
close(callback->fd);
lldpd_callback_del(cfg, callback->fd, ctl_callback);
}
#include "lldpd.h"
#include <unistd.h>
+#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
return s;
}
-void
-ctl_msg_init(struct hmsg *t, enum hmsg_type type)
-{
- memset(t, 0, MAX_HMSGSIZE);
- t->hdr.type = type;
- t->hdr.len = 0;
- t->hdr.pid = getpid();
-}
+struct hmsg_header {
+ enum hmsg_type type;
+ size_t len;
+};
+/* The protocol is pretty simple. We send a single message containing the
+ * provided message type with the message length, followed by the message
+ * content. It is expected the message content to be serialized. */
int
-ctl_msg_send(int fd, struct hmsg *t)
+ctl_msg_send(int fd, enum hmsg_type type, void *t, size_t len)
{
- return write(fd, t, t->hdr.len + sizeof(struct hmsg_hdr));
+ struct iovec iov[2];
+ struct hmsg_header hdr;
+ hdr.type = type;
+ hdr.len = len;
+ iov[0].iov_base = &hdr;
+ iov[0].iov_len = sizeof(struct hmsg_header);
+ iov[1].iov_base = t;
+ iov[1].iov_len = len;
+ return writev(fd, iov, t?2:1);
}
int
-ctl_msg_recv(int fd, struct hmsg *t)
-{
- int n;
- if ((n = read(fd, t, MAX_HMSGSIZE)) == -1) {
- return -1;
- }
- if (n < sizeof(struct hmsg_hdr)) {
- LLOG_WARNX("message received too short");
- errno = 0;
- return -1;
- }
- if (n != sizeof(struct hmsg_hdr) + t->hdr.len) {
- LLOG_WARNX("message from %d seems to be truncated (or too large)",
- t->hdr.pid);
- errno = 0;
- return -1;
- }
- return 1;
-}
-
-void
-ctl_cleanup(char *name)
-{
- if (unlink(name) == -1)
- LLOG_WARN("unable to unlink %s", name);
-}
-
-/* Packing/unpacking */
-
-/* This structure is used to track memory allocation when unpacking */
-struct gc {
- TAILQ_ENTRY(gc) next;
- void *pointer;
-};
-TAILQ_HEAD(gc_l, gc);
-
-typedef struct { char c; int16_t x; } st_int16;
-typedef struct { char c; int32_t x; } st_int32;
-typedef struct { char c; time_t x; } st_timet;
-typedef struct { char c; void *x; } st_void_p;
-
-#define INT16_ALIGN (sizeof(st_int16) - sizeof(int16_t))
-#define INT32_ALIGN (sizeof(st_int32) - sizeof(int32_t))
-#define TIMET_ALIGN (sizeof(st_timet) - sizeof(time_t))
-#define VOID_P_ALIGN (sizeof(st_void_p) - sizeof(void *))
-
-struct formatdef {
- char format;
- int size;
- int alignment;
- int (*pack)(struct hmsg*, void **, void *,
- const struct formatdef *);
- int (*unpack)(struct hmsg*, void **, void *,
- const struct formatdef *, struct gc_l *);
-};
-
-/* void** is a pointer to a pointer to the end of struct hmsg*. It should be
- * updated. void* is a pointer to the entity to pack */
-
-static int
-ctl_alloc_pointer(struct gc_l *pointers, void *pointer)
-{
- struct gc *gpointer;
- if (pointers != NULL) {
- if ((gpointer = (struct gc *)calloc(1,
- sizeof(struct gc))) == NULL) {
- LLOG_WARN("unable to allocate memory for garbage collector");
- return -1;
- }
- gpointer->pointer = pointer;
- TAILQ_INSERT_TAIL(pointers, gpointer, next);
- }
- return 0;
-}
-
-static void
-ctl_free_pointers(struct gc_l *pointers, int listonly)
-{
- struct gc *pointer, *pointer_next;
- for (pointer = TAILQ_FIRST(pointers);
- pointer != NULL;
- pointer = pointer_next) {
- pointer_next = TAILQ_NEXT(pointer, next);
- TAILQ_REMOVE(pointers, pointer, next);
- if (!listonly)
- free(pointer->pointer);
- free(pointer);
- }
-}
-
-static int
-pack_copy(struct hmsg *h, void **p, void *s,
- const struct formatdef *ct)
-{
- if (h->hdr.len + ct->size > MAX_HMSGSIZE - sizeof(struct hmsg_hdr)) {
- LLOG_WARNX("message became too large");
- return -1;
- }
- memcpy(*p, s, ct->size);
- *p += ct->size;
- h->hdr.len += ct->size;
- return ct->size;
-}
-
-static int
-unpack_copy(struct hmsg *h, void **p, void *s,
- const struct formatdef *ct, struct gc_l *pointers)
-{
- memcpy(s, *p, ct->size);
- *p += ct->size;
- return ct->size;
-}
-
-static int
-pack_string(struct hmsg *h, void **p, void *s,
- const struct formatdef *ct)
-{
- int len, ss;
- if ((*(char**)s) == NULL)
- len = -1;
- else
- len = strlen(*(char**)s);
- if (h->hdr.len + len + sizeof(int) > MAX_HMSGSIZE -
- sizeof(struct hmsg_hdr)) {
- LLOG_WARNX("message became too large");
- return -1;
- }
- memcpy(*p, &len, sizeof(int));
- *p += sizeof(int);
- ss = sizeof(int);
- if (len != -1) {
- memcpy(*p, *(char **)s, len);
- *p += len;
- ss += len;
- }
- h->hdr.len += ss;
- return ss;
-}
-
-static int
-unpack_string(struct hmsg *h, void **p, void *s,
- const struct formatdef *ct, struct gc_l *pointers)
-{
- char *string;
- int len;
- memcpy(&len, *p, sizeof(int));
- *p += sizeof(int);
- if (len == -1) {
- string = NULL;
- } else {
- if ((string = (char *)calloc(1, len + 1)) == NULL) {
- LLOG_WARNX("unable to allocate new string");
- return -1;
- }
- if (ctl_alloc_pointer(pointers, string) == -1) {
- free(string);
- return -1;
- }
- memcpy(string, *p, len);
- *p += len;
- }
- memcpy(s, &string, sizeof(char *));
- return sizeof(char*);
-}
-
-static int
-pack_chars(struct hmsg *h, void **p, void *s,
- const struct formatdef *ct)
-{
- char *string;
- int string_len;
- string = *(char **)s;
- s += sizeof(char *);
- memcpy(&string_len, s, sizeof(int));
-
- if (h->hdr.len + string_len + sizeof(int) > MAX_HMSGSIZE -
- sizeof(struct hmsg_hdr)) {
- LLOG_WARNX("message became too large");
+ctl_msg_recv(int fd, enum hmsg_type *type, void **t)
+{
+ int n, flags = -1;
+ *type = NONE; *t = NULL;
+ /* First, we read the header to know the size of the message */
+ struct hmsg_header hdr;
+ if ((n = read(fd, &hdr, sizeof(struct hmsg_header))) == -1) {
+ LLOG_WARN("unable to read message header");
return -1;
}
- memcpy(*p, &string_len, sizeof(int));
- *p += sizeof(int);
- memcpy(*p, string, string_len);
- *p += string_len;
- h->hdr.len += sizeof(int) + string_len;
- return sizeof(int) + string_len;
-}
-
-static int
-unpack_chars(struct hmsg *h, void **p, void *s,
- const struct formatdef *ct, struct gc_l *pointers)
-{
- char *string;
- struct __attribute__ ((__packed__)) {
- char *string;
- int len;
- } reals;
- int len;
- memcpy(&len, *p, sizeof(int));
- *p += sizeof(int);
- if ((string = (char *)malloc(len)) == NULL) {
- LLOG_WARN("unable to allocate new string");
- return -1;
- }
- if (ctl_alloc_pointer(pointers, string) == -1) {
- free(string);
- return -1;
- }
- memcpy(string, *p, len);
- *p += len;
- reals.string = string;
- reals.len = len;
- memcpy(s, &reals, sizeof(reals));
- return sizeof(char*);
-}
-
-static int
-pack_zero(struct hmsg *h, void **p, void *s,
- const struct formatdef *ct)
-{
- if (h->hdr.len + ct->size > MAX_HMSGSIZE - sizeof(struct hmsg_hdr)) {
- LLOG_WARNX("message became too large");
+ if (n == 0)
+ /* Remote closed the connection. */
return -1;
- }
- memset(*p, 0, ct->size);
- *p += ct->size;
- h->hdr.len += ct->size;
- return ct->size;
-}
-
-static struct formatdef conv_table[] = {
- {'b', 1, 0,
- pack_copy, unpack_copy},
- {'w', 2, INT16_ALIGN,
- pack_copy, unpack_copy},
- {'l', 4, INT32_ALIGN,
- pack_copy, unpack_copy},
- {'t', sizeof(time_t), TIMET_ALIGN,
- pack_copy, unpack_copy},
- /* Null terminated string */
- {'s', sizeof(void*), VOID_P_ALIGN,
- pack_string, unpack_string},
- /* Pointer (is packed with 0) */
- {'P', sizeof(void*), VOID_P_ALIGN,
- pack_zero, unpack_copy},
- /* A list (same as pointer), should be at the beginning */
- {'L', sizeof(void*)*2, VOID_P_ALIGN,
- pack_zero, unpack_copy},
- /* Non null terminated string, followed by an int for the size */
- {'C', sizeof(void*) + sizeof(int), VOID_P_ALIGN,
- pack_chars, unpack_chars},
- {0, 0, 0, NULL, NULL}
-};
-
-/* Lists can be packed only if the "next" member is the first one of the
- * structure! No check is done for this. */
-struct fakelist_m {
- TAILQ_ENTRY(fakelist_m) next;
- void *data;
-};
-TAILQ_HEAD(fakelist_l, fakelist_m);
-
-static int ctl_msg_get_alignment(char *format)
-{
- char *f;
- int maxalign = 0, align;
- int paren = 0;
- struct formatdef *ce;
-
- /* We just want to get the maximum required alignment for the
- * structure. Instead of going recursive, we just count parentheses to
- * get the end of the structure. */
- for (f = format; *f != 0; f++) {
- if (*f == ')') {
- paren--;
- if (!paren)
- return maxalign;
- continue;
- } else if (*f == '(') {
- paren++;
- continue;
- } else {
- for (ce = conv_table;
- (ce->format != 0) && (ce->format != *f);
- ce++);
- align = ce->alignment;
- }
- if (align != 0)
- maxalign = (maxalign>align)?maxalign:align;
- }
- if (paren)
- LLOG_WARNX("unbalanced parenthesis in format '%s'",
- format);
- return maxalign;
-}
-
-/* Define a stack of align values */
-struct stack_align {
- SLIST_ENTRY(stack_align) next;
- int align;
-};
-
-static int
-ctl_msg_packunpack_structure(char *format, void *structure, unsigned int size,
- struct hmsg *h, void **p, struct gc_l *pointers, int pack)
-{
- char *f;
- struct formatdef *ce = NULL;
- unsigned int csize = 0;
- uintptr_t offset;
- struct stack_align *align, *align_next;
- int talign;
- SLIST_HEAD(, stack_align) aligns;
-
- SLIST_INIT(&aligns);
- for (f = format; *f != 0; f++) {
- /* If we have a substructure, when entering into the structure,
- * we get the alignment and push it to the stack. When exiting
- * the structure, we pop the alignment from the stack and we do
- * the padding. This means that the whole structure should be
- * enclosed into parentheses, otherwise the padding won't
- * occur. */
- ce = NULL;
- if (*f == '(') {
- /* We need to align, compute the needed alignment */
- if ((align = calloc(1,
- sizeof(struct stack_align))) == NULL) {
- LLOG_WARN("unable to allocate memory "
- "for alignment stack");
- goto packunpack_error;
- }
- talign = align->align = ctl_msg_get_alignment(f);
- SLIST_INSERT_HEAD(&aligns, align, next);
- } else if (*f == ')') {
- /* We need to pad, retrieve the needed alignment */
- align = SLIST_FIRST(&aligns);
- talign = align->align;
- align_next = SLIST_NEXT(align, next);
- SLIST_REMOVE_HEAD(&aligns, next);
- free(align);
- } else {
- for (ce = conv_table;
- (ce->format != 0) && (ce->format != *f);
- ce++);
- if (ce->format != *f) {
- LLOG_WARNX("unknown format char %c", *f);
- goto packunpack_error;
- }
- talign = ce->alignment;
- }
-
- /* Align the structure member */
- if (talign != 0) {
- offset = (uintptr_t)structure % talign;
- if (offset != 0) {
- structure += talign - offset;
- csize += talign - offset;
- }
- }
-
- if (!ce) continue;
-
- /* Check that the size is still ok */
- csize += ce->size;
- if (csize > size) {
- LLOG_WARNX("size of structure is too small for given "
- "format (%d vs %d)", size, csize);
- goto packunpack_error;
- }
-
- /* Pack or unpack */
- if (pack) {
- if (ce->pack(h, p, structure, ce) == -1) {
- LLOG_WARNX("error while packing %c in %s", *f,
- format);
- goto packunpack_error;
- }
- } else {
- if (ce->unpack(h, p, structure, ce, pointers) == -1) {
- LLOG_WARNX("error while unpacking %c", *f);
- goto packunpack_error;
- }
+ if (n < sizeof(struct hmsg_header)) {
+ LLOG_WARNX("message received too short (%d)", n);
+ goto recv_error;
+ }
+ if (hdr.len > (1<<15)) {
+ LLOG_WARNX("message received is too large");
+ goto recv_error;
+ }
+ if (hdr.len == 0) {
+ /* No answer */
+ *type = hdr.type;
+ return 0;
+ }
+ /* Now, we read the remaining message. We need to use non-blocking stuff
+ * just in case the message was truncated. */
+ if ((*t = malloc(hdr.len)) == NULL) {
+ LLOG_WARNX("not enough space available for incoming message");
+ goto recv_error;
+ }
+ if ((flags = fcntl(fd, F_GETFL, 0)) == -1 ||
+ fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
+ LLOG_WARN("unable to set socket access mode to non blocking");
+ goto recv_error;
+ }
+ if ((n = read(fd, *t, hdr.len)) == -1) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ LLOG_WARNX("message seems truncated");
+ goto recv_error;
}
- structure += ce->size;
- }
-
- if (size < csize) {
- LLOG_WARNX("size of structure does not match its "
- "declaration (%d vs %d)", size, csize);
- goto packunpack_error;
- }
- if (!SLIST_EMPTY(&aligns)) {
- LLOG_WARNX("format is badly balanced ('%s')", format);
- goto packunpack_error;
- }
- return 0;
-
-packunpack_error:
- for (align = SLIST_FIRST(&aligns);
- align != NULL;
- align = align_next) {
- align_next = SLIST_NEXT(align, next);
- SLIST_REMOVE_HEAD(&aligns, next);
- free(align);
- }
+ LLOG_WARN("unable to read incoming request");
+ goto recv_error;
+ }
+ if (n != hdr.len) {
+ LLOG_WARNX("received message is too short (%d < %ld)",
+ n, hdr.len);
+ goto recv_error;
+ }
+ fcntl(fd, F_SETFL, flags); /* No error check */
+ *type = hdr.type;
+ return hdr.len;
+recv_error:
+ free(*t); *t = NULL;
+ if (flags != -1) fcntl(fd, F_SETFL, flags);
return -1;
-
-}
-
-int
-ctl_msg_pack_structure(char *format, void *structure, unsigned int size,
- struct hmsg *h, void **p)
-{
- return ctl_msg_packunpack_structure(format, structure, size, h, p, NULL, 1);
}
int
-ctl_msg_unpack_structure(char *format, void *structure, unsigned int size,
- struct hmsg *h, void **p)
-{
- struct gc_l pointers;
- int rc;
- TAILQ_INIT(&pointers);
- if ((rc = ctl_msg_packunpack_structure(format, structure, size,
- h, p, &pointers, 0)) == -1) {
- LLOG_WARNX("unable to unpack structure, freeing");
- ctl_free_pointers(&pointers, 0);
- return -1;
- }
- ctl_free_pointers(&pointers, 1);
- return rc;
-}
-
-int
-ctl_msg_pack_list(char *format, void *list, unsigned int size, struct hmsg *h, void **p)
-{
- struct fakelist_m *member;
- struct fakelist_l *flist = (struct fakelist_l *)list;
- TAILQ_FOREACH(member, flist, next) {
- if (ctl_msg_pack_structure(format, member, size, h, p) == -1) {
- LLOG_WARNX("error while packing list, aborting");
+ctl_msg_send_recv(int fd,
+ enum hmsg_type type,
+ void *input, struct marshal_info *input_mi,
+ void **output, struct marshal_info *output_mi)
+{
+ int n, input_len = 0;
+ void *input_buffer = NULL;
+ void *serialized = NULL;
+ enum hmsg_type received_type;
+
+ /* Serialize */
+ if (input) {
+ input_len = marshal_serialize_(input_mi, input, &input_buffer, 0, NULL, 0);
+ if (input_len <= 0) {
+ LLOG_WARNX("unable to serialize input data");
return -1;
}
}
+ /* Send request */
+ if (ctl_msg_send(fd, type, input_buffer, input_len) == -1) {
+ LLOG_WARN("unable to send request");
+ goto send_recv_error;
+ }
+ free(input_buffer); input_buffer = NULL;
+ /* Receive answer */
+ if ((n = ctl_msg_recv(fd, &received_type, &serialized)) == -1)
+ goto send_recv_error;
+ /* Check type */
+ if (received_type != type) {
+ LLOG_WARNX("incorrect received message type (expected: %d, received: %d)",
+ type, received_type);
+ goto send_recv_error;
+ }
+ /* Unserialize */
+ if (output == NULL) {
+ free(serialized);
+ return 0;
+ }
+ if (n == 0) {
+ LLOG_WARNX("no payload available in answer");
+ goto send_recv_error;
+ }
+ if (marshal_unserialize_(output_mi, serialized, n, output, NULL, 0, 0) <= 0) {
+ LLOG_WARNX("unable to deserialize received data");
+ goto send_recv_error;
+ }
+ /* All done. */
return 0;
+send_recv_error:
+ free(serialized);
+ free(input_buffer);
+ return -1;
}
-int
-ctl_msg_unpack_list(char *format, void *list, unsigned int size, struct hmsg *h, void **p)
+void
+ctl_cleanup(char *name)
{
- struct fakelist_m *member, *member_next;
- struct gc_l pointers;
- struct fakelist_l *flist = (struct fakelist_l *)list;
- TAILQ_INIT(flist);
- TAILQ_INIT(&pointers);
- while (*p - (void *)h - sizeof(struct hmsg_hdr) < h->hdr.len) {
- if ((member = calloc(1, size)) == NULL) {
- LLOG_WARN("unable to allocate memory for structure");
- return -1;
- }
- if (ctl_msg_packunpack_structure(format, member, size,
- h, p, &pointers, 0) == -1) {
- LLOG_WARNX("unable to unpack list, aborting");
- free(member);
- /* Free each list member */
- for (member = TAILQ_FIRST(flist);
- member != NULL;
- member = member_next) {
- member_next = TAILQ_NEXT(member, next);
- TAILQ_REMOVE(flist, member, next);
- free(member);
- }
- ctl_free_pointers(&pointers, 0);
- return -1;
- }
- TAILQ_INSERT_TAIL(flist, member, next);
- }
- ctl_free_pointers(&pointers, 1);
- return 0;
+ if (unlink(name) == -1)
+ LLOG_WARN("unable to unlink %s", name);
}
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include "lldpd.h"
-#include "writer.h"
+#include "lldpctl.h"
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h>
TAILQ_HEAD(interfaces, lldpd_interface);
-#ifdef ENABLE_DOT1
-TAILQ_HEAD(vlans, lldpd_vlan);
-TAILQ_HEAD(ppvids, lldpd_ppvid);
-TAILQ_HEAD(pids, lldpd_pi);
-#endif
#define ntohll(x) (((u_int64_t)(ntohl((int)((x << 32) >> 32))) << 32) | \
(unsigned int)ntohl(((int)(x >> 32))))
return buffer;
}
-
-void
-get_interfaces(int s, struct interfaces *ifs)
-{
- void *p;
- struct hmsg *h;
-
- if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
- fatal(NULL);
- ctl_msg_init(h, HMSG_GET_INTERFACES);
- if (ctl_msg_send(s, h) == -1)
- fatalx("get_interfaces: unable to send request");
- if (ctl_msg_recv(s, h) == -1)
- fatalx("get_interfaces: unable to receive answer");
- if (h->hdr.type != HMSG_GET_INTERFACES)
- fatalx("get_interfaces: unknown answer type received");
- p = &h->data;
- if (ctl_msg_unpack_list(STRUCT_LLDPD_INTERFACE,
- ifs, sizeof(struct lldpd_interface), h, &p) == -1)
- fatalx("get_interfaces: unable to retrieve the list of interfaces");
-}
-
-#ifdef ENABLE_DOT1
-static int
-get_vlans(int s, struct vlans *vls, char *interface, int nb)
-{
- void *p;
- struct hmsg *h;
-
- if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
- fatal(NULL);
- ctl_msg_init(h, HMSG_GET_VLANS);
- strlcpy((char *)&h->data, interface, IFNAMSIZ);
- memcpy((char*)&h->data + IFNAMSIZ, &nb, sizeof(int));
- h->hdr.len += IFNAMSIZ + sizeof(int);
- if (ctl_msg_send(s, h) == -1)
- fatalx("get_vlans: unable to send request");
- if (ctl_msg_recv(s, h) == -1)
- fatalx("get_vlans: unable to receive answer");
- if (h->hdr.type != HMSG_GET_VLANS)
- fatalx("get_vlans: unknown answer type received");
- p = &h->data;
- if (ctl_msg_unpack_list(STRUCT_LLDPD_VLAN,
- vls, sizeof(struct lldpd_vlan), h, &p) == -1)
- fatalx("get_vlans: unable to retrieve the list of vlans");
- return 1;
-}
-
-static int
-get_ppvids(int s, struct ppvids *pvs, char *interface, int nb)
-{
- void *p;
- struct hmsg *h;
-
- if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
- fatal(NULL);
- ctl_msg_init(h, HMSG_GET_PPVIDS);
- strlcpy((char *)&h->data, interface, IFNAMSIZ);
- memcpy((char*)&h->data + IFNAMSIZ, &nb, sizeof(int));
- h->hdr.len += IFNAMSIZ + sizeof(int);
- if (ctl_msg_send(s, h) == -1)
- fatalx("get_ppvids: unable to send request");
- if (ctl_msg_recv(s, h) == -1)
- fatalx("get_ppvids: unable to receive answer");
- if (h->hdr.type != HMSG_GET_PPVIDS)
- fatalx("get_ppvids: unknown answer type received");
- p = &h->data;
- if (ctl_msg_unpack_list(STRUCT_LLDPD_PPVID,
- pvs, sizeof(struct lldpd_ppvid), h, &p) == -1)
- fatalx("get_ppvids: unable to retrieve the list of ppvids");
- return 1;
-}
-
-static int
-get_pids(int s, struct pids *pids, char *interface, int nb)
-{
- void *p;
- struct hmsg *h;
-
- if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
- fatal(NULL);
- ctl_msg_init(h, HMSG_GET_PIDS);
- strlcpy((char *)&h->data, interface, IFNAMSIZ);
- memcpy((char*)&h->data + IFNAMSIZ, &nb, sizeof(int));
- h->hdr.len += IFNAMSIZ + sizeof(int);
- if (ctl_msg_send(s, h) == -1)
- fatalx("get_pids: unable to send request");
- if (ctl_msg_recv(s, h) == -1)
- fatalx("get_pids: unable to receive answer");
- if (h->hdr.type != HMSG_GET_PIDS)
- fatalx("get_pids: unknown answer type received");
- p = &h->data;
- if (ctl_msg_unpack_list(STRUCT_LLDPD_PI,
- pids, sizeof(struct lldpd_pi), h, &p) == -1)
- fatalx("get_pids: unable to retrieve the list of pids");
- return 1;
-}
-#endif
-
-static int
-get_chassis(int s, struct lldpd_chassis *chassis, char *interface, int nb)
-{
- struct hmsg *h;
- void *p;
-
- if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
- fatal(NULL);
- ctl_msg_init(h, HMSG_GET_CHASSIS);
- strlcpy((char *)&h->data, interface, IFNAMSIZ);
- memcpy((char*)&h->data + IFNAMSIZ, &nb, sizeof(int));
- h->hdr.len += IFNAMSIZ + sizeof(int);
- if (ctl_msg_send(s, h) == -1)
- fatalx("get_chassis: unable to send request to get chassis");
- if (ctl_msg_recv(s, h) == -1)
- fatalx("get_chassis: unable to receive answer to get chassis");
- if (h->hdr.type == HMSG_NONE)
- /* No chassis */
- return -1;
- p = &h->data;
- if (ctl_msg_unpack_structure(STRUCT_LLDPD_CHASSIS,
- chassis, sizeof(struct lldpd_chassis), h, &p) == -1) {
- LLOG_WARNX("unable to retrieve chassis for %s", interface);
- fatalx("get_chassis: abort");
- }
- return 1;
-}
-
-static int
-get_port(int s, struct lldpd_port *port, char *interface, int nb)
-{
- struct hmsg *h;
- void *p;
-
- if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
- fatal(NULL);
- ctl_msg_init(h, HMSG_GET_PORT);
- strlcpy((char *)&h->data, interface, IFNAMSIZ);
- memcpy((char*)&h->data + IFNAMSIZ, &nb, sizeof(int));
- h->hdr.len += IFNAMSIZ + sizeof(int);
- if (ctl_msg_send(s, h) == -1)
- fatalx("get_port: unable to send request to get port");
- if (ctl_msg_recv(s, h) == -1)
- fatalx("get_port: unable to receive answer to get port");
- if (h->hdr.type == HMSG_NONE)
- /* No port */
- return -1;
- p = &h->data;
- if (ctl_msg_unpack_structure(STRUCT_LLDPD_PORT,
- port, sizeof(struct lldpd_port), h, &p) == -1) {
- LLOG_WARNX("unable to retrieve port information for %s",
- interface);
- fatalx("get_chassis: abort");
- }
- return 1;
-}
-
-static int
-get_nb_port(int s, char *interface)
-{
- struct hmsg *h;
- int nb;
-
- if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
- fatal(NULL);
- ctl_msg_init(h, HMSG_GET_NB_PORTS);
- strlcpy((char *)&h->data, interface, IFNAMSIZ);
- h->hdr.len += IFNAMSIZ;
- if (ctl_msg_send(s, h) == -1)
- fatalx("get_nb_port: unable to send request to get number of ports");
- if (ctl_msg_recv(s, h) == -1)
- fatalx("get_nb_port: unable to receive answer to get number of ports");
- if (h->hdr.type == HMSG_NONE)
- return -1;
- if (h->hdr.len != sizeof(int))
- fatalx("get_nb_port: bad message length");
- memcpy(&nb, &h->data, sizeof(int));
- return nb;
-}
-
static void
display_cap(struct writer * w, struct lldpd_chassis *chassis, u_int8_t bit, char *symbol)
{
void
display_interfaces(int s, const char * fmt, int argc, char *argv[])
{
+ int i;
struct writer * w;
- int i, nb;
- struct interfaces ifs;
-#ifdef ENABLE_DOT1
- struct vlans vls;
- struct ppvids pvs;
- struct pids pids;
-#endif
- struct lldpd_interface *iff;
- struct lldpd_chassis chassis;
- struct lldpd_port port;
- char sep[80];
-
if ( strcmp(fmt,"plain") == 0 ) {
w = txt_init( stdout );
} else if (strcmp(fmt, "keyvalue") == 0) {
w = txt_init( stdout );
}
+ char sep[80];
memset(sep, '-', 79);
sep[79] = 0;
- get_interfaces(s, &ifs);
+ struct lldpd_interface *iff;
+ struct lldpd_interface_list *ifs = get_interfaces(s);
tag_start(w, "lldp", "LLDP neighbors");
- TAILQ_FOREACH(iff, &ifs, next) {
+ TAILQ_FOREACH(iff, ifs, next) {
if (optind < argc) {
for (i = optind; i < argc; i++)
if (strncmp(argv[i], iff->name, IFNAMSIZ) == 0)
if (i == argc)
continue;
}
- nb = get_nb_port(s, iff->name);
- for (i = 0; i < nb; i++) {
- if (!((get_chassis(s, &chassis, iff->name, i) != -1) &&
- (get_port(s, &port, iff->name, i) != -1)))
- continue;
+
+ struct lldpd_port *port;
+ struct lldpd_chassis *chassis;
+ struct lldpd_hardware *hardware = get_interface(s, iff->name);
+ if (TAILQ_EMPTY(&hardware->h_rports))
+ continue;
+ TAILQ_FOREACH(port, &hardware->h_rports, p_entries) {
+ if (SMART_HIDDEN(port)) continue;
+ chassis = port->p_chassis;
+
tag_start(w, "interface", "Interface");
tag_attr(w, "name", "", iff->name );
- tag_attr(w, "via" , "via", map_lookup(lldpd_protocol_map, port.p_protocol));
- tag_attr(w, "rid" , "RID", u2str(chassis.c_index));
- tag_attr(w, "age" , "Time", display_age(&port));
+ tag_attr(w, "via" , "via", map_lookup(lldpd_protocol_map, port->p_protocol));
+ tag_attr(w, "rid" , "RID", u2str(chassis->c_index));
+ tag_attr(w, "age" , "Time", display_age(port));
- display_chassis(w,&chassis);
- display_port(w, &port);
+ display_chassis(w,chassis);
+ display_port(w, port);
#ifdef ENABLE_DOT1
- if (get_vlans(s, &vls, iff->name, i) != -1)
- memcpy(&port.p_vlans, &vls, sizeof(struct vlans));
- if (!TAILQ_EMPTY(&port.p_vlans) || port.p_pvid) {
- display_vlans(w, &port);
+ if (!TAILQ_EMPTY(&port->p_vlans) || port->p_pvid) {
+ display_vlans(w, port);
}
- if (get_ppvids(s, &pvs, iff->name, i) != -1)
- memcpy(&port.p_ppvids, &pvs, sizeof(struct ppvids));
- if (!TAILQ_EMPTY(&port.p_ppvids)) {
- display_ppvids(w, &port);
+ if (!TAILQ_EMPTY(&port->p_ppvids)) {
+ display_ppvids(w, port);
}
- if (get_pids(s, &pids, iff->name, i) != -1)
- memcpy(&port.p_pids, &pids, sizeof(struct pids));
- if (!TAILQ_EMPTY(&port.p_pids)) {
- display_pids(w, &port);
+ if (!TAILQ_EMPTY(&port->p_pids)) {
+ display_pids(w, port);
}
#endif
#ifdef ENABLE_LLDPMED
- if (port.p_med_cap_enabled) {
- display_med(w, &chassis, &port);
+ if (port->p_med_cap_enabled) {
+ display_med(w, chassis, port);
}
#endif
tag_end(w); /* interface */
tag_end(w);
w->finish(w);
}
-
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include "lldpd.h"
+#include "lldpctl.h"
#include <stdio.h>
#include <unistd.h>
static void usage(void);
-TAILQ_HEAD(interfaces, lldpd_interface);
-
#ifdef HAVE___PROGNAME
extern const char *__progname;
#else
# define __progname "lldpctl"
#endif
-extern void
-get_interfaces(int s, struct interfaces *ifs);
-
-extern void
-display_interfaces(int s, const char * fmt, int argc, char *argv[]);
-
#define LLDPCTL_ARGS "hdf:L:P:O:o:"
static void
#ifdef ENABLE_LLDPMED
static int
-lldpd_parse_location(struct lldpd_port *port, const char *location)
+lldpd_parse_location(struct lldpd_med_loc *medloc, const char *location)
{
char *l, *e, *s, *data, *n;
double ll, altitude;
u_int32_t intpart, floatpart;
int type = 0, i;
+ memset(medloc, 0, sizeof(struct lldpd_med_loc));
+
if (strlen(location) == 0)
return 0;
if ((l = strdup(location)) == NULL)
switch (type) {
case LLDPMED_LOCFORMAT_COORD:
/* Coordinates */
- if ((port->p_med_location[0].data =
- (char *)malloc(16)) == NULL)
+ if ((medloc->data = (char *)malloc(16)) == NULL)
fatal(NULL);
- port->p_med_location[0].data_len = 16;
- port->p_med_location[0].format = LLDPMED_LOCFORMAT_COORD;
- data = port->p_med_location[0].data;
+ medloc->data_len = 16;
+ medloc->format = LLDPMED_LOCFORMAT_COORD;
+ data = medloc->data;
/* Latitude and longitude */
for (i = 0; i < 2; i++) {
break;
case LLDPMED_LOCFORMAT_CIVIC:
/* Civic address */
- port->p_med_location[1].data_len = 4;
+ medloc->data_len = 4;
s = e+1;
if ((s = strchr(s, ':')) == NULL)
goto invalid_location;
if ((n = strchr(s, ':')) == NULL)
n = s + strlen(s);
/* n is the end of the word */
- port->p_med_location[1].data_len += (n - s) + 2;
+ medloc->data_len += (n - s) + 2;
if ((s = strchr(s, ':')) == NULL)
break;
s = s+1;
} while (1);
s = e+1;
- if ((port->p_med_location[1].data =
- (char *)malloc(port->p_med_location[1].data_len)) ==
- NULL)
+ if ((medloc->data =
+ (char *)malloc(medloc->data_len)) == NULL)
fatal(NULL);
- port->p_med_location[1].format = LLDPMED_LOCFORMAT_CIVIC;
- data = port->p_med_location[1].data;
- *(u_int8_t *)data = port->p_med_location[1].data_len - 1;
+ medloc->format = LLDPMED_LOCFORMAT_CIVIC;
+ data = medloc->data;
+ *(u_int8_t *)data = medloc->data_len - 1;
data++;
*(u_int8_t *)data = 2; /* Client location */
data++;
break;
case LLDPMED_LOCFORMAT_ELIN:
s = e+1;
- port->p_med_location[2].data_len = strlen(s);
- if ((port->p_med_location[2].data =
- (char *)malloc(strlen(s))) == NULL)
+ medloc->data_len = strlen(s);
+ if ((medloc->data = (char *)malloc(strlen(s))) == NULL)
fatal(NULL);
- port->p_med_location[2].format = LLDPMED_LOCFORMAT_ELIN;
- strcpy(port->p_med_location[2].data, s);
+ medloc->format = LLDPMED_LOCFORMAT_ELIN;
+ strcpy(medloc->data, s);
break;
default:
type = 0;
goto invalid_location;
}
- port->p_med_cap_enabled |= LLDPMED_CAP_LOCATION;
return 0;
invalid_location:
LLOG_WARNX("the format of the location is invalid (%s)",
location);
- if (type) {
- free(port->p_med_location[type-1].data);
- memset(&port->p_med_location[type-1], 0,
- sizeof(struct lldpd_med_loc));
- }
- free(l);
return -1;
}
static int
-lldpd_parse_policy(struct lldpd_port *port, const char *policy)
+lldpd_parse_policy(struct lldpd_med_policy *medpolicy, const char *policy)
{
const char *e;
int app_type = 0;
int l2_prio = 0;
int dscp = 0;
+ memset(medpolicy, 0, sizeof(struct lldpd_med_policy));
+
if (strlen(policy) == 0) {
return 0;
}
goto invalid_policy;
}
- port->p_med_policy[app_type - 1].type = (u_int8_t) app_type;
- port->p_med_policy[app_type - 1].unknown = (u_int8_t) unknown_policy_flag;
- port->p_med_policy[app_type - 1].tagged = (u_int8_t) tagged_flag;
- port->p_med_policy[app_type - 1].vid = (u_int16_t) vlan_id;
- port->p_med_policy[app_type - 1].priority = (u_int8_t) l2_prio;
- port->p_med_policy[app_type - 1].dscp = (u_int8_t) dscp;
+ medpolicy->type = (u_int8_t) app_type;
+ medpolicy->unknown = (u_int8_t) unknown_policy_flag;
+ medpolicy->tagged = (u_int8_t) tagged_flag;
+ medpolicy->vid = (u_int16_t) vlan_id;
+ medpolicy->priority = (u_int8_t) l2_prio;
+ medpolicy->dscp = (u_int8_t) dscp;
- port->p_med_cap_enabled |= LLDPMED_CAP_POLICY;
return 0;
invalid_policy:
}
static int
-lldpd_parse_power(struct lldpd_port *port, const char *poe)
+lldpd_parse_power(struct lldpd_med_power *medpower, const char *poe)
{
const char *e;
int device_type = 0;
int priority = 0;
int val = 0;
+ memset(medpower, 0, sizeof(struct lldpd_med_power));
+
if (strlen(poe) == 0)
return 0;
e = poe;
goto invalid_poe;
}
- port->p_med_power.devicetype = device_type;
- port->p_med_power.priority = priority;
- port->p_med_power.val = val;
+ medpower->devicetype = device_type;
+ medpower->priority = priority;
+ medpower->val = val;
switch (device_type) {
case LLDPMED_POW_TYPE_PD:
switch (source) {
case 1:
- port->p_med_power.source = LLDPMED_POW_SOURCE_PSE;
+ medpower->source = LLDPMED_POW_SOURCE_PSE;
break;
case 2:
- port->p_med_power.source = LLDPMED_POW_SOURCE_LOCAL;
+ medpower->source = LLDPMED_POW_SOURCE_LOCAL;
break;
case 3:
- port->p_med_power.source = LLDPMED_POW_SOURCE_BOTH;
+ medpower->source = LLDPMED_POW_SOURCE_BOTH;
break;
default:
- port->p_med_power.source = LLDPMED_POW_SOURCE_UNKNOWN;
+ medpower->source = LLDPMED_POW_SOURCE_UNKNOWN;
break;
}
- port->p_med_cap_enabled |= LLDPMED_CAP_MDI_PD;
break;
case LLDPMED_POW_TYPE_PSE:
switch (source) {
case 1:
- port->p_med_power.source = LLDPMED_POW_SOURCE_PRIMARY;
+ medpower->source = LLDPMED_POW_SOURCE_PRIMARY;
break;
case 2:
- port->p_med_power.source = LLDPMED_POW_SOURCE_BACKUP;
+ medpower->source = LLDPMED_POW_SOURCE_BACKUP;
break;
default:
- port->p_med_power.source = LLDPMED_POW_SOURCE_UNKNOWN;
+ medpower->source = LLDPMED_POW_SOURCE_UNKNOWN;
break;
}
- port->p_med_cap_enabled |= LLDPMED_CAP_MDI_PSE;
break;
}
return 0;
#ifdef ENABLE_DOT3
static int
-lldpd_parse_dot3_power(struct lldpd_port *port, const char *poe)
+lldpd_parse_dot3_power(struct lldpd_dot3_power *dot3power, const char *poe)
{
const char *e;
- struct lldpd_dot3_power target;
+
+ memset(dot3power, 0, sizeof(struct lldpd_dot3_power));
if (strlen(poe) == 0)
return 0;
e = poe;
- memset(&target, 0, sizeof(target));
/* Device type */
if (!strncmp(e, "PD", 2))
- target.devicetype = LLDP_DOT3_POWER_PD;
+ dot3power->devicetype = LLDP_DOT3_POWER_PD;
else if (!strncmp(e, "PSE", 3))
- target.devicetype = LLDP_DOT3_POWER_PSE;
+ dot3power->devicetype = LLDP_DOT3_POWER_PSE;
else {
LLOG_WARNX("Device type should be either 'PD' or 'PSE'.");
goto invalid_dot3_poe;
LLOG_WARNX("Expected power support.");
goto invalid_dot3_poe;
}
- target.supported = atoi(++e);
- if (target.supported > 1) {
- LLOG_WARNX("Power support should be 1 or 0, not %d", target.supported);
+ dot3power->supported = atoi(++e);
+ if (dot3power->supported > 1) {
+ LLOG_WARNX("Power support should be 1 or 0, not %d", dot3power->supported);
goto invalid_dot3_poe;
}
LLOG_WARNX("Expected power ability.");
goto invalid_dot3_poe;
}
- target.enabled = atoi(++e);
- if (target.enabled > 1) {
- LLOG_WARNX("Power ability should be 1 or 0, not %d", target.enabled);
+ dot3power->enabled = atoi(++e);
+ if (dot3power->enabled > 1) {
+ LLOG_WARNX("Power ability should be 1 or 0, not %d", dot3power->enabled);
goto invalid_dot3_poe;
}
LLOG_WARNX("Expected power pair control ability.");
goto invalid_dot3_poe;
}
- target.paircontrol = atoi(++e);
- if (target.paircontrol > 1) {
+ dot3power->paircontrol = atoi(++e);
+ if (dot3power->paircontrol > 1) {
LLOG_WARNX("Power pair control ability should be 1 or 0, not %d",
- target.paircontrol);
+ dot3power->paircontrol);
goto invalid_dot3_poe;
}
LLOG_WARNX("Expected power pairs.");
goto invalid_dot3_poe;
}
- target.pairs = atoi(++e);
- if (target.pairs < 1 || target.pairs > 2) {
- LLOG_WARNX("Power pairs should be 1 or 2, not %d.", target.pairs);
+ dot3power->pairs = atoi(++e);
+ if (dot3power->pairs < 1 || dot3power->pairs > 2) {
+ LLOG_WARNX("Power pairs should be 1 or 2, not %d.", dot3power->pairs);
goto invalid_dot3_poe;
}
LLOG_WARNX("Expected power class.");
goto invalid_dot3_poe;
}
- target.class = atoi(++e);
- if (target.class > 5) {
- LLOG_WARNX("Power class out of range (%d).", target.class);
+ dot3power->class = atoi(++e);
+ if (dot3power->class > 5) {
+ LLOG_WARNX("Power class out of range (%d).", dot3power->class);
goto invalid_dot3_poe;
}
/* 802.3at */
if ((e = strchr(e, ':')) == NULL) {
- target.powertype = LLDP_DOT3_POWER_8023AT_OFF;
- goto no8023at;
+ dot3power->powertype = LLDP_DOT3_POWER_8023AT_OFF;
+ return 0;
}
/* 802.3at: Power type */
- target.powertype = atoi(++e);
- if ((target.powertype != LLDP_DOT3_POWER_8023AT_TYPE1) &&
- (target.powertype != LLDP_DOT3_POWER_8023AT_TYPE2)) {
- LLOG_WARNX("Incorrect power type (%d).", target.powertype);
+ dot3power->powertype = atoi(++e);
+ if ((dot3power->powertype != LLDP_DOT3_POWER_8023AT_TYPE1) &&
+ (dot3power->powertype != LLDP_DOT3_POWER_8023AT_TYPE2)) {
+ LLOG_WARNX("Incorrect power type (%d).", dot3power->powertype);
goto invalid_dot3_poe;
}
/* 802.3at: Source */
LLOG_WARNX("Expected power source.");
goto invalid_dot3_poe;
}
- target.source = atoi(++e);
- if (target.source > 3) {
- LLOG_WARNX("Power source out of range (%d).", target.source);
+ dot3power->source = atoi(++e);
+ if (dot3power->source > 3) {
+ LLOG_WARNX("Power source out of range (%d).", dot3power->source);
goto invalid_dot3_poe;
}
/* 802.3at: priority */
LLOG_WARNX("Expected power priority.");
goto invalid_dot3_poe;
}
- target.priority = atoi(++e);
- if (target.priority > 3) {
- LLOG_WARNX("Power priority out of range (%d).", target.priority);
+ dot3power->priority = atoi(++e);
+ if (dot3power->priority > 3) {
+ LLOG_WARNX("Power priority out of range (%d).", dot3power->priority);
goto invalid_dot3_poe;
}
/* 802.3at: requested */
LLOG_WARNX("Expected requested power value.");
goto invalid_dot3_poe;
}
- target.requested = atoi(++e);
+ dot3power->requested = atoi(++e);
/* 802.3at: allocated */
if ((e = strchr(e, ':')) == NULL) {
LLOG_WARNX("Expected allocated power value.");
goto invalid_dot3_poe;
}
- target.allocated = atoi(++e);
-
- no8023at:
- memcpy(&port->p_power, &target, sizeof(target));
+ dot3power->allocated = atoi(++e);
return 0;
invalid_dot3_poe:
}
#endif
-#ifdef ENABLE_LLDPMED
+#define ACTION_SET_LOCATION (1 << 0)
+#define ACTION_SET_POLICY (1 << 1)
+#define ACTION_SET_POWER (1 << 2)
+#define ACTION_SET_DOT3_POWER (1 << 3)
static void
-set_location(int s, int argc, char *argv[])
+set_port(int s, int argc, char *argv[], int action)
{
- int i, ch;
- struct interfaces ifs;
- struct lldpd_interface *iff;
- struct lldpd_port port;
- void *p;
- struct hmsg *h;
-
- if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
- fatal(NULL);
+ int ch;
+#ifdef ENABLE_LLDPMED
+ struct lldpd_med_loc location;
+ struct lldpd_med_power medpower;
+ struct lldpd_med_policy policy;
+#endif
+#ifdef ENABLE_DOT3
+ struct lldpd_dot3_power dot3power;
+#endif
+ int done;
+ int skip[4] = {0, 0, 0, 0};
+ int skip_[4];
- memset(&port, 0, sizeof(struct lldpd_port));
+ redo_set_port:
+ memcpy(skip_, skip, sizeof(skip));
+ done = 1;
optind = 1;
while ((ch = getopt(argc, argv, LLDPCTL_ARGS)) != -1) {
switch (ch) {
+#ifdef ENABLE_LLDPMED
case 'L':
- if ((lldpd_parse_location(&port, optarg)) == -1)
- fatalx("incorrect location");
+ if (action & ACTION_SET_LOCATION) {
+ if (skip_[0]--) break;
+ if (lldpd_parse_location(&location, optarg) == -1)
+ fatalx("set_port: incorrect location");
+ done = 0;
+ skip[0]++;
+ }
break;
- }
- }
-
- get_interfaces(s, &ifs);
- TAILQ_FOREACH(iff, &ifs, next) {
- if (optind < argc) {
- for (i = optind; i < argc; i++)
- if (strncmp(argv[i], iff->name, IFNAMSIZ) == 0)
- break;
- if (i == argc)
- continue;
- }
-
- ctl_msg_init(h, HMSG_SET_LOCATION);
- strlcpy((char *)&h->data, iff->name, IFNAMSIZ);
- h->hdr.len += IFNAMSIZ;
- p = (char*)&h->data + IFNAMSIZ;
- if (ctl_msg_pack_structure(STRUCT_LLDPD_MED_LOC
- STRUCT_LLDPD_MED_LOC STRUCT_LLDPD_MED_LOC,
- port.p_med_location,
- 3*sizeof(struct lldpd_med_loc), h, &p) == -1) {
- LLOG_WARNX("set_location: unable to set location for %s", iff->name);
- fatalx("aborting");
- }
- if (ctl_msg_send(s, h) == -1)
- fatalx("set_location: unable to send request");
- if (ctl_msg_recv(s, h) == -1)
- fatalx("set_location: unable to receive answer");
- if (h->hdr.type != HMSG_SET_LOCATION)
- fatalx("set_location: unknown answer type received");
- LLOG_INFO("Location set successfully for %s", iff->name);
- }
-}
-
-static void
-set_policy(int s, int argc, char *argv[])
-{
- int i, ch;
- struct interfaces ifs;
- struct lldpd_interface *iff;
- struct lldpd_port port;
- void *p;
- struct hmsg *h;
-
- if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
- fatal(NULL);
-
- memset(&port, 0, sizeof(struct lldpd_port));
- optind = 1;
- while ((ch = getopt(argc, argv, LLDPCTL_ARGS)) != -1) {
- switch (ch) {
case 'P':
- if ((lldpd_parse_policy(&port, optarg)) == -1)
- fatalx("Incorrect Network Policy.");
+ if (action & ACTION_SET_POLICY) {
+ if (skip_[1]--) break;
+ if (lldpd_parse_policy(&policy, optarg) == -1)
+ fatalx("set_port: incorrect network policy.");
+ done = 0;
+ skip[1]++;
+ }
break;
- }
- }
-
- get_interfaces(s, &ifs);
- TAILQ_FOREACH(iff, &ifs, next) {
- if (optind < argc) {
- for (i = optind; i < argc; i++)
- if (strncmp(argv[i], iff->name, IFNAMSIZ) == 0)
- break;
- if (i == argc)
- continue;
- }
-
- ctl_msg_init(h, HMSG_SET_POLICY);
- strlcpy((char *)&h->data, iff->name, IFNAMSIZ);
- h->hdr.len += IFNAMSIZ;
- p = (char*)&h->data + IFNAMSIZ;
- if (ctl_msg_pack_structure(
- STRUCT_LLDPD_MED_POLICY
- STRUCT_LLDPD_MED_POLICY
- STRUCT_LLDPD_MED_POLICY
- STRUCT_LLDPD_MED_POLICY
- STRUCT_LLDPD_MED_POLICY
- STRUCT_LLDPD_MED_POLICY
- STRUCT_LLDPD_MED_POLICY
- STRUCT_LLDPD_MED_POLICY,
- port.p_med_policy,
- 8*sizeof(struct lldpd_med_policy), h, &p) == -1) {
- LLOG_WARNX("set_policy: Unable to set Network Policy for %s", iff->name);
- fatalx("aborting");
- }
- if (ctl_msg_send(s, h) == -1)
- fatalx("set_policy: unable to send request");
- if (ctl_msg_recv(s, h) == -1)
- fatalx("set_policy: unable to receive answer");
- if (h->hdr.type != HMSG_SET_POLICY)
- fatalx("set_policy: unknown answer type received");
- LLOG_INFO("Network Policy successfully set for %s", iff->name);
- }
-}
-
-static void
-set_power(int s, int argc, char *argv[])
-{
- int i, ch;
- struct interfaces ifs;
- struct lldpd_interface *iff;
- struct lldpd_port port;
- void *p;
- struct hmsg *h;
-
- if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
- fatal(NULL);
-
- memset(&port, 0, sizeof(struct lldpd_port));
- optind = 1;
- while ((ch = getopt(argc, argv, LLDPCTL_ARGS)) != -1) {
- switch (ch) {
case 'O':
- if ((lldpd_parse_power(&port, optarg)) == -1)
- fatalx("Incorrect POE-MDI.");
+ if (action & ACTION_SET_POWER) {
+ if (skip_[2]--) break;
+ if (lldpd_parse_power(&medpower, optarg) == -1)
+ fatalx("set_port: incorrect MED POE-MDI.");
+ done = 0;
+ skip[2]++;
+ }
break;
- }
- }
-
- get_interfaces(s, &ifs);
- TAILQ_FOREACH(iff, &ifs, next) {
- if (optind < argc) {
- for (i = optind; i < argc; i++)
- if (strncmp(argv[i], iff->name, IFNAMSIZ) == 0)
- break;
- if (i == argc)
- continue;
- }
-
- ctl_msg_init(h, HMSG_SET_POWER);
- strlcpy((char *)&h->data, iff->name, IFNAMSIZ);
- h->hdr.len += IFNAMSIZ;
- p = (char*)&h->data + IFNAMSIZ;
- if (ctl_msg_pack_structure(STRUCT_LLDPD_MED_POWER,
- &port.p_med_power,
- sizeof(struct lldpd_med_power), h, &p) == -1) {
- LLOG_WARNX("set_power: Unable to set POE-MDI for %s", iff->name);
- fatalx("aborting");
- }
- if (ctl_msg_send(s, h) == -1)
- fatalx("set_power: unable to send request");
- if (ctl_msg_recv(s, h) == -1)
- fatalx("set_power: unable to receive answer");
- if (h->hdr.type != HMSG_SET_POWER)
- fatalx("set_power: unknown answer type received");
- LLOG_INFO("POE-MDI successfully set for %s", iff->name);
- }
-}
#endif
-
#ifdef ENABLE_DOT3
-static void
-set_dot3_power(int s, int argc, char *argv[])
-{
- int i, ch;
- struct interfaces ifs;
- struct lldpd_interface *iff;
- struct lldpd_port port;
- void *p;
- struct hmsg *h;
-
- if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
- fatal(NULL);
-
- memset(&port, 0, sizeof(struct lldpd_port));
- optind = 1;
- while ((ch = getopt(argc, argv, LLDPCTL_ARGS)) != -1) {
- switch (ch) {
case 'o':
- if ((lldpd_parse_dot3_power(&port, optarg)) == -1)
- fatalx("Incorrect POE-MDI.");
+ if (action & ACTION_SET_DOT3_POWER) {
+ if (skip_[3]--) break;
+ if (lldpd_parse_dot3_power(&dot3power, optarg) == -1)
+ fatalx("set_port: incorrect DOT3 POE-MDI.");
+ done = 0;
+ skip[3]++;
+ }
break;
+#endif
}
}
+ if (done) return;
- get_interfaces(s, &ifs);
- TAILQ_FOREACH(iff, &ifs, next) {
+ struct lldpd_interface *iff;
+ struct lldpd_interface_list *ifs = get_interfaces(s);
+ int i;
+ TAILQ_FOREACH(iff, ifs, next) {
if (optind < argc) {
for (i = optind; i < argc; i++)
if (strncmp(argv[i], iff->name, IFNAMSIZ) == 0)
continue;
}
- ctl_msg_init(h, HMSG_SET_DOT3_POWER);
- strlcpy((char *)&h->data, iff->name, IFNAMSIZ);
- h->hdr.len += IFNAMSIZ;
- p = (char*)&h->data + IFNAMSIZ;
- if (ctl_msg_pack_structure(STRUCT_LLDPD_DOT3_POWER,
- &port.p_power,
- sizeof(struct lldpd_dot3_power), h, &p) == -1) {
- LLOG_WARNX("set_dot3_power: Unable to set POE-MDI for %s", iff->name);
- fatalx("aborting");
- }
- if (ctl_msg_send(s, h) == -1)
- fatalx("set_dot3_power: unable to send request");
- if (ctl_msg_recv(s, h) == -1)
- fatalx("set_dot3_power: unable to receive answer");
- if (h->hdr.type != HMSG_SET_DOT3_POWER)
- fatalx("set_dot3_power: unknown answer type received");
- LLOG_INFO("Dot3 POE-MDI successfully set for %s", iff->name);
+ struct lldpd_port_set set;
+ memset(&set, 0, sizeof(struct lldpd_port_set));
+ set.ifname = iff->name;
+#ifdef ENABLE_LLDPMED
+ if (action & ACTION_SET_LOCATION) set.med_location = &location;
+ if (action & ACTION_SET_POLICY) set.med_policy = &policy;
+ if (action & ACTION_SET_POWER) set.med_power = &medpower;
+#endif
+#ifdef ENABLE_DOT3
+ if (action & ACTION_SET_DOT3_POWER)set.dot3_power = &dot3power;
+#endif
+ if (ctl_msg_send_recv(s, SET_PORT,
+ &set, &MARSHAL_INFO(lldpd_port_set),
+ NULL, NULL) == -1)
+ fatalx("set_port: unable to send new location information");
+ LLOG_INFO("configuration change for %s", iff->name);
}
+ goto redo_set_port;
+}
+
+struct lldpd_interface_list*
+get_interfaces(int s)
+{
+ struct lldpd_interface_list *ifs;
+ if (ctl_msg_send_recv(s, GET_INTERFACES, NULL, NULL, (void **)&ifs,
+ &MARSHAL_INFO(lldpd_interface_list)) == -1)
+ fatalx("get_interfaces: unable to get the list of interfaces");
+ return ifs;
+}
+
+struct lldpd_hardware*
+get_interface(int s, char *name)
+{
+ struct lldpd_hardware *h;
+ if (ctl_msg_send_recv(s, GET_INTERFACE,
+ name, &MARSHAL_INFO(string),
+ (void **)&h, &MARSHAL_INFO(lldpd_hardware)) == -1)
+ fatalx("get_interface: unable to get information for specified interface");
+ return h;
}
-#endif
int
main(int argc, char *argv[])
{
int ch, s, debug = 1;
char * fmt = "plain";
-#define ACTION_SET_LOCATION (1 << 0)
-#define ACTION_SET_POLICY (1 << 1)
-#define ACTION_SET_POWER (1 << 2)
-#define ACTION_SET_DOT3_POWER (1 << 3)
int action = 0;
/*
if ((s = ctl_connect(LLDPD_CTL_SOCKET)) == -1)
fatalx("unable to connect to socket " LLDPD_CTL_SOCKET);
-#ifdef ENABLE_LLDPMED
- if (action & ACTION_SET_LOCATION)
- set_location(s, argc, argv);
- if (action & ACTION_SET_POLICY)
- set_policy(s, argc, argv);
- if (action & ACTION_SET_POWER)
- set_power(s, argc, argv);
-#endif
-#ifdef ENABLE_DOT3
- if (action & ACTION_SET_DOT3_POWER)
- set_dot3_power(s, argc, argv);
-#endif
if (!action)
display_interfaces(s, fmt, argc, argv);
+ else
+ set_port(s, argc, argv, action);
close(s);
return 0;
#define _GNU_SOURCE 1
#include <stdlib.h>
+#include <stddef.h>
#include <string.h>
#include <sys/queue.h>
#ifdef HAVE_SYS_TYPES_H
u_int8_t p_cap_status;
u_int16_t p_ppvid;
};
-#define STRUCT_LLDPD_PPVID "(Lbw)"
+MARSHAL_BEGIN(lldpd_ppvid)
+MARSHAL_TQE(lldpd_ppvid, p_entries)
+MARSHAL_END;
struct lldpd_vlan {
TAILQ_ENTRY(lldpd_vlan) v_entries;
char *v_name;
u_int16_t v_vid;
};
-#define STRUCT_LLDPD_VLAN "(Lsw)"
+MARSHAL_BEGIN(lldpd_vlan)
+MARSHAL_TQE(lldpd_vlan, v_entries)
+MARSHAL_STR(lldpd_vlan, v_name)
+MARSHAL_END;
struct lldpd_pi {
TAILQ_ENTRY(lldpd_pi) p_entries;
char *p_pi;
int p_pi_len;
};
-#define STRUCT_LLDPD_PI "(LC)"
+MARSHAL_BEGIN(lldpd_pi)
+MARSHAL_TQE(lldpd_pi, p_entries)
+MARSHAL_FSTR(lldpd_pi, p_pi, p_pi_len)
+MARSHAL_END;
#endif
#ifdef ENABLE_LLDPMED
-#define STRUCT_LLDPD_MED_POLICY "(bbbwbb)"
struct lldpd_med_policy {
u_int8_t type;
u_int8_t unknown;
u_int8_t priority;
u_int8_t dscp;
};
+MARSHAL(lldpd_med_policy);
-#define STRUCT_LLDPD_MED_LOC "(bC)"
struct lldpd_med_loc {
u_int8_t format;
char *data;
int data_len;
};
+MARSHAL_BEGIN(lldpd_med_loc)
+MARSHAL_FSTR(lldpd_med_loc, data, data_len)
+MARSHAL_END;
-#define STRUCT_LLDPD_MED_POWER "(bbbw)"
struct lldpd_med_power {
u_int8_t devicetype; /* PD or PSE */
u_int8_t source;
u_int8_t priority;
u_int16_t val;
};
+MARSHAL(lldpd_med_power);
#endif
#ifdef ENABLE_DOT3
-#define STRUCT_LLDPD_DOT3_MACPHY "(bbww)"
struct lldpd_dot3_macphy {
u_int8_t autoneg_support;
u_int8_t autoneg_enabled;
u_int16_t mau_type;
};
-#define STRUCT_LLDPD_DOT3_POWER "(bbbbbbbbbww)"
struct lldpd_dot3_power {
u_int8_t devicetype;
u_int8_t supported;
u_int16_t requested;
u_int16_t allocated;
};
+MARSHAL(lldpd_dot3_power);
#endif
struct lldpd_chassis {
u_int32_t c_mgmt_if;
#ifdef ENABLE_LLDPMED
-#define STRUCT_LLDPD_CHASSIS_MED "wbsssssss"
u_int16_t c_med_cap_available;
u_int8_t c_med_type;
char *c_med_hw;
char *c_med_manuf;
char *c_med_model;
char *c_med_asset;
-#else
-#define STRUCT_LLDPD_CHASSIS_MED ""
#endif
};
-#define STRUCT_LLDPD_CHASSIS "(LwwbbCsswwwll" STRUCT_LLDPD_CHASSIS_MED ")"
+MARSHAL_BEGIN(lldpd_chassis)
+MARSHAL_TQE(lldpd_chassis, c_entries)
+MARSHAL_FSTR(lldpd_chassis, c_id, c_id_len)
+MARSHAL_STR(lldpd_chassis, c_name)
+MARSHAL_STR(lldpd_chassis, c_descr)
+#ifdef ENABLE_LLDPMED
+MARSHAL_STR(lldpd_chassis, c_med_hw)
+MARSHAL_STR(lldpd_chassis, c_med_fw)
+MARSHAL_STR(lldpd_chassis, c_med_sw)
+MARSHAL_STR(lldpd_chassis, c_med_sn)
+MARSHAL_STR(lldpd_chassis, c_med_manuf)
+MARSHAL_STR(lldpd_chassis, c_med_model)
+MARSHAL_STR(lldpd_chassis, c_med_asset)
+#endif
+MARSHAL_END;
+
struct lldpd_port {
TAILQ_ENTRY(lldpd_port) p_entries;
u_int8_t p_hidden_out:2; /* Considered as hidden for emission */
#ifdef ENABLE_DOT3
-#define STRUCT_LLDPD_PORT_DOT3 "l" STRUCT_LLDPD_DOT3_MACPHY STRUCT_LLDPD_DOT3_POWER
/* Dot3 stuff */
u_int32_t p_aggregid;
struct lldpd_dot3_macphy p_macphy;
struct lldpd_dot3_power p_power;
-#else
-#define STRUCT_LLDPD_PORT_DOT3 ""
#endif
#ifdef ENABLE_LLDPMED
-#define STRUCT_LLDPD_PORT_MED "w" \
- STRUCT_LLDPD_MED_POLICY \
- STRUCT_LLDPD_MED_POLICY \
- STRUCT_LLDPD_MED_POLICY \
- STRUCT_LLDPD_MED_POLICY \
- STRUCT_LLDPD_MED_POLICY \
- STRUCT_LLDPD_MED_POLICY \
- STRUCT_LLDPD_MED_POLICY \
- STRUCT_LLDPD_MED_POLICY \
- STRUCT_LLDPD_MED_LOC \
- STRUCT_LLDPD_MED_LOC \
- STRUCT_LLDPD_MED_LOC \
- STRUCT_LLDPD_MED_POWER
u_int16_t p_med_cap_enabled;
struct lldpd_med_policy p_med_policy[LLDPMED_APPTYPE_LAST];
struct lldpd_med_loc p_med_location[LLDPMED_LOCFORMAT_LAST];
struct lldpd_med_power p_med_power;
-#else
-#define STRUCT_LLDPD_PORT_MED ""
#endif
#ifdef ENABLE_DOT1
-#define STRUCT_LLDPD_PORT_DOT1 "wPPPPPP"
u_int16_t p_pvid;
TAILQ_HEAD(, lldpd_vlan) p_vlans;
TAILQ_HEAD(, lldpd_ppvid) p_ppvids;
TAILQ_HEAD(, lldpd_pi) p_pids;
-#else
-#define STRUCT_LLDPD_PORT_DOT1 ""
#endif
};
+MARSHAL_BEGIN(lldpd_port)
+MARSHAL_TQE(lldpd_port, p_entries)
+MARSHAL_POINTER(lldpd_port, lldpd_chassis, p_chassis)
+MARSHAL_IGNORE(lldpd_port, p_lastframe)
+MARSHAL_FSTR(lldpd_port, p_id, p_id_len)
+MARSHAL_STR(lldpd_port, p_descr)
+#ifdef ENABLE_LLDPMED
+MARSHAL_SUBSTRUCT(lldpd_port, lldpd_med_loc, p_med_location[0])
+MARSHAL_SUBSTRUCT(lldpd_port, lldpd_med_loc, p_med_location[1])
+MARSHAL_SUBSTRUCT(lldpd_port, lldpd_med_loc, p_med_location[2])
+#endif
+#ifdef ENABLE_DOT1
+MARSHAL_SUBTQ(lldpd_port, lldpd_vlan, p_vlans)
+MARSHAL_SUBTQ(lldpd_port, lldpd_ppvid, p_ppvids)
+MARSHAL_SUBTQ(lldpd_port, lldpd_pi, p_pids)
+#endif
+MARSHAL_END;
-#define STRUCT_LLDPD_PORT "(LPttPbbCswb" \
- STRUCT_LLDPD_PORT_DOT3 \
- STRUCT_LLDPD_PORT_MED \
- STRUCT_LLDPD_PORT_DOT1 ")"
+/* Used to modify some port related settings */
+struct lldpd_port_set {
+ char *ifname;
+#ifdef ENABLE_LLDPMED
+ struct lldpd_med_policy *med_policy;
+ struct lldpd_med_loc *med_location;
+ struct lldpd_med_power *med_power;
+#endif
+#ifdef ENABLE_DOT3
+ struct lldpd_dot3_power *dot3_power;
+#endif
+};
+MARSHAL_BEGIN(lldpd_port_set)
+MARSHAL_STR(lldpd_port_set, ifname)
+#ifdef ENABLE_LLDPMED
+MARSHAL_POINTER(lldpd_port_set, lldpd_med_policy, med_policy)
+MARSHAL_POINTER(lldpd_port_set, lldpd_med_loc, med_location)
+MARSHAL_POINTER(lldpd_port_set, lldpd_med_power, med_power)
+#endif
+#ifdef ENABLE_DOT3
+MARSHAL_POINTER(lldpd_port_set, lldpd_dot3_power, dot3_power)
+#endif
+MARSHAL_END;
struct lldpd_frame {
int size;
struct lldpd_port h_lport; /* Port attached to this hardware port */
TAILQ_HEAD(, lldpd_port) h_rports; /* Remote ports */
};
+MARSHAL_BEGIN(lldpd_hardware)
+MARSHAL_IGNORE(lldpd_hardware, h_entries.tqe_next)
+MARSHAL_IGNORE(lldpd_hardware, h_entries.tqe_prev)
+MARSHAL_IGNORE(lldpd_hardware, h_ops)
+MARSHAL_IGNORE(lldpd_hardware, h_data)
+MARSHAL_SUBSTRUCT(lldpd_hardware, lldpd_port, h_lport)
+MARSHAL_SUBTQ(lldpd_hardware, lldpd_port, h_rports)
+MARSHAL_END;
struct lldpd_interface {
TAILQ_ENTRY(lldpd_interface) next;
char *name;
};
-#define STRUCT_LLDPD_INTERFACE "(Ls)"
+MARSHAL_BEGIN(lldpd_interface)
+MARSHAL_TQE(lldpd_interface, next)
+MARSHAL_STR(lldpd_interface, name)
+MARSHAL_END;
+TAILQ_HEAD(lldpd_interface_list, lldpd_interface);
+MARSHAL_TQ(lldpd_interface_list, lldpd_interface);
#define PROTO_SEND_SIG struct lldpd *, struct lldpd_hardware *
#define PROTO_DECODE_SIG struct lldpd *, char *, int, struct lldpd_hardware *, struct lldpd_chassis **, struct lldpd_port **
typedef void(*lldpd_ifhandlers)(struct lldpd *, struct ifaddrs *);
enum hmsg_type {
- HMSG_NONE,
- HMSG_GET_INTERFACES,
- HMSG_GET_NB_PORTS,
- HMSG_GET_PORT,
- HMSG_GET_CHASSIS,
- HMSG_GET_VLANS,
- HMSG_GET_PPVIDS,
- HMSG_GET_PIDS,
- HMSG_SET_LOCATION,
- HMSG_SET_POLICY,
- HMSG_SET_POWER,
- HMSG_SET_DOT3_POWER,
- HMSG_SHUTDOWN
-};
-
-struct hmsg_hdr {
- enum hmsg_type type;
- int16_t len;
- pid_t pid;
+ NONE,
+ GET_INTERFACES, /* Get list of interfaces */
+ GET_INTERFACE, /* Get all information related to an interface */
+ SET_PORT, /* Set port-related information (location, power, policy) */
};
-struct hmsg {
- struct hmsg_hdr hdr;
- char data[];
-};
-
-#define HMSG_HEADER_SIZE sizeof(struct hmsg_hdr)
-#define MAX_HMSGSIZE 8192
-
/* lldpd.c */
struct lldpd_hardware *lldpd_get_hardware(struct lldpd *,
char *, int, struct lldpd_ops *);
int ctl_connect(char *);
void ctl_cleanup(char *);
void ctl_accept(struct lldpd *, struct lldpd_callback *);
-void ctl_msg_init(struct hmsg *, enum hmsg_type);
-int ctl_msg_send(int, struct hmsg *);
-int ctl_msg_recv(int, struct hmsg *);
-int ctl_msg_pack_list(char *, void *, unsigned int, struct hmsg *, void **);
-int ctl_msg_unpack_list(char *, void *, unsigned int, struct hmsg *, void **);
-int ctl_msg_pack_structure(char *, void *, unsigned int, struct hmsg *, void **);
-int ctl_msg_unpack_structure(char *, void *, unsigned int, struct hmsg *, void **);
+int ctl_msg_send(int, enum hmsg_type, void *, size_t);
+int ctl_msg_recv(int, enum hmsg_type *, void **);
+int ctl_msg_send_recv(int, enum hmsg_type,
+ void *, struct marshal_info *, void **, struct marshal_info *);
/* interfaces.c */
void lldpd_ifh_whitelist(struct lldpd *, struct ifaddrs *);
/* client.c */
struct client_handle {
enum hmsg_type type;
- void (*handle)(struct lldpd*, struct hmsg*, struct hmsg*);
+ int (*handle)(struct lldpd*, enum hmsg_type *,
+ void *, int, void **);
};
-void client_handle_client(struct lldpd *, struct lldpd_callback *,
- char *, int);
-void client_handle_none(struct lldpd *, struct hmsg *,
- struct hmsg *);
-void client_handle_get_interfaces(struct lldpd *, struct hmsg *,
- struct hmsg *);
-void client_handle_port_related(struct lldpd *, struct hmsg *,
- struct hmsg *);
-void client_handle_shutdown(struct lldpd *, struct hmsg *,
- struct hmsg *);
+int client_handle_client(struct lldpd *, struct lldpd_callback *,
+ enum hmsg_type, void *, int);
/* priv.c */
void priv_init(char*);
-TESTS = check_pack check_marshal check_lldp check_cdp check_sonmp check_edp check_ifaddrs
+TESTS = check_marshal check_lldp check_cdp check_sonmp check_edp check_ifaddrs
if HAVE_CHECK
-check_pack_SOURCES = check_pack.c \
- $(top_builddir)/src/lldpd.h
-
check_marshal_SOURCES = check_marshal.c \
- $(top_builddir)/src/lldpd.h
+ $(top_builddir)/src/marshal.h
check_lldp_SOURCES = check_lldp.c \
$(top_builddir)/src/lldpd.h \
+++ /dev/null
-#include <stdlib.h>
-#include <unistd.h>
-#include <check.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include "../src/lldpd.h"
-
-struct hmsg *h = NULL;
-
-void
-setup()
-{
- h = (struct hmsg *)calloc(1, MAX_HMSGSIZE);
- fail_unless(h != NULL);
-}
-
-void teardown()
-{
- free(h); h = NULL;
-}
-
-START_TEST (test_pack_byte)
-{
- /* Packing a single byte */
- char byte = 18;
- void *p;
- p = (char*)&h->data;
- if (ctl_msg_pack_structure("b", &byte, sizeof(char),
- h, &p) == -1) {
- fail("unable to pack");
- return;
- }
- mark_point();
- p = (char*)&h->data;
- if (ctl_msg_unpack_structure("b", &byte, sizeof(char),
- h, &p) == -1) {
- fail("unable to unpack");
- return;
- }
- ck_assert_int_eq(byte, 18);
-}
-END_TEST
-
-START_TEST (test_pack_word)
-{
- /* Packing a single word */
- u_int16_t word = 7874;
- void *p;
- p = (char*)&h->data;
- if (ctl_msg_pack_structure("w", &word, sizeof(u_int16_t),
- h, &p) == -1) {
- fail("unable to pack");
- return;
- }
- mark_point();
- p = (char*)&h->data;
- if (ctl_msg_unpack_structure("w", &word, sizeof(u_int16_t),
- h, &p) == -1) {
- fail("unable to unpack");
- return;
- }
- ck_assert_int_eq(word, 7874);
-}
-END_TEST
-
-START_TEST (test_pack_long)
-{
- /* Packing a single long */
- u_int32_t l = 14523657UL;
- void *p;
- p = (char*)&h->data;
- if (ctl_msg_pack_structure("l", &l, sizeof(u_int32_t),
- h, &p) == -1) {
- fail("unable to pack");
- return;
- }
- mark_point();
- p = (char*)&h->data;
- if (ctl_msg_unpack_structure("l", &l, sizeof(u_int32_t),
- h, &p) == -1) {
- fail("unable to unpack");
- return;
- }
- ck_assert_int_eq(l, 14523657UL);
-}
-END_TEST
-
-START_TEST (test_pack_time)
-{
- /* Packing a single time_t */
- time_t t = time(NULL);
- time_t t2;
- void *p;
- t2 = t;
- p = (char*)&h->data;
- if (ctl_msg_pack_structure("t", &t, sizeof(time_t),
- h, &p) == -1) {
- fail("unable to pack");
- return;
- }
- mark_point();
- p = (char*)&h->data;
- if (ctl_msg_unpack_structure("t", &t, sizeof(time_t),
- h, &p) == -1) {
- fail("unable to unpack");
- return;
- }
- ck_assert_int_eq(t, t2);
-}
-END_TEST
-
-START_TEST (test_pack_string)
-{
- /* Packing a single string */
- char *s = "My simple string";
- char *rs;
- void *p;
- p = (char*)&h->data;
- if (ctl_msg_pack_structure("s", &s, sizeof(char *),
- h, &p) == -1) {
- fail("unable to pack");
- return;
- }
- mark_point();
- p = (char*)&h->data;
- if (ctl_msg_unpack_structure("s", &rs, sizeof(char *),
- h, &p) == -1) {
- fail("unable to unpack");
- return;
- }
- ck_assert_str_eq(s, rs);
- ck_assert_str_eq(rs, "My simple string");
- free(rs);
-}
-END_TEST
-
-START_TEST (test_pack_null_string)
-{
- /* Packing a single empty string */
- char *s = "";
- char *rs;
- void *p;
- p = (char*)&h->data;
- if (ctl_msg_pack_structure("s", &s, sizeof(char *),
- h, &p) == -1) {
- fail("unable to pack");
- return;
- }
- mark_point();
- p = (char*)&h->data;
- if (ctl_msg_unpack_structure("s", &rs, sizeof(char *),
- h, &p) == -1) {
- fail("unable to unpack");
- return;
- }
- ck_assert_str_eq(s, rs);
- ck_assert_int_eq(strlen(rs), 0);
- free(rs);
-}
-END_TEST
-
-struct tpls {
- char *s;
- int l;
-};
-
-START_TEST (test_pack_len_string)
-{
- /* Packing a single string with its length */
- struct tpls t;
- void *p;
-
- t.s = "My string";
- t.l = strlen(t.s);
-
- p = (char*)&h->data;
- if (ctl_msg_pack_structure("C", &t, sizeof(struct tpls),
- h, &p) == -1) {
- fail("unable to pack");
- return;
- }
- mark_point();
- p = (char*)&h->data;
- if (ctl_msg_unpack_structure("C", &t, sizeof(struct tpls),
- h, &p) == -1) {
- fail("unable to unpack");
- return;
- }
- ck_assert_int_eq(t.l, strlen("My string"));
- fail_unless(memcmp(t.s, "My string", t.l) == 0);
- free(t.s);
-}
-END_TEST
-
-struct tps1 {
- u_int8_t a;
- u_int16_t b;
- u_int32_t c;
- u_int8_t d;
- void *e;
- u_int8_t f;
- time_t g;
-};
-
-START_TEST (test_pack_structures1)
-{
- /* Test padding */
- struct tps1 t;
- void *p;
- t.a = 129;
- t.b = 37814;
- t.c = 3456781258UL;
- t.d = 14;
- t.e = &t;
- t.f = 47;
- t.g = 1246799447UL;
-
- p = (char*)&h->data;
- if (ctl_msg_pack_structure("bwlbPbt", &t, sizeof(struct tps1),
- h, &p) == -1) {
- fail("unable to pack");
- return;
- }
- mark_point();
- p = (char*)&h->data;
- if (ctl_msg_unpack_structure("bwlbPbt", &t, sizeof(struct tps1),
- h, &p) == -1) {
- fail("unable to unpack");
- return;
- }
- ck_assert_int_eq(t.a, 129);
- ck_assert_int_eq(t.b, 37814);
- ck_assert_int_eq(t.c, 3456781258UL);
- ck_assert_int_eq(t.d, 14);
- ck_assert_int_eq(t.f, 47);
- ck_assert_int_eq(t.g, 1246799447UL);
-}
-END_TEST
-
-struct tps2 {
- u_int8_t a;
- void *b;
- u_int16_t c;
- void *d;
- u_int32_t e;
- void *f;
- time_t g;
- void *h;
- u_int8_t i;
-};
-
-START_TEST (test_pack_structures2)
-{
- /* More padding */
- struct tps2 t;
- void *p;
- t.a = 129;
- t.c = 37814;
- t.e = 3456781258UL;
- t.g = 1246799447;
- t.i = 12;
-
- p = (char*)&h->data;
- if (ctl_msg_pack_structure("bPwPlPtPb", &t, sizeof(struct tps2),
- h, &p) == -1) {
- fail("unable to pack");
- return;
- }
- mark_point();
- p = (char*)&h->data;
- if (ctl_msg_unpack_structure("bPwPlPtPb", &t, sizeof(struct tps2),
- h, &p) == -1) {
- fail("unable to unpack");
- return;
- }
- ck_assert_int_eq(t.a, 129);
- ck_assert_int_eq(t.c, 37814);
- ck_assert_int_eq(t.e, 3456781258UL);
- ck_assert_int_eq(t.g, 1246799447UL);
- ck_assert_int_eq(t.i, 12);
-}
-END_TEST
-
-struct tps3 {
- u_int8_t a;
- char *b;
- u_int16_t c;
- char *d;
- u_int32_t e;
- char *f;
- time_t g;
- char *h;
- u_int8_t i;
- char *j;
- int l;
- u_int8_t k;
- char *m;
-};
-
-START_TEST (test_pack_structures3)
-{
- /* More padding, with strings */
- struct tps3 t;
- void *p;
- t.a = 129;
- t.b = "First string";
- t.c = 37814;
- t.d = "Second string";
- t.e = 3456781258UL;
- t.f = "Third string";
- t.g = 1246799447UL;
- t.h = "Fourth string";
- t.i = 12;
- t.j = "Fifth string";
- t.l = strlen(t.j);
- t.k = 89;
- t.m = "Last string";
-
- p = (char*)&h->data;
- if (ctl_msg_pack_structure("bswslstsbCbs", &t, sizeof(struct tps3),
- h, &p) == -1) {
- fail("unable to pack");
- return;
- }
- mark_point();
- p = (char*)&h->data;
- if (ctl_msg_unpack_structure("bswslstsbCbs", &t, sizeof(struct tps3),
- h, &p) == -1) {
- fail("unable to unpack");
- return;
- }
- ck_assert_int_eq(t.a, 129);
- ck_assert_str_eq(t.b, "First string");
- ck_assert_int_eq(t.c, 37814);
- ck_assert_str_eq(t.d, "Second string");
- ck_assert_int_eq(t.e, 3456781258UL);
- ck_assert_str_eq(t.f, "Third string");
- ck_assert_int_eq(t.g, 1246799447UL);
- ck_assert_str_eq(t.h, "Fourth string");
- ck_assert_int_eq(t.i, 12);
- ck_assert_int_eq(t.l, strlen("Fifth string"));
- fail_unless(memcmp(t.j, "Fifth string", t.l) == 0);
- ck_assert_int_eq(t.k, 89);
- ck_assert_str_eq(t.m, "Last string");
- free(t.b); free(t.d); free(t.f); free(t.h); free(t.j); free(t.m);
-}
-END_TEST
-
-struct tps4_1 {
- u_int8_t a;
- u_int16_t b;
- u_int32_t c;
- time_t d;
- u_int8_t e;
- void *f;
- u_int8_t g;
- char *h;
- u_int8_t i;
-};
-#define TPS41 "(bwltbPbsb)"
-
-struct tps4 {
- u_int8_t a;
- struct tps4_1 b;
- u_int16_t c;
- struct tps4_1 d;
- u_int32_t e;
- struct tps4_1 f;
- void *g;
- struct tps4_1 h;
- struct tps4_1 i;
- u_int8_t j;
-};
-#define TPS4 "b" TPS41 "w" TPS41 "l" TPS41 "P" TPS41 TPS41 "b"
-
-START_TEST (test_pack_structures4)
-{
- /* More padding, with substructures */
- struct tps4 t;
- void *p;
- t.a = 129;
- t.b.a = 178;
- t.b.b = 37894;
- t.b.c = 345678914UL;
- t.b.d = 345781741UL;
- t.b.e = 74;
- t.b.g = 78;
- t.b.h = "First string";
- t.b.i = 230;
- t.c = 37814;
- t.d.a = t.b.a + 1;
- t.d.b = t.b.b + 1;
- t.d.c = t.b.c + 1;
- t.d.d = t.b.d + 1;
- t.d.e = t.b.e + 1;
- t.d.g = t.b.g + 1;
- t.d.h = "Second string";
- t.d.i = t.b.i + 1;
- t.e = 3456781258UL;
- t.f.a = t.b.a + 2;
- t.f.b = t.b.b + 2;
- t.f.c = t.b.c + 2;
- t.f.d = t.b.d + 2;
- t.f.e = t.b.e + 2;
- t.f.g = t.b.g + 2;
- t.f.h = "Third string";
- t.f.i = t.b.i + 2;
- t.h.a = t.b.a + 3;
- t.h.b = t.b.b + 3;
- t.h.c = t.b.c + 3;
- t.h.d = t.b.d + 3;
- t.h.e = t.b.e + 3;
- t.h.g = t.b.g + 3;
- t.h.h = "Fourth string";
- t.h.i = t.b.i + 3;
- t.i.a = t.b.a + 4;
- t.i.b = t.b.b + 4;
- t.i.c = t.b.c + 4;
- t.i.d = t.b.d + 4;
- t.i.e = t.b.e + 4;
- t.i.g = t.b.g + 4;
- t.i.h = "Fifth string";
- t.i.i = t.b.i + 4;
- t.j = 12;
-
- p = (char*)&h->data;
- if (ctl_msg_pack_structure(TPS4, &t, sizeof(struct tps4),
- h, &p) == -1) {
- fail("unable to pack");
- return;
- }
- mark_point();
- p = (char*)&h->data;
- if (ctl_msg_unpack_structure(TPS4, &t, sizeof(struct tps4),
- h, &p) == -1) {
- fail("unable to unpack");
- return;
- }
-
- ck_assert_int_eq(t.a, 129);
- ck_assert_int_eq(t.b.a, 178);
- ck_assert_int_eq(t.b.b, 37894);
- ck_assert_int_eq(t.b.c, 345678914UL);
- ck_assert_int_eq(t.b.d, 345781741UL);
- ck_assert_int_eq(t.b.e, 74);
- ck_assert_int_eq(t.b.g, 78);
- ck_assert_str_eq(t.b.h, "First string");
- ck_assert_int_eq(t.b.i, 230);
- ck_assert_int_eq(t.c, 37814);
- ck_assert_int_eq(t.d.a, t.b.a + 1);
- ck_assert_int_eq(t.d.b, t.b.b + 1);
- ck_assert_int_eq(t.d.c, t.b.c + 1);
- ck_assert_int_eq(t.d.d, t.b.d + 1);
- ck_assert_int_eq(t.d.e, t.b.e + 1);
- ck_assert_int_eq(t.d.g, t.b.g + 1);
- ck_assert_str_eq(t.d.h, "Second string");
- ck_assert_int_eq(t.d.i, t.b.i + 1);
- ck_assert_int_eq(t.e, 3456781258UL);
- ck_assert_int_eq(t.f.a, t.b.a + 2);
- ck_assert_int_eq(t.f.b, t.b.b + 2);
- ck_assert_int_eq(t.f.c, t.b.c + 2);
- ck_assert_int_eq(t.f.d, t.b.d + 2);
- ck_assert_int_eq(t.f.e, t.b.e + 2);
- ck_assert_int_eq(t.f.g, t.b.g + 2);
- ck_assert_str_eq(t.f.h, "Third string");
- ck_assert_int_eq(t.f.i, t.b.i + 2);
- ck_assert_int_eq(t.h.a, t.b.a + 3);
- ck_assert_int_eq(t.h.b, t.b.b + 3);
- ck_assert_int_eq(t.h.c, t.b.c + 3);
- ck_assert_int_eq(t.h.d, t.b.d + 3);
- ck_assert_int_eq(t.h.e, t.b.e + 3);
- ck_assert_int_eq(t.h.g, t.b.g + 3);
- fail_unless(strcmp(t.h.h, "Fourth string") == 0);
- ck_assert_int_eq(t.h.i, t.b.i + 3);
- ck_assert_int_eq(t.i.a, t.b.a + 4);
- ck_assert_int_eq(t.i.b, t.b.b + 4);
- ck_assert_int_eq(t.i.c, t.b.c + 4);
- ck_assert_int_eq(t.i.d, t.b.d + 4);
- ck_assert_int_eq(t.i.e, t.b.e + 4);
- ck_assert_int_eq(t.i.g, t.b.g + 4);
- ck_assert_str_eq(t.i.h, "Fifth string");
- ck_assert_int_eq(t.i.i, t.b.i + 4);
- ck_assert_int_eq(t.j, 12);
- free(t.i.h); free(t.h.h); free(t.f.h); free(t.d.h); free(t.b.h);
-}
-END_TEST
-
-struct tps51 {
- u_int8_t a;
- u_int16_t b;
- u_int32_t c;
- u_int8_t e;
- time_t f;
- u_int16_t g;
- u_int8_t h;
- u_int32_t i;
- u_int16_t j;
-};
-#define TPS51 "(bwlbtwblw)"
-
-struct tps52 {
- u_int8_t a;
- struct tps51 b;
- u_int16_t c;
- struct tps51 d;
- u_int32_t e;
- struct tps51 f;
- struct tps51 g;
- u_int8_t h;
-};
-#define TPS52 "(b" TPS51 "w" TPS51 "l" TPS51 TPS51 "b)"
-
-struct tps53 {
- u_int8_t a;
- struct tps52 b;
- u_int16_t c;
- struct tps52 d;
- u_int32_t e;
- struct tps51 f;
- struct tps52 g;
- u_int8_t h;
-};
-#define TPS53 "(b" TPS52 "w" TPS52 "l" TPS51 TPS52 "b)"
-
-struct tps5 {
- u_int8_t a;
- struct tps51 b;
- u_int16_t c;
- struct tps53 d;
- u_int32_t e;
- struct tps53 f;
- struct tps53 g;
- u_int8_t h;
-};
-#define TPS5 "(b" TPS51 "w" TPS53 "l" TPS53 TPS53 "b)"
-
-START_TEST (test_pack_structures5)
-{
- /* More padding, with recursive substructures */
- struct tps5 t;
- struct tps5 tc;
- int f, n;
- void *p;
-
- f = open("/dev/urandom", O_RDONLY);
- if (f == -1) {
- fail("unable to open /dev/urandom");
- return;
- }
- n = read(f, &t, sizeof(struct tps5));
- if (n != sizeof(struct tps5)) {
- fail("Should have read %d bytes from /dev/random but got %d",
- sizeof(struct tps5), n);
- close(f);
- return;
- }
- memcpy(&tc, &t, sizeof(struct tps5));
- close(f);
-
- p = (char*)&h->data;
- if (ctl_msg_pack_structure(TPS5, &t, sizeof(struct tps5),
- h, &p) == -1) {
- fail("unable to pack");
- return;
- }
- mark_point();
- p = (char*)&h->data;
- if (ctl_msg_unpack_structure(TPS5, &t, sizeof(struct tps5),
- h, &p) == -1) {
- fail("unable to unpack");
- return;
- }
-
- fail_unless(memcmp(&t, &tc, sizeof(struct tps5)) == 0);
-}
-END_TEST
-
-struct tpl {
- TAILQ_ENTRY(tpl) next;
- u_int16_t a;
- u_int8_t b;
- u_int32_t c;
- char *e;
- u_int8_t d;
-};
-#define TPL "(Lwblsb)"
-
-START_TEST (test_pack_empty_list)
-{
- TAILQ_HEAD(, tpl) l;
- void *p;
-
- TAILQ_INIT(&l);
- p = (char*)&h->data;
- if (ctl_msg_pack_list(TPL, &l, sizeof(struct tpl),
- h, &p) == -1) {
- fail("unable to pack");
- return;
- }
- mark_point();
- p = (char*)&h->data;
- if (ctl_msg_unpack_list(TPL, &l, sizeof(struct tpl),
- h, &p) == -1) {
- fail("unable to unpack");
- return;
- }
-
- fail_unless(TAILQ_EMPTY(&l));
-}
-END_TEST
-
-START_TEST (test_pack_list)
-{
- TAILQ_HEAD(, tpl) l;
- struct tpl tpl1, tpl2, tpl3;
- struct tpl *tpl4;
- void *p;
- int count;
-
- TAILQ_INIT(&l);
- tpl1.a = 47241;
- tpl1.b = 147;
- tpl1.c = 1474142364UL;
- tpl1.d = 198;
- tpl1.e = "First string";
- mark_point();
- TAILQ_INSERT_TAIL(&l, &tpl1, next);
- tpl2.a = tpl1.a+1;
- tpl2.b = tpl1.b+1;
- tpl2.c = tpl1.c+1;
- tpl2.d = tpl1.d+1;
- tpl2.e = "Second string";
- mark_point();
- TAILQ_INSERT_TAIL(&l, &tpl2, next);
- tpl3.a = tpl1.a+2;
- tpl3.b = tpl1.b+2;
- tpl3.c = tpl1.c+2;
- tpl3.d = tpl1.d+2;
- tpl3.e = "Last string";
- mark_point();
- TAILQ_INSERT_TAIL(&l, &tpl3, next);
-
- mark_point();
- p = (char*)&h->data;
- if (ctl_msg_pack_list(TPL, &l, sizeof(struct tpl),
- h, &p) == -1) {
- fail("unable to pack");
- return;
- }
- mark_point();
- p = (char*)&h->data;
- if (ctl_msg_unpack_list(TPL, &l, sizeof(struct tpl),
- h, &p) == -1) {
- fail("unable to unpack");
- return;
- }
-
- count = 0;
- TAILQ_FOREACH(tpl4, &l, next) {
- mark_point();
- ck_assert_int_eq(tpl4->a, tpl1.a+count);
- ck_assert_int_eq(tpl4->b, tpl1.b+count);
- ck_assert_int_eq(tpl4->c, tpl1.c+count);
- ck_assert_int_eq(tpl4->d, tpl1.d+count);
- switch (count) {
- case 0:
- ck_assert_str_eq(tpl4->e, "First string");
- break;
- case 1:
- ck_assert_str_eq(tpl4->e, "Second string");
- break;
- case 2:
- ck_assert_str_eq(tpl4->e, "Last string");
- break;
- default:
- fail("Should not be there... List too long.");
- break;
- }
- count++;
- }
-
- ck_assert_int_eq(count, 3);
-}
-END_TEST
-
-Suite *
-pack_suite(void)
-{
- Suite *s = suite_create("Packing");
-
- /* Single objects packing/unpacking */
- TCase *tc_core = tcase_create("Single objects");
- tcase_add_checked_fixture(tc_core, setup, teardown);
- tcase_add_test(tc_core, test_pack_byte);
- tcase_add_test(tc_core, test_pack_word);
- tcase_add_test(tc_core, test_pack_long);
- tcase_add_test(tc_core, test_pack_time);
- tcase_add_test(tc_core, test_pack_string);
- tcase_add_test(tc_core, test_pack_null_string);
- tcase_add_test(tc_core, test_pack_len_string);
- suite_add_tcase(s, tc_core);
-
- /* Complex structure packing/unpacking */
- TCase *tc_structures = tcase_create("Structures");
- tcase_add_checked_fixture(tc_structures, setup, teardown);
- tcase_add_test(tc_structures, test_pack_structures1);
- tcase_add_test(tc_structures, test_pack_structures2);
- tcase_add_test(tc_structures, test_pack_structures3);
- tcase_add_test(tc_structures, test_pack_structures4);
- tcase_add_test(tc_structures, test_pack_structures5);
- suite_add_tcase(s, tc_structures);
-
- /* List packing/unpacking */
- TCase *tc_lists = tcase_create("Lists");
- tcase_add_checked_fixture(tc_lists, setup, teardown);
- tcase_add_test(tc_lists, test_pack_empty_list);
- tcase_add_test(tc_lists, test_pack_list);
- suite_add_tcase(s, tc_lists);
-
- return s;
-}
-
-int
-main()
-{
- int number_failed;
- Suite *s = pack_suite ();
- SRunner *sr = srunner_create (s);
- srunner_run_all (sr, CK_ENV);
- number_failed = srunner_ntests_failed (sr);
- srunner_free (sr);
- return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
-}