diff --git a/CHANGELOG b/CHANGELOG index 3979fde0..c9c0799d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -19,6 +19,12 @@ HISTORY ++ New features: + 2007-09-15 Frédéric Bernon + * udp.h, udp.c, sockets.c: Changes for "#20503 IGMP Improvement". Add IP_MULTICAST_IF + option in socket API, and a new field "multicast_ip" in "struct udp_pcb" (for + netconn and raw API users), only if LWIP_IGMP=1. Add getsockopt processing for + IP_MULTICAST_TTL and IP_MULTICAST_IF. + 2007-09-10 Frédéric Bernon * snmp.h, mib2.c: enable to remove SNMP timer (which consumne several cycles even when it's not necessary). snmp_agent.txt tell to call snmp_inc_sysuptime() diff --git a/src/api/sockets.c b/src/api/sockets.c index 74ee6086..f61cf5a8 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -1108,6 +1108,18 @@ int lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optl err = EINVAL; } break; +#if LWIP_IGMP + case IP_MULTICAST_TTL: + if (*optlen < sizeof(u8_t)) { + err = EINVAL; + } + break; + case IP_MULTICAST_IF: + if (*optlen < sizeof(struct in_addr)) { + err = EINVAL; + } + break; +#endif /* LWIP_IGMP */ default: LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", @@ -1300,6 +1312,18 @@ static void lwip_getsockopt_internal(void *arg) LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n", s, *(int *)optval)); break; +#if LWIP_IGMP + case IP_MULTICAST_TTL: + *(u8_t*)optval = sock->conn->pcb.ip->ttl; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n", + s, *(int *)optval)); + break; + case IP_MULTICAST_IF: + ((struct in_addr*) optval)->s_addr = sock->conn->pcb.udp->multicast_ip.addr; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%x\n", + s, *(u32_t *)optval)); + break; +#endif /* LWIP_IGMP */ } /* switch (optname) */ break; @@ -1437,16 +1461,27 @@ int lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t break; #if LWIP_IGMP case IP_MULTICAST_TTL: - /* NOTE, some BSD implementation use "int", some others "char" */ - if ((optlen != sizeof(char)) && (optlen != sizeof(int))) + if (optlen < sizeof(u8_t)) { err = EINVAL; + } + if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { + err = EAFNOSUPPORT; + } + break; + case IP_MULTICAST_IF: + if (optlen < sizeof(struct in_addr)) { + err = EINVAL; + } + if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { + err = EAFNOSUPPORT; + } break; case IP_ADD_MEMBERSHIP: case IP_DROP_MEMBERSHIP: if (optlen < sizeof(struct ip_mreq)) { err = EINVAL; } - if ((sock->conn->type == NETCONN_TCP) || (sock->conn->type == NETCONN_RAW)) { + if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) { err = EAFNOSUPPORT; } break; @@ -1622,10 +1657,10 @@ static void lwip_setsockopt_internal(void *arg) break; #if LWIP_IGMP case IP_MULTICAST_TTL: - if (optlen == sizeof(int)) - sock->conn->pcb.tcp->ttl = (u8_t)(*(int*) optval); - if (optlen == sizeof(u8_t)) - sock->conn->pcb.tcp->ttl = (u8_t)(*(u8_t*)optval); + sock->conn->pcb.udp->ttl = (u8_t)(*(u8_t*)optval); + break; + case IP_MULTICAST_IF: + sock->conn->pcb.udp->multicast_ip.addr = ((struct in_addr*) optval)->s_addr; break; case IP_ADD_MEMBERSHIP: case IP_DROP_MEMBERSHIP: diff --git a/src/core/udp.c b/src/core/udp.c index 8f259a1c..4b102b87 100644 --- a/src/core/udp.c +++ b/src/core/udp.c @@ -355,8 +355,14 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p) return err; } } + /* find the outgoing network interface for this packet */ +#if LWIP_IGMP + netif = ip_route((ip_addr_ismulticast(&(pcb->remote_ip)))?(&(pcb->multicast_ip)):(&(pcb->remote_ip))); +#else netif = ip_route(&(pcb->remote_ip)); +#endif /* LWIP_IGMP */ + /* no outgoing network interface could be found? */ if (netif == NULL) { LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_send: No route to 0x%"X32_F"\n", pcb->remote_ip.addr)); diff --git a/src/include/lwip/udp.h b/src/include/lwip/udp.h index afc152da..cd0f33cd 100644 --- a/src/include/lwip/udp.h +++ b/src/include/lwip/udp.h @@ -77,7 +77,12 @@ struct udp_pcb { u8_t flags; /* ports are in host byte order */ u16_t local_port, remote_port; - + +#if LWIP_IGMP + /* outgoing network interface for multicast packets */ + struct ip_addr multicast_ip; +#endif /* LWIP_IGMP */ + #if LWIP_UDPLITE /* used for UDP_LITE only */ u16_t chksum_len_rx, chksum_len_tx;