mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-11-19 05:10:40 +00:00
Fixed UDPLite SENDING: Checksum was always generated too short and also was generated wrong if checksum coverage != tot_len.
This commit is contained in:
parent
911ee4d9f9
commit
2ca113a218
@ -424,6 +424,10 @@ HISTORY
|
|||||||
|
|
||||||
++ Bug fixes:
|
++ Bug fixes:
|
||||||
|
|
||||||
|
2007-10-07 Simon Goldschmidt
|
||||||
|
* udp.c, inet.c, inet.h: Fixed UDPLite SENDING: Checksum was always generated
|
||||||
|
too short and also was generated wrong if checksum coverage != tot_len.
|
||||||
|
|
||||||
2007-10-07 Frédéric Bernon
|
2007-10-07 Frédéric Bernon
|
||||||
* sockets.c, api.h, api_lib.c: First step to fix "bug #20900 : Potential
|
* sockets.c, api.h, api_lib.c: First step to fix "bug #20900 : Potential
|
||||||
crash error problem with netconn_peer & netconn_addr". VERY IMPORTANT:
|
crash error problem with netconn_peer & netconn_addr". VERY IMPORTANT:
|
||||||
|
@ -294,6 +294,69 @@ inet_chksum_pseudo(struct pbuf *p,
|
|||||||
return (u16_t)~(acc & 0xffffUL);
|
return (u16_t)~(acc & 0xffffUL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* inet_chksum_pseudo:
|
||||||
|
*
|
||||||
|
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
|
||||||
|
* IP addresses are expected to be in network byte order.
|
||||||
|
*
|
||||||
|
* @param p chain of pbufs over that a checksum should be calculated (ip data part)
|
||||||
|
* @param src source ip address (used for checksum of pseudo header)
|
||||||
|
* @param dst destination ip address (used for checksum of pseudo header)
|
||||||
|
* @param proto ip protocol (used for checksum of pseudo header)
|
||||||
|
* @param proto_len length of the ip data part (used for checksum of pseudo header)
|
||||||
|
* @return checksum (as u16_t) to be saved directly in the protocol header
|
||||||
|
*/
|
||||||
|
u16_t
|
||||||
|
inet_chksum_pseudo_partial(struct pbuf *p,
|
||||||
|
struct ip_addr *src, struct ip_addr *dest,
|
||||||
|
u8_t proto, u16_t proto_len, u16_t chksum_len)
|
||||||
|
{
|
||||||
|
u32_t acc;
|
||||||
|
struct pbuf *q;
|
||||||
|
u8_t swapped;
|
||||||
|
u16_t chklen;
|
||||||
|
|
||||||
|
acc = 0;
|
||||||
|
swapped = 0;
|
||||||
|
/* iterate through all pbuf in chain */
|
||||||
|
for(q = p; (q != NULL) && (chksum_len > 0); q = q->next) {
|
||||||
|
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
|
||||||
|
(void *)q, (void *)q->next));
|
||||||
|
chklen = q->len;
|
||||||
|
if (chklen > chksum_len) {
|
||||||
|
chklen = chksum_len;
|
||||||
|
}
|
||||||
|
acc += LWIP_CHKSUM(q->payload, chklen);
|
||||||
|
chksum_len -= chklen;
|
||||||
|
LWIP_ASSERT("delete me", chksum_len < 0x7fff);
|
||||||
|
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
|
||||||
|
while ((acc >> 16) != 0) {
|
||||||
|
acc = (acc & 0xffffUL) + (acc >> 16);
|
||||||
|
}
|
||||||
|
if (q->len % 2 != 0) {
|
||||||
|
swapped = 1 - swapped;
|
||||||
|
acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
|
||||||
|
}
|
||||||
|
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
|
||||||
|
}
|
||||||
|
|
||||||
|
if (swapped) {
|
||||||
|
acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
|
||||||
|
}
|
||||||
|
acc += (src->addr & 0xffffUL);
|
||||||
|
acc += ((src->addr >> 16) & 0xffffUL);
|
||||||
|
acc += (dest->addr & 0xffffUL);
|
||||||
|
acc += ((dest->addr >> 16) & 0xffffUL);
|
||||||
|
acc += (u32_t)htons((u16_t)proto);
|
||||||
|
acc += (u32_t)htons(proto_len);
|
||||||
|
|
||||||
|
while ((acc >> 16) != 0) {
|
||||||
|
acc = (acc & 0xffffUL) + (acc >> 16);
|
||||||
|
}
|
||||||
|
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
|
||||||
|
return (u16_t)~(acc & 0xffffUL);
|
||||||
|
}
|
||||||
|
|
||||||
/* inet_chksum:
|
/* inet_chksum:
|
||||||
*
|
*
|
||||||
* Calculates the Internet checksum over a portion of memory. Used primarily for IP
|
* Calculates the Internet checksum over a portion of memory. Used primarily for IP
|
||||||
|
@ -39,10 +39,13 @@
|
|||||||
|
|
||||||
/* udp.c
|
/* udp.c
|
||||||
*
|
*
|
||||||
* The code for the User Datagram Protocol UDP.
|
* The code for the User Datagram Protocol UDP & UDPLite (RFC 3828).
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* @todo Check the use of '(struct udp_pcb).chksum_len_rx'!
|
||||||
|
*/
|
||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */
|
#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */
|
||||||
@ -425,11 +428,11 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
|||||||
#if LWIP_UDPLITE
|
#if LWIP_UDPLITE
|
||||||
/* UDP Lite protocol? */
|
/* UDP Lite protocol? */
|
||||||
if (pcb->flags & UDP_FLAGS_UDPLITE) {
|
if (pcb->flags & UDP_FLAGS_UDPLITE) {
|
||||||
u16_t chklen;
|
u16_t chklen, chklen_hdr;
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len));
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len));
|
||||||
/* set UDP message length in UDP header */
|
/* set UDP message length in UDP header */
|
||||||
chklen = pcb->chksum_len_rx;
|
chklen_hdr = chklen = pcb->chksum_len_tx;
|
||||||
if (chklen < sizeof(struct udp_hdr)) {
|
if ((chklen < sizeof(struct udp_hdr)) || (chklen > q->tot_len)) {
|
||||||
if (chklen != 0) {
|
if (chklen != 0) {
|
||||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE pcb->chksum_len is illegal: %"U16_F"\n", chklen));
|
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE pcb->chksum_len is illegal: %"U16_F"\n", chklen));
|
||||||
}
|
}
|
||||||
@ -439,13 +442,14 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
|||||||
checksum, therefore, if chksum_len has an illegal
|
checksum, therefore, if chksum_len has an illegal
|
||||||
value, we generate the checksum over the complete
|
value, we generate the checksum over the complete
|
||||||
packet to be safe. */
|
packet to be safe. */
|
||||||
chklen = p->tot_len;
|
chklen_hdr = 0;
|
||||||
|
chklen = q->tot_len;
|
||||||
}
|
}
|
||||||
udphdr->len = htons(chklen);
|
udphdr->len = htons(chklen_hdr);
|
||||||
/* calculate checksum */
|
/* calculate checksum */
|
||||||
#if CHECKSUM_GEN_UDP
|
#if CHECKSUM_GEN_UDP
|
||||||
udphdr->chksum = inet_chksum_pseudo(q, src_ip, &(pcb->remote_ip),
|
udphdr->chksum = inet_chksum_pseudo_partial(q, src_ip, &(pcb->remote_ip),
|
||||||
IP_PROTO_UDP, chklen);
|
IP_PROTO_UDPLITE, q->tot_len, chklen);
|
||||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||||
if (udphdr->chksum == 0x0000)
|
if (udphdr->chksum == 0x0000)
|
||||||
udphdr->chksum = 0xffff;
|
udphdr->chksum = 0xffff;
|
||||||
|
@ -49,6 +49,9 @@ u16_t inet_chksum_pbuf(struct pbuf *p);
|
|||||||
u16_t inet_chksum_pseudo(struct pbuf *p,
|
u16_t inet_chksum_pseudo(struct pbuf *p,
|
||||||
struct ip_addr *src, struct ip_addr *dest,
|
struct ip_addr *src, struct ip_addr *dest,
|
||||||
u8_t proto, u16_t proto_len);
|
u8_t proto, u16_t proto_len);
|
||||||
|
u16_t inet_chksum_pseudo_partial(struct pbuf *p,
|
||||||
|
struct ip_addr *src, struct ip_addr *dest,
|
||||||
|
u8_t proto, u16_t proto_len, u16_t chksum_len);
|
||||||
|
|
||||||
u32_t inet_addr(const char *cp);
|
u32_t inet_addr(const char *cp);
|
||||||
int inet_aton(const char *cp, struct in_addr *addr);
|
int inet_aton(const char *cp, struct in_addr *addr);
|
||||||
|
Loading…
Reference in New Issue
Block a user