]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
Move LLDP-MED location/policy to port instead of chassis.
authorVincent Bernat <vbernat.ext@orange-ftgroup.com>
Tue, 23 Dec 2008 15:16:36 +0000 (16:16 +0100)
committerVincent Bernat <vbernat.ext@orange-ftgroup.com>
Tue, 23 Dec 2008 15:16:36 +0000 (16:16 +0100)
Handle setting of location in lldpctl instead of lldpd.

man/lldpctl.8
man/lldpd.8
src/agent.c
src/client.c
src/ctl.c
src/lldp.c
src/lldpctl.c
src/lldpd.c
src/lldpd.h

index 60a0bb6f6cec28c2e74333830ab91225ac6a77e9..6407d1e405772ebec7386bd78fce12a183dfdcfe 100644 (file)
 .Os
 .Sh NAME
 .Nm lldpctl
-.Nd retrieve neighbors discovered by the LLDP daemon
+.Nd control LLDP daemon
 .Sh SYNOPSIS
 .Nm
 .Op Fl d
+.Op Fl L Ar location
 .Op Ar interface ...
 .Sh DESCRIPTION
 The
@@ -30,19 +31,118 @@ program controls
 .Xr lldpd 8
 daemon.
 .Pp
-Currently,
+When no specific option is given,
 .Nm
-is only able to display the list of discovered neighbors along with
-some of their advertised capabilities.
+displays the list of discovered neighbors along with
+some of their advertised capabilities. If some interfaces are given,
+only those interfaces will be displayed.
 .Pp
 The options are as follows:
 .Bl -tag -width Ds
 .It Fl d
 Enable more debugging information.
+.It Fl L Ar location
+Enable the transmission of LLDP-MED location TLV for the given
+interfaces. This option can be repeated several times to enable the
+transmission of the location in several formats. Several formats are
+accepted:
+.Bl -tag -width "XX"
+.It Em Coordinate based location
+The format of
+.Ar location
+is
+.Ar 1:48.85667:N:2.2014:E:117.47:m:1
+The first digit is always
+.Ar 1 .
+It is followed by the latitude, a letter for the direction (
+.Ar E
+or
+.Ar W
+for East or West), the longitude and a letter for the direction (
+.Ar N
+or
+.Ar S
+). The next figure is the altitude. It can be expressed in meters (the
+next letter is then
+.Ar m
+) or in floors (the letter should be
+.Ar f
+). The last digit is the datum. It can either be
+.Ar 1
+(WGS84),
+.Ar 2
+(NAD83) or
+.Ar 3
+(NAD83/MLLW).
+.It Em Civic address
+The location can be expressed as an address. The format of the
+location is then
+.Ar 2:FR:6:Commercial Rd:3:Roseville:19:4
+The first digit is always
+.Ar 2 .
+The next two letters are the country code. Then, arguments are paired
+to form the address. The first member of the pair is a digit
+indicating the type of the second member. Here is the list of
+valid types:
+.Bl -tag -width "XXXX." -compact
+.It Sy 0
+Language
+.It Sy 1
+National subdivisions
+.It Sy 2
+County, parish, district
+.It Sy 3
+City, township
+.It Sy 4
+City division, borough, ward
+.It Sy 5
+Neighborhood, block
+.It Sy 6
+Street
+.It Sy 16
+Leading street direction
+.It Sy 17
+Trailing street suffix
+.It Sy 18
+Street suffix
+.It Sy 19
+House number
+.It Sy 20
+House number suffix
+.It Sy 21
+Landmark or vanity address
+.It Sy 22
+Additional location info
+.It Sy 23
+Name
+.It Sy 24
+Postal/ZIP code
+.It Sy 25
+Building
+.It Sy 26
+Unit
+.It Sy 27
+Floor
+.It Sy 28
+Room number
+.It Sy 29
+Place type
+.It Sy 128
+Script
+.El
+.It ECS ELIN
+This is a numerical string using for setting up emergency call. The
+format of the location is then the following:
+.Ar 3:0000000911
+where the first digit should be
+.Ar 3
+and the second argument is the ELIN number.
 .El
 .Pp
-Optionally, interfaces to display may be specified on the command
-line. By default, all interfaces are displayed.
+When setting a location for a given port, all previous locations are
+erased. To erase all location, just use the empty string. There is
+currently no way to get the location from the command line.
+.El
 .Sh FILES
 .Bl -tag -width "/var/run/lldpd.socketXX" -compact
 .It /var/run/lldpd.socket
index a1c4a53f17a4bfeb48e3914113636d95600cba89..ea31ac42e9b9473adbcbd30ef6aeee0e07d1ffd1 100644 (file)
@@ -25,7 +25,6 @@
 .Op Fl m Ar management
 .Op Fl p Ar probe time
 .Op Fl M Ar class
-.Op Fl L Ar location
 .Sh DESCRIPTION
 .Nm
 is a daemon able to receive and send
@@ -112,113 +111,6 @@ Disable LLDP-MED inventory TLV transmission.
 will still receive (and publish using SNMP if enabled) those LLDP-MED
 TLV but will not send them. Use this option if you don't want to
 transmit sensible information like serial numbers.
-.It Fl L Ar location
-Enable the transmission of LLDP-MED location TLV. This option can be
-repeated several times to enable the transmission of the location in
-several formats. Several formats are accepted:
-.Bl -tag -width "XX"
-.It Em Coordinate based location
-The format of
-.Ar location
-is
-.Ar 1:48.85667:N:2.2014:E:117.47:m:1
-The first digit is always
-.Ar 1 .
-It is followed by the latitude, a letter for the direction (
-.Ar E
-or
-.Ar W
-for East or West), the longitude and a letter for the direction (
-.Ar N
-or
-.Ar S
-). The next figure is the altitude. It can be expressed in meters (the
-next letter is then
-.Ar m
-) or in floors (the letter should be
-.Ar f
-). The last digit is the datum. It can either be
-.Ar 1
-(WGS84), 
-.Ar 2
-(NAD83) or
-.Ar 3
-(NAD83/MLLW).
-.It Em Civic address
-The location can be expressed as an address. The format of the
-location is then
-.Ar 2:FR:6:Commercial Rd:3:Roseville:19:4
-The first digit is always
-.Ar 2 .
-The next two letters are the country code. Then, arguments are paired
-to form the address. The first member of the pair is a digit
-indicating the type of the second member. Here is the list of
-valid types:
-.Bl -tag -width "XXXX." -compact
-.It Sy 0
-Language
-.It Sy 1
-National subdivisions
-.It Sy 2
-County, parish, district
-.It Sy 3
-City, township
-.It Sy 4
-City division, borough, ward
-.It Sy 5
-Neighborhood, block
-.It Sy 6
-Street
-.It Sy 16
-Leading street direction
-.It Sy 17
-Trailing street suffix
-.It Sy 18
-Street suffix
-.It Sy 19
-House number
-.It Sy 20
-House number suffix
-.It Sy 21
-Landmark or vanity address
-.It Sy 22
-Additional location info
-.It Sy 23
-Name
-.It Sy 24
-Postal/ZIP code
-.It Sy 25
-Building
-.It Sy 26
-Unit
-.It Sy 27
-Floor
-.It Sy 28
-Room number
-.It Sy 29
-Place type
-.It Sy 128
-Script
-.El
-.It ECS ELIN
-This is a numerical string using for setting up emergency call. The
-format of the location is then the following:
-.Ar 3:0000000911
-where the first digit should be
-.Ar 3
-and the second argument is the ELIN number.
-.El
-.Pp
-Locations set using this option are set for all ports. There is
-currently no way to affect different locations to different
-ports. Using this TLV, network connectivity devices usually advertise
-the location of a class III device. Since it is unlikely that all
-devices are in the same location, the location TLV should be different
-for each port. This is not possible actually.
-.Pp
-Therefore, this option is likely to be removed in the future and will
-moved into
-.Xr lldpctl 8 .
 .El
 .Sh FILES
 .Bl -tag -width "/var/run/lldpd.socketXX" -compact
index 86e425b877f34c204a032cc798ba9f9712666356..8aa703f66b4e71b35539b0dc8b9de83fb98fb8d9 100644 (file)
@@ -533,10 +533,10 @@ agent_h_remote_med(struct variable *vp, oid *name, size_t *length,
                return (u_char *)&bit;
        case LLDP_SNMP_MED_REMOTE_CAP_ENABLED:
                *var_len = 1;
-               bit = swap_bits(hardware->h_rchassis->c_med_cap_enabled);
+               bit = swap_bits(hardware->h_rport->p_med_cap_enabled);
                return (u_char *)&bit;
        case LLDP_SNMP_MED_REMOTE_POE_DEVICETYPE:
-               switch (hardware->h_rchassis->c_med_pow_devicetype) {
+               switch (hardware->h_rport->p_med_pow_devicetype) {
                case LLDPMED_POW_TYPE_PSE:
                        long_ret = 2; break;
                case LLDPMED_POW_TYPE_PD:
@@ -550,19 +550,19 @@ agent_h_remote_med(struct variable *vp, oid *name, size_t *length,
        case LLDP_SNMP_MED_REMOTE_POE_PSE_POWERVAL:
        case LLDP_SNMP_MED_REMOTE_POE_PD_POWERVAL:
                if (((vp->magic == LLDP_SNMP_MED_REMOTE_POE_PSE_POWERVAL) &&
-                       (hardware->h_rchassis->c_med_pow_devicetype ==
+                       (hardware->h_rport->p_med_pow_devicetype ==
                        LLDPMED_POW_TYPE_PSE)) ||
                    ((vp->magic == LLDP_SNMP_MED_REMOTE_POE_PD_POWERVAL) &&
-                       (hardware->h_rchassis->c_med_pow_devicetype ==
+                       (hardware->h_rport->p_med_pow_devicetype ==
                            LLDPMED_POW_TYPE_PD))) {
-                       long_ret = hardware->h_rchassis->c_med_pow_val;
+                       long_ret = hardware->h_rport->p_med_pow_val;
                        return (u_char *)&long_ret;
                }
                break;
        case LLDP_SNMP_MED_REMOTE_POE_PSE_POWERSOURCE:
-               if (hardware->h_rchassis->c_med_pow_devicetype ==
+               if (hardware->h_rport->p_med_pow_devicetype ==
                    LLDPMED_POW_TYPE_PSE) {
-                       switch (hardware->h_rchassis->c_med_pow_source) {
+                       switch (hardware->h_rport->p_med_pow_source) {
                        case LLDPMED_POW_SOURCE_PRIMARY:
                                long_ret = 2; break;
                        case LLDPMED_POW_SOURCE_BACKUP:
@@ -574,9 +574,9 @@ agent_h_remote_med(struct variable *vp, oid *name, size_t *length,
                }
                break;
        case LLDP_SNMP_MED_REMOTE_POE_PD_POWERSOURCE:
-               if (hardware->h_rchassis->c_med_pow_devicetype ==
+               if (hardware->h_rport->p_med_pow_devicetype ==
                    LLDPMED_POW_TYPE_PD) {
-                       switch (hardware->h_rchassis->c_med_pow_source) {
+                       switch (hardware->h_rport->p_med_pow_source) {
                        case LLDPMED_POW_SOURCE_PSE:
                                long_ret = 2; break;
                        case LLDPMED_POW_SOURCE_LOCAL:
@@ -592,12 +592,12 @@ agent_h_remote_med(struct variable *vp, oid *name, size_t *length,
        case LLDP_SNMP_MED_REMOTE_POE_PSE_POWERPRIORITY:
        case LLDP_SNMP_MED_REMOTE_POE_PD_POWERPRIORITY:
                if (((vp->magic == LLDP_SNMP_MED_REMOTE_POE_PSE_POWERPRIORITY) &&
-                       (hardware->h_rchassis->c_med_pow_devicetype ==
+                       (hardware->h_rport->p_med_pow_devicetype ==
                        LLDPMED_POW_TYPE_PSE)) ||
                    ((vp->magic == LLDP_SNMP_MED_REMOTE_POE_PD_POWERPRIORITY) &&
-                       (hardware->h_rchassis->c_med_pow_devicetype ==
+                       (hardware->h_rport->p_med_pow_devicetype ==
                            LLDPMED_POW_TYPE_PD))) {
-                       switch (hardware->h_rchassis->c_med_pow_priority) {
+                       switch (hardware->h_rport->p_med_pow_priority) {
                        case LLDPMED_POW_PRIO_CRITICAL:
                                long_ret = 2; break;
                        case LLDPMED_POW_PRIO_HIGH:
@@ -669,7 +669,7 @@ agent_h_remote_med_policy(struct variable *vp, oid *name, size_t *length,
        type = name[*length - 1];
        if ((type < 1) || (type > LLDPMED_APPTYPE_LAST))
                goto remotemedpolicy_failed;
-       policy = &hardware->h_rchassis->c_med_policy[type-1];
+       policy = &hardware->h_rport->p_med_policy[type-1];
        if (policy->type != type)
                goto remotemedpolicy_failed;
 
@@ -721,7 +721,7 @@ agent_h_remote_med_location(struct variable *vp, oid *name, size_t *length,
        type = name[*length - 1];
        if ((type < 1) || (type > LLDPMED_APPTYPE_LAST))
                goto remotemedlocation_failed;
-       location = &hardware->h_rchassis->c_med_location[type-1];
+       location = &hardware->h_rport->p_med_location[type-1];
        if (location->format != type)
                goto remotemedlocation_failed;
 
index a4ea111dbfad8095dd016eb7e6ac96cc0b1a4af1..30ebc36ff3a2df78e5bd476de76b2d7c1382cc3d 100644 (file)
 struct client_handle client_handles[] = {
        { HMSG_NONE, client_handle_none },
        { HMSG_GET_INTERFACES, client_handle_get_interfaces },
-       { HMSG_GET_CHASSIS, client_handle_get_port_related },
-       { HMSG_GET_PORT, client_handle_get_port_related },
+       { HMSG_GET_CHASSIS, client_handle_port_related },
+       { HMSG_GET_PORT, client_handle_port_related },
+#ifdef ENABLE_LLDPMED
+       { HMSG_SET_LOCATION, client_handle_port_related },
+#endif
 #ifdef ENABLE_DOT1
-       { HMSG_GET_VLANS, client_handle_get_port_related },
+       { HMSG_GET_VLANS, client_handle_port_related },
 #endif
        { HMSG_SHUTDOWN, client_handle_shutdown },
        { 0, NULL } };
@@ -47,7 +50,7 @@ client_handle_client(struct lldpd *cfg, struct lldpd_client *client,
                return;
        }
 
-       if ((t = (struct hmsg*)calloc(1, MAX_HMSGSIZE)) == NULL) {
+       if ((t = (struct hmsg*)malloc(MAX_HMSGSIZE)) == NULL) {
                LLOG_WARNX("unable to allocate memory to answer to %d",
                    h->hdr.pid);
                return;
@@ -126,28 +129,51 @@ client_handle_get_interfaces(struct lldpd *cfg, struct hmsg *r, struct hmsg *s)
 }
 
 void
-client_handle_get_port_related(struct lldpd *cfg, struct hmsg *r, struct hmsg *s)
+client_handle_port_related(struct lldpd *cfg, struct hmsg *r, struct hmsg *s)
 {
        char *ifname;
        struct lldpd_hardware *hardware;
        void *p;
+       int i;
 
        ifname = (char*)(&r->data);
-       if (ifname[r->hdr.len - 1] != 0) {
-               LLOG_WARNX("bad message format for get port related message");
+       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;
        }
        TAILQ_FOREACH(hardware, &cfg->g_hardware, h_entries) {
                if (strncmp(ifname, hardware->h_ifname, IFNAMSIZ) == 0) {
-                       if ((hardware->h_rport == NULL) ||
-                           (hardware->h_rchassis == NULL)) {
-                               s->hdr.len = 0;
-                               s->hdr.type = HMSG_NONE;
-                               return;
+                       if (r->hdr.type != HMSG_SET_LOCATION) {
+                               if ((hardware->h_rport == NULL) ||
+                                   (hardware->h_rchassis == NULL)) {
+                                       s->hdr.len = 0;
+                                       s->hdr.type = HMSG_NONE;
+                                       return;
+                               }
                        }
                        p = &s->data;
                        switch (r->hdr.type) {
+#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;
+#endif
 #ifdef ENABLE_DOT1
                        case HMSG_GET_VLANS:
                                if (ctl_msg_pack_list(STRUCT_LLDPD_VLAN,
index 4988b69c2c356b480607e09f508b4db7bad76b80..950b1c460ad0bf1910e755038f3a4ad2a7487d6c 100644 (file)
--- a/src/ctl.c
+++ b/src/ctl.c
@@ -86,6 +86,7 @@ ctl_accept(struct lldpd *cfg, int c)
 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();
index d47d489b61107143281d692e02109f88bfa6325d..d7a31538e0d00e1bca6dd9caae8a5ab4aad6948b 100644 (file)
@@ -265,7 +265,7 @@ lldp_send(struct lldpd *global, struct lldpd_chassis *chassis,
 #endif
 
 #ifdef ENABLE_LLDPMED
-       if (global->g_lchassis.c_med_cap_enabled) {
+       if (port->p_med_cap_enabled) {
                /* LLDP-MED cap */
                memset(&medcap, 0, sizeof(medcap));
                medcap.tlv_head.type_len = LLDP_TLV_HEAD(LLDP_TLV_ORG,
@@ -301,7 +301,7 @@ lldp_send(struct lldpd *global, struct lldpd_chassis *chassis,
                    iov[c].iov_len = len;                               \
                }
 
-               if (global->g_lchassis.c_med_cap_enabled & LLDPMED_CAP_IV) {
+               if (port->p_med_cap_enabled & LLDPMED_CAP_IV) {
                        LLDP_INVENTORY(global->g_lchassis.c_med_hw,
                            medhw, LLDP_TLV_MED_IV_HW);
                        LLDP_INVENTORY(global->g_lchassis.c_med_fw,
@@ -320,13 +320,13 @@ lldp_send(struct lldpd *global, struct lldpd_chassis *chassis,
 
                /* LLDP-MED location */
                for (i = 0; i < LLDPMED_LOCFORMAT_LAST; i++) {
-                       if (global->g_lchassis.c_med_location[i].format == i + 1) {
+                       if (port->p_med_location[i].format == i + 1) {
                                memset(&medloc[i], 0, sizeof(struct lldp_org));
                                medloc[i].tlv_head.type_len =
                                    LLDP_TLV_HEAD(LLDP_TLV_ORG,
                                        sizeof(medloc[i].tlv_org_id) +
                                        sizeof(medloc[i].tlv_org_subtype) + 1 +
-                                       global->g_lchassis.c_med_location[i].data_len);
+                                       port->p_med_location[i].data_len);
                                memcpy(medloc[i].tlv_org_id, med,
                                    sizeof(medloc[i].tlv_org_id));
                                medloc[i].tlv_org_subtype = LLDP_TLV_MED_LOCATION;
@@ -335,13 +335,13 @@ lldp_send(struct lldpd *global, struct lldpd_chassis *chassis,
                                iov[c].iov_len = sizeof(medloc[i]);
                                IOV_NEW;
                                iov[c].iov_base =
-                                   &global->g_lchassis.c_med_location[i].format;
+                                   &port->p_med_location[i].format;
                                iov[c].iov_len = 1;
                                IOV_NEW;
                                iov[c].iov_base =
-                                   global->g_lchassis.c_med_location[i].data;
+                                   port->p_med_location[i].data;
                                iov[c].iov_len =
-                                   global->g_lchassis.c_med_location[i].data_len;
+                                   port->p_med_location[i].data_len;
                        }
                }
        }
@@ -707,7 +707,7 @@ lldp_decode(struct lldpd *cfg, char *frame, int s,
                                        chassis->c_med_type =
                                            *(u_int8_t*)(frame + f);
                                        f += size - 6;
-                                       chassis->c_med_cap_enabled |=
+                                       port->p_med_cap_enabled |=
                                            LLDPMED_CAP_CAP;
                                        break;
                                case LLDP_TLV_MED_POLICY:
@@ -727,20 +727,20 @@ lldp_decode(struct lldpd *cfg, char *frame, int s,
                                                f += 4;
                                                break;
                                        }
-                                       chassis->c_med_policy[(policy >> 24) - 1].type =
+                                       port->p_med_policy[(policy >> 24) - 1].type =
                                            (policy >> 24);
-                                       chassis->c_med_policy[(policy >> 24) - 1].unknown =
+                                       port->p_med_policy[(policy >> 24) - 1].unknown =
                                            ((policy & 0x800000) != 0);
-                                       chassis->c_med_policy[(policy >> 24) - 1].tagged =
+                                       port->p_med_policy[(policy >> 24) - 1].tagged =
                                            ((policy & 0x400000) != 0);
-                                       chassis->c_med_policy[(policy >> 24) - 1].vid =
+                                       port->p_med_policy[(policy >> 24) - 1].vid =
                                            (policy & 0x001FFE00) >> 9;
-                                       chassis->c_med_policy[(policy >> 24) - 1].priority =
+                                       port->p_med_policy[(policy >> 24) - 1].priority =
                                            (policy & 0x1C0) >> 6;
-                                       chassis->c_med_policy[(policy >> 24) - 1].dscp =
+                                       port->p_med_policy[(policy >> 24) - 1].dscp =
                                            policy & 0x3F;
                                        f += size - 4;
-                                       chassis->c_med_cap_enabled |=
+                                       port->p_med_cap_enabled |=
                                            LLDPMED_CAP_POLICY;
                                        break;
                                case LLDP_TLV_MED_LOCATION:
@@ -760,7 +760,7 @@ lldp_decode(struct lldpd *cfg, char *frame, int s,
                                                f += size - 5;
                                                break;
                                        }
-                                       if ((chassis->c_med_location[loctype - 1].data =
+                                       if ((port->p_med_location[loctype - 1].data =
                                                (char*)malloc(size - 5)) == NULL) {
                                                LLOG_WARN("unable to allocate memory "
                                                    "for LLDP-MED location for "
@@ -768,14 +768,14 @@ lldp_decode(struct lldpd *cfg, char *frame, int s,
                                                    hardware->h_ifname);
                                                goto malformed;
                                        }
-                                       memcpy(chassis->c_med_location[loctype - 1].data,
+                                       memcpy(port->p_med_location[loctype - 1].data,
                                            (char*)(frame + f),
                                            size - 5);
-                                       chassis->c_med_location[loctype - 1].data_len =
+                                       port->p_med_location[loctype - 1].data_len =
                                            size - 5;
-                                       chassis->c_med_location[loctype - 1].format = loctype;
+                                       port->p_med_location[loctype - 1].format = loctype;
                                        f += size - 5;
-                                       chassis->c_med_cap_enabled |=
+                                       port->p_med_cap_enabled |=
                                            LLDPMED_CAP_LOCATION;
                                        break;
                                case LLDP_TLV_MED_MDI:
@@ -788,76 +788,76 @@ lldp_decode(struct lldpd *cfg, char *frame, int s,
                                        }
                                        switch (*(u_int8_t*)(frame + f) & 0xC0) {
                                        case 0x0:
-                                               chassis->c_med_pow_devicetype = LLDPMED_POW_TYPE_PSE;
-                                               chassis->c_med_cap_enabled |=
+                                               port->p_med_pow_devicetype = LLDPMED_POW_TYPE_PSE;
+                                               port->p_med_cap_enabled |=
                                                    LLDPMED_CAP_MDI_PSE;
                                                switch (*(u_int8_t*)(frame + f) & 0x30) {
                                                case 0x0:
-                                                       chassis->c_med_pow_source =
+                                                       port->p_med_pow_source =
                                                            LLDPMED_POW_SOURCE_UNKNOWN;
                                                        break;
                                                case 0x10:
-                                                       chassis->c_med_pow_source =
+                                                       port->p_med_pow_source =
                                                            LLDPMED_POW_SOURCE_PRIMARY;
                                                        break;
                                                case 0x20:
-                                                       chassis->c_med_pow_source =
+                                                       port->p_med_pow_source =
                                                            LLDPMED_POW_SOURCE_BACKUP;
                                                        break;
                                                default:
-                                                       chassis->c_med_pow_source =
+                                                       port->p_med_pow_source =
                                                            LLDPMED_POW_SOURCE_RESERVED;
                                                }
                                                break;
                                        case 0x40:
-                                               chassis->c_med_pow_devicetype = LLDPMED_POW_TYPE_PD;
-                                               chassis->c_med_cap_enabled |=
+                                               port->p_med_pow_devicetype = LLDPMED_POW_TYPE_PD;
+                                               port->p_med_cap_enabled |=
                                                    LLDPMED_CAP_MDI_PD;
                                                switch (*(u_int8_t*)(frame + f) & 0x30) {
                                                case 0x0:
-                                                       chassis->c_med_pow_source =
+                                                       port->p_med_pow_source =
                                                            LLDPMED_POW_SOURCE_UNKNOWN;
                                                        break;
                                                case 0x10:
-                                                       chassis->c_med_pow_source =
+                                                       port->p_med_pow_source =
                                                            LLDPMED_POW_SOURCE_PSE;
                                                        break;
                                                case 0x20:
-                                                       chassis->c_med_pow_source =
+                                                       port->p_med_pow_source =
                                                            LLDPMED_POW_SOURCE_LOCAL;
                                                        break;
                                                default:
-                                                       chassis->c_med_pow_source =
+                                                       port->p_med_pow_source =
                                                            LLDPMED_POW_SOURCE_BOTH;
                                                }
                                                break;
                                        default:
-                                               chassis->c_med_pow_devicetype =
+                                               port->p_med_pow_devicetype =
                                                    LLDPMED_POW_TYPE_RESERVED;
                                        }
                                        switch (*(u_int8_t*)(frame + f) & 0x0F) {
                                        case 0x0:
-                                               chassis->c_med_pow_priority =
+                                               port->p_med_pow_priority =
                                                    LLDPMED_POW_PRIO_UNKNOWN;
                                                break;
                                        case 0x1:
-                                               chassis->c_med_pow_priority =
+                                               port->p_med_pow_priority =
                                                    LLDPMED_POW_PRIO_CRITICAL;
                                                break;
                                        case 0x2:
-                                               chassis->c_med_pow_priority =
+                                               port->p_med_pow_priority =
                                                    LLDPMED_POW_PRIO_HIGH;
                                                break;
                                        case 0x3:
-                                               chassis->c_med_pow_priority =
+                                               port->p_med_pow_priority =
                                                    LLDPMED_POW_PRIO_LOW;
                                                break;
                                        default:
-                                               chassis->c_med_pow_priority =
+                                               port->p_med_pow_priority =
                                                    LLDPMED_POW_PRIO_UNKNOWN;
                                        }
                                        f += 1;
-                                       chassis->c_med_pow_val =
+                                       port->p_med_pow_val =
                                            ntohs(*(u_int16_t*)(frame + f));
                                        f += size - 5;
                                        break;
@@ -913,7 +913,7 @@ lldp_decode(struct lldpd *cfg, char *frame, int s,
                                                break;
                                        }
                                        f += size - 4;
-                                       chassis->c_med_cap_enabled |=
+                                       port->p_med_cap_enabled |=
                                            LLDPMED_CAP_IV;
                                        break;
                                default:
index 9fb9faa50955233a936ed71118b0732397d0056f..8eb90bbb92877c3f1714e0f2007d5ab617e32b8c 100644 (file)
@@ -133,7 +133,8 @@ usage(void)
 {
        extern const char       *__progname;
 
-       fprintf(stderr, "usage: %s [-d]\n", __progname);
+       fprintf(stderr, "usage: %s [options]\n", __progname);
+       fprintf(stderr, "see manual page lldpctl(8) for more information\n");
        exit(1);
 }
 
@@ -195,8 +196,8 @@ get_vlans(int s, struct vlans *vls, char *interface)
        if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
                fatal(NULL);
        ctl_msg_init(h, HMSG_GET_VLANS);
-       h->hdr.len += strlcpy((char *)&h->data, interface,
-           MAX_HMSGSIZE - sizeof(struct hmsg_hdr)) + 1;
+       strlcpy((char *)&h->data, interface, IFNAMSIZ);
+       h->hdr.len += IFNAMSIZ;
        if (ctl_msg_send(s, h) == -1)
                fatalx("get_vlans: unable to send request");
        if (ctl_msg_recv(s, h) == -1)
@@ -220,8 +221,8 @@ get_chassis(int s, struct lldpd_chassis *chassis, char *interface)
        if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
                fatal(NULL);
        ctl_msg_init(h, HMSG_GET_CHASSIS);
-       h->hdr.len += strlcpy((char *)&h->data, interface,
-           MAX_HMSGSIZE - sizeof(struct hmsg_hdr)) + 1;
+       strlcpy((char *)&h->data, interface, IFNAMSIZ);
+       h->hdr.len += IFNAMSIZ;
        if (ctl_msg_send(s, h) == -1)
                fatalx("get_chassis: unable to send request to get chassis");
        if (ctl_msg_recv(s, h) == -1)
@@ -247,8 +248,8 @@ get_port(int s, struct lldpd_port *port, char *interface)
        if ((h = (struct hmsg *)malloc(MAX_HMSGSIZE)) == NULL)
                fatal(NULL);
        ctl_msg_init(h, HMSG_GET_PORT);
-       h->hdr.len += strlcpy((char *)&h->data, interface,
-           MAX_HMSGSIZE - sizeof(struct hmsg_hdr)) + 1;
+       strlcpy((char *)&h->data, interface, IFNAMSIZ);
+       h->hdr.len += IFNAMSIZ;
        if (ctl_msg_send(s, h) == -1)
                fatalx("get_port: unable to send request to get port");
        if (ctl_msg_recv(s, h) == -1)
@@ -325,7 +326,7 @@ display_latitude_or_longitude(int option, u_int64_t value)
 }
 
 void
-display_med(struct lldpd_chassis *chassis)
+display_med(struct lldpd_chassis *chassis, struct lldpd_port *port)
 {
        int i;
        char *value;
@@ -362,9 +363,9 @@ display_med(struct lldpd_chassis *chassis)
                printf(" Inventory");
        printf("\n");
        for (i = 0; i < LLDPMED_APPTYPE_LAST; i++) {
-               if (i+1 == chassis->c_med_policy[i].type) {
+               if (i+1 == port->p_med_policy[i].type) {
                        printf(" LLDP-MED Network Policy for ");
-                       switch(chassis->c_med_policy[i].type) {
+                       switch(port->p_med_policy[i].type) {
                        case LLDPMED_APPTYPE_VOICE:
                                printf("Voice");
                                break;
@@ -393,55 +394,55 @@ display_med(struct lldpd_chassis *chassis)
                                printf("Reserved");
                        }
                        printf(":\n  Policy:           ");
-                       if (chassis->c_med_policy[i].unknown) {
+                       if (port->p_med_policy[i].unknown) {
                                printf("unknown, ");
                        } else {
                                printf("defined, ");
                        }
-                       if (!chassis->c_med_policy[i].tagged) {
+                       if (!port->p_med_policy[i].tagged) {
                                printf("un");
                        }
                        printf("tagged");
                        printf("\n  VLAN ID:          ");
-                       if (chassis->c_med_policy[i].vid == 0) {
+                       if (port->p_med_policy[i].vid == 0) {
                                printf("Priority Tagged");
-                       } else if (chassis->c_med_policy[i].vid == 4095) {
+                       } else if (port->p_med_policy[i].vid == 4095) {
                                printf("reserved");
                        } else {
-                               printf("%u", chassis->c_med_policy[i].vid);
+                               printf("%u", port->p_med_policy[i].vid);
                        }
                        printf("\n  Layer 2 Priority: ");
-                       printf("%u", chassis->c_med_policy[i].priority);
+                       printf("%u", port->p_med_policy[i].priority);
                        printf("\n  DSCP Value:       ");
-                       printf("%u\n", chassis->c_med_policy[i].dscp);
+                       printf("%u\n", port->p_med_policy[i].dscp);
                }
        }
        for (i = 0; i < LLDPMED_LOCFORMAT_LAST; i++) {
-               if (i+1 == chassis->c_med_location[i].format) {
+               if (i+1 == port->p_med_location[i].format) {
                        printf(" LLDP-MED Location Identification: ");
-                       switch(chassis->c_med_location[i].format) {
+                       switch(port->p_med_location[i].format) {
                        case LLDPMED_LOCFORMAT_COORD:
                                printf("\n   Coordinate-based data: ");
-                               if (chassis->c_med_location[i].data_len != 16)
+                               if (port->p_med_location[i].data_len != 16)
                                        printf("bad data length");
                                else {
                                        u_int64_t l;
 
                                        /* Latitude and longitude */
-                                       l = (ntohll(*(u_int64_t*)chassis->c_med_location[i].data) &
+                                       l = (ntohll(*(u_int64_t*)port->p_med_location[i].data) &
                                            0x03FFFFFFFF000000ULL) >> 24;
                                        display_latitude_or_longitude(0, l);
                                        printf(", ");
-                                       l = (ntohll(*(u_int64_t*)(chassis->c_med_location[i].data + 5)) &
+                                       l = (ntohll(*(u_int64_t*)(port->p_med_location[i].data + 5)) &
                                            0x03FFFFFFFF000000ULL) >> 24;
                                        display_latitude_or_longitude(1, l);
 
                                        /* Altitude */
                                        printf(", ");
-                                       l = (ntohll(*(u_int64_t*)(chassis->c_med_location[i].data + 10)) &
+                                       l = (ntohll(*(u_int64_t*)(port->p_med_location[i].data + 10)) &
                                            0x3FFFFFFF000000ULL) >> 24;
                                        display_fixed_precision(l, 22, 8, 1);
-                                       switch ((*(u_int8_t*)(chassis->c_med_location[i].data +
+                                       switch ((*(u_int8_t*)(port->p_med_location[i].data +
                                                    10)) & 0xf0) {
                                        case (1 << 4):
                                                printf(" meters"); break;
@@ -452,7 +453,7 @@ display_med(struct lldpd_chassis *chassis)
                                        }
 
                                        /* Datum */
-                                       switch (*(u_int8_t*)(chassis->c_med_location[i].data +
+                                       switch (*(u_int8_t*)(port->p_med_location[i].data +
                                                    15)) {
                                        case 1:
                                                printf(", WGS84"); break;
@@ -465,21 +466,21 @@ display_med(struct lldpd_chassis *chassis)
                                break;
                        case LLDPMED_LOCFORMAT_CIVIC:
                                printf("Civic address: ");
-                               if ((chassis->c_med_location[i].data_len < 3) ||
-                                   (chassis->c_med_location[i].data_len - 1 !=
-                                       *(u_int8_t*)chassis->c_med_location[i].data))
+                               if ((port->p_med_location[i].data_len < 3) ||
+                                   (port->p_med_location[i].data_len - 1 !=
+                                       *(u_int8_t*)port->p_med_location[i].data))
                                        printf("bad data length");
                                else {
                                        int l = 4, n, catype, calength, j = 0;
                                        printf("\n%28s: %c%c", "Country",
-                                           ((char *)chassis->c_med_location[i].data)[2],
-                                           ((char *)chassis->c_med_location[i].data)[3]);
-                                       while ((n = (chassis->
-                                                   c_med_location[i].data_len - l)) >= 2) {
-                                               catype = *(u_int8_t*)(chassis->
-                                                   c_med_location[i].data + l);
-                                               calength = *(u_int8_t*)(chassis->
-                                                   c_med_location[i].data + l + 1);
+                                           ((char *)port->p_med_location[i].data)[2],
+                                           ((char *)port->p_med_location[i].data)[3]);
+                                       while ((n = (port->
+                                                   p_med_location[i].data_len - l)) >= 2) {
+                                               catype = *(u_int8_t*)(port->
+                                                   p_med_location[i].data + l);
+                                               calength = *(u_int8_t*)(port->
+                                                   p_med_location[i].data + l + 1);
                                                if (n < 2 + calength) {
                                                        printf("bad data length");
                                                        break;
@@ -495,8 +496,8 @@ display_med(struct lldpd_chassis *chassis)
                                                        printf("unknown type %d", catype);
                                                        break;
                                                }
-                                               if ((value = strndup((char *)(chassis->
-                                                       c_med_location[i].data + l + 2),
+                                               if ((value = strndup((char *)(port->
+                                                       p_med_location[i].data + l + 2),
                                                            calength)) == NULL) {
                                                        printf("not enough memory");
                                                        break;
@@ -510,9 +511,9 @@ display_med(struct lldpd_chassis *chassis)
                                }
                                break;
                        case LLDPMED_LOCFORMAT_ELIN:
-                               if ((value = strndup((char *)(chassis->
-                                               c_med_location[i].data),
-                                           chassis->c_med_location[i].data_len)) == NULL) {
+                               if ((value = strndup((char *)(port->
+                                               p_med_location[i].data),
+                                           port->p_med_location[i].data_len)) == NULL) {
                                        printf("not enough memory");
                                        break;
                                }
@@ -521,16 +522,16 @@ display_med(struct lldpd_chassis *chassis)
                                break;
                        default:
                                printf("unknown location data format: \n   %s",
-                                   dump(chassis->c_med_location[i].data,
-                                       chassis->c_med_location[i].data_len, 20, ' '));
+                                   dump(port->p_med_location[i].data,
+                                       port->p_med_location[i].data_len, 20, ' '));
                        }
                        printf("\n");
                }
        }
-       if (chassis->c_med_pow_devicetype) {
+       if (port->p_med_pow_devicetype) {
                printf(" LLDP-MED Extended Power-over-Ethernet:\n");
                printf("  Power Type & Source: ");
-               switch (chassis->c_med_pow_devicetype) {
+               switch (port->p_med_pow_devicetype) {
                case LLDPMED_POW_TYPE_PSE:
                        printf("PSE Device");
                        break;
@@ -540,7 +541,7 @@ display_med(struct lldpd_chassis *chassis)
                default:
                        printf("reserved");
                }
-               switch (chassis->c_med_pow_source) {
+               switch (port->p_med_pow_source) {
                case LLDPMED_POW_SOURCE_UNKNOWN:
                case LLDPMED_POW_SOURCE_RESERVED:
                        printf(", unknown"); break;
@@ -559,7 +560,7 @@ display_med(struct lldpd_chassis *chassis)
                        break;
                }
                printf("\n  Power Priority:      ");
-               switch (chassis->c_med_pow_priority) {
+               switch (port->p_med_pow_priority) {
                case LLDPMED_POW_PRIO_CRITICAL:
                        printf("critical"); break;
                case LLDPMED_POW_PRIO_HIGH:
@@ -570,8 +571,8 @@ display_med(struct lldpd_chassis *chassis)
                        printf("unknown");
                }
                printf("\n  Power Value:         ");
-               if(chassis->c_med_pow_val < 1024) {
-                       printf("%u mW", chassis->c_med_pow_val * 100);
+               if(port->p_med_pow_val < 1024) {
+                       printf("%u mW", port->p_med_pow_val * 100);
                } else {
                        printf("reserved");
                }
@@ -778,11 +779,10 @@ display_vlans(struct lldpd_port *port)
 }
 #endif
 
-int
-main(int argc, char *argv[])
+void
+display_interfaces(int s, int argc, char *argv[])
 {
-       int s, i;
-       int ch, debug = 1;
+       int i;
        struct interfaces ifs;
 #ifdef ENABLE_DOT1
        struct vlans vls;
@@ -791,28 +791,11 @@ main(int argc, char *argv[])
        struct lldpd_chassis chassis;
        struct lldpd_port port;
        char sep[80];
-       
-       /*
-        * Get and parse command line options
-        */
-       while ((ch = getopt(argc, argv, "d")) != -1) {
-               switch (ch) {
-               case 'd':
-                       debug++;
-                       break;
-               default:
-                       usage();
-               }
-       }               
-       
-       log_init(debug);
+
        memset(sep, '-', 79);
        sep[79] = 0;
-       
-       if ((s = ctl_connect(LLDPD_CTL_SOCKET)) == -1)
-               fatalx("unable to connect to socket " LLDPD_CTL_SOCKET);
        get_interfaces(s, &ifs);
-
+       
        printf("%s\n", sep);
        printf("    LLDP neighbors\n");
        printf("%s\n", sep);    
@@ -840,16 +823,300 @@ main(int argc, char *argv[])
                        }
 #endif
 #ifdef ENABLE_LLDPMED
-                       if (chassis.c_med_cap_enabled) {
+                       if (port.p_med_cap_enabled) {
                                printf("\n");
-                               display_med(&chassis);
+                               display_med(&chassis, &port);
                        }
 #endif
                        printf("%s\n", sep);
                }
        }
+}
+
+#ifdef ENABLE_LLDPMED
+int
+lldpd_parse_location(struct lldpd_port *port, const char *location)
+{
+       char *l, *e, *s, *data, *n;
+       double ll, altitude;
+       u_int32_t intpart, floatpart;
+       int type = 0, i;
+
+       if (strlen(location) == 0)
+               return 0;
+       if ((l = strdup(location)) == NULL)
+               fatal(NULL);
+       s = l;
+       if ((e = index(s, ':')) == NULL)
+               goto invalid_location;
+       *e = '\0';
+       type = atoi(s);
+       switch (type) {
+       case LLDPMED_LOCFORMAT_COORD:
+               /* Coordinates */
+               if ((port->p_med_location[0].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;
+
+               /* Latitude and longitude */
+               for (i = 0; i < 2; i++) {
+                       s = e+1;
+                       if ((e = index(s, ':')) == NULL)
+                               goto invalid_location;
+                       *e = '\0';
+                       ll = atof(s);
+                       s = e + 1;
+                       if ((e = index(s, ':')) == NULL)
+                               goto invalid_location;
+                       *e = '\0';
+                       intpart = (int)ll;
+                       floatpart = (ll - intpart) * (1 << 25);
+                       if (((i == 0) && (*s == 'S')) ||
+                           ((i == 1) && (*s == 'W'))) {
+                               intpart = ~intpart;
+                               intpart += 1;
+                               floatpart = ~floatpart;
+                               floatpart += 1;
+                       } else if (((i == 0) && (*s != 'N')) ||
+                           ((i == 1) && (*s != 'E'))) 
+                               goto invalid_location;
+                       *(u_int8_t *)data = (6 << 2) |         /* Precision */
+                           ((intpart & 0x180) >> 7);          /* Int part 2 bits */
+                       data++;
+                       *(u_int8_t *)data = (((intpart & 0x7f) << 1) | /* Int part 7 bits */
+                           ((floatpart & 0x1000000) >> 24));   /* Float part 1 bit */
+                       data++;
+                       *(u_int8_t *)data = (floatpart & 0xff0000) >> 16; /* 8 bits */
+                       data++;
+                       *(u_int8_t *)data = (floatpart & 0xff00) >> 8; /* 8 bits */
+                       data++;
+                       *(u_int8_t *)data = (floatpart & 0xff); /* 8 bits */
+                       data++;
+               }
+               
+               /* Altitude */
+               s = e+1;
+               if ((e = index(s, ':')) == NULL)
+                       goto invalid_location;
+               *e = '\0';
+               altitude = atof(s);
+               s = e+1;
+               if ((e = index(s, ':')) == NULL)
+                       goto invalid_location;
+               *e = '\0';
+               if (altitude < 0) {
+                       intpart = -(int)altitude;
+                       floatpart = (-(altitude + intpart)) * (1 << 8);
+                       intpart = ~intpart; intpart += 1;
+                       floatpart = ~floatpart; floatpart += 1;
+               } else {
+                       intpart = (int)altitude;
+                       floatpart = (altitude - intpart) * (1 << 8);
+               }
+               if ((*s != 'm') && (*s != 'f'))
+                       goto invalid_location;
+               *(u_int8_t *)data = ((((*s == 'm')?1:2) << 4) |        /* Type 4 bits */
+                   0);                                                /* Precision 4 bits */
+               data++;
+               *(u_int8_t *)data = ((6 << 6) |                        /* Precision 2 bits */
+                   ((intpart & 0x3f0000) >> 16));                     /* Int 6 bits */
+               data++;
+               *(u_int8_t *)data = (intpart & 0xff00) >> 8; /* Int 8 bits */
+               data++;
+               *(u_int8_t *)data = intpart & 0xff; /* Int 8 bits */
+               data++;
+               *(u_int8_t *)data = floatpart & 0xff; /* Float 8 bits */
+               data++;
+
+               /* Datum */
+               s = e + 1;
+               if (index(s, ':') != NULL)
+                       goto invalid_location;
+               *(u_int8_t *)data = atoi(s);
+               break;
+       case LLDPMED_LOCFORMAT_CIVIC:
+               /* Civic address */
+               port->p_med_location[1].data_len = 4;
+               s = e+1;
+               if ((s = index(s, ':')) == NULL)
+                       goto invalid_location;
+               s = s+1;
+               do {
+                       if ((s = index(s, ':')) == NULL)
+                               break;
+                       s = s+1;
+                       /* s is the beginning of the word */
+                       if ((n = index(s, ':')) == NULL)
+                               n = s + strlen(s);
+                       /* n is the end of the word */
+                       port->p_med_location[1].data_len += (n - s) + 2;
+                       if ((s = index(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)
+                       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;
+               data++;
+               *(u_int8_t *)data = 2; /* Client location */
+               data++;
+               if ((e = index(s, ':')) == NULL)
+                       goto invalid_location;
+               if ((e - s) != 2)
+                       goto invalid_location;
+               memcpy(data, s, 2); /* Country code */
+               data += 2;
+               while (*e != '\0') {
+                       s=e+1;
+                       if ((e = index(s, ':')) == NULL)
+                               goto invalid_location;
+                       *e = '\0';
+                       *(u_int8_t *)data = atoi(s);
+                       data++;
+                       s=e+1;
+                       if ((e = index(s, ':')) == NULL)
+                               e = s + strlen(s);
+                       *(u_int8_t *)data = e - s;
+                       data++;
+                       memcpy(data, s, e-s);
+                       data += e-s;
+               }
+               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)
+                       fatal(NULL);
+               port->p_med_location[2].format = LLDPMED_LOCFORMAT_ELIN;
+               strcpy(port->p_med_location[2].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;
+}
+
+void
+set_location(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, "dL:")) != -1) {
+               switch (ch) {
+               case 'L':
+                       if ((lldpd_parse_location(&port, optarg)) == -1)
+                               fatalx("incorrect location");
+                       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 succesfully for %s", iff->name);
+       }
+}
+#endif
+
+int
+main(int argc, char *argv[])
+{
+       int ch, s, debug = 1;
+#define ACTION_SET_LOCATION 1
+       int action = 0;
        
-       close(s);
+       /*
+        * Get and parse command line options
+        */
+       while ((ch = getopt(argc, argv, "dL:")) != -1) {
+               switch (ch) {
+               case 'd':
+                       debug++;
+                       break;
+               case 'L':
+#ifdef ENABLE_LLDPMED
+                       action = ACTION_SET_LOCATION;
+#else
+                       fprintf(stderr, "LLDP-MED support is not built-in\n");
+                       usage();
+#endif
+                       break;
+               default:
+                       usage();
+               }
+       }               
+       
+       log_init(debug);
        
+       if ((s = ctl_connect(LLDPD_CTL_SOCKET)) == -1)
+               fatalx("unable to connect to socket " LLDPD_CTL_SOCKET);
+
+       switch (action) {
+#ifdef ENABLE_LLDPMED
+       case ACTION_SET_LOCATION:
+               set_location(s, argc, argv);
+               break;
+#endif
+       default:
+               display_interfaces(s, argc, argv);
+       }
+       
+       close(s);
        return 0;
 }
index 03d87670728e7cc60f354f8ca65bda5ccf629d71..1d2364fbb43b06af1aab1db0a050436ab686f6dc 100644 (file)
@@ -367,6 +367,11 @@ lldpd_vlan_cleanup(struct lldpd_port *port)
 void
 lldpd_port_cleanup(struct lldpd_port *port)
 {
+#ifdef ENABLE_LLDPMED
+       int i;
+       for (i=0; i < LLDPMED_LOCFORMAT_LAST; i++)
+               free(port->p_med_location[i].data);
+#endif
 #ifdef ENABLE_DOT1
        lldpd_vlan_cleanup(port);
 #endif
@@ -379,15 +384,12 @@ void
 lldpd_chassis_cleanup(struct lldpd_chassis *chassis)
 {
 #ifdef ENABLE_LLDPMED
-       int i;
        free(chassis->c_med_hw);
        free(chassis->c_med_fw);
        free(chassis->c_med_sn);
        free(chassis->c_med_manuf);
        free(chassis->c_med_model);
        free(chassis->c_med_asset);
-       for (i=0; i < LLDPMED_LOCFORMAT_LAST; i++)
-               free(chassis->c_med_location[i].data);
 #endif
        free(chassis->c_id);
        free(chassis->c_name);
@@ -545,6 +547,11 @@ lldpd_port_add(struct lldpd *cfg, struct ifaddrs *ifa)
                hardware->h_raw_real = -1;
                hardware->h_start_probe = 0;
                hardware->h_proto_macs = (u_int8_t*)calloc(cfg->g_multi+1, ETH_ALEN);
+#ifdef ENABLE_LLDPMED
+               hardware->h_lport.p_med_cap_enabled = LLDPMED_CAP_CAP;
+               if (!cfg->g_noinventory)
+                       hardware->h_lport.p_med_cap_enabled |= LLDPMED_CAP_IV;
+#endif
 #ifdef ENABLE_DOT1
                TAILQ_INIT(&hardware->h_lport.p_vlans);
        } else {
@@ -1362,188 +1369,6 @@ lldpd_loop(struct lldpd *cfg)
        lldpd_recv_all(cfg);
 }
 
-#ifdef ENABLE_LLDPMED
-void
-lldpd_parse_location(struct lldpd_chassis *chassis, const char *location)
-{
-       char *l, *e, *s, *data, *n;
-       double ll, altitude;
-       u_int32_t intpart, floatpart;
-       int type = 0, i;
-
-       if ((l = strdup(location)) == NULL)
-               fatal(NULL);
-       s = l;
-       if ((e = index(s, ':')) == NULL)
-               goto invalid_location;
-       *e = '\0';
-       type = atoi(s);
-       switch (type) {
-       case LLDPMED_LOCFORMAT_COORD:
-               /* Coordinates */
-               if ((chassis->c_med_location[0].data =
-                       (char *)malloc(16)) == NULL)
-                       fatal(NULL);
-               chassis->c_med_location[0].data_len = 16;
-               chassis->c_med_location[0].format = LLDPMED_LOCFORMAT_COORD;
-               data = chassis->c_med_location[0].data;
-
-               /* Latitude and longitude */
-               for (i = 0; i < 2; i++) {
-                       s = e+1;
-                       if ((e = index(s, ':')) == NULL)
-                               goto invalid_location;
-                       *e = '\0';
-                       ll = atof(s);
-                       s = e + 1;
-                       if ((e = index(s, ':')) == NULL)
-                               goto invalid_location;
-                       *e = '\0';
-                       intpart = (int)ll;
-                       floatpart = (ll - intpart) * (1 << 25);
-                       if (((i == 0) && (*s == 'S')) ||
-                           ((i == 1) && (*s == 'W'))) {
-                               intpart = ~intpart;
-                               intpart += 1;
-                               floatpart = ~floatpart;
-                               floatpart += 1;
-                       } else if (((i == 0) && (*s != 'N')) ||
-                           ((i == 1) && (*s != 'E'))) 
-                               goto invalid_location;
-                       *(u_int8_t *)data = (6 << 2) |         /* Precision */
-                           ((intpart & 0x180) >> 7);          /* Int part 2 bits */
-                       data++;
-                       *(u_int8_t *)data = (((intpart & 0x7f) << 1) | /* Int part 7 bits */
-                           ((floatpart & 0x1000000) >> 24));   /* Float part 1 bit */
-                       data++;
-                       *(u_int8_t *)data = (floatpart & 0xff0000) >> 16; /* 8 bits */
-                       data++;
-                       *(u_int8_t *)data = (floatpart & 0xff00) >> 8; /* 8 bits */
-                       data++;
-                       *(u_int8_t *)data = (floatpart & 0xff); /* 8 bits */
-                       data++;
-               }
-               
-               /* Altitude */
-               s = e+1;
-               if ((e = index(s, ':')) == NULL)
-                       goto invalid_location;
-               *e = '\0';
-               altitude = atof(s);
-               s = e+1;
-               if ((e = index(s, ':')) == NULL)
-                       goto invalid_location;
-               *e = '\0';
-               if (altitude < 0) {
-                       intpart = -(int)altitude;
-                       floatpart = (-(altitude + intpart)) * (1 << 8);
-                       intpart = ~intpart; intpart += 1;
-                       floatpart = ~floatpart; floatpart += 1;
-               } else {
-                       intpart = (int)altitude;
-                       floatpart = (altitude - intpart) * (1 << 8);
-               }
-               if ((*s != 'm') && (*s != 'f'))
-                       goto invalid_location;
-               *(u_int8_t *)data = ((((*s == 'm')?1:2) << 4) |        /* Type 4 bits */
-                   0);                                                /* Precision 4 bits */
-               data++;
-               *(u_int8_t *)data = ((6 << 6) |                        /* Precision 2 bits */
-                   ((intpart & 0x3f0000) >> 16));                     /* Int 6 bits */
-               data++;
-               *(u_int8_t *)data = (intpart & 0xff00) >> 8; /* Int 8 bits */
-               data++;
-               *(u_int8_t *)data = intpart & 0xff; /* Int 8 bits */
-               data++;
-               *(u_int8_t *)data = floatpart & 0xff; /* Float 8 bits */
-               data++;
-
-               /* Datum */
-               s = e + 1;
-               if (index(s, ':') != NULL)
-                       goto invalid_location;
-               *(u_int8_t *)data = atoi(s);
-               break;
-       case LLDPMED_LOCFORMAT_CIVIC:
-               /* Civic address */
-               chassis->c_med_location[1].data_len = 4;
-               s = e+1;
-               if ((s = index(s, ':')) == NULL)
-                       goto invalid_location;
-               s = s+1;
-               do {
-                       if ((s = index(s, ':')) == NULL)
-                               break;
-                       s = s+1;
-                       /* s is the beginning of the word */
-                       if ((n = index(s, ':')) == NULL)
-                               n = s + strlen(s);
-                       /* n is the end of the word */
-                       chassis->c_med_location[1].data_len += (n - s) + 2;
-                       if ((s = index(s, ':')) == NULL)
-                               break;
-                       s = s+1;
-               } while (1);
-               s = e+1;
-               if ((chassis->c_med_location[1].data =
-                       (char *)malloc(chassis->c_med_location[1].data_len)) ==
-                   NULL)
-                       fatal(NULL);
-               chassis->c_med_location[1].format = LLDPMED_LOCFORMAT_CIVIC;
-               data = chassis->c_med_location[1].data;
-               *(u_int8_t *)data = chassis->c_med_location[1].data_len - 1;
-               data++;
-               *(u_int8_t *)data = 2; /* Client location */
-               data++;
-               if ((e = index(s, ':')) == NULL)
-                       goto invalid_location;
-               if ((e - s) != 2)
-                       goto invalid_location;
-               memcpy(data, s, 2); /* Country code */
-               data += 2;
-               while (*e != '\0') {
-                       s=e+1;
-                       if ((e = index(s, ':')) == NULL)
-                               goto invalid_location;
-                       *e = '\0';
-                       *(u_int8_t *)data = atoi(s);
-                       data++;
-                       s=e+1;
-                       if ((e = index(s, ':')) == NULL)
-                               e = s + strlen(s);
-                       *(u_int8_t *)data = e - s;
-                       data++;
-                       memcpy(data, s, e-s);
-                       data += e-s;
-               }
-               break;
-       case LLDPMED_LOCFORMAT_ELIN:
-               s = e+1;
-               chassis->c_med_location[2].data_len = strlen(s);
-               if ((chassis->c_med_location[2].data =
-                       (char *)malloc(strlen(s))) == NULL)
-                       fatal(NULL);
-               chassis->c_med_location[2].format = LLDPMED_LOCFORMAT_ELIN;
-               strcpy(chassis->c_med_location[2].data, s);
-               break;
-       default:
-               goto invalid_location;
-       }
-
-       chassis->c_med_cap_enabled |= LLDPMED_CAP_LOCATION;
-       return;
-invalid_location:
-       LLOG_WARNX("the format of the location is invalid (%s)",
-               location);
-       if (type) {
-               free(chassis->c_med_location[type-1].data);
-               memset(&chassis->c_med_location[type-1], 0,
-                   sizeof(struct lldpd_med_loc));
-       }
-       free(l);
-}
-#endif
-
 void
 lldpd_shutdown(int sig)
 {
@@ -1584,7 +1409,7 @@ main(int argc, char *argv[])
        int snmp = 0;
 #endif
        char *mgmtp = NULL;
-       char *popt, opts[] = "vdxm:p:M:iL:@                    ";
+       char *popt, opts[] = "vdxm:p:M:i@                    ";
        int probe = 0, i, found, vlan = 0;
 #ifdef ENABLE_LLDPMED
        int lldpmed = 0, noinventory = 0;
@@ -1623,13 +1448,9 @@ main(int argc, char *argv[])
                case 'i':
                        noinventory = 1;
                        break;
-               case 'L':
-                       /* Handled later */
-                       break;
 #else
                case 'M':
                case 'i':
-               case 'L':
                case 'P':
                        fprintf(stderr, "LLDP-MED support is not built-in\n");
                        usage();
@@ -1704,17 +1525,7 @@ main(int argc, char *argv[])
                cfg->g_lchassis.c_med_type = lldpmed;
                cfg->g_lchassis.c_med_cap_available = LLDPMED_CAP_CAP |
                    LLDPMED_CAP_IV | LLDPMED_CAP_LOCATION;
-               cfg->g_lchassis.c_med_cap_enabled = LLDPMED_CAP_CAP;
-               if (!noinventory)
-                       cfg->g_lchassis.c_med_cap_enabled |= LLDPMED_CAP_IV;
-               optind = 1;
-               while ((ch = getopt(argc, argv, opts)) != -1) {
-                       switch (ch) {
-                       case 'L':
-                               lldpd_parse_location(&cfg->g_lchassis, optarg);
-                               break;
-                       }
-               }
+               cfg->g_noinventory = noinventory;
        }
 #endif
 
index 36bc0b5aae99ed6b058150ac514659370dffda8f..e13ae0550a091de55af16f86be8be051437dd5ff 100644 (file)
@@ -103,29 +103,9 @@ struct lldpd_chassis {
        u_int32_t                c_mgmt_if;
 
 #ifdef ENABLE_LLDPMED
-#define STRUCT_LLDPD_CHASSIS_MED       \
-       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           \
-       "wwbbbbwsssssss"
-
-       struct lldpd_med_policy  c_med_policy[LLDPMED_APPTYPE_LAST];
-       struct lldpd_med_loc     c_med_location[LLDPMED_LOCFORMAT_LAST];
+#define STRUCT_LLDPD_CHASSIS_MED "wwbsssssss"
        u_int16_t                c_med_cap_available;
-       u_int16_t                c_med_cap_enabled;
        u_int8_t                 c_med_type;
-       u_int8_t                 c_med_pow_devicetype; /* PD or PSE */
-       u_int8_t                 c_med_pow_source;
-       u_int8_t                 c_med_pow_priority;
-       u_int16_t                c_med_pow_val;
        char                    *c_med_hw;
        char                    *c_med_fw;
        char                    *c_med_sw;
@@ -159,6 +139,32 @@ struct lldpd_port {
 #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           \
+       "bbbw"
+       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];
+       u_int8_t                 p_med_pow_devicetype; /* PD or PSE */
+       u_int8_t                 p_med_pow_source;
+       u_int8_t                 p_med_pow_priority;
+       u_int16_t                p_med_pow_val;
+#else
+#define STRUCT_LLDPD_PORT_MED ""
+#endif
+
+
 #ifdef ENABLE_DOT1
 #define STRUCT_LLDPD_PORT_DOT1 "wPP"
        u_int16_t                p_pvid;
@@ -168,7 +174,10 @@ struct lldpd_port {
 #endif
 };
 
-#define STRUCT_LLDPD_PORT "(bCsw" STRUCT_LLDPD_PORT_DOT3 STRUCT_LLDPD_PORT_DOT1 ")"
+#define STRUCT_LLDPD_PORT "(bCsw"                              \
+       STRUCT_LLDPD_PORT_DOT3                                  \
+       STRUCT_LLDPD_PORT_MED                                   \
+       STRUCT_LLDPD_PORT_DOT1 ")"
 
 struct lldpd_frame {
        int size;
@@ -271,6 +280,9 @@ struct lldpd {
        int                      g_multi; /* Set to 1 if multiple protocols */
        int                      g_probe_time;
        int                      g_listen_vlans;
+#ifdef ENABLE_LLDPMED
+       int                      g_noinventory;
+#endif
 
        time_t                   g_lastsent;
        int                      g_lastrid;
@@ -296,6 +308,7 @@ enum hmsg_type {
        HMSG_GET_CHASSIS,
        HMSG_GET_PORT,
        HMSG_GET_VLANS,
+       HMSG_SET_LOCATION,
        HMSG_SHUTDOWN
 };
 
@@ -425,7 +438,7 @@ void         client_handle_none(struct lldpd *, struct hmsg *,
            struct hmsg *);
 void    client_handle_get_interfaces(struct lldpd *, struct hmsg *,
            struct hmsg *);
-void    client_handle_get_port_related(struct lldpd *, struct hmsg *,
+void    client_handle_port_related(struct lldpd *, struct hmsg *,
            struct hmsg *);
 void    client_handle_shutdown(struct lldpd *, struct hmsg *,
            struct hmsg *);