From: Vincent Bernat Date: Tue, 25 Dec 2012 11:15:36 +0000 (+0100) Subject: interfaces: sending/receiving on raw interfaces is OS specific X-Git-Tag: 0.7.0~42 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=22e8cd65738d9f74f23f07cc50709dd147225359;p=thirdparty%2Flldpd.git interfaces: sending/receiving on raw interfaces is OS specific On Linux, we can send/receive with `recvfrom()`. With BSD and the use of BPF, we send receive from BPF buffers. Therefore, ethernet operations are moved into `interfaces-linux.c`. --- diff --git a/src/daemon/interfaces-linux.c b/src/daemon/interfaces-linux.c index 88020365..c4be843f 100644 --- a/src/daemon/interfaces-linux.c +++ b/src/daemon/interfaces-linux.c @@ -78,6 +78,58 @@ iflinux_eth_init(struct lldpd *cfg, struct lldpd_hardware *hardware) return 0; } +/* Generic ethernet send/receive */ +static int +iflinux_eth_send(struct lldpd *cfg, struct lldpd_hardware *hardware, + char *buffer, size_t size) +{ + log_debug("interfaces", "send PDU to ethernet device %s (fd=%d)", + hardware->h_ifname, hardware->h_sendfd); + return write(hardware->h_sendfd, + buffer, size); +} + +static int +iflinux_eth_recv(struct lldpd *cfg, struct lldpd_hardware *hardware, + int fd, char *buffer, size_t size) +{ + int n; + struct sockaddr_ll from; + socklen_t fromlen; + + log_debug("interfaces", "receive PDU from ethernet device %s", + hardware->h_ifname); + fromlen = sizeof(from); + if ((n = recvfrom(fd, + buffer, + size, 0, + (struct sockaddr *)&from, + &fromlen)) == -1) { + log_warn("interfaces", "error while receiving frame on %s", + hardware->h_ifname); + hardware->h_rx_discarded_cnt++; + return -1; + } + if (from.sll_pkttype == PACKET_OUTGOING) + return -1; + return n; +} + +static int +iflinux_eth_close(struct lldpd *cfg, struct lldpd_hardware *hardware) +{ + log_debug("interfaces", "close ethernet device %s", + hardware->h_ifname); + interfaces_setup_multicast(cfg, hardware->h_ifname, 1); + return 0; +} + +static struct lldpd_ops eth_ops = { + .send = iflinux_eth_send, + .recv = iflinux_eth_recv, + .cleanup = iflinux_eth_close, +}; + static int old_iflinux_is_bridge(struct lldpd *cfg, struct interfaces_device_list *interfaces, @@ -782,6 +834,7 @@ interfaces_update(struct lldpd *cfg) interfaces_helper_whitelist(cfg, interfaces); iflinux_handle_bond(cfg, interfaces); interfaces_helper_physical(cfg, interfaces, + ð_ops, iflinux_eth_init); #ifdef ENABLE_DOT1 interfaces_helper_vlan(cfg, interfaces); diff --git a/src/daemon/interfaces.c b/src/daemon/interfaces.c index 14f54763..e3908efd 100644 --- a/src/daemon/interfaces.c +++ b/src/daemon/interfaces.c @@ -25,58 +25,6 @@ #include #include -/* Generic ethernet send/receive */ -static int -iface_eth_send(struct lldpd *cfg, struct lldpd_hardware *hardware, - char *buffer, size_t size) -{ - log_debug("interfaces", "send PDU to ethernet device %s (fd=%d)", - hardware->h_ifname, hardware->h_sendfd); - return write(hardware->h_sendfd, - buffer, size); -} - -static int -iface_eth_recv(struct lldpd *cfg, struct lldpd_hardware *hardware, - int fd, char *buffer, size_t size) -{ - int n; - struct sockaddr_ll from; - socklen_t fromlen; - - log_debug("interfaces", "receive PDU from ethernet device %s", - hardware->h_ifname); - fromlen = sizeof(from); - if ((n = recvfrom(fd, - buffer, - size, 0, - (struct sockaddr *)&from, - &fromlen)) == -1) { - log_warn("interfaces", "error while receiving frame on %s", - hardware->h_ifname); - hardware->h_rx_discarded_cnt++; - return -1; - } - if (from.sll_pkttype == PACKET_OUTGOING) - return -1; - return n; -} - -static int -iface_eth_close(struct lldpd *cfg, struct lldpd_hardware *hardware) -{ - log_debug("interfaces", "close ethernet device %s", - hardware->h_ifname); - interfaces_setup_multicast(cfg, hardware->h_ifname, 1); - return 0; -} - -struct lldpd_ops eth_ops = { - .send = iface_eth_send, - .recv = iface_eth_recv, - .cleanup = iface_eth_close, -}; - /* Generic ethernet interface initialization */ /** * Enable multicast on the given interface. @@ -548,6 +496,7 @@ interfaces_helper_port_name_desc(struct lldpd_hardware *hardware, void interfaces_helper_physical(struct lldpd *cfg, struct interfaces_device_list *interfaces, + struct lldpd_ops *ops, int(*init)(struct lldpd *, struct lldpd_hardware *)) { struct interfaces_device *iface; @@ -562,7 +511,7 @@ interfaces_helper_physical(struct lldpd *cfg, if ((hardware = lldpd_get_hardware(cfg, iface->name, iface->index, - ð_ops)) == NULL) { + ops)) == NULL) { if ((hardware = lldpd_alloc_hardware(cfg, iface->name, iface->index)) == NULL) { @@ -577,7 +526,7 @@ interfaces_helper_physical(struct lldpd *cfg, lldpd_hardware_cleanup(cfg, hardware); continue; } - hardware->h_ops = ð_ops; + hardware->h_ops = ops; TAILQ_INSERT_TAIL(&cfg->g_hardware, hardware, h_entries); } else { if (hardware->h_flags) continue; /* Already seen this time */ diff --git a/src/daemon/lldpd.h b/src/daemon/lldpd.h index 400285aa..69006553 100644 --- a/src/daemon/lldpd.h +++ b/src/daemon/lldpd.h @@ -314,6 +314,7 @@ void interfaces_helper_chassis(struct lldpd *, struct interfaces_device_list *); void interfaces_helper_physical(struct lldpd *, struct interfaces_device_list *, + struct lldpd_ops *, int(*init)(struct lldpd *, struct lldpd_hardware *)); void interfaces_helper_port_name_desc(struct lldpd_hardware *, struct interfaces_device *);