00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #include "lwip/opt.h"
00050
00051 #if LWIP_UDP
00052
00053 #include "lwip/udp.h"
00054 #include "lwip/def.h"
00055 #include "lwip/memp.h"
00056 #include "lwip/inet_chksum.h"
00057 #include "lwip/ip_addr.h"
00058 #include "lwip/netif.h"
00059 #include "lwip/icmp.h"
00060 #include "lwip/stats.h"
00061 #include "lwip/snmp.h"
00062 #include "arch/perf.h"
00063 #include "lwip/dhcp.h"
00064
00065 #include <string.h>
00066
00067 #ifndef UDP_LOCAL_PORT_RANGE_START
00068
00069
00070 #define UDP_LOCAL_PORT_RANGE_START 0xc000
00071 #define UDP_LOCAL_PORT_RANGE_END 0xffff
00072 #define UDP_ENSURE_LOCAL_PORT_RANGE(port) (((port) & ~UDP_LOCAL_PORT_RANGE_START) + UDP_LOCAL_PORT_RANGE_START)
00073 #endif
00074
00075
00076 static u16_t udp_port = UDP_LOCAL_PORT_RANGE_START;
00077
00078
00079
00080 struct udp_pcb *udp_pcbs;
00081
00082
00083
00084
00085 void
00086 udp_init(void)
00087 {
00088 #if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND)
00089 udp_port = UDP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND());
00090 #endif
00091 }
00092
00093
00094
00095
00096
00097
00098 static u16_t
00099 udp_new_port(void)
00100 {
00101 u16_t n = 0;
00102 struct udp_pcb *pcb;
00103
00104 again:
00105 if (udp_port++ == UDP_LOCAL_PORT_RANGE_END) {
00106 udp_port = UDP_LOCAL_PORT_RANGE_START;
00107 }
00108
00109 for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
00110 if (pcb->local_port == udp_port) {
00111 if (++n > (UDP_LOCAL_PORT_RANGE_END - UDP_LOCAL_PORT_RANGE_START)) {
00112 return 0;
00113 }
00114 goto again;
00115 }
00116 }
00117 return udp_port;
00118 #if 0
00119 struct udp_pcb *ipcb = udp_pcbs;
00120 while ((ipcb != NULL) && (udp_port != UDP_LOCAL_PORT_RANGE_END)) {
00121 if (ipcb->local_port == udp_port) {
00122
00123 udp_port++;
00124
00125 ipcb = udp_pcbs;
00126 } else {
00127
00128 ipcb = ipcb->next;
00129 }
00130 }
00131 if (ipcb != NULL) {
00132 return 0;
00133 }
00134 return udp_port;
00135 #endif
00136 }
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 void
00151 udp_input(struct pbuf *p, struct netif *inp)
00152 {
00153 struct udp_hdr *udphdr;
00154 struct udp_pcb *pcb, *prev;
00155 struct udp_pcb *uncon_pcb;
00156 struct ip_hdr *iphdr;
00157 u16_t src, dest;
00158 u8_t local_match;
00159 u8_t broadcast;
00160
00161 PERF_START;
00162
00163 UDP_STATS_INC(udp.recv);
00164
00165 iphdr = (struct ip_hdr *)p->payload;
00166
00167
00168
00169 if (p->tot_len < (IPH_HL(iphdr) * 4 + UDP_HLEN) || pbuf_header(p, -(s16_t)(IPH_HL(iphdr) * 4))) {
00170
00171 LWIP_DEBUGF(UDP_DEBUG,
00172 ("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len));
00173 UDP_STATS_INC(udp.lenerr);
00174 UDP_STATS_INC(udp.drop);
00175 snmp_inc_udpinerrors();
00176 pbuf_free(p);
00177 goto end;
00178 }
00179
00180 udphdr = (struct udp_hdr *)p->payload;
00181
00182
00183 broadcast = ip_addr_isbroadcast(¤t_iphdr_dest, inp);
00184
00185 LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len));
00186
00187
00188 src = ntohs(udphdr->src);
00189 dest = ntohs(udphdr->dest);
00190
00191 udp_debug_print(udphdr);
00192
00193
00194 LWIP_DEBUGF(UDP_DEBUG,
00195 ("udp (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") <-- "
00196 "(%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n",
00197 ip4_addr1_16(&iphdr->dest), ip4_addr2_16(&iphdr->dest),
00198 ip4_addr3_16(&iphdr->dest), ip4_addr4_16(&iphdr->dest), ntohs(udphdr->dest),
00199 ip4_addr1_16(&iphdr->src), ip4_addr2_16(&iphdr->src),
00200 ip4_addr3_16(&iphdr->src), ip4_addr4_16(&iphdr->src), ntohs(udphdr->src)));
00201
00202 #if LWIP_DHCP
00203 pcb = NULL;
00204
00205
00206 if (dest == DHCP_CLIENT_PORT) {
00207
00208 if (src == DHCP_SERVER_PORT) {
00209 if ((inp->dhcp != NULL) && (inp->dhcp->pcb != NULL)) {
00210
00211
00212
00213 if ((ip_addr_isany(&inp->dhcp->pcb->remote_ip) ||
00214 ip_addr_cmp(&(inp->dhcp->pcb->remote_ip), ¤t_iphdr_src))) {
00215 pcb = inp->dhcp->pcb;
00216 }
00217 }
00218 }
00219 } else
00220 #endif
00221 {
00222 prev = NULL;
00223 local_match = 0;
00224 uncon_pcb = NULL;
00225
00226
00227
00228
00229 for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
00230 local_match = 0;
00231
00232 LWIP_DEBUGF(UDP_DEBUG,
00233 ("pcb (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") --- "
00234 "(%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n",
00235 ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip),
00236 ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip), pcb->local_port,
00237 ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip),
00238 ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip), pcb->remote_port));
00239
00240
00241 if (pcb->local_port == dest) {
00242 if (
00243 (!broadcast && ip_addr_isany(&pcb->local_ip)) ||
00244 ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest) ||
00245 #if LWIP_IGMP
00246 ip_addr_ismulticast(¤t_iphdr_dest) ||
00247 #endif
00248 #if IP_SOF_BROADCAST_RECV
00249 (broadcast && ip_get_option(pcb, SOF_BROADCAST) &&
00250 (ip_addr_isany(&pcb->local_ip) ||
00251 ip_addr_netcmp(&pcb->local_ip, ip_current_dest_addr(), &inp->netmask)))) {
00252 #else
00253 (broadcast &&
00254 (ip_addr_isany(&pcb->local_ip) ||
00255 ip_addr_netcmp(&pcb->local_ip, ip_current_dest_addr(), &inp->netmask)))) {
00256 #endif
00257 local_match = 1;
00258 if ((uncon_pcb == NULL) &&
00259 ((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) {
00260
00261 uncon_pcb = pcb;
00262 }
00263 }
00264 }
00265
00266 if ((local_match != 0) &&
00267 (pcb->remote_port == src) &&
00268 (ip_addr_isany(&pcb->remote_ip) ||
00269 ip_addr_cmp(&(pcb->remote_ip), ¤t_iphdr_src))) {
00270
00271 if (prev != NULL) {
00272
00273
00274 prev->next = pcb->next;
00275 pcb->next = udp_pcbs;
00276 udp_pcbs = pcb;
00277 } else {
00278 UDP_STATS_INC(udp.cachehit);
00279 }
00280 break;
00281 }
00282 prev = pcb;
00283 }
00284
00285 if (pcb == NULL) {
00286 pcb = uncon_pcb;
00287 }
00288 }
00289
00290
00291 if (pcb != NULL || ip_addr_cmp(&inp->ip_addr, ¤t_iphdr_dest)) {
00292 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\n"));
00293 #if LWIP_UDPLITE
00294 if (IPH_PROTO(iphdr) == IP_PROTO_UDPLITE) {
00295
00296 #if CHECKSUM_CHECK_UDP
00297 u16_t chklen = ntohs(udphdr->len);
00298 if (chklen < sizeof(struct udp_hdr)) {
00299 if (chklen == 0) {
00300
00301
00302 chklen = p->tot_len;
00303 } else {
00304
00305
00306 UDP_STATS_INC(udp.chkerr);
00307 UDP_STATS_INC(udp.drop);
00308 snmp_inc_udpinerrors();
00309 pbuf_free(p);
00310 goto end;
00311 }
00312 }
00313 if (inet_chksum_pseudo_partial(p, ¤t_iphdr_src, ¤t_iphdr_dest,
00314 IP_PROTO_UDPLITE, p->tot_len, chklen) != 0) {
00315 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00316 ("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
00317 UDP_STATS_INC(udp.chkerr);
00318 UDP_STATS_INC(udp.drop);
00319 snmp_inc_udpinerrors();
00320 pbuf_free(p);
00321 goto end;
00322 }
00323 #endif
00324 } else
00325 #endif
00326 {
00327 #if CHECKSUM_CHECK_UDP
00328 if (udphdr->chksum != 0) {
00329 if (inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(),
00330 IP_PROTO_UDP, p->tot_len) != 0) {
00331 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00332 ("udp_input: UDP datagram discarded due to failing checksum\n"));
00333 UDP_STATS_INC(udp.chkerr);
00334 UDP_STATS_INC(udp.drop);
00335 snmp_inc_udpinerrors();
00336 pbuf_free(p);
00337 goto end;
00338 }
00339 }
00340 #endif
00341 }
00342 if(pbuf_header(p, -UDP_HLEN)) {
00343
00344 LWIP_ASSERT("pbuf_header failed\n", 0);
00345 UDP_STATS_INC(udp.drop);
00346 snmp_inc_udpinerrors();
00347 pbuf_free(p);
00348 goto end;
00349 }
00350 if (pcb != NULL) {
00351 snmp_inc_udpindatagrams();
00352 #if SO_REUSE && SO_REUSE_RXTOALL
00353 if ((broadcast || ip_addr_ismulticast(¤t_iphdr_dest)) &&
00354 ip_get_option(pcb, SOF_REUSEADDR)) {
00355
00356
00357 struct udp_pcb *mpcb;
00358 u8_t p_header_changed = 0;
00359 for (mpcb = udp_pcbs; mpcb != NULL; mpcb = mpcb->next) {
00360 if (mpcb != pcb) {
00361
00362 if ((mpcb->local_port == dest) &&
00363 ((!broadcast && ip_addr_isany(&mpcb->local_ip)) ||
00364 ip_addr_cmp(&(mpcb->local_ip), ¤t_iphdr_dest) ||
00365 #if LWIP_IGMP
00366 ip_addr_ismulticast(¤t_iphdr_dest) ||
00367 #endif
00368 #if IP_SOF_BROADCAST_RECV
00369 (broadcast && ip_get_option(mpcb, SOF_BROADCAST)))) {
00370 #else
00371 (broadcast))) {
00372 #endif
00373
00374 if (mpcb->recv != NULL) {
00375 struct pbuf *q;
00376
00377 if (p_header_changed == 0) {
00378 pbuf_header(p, (s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
00379 p_header_changed = 1;
00380 }
00381 q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
00382 if (q != NULL) {
00383 err_t err = pbuf_copy(q, p);
00384 if (err == ERR_OK) {
00385
00386 pbuf_header(q, -(s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
00387 mpcb->recv(mpcb->recv_arg, mpcb, q, ip_current_src_addr(), src);
00388 }
00389 }
00390 }
00391 }
00392 }
00393 }
00394 if (p_header_changed) {
00395
00396 pbuf_header(p, -(s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
00397 }
00398 }
00399 #endif
00400
00401 if (pcb->recv != NULL) {
00402
00403 pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr(), src);
00404 } else {
00405
00406 pbuf_free(p);
00407 goto end;
00408 }
00409 } else {
00410 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: not for us.\n"));
00411
00412 #if LWIP_ICMP
00413
00414
00415 if (!broadcast &&
00416 !ip_addr_ismulticast(¤t_iphdr_dest)) {
00417
00418 pbuf_header(p, (IPH_HL(iphdr) * 4) + UDP_HLEN);
00419 LWIP_ASSERT("p->payload == iphdr", (p->payload == iphdr));
00420 icmp_dest_unreach(p, ICMP_DUR_PORT);
00421 }
00422 #endif
00423 UDP_STATS_INC(udp.proterr);
00424 UDP_STATS_INC(udp.drop);
00425 snmp_inc_udpnoports();
00426 pbuf_free(p);
00427 }
00428 } else {
00429 pbuf_free(p);
00430 }
00431 end:
00432 PERF_STOP("udp_input");
00433 }
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453 err_t
00454 udp_send(struct udp_pcb *pcb, struct pbuf *p)
00455 {
00456
00457 return udp_sendto(pcb, p, &pcb->remote_ip, pcb->remote_port);
00458 }
00459
00460 #if LWIP_CHECKSUM_ON_COPY
00461
00462
00463 err_t
00464 udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p,
00465 u8_t have_chksum, u16_t chksum)
00466 {
00467
00468 return udp_sendto_chksum(pcb, p, &pcb->remote_ip, pcb->remote_port,
00469 have_chksum, chksum);
00470 }
00471 #endif
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 err_t
00491 udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
00492 ip_addr_t *dst_ip, u16_t dst_port)
00493 {
00494 #if LWIP_CHECKSUM_ON_COPY
00495 return udp_sendto_chksum(pcb, p, dst_ip, dst_port, 0, 0);
00496 }
00497
00498
00499 err_t
00500 udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
00501 u16_t dst_port, u8_t have_chksum, u16_t chksum)
00502 {
00503 #endif
00504 struct netif *netif;
00505
00506 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n"));
00507
00508
00509 #if LWIP_IGMP
00510 netif = ip_route((ip_addr_ismulticast(dst_ip))?(&(pcb->multicast_ip)):(dst_ip));
00511 #else
00512 netif = ip_route(dst_ip);
00513 #endif
00514
00515
00516 if (netif == NULL) {
00517 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
00518 ip4_addr1_16(dst_ip), ip4_addr2_16(dst_ip), ip4_addr3_16(dst_ip), ip4_addr4_16(dst_ip)));
00519 UDP_STATS_INC(udp.rterr);
00520 return ERR_RTE;
00521 }
00522 #if LWIP_CHECKSUM_ON_COPY
00523 return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum);
00524 #else
00525 return udp_sendto_if(pcb, p, dst_ip, dst_port, netif);
00526 #endif
00527 }
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548 err_t
00549 udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
00550 ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif)
00551 {
00552 #if LWIP_CHECKSUM_ON_COPY
00553 return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0);
00554 }
00555
00556
00557 err_t
00558 udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
00559 u16_t dst_port, struct netif *netif, u8_t have_chksum,
00560 u16_t chksum)
00561 {
00562 #endif
00563 struct udp_hdr *udphdr;
00564 ip_addr_t *src_ip;
00565 err_t err;
00566 struct pbuf *q;
00567
00568 #if IP_SOF_BROADCAST
00569
00570 if (!ip_get_option(pcb, SOF_BROADCAST) && ip_addr_isbroadcast(dst_ip, netif)) {
00571 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00572 ("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
00573 return ERR_VAL;
00574 }
00575 #endif
00576
00577
00578 if (pcb->local_port == 0) {
00579 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send: not yet bound to a port, binding now\n"));
00580 err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
00581 if (err != ERR_OK) {
00582 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: forced port bind failed\n"));
00583 return err;
00584 }
00585 }
00586
00587
00588 if (pbuf_header(p, UDP_HLEN)) {
00589
00590 q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM);
00591
00592 if (q == NULL) {
00593 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: could not allocate header\n"));
00594 return ERR_MEM;
00595 }
00596 if (p->tot_len != 0) {
00597
00598 pbuf_chain(q, p);
00599 }
00600
00601 LWIP_DEBUGF(UDP_DEBUG,
00602 ("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
00603 } else {
00604
00605
00606 q = p;
00607 LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p));
00608 }
00609 LWIP_ASSERT("check that first pbuf can hold struct udp_hdr",
00610 (q->len >= sizeof(struct udp_hdr)));
00611
00612 udphdr = (struct udp_hdr *)q->payload;
00613 udphdr->src = htons(pcb->local_port);
00614 udphdr->dest = htons(dst_port);
00615
00616 udphdr->chksum = 0x0000;
00617
00618
00619 #if LWIP_IGMP
00620 if (ip_addr_ismulticast(dst_ip) && ((pcb->flags & UDP_FLAGS_MULTICAST_LOOP) != 0)) {
00621 q->flags |= PBUF_FLAG_MCASTLOOP;
00622 }
00623 #endif
00624
00625
00626
00627 if (ip_addr_isany(&pcb->local_ip)) {
00628
00629 src_ip = &(netif->ip_addr);
00630 } else {
00631
00632
00633 if (!ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) {
00634
00635 if (q != p) {
00636
00637 pbuf_free(q);
00638 q = NULL;
00639
00640 }
00641 return ERR_VAL;
00642 }
00643
00644 src_ip = &(pcb->local_ip);
00645 }
00646
00647 LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len));
00648
00649 #if LWIP_UDPLITE
00650
00651 if (pcb->flags & UDP_FLAGS_UDPLITE) {
00652 u16_t chklen, chklen_hdr;
00653 LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len));
00654
00655 chklen_hdr = chklen = pcb->chksum_len_tx;
00656 if ((chklen < sizeof(struct udp_hdr)) || (chklen > q->tot_len)) {
00657 if (chklen != 0) {
00658 LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE pcb->chksum_len is illegal: %"U16_F"\n", chklen));
00659 }
00660
00661
00662
00663
00664
00665
00666 chklen_hdr = 0;
00667 chklen = q->tot_len;
00668 }
00669 udphdr->len = htons(chklen_hdr);
00670
00671 #if CHECKSUM_GEN_UDP
00672 udphdr->chksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip,
00673 IP_PROTO_UDPLITE, q->tot_len,
00674 #if !LWIP_CHECKSUM_ON_COPY
00675 chklen);
00676 #else
00677 (have_chksum ? UDP_HLEN : chklen));
00678 if (have_chksum) {
00679 u32_t acc;
00680 acc = udphdr->chksum + (u16_t)~(chksum);
00681 udphdr->chksum = FOLD_U32T(acc);
00682 }
00683 #endif
00684
00685
00686 if (udphdr->chksum == 0x0000) {
00687 udphdr->chksum = 0xffff;
00688 }
00689 #endif
00690
00691 LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDPLITE,)\n"));
00692 NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint);
00693 err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
00694 NETIF_SET_HWADDRHINT(netif, NULL);
00695 } else
00696 #endif
00697 {
00698 LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len));
00699 udphdr->len = htons(q->tot_len);
00700
00701 #if CHECKSUM_GEN_UDP
00702 if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
00703 u16_t udpchksum;
00704 #if LWIP_CHECKSUM_ON_COPY
00705 if (have_chksum) {
00706 u32_t acc;
00707 udpchksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip, IP_PROTO_UDP,
00708 q->tot_len, UDP_HLEN);
00709 acc = udpchksum + (u16_t)~(chksum);
00710 udpchksum = FOLD_U32T(acc);
00711 } else
00712 #endif
00713 {
00714 udpchksum = inet_chksum_pseudo(q, src_ip, dst_ip, IP_PROTO_UDP, q->tot_len);
00715 }
00716
00717
00718 if (udpchksum == 0x0000) {
00719 udpchksum = 0xffff;
00720 }
00721 udphdr->chksum = udpchksum;
00722 }
00723 #endif
00724 LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum));
00725 LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
00726
00727 NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint);
00728 err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
00729 NETIF_SET_HWADDRHINT(netif, NULL);
00730 }
00731
00732 snmp_inc_udpoutdatagrams();
00733
00734
00735 if (q != p) {
00736
00737 pbuf_free(q);
00738 q = NULL;
00739
00740 }
00741
00742 UDP_STATS_INC(udp.xmit);
00743 return err;
00744 }
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765 err_t
00766 udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
00767 {
00768 struct udp_pcb *ipcb;
00769 u8_t rebind;
00770
00771 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_bind(ipaddr = "));
00772 ip_addr_debug_print(UDP_DEBUG, ipaddr);
00773 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, (", port = %"U16_F")\n", port));
00774
00775 rebind = 0;
00776
00777 for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
00778
00779 if (pcb == ipcb) {
00780
00781 LWIP_ASSERT("rebind == 0", rebind == 0);
00782
00783 rebind = 1;
00784 }
00785
00786
00787
00788
00789 #if SO_REUSE
00790 else if (!ip_get_option(pcb, SOF_REUSEADDR) &&
00791 !ip_get_option(ipcb, SOF_REUSEADDR)) {
00792 #else
00793
00794 else {
00795 #endif
00796 if ((ipcb->local_port == port) &&
00797
00798 (ip_addr_isany(&(ipcb->local_ip)) ||
00799 ip_addr_isany(ipaddr) ||
00800 ip_addr_cmp(&(ipcb->local_ip), ipaddr))) {
00801
00802 LWIP_DEBUGF(UDP_DEBUG,
00803 ("udp_bind: local port %"U16_F" already bound by another pcb\n", port));
00804 return ERR_USE;
00805 }
00806 }
00807 }
00808
00809 ip_addr_set(&pcb->local_ip, ipaddr);
00810
00811
00812 if (port == 0) {
00813 port = udp_new_port();
00814 if (port == 0) {
00815
00816 LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n"));
00817 return ERR_USE;
00818 }
00819 }
00820 pcb->local_port = port;
00821 snmp_insert_udpidx_tree(pcb);
00822
00823 if (rebind == 0) {
00824
00825 pcb->next = udp_pcbs;
00826 udp_pcbs = pcb;
00827 }
00828 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
00829 ("udp_bind: bound to %"U16_F".%"U16_F".%"U16_F".%"U16_F", port %"U16_F"\n",
00830 ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip),
00831 ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip),
00832 pcb->local_port));
00833 return ERR_OK;
00834 }
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852 err_t
00853 udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
00854 {
00855 struct udp_pcb *ipcb;
00856
00857 if (pcb->local_port == 0) {
00858 err_t err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
00859 if (err != ERR_OK) {
00860 return err;
00861 }
00862 }
00863
00864 ip_addr_set(&pcb->remote_ip, ipaddr);
00865 pcb->remote_port = port;
00866 pcb->flags |= UDP_FLAGS_CONNECTED;
00867
00868 #ifdef LWIP_UDP_TODO
00869
00870 if (ip_addr_isany(&pcb->local_ip) && !ip_addr_isany(&pcb->remote_ip)) {
00871 struct netif *netif;
00872
00873 if ((netif = ip_route(&(pcb->remote_ip))) == NULL) {
00874 LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", pcb->remote_ip.addr));
00875 UDP_STATS_INC(udp.rterr);
00876 return ERR_RTE;
00877 }
00878
00879
00880
00881 pcb->local_ip = netif->ip_addr;
00882 } else if (ip_addr_isany(&pcb->remote_ip)) {
00883 pcb->local_ip.addr = 0;
00884 }
00885 #endif
00886 LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
00887 ("udp_connect: connected to %"U16_F".%"U16_F".%"U16_F".%"U16_F",port %"U16_F"\n",
00888 ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip),
00889 ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip),
00890 pcb->local_port));
00891
00892
00893 for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
00894 if (pcb == ipcb) {
00895
00896 return ERR_OK;
00897 }
00898 }
00899
00900 pcb->next = udp_pcbs;
00901 udp_pcbs = pcb;
00902 return ERR_OK;
00903 }
00904
00905
00906
00907
00908
00909
00910 void
00911 udp_disconnect(struct udp_pcb *pcb)
00912 {
00913
00914 ip_addr_set_any(&pcb->remote_ip);
00915 pcb->remote_port = 0;
00916
00917 pcb->flags &= ~UDP_FLAGS_CONNECTED;
00918 }
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929 void
00930 udp_recv(struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg)
00931 {
00932
00933 pcb->recv = recv;
00934 pcb->recv_arg = recv_arg;
00935 }
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945 void
00946 udp_remove(struct udp_pcb *pcb)
00947 {
00948 struct udp_pcb *pcb2;
00949
00950 snmp_delete_udpidx_tree(pcb);
00951
00952 if (udp_pcbs == pcb) {
00953
00954 udp_pcbs = udp_pcbs->next;
00955
00956 } else {
00957 for (pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
00958
00959 if (pcb2->next != NULL && pcb2->next == pcb) {
00960
00961 pcb2->next = pcb->next;
00962 }
00963 }
00964 }
00965 memp_free(MEMP_UDP_PCB, pcb);
00966 }
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976 struct udp_pcb *
00977 udp_new(void)
00978 {
00979 struct udp_pcb *pcb;
00980 pcb = (struct udp_pcb *)memp_malloc(MEMP_UDP_PCB);
00981
00982 if (pcb != NULL) {
00983
00984
00985
00986
00987 memset(pcb, 0, sizeof(struct udp_pcb));
00988 pcb->ttl = UDP_TTL;
00989 }
00990 return pcb;
00991 }
00992
00993 #if UDP_DEBUG
00994
00995
00996
00997
00998
00999 void
01000 udp_debug_print(struct udp_hdr *udphdr)
01001 {
01002 LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n"));
01003 LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
01004 LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n",
01005 ntohs(udphdr->src), ntohs(udphdr->dest)));
01006 LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
01007 LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | 0x%04"X16_F" | (len, chksum)\n",
01008 ntohs(udphdr->len), ntohs(udphdr->chksum)));
01009 LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
01010 }
01011 #endif
01012
01013 #endif