diff --git a/src/core/raw.c b/src/core/raw.c index 9f911140..243333e4 100644 --- a/src/core/raw.c +++ b/src/core/raw.c @@ -68,6 +68,12 @@ static u8_t raw_input_local_match(struct raw_pcb *pcb, u8_t broadcast) { LWIP_UNUSED_ARG(broadcast); /* in IPv6 only case */ + + /* check if PCB is bound to specific netif */ + if ((pcb->netif_idx != NETIF_NO_INDEX) && + (pcb->netif_idx != netif_get_index(ip_data.current_input_netif))) { + return 0; + } #if LWIP_IPV4 && LWIP_IPV6 /* Dual-stack: PCBs listening to any IP type also listen to any IP address */ @@ -227,6 +233,25 @@ raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr) return ERR_OK; } +/** + * @ingroup raw_raw + * Bind a RAW PCB. + * + * @param pcb RAW PCB to be bound with netif. + * @param netif netif to bind to. Can be NULL. + * + * @see raw_disconnect() + */ +void +raw_bind_netif(struct raw_pcb *pcb, const struct netif *netif) +{ + if (netif != NULL) { + pcb->netif_idx = netif_get_index(netif); + } else { + pcb->netif_idx = NETIF_NO_INDEX; + } +} + /** * @ingroup raw_raw * Connect an RAW PCB. This function is required by upper layers @@ -279,6 +304,7 @@ raw_disconnect(struct raw_pcb *pcb) #if LWIP_IPV4 && LWIP_IPV6 } #endif + pcb->netif_idx = NETIF_NO_INDEX; /* mark PCB as unconnected */ pcb->flags &= ~RAW_FLAGS_CONNECTED; } @@ -325,23 +351,27 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr) LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n")); + if (pcb->netif_idx != NETIF_NO_INDEX) { + netif = netif_get_by_index(pcb->netif_idx); + } else { #if LWIP_MULTICAST_TX_OPTIONS - netif = NULL; - if (ip_addr_ismulticast(ipaddr)) { - /* For multicast-destined packets, use the user-provided interface index to - * determine the outgoing interface, if an interface index is set and a - * matching netif can be found. Otherwise, fall back to regular routing. */ - netif = netif_get_by_index(pcb->mcast_ifindex); - } + netif = NULL; + if (ip_addr_ismulticast(ipaddr)) { + /* For multicast-destined packets, use the user-provided interface index to + * determine the outgoing interface, if an interface index is set and a + * matching netif can be found. Otherwise, fall back to regular routing. */ + netif = netif_get_by_index(pcb->mcast_ifindex); + } - if (netif == NULL) + if (netif == NULL) #endif /* LWIP_MULTICAST_TX_OPTIONS */ - { - if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { - /* Don't call ip_route() with IP_ANY_TYPE */ - netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(ipaddr)), ipaddr); - } else { - netif = ip_route(&pcb->local_ip, ipaddr); + { + if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { + /* Don't call ip_route() with IP_ANY_TYPE */ + netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(ipaddr)), ipaddr); + } else { + netif = ip_route(&pcb->local_ip, ipaddr); + } } } diff --git a/src/core/tcp.c b/src/core/tcp.c index d3e03506..2b5da31f 100644 --- a/src/core/tcp.c +++ b/src/core/tcp.c @@ -546,7 +546,7 @@ tcp_abort(struct tcp_pcb *pcb) * * @param pcb the tcp_pcb to bind (no check is done whether this pcb is * already bound!) - * @param ipaddr the local ip address to bind to (use IP4_ADDR_ANY to bind + * @param ipaddr the local ip address to bind to (use IPx_ADDR_ANY to bind * to any local address * @param port the local port to bind to * @return ERR_USE if the port is already in use @@ -639,6 +639,24 @@ tcp_bind(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port)); return ERR_OK; } + +/** + * @ingroup tcp_raw + * Binds the connection to a netif and IP address. + * + * @param pcb the tcp_pcb to bind. + * @param netif the netif to bind to. Can be NULL. + */ +void +tcp_bind_netif(struct tcp_pcb *pcb, const struct netif *netif) +{ + if (netif != NULL) { + pcb->netif_idx = netif_get_index(netif); + } else { + pcb->netif_idx = NETIF_NO_INDEX; + } +} + #if LWIP_CALLBACK_API /** * Default accept callback if no accept callback is specified by the user. diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c index d154f98d..edc5f2a9 100644 --- a/src/core/tcp_in.c +++ b/src/core/tcp_in.c @@ -268,6 +268,12 @@ tcp_input(struct pbuf *p, struct netif *inp) are LISTENing for incoming connections. */ prev = NULL; for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + /* check if PCB is bound to specific netif */ + if ((pcb->netif_idx != NETIF_NO_INDEX) && + (pcb->netif_idx != netif_get_index(ip_data.current_input_netif))) { + continue; + } + if (lpcb->local_port == tcphdr->dest) { if (IP_IS_ANY_TYPE_VAL(lpcb->local_ip)) { /* found an ANY TYPE (IPv4/IPv6) match */ diff --git a/src/core/udp.c b/src/core/udp.c index e402ff35..f7b305dd 100644 --- a/src/core/udp.c +++ b/src/core/udp.c @@ -129,9 +129,14 @@ again: static u8_t udp_input_local_match(struct udp_pcb *pcb, struct netif *inp, u8_t broadcast) { - LWIP_UNUSED_ARG(inp); /* in IPv6 only case */ LWIP_UNUSED_ARG(broadcast); /* in IPv6 only case */ + /* check if PCB is bound to specific netif */ + if ((pcb->netif_idx != NETIF_NO_INDEX) && + (pcb->netif_idx != netif_get_index(ip_data.current_input_netif))) { + return 0; + } + /* Dual-stack: PCBs listening to any IP type also listen to any IP address */ if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { #if LWIP_IPV4 && IP_SOF_BROADCAST_RECV @@ -522,50 +527,54 @@ udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n")); - if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { - /* Don't call ip_route() with IP_ANY_TYPE */ - src_ip_route = IP46_ADDR_ANY(IP_GET_TYPE(dst_ip)); + if (pcb->netif_idx != NETIF_NO_INDEX) { + netif = netif_get_by_index(pcb->netif_idx); } else { - src_ip_route = &pcb->local_ip; - } - LWIP_UNUSED_ARG(src_ip_route); /* IPv4 only and no source based routing */ + if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { + /* Don't call ip_route() with IP_ANY_TYPE */ + src_ip_route = IP46_ADDR_ANY(IP_GET_TYPE(dst_ip)); + } else { + src_ip_route = &pcb->local_ip; + } + LWIP_UNUSED_ARG(src_ip_route); /* IPv4 only and no source based routing */ #if LWIP_MULTICAST_TX_OPTIONS - netif = NULL; - if (ip_addr_ismulticast(dst_ip)) { - /* For IPv6, the interface to use for packets with a multicast destination - * is specified using an interface index. The same approach may be used for - * IPv4 as well, in which case it overrides the IPv4 multicast override - * address below. Here we have to look up the netif by going through the - * list, but by doing so we skip a route lookup. If the interface index has - * gone stale, we fall through and do the regular route lookup after all. */ - if (pcb->mcast_ifindex != NETIF_NO_INDEX) { - netif = netif_get_by_index(pcb->mcast_ifindex); - } -#if LWIP_IPV4 - else -#if LWIP_IPV6 - if (IP_IS_V4(dst_ip)) -#endif /* LWIP_IPV6 */ - { - /* IPv4 does not use source-based routing by default, so we use an - administratively selected interface for multicast by default. - However, this can be overridden by setting an interface address - in pcb->mcast_ip4 that is used for routing. If this routing lookup - fails, we try regular routing as though no override was set. */ - if (!ip4_addr_isany_val(pcb->mcast_ip4) && - !ip4_addr_cmp(&pcb->mcast_ip4, IP4_ADDR_BROADCAST)) { - netif = ip4_route_src(ip_2_ip4(src_ip_route), &pcb->mcast_ip4); + netif = NULL; + if (ip_addr_ismulticast(dst_ip)) { + /* For IPv6, the interface to use for packets with a multicast destination + * is specified using an interface index. The same approach may be used for + * IPv4 as well, in which case it overrides the IPv4 multicast override + * address below. Here we have to look up the netif by going through the + * list, but by doing so we skip a route lookup. If the interface index has + * gone stale, we fall through and do the regular route lookup after all. */ + if (pcb->mcast_ifindex != NETIF_NO_INDEX) { + netif = netif_get_by_index(pcb->mcast_ifindex); + } +#if LWIP_IPV4 + else +#if LWIP_IPV6 + if (IP_IS_V4(dst_ip)) +#endif /* LWIP_IPV6 */ + { + /* IPv4 does not use source-based routing by default, so we use an + administratively selected interface for multicast by default. + However, this can be overridden by setting an interface address + in pcb->mcast_ip4 that is used for routing. If this routing lookup + fails, we try regular routing as though no override was set. */ + if (!ip4_addr_isany_val(pcb->mcast_ip4) && + !ip4_addr_cmp(&pcb->mcast_ip4, IP4_ADDR_BROADCAST)) { + netif = ip4_route_src(ip_2_ip4(src_ip_route), &pcb->mcast_ip4); + } } - } #endif /* LWIP_IPV4 */ - } + } - if (netif == NULL) + if (netif == NULL) #endif /* LWIP_MULTICAST_TX_OPTIONS */ - { - /* find the outgoing network interface for this packet */ - netif = ip_route(src_ip_route, dst_ip); + { + /* find the outgoing network interface for this packet */ + netif = ip_route(src_ip_route, dst_ip); + } } /* no outgoing network interface could be found? */ @@ -994,6 +1003,25 @@ udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) return ERR_OK; } +/** + * @ingroup udp_raw + * Bind an UDP PCB to a specific netif. + * + * @param pcb UDP PCB to be bound. + * @param netif netif to bind udp pcb to. Can be NULL. + * + * @see udp_disconnect() + */ +void +udp_bind_netif(struct udp_pcb *pcb, const struct netif *netif) +{ + if (netif != NULL) { + pcb->netif_idx = netif_get_index(netif); + } else { + pcb->netif_idx = NETIF_NO_INDEX; + } +} + /** * @ingroup udp_raw * Connect an UDP PCB. @@ -1079,6 +1107,7 @@ udp_disconnect(struct udp_pcb *pcb) } #endif pcb->remote_port = 0; + pcb->netif_idx = NETIF_NO_INDEX; /* mark PCB as unconnected */ pcb->flags &= ~UDP_FLAGS_CONNECTED; } diff --git a/src/include/lwip/ip.h b/src/include/lwip/ip.h index c9d9acf5..3c89d5b2 100644 --- a/src/include/lwip/ip.h +++ b/src/include/lwip/ip.h @@ -77,6 +77,8 @@ extern "C" { /* ip addresses in network byte order */ \ ip_addr_t local_ip; \ ip_addr_t remote_ip; \ + /* Bound netif index */ \ + u8_t netif_idx; \ /* Socket options */ \ u8_t so_options; \ /* Type Of Service */ \ diff --git a/src/include/lwip/raw.h b/src/include/lwip/raw.h index 1235986b..e701087b 100644 --- a/src/include/lwip/raw.h +++ b/src/include/lwip/raw.h @@ -105,6 +105,7 @@ struct raw_pcb * raw_new (u8_t proto); struct raw_pcb * raw_new_ip_type(u8_t type, u8_t proto); void raw_remove (struct raw_pcb *pcb); err_t raw_bind (struct raw_pcb *pcb, const ip_addr_t *ipaddr); +void raw_bind_netif (struct raw_pcb *pcb, const struct netif *netif); err_t raw_connect (struct raw_pcb *pcb, const ip_addr_t *ipaddr); void raw_disconnect (struct raw_pcb *pcb); diff --git a/src/include/lwip/tcp.h b/src/include/lwip/tcp.h index f7da50dc..9c187299 100644 --- a/src/include/lwip/tcp.h +++ b/src/include/lwip/tcp.h @@ -385,6 +385,7 @@ void tcp_backlog_accepted(struct tcp_pcb* pcb); void tcp_recved (struct tcp_pcb *pcb, u16_t len); err_t tcp_bind (struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port); +void tcp_bind_netif(struct tcp_pcb *pcb, const struct netif *netif); err_t tcp_connect (struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port, tcp_connected_fn connected); diff --git a/src/include/lwip/udp.h b/src/include/lwip/udp.h index 30cfb332..7c11c55d 100644 --- a/src/include/lwip/udp.h +++ b/src/include/lwip/udp.h @@ -121,6 +121,7 @@ struct udp_pcb * udp_new_ip_type(u8_t type); void udp_remove (struct udp_pcb *pcb); err_t udp_bind (struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port); +void udp_bind_netif (struct udp_pcb *pcb, const struct netif* netif); err_t udp_connect (struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port); void udp_disconnect (struct udp_pcb *pcb);