PageRenderTime 37ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/scone/sw/lwtcp/udp.c

https://github.com/Caustic/netfpga
C | 427 lines | 295 code | 55 blank | 77 comment | 78 complexity | a3f8ca3f032ab44339ff3b9ceb99cd70 MD5 | raw file
Possible License(s): Unlicense
  1. /*
  2. * Copyright (c) 2001, Swedish Institute of Computer Science.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the Institute nor the names of its contributors
  14. * may be used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. *
  29. * This file is part of the lwIP TCP/IP stack.
  30. *
  31. * Author: Adam Dunkels <adam@sics.se>
  32. *
  33. * $Id: udp.c 2430 2007-04-06 22:29:40Z paun $
  34. */
  35. /*-----------------------------------------------------------------------------------*/
  36. /* udp.c
  37. *
  38. * The code for the User Datagram Protocol UDP.
  39. *
  40. */
  41. /*-----------------------------------------------------------------------------------*/
  42. #include "lwip/debug.h"
  43. #include "lwip/def.h"
  44. #include "lwip/memp.h"
  45. #include "lwip/inet.h"
  46. #include "lwip/netif.h"
  47. #include "lwip/udp.h"
  48. #include "lwip/icmp.h"
  49. #include "lwip/stats.h"
  50. #include "lwtcp_sr_integration.h"
  51. /*-----------------------------------------------------------------------------------*/
  52. /* The list of UDP PCBs. */
  53. static struct udp_pcb *udp_pcbs = NULL;
  54. #ifdef LWIP_DEBUG
  55. static struct udp_pcb *pcb_cache = NULL;
  56. #endif /* LWIP_DEBUG */
  57. #if UDP_DEBUG
  58. int udp_debug_print(struct udp_hdr *udphdr);
  59. #endif /* UDP_DEBUG */
  60. /*-----------------------------------------------------------------------------------*/
  61. void
  62. udp_init(void)
  63. {
  64. }
  65. /*-----------------------------------------------------------------------------------*/
  66. /* udp_lookup:
  67. *
  68. * An experimental feature that will be changed in future versions. Do
  69. * not depend on it yet...
  70. */
  71. /*-----------------------------------------------------------------------------------*/
  72. #ifdef LWIP_DEBUG
  73. uint8_t
  74. udp_lookup(struct ip_hdr *iphdr, struct netif *inp)
  75. {
  76. struct udp_pcb *pcb;
  77. struct udp_hdr *udphdr;
  78. uint16_t src, dest;
  79. udphdr = (struct udp_hdr *)(uint8_t *)iphdr + IPH_HL(iphdr) * 4/sizeof(uint8_t);
  80. src = NTOHS(udphdr->src);
  81. dest = NTOHS(udphdr->dest);
  82. pcb = pcb_cache;
  83. if(pcb != NULL &&
  84. pcb->remote_port == src &&
  85. pcb->local_port == dest &&
  86. (ip_addr_isany(&pcb->remote_ip) ||
  87. ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
  88. (ip_addr_isany(&pcb->local_ip) ||
  89. ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
  90. return 1;
  91. } else {
  92. for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
  93. if(pcb->remote_port == src &&
  94. pcb->local_port == dest &&
  95. (ip_addr_isany(&pcb->remote_ip) ||
  96. ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
  97. (ip_addr_isany(&pcb->local_ip) ||
  98. ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
  99. pcb_cache = pcb;
  100. break;
  101. }
  102. }
  103. if(pcb == NULL) {
  104. for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
  105. if(pcb->local_port == dest &&
  106. (ip_addr_isany(&pcb->remote_ip) ||
  107. ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
  108. (ip_addr_isany(&pcb->local_ip) ||
  109. ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
  110. break;
  111. }
  112. }
  113. }
  114. }
  115. if(pcb != NULL) {
  116. return 1;
  117. } else {
  118. return 1;
  119. }
  120. }
  121. #endif /* LWIP_DEBUG */
  122. /*-----------------------------------------------------------------------------------*/
  123. void
  124. udp_input(struct pbuf *p, struct netif *inp)
  125. {
  126. struct udp_hdr *udphdr;
  127. struct udp_pcb *pcb;
  128. struct ip_hdr *iphdr;
  129. uint16_t src, dest;
  130. #ifdef UDP_STATS
  131. ++stats.udp.recv;
  132. #endif /* UDP_STATS */
  133. iphdr = p->payload;
  134. pbuf_header(p, -(UDP_HLEN + IPH_HL(iphdr) * 4));
  135. udphdr = (struct udp_hdr *)((uint8_t *)p->payload - UDP_HLEN);
  136. DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %d\n", p->tot_len));
  137. src = NTOHS(udphdr->src);
  138. dest = NTOHS(udphdr->dest);
  139. #if UDP_DEBUG
  140. udp_debug_print(udphdr);
  141. #endif /* UDP_DEBUG */
  142. /* Demultiplex packet. First, go for a perfect match. */
  143. for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
  144. DEBUGF(UDP_DEBUG, ("udp_input: pcb local port %d (dgram %d)\n",
  145. pcb->local_port, ntohs(udphdr->dest)));
  146. if(pcb->remote_port == src &&
  147. pcb->local_port == dest &&
  148. (ip_addr_isany(&pcb->remote_ip) ||
  149. ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
  150. (ip_addr_isany(&pcb->local_ip) ||
  151. ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
  152. break;
  153. }
  154. }
  155. if(pcb == NULL) {
  156. for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
  157. DEBUGF(UDP_DEBUG, ("udp_input: pcb local port %d (dgram %d)\n",
  158. pcb->local_port, dest));
  159. if(pcb->local_port == dest &&
  160. (ip_addr_isany(&pcb->remote_ip) ||
  161. ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
  162. (ip_addr_isany(&pcb->local_ip) ||
  163. ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
  164. break;
  165. }
  166. }
  167. }
  168. /* Check checksum if this is a match or if it was directed at us. */
  169. /* if(pcb != NULL ||
  170. ip_addr_cmp(&inp->ip_addr, &iphdr->dest)) {*/
  171. if(pcb != NULL) {
  172. DEBUGF(UDP_DEBUG, ("udp_input: calculating checksum\n"));
  173. pbuf_header(p, UDP_HLEN);
  174. #ifdef IPv6
  175. if(iphdr->nexthdr == IP_PROTO_UDPLITE) {
  176. #else
  177. if(IPH_PROTO(iphdr) == IP_PROTO_UDPLITE) {
  178. #endif /* IPv4 */
  179. /* Do the UDP Lite checksum */
  180. if(inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
  181. (struct ip_addr *)&(iphdr->dest),
  182. IP_PROTO_UDPLITE, ntohs(udphdr->len)) != 0) {
  183. DEBUGF(UDP_DEBUG, ("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
  184. #ifdef UDP_STATS
  185. ++stats.udp.chkerr;
  186. ++stats.udp.drop;
  187. #endif /* UDP_STATS */
  188. pbuf_free(p);
  189. goto end;
  190. }
  191. } else {
  192. if(udphdr->chksum != 0) {
  193. if(inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
  194. (struct ip_addr *)&(iphdr->dest),
  195. IP_PROTO_UDP, p->tot_len) != 0) {
  196. DEBUGF(UDP_DEBUG, ("udp_input: UDP datagram discarded due to failing checksum\n"));
  197. #ifdef UDP_STATS
  198. ++stats.udp.chkerr;
  199. ++stats.udp.drop;
  200. #endif /* UDP_STATS */
  201. pbuf_free(p);
  202. goto end;
  203. }
  204. }
  205. }
  206. pbuf_header(p, -UDP_HLEN);
  207. if(pcb != NULL) {
  208. pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src);
  209. } else {
  210. DEBUGF(UDP_DEBUG, ("udp_input: not for us.\n"));
  211. /* No match was found, send ICMP destination port unreachable unless
  212. destination address was broadcast/multicast. */
  213. if(!ip_addr_isbroadcast(&iphdr->dest, &inp->netmask) &&
  214. !ip_addr_ismulticast(&iphdr->dest)) {
  215. /* deconvert from host to network byte order */
  216. udphdr->src = htons(udphdr->src);
  217. udphdr->dest = htons(udphdr->dest);
  218. /* adjust pbuf pointer */
  219. p->payload = iphdr;
  220. icmp_dest_unreach(p, ICMP_DUR_PORT);
  221. }
  222. #ifdef UDP_STATS
  223. ++stats.udp.proterr;
  224. ++stats.udp.drop;
  225. #endif /* UDP_STATS */
  226. pbuf_free(p);
  227. }
  228. } else {
  229. pbuf_free(p);
  230. }
  231. end:
  232. while(0); /* hack to remove compiler warning */
  233. }
  234. /*-----------------------------------------------------------------------------------*/
  235. err_t
  236. udp_send(struct udp_pcb *pcb, struct pbuf *p)
  237. {
  238. struct udp_hdr *udphdr;
  239. struct ip_addr *src_ip;
  240. err_t err;
  241. struct pbuf *q;
  242. if(pbuf_header(p, UDP_HLEN)) {
  243. q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM);
  244. if(q == NULL) {
  245. return ERR_MEM;
  246. }
  247. pbuf_chain(q, p);
  248. p = q;
  249. }
  250. udphdr = p->payload;
  251. udphdr->src = htons(pcb->local_port);
  252. udphdr->dest = htons(pcb->remote_port);
  253. udphdr->chksum = 0x0000;
  254. src_ip = &(pcb->local_ip);
  255. DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %d\n", p->tot_len));
  256. if(pcb->flags & UDP_FLAGS_UDPLITE) {
  257. udphdr->len = htons(pcb->chksum_len);
  258. /* calculate checksum */
  259. udphdr->chksum = inet_chksum_pseudo(p, src_ip, &(pcb->remote_ip),
  260. IP_PROTO_UDP, pcb->chksum_len);
  261. if(udphdr->chksum == 0x0000) {
  262. udphdr->chksum = 0xffff;
  263. }
  264. err = sr_lwip_output(p, &pcb->local_ip, &pcb->remote_ip, IP_PROTO_UDPLITE);
  265. } else {
  266. udphdr->len = htons(p->tot_len);
  267. /* calculate checksum */
  268. if((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
  269. udphdr->chksum = inet_chksum_pseudo(p, src_ip, &pcb->remote_ip,
  270. IP_PROTO_UDP, p->tot_len);
  271. if(udphdr->chksum == 0x0000) {
  272. udphdr->chksum = 0xffff;
  273. }
  274. }
  275. err = sr_lwip_output(p,&pcb->local_ip, &pcb->remote_ip, IP_PROTO_UDP);
  276. }
  277. #ifdef UDP_STATS
  278. ++stats.udp.xmit;
  279. #endif /* UDP_STATS */
  280. return err;
  281. }
  282. /*-----------------------------------------------------------------------------------*/
  283. err_t
  284. udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, uint16_t port)
  285. {
  286. struct udp_pcb *ipcb;
  287. ip_addr_set(&pcb->local_ip, ipaddr);
  288. pcb->local_port = port;
  289. /* Insert UDP PCB into the list of active UDP PCBs. */
  290. for(ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
  291. if(pcb == ipcb) {
  292. /* Already on the list, just return. */
  293. return ERR_OK;
  294. }
  295. }
  296. /* We need to place the PCB on the list. */
  297. pcb->next = udp_pcbs;
  298. udp_pcbs = pcb;
  299. DEBUGF(UDP_DEBUG, ("udp_bind: bound to port %d\n", port));
  300. return ERR_OK;
  301. }
  302. /*-----------------------------------------------------------------------------------*/
  303. err_t
  304. udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, uint16_t port)
  305. {
  306. struct udp_pcb *ipcb;
  307. ip_addr_set(&pcb->remote_ip, ipaddr);
  308. pcb->remote_port = port;
  309. /* Insert UDP PCB into the list of active UDP PCBs. */
  310. for(ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
  311. if(pcb == ipcb) {
  312. /* Already on the list, just return. */
  313. return ERR_OK;
  314. }
  315. }
  316. /* We need to place the PCB on the list. */
  317. pcb->next = udp_pcbs;
  318. udp_pcbs = pcb;
  319. return ERR_OK;
  320. }
  321. /*-----------------------------------------------------------------------------------*/
  322. void
  323. udp_recv(struct udp_pcb *pcb,
  324. void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p,
  325. struct ip_addr *addr, uint16_t port),
  326. void *recv_arg)
  327. {
  328. pcb->recv = recv;
  329. pcb->recv_arg = recv_arg;
  330. }
  331. /*-----------------------------------------------------------------------------------*/
  332. void
  333. udp_remove(struct udp_pcb *pcb)
  334. {
  335. struct udp_pcb *pcb2;
  336. if(udp_pcbs == pcb) {
  337. udp_pcbs = udp_pcbs->next;
  338. } else for(pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
  339. if(pcb2->next != NULL && pcb2->next == pcb) {
  340. pcb2->next = pcb->next;
  341. }
  342. }
  343. memp_free(MEMP_UDP_PCB, pcb);
  344. }
  345. /*-----------------------------------------------------------------------------------*/
  346. struct udp_pcb *
  347. udp_new(void) {
  348. struct udp_pcb *pcb;
  349. pcb = memp_malloc(MEMP_UDP_PCB);
  350. if(pcb != NULL) {
  351. bzero(pcb, sizeof(struct udp_pcb));
  352. return pcb;
  353. }
  354. return NULL;
  355. }
  356. /*-----------------------------------------------------------------------------------*/
  357. #if UDP_DEBUG
  358. int
  359. udp_debug_print(struct udp_hdr *udphdr)
  360. {
  361. DEBUGF(UDP_DEBUG, ("UDP header:\n"));
  362. DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
  363. DEBUGF(UDP_DEBUG, ("| %5d | %5d | (src port, dest port)\n",
  364. ntohs(udphdr->src), ntohs(udphdr->dest)));
  365. DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
  366. DEBUGF(UDP_DEBUG, ("| %5d | 0x%04x | (len, chksum)\n",
  367. ntohs(udphdr->len), ntohs(udphdr->chksum)));
  368. DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
  369. return 0;
  370. }
  371. #endif /* UDP_DEBUG */
  372. /*-----------------------------------------------------------------------------------*/