From 90b32da05699143e24738606a297160ff0b36799 Mon Sep 17 00:00:00 2001 From: lefranc Date: Tue, 22 Jun 2010 07:22:04 +0000 Subject: cleo/appli/managerd: listen to 'lo' interface, refs #1669 - managerd listen to br0, lo and nl_mme interface - lo is used by local applications sending local MME git-svn-id: svn+ssh://pessac/svn/cesar/trunk@7243 017c9cb6-072f-447c-8318-d5b54f68fe89 --- cleopatre/application/managerd/inc/bridge.h | 4 +- cleopatre/application/managerd/inc/managerd.h | 3 +- cleopatre/application/managerd/src/bridge.c | 81 +++++++++++++++++++++------ cleopatre/application/managerd/src/managerd.c | 10 ++-- 4 files changed, 73 insertions(+), 25 deletions(-) (limited to 'cleopatre/application/managerd') diff --git a/cleopatre/application/managerd/inc/bridge.h b/cleopatre/application/managerd/inc/bridge.h index 4ef79d70a1..3a29d15055 100644 --- a/cleopatre/application/managerd/inc/bridge.h +++ b/cleopatre/application/managerd/inc/bridge.h @@ -27,6 +27,7 @@ /** Interfaces name */ #define BR_IFNAME "br0" +#define LO_IFNAME "lo" #define ETH_IFNAME "eth0" /** Reception timeout in seconds */ @@ -56,9 +57,10 @@ enum bridge_status bridge_processing(struct managerd_ctx *ctx, uint8_t *buffer, * \param ctx managerd context. * \param buffer frame pointer. * \param len length allowed. + * \param is_local boolean; TRUE: get packet from loopback, else: get packet from bridge * \return received length or error code. */ -int bridge_receive(struct managerd_ctx *ctx, uint8_t *buffer, int len); +int bridge_receive(struct managerd_ctx *ctx, uint8_t *buffer, int len, int is_local); /** * Send a frame to BR interface. diff --git a/cleopatre/application/managerd/inc/managerd.h b/cleopatre/application/managerd/inc/managerd.h index 7591b49ebf..d18e16a946 100644 --- a/cleopatre/application/managerd/inc/managerd.h +++ b/cleopatre/application/managerd/inc/managerd.h @@ -36,12 +36,11 @@ /** Context structure */ struct managerd_ctx { int sock_br; /* bridge socket */ + int sock_lo; /* loopback socket */ int sock_mme; /* netlink socket for rx/tx MME to/from AV stack */ int gpio_fd; struct sockaddr_ll br_sll; struct sockaddr_nl mme_snl; - socklen_t br_sll_sz; - struct ifreq br_ifr; uint8_t br_mac_addr[ETH_ALEN]; union gpio_info sc_gpio; union gpio_info led_gpio; diff --git a/cleopatre/application/managerd/src/bridge.c b/cleopatre/application/managerd/src/bridge.c index 6ca8e2334d..3d6c13a973 100644 --- a/cleopatre/application/managerd/src/bridge.c +++ b/cleopatre/application/managerd/src/bridge.c @@ -89,27 +89,35 @@ enum bridge_status bridge_processing(struct managerd_ctx *ctx, uint8_t *buffer, } /** - * Receive a frame from BR interface. + * Receive a frame from BR or LO interface. * * \param ctx managerd context. * \param buffer frame pointer. * \param len length allowed. - * \return received length or error code. + * \param is_local boolean; TRUE: get packet from loopback, else: get packet from bridge + * \return received length or error code. */ -int bridge_receive(struct managerd_ctx *ctx, uint8_t *buffer, int len) +int bridge_receive(struct managerd_ctx *ctx, uint8_t *buffer, int len, int is_local) { //Receive a raw packet from BR interface - len = recv(ctx->sock_br, buffer, len, 0); + if(is_local) + { + len = recv(ctx->sock_lo, buffer, len, 0); + } + else + { + len = recv(ctx->sock_br, buffer, len, 0); + } if(0 >= len) { - syslog(LOG_WARNING, "receive failed on %s (%s)", BR_IFNAME, strerror(errno)); + syslog(LOG_WARNING, "receive failed on %s (%s)", is_local ? LO_IFNAME : BR_IFNAME, strerror(errno)); return -1; } return len; } /** - * Send a frame to BR interface. + * Send a frame to BR or LO interface. * * \param ctx managerd context. * \param buffer frame pointer. @@ -119,11 +127,20 @@ int bridge_receive(struct managerd_ctx *ctx, uint8_t *buffer, int len) int bridge_send(struct managerd_ctx *ctx, uint8_t *buffer, int len) { - //Send a raw packet to BR interface - len = send(ctx->sock_br, buffer, len, 0); + struct ethhdr *ethhdr; + int is_local = 0; + ethhdr = (struct ethhdr *)buffer; + + /* check destination mac address */ + if(!memcmp (ethhdr->h_dest, ctx->br_mac_addr, ETH_ALEN)) + { + is_local = 1; + } + //Send a raw packet to right interface + len = send (is_local ? ctx->sock_lo : ctx->sock_br, buffer, len, 0); if(0 > len) { - syslog(LOG_WARNING, "send failed on %s (%s)", BR_IFNAME, strerror(errno)); + syslog(LOG_WARNING, "send failed on %s (%s)", is_local ? LO_IFNAME : BR_IFNAME, strerror(errno)); return -1; } return 0; @@ -143,9 +160,6 @@ int bridge_init(struct managerd_ctx *ctx) //Check arguments assert(ctx != NULL); - //Set context - ctx->br_sll_sz = (socklen_t)(sizeof(struct sockaddr_ll)); - //Create a receive connection on BR interface if(0 > (ctx->sock_br = socket(AF_PACKET, SOCK_RAW, ETH_P_HPAV))) { @@ -154,25 +168,25 @@ int bridge_init(struct managerd_ctx *ctx) } //Prepare BR socket address - strncpy(ctx->br_ifr.ifr_name, (char*)BR_IFNAME, IFNAMSIZ); - if(-1 == (ioctl(ctx->sock_br, SIOCGIFINDEX, &ctx->br_ifr))) + strncpy(ifr.ifr_name, (char*)BR_IFNAME, IFNAMSIZ); + if(-1 == (ioctl(ctx->sock_br, SIOCGIFINDEX, &ifr))) { syslog(LOG_WARNING, "cannot get interface %s index (%s)", BR_IFNAME, strerror(errno)); close(ctx->sock_br); return -1; } ctx->br_sll.sll_family = AF_PACKET; - ctx->br_sll.sll_ifindex = ctx->br_ifr.ifr_ifindex; + ctx->br_sll.sll_ifindex = ifr.ifr_ifindex; ctx->br_sll.sll_protocol = htons(ETH_P_HPAV); //Find BR mac address - if(-1 == (ioctl(ctx->sock_br, SIOCGIFHWADDR, &ctx->br_ifr))) + if(-1 == (ioctl(ctx->sock_br, SIOCGIFHWADDR, &ifr))) { syslog(LOG_WARNING, "cannot get interface %s mac address (%s)", BR_IFNAME, strerror(errno)); close(ctx->sock_br); return -1; } - memcpy(ctx->br_mac_addr, ctx->br_ifr.ifr_hwaddr.sa_data, ETH_ALEN); + memcpy(ctx->br_mac_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); //Bind BR socket to this interface if(-1 == (bind(ctx->sock_br, (struct sockaddr *)&ctx->br_sll, sizeof(struct sockaddr_ll)))) @@ -182,6 +196,36 @@ int bridge_init(struct managerd_ctx *ctx) return -1; } + //Create a receive connection on LO interface + if(0 > (ctx->sock_lo = socket(AF_PACKET, SOCK_RAW, ETH_P_HPAV))) + { + syslog(LOG_WARNING, "cannot open socket on %s (%s)", LO_IFNAME, strerror(errno)); + close(ctx->sock_br); + return -1; + } + + //Prepare LO socket address + strncpy(ifr.ifr_name, (char*)LO_IFNAME, IFNAMSIZ); + if(-1 == (ioctl(ctx->sock_lo, SIOCGIFINDEX, &ifr))) + { + syslog(LOG_WARNING, "cannot get interface %s index (%s)", LO_IFNAME, strerror(errno)); + close(ctx->sock_br); + close(ctx->sock_lo); + return -1; + } + sll.sll_family = AF_PACKET; + sll.sll_ifindex = ifr.ifr_ifindex; + sll.sll_protocol = htons(ETH_P_HPAV); + + //Bind LO socket to this interface + if(-1 == (bind(ctx->sock_lo, (struct sockaddr *)&sll, sizeof(struct sockaddr_ll)))) + { + syslog(LOG_WARNING, "cannot bind raw socket to interface %s (%s)", LO_IFNAME, strerror(errno)); + close(ctx->sock_lo); + close(ctx->sock_br); + return -1; + } + return 0; } @@ -197,5 +241,6 @@ void bridge_uninit(struct managerd_ctx *ctx) //Close BR connections close(ctx->sock_br); + //Close LO connections + close(ctx->sock_lo); } - diff --git a/cleopatre/application/managerd/src/managerd.c b/cleopatre/application/managerd/src/managerd.c index 0db0e3cdbb..4944cf21b0 100644 --- a/cleopatre/application/managerd/src/managerd.c +++ b/cleopatre/application/managerd/src/managerd.c @@ -68,10 +68,11 @@ static int managerd_process(struct managerd_ctx *ctx) timeout.tv_usec = 0; FD_ZERO(&readfds); FD_SET(ctx->sock_br, &readfds); + FD_SET(ctx->sock_lo, &readfds); FD_SET (ctx->sock_mme, &readfds); - //Select on BR connection - result = select(ctx->sock_br + 2, &readfds, NULL, NULL, &timeout); + //Select + result = select(ctx->sock_br + 3, &readfds, NULL, NULL, &timeout); //Select error if(0 > result) @@ -88,10 +89,11 @@ static int managerd_process(struct managerd_ctx *ctx) else continue; } - else if FD_ISSET (ctx->sock_br, &readfds) + else if (FD_ISSET (ctx->sock_br, &readfds) + || FD_ISSET (ctx->sock_lo, &readfds)) { //Receive a frame from bridge: process it - len = bridge_receive(ctx, buffer, MAX_PKT_LEN); + len = bridge_receive(ctx, buffer, MAX_PKT_LEN, FD_ISSET (ctx->sock_lo, &readfds) /* check for local if */); if(0 >= len) { result = -1; -- cgit v1.2.3