From: Vincent Bernat Date: Mon, 20 Oct 2008 09:12:02 +0000 (+0200) Subject: Do not try to catch CDP frame inside VLAN tagged frame. X-Git-Tag: 0.2~34 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=348f6df627263b0bad5ac27c272de4745f676fab;p=thirdparty%2Flldpd.git Do not try to catch CDP frame inside VLAN tagged frame. With hardware accelerated VLAN supported by some cards like e1000, this does not work. We need to listen on the corresponding VLAN instead. This reverts commit dc1539a44534a36fa8683ecfaddbbd6b34466b96. --- diff --git a/src/cdp.c b/src/cdp.c index bd2d6fae..d2fb90e3 100644 --- a/src/cdp.c +++ b/src/cdp.c @@ -48,10 +48,10 @@ cdp_send(struct lldpd *global, struct lldpd_chassis *chassis, sizeof(llc.ether.shost)); memcpy(&llc.ether.dhost, &mcastaddr, sizeof(llc.ether.dhost)); - llc.llc.dsap = llc.llc.ssap = 0xaa; - llc.llc.control = 0x03; - memcpy(llc.llc.org, llcorg, sizeof(llc.llc.org)); - llc.llc.protoid = htons(LLC_PID_CDP); + llc.dsap = llc.ssap = 0xaa; + llc.control = 0x03; + memcpy(llc.org, llcorg, sizeof(llc.org)); + llc.protoid = htons(LLC_PID_CDP); IOV_NEW; iov[c].iov_base = &llc; iov[c].iov_len = sizeof(llc); @@ -172,8 +172,7 @@ cdp_decode(struct lldpd *cfg, char *frame, int s, { struct lldpd_chassis *chassis; struct lldpd_port *port; - struct ieee8023 *ether; - struct llc *llc; + struct ethllc *llc; struct cdp_header *ch; struct cdp_tlv_head *tlv; struct cdp_tlv_address_head *ah; @@ -196,46 +195,21 @@ cdp_decode(struct lldpd *cfg, char *frame, int s, } TAILQ_INIT(&port->p_vlans); - if (s < sizeof(struct ieee8023)) { + if (s < sizeof(struct ethllc) + sizeof(struct cdp_header)) { LLOG_WARNX("too short frame received on %s", hardware->h_ifname); goto malformed; } - ether = (struct ieee8023*)frame; - if (memcmp(ðer->dhost, cdpaddr, sizeof(cdpaddr)) != 0) { + llc = (struct ethllc *)frame; + if (memcmp(&llc->ether.dhost, cdpaddr, sizeof(cdpaddr)) != 0) { LLOG_INFO("frame not targeted at CDP multicast address received on %s", hardware->h_ifname); goto malformed; } - - /* Is it a CDP frame encapsulated into a VLAN? */ - if (ether->size == htons(ETHERTYPE_VLAN)) { - if (s < sizeof(struct ieee8023) + sizeof(struct ieee8021q) + - sizeof(struct llc) + sizeof(struct cdp_header)) { - LLOG_WARNX("too short frame received on %s", hardware->h_ifname); - goto malformed; - } - if (ntohs(((struct ieee8021q*)(frame + - sizeof(struct ieee8023)))->size) > - s - sizeof(struct ieee8023) - sizeof(struct ieee8021q)) { - LLOG_WARNX("incorrect 802.3/802.1q frame size reported on %s", - hardware->h_ifname); - goto malformed; - } - llc = (struct llc*)(frame + sizeof(struct ieee8023) + - sizeof(struct ieee8021q)); - } else { - if (s < sizeof(struct ethllc) + sizeof(struct cdp_header)) { - LLOG_WARNX("too short frame received on %s", hardware->h_ifname); - goto malformed; - } - - if (ntohs(ether->size) > s - sizeof(struct ieee8023)) { - LLOG_WARNX("incorrect 802.3 frame size reported on %s", - hardware->h_ifname); - goto malformed; - } - llc = (struct llc*)(frame + sizeof(struct ieee8023)); + if (ntohs(llc->ether.size) > s - sizeof(struct ieee8023)) { + LLOG_WARNX("incorrect 802.3 frame size reported on %s", + hardware->h_ifname); + goto malformed; } if (llc->protoid != htons(LLC_PID_CDP)) { if ((llc->protoid != htons(LLC_PID_DRIP)) && @@ -249,7 +223,7 @@ cdp_decode(struct lldpd *cfg, char *frame, int s, hardware->h_ifname); goto malformed; } - f = (void*)llc - (void*)frame + sizeof(struct llc); + f = sizeof(struct ethllc); ch = (struct cdp_header *)(frame + f); if ((ch->version != 1) && (ch->version != 2)) { LLOG_WARNX("incorrect CDP version (%d) for frame received on %s", @@ -353,7 +327,7 @@ cdp_decode(struct lldpd *cfg, char *frame, int s, LLOG_WARN("unable to allocate memory for port ID"); goto malformed; } - memcpy(port->p_id, ether->shost, ETH_ALEN); + memcpy(port->p_id, llc->ether.shost, ETH_ALEN); port->p_id_len = ETH_ALEN; f += len; break; @@ -466,25 +440,11 @@ cdp_guess(char *frame, int len, int version) { const u_int8_t mcastaddr[] = CDP_MULTICAST_ADDR; struct cdp_header *ch; - if (len < sizeof(struct ieee8023)) + if (len < sizeof(struct ethllc) + sizeof(struct cdp_header)) return 0; if (memcmp(frame, mcastaddr, ETH_ALEN) != 0) return 0; - /* Maybe this is encapsulated into a VLAN */ - if (((struct ieee8023*)frame)->size != htons(ETHERTYPE_VLAN)) { - /* Not a 802.1q frame */ - if (len < sizeof(struct ethllc) + - sizeof(struct cdp_header)) - return 0; - ch = (struct cdp_header *)(frame + sizeof(struct ethllc)); - } else { - /* 802.1q frame */ - if (len < sizeof(struct ieee8023) + sizeof(struct ieee8021q) + - sizeof(struct llc) + sizeof(struct cdp_header)) - return 0; - ch = (struct cdp_header *)(frame + sizeof(struct ieee8023) + - sizeof(struct ieee8021q) + sizeof(struct llc)); - } + ch = (struct cdp_header *)(frame + sizeof(struct ethllc)); return (ch->version == version); } diff --git a/src/edp.c b/src/edp.c index ecc8546d..0275074d 100644 --- a/src/edp.c +++ b/src/edp.c @@ -60,10 +60,10 @@ edp_send(struct lldpd *global, struct lldpd_chassis *chassis, sizeof(llc.ether.shost)); memcpy(&llc.ether.dhost, &mcastaddr, sizeof(llc.ether.dhost)); - llc.llc.dsap = llc.llc.ssap = 0xaa; - llc.llc.control = 0x03; - memcpy(llc.llc.org, llcorg, sizeof(llc.llc.org)); - llc.llc.protoid = htons(LLC_PID_EDP); + llc.dsap = llc.ssap = 0xaa; + llc.control = 0x03; + memcpy(llc.org, llcorg, sizeof(llc.org)); + llc.protoid = htons(LLC_PID_EDP); IOV_NEW; iov[c].iov_base = &llc; iov[c].iov_len = sizeof(llc); @@ -241,7 +241,7 @@ edp_decode(struct lldpd *cfg, char *frame, int s, hardware->h_ifname); goto malformed; } - if (llc->llc.protoid != htons(LLC_PID_EDP)) { + if (llc->protoid != htons(LLC_PID_EDP)) { LLOG_DEBUG("incorrect LLC protocol ID received on %s", hardware->h_ifname); goto malformed; diff --git a/src/llc.h b/src/llc.h index 0ca0651f..002ccf18 100644 --- a/src/llc.h +++ b/src/llc.h @@ -23,12 +23,8 @@ struct ieee8023 { u_int16_t size; /* packet type ID field */ } __attribute__ ((__packed__)); -struct ieee8021q { - u_int16_t vid; - u_int16_t size; -} __attribute__ ((__packed__)); - -struct llc { +struct ethllc { + struct ieee8023 ether; u_int8_t dsap; /* destination SAP */ u_int8_t ssap; /* source SAP */ u_int8_t control; /* LLC control field */ @@ -36,10 +32,4 @@ struct llc { u_int16_t protoid; } __attribute__ ((__packed__)); -/* IEEE 802.3 + LLC */ -struct ethllc { - struct ieee8023 ether; - struct llc llc; -} __attribute__ ((__packed__)); - #endif diff --git a/src/lldpd.c b/src/lldpd.c index c4e48fdd..e4161b5f 100644 --- a/src/lldpd.c +++ b/src/lldpd.c @@ -64,20 +64,14 @@ void lldpd_iface_multicast(struct lldpd *, const char *, int); { 0x6, 0, 0, 0x0000ffff }, \ { 0x6, 0, 0, 0x00000000 }, struct sock_filter lldpd_filter_lldp_f[] = { LLDPD_FILTER_LLDP_F }; -/* "(ether dst 01:00:0c:cc:cc:cc) or (vlan and ether dst 01:00:0c:cc:cc:cc)" */ +/* "ether dst 01:00:0c:cc:cc:cc" */ #define LLDPD_FILTER_CDP_F \ - { 0x20, 0, 0, 0x00000002 }, \ - { 0x15, 0, 2, 0x0ccccccc }, \ - { 0x28, 0, 0, 0x00000000 }, \ - { 0x15, 6, 0, 0x00000100 }, \ - { 0x28, 0, 0, 0x0000000c }, \ - { 0x15, 0, 5, 0x00008100 }, \ - { 0x20, 0, 0, 0x00000002 }, \ - { 0x15, 0, 3, 0x0ccccccc }, \ - { 0x28, 0, 0, 0x00000000 }, \ - { 0x15, 0, 1, 0x00000100 }, \ - { 0x6, 0, 0, 0x0000ffff }, \ - { 0x6, 0, 0, 0x00000000 }, + { 0x20, 0, 0, 0x00000002 }, \ + { 0x15, 0, 3, 0x0ccccccc }, \ + { 0x28, 0, 0, 0x00000000 }, \ + { 0x15, 0, 1, 0x00000100 }, \ + { 0x6, 0, 0, 0x0000ffff }, \ + { 0x6, 0, 0, 0x00000000 }, struct sock_filter lldpd_filter_cdp_f[] = { LLDPD_FILTER_CDP_F }; /* "ether dst 01:00:81:00:01:00" */ #define LLDPD_FILTER_SONMP_F \ diff --git a/src/sonmp.c b/src/sonmp.c index 19f9caa4..19067c70 100644 --- a/src/sonmp.c +++ b/src/sonmp.c @@ -190,10 +190,10 @@ sonmp_send(struct lldpd *global, struct lldpd_chassis *chassis, sizeof(frame.llc.ether.dhost)); frame.llc.ether.size = htons(sizeof(struct sonmp) - sizeof(struct ieee8023)); - frame.llc.llc.dsap = frame.llc.llc.ssap = 0xaa; - frame.llc.llc.control = 0x03; - memcpy(frame.llc.llc.org, llcorg, sizeof(frame.llc.llc.org)); - frame.llc.llc.protoid = htons(LLC_PID_SONMP_HELLO); + frame.llc.dsap = frame.llc.ssap = 0xaa; + frame.llc.control = 0x03; + memcpy(frame.llc.org, llcorg, sizeof(frame.llc.org)); + frame.llc.protoid = htons(LLC_PID_SONMP_HELLO); memcpy(&frame.addr, &chassis->c_mgmt, sizeof(struct in_addr)); frame.seg[2] = if_nametoindex(hardware->h_ifname); frame.chassis = 1; /* Other */ @@ -208,7 +208,7 @@ sonmp_send(struct lldpd *global, struct lldpd_chassis *chassis, return ENETDOWN; } - frame.llc.llc.protoid = htons(LLC_PID_SONMP_FLATNET); + frame.llc.protoid = htons(LLC_PID_SONMP_FLATNET); frame.llc.ether.dhost[ETH_ALEN-1] = 1; if (write((hardware->h_raw_real > 0) ? hardware->h_raw_real : @@ -255,7 +255,7 @@ sonmp_decode(struct lldpd *cfg, char *frame, int s, * them. */ goto malformed; } - if (f->llc.llc.protoid != htons(LLC_PID_SONMP_HELLO)) { + if (f->llc.protoid != htons(LLC_PID_SONMP_HELLO)) { LLOG_DEBUG("incorrect LLC protocol ID received on %s", hardware->h_ifname); goto malformed;