diff --git a/src/api/api_lib.c b/src/api/api_lib.c index f93a9b78..9076a1db 100644 --- a/src/api/api_lib.c +++ b/src/api/api_lib.c @@ -1129,6 +1129,48 @@ netconn_join_leave_group(struct netconn *conn, return err; } +/** + * @ingroup netconn_udp + * Join multicast groups for UDP netconns. + * + * @param conn the UDP netconn for which to change multicast addresses + * @param multiaddr IP address of the multicast group to join or leave + * @param if_idx the index of the netif + * @param join_or_leave flag whether to send a join- or leave-message + * @return ERR_OK if the action was taken, any err_t on error + */ +err_t +netconn_join_leave_group_netif(struct netconn *conn, + const ip_addr_t *multiaddr, + u8_t if_idx, + enum netconn_igmp join_or_leave) +{ + API_MSG_VAR_DECLARE(msg); + err_t err; + + LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;); + + API_MSG_VAR_ALLOC(msg); + +#if LWIP_IPV4 + /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ + if (multiaddr == NULL) { + multiaddr = IP4_ADDR_ANY; + } + if (if_idx == NETIF_NO_INDEX) { + return ERR_IF; + } +#endif /* LWIP_IPV4 */ + + API_MSG_VAR_REF(msg).conn = conn; + API_MSG_VAR_REF(msg).msg.jl.multiaddr = API_MSG_VAR_REF(multiaddr); + API_MSG_VAR_REF(msg).msg.jl.if_idx = if_idx; + API_MSG_VAR_REF(msg).msg.jl.join_or_leave = join_or_leave; + err = netconn_apimsg(lwip_netconn_do_join_leave_group_netif, &API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); + + return err; +} #endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ #if LWIP_DNS diff --git a/src/api/api_msg.c b/src/api/api_msg.c index 09e91ec8..5d432d10 100644 --- a/src/api/api_msg.c +++ b/src/api/api_msg.c @@ -1995,6 +1995,67 @@ lwip_netconn_do_join_leave_group(void *m) } TCPIP_APIMSG_ACK(msg); } +/** + * Join multicast groups for UDP netconns. + * Called from netconn_join_leave_group_netif + * + * @param m the api_msg pointing to the connection + */ +void +lwip_netconn_do_join_leave_group_netif(void *m) +{ + struct api_msg *msg = (struct api_msg*)m; + struct netif *netif; + + if (msg->msg.jl.if_idx == NETIF_NO_INDEX) { + msg->err = ERR_IF; + goto done; + } + + netif = netif_get_by_index(msg->msg.jl.if_idx); + if (netif == NULL) { + msg->err = ERR_IF; + goto done; + } + + msg->err = ERR_CONN; + if (msg->conn->pcb.tcp != NULL) { + if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { +#if LWIP_UDP +#if LWIP_IPV6 && LWIP_IPV6_MLD + if (NETCONNTYPE_ISIPV6(msg->conn->type)) { + if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { + msg->err = mld6_joingroup_netif(netif, + ip_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr))); + } else { + msg->err = mld6_leavegroup_netif(netif, + ip_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr))); + } + } + else +#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + { +#if LWIP_IGMP + if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { + msg->err = igmp_joingroup_netif(netif, + ip_2_ip4(API_EXPR_REF(msg->msg.jl.multiaddr))); + } else { + msg->err = igmp_leavegroup_netif(netif, + ip_2_ip4(API_EXPR_REF(msg->msg.jl.multiaddr))); + } +#endif /* LWIP_IGMP */ + } +#endif /* LWIP_UDP */ +#if (LWIP_TCP || LWIP_RAW) + } else { + msg->err = ERR_VAL; +#endif /* (LWIP_TCP || LWIP_RAW) */ + } + } + +done: + TCPIP_APIMSG_ACK(msg); +} #endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ #if LWIP_DNS diff --git a/src/include/lwip/api.h b/src/include/lwip/api.h index 7e187697..f6175ff0 100644 --- a/src/include/lwip/api.h +++ b/src/include/lwip/api.h @@ -341,6 +341,8 @@ err_t netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx); #if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) err_t netconn_join_leave_group(struct netconn *conn, const ip_addr_t *multiaddr, const ip_addr_t *netif_addr, enum netconn_igmp join_or_leave); +err_t netconn_join_leave_group_netif(struct netconn *conn, const ip_addr_t *multiaddr, + u8_t if_idx, enum netconn_igmp join_or_leave); #endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ #if LWIP_DNS #if LWIP_IPV4 && LWIP_IPV6 diff --git a/src/include/lwip/priv/api_msg.h b/src/include/lwip/priv/api_msg.h index f29c5a8e..a64e4c31 100644 --- a/src/include/lwip/priv/api_msg.h +++ b/src/include/lwip/priv/api_msg.h @@ -139,6 +139,7 @@ struct api_msg { struct { API_MSG_M_DEF_C(ip_addr_t, multiaddr); API_MSG_M_DEF_C(ip_addr_t, netif_addr); + u8_t if_idx; enum netconn_igmp join_or_leave; } jl; #endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ @@ -205,6 +206,7 @@ void lwip_netconn_do_close (void *m); void lwip_netconn_do_shutdown (void *m); #if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) void lwip_netconn_do_join_leave_group(void *m); +void lwip_netconn_do_join_leave_group_netif(void *m); #endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ #if LWIP_DNS