]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
Major rewrite: rewrite lldpd/lldpctl communication mechanism
authorVincent Bernat <bernat@luffy.cx>
Mon, 23 Jan 2012 21:24:00 +0000 (22:24 +0100)
committerVincent Bernat <bernat@luffy.cx>
Mon, 23 Jan 2012 21:26:30 +0000 (22:26 +0100)
The new marshalling stuff is used instead of the previous packing
mechanism. Less code. Better code.

src/Makefile.am
src/client.c
src/ctl-server.c
src/ctl.c
src/display.c
src/lldpctl.c
src/lldpd.h
tests/Makefile.am
tests/check_pack.c [deleted file]

index 6931ef63957e471b3506d7c25101af6cd5a4db25..006ac62438c61a06abbe66c810e9b093ecaf5ff2 100644 (file)
@@ -15,7 +15,7 @@ lldpd_SOURCES = main.c
 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...
index 036fa89d9ba277e2417dcdc32602dc9b16212726..b9bfca489e7ec0810c132c60c78a26e0c7ba817a 100644 (file)
 
 #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(
@@ -119,11 +47,10 @@ client_handle_get_interfaces(struct lldpd *cfg, struct hmsg *r, struct hmsg *s)
                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 */
@@ -134,227 +61,161 @@ client_handle_get_interfaces(struct lldpd *cfg, struct hmsg *r, struct hmsg *s)
                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;
 }
index 090db2586c6c7ad8db4bb0abe6eea313a47e07a2..a0d5e962673ea5e150e28075afd3cbbd88a73433 100644 (file)
 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);
        }
index 3bf38030ebe2a53ca6578d5c2f0b9959476528cc..6c644cbd0aac99ef5c0d09a8fedc7ff9bb6d0c01 100644 (file)
--- a/src/ctl.c
+++ b/src/ctl.c
@@ -17,6 +17,7 @@
 #include "lldpd.h"
 
 #include <unistd.h>
+#include <fcntl.h>
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -63,499 +64,146 @@ ctl_connect(char *name)
        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);
 }
index 97f26332dbba68321cdbbcc9651ddaad3ad36847..1c88656f203cc0df0217e22d61571923729ee555 100644 (file)
@@ -14,8 +14,7 @@
  * 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))))
@@ -348,185 +342,6 @@ dump(void *data, int size, int max, char sep)
        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)
 {
@@ -1109,19 +924,8 @@ display_age(struct lldpd_port *port)
 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) {
@@ -1136,13 +940,15 @@ display_interfaces(int s, const char * fmt, int argc, char *argv[])
                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)
@@ -1150,39 +956,38 @@ display_interfaces(int s, const char * fmt, int argc, char *argv[])
                        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 */
@@ -1192,4 +997,3 @@ display_interfaces(int s, const char * fmt, int argc, char *argv[])
        tag_end(w);
        w->finish(w);
 }
-
index f225c71695892ec38d06d56b8ac885a29f3d7f95..69ec909196cd1c661ec0341a3084510eca1d77cf 100644 (file)
@@ -14,7 +14,7 @@
  * 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
@@ -75,13 +67,15 @@ usage(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)
@@ -94,12 +88,11 @@ lldpd_parse_location(struct lldpd_port *port, const char *location)
        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++) {
@@ -179,7 +172,7 @@ lldpd_parse_location(struct lldpd_port *port, const char *location)
                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;
@@ -192,19 +185,18 @@ lldpd_parse_location(struct lldpd_port *port, const char *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++;
@@ -232,34 +224,26 @@ lldpd_parse_location(struct lldpd_port *port, const char *location)
                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;
@@ -269,6 +253,8 @@ lldpd_parse_policy(struct lldpd_port *port, const char *policy)
        int l2_prio             = 0;
        int dscp                = 0;
 
+       memset(medpolicy, 0, sizeof(struct lldpd_med_policy));
+
        if (strlen(policy) == 0) {
                return 0;
        }
@@ -342,14 +328,13 @@ lldpd_parse_policy(struct lldpd_port *port, const char *policy)
                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:
@@ -359,7 +344,7 @@ 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;
@@ -367,6 +352,8 @@ lldpd_parse_power(struct lldpd_port *port, const char *poe)
        int priority    = 0;
        int val         = 0;
 
+       memset(medpower, 0, sizeof(struct lldpd_med_power));
+
        if (strlen(poe) == 0)
                return 0;
        e = poe;
@@ -414,41 +401,39 @@ lldpd_parse_power(struct lldpd_port *port, const char *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;
@@ -461,21 +446,21 @@ lldpd_parse_power(struct lldpd_port *port, const char *poe)
 
 #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;
@@ -486,9 +471,9 @@ lldpd_parse_dot3_power(struct lldpd_port *port, const char *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;
        }
 
@@ -497,9 +482,9 @@ lldpd_parse_dot3_power(struct lldpd_port *port, const char *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;
        }
 
@@ -508,10 +493,10 @@ lldpd_parse_dot3_power(struct lldpd_port *port, const char *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;
        }
 
@@ -520,9 +505,9 @@ lldpd_parse_dot3_power(struct lldpd_port *port, const char *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;
        }
 
@@ -531,21 +516,21 @@ lldpd_parse_dot3_power(struct lldpd_port *port, const char *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 */
@@ -553,9 +538,9 @@ lldpd_parse_dot3_power(struct lldpd_port *port, const char *poe)
                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 */
@@ -563,9 +548,9 @@ lldpd_parse_dot3_power(struct lldpd_port *port, const char *poe)
                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 */
@@ -573,16 +558,13 @@ lldpd_parse_dot3_power(struct lldpd_port *port, const char *poe)
                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:
@@ -591,206 +573,80 @@ lldpd_parse_dot3_power(struct lldpd_port *port, const char *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)
@@ -799,36 +655,52 @@ set_dot3_power(int s, int argc, char *argv[])
                                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;
        
        /*
@@ -881,20 +753,10 @@ main(int argc, char *argv[])
        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;
index ad9ce7da65c301ba83cad75592a3401b63c160f9..74c14d98c45de3e1a19873ff8970c19a2e50f124 100644 (file)
@@ -23,6 +23,7 @@
 
 #define _GNU_SOURCE 1
 #include <stdlib.h>
+#include <stddef.h>
 #include <string.h>
 #include <sys/queue.h>
 #ifdef HAVE_SYS_TYPES_H
@@ -76,25 +77,32 @@ struct lldpd_ppvid {
        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;
@@ -103,25 +111,27 @@ struct lldpd_med_policy {
        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;
@@ -129,7 +139,6 @@ struct lldpd_dot3_macphy {
        u_int16_t                mau_type;
 };
 
-#define STRUCT_LLDPD_DOT3_POWER "(bbbbbbbbbww)"
 struct lldpd_dot3_power {
        u_int8_t                devicetype;
        u_int8_t                supported;
@@ -144,6 +153,7 @@ struct lldpd_dot3_power {
        u_int16_t               requested;
        u_int16_t               allocated;
 };
+MARSHAL(lldpd_dot3_power);
 #endif
 
 struct lldpd_chassis {
@@ -166,7 +176,6 @@ 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;
@@ -176,12 +185,25 @@ struct lldpd_chassis {
        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;
@@ -199,52 +221,67 @@ struct lldpd_port {
        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;
@@ -293,12 +330,25 @@ struct lldpd_hardware {
        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 **
@@ -382,35 +432,12 @@ struct lldpd {
 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 *);
@@ -463,13 +490,10 @@ int        ctl_create(char *);
 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 *);
@@ -515,19 +539,12 @@ void               agent_priv_register_domain(void);
 /* 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*);
index 41c863eb8e32df1aad66bdfd366a38bfc0e398a9..df67292b2023a1203e21d648707234fcc805730f 100644 (file)
@@ -1,12 +1,9 @@
-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 \
diff --git a/tests/check_pack.c b/tests/check_pack.c
deleted file mode 100644 (file)
index 7738524..0000000
+++ /dev/null
@@ -1,735 +0,0 @@
-#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;
-}