Start working task #14494: Implement SO_BINDTODEVICE

Implement binding TCP, UDP and RAW PCBs to a netif
This commit is contained in:
Dirk Ziegelmeier 2017-05-02 09:39:48 +02:00
parent 20fed63297
commit 13ffc86aef
8 changed files with 141 additions and 53 deletions

View File

@ -68,6 +68,12 @@ static u8_t
raw_input_local_match(struct raw_pcb *pcb, u8_t broadcast) raw_input_local_match(struct raw_pcb *pcb, u8_t broadcast)
{ {
LWIP_UNUSED_ARG(broadcast); /* 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;
}
#if LWIP_IPV4 && LWIP_IPV6 #if LWIP_IPV4 && LWIP_IPV6
/* Dual-stack: PCBs listening to any IP type also listen to any IP address */ /* 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; 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 * @ingroup raw_raw
* Connect an RAW PCB. This function is required by upper layers * 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 #if LWIP_IPV4 && LWIP_IPV6
} }
#endif #endif
pcb->netif_idx = NETIF_NO_INDEX;
/* mark PCB as unconnected */ /* mark PCB as unconnected */
pcb->flags &= ~RAW_FLAGS_CONNECTED; 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")); 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 #if LWIP_MULTICAST_TX_OPTIONS
netif = NULL; netif = NULL;
if (ip_addr_ismulticast(ipaddr)) { if (ip_addr_ismulticast(ipaddr)) {
/* For multicast-destined packets, use the user-provided interface index to /* For multicast-destined packets, use the user-provided interface index to
* determine the outgoing interface, if an interface index is set and a * determine the outgoing interface, if an interface index is set and a
* matching netif can be found. Otherwise, fall back to regular routing. */ * matching netif can be found. Otherwise, fall back to regular routing. */
netif = netif_get_by_index(pcb->mcast_ifindex); netif = netif_get_by_index(pcb->mcast_ifindex);
} }
if (netif == NULL) if (netif == NULL)
#endif /* LWIP_MULTICAST_TX_OPTIONS */ #endif /* LWIP_MULTICAST_TX_OPTIONS */
{ {
if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) {
/* Don't call ip_route() with IP_ANY_TYPE */ /* Don't call ip_route() with IP_ANY_TYPE */
netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(ipaddr)), ipaddr); netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(ipaddr)), ipaddr);
} else { } else {
netif = ip_route(&pcb->local_ip, ipaddr); netif = ip_route(&pcb->local_ip, ipaddr);
}
} }
} }

View File

@ -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 * @param pcb the tcp_pcb to bind (no check is done whether this pcb is
* already bound!) * 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 * to any local address
* @param port the local port to bind to * @param port the local port to bind to
* @return ERR_USE if the port is already in use * @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)); LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port));
return ERR_OK; 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 #if LWIP_CALLBACK_API
/** /**
* Default accept callback if no accept callback is specified by the user. * Default accept callback if no accept callback is specified by the user.

View File

@ -268,6 +268,12 @@ tcp_input(struct pbuf *p, struct netif *inp)
are LISTENing for incoming connections. */ are LISTENing for incoming connections. */
prev = NULL; prev = NULL;
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { 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 (lpcb->local_port == tcphdr->dest) {
if (IP_IS_ANY_TYPE_VAL(lpcb->local_ip)) { if (IP_IS_ANY_TYPE_VAL(lpcb->local_ip)) {
/* found an ANY TYPE (IPv4/IPv6) match */ /* found an ANY TYPE (IPv4/IPv6) match */

View File

@ -129,9 +129,14 @@ again:
static u8_t static u8_t
udp_input_local_match(struct udp_pcb *pcb, struct netif *inp, u8_t broadcast) 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 */ 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 */ /* Dual-stack: PCBs listening to any IP type also listen to any IP address */
if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) {
#if LWIP_IPV4 && IP_SOF_BROADCAST_RECV #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")); LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n"));
if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { if (pcb->netif_idx != NETIF_NO_INDEX) {
/* Don't call ip_route() with IP_ANY_TYPE */ netif = netif_get_by_index(pcb->netif_idx);
src_ip_route = IP46_ADDR_ANY(IP_GET_TYPE(dst_ip));
} else { } else {
src_ip_route = &pcb->local_ip; if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) {
} /* Don't call ip_route() with IP_ANY_TYPE */
LWIP_UNUSED_ARG(src_ip_route); /* IPv4 only and no source based routing */ 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 #if LWIP_MULTICAST_TX_OPTIONS
netif = NULL; netif = NULL;
if (ip_addr_ismulticast(dst_ip)) { if (ip_addr_ismulticast(dst_ip)) {
/* For IPv6, the interface to use for packets with a multicast destination /* 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 * 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 * 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 * 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 * 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. */ * gone stale, we fall through and do the regular route lookup after all. */
if (pcb->mcast_ifindex != NETIF_NO_INDEX) { if (pcb->mcast_ifindex != NETIF_NO_INDEX) {
netif = netif_get_by_index(pcb->mcast_ifindex); netif = netif_get_by_index(pcb->mcast_ifindex);
} }
#if LWIP_IPV4 #if LWIP_IPV4
else else
#if LWIP_IPV6 #if LWIP_IPV6
if (IP_IS_V4(dst_ip)) if (IP_IS_V4(dst_ip))
#endif /* LWIP_IPV6 */ #endif /* LWIP_IPV6 */
{ {
/* IPv4 does not use source-based routing by default, so we use an /* IPv4 does not use source-based routing by default, so we use an
administratively selected interface for multicast by default. administratively selected interface for multicast by default.
However, this can be overridden by setting an interface address However, this can be overridden by setting an interface address
in pcb->mcast_ip4 that is used for routing. If this routing lookup in pcb->mcast_ip4 that is used for routing. If this routing lookup
fails, we try regular routing as though no override was set. */ fails, we try regular routing as though no override was set. */
if (!ip4_addr_isany_val(pcb->mcast_ip4) && if (!ip4_addr_isany_val(pcb->mcast_ip4) &&
!ip4_addr_cmp(&pcb->mcast_ip4, IP4_ADDR_BROADCAST)) { !ip4_addr_cmp(&pcb->mcast_ip4, IP4_ADDR_BROADCAST)) {
netif = ip4_route_src(ip_2_ip4(src_ip_route), &pcb->mcast_ip4); netif = ip4_route_src(ip_2_ip4(src_ip_route), &pcb->mcast_ip4);
}
} }
}
#endif /* LWIP_IPV4 */ #endif /* LWIP_IPV4 */
} }
if (netif == NULL) if (netif == NULL)
#endif /* LWIP_MULTICAST_TX_OPTIONS */ #endif /* LWIP_MULTICAST_TX_OPTIONS */
{ {
/* find the outgoing network interface for this packet */ /* find the outgoing network interface for this packet */
netif = ip_route(src_ip_route, dst_ip); netif = ip_route(src_ip_route, dst_ip);
}
} }
/* no outgoing network interface could be found? */ /* 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; 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 * @ingroup udp_raw
* Connect an UDP PCB. * Connect an UDP PCB.
@ -1079,6 +1107,7 @@ udp_disconnect(struct udp_pcb *pcb)
} }
#endif #endif
pcb->remote_port = 0; pcb->remote_port = 0;
pcb->netif_idx = NETIF_NO_INDEX;
/* mark PCB as unconnected */ /* mark PCB as unconnected */
pcb->flags &= ~UDP_FLAGS_CONNECTED; pcb->flags &= ~UDP_FLAGS_CONNECTED;
} }

View File

@ -77,6 +77,8 @@ extern "C" {
/* ip addresses in network byte order */ \ /* ip addresses in network byte order */ \
ip_addr_t local_ip; \ ip_addr_t local_ip; \
ip_addr_t remote_ip; \ ip_addr_t remote_ip; \
/* Bound netif index */ \
u8_t netif_idx; \
/* Socket options */ \ /* Socket options */ \
u8_t so_options; \ u8_t so_options; \
/* Type Of Service */ \ /* Type Of Service */ \

View File

@ -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); struct raw_pcb * raw_new_ip_type(u8_t type, u8_t proto);
void raw_remove (struct raw_pcb *pcb); void raw_remove (struct raw_pcb *pcb);
err_t raw_bind (struct raw_pcb *pcb, const ip_addr_t *ipaddr); 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); err_t raw_connect (struct raw_pcb *pcb, const ip_addr_t *ipaddr);
void raw_disconnect (struct raw_pcb *pcb); void raw_disconnect (struct raw_pcb *pcb);

View File

@ -385,6 +385,7 @@ void tcp_backlog_accepted(struct tcp_pcb* pcb);
void tcp_recved (struct tcp_pcb *pcb, u16_t len); void tcp_recved (struct tcp_pcb *pcb, u16_t len);
err_t tcp_bind (struct tcp_pcb *pcb, const ip_addr_t *ipaddr, err_t tcp_bind (struct tcp_pcb *pcb, const ip_addr_t *ipaddr,
u16_t port); 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, err_t tcp_connect (struct tcp_pcb *pcb, const ip_addr_t *ipaddr,
u16_t port, tcp_connected_fn connected); u16_t port, tcp_connected_fn connected);

View File

@ -121,6 +121,7 @@ struct udp_pcb * udp_new_ip_type(u8_t type);
void udp_remove (struct udp_pcb *pcb); void udp_remove (struct udp_pcb *pcb);
err_t udp_bind (struct udp_pcb *pcb, const ip_addr_t *ipaddr, err_t udp_bind (struct udp_pcb *pcb, const ip_addr_t *ipaddr,
u16_t port); 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, err_t udp_connect (struct udp_pcb *pcb, const ip_addr_t *ipaddr,
u16_t port); u16_t port);
void udp_disconnect (struct udp_pcb *pcb); void udp_disconnect (struct udp_pcb *pcb);