Implemented new function udp_sendto_if which takes the netif to send as an argument (to be able to send on netifs that are down).

This commit is contained in:
goldsimon 2007-11-27 20:13:16 +00:00
parent 3874f5f5e8
commit b4741332e0
4 changed files with 93 additions and 81 deletions

View File

@ -499,6 +499,10 @@ HISTORY
++ Bug fixes:
2007-11-27 Simon Goldschmidt
* udp.h, udp.c, dhcp.c: Implemented new function udp_sendto_if which takes the
netif to send as an argument (to be able to send on netifs that are down).
2007-11-26 Simon Goldschmidt
* tcp_in.c: Fixed bug #21582: pcb->acked accounting can be wrong when ACKs
arrive out-of-order

View File

@ -269,10 +269,8 @@ dhcp_select(struct netif *netif)
/* TODO: we really should bind to a specific local interface here
but we cannot specify an unconfigured netif as it is addressless */
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
/* send broadcast to any DHCP server */
udp_connect(dhcp->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
udp_send(dhcp->pcb, dhcp->p_out);
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
/* reconnect to any (or to server here?!) */
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
dhcp_delete_request(netif);
@ -589,6 +587,11 @@ dhcp_start(struct netif *netif)
netif->dhcp = dhcp = NULL;
return ERR_MEM;
}
/* set up local and remote port for the pcb */
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
/* set up the recv callback and argument */
udp_recv(dhcp->pcb, dhcp_recv, netif);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n"));
/* (re)start the DHCP negotiation */
result = dhcp_discover(netif);
@ -613,7 +616,7 @@ dhcp_start(struct netif *netif)
void
dhcp_inform(struct netif *netif)
{
struct dhcp *dhcp;
struct dhcp *dhcp, *old_dhcp = netif->dhcp;
err_t result = ERR_OK;
dhcp = mem_malloc(sizeof(struct dhcp));
if (dhcp == NULL) {
@ -649,7 +652,7 @@ dhcp_inform(struct netif *netif)
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
udp_connect(dhcp->pcb, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n"));
udp_send(dhcp->pcb, dhcp->p_out);
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
dhcp_delete_request(netif);
} else {
@ -662,7 +665,7 @@ dhcp_inform(struct netif *netif)
}
dhcp->pcb = NULL;
mem_free((void *)dhcp);
netif->dhcp = NULL;
netif->dhcp = old_dhcp;
}
}
@ -723,11 +726,10 @@ dhcp_decline(struct netif *netif)
/* resize pbuf to reflect true size of options */
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
/* @todo: should we really connect here? we are performing sendto() */
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
/* per section 4.4.4, broadcast DECLINE messages */
udp_sendto(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
dhcp_delete_request(netif);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n"));
} else {
@ -776,12 +778,9 @@ dhcp_discover(struct netif *netif)
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: realloc()ing\n"));
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
/* set receive callback function with netif as user data */
udp_recv(dhcp->pcb, dhcp_recv, netif);
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n"));
udp_sendto(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n"));
dhcp_delete_request(netif);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n"));
@ -924,9 +923,8 @@ dhcp_renew(struct netif *netif)
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
udp_send(dhcp->pcb, dhcp->p_out);
udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif);
dhcp_delete_request(netif);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew: RENEWING\n"));
@ -977,11 +975,9 @@ dhcp_rebind(struct netif *netif)
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
/* set remote IP association to any DHCP server */
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
/* broadcast to server */
udp_sendto(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT);
udp_connect(dhcp->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
udp_sendto_if(dhcp->pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif);
dhcp_delete_request(netif);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind: REBINDING\n"));
} else {
@ -1026,9 +1022,8 @@ dhcp_release(struct netif *netif)
pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len);
udp_bind(dhcp->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
udp_connect(dhcp->pcb, &dhcp->server_ip_addr, DHCP_SERVER_PORT);
udp_send(dhcp->pcb, dhcp->p_out);
udp_sendto_if(dhcp->pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif);
dhcp_delete_request(netif);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_OFF\n"));
} else {

View File

@ -273,45 +273,6 @@ end:
PERF_STOP("udp_input");
}
/**
* Send data to a specified address using UDP.
*
* @param pcb UDP PCB used to send the data.
* @param p chain of pbuf's to be sent.
* @param dst_ip Destination IP address.
* @param dst_port Destination UDP port.
*
* dst_ip & dst_port are expected to be in the same byte order as in the pcb.
*
* If the PCB already has a remote address association, it will
* be restored after the data is sent.
*
* @return lwIP error code (@see udp_send for possible error codes)
*
* @see udp_disconnect() udp_send()
*/
err_t
udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
struct ip_addr *dst_ip, u16_t dst_port)
{
err_t err;
/* temporary space for current PCB remote address */
struct ip_addr pcb_remote_ip;
u16_t pcb_remote_port;
/* remember current remote peer address of PCB */
pcb_remote_ip.addr = pcb->remote_ip.addr;
pcb_remote_port = pcb->remote_port;
/* copy packet destination address to PCB remote peer address */
pcb->remote_ip.addr = dst_ip->addr;
pcb->remote_port = dst_port;
/* send to the packet destination address */
err = udp_send(pcb, p);
/* restore PCB remote peer address */
pcb->remote_ip.addr = pcb_remote_ip.addr;
pcb->remote_port = pcb_remote_port;
return err;
}
/**
* Send data using UDP.
*
@ -333,14 +294,79 @@ udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
err_t
udp_send(struct udp_pcb *pcb, struct pbuf *p)
{
struct udp_hdr *udphdr;
/* send to the packet using remote ip and port stored in the pcb */
return udp_sendto(pcb, p, &pcb->remote_ip, pcb->remote_port);
}
/**
* Send data to a specified address using UDP.
*
* @param pcb UDP PCB used to send the data.
* @param p chain of pbuf's to be sent.
* @param dst_ip Destination IP address.
* @param dst_port Destination UDP port.
*
* dst_ip & dst_port are expected to be in the same byte order as in the pcb.
*
* If the PCB already has a remote address association, it will
* be restored after the data is sent.
*
* @return lwIP error code (@see udp_send for possible error codes)
*
* @see udp_disconnect() udp_send()
*/
err_t
udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
struct ip_addr *dst_ip, u16_t dst_port)
{
struct netif *netif;
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | 3, ("udp_send\n"));
/* find the outgoing network interface for this packet */
#if LWIP_IGMP
netif = ip_route((ip_addr_ismulticast(dst_ip))?(&(pcb->multicast_ip)):(dst_ip));
#else
netif = ip_route(dst_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", dst_ip->addr));
UDP_STATS_INC(udp.rterr);
return ERR_RTE;
}
return udp_sendto_if(pcb, p, dst_ip, dst_port, netif);
}
/**
* Send data to a specified address using UDP.
* The netif used for sending can be specified.
*
* This function exists mainly for DHCP, to be able to send UDP packets
* on a netif that is still down.
*
* @param pcb UDP PCB used to send the data.
* @param p chain of pbuf's to be sent.
* @param dst_ip Destination IP address.
* @param dst_port Destination UDP port.
* @param netif the netif used for sending.
*
* dst_ip & dst_port are expected to be in the same byte order as in the pcb.
*
* @return lwIP error code (@see udp_send for possible error codes)
*
* @see udp_disconnect() udp_send()
*/
err_t
udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
struct ip_addr *dst_ip, u16_t dst_port, struct netif *netif)
{
struct udp_hdr *udphdr;
struct ip_addr *src_ip;
err_t err;
struct pbuf *q; /* q will be sent down the stack */
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | 3, ("udp_send\n"));
/* if the PCB is not yet bound to a port, bind it here */
if (pcb->local_port == 0) {
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | 2, ("udp_send: not yet bound to a port, binding now\n"));
@ -351,20 +377,6 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
}
}
/* 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));
UDP_STATS_INC(udp.rterr);
return ERR_RTE;
}
/* not enough space to add an UDP header to first pbuf in given p chain? */
if (pbuf_header(p, UDP_HLEN)) {
/* allocate header in a seperate new pbuf */
@ -390,7 +402,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
/* q now represents the packet to be sent */
udphdr = q->payload;
udphdr->src = htons(pcb->local_port);
udphdr->dest = htons(pcb->remote_port);
udphdr->dest = htons(dst_port);
/* in UDP, 0 checksum means 'no checksum' */
udphdr->chksum = 0x0000;
@ -440,7 +452,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
udphdr->len = htons(chklen_hdr);
/* calculate checksum */
#if CHECKSUM_GEN_UDP
udphdr->chksum = inet_chksum_pseudo_partial(q, src_ip, &(pcb->remote_ip),
udphdr->chksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip,
IP_PROTO_UDPLITE, q->tot_len, chklen);
/* chksum zero must become 0xffff, as zero means 'no checksum' */
if (udphdr->chksum == 0x0000)
@ -451,7 +463,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
#if LWIP_NETIF_HWADDRHINT
netif->addr_hint = &(pcb->addr_hint);
#endif /* LWIP_NETIF_HWADDRHINT*/
err = ip_output_if(q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
#if LWIP_NETIF_HWADDRHINT
netif->addr_hint = NULL;
#endif /* LWIP_NETIF_HWADDRHINT*/
@ -463,7 +475,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
/* calculate checksum */
#if CHECKSUM_GEN_UDP
if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
udphdr->chksum = inet_chksum_pseudo(q, src_ip, &pcb->remote_ip, IP_PROTO_UDP, q->tot_len);
udphdr->chksum = inet_chksum_pseudo(q, src_ip, dst_ip, IP_PROTO_UDP, q->tot_len);
/* chksum zero must become 0xffff, as zero means 'no checksum' */
if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
}
@ -474,7 +486,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
#if LWIP_NETIF_HWADDRHINT
netif->addr_hint = &(pcb->addr_hint);
#endif /* LWIP_NETIF_HWADDRHINT*/
err = ip_output_if(q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
#if LWIP_NETIF_HWADDRHINT
netif->addr_hint = NULL;
#endif /* LWIP_NETIF_HWADDRHINT*/

View File

@ -123,6 +123,7 @@ void udp_recv (struct udp_pcb *pcb,
struct ip_addr *addr,
u16_t port),
void *recv_arg);
err_t udp_sendto_if (struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *dst_ip, u16_t dst_port, struct netif *netif);
err_t udp_sendto (struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *dst_ip, u16_t dst_port);
err_t udp_send (struct udp_pcb *pcb, struct pbuf *p);