From 740593ff74758bc6677419f59519f6c8cc2a19cd Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Tue, 23 Dec 2008 16:16:36 +0100 Subject: [PATCH] Move LLDP-MED location/policy to port instead of chassis. Handle setting of location in lldpctl instead of lldpd. --- man/lldpctl.8 | 112 +++++++++++++- man/lldpd.8 | 108 ------------- src/agent.c | 28 ++-- src/client.c | 50 ++++-- src/ctl.c | 1 + src/lldp.c | 80 +++++----- src/lldpctl.c | 417 +++++++++++++++++++++++++++++++++++++++++--------- src/lldpd.c | 213 ++------------------------ src/lldpd.h | 59 ++++--- 9 files changed, 589 insertions(+), 479 deletions(-) diff --git a/man/lldpctl.8 b/man/lldpctl.8 index 60a0bb6f..6407d1e4 100644 --- a/man/lldpctl.8 +++ b/man/lldpctl.8 @@ -18,10 +18,11 @@ .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 diff --git a/man/lldpd.8 b/man/lldpd.8 index a1c4a53f..ea31ac42 100644 --- a/man/lldpd.8 +++ b/man/lldpd.8 @@ -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 diff --git a/src/agent.c b/src/agent.c index 86e425b8..8aa703f6 100644 --- a/src/agent.c +++ b/src/agent.c @@ -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; diff --git a/src/client.c b/src/client.c index a4ea111d..30ebc36f 100644 --- a/src/client.c +++ b/src/client.c @@ -19,10 +19,13 @@ 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, diff --git a/src/ctl.c b/src/ctl.c index 4988b69c..950b1c46 100644 --- 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(); diff --git a/src/lldp.c b/src/lldp.c index d47d489b..d7a31538 100644 --- a/src/lldp.c +++ b/src/lldp.c @@ -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: diff --git a/src/lldpctl.c b/src/lldpctl.c index 9fb9faa5..8eb90bbb 100644 --- a/src/lldpctl.c +++ b/src/lldpctl.c @@ -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; } diff --git a/src/lldpd.c b/src/lldpd.c index 03d87670..1d2364fb 100644 --- a/src/lldpd.c +++ b/src/lldpd.c @@ -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 diff --git a/src/lldpd.h b/src/lldpd.h index 36bc0b5a..e13ae055 100644 --- a/src/lldpd.h +++ b/src/lldpd.h @@ -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 *); -- 2.39.5