sd-lldp.c revision 49699bac94d24b444274f91f85c82e6fad04d029
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright (C) 2014 Tom Gundersen
Copyright (C) 2014 Susant Sahani
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "siphash24.h"
#include "hashmap.h"
#include "event-util.h"
#include "lldp-tlv.h"
#include "lldp-port.h"
#include "sd-lldp.h"
#include "prioq.h"
#include "strv.h"
#include "lldp-internal.h"
#include "ether-addr-util.h"
typedef enum LLDPAgentRXState {
_LLDP_AGENT_RX_INVALID = -1,
/* Section 10.5.2.2 Reception counters */
struct lldp_agent_statitics {
};
struct sd_lldp {
void *userdata;
};
static unsigned long chassis_id_hash_func(const void *p,
uint64_t u;
const lldp_chassis_id *id = p;
return (unsigned long) u;
}
const lldp_chassis_id *a, *b;
a = _a;
b = _b;
return -1;
}
static const struct hash_ops chassis_id_hash_ops = {
};
int r;
/* Remove expired packets */
}
if (r < 0)
goto out;
log_lldp("Packet added. MIB size: %d , PQ size: %d",
return 0;
out:
if (r < 0)
return 0;
}
/* 10.3.2 LLDPDU validation: rxProcessFrame() */
bool chassis_id = false;
bool malformed = false;
bool port_id = false;
bool ttl = false;
bool end = false;
uint8_t *p, *q;
int r;
log_lldp("Port is disabled : %s . Dropping ...",
goto out;
}
p += sizeof(struct ether_header);
for (i = 1, l = 0; l <= length; i++) {
if (type == LLDP_TYPE_END) {
if (len != 0) {
log_lldp("TLV type end is not length 0. Length:%d received . Dropping ...",
len);
malformed = true;
goto out;
}
end = true;
break;
} else if (type >=_LLDP_TYPE_MAX) {
log_lldp("TLV type not recognized %d . Dropping ...",
type);
malformed = true;
goto out;
}
/* skip type and lengh encoding */
p += 2;
q = p;
p += len;
l += (len + 2);
if (i <= 3) {
if (i != type) {
log_lldp("TLV missing or out of order. Dropping ...");
malformed = true;
goto out;
}
}
switch(type) {
case LLDP_TYPE_CHASSIS_ID:
if (len < 2) {
log_lldp("Received malformed Chassis ID TLV len = %d. Dropping",
len);
malformed = true;
goto out;
}
if (chassis_id) {
log_lldp("Duplicate Chassis ID TLV found. Dropping ...");
malformed = true;
goto out;
}
/* Look what subtype it has */
if (*q == LLDP_CHASSIS_SUBTYPE_RESERVED ||
log_lldp("Unknown subtype: %d found in Chassis ID TLV . Dropping ...",
*q);
malformed = true;
goto out;
}
chassis_id = true;
break;
case LLDP_TYPE_PORT_ID:
if (len < 2) {
log_lldp("Received malformed Port ID TLV len = %d. Dropping",
len);
malformed = true;
goto out;
}
if (port_id) {
log_lldp("Duplicate Port ID TLV found. Dropping ...");
malformed = true;
goto out;
}
/* Look what subtype it has */
if (*q == LLDP_PORT_SUBTYPE_RESERVED ||
log_lldp("Unknown subtype: %d found in Port ID TLV . Dropping ...",
*q);
malformed = true;
goto out;
}
port_id = true;
break;
case LLDP_TYPE_TTL:
if(len != 2) {
"Received invalid lenth: %d TTL TLV. Dropping ...",
len);
malformed = true;
goto out;
}
if (ttl) {
log_lldp("Duplicate TTL TLV found. Dropping ...");
malformed = true;
goto out;
}
ttl = true;
break;
default:
if (len == 0) {
log_lldp("TLV type = %d's, length 0 received . Dropping ...",
type);
malformed = true;
goto out;
}
break;
}
}
log_lldp( "One or more mandotory TLV missing . Dropping ...");
malformed = true;
goto out;
}
if (r < 0) {
log_lldp( "Failed to parse the TLV. Dropping ...");
malformed = true;
goto out;
}
out:
if (malformed) {
}
return 0;
}
static int ttl_expiry_item_prioq_compare_func(const void *a, const void *b) {
const lldp_neighbour_port *p = a, *q = b;
return -1;
return 1;
return 0;
}
}
}
/* 10.5.5.2.1 mibDeleteObjects ()
* The mibDeleteObjects () procedure deletes all information in the LLDP remote
* systems MIB associated with the MSAP identifier if an LLDPDU is received with
* an rxTTL value of zero (see 10.3.2) or the timing counter rxInfoTTL expires. */
usec_t t = 0;
/* Remove all entries that are past their TTL */
for (;;) {
break;
if (!p)
break;
if (t <= 0)
t = now(CLOCK_BOOTTIME);
if (p->until > t)
break;
}
}
lldp_neighbour_port *p, *q;
lldp_chassis *c;
/* Drop all packets */
}
}
}
lldp_chassis *c;
Iterator i;
int r;
if (r < 0)
goto finish;
if (r < 0)
continue;
if (!s)
return -ENOMEM;
if (r < 0) {
free(s);
continue;
}
if (type != LLDP_PORT_SUBTYPE_MAC_ADDRESS) {
if (!k)
return -ENOMEM;
free(k);
} else {
}
if (!t)
return -ENOMEM;
free(s);
s = t;
/* Don't write expired packets */
free(s);
continue;
}
if (!t)
return -ENOMEM;
free(s);
s = t;
if (r < 0)
k = strappend(s, "'_NAME=N/A' ");
else {
if (!t)
return -ENOMEM;
}
if (!k)
return -ENOMEM;
free(s);
s = k;
if (!t)
return -ENOMEM;
fprintf(f, "%s\n", t);
free(s);
free(t);
}
}
r = 0;
s = NULL;
t = NULL;
k = NULL;
fflush(f);
r = -errno;
}
if (r < 0)
return r;
}
int r;
if (r < 0) {
log_lldp("Failed to start Port : %s , %s",
strerror(-r));
return r;
}
return 0;
}
int r;
if (r < 0)
return r;
return 0;
}
int r;
if (event)
else {
if (r < 0)
return r;
}
return 0;
}
return 0;
}
return 0;
}
if (!lldp)
return;
/* Drop all packets */
}
int sd_lldp_new(int ifindex,
char *ifname,
struct ether_addr *mac,
int r;
if (!lldp)
return -ENOMEM;
if (r < 0)
return r;
if (!lldp->neighbour_mib)
return -ENOMEM;
if (r < 0)
return r;
return 0;
}