102 |
dest = ntohs(udphdr->dest); |
dest = ntohs(udphdr->dest); |
103 |
|
|
104 |
pcb = pcb_cache; |
pcb = pcb_cache; |
105 |
if(pcb != NULL && |
if (pcb != NULL && |
106 |
pcb->remote_port == src && |
pcb->remote_port == src && |
107 |
pcb->local_port == dest && |
pcb->local_port == dest && |
108 |
(ip_addr_isany(&pcb->remote_ip) || |
(ip_addr_isany(&pcb->remote_ip) || |
113 |
} |
} |
114 |
else { |
else { |
115 |
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { |
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { |
116 |
if(pcb->remote_port == src && |
if (pcb->remote_port == src && |
117 |
pcb->local_port == dest && |
pcb->local_port == dest && |
118 |
(ip_addr_isany(&pcb->remote_ip) || |
(ip_addr_isany(&pcb->remote_ip) || |
119 |
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) && |
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) && |
124 |
} |
} |
125 |
} |
} |
126 |
|
|
127 |
if(pcb == NULL) { |
if (pcb == NULL) { |
128 |
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { |
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { |
129 |
if(pcb->remote_port == 0 && |
if (pcb->remote_port == 0 && |
130 |
pcb->local_port == dest && |
pcb->local_port == dest && |
131 |
(ip_addr_isany(&pcb->remote_ip) || |
(ip_addr_isany(&pcb->remote_ip) || |
132 |
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) && |
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) && |
140 |
|
|
141 |
PERF_STOP("udp_lookup"); |
PERF_STOP("udp_lookup"); |
142 |
|
|
143 |
if(pcb != NULL) { |
if (pcb != NULL) { |
144 |
return 1; |
return 1; |
145 |
} |
} |
146 |
else { |
else { |
204 |
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port)); |
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port)); |
205 |
|
|
206 |
/* PCB remote port matches UDP source port? */ |
/* PCB remote port matches UDP source port? */ |
207 |
if((pcb->remote_port == src) && |
if ((pcb->remote_port == src) && |
208 |
/* PCB local port matches UDP destination port? */ |
/* PCB local port matches UDP destination port? */ |
209 |
(pcb->local_port == dest) && |
(pcb->local_port == dest) && |
210 |
/* accepting from any remote (source) IP address? or... */ |
/* accepting from any remote (source) IP address? or... */ |
229 |
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip), |
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip), |
230 |
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port)); |
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port)); |
231 |
/* unconnected? */ |
/* unconnected? */ |
232 |
if(((pcb->flags & UDP_FLAGS_CONNECTED) == 0) && |
if (((pcb->flags & UDP_FLAGS_CONNECTED) == 0) && |
233 |
/* destination port matches? */ |
/* destination port matches? */ |
234 |
(pcb->local_port == dest) && |
(pcb->local_port == dest) && |
235 |
/* not bound to a specific (local) interface address? or... */ |
/* not bound to a specific (local) interface address? or... */ |
242 |
} |
} |
243 |
|
|
244 |
/* Check checksum if this is a match or if it was directed at us. */ |
/* Check checksum if this is a match or if it was directed at us. */ |
245 |
if(pcb != NULL || ip_addr_cmp(&inp->ip_addr, &iphdr->dest)) |
if (pcb != NULL || ip_addr_cmp(&inp->ip_addr, &iphdr->dest)) |
246 |
{ |
{ |
247 |
DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: calculating checksum\n")); |
DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: calculating checksum\n")); |
248 |
pbuf_header(p, UDP_HLEN); |
pbuf_header(p, UDP_HLEN); |
249 |
#ifdef IPv6 |
#ifdef IPv6 |
250 |
if(iphdr->nexthdr == IP_PROTO_UDPLITE) { |
if (iphdr->nexthdr == IP_PROTO_UDPLITE) { |
251 |
#else |
#else |
252 |
if(IPH_PROTO(iphdr) == IP_PROTO_UDPLITE) { |
if (IPH_PROTO(iphdr) == IP_PROTO_UDPLITE) { |
253 |
#endif /* IPv4 */ |
#endif /* IPv4 */ |
254 |
/* Do the UDP Lite checksum */ |
/* Do the UDP Lite checksum */ |
255 |
if(inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), |
if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), |
256 |
(struct ip_addr *)&(iphdr->dest), |
(struct ip_addr *)&(iphdr->dest), |
257 |
IP_PROTO_UDPLITE, ntohs(udphdr->len)) != 0) { |
IP_PROTO_UDPLITE, ntohs(udphdr->len)) != 0) { |
258 |
DEBUGF(UDP_DEBUG | 2, ("udp_input: UDP Lite datagram discarded due to failing checksum\n")); |
DEBUGF(UDP_DEBUG | 2, ("udp_input: UDP Lite datagram discarded due to failing checksum\n")); |
265 |
goto end; |
goto end; |
266 |
} |
} |
267 |
} else { |
} else { |
268 |
if(udphdr->chksum != 0) { |
if (udphdr->chksum != 0) { |
269 |
if(inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), |
if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), |
270 |
(struct ip_addr *)&(iphdr->dest), |
(struct ip_addr *)&(iphdr->dest), |
271 |
IP_PROTO_UDP, p->tot_len) != 0) { |
IP_PROTO_UDP, p->tot_len) != 0) { |
272 |
DEBUGF(UDP_DEBUG | 2, ("udp_input: UDP datagram discarded due to failing checksum\n")); |
DEBUGF(UDP_DEBUG | 2, ("udp_input: UDP datagram discarded due to failing checksum\n")); |
282 |
} |
} |
283 |
} |
} |
284 |
pbuf_header(p, -UDP_HLEN); |
pbuf_header(p, -UDP_HLEN); |
285 |
if(pcb != NULL) { |
if (pcb != NULL) { |
286 |
snmp_inc_udpindatagrams(); |
snmp_inc_udpindatagrams(); |
287 |
pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src); |
pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src); |
288 |
} else { |
} else { |
291 |
/* No match was found, send ICMP destination port unreachable unless |
/* No match was found, send ICMP destination port unreachable unless |
292 |
destination address was broadcast/multicast. */ |
destination address was broadcast/multicast. */ |
293 |
|
|
294 |
if(!ip_addr_isbroadcast(&iphdr->dest, &inp->netmask) && |
if (!ip_addr_isbroadcast(&iphdr->dest, &inp->netmask) && |
295 |
!ip_addr_ismulticast(&iphdr->dest)) { |
!ip_addr_ismulticast(&iphdr->dest)) { |
296 |
|
|
297 |
/* adjust pbuf pointer */ |
/* adjust pbuf pointer */ |
371 |
udphdr->dest = htons(pcb->remote_port); |
udphdr->dest = htons(pcb->remote_port); |
372 |
udphdr->chksum = 0x0000; |
udphdr->chksum = 0x0000; |
373 |
|
|
374 |
if((netif = ip_route(&(pcb->remote_ip))) == NULL) { |
if ((netif = ip_route(&(pcb->remote_ip))) == NULL) { |
375 |
DEBUGF(UDP_DEBUG | 1, ("udp_send: No route to 0x%lx\n", pcb->remote_ip.addr)); |
DEBUGF(UDP_DEBUG | 1, ("udp_send: No route to 0x%lx\n", pcb->remote_ip.addr)); |
376 |
#ifdef UDP_STATS |
#ifdef UDP_STATS |
377 |
++lwip_stats.udp.rterr; |
++lwip_stats.udp.rterr; |
379 |
return ERR_RTE; |
return ERR_RTE; |
380 |
} |
} |
381 |
/* using IP_ANY_ADDR? */ |
/* using IP_ANY_ADDR? */ |
382 |
if(ip_addr_isany(&pcb->local_ip)) { |
if (ip_addr_isany(&pcb->local_ip)) { |
383 |
/* use network interface IP address as source address */ |
/* use network interface IP address as source address */ |
384 |
src_ip = &(netif->ip_addr); |
src_ip = &(netif->ip_addr); |
385 |
} else { |
} else { |
390 |
DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %u\n", q->tot_len)); |
DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %u\n", q->tot_len)); |
391 |
|
|
392 |
/* UDP Lite protocol? */ |
/* UDP Lite protocol? */ |
393 |
if(pcb->flags & UDP_FLAGS_UDPLITE) { |
if (pcb->flags & UDP_FLAGS_UDPLITE) { |
394 |
DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %u\n", q->tot_len)); |
DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %u\n", q->tot_len)); |
395 |
/* set UDP message length in UDP header */ |
/* set UDP message length in UDP header */ |
396 |
udphdr->len = htons(pcb->chksum_len); |
udphdr->len = htons(pcb->chksum_len); |
398 |
udphdr->chksum = inet_chksum_pseudo(q, src_ip, &(pcb->remote_ip), |
udphdr->chksum = inet_chksum_pseudo(q, src_ip, &(pcb->remote_ip), |
399 |
IP_PROTO_UDP, pcb->chksum_len); |
IP_PROTO_UDP, pcb->chksum_len); |
400 |
/* chksum zero must become 0xffff, as zero means 'no checksum' */ |
/* chksum zero must become 0xffff, as zero means 'no checksum' */ |
401 |
if(udphdr->chksum == 0x0000) udphdr->chksum = 0xffff; |
if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff; |
402 |
/* output to IP */ |
/* output to IP */ |
403 |
err = ip_output_if(q, src_ip, &pcb->remote_ip, UDP_TTL, IP_PROTO_UDPLITE, netif); |
err = ip_output_if (q, src_ip, &pcb->remote_ip, UDP_TTL, IP_PROTO_UDPLITE, netif); |
404 |
snmp_inc_udpoutdatagrams(); |
snmp_inc_udpoutdatagrams(); |
405 |
} else { |
} else { |
406 |
DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %u\n", q->tot_len)); |
DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %u\n", q->tot_len)); |
407 |
udphdr->len = htons(q->tot_len); |
udphdr->len = htons(q->tot_len); |
408 |
/* calculate checksum */ |
/* calculate checksum */ |
409 |
if((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) { |
if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) { |
410 |
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, &pcb->remote_ip, IP_PROTO_UDP, q->tot_len); |
411 |
/* chksum zero must become 0xffff, as zero means 'no checksum' */ |
/* chksum zero must become 0xffff, as zero means 'no checksum' */ |
412 |
if(udphdr->chksum == 0x0000) udphdr->chksum = 0xffff; |
if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff; |
413 |
} |
} |
414 |
DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04x\n", udphdr->chksum)); |
DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04x\n", udphdr->chksum)); |
415 |
snmp_inc_udpoutdatagrams(); |
snmp_inc_udpoutdatagrams(); |
416 |
DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if(,,,,IP_PROTO_UDP,)\n")); |
DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n")); |
417 |
/* output to IP */ |
/* output to IP */ |
418 |
err = ip_output_if(q, src_ip, &pcb->remote_ip, UDP_TTL, IP_PROTO_UDP, netif); |
err = ip_output_if (q, src_ip, &pcb->remote_ip, UDP_TTL, IP_PROTO_UDP, netif); |
419 |
} |
} |
420 |
|
|
421 |
/* did we chain a header earlier? */ |
/* did we chain a header earlier? */ |
533 |
{ |
{ |
534 |
struct udp_pcb *ipcb; |
struct udp_pcb *ipcb; |
535 |
|
|
536 |
if(pcb->local_port == 0) { |
if (pcb->local_port == 0) { |
537 |
err_t err = udp_bind(pcb, &pcb->local_ip, pcb->local_port); |
err_t err = udp_bind(pcb, &pcb->local_ip, pcb->local_port); |
538 |
if(err != ERR_OK) |
if (err != ERR_OK) |
539 |
return err; |
return err; |
540 |
} |
} |
541 |
|
|
545 |
#if 0 |
#if 0 |
546 |
pcb->flags |= UDP_FLAGS_CONNECTED; |
pcb->flags |= UDP_FLAGS_CONNECTED; |
547 |
/* Nail down local IP for netconn_addr()/getsockname() */ |
/* Nail down local IP for netconn_addr()/getsockname() */ |
548 |
if(ip_addr_isany(&pcb->local_ip) && !ip_addr_isany(&pcb->remote_ip)) { |
if (ip_addr_isany(&pcb->local_ip) && !ip_addr_isany(&pcb->remote_ip)) { |
549 |
struct netif *netif; |
struct netif *netif; |
550 |
|
|
551 |
if((netif = ip_route(&(pcb->remote_ip))) == NULL) { |
if ((netif = ip_route(&(pcb->remote_ip))) == NULL) { |
552 |
DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", pcb->remote_ip.addr)); |
DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", pcb->remote_ip.addr)); |
553 |
#ifdef UDP_STATS |
#ifdef UDP_STATS |
554 |
++lwip_stats.udp.rterr; |
++lwip_stats.udp.rterr; |
559 |
is used to route output packets to the remote address. However, we |
is used to route output packets to the remote address. However, we |
560 |
might want to accept incoming packets on any interface! */ |
might want to accept incoming packets on any interface! */ |
561 |
pcb->local_ip = netif->ip_addr; |
pcb->local_ip = netif->ip_addr; |
562 |
} else if(ip_addr_isany(&pcb->remote_ip)) { |
} else if (ip_addr_isany(&pcb->remote_ip)) { |
563 |
pcb->local_ip.addr = 0; |
pcb->local_ip.addr = 0; |
564 |
} |
} |
565 |
#endif |
#endif |
571 |
|
|
572 |
/* Insert UDP PCB into the list of active UDP PCBs. */ |
/* Insert UDP PCB into the list of active UDP PCBs. */ |
573 |
for(ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { |
for(ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { |
574 |
if(pcb == ipcb) { |
if (pcb == ipcb) { |
575 |
/* already on the list, just return */ |
/* already on the list, just return */ |
576 |
return ERR_OK; |
return ERR_OK; |
577 |
} |
} |
617 |
/* pcb not 1st in list */ |
/* pcb not 1st in list */ |
618 |
} else for(pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { |
} else for(pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { |
619 |
/* find pcb in udp_pcbs list */ |
/* find pcb in udp_pcbs list */ |
620 |
if(pcb2->next != NULL && pcb2->next == pcb) { |
if (pcb2->next != NULL && pcb2->next == pcb) { |
621 |
/* remove pcb from list */ |
/* remove pcb from list */ |
622 |
pcb2->next = pcb->next; |
pcb2->next = pcb->next; |
623 |
} |
} |
637 |
struct udp_pcb *pcb; |
struct udp_pcb *pcb; |
638 |
pcb = memp_malloc(MEMP_UDP_PCB); |
pcb = memp_malloc(MEMP_UDP_PCB); |
639 |
/* could allocate UDP PCB? */ |
/* could allocate UDP PCB? */ |
640 |
if(pcb != NULL) { |
if (pcb != NULL) { |
641 |
/* initialize PCB to all zeroes */ |
/* initialize PCB to all zeroes */ |
642 |
memset(pcb, 0, sizeof(struct udp_pcb)); |
memset(pcb, 0, sizeof(struct udp_pcb)); |
643 |
} |
} |