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)
{
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);
}
}
}

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
* 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.

View File

@ -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 */

View File

@ -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;
}

View File

@ -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 */ \

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);
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);

View File

@ -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);

View File

@ -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);