udpsock.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. /*
  2. * Copyright (C) 2001-2003 by egnite Software GmbH
  3. * Copyright (c) 1993 by Digital Equipment Corporation
  4. * Copyright (c) 1983, 1993 by The Regents of the University of California
  5. *
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 3. Neither the name of the copyright holders nor the names of
  18. * contributors may be used to endorse or promote products derived
  19. * from this software without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  30. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  31. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32. * SUCH DAMAGE.
  33. *
  34. * For additional information see http://www.ethernut.de/
  35. */
  36. /*!
  37. * \file net/udpsock.c
  38. * \brief UDP socket interface.
  39. *
  40. * \verbatim
  41. * $Id: udpsock.c 5509 2014-01-02 20:46:54Z mifi $
  42. * \endverbatim
  43. */
  44. #include <sys/heap.h>
  45. #include <sys/event.h>
  46. #include <sys/timer.h>
  47. #include <sys/types.h>
  48. #include <netinet/ip.h>
  49. #include <netinet/udp.h>
  50. #include <netinet/in.h>
  51. #include <sys/socket.h>
  52. #include <errno.h>
  53. #include <stdlib.h>
  54. #include <string.h>
  55. #include <memdebug.h>
  56. /*!
  57. * \addtogroup xgUdpSocket
  58. */
  59. /*@{*/
  60. UDPSOCKET *udpSocketList; /*!< Global linked list of all UDP sockets. */
  61. static uint16_t last_local_port; /* Unassigned local port. */
  62. static uint_fast8_t registered;
  63. /*!
  64. * \brief Create a UDP socket.
  65. *
  66. * \param port Server applications provide the local port number
  67. * with this parameter. Client applications should
  68. * pass zero.
  69. *
  70. * \return Socket descriptor of the newly created UDP socket or
  71. * 0 if there is not enough memory left.
  72. *
  73. */
  74. UDPSOCKET *NutUdpCreateSocket(uint16_t port)
  75. {
  76. UDPSOCKET *sock;
  77. uint16_t ticks;
  78. if (!registered) {
  79. if (NutRegisterIpHandler(IPPROTO_UDP, NutUdpInput)) {
  80. return NULL;
  81. }
  82. registered = 1;
  83. }
  84. if (port == 0) {
  85. do {
  86. /* Each time a new socket is created the local port number in incremented
  87. by a more or less randomized value between 1 and 15 (the lowest 4 bit of
  88. NutGetMillis() | 1). The highest two bits are always set to 1.
  89. This way a port range of 49152 to 65535 is used according to the IANA
  90. suggestions for ephemeral port usage.
  91. */
  92. ticks = (uint16_t) NutGetMillis();
  93. if (last_local_port) {
  94. last_local_port += (uint16_t) ((ticks & 0x000F) | 1);
  95. } else {
  96. last_local_port = ticks;
  97. }
  98. last_local_port |= 0xC000;
  99. port = htons(last_local_port);
  100. sock = udpSocketList;
  101. while (sock) {
  102. if (sock->so_local_port == port)
  103. break;
  104. sock = sock->so_next;
  105. }
  106. } while (sock);
  107. port = last_local_port;
  108. }
  109. if ((sock = calloc(1, sizeof(UDPSOCKET))) != 0) {
  110. sock->so_local_port = htons(port);
  111. sock->so_next = udpSocketList;
  112. udpSocketList = sock;
  113. }
  114. return sock;
  115. }
  116. /*!
  117. * \brief Send a UDP datagram.
  118. *
  119. * \param sock Socket descriptor. This pointer must have been
  120. * retrieved by calling NutUdpCreateSocket().
  121. * \param addr IP address of the remote host in network byte order.
  122. * \param port Remote port number in host byte order.
  123. * \param data Pointer to a buffer containing the data to send.
  124. * \param len Number of bytes to be sent.
  125. *
  126. * \return 0 on success, -1 otherwise. The specific error code
  127. * can be retrieved by calling NutUdpError().
  128. */
  129. int NutUdpSendTo(UDPSOCKET * sock, uint32_t addr, uint16_t port, void *data, int len)
  130. {
  131. int rc;
  132. NETBUF *nb;
  133. #ifndef NUT_UDP_ICMP_EXCLUDE
  134. if (sock->so_last_error)
  135. return -1;
  136. #endif
  137. if ((nb = NutNetBufAlloc(0, NBAF_APPLICATION, len)) == 0) {
  138. sock->so_last_error = ENOMEM;
  139. return -1;
  140. }
  141. memcpy(nb->nb_ap.vp, data, len);
  142. /* Bugfix by Ralph Mason. We should not free the NETBUF in case of an error. */
  143. if ((rc = NutUdpOutput(sock, addr, port, nb)) == 0)
  144. NutNetBufFree(nb);
  145. return rc;
  146. }
  147. /*!
  148. * \brief Receive a UDP datagram.
  149. *
  150. * \param sock Socket descriptor. This pointer must have been
  151. * retrieved by calling NutUdpCreateSocket().
  152. * \param addr IP address of the remote host in network byte order.
  153. * \param port Remote port number in host byte order.
  154. * \param data Pointer to the buffer that receives the data.
  155. * \param size Size of the buffer that receives the data.
  156. * \param timeout Maximum number of milliseconds to wait.
  157. *
  158. * \return The number of bytes received, if successful. The return
  159. * value < 0 indicates an error. The specific error code
  160. * can be retrieved by calling NutUdpError().
  161. *
  162. * \note Timeout is limited to the granularity of the system timer.
  163. */
  164. /* @@@ 2003-10-24: modified by OS for udp packet queue */
  165. int NutUdpReceiveFrom(UDPSOCKET * sock, uint32_t * addr, uint16_t * port, void *data, int size, uint32_t timeout)
  166. {
  167. IPHDR *ip;
  168. UDPHDR *uh;
  169. NETBUF *nb;
  170. #ifndef NUT_UDP_ICMP_EXCLUDE
  171. /* The ICMP handler might have set an error condition. */
  172. if (sock->so_last_error)
  173. return -1;
  174. #endif
  175. if (sock->so_rx_nb == 0)
  176. NutEventWait(&sock->so_rx_rdy, timeout);
  177. #ifndef NUT_UDP_ICMP_EXCLUDE
  178. /* An ICMP message might have posted the rx event. So check again */
  179. if (sock->so_last_error)
  180. return -1;
  181. #endif
  182. if ((nb = sock->so_rx_nb) == 0)
  183. return 0;
  184. /* forward the queue's head to the next packet */
  185. sock->so_rx_nb = nb->nb_next;
  186. ip = nb->nb_nw.vp;
  187. *addr = ip->ip_src;
  188. uh = nb->nb_tp.vp;
  189. *port = htons(uh->uh_sport);
  190. if (size > nb->nb_ap.sz)
  191. size = nb->nb_ap.sz;
  192. sock->so_rx_cnt -= nb->nb_ap.sz; /* decrement input buffer count */
  193. memcpy(data, nb->nb_ap.vp, size);
  194. NutNetBufFree(nb);
  195. return size;
  196. }
  197. /*!
  198. * \brief Close UDP socket.
  199. *
  200. * The memory occupied by the socket is immediately released
  201. * after calling this function. The application must not use
  202. * the socket after this call.
  203. *
  204. * \param sock Socket descriptor. This pointer must have been
  205. * retrieved by calling NutUdpCreateSocket().
  206. *
  207. * \return 0 on success, -1 otherwise.
  208. */
  209. /* @@@ 2003-10-24: modified by OS for udp packet queue */
  210. int NutUdpDestroySocket(UDPSOCKET * sock)
  211. {
  212. UDPSOCKET *sp;
  213. UDPSOCKET **spp;
  214. int rc = -1;
  215. NETBUF *nb;
  216. spp = &udpSocketList;
  217. sp = udpSocketList;
  218. while (sp) {
  219. if (sp == sock) {
  220. *spp = sock->so_next;
  221. /* packets may have arrived that the application
  222. did not read before closing the socket. */
  223. while ((nb = sock->so_rx_nb) != 0) {
  224. sock->so_rx_nb = nb->nb_next;
  225. NutNetBufFree(nb);
  226. }
  227. free(sock);
  228. rc = 0;
  229. break;
  230. }
  231. spp = &sp->so_next;
  232. sp = sp->so_next;
  233. }
  234. return rc;
  235. }
  236. /*!
  237. * \brief Return specific code of the last error and the IP address / port of
  238. * the host to which the communication failed
  239. *
  240. * Possible error codes are:
  241. * - ENOTSOCK: Socket operation on non-socket
  242. * - EMSGSIZE: Message too long
  243. * - ENOPROTOOPT: Protocol not available
  244. * - EOPNOTSUPP: Operation not supported on socket
  245. * - ENETUNREACH: Network is unreachable
  246. * - ECONNREFUSED: Connection refused
  247. * - EHOSTDOWN: Host is down
  248. * - EHOSTUNREACH: No route to host
  249. *
  250. * \param sock Socket descriptor. This pointer must have been
  251. * retrieved by calling NutUdpCreateSocket().
  252. * \param addr IP address of the remote host in network byte order.
  253. * \param port Remote port number in host byte order.
  254. *
  255. * \todo Not all error codes are properly set right now. Some socket
  256. * functions return an error without setting an error code.
  257. */
  258. int NutUdpError(UDPSOCKET * sock, uint32_t * addr, uint16_t * port)
  259. {
  260. int rc;
  261. if (sock == 0) {
  262. addr = 0;
  263. port = 0;
  264. return ENOTSOCK;
  265. }
  266. if (sock->so_last_error) {
  267. rc = sock->so_last_error;
  268. *port = ntohs(sock->so_remote_port);
  269. *addr = sock->so_remote_addr;
  270. sock->so_last_error = 0;
  271. sock->so_remote_port = 0;
  272. sock->so_remote_addr = 0;
  273. return rc;
  274. }
  275. return 0;
  276. }
  277. /*!
  278. * \brief Find a matching socket.
  279. *
  280. * Loop through all sockets and find a matching one.
  281. *
  282. * \note Applications typically do not need to call this function.
  283. *
  284. * \param port Local port number.
  285. *
  286. * \return Socket descriptor.
  287. */
  288. UDPSOCKET *NutUdpFindSocket(uint16_t port)
  289. {
  290. UDPSOCKET *sp;
  291. UDPSOCKET *sock = 0;
  292. for (sp = udpSocketList; sp; sp = sp->so_next) {
  293. if (sp->so_local_port == port) {
  294. sock = sp;
  295. break;
  296. }
  297. }
  298. return sock;
  299. }
  300. /*!
  301. * \brief Set value of a UDP socket option.
  302. *
  303. * The following values can be set:
  304. *
  305. * - #SO_RCVBUF Socket input buffer size (#uint16_t).
  306. *
  307. * \param sock Socket descriptor. This pointer must have been
  308. * retrieved by calling NutUdpCreateSocket().
  309. * \param optname Option to set.
  310. * \param optval Pointer to the value.
  311. * \param optlen Length of the value.
  312. * \return 0 on success, -1 otherwise.
  313. */
  314. int NutUdpSetSockOpt(UDPSOCKET * sock, int optname, const void *optval, int optlen)
  315. {
  316. int rc = -1;
  317. if (sock == 0)
  318. return -1;
  319. switch (optname) {
  320. case SO_RCVBUF:
  321. if (optval != 0 && optlen == sizeof(uint16_t)) {
  322. sock->so_rx_bsz = *((uint16_t *) optval);
  323. rc = 0;
  324. }
  325. break;
  326. default:
  327. /* sock->so_last_error = ENOPROTOOPT; */
  328. break;
  329. }
  330. return rc;
  331. }
  332. /*!
  333. * \brief Get a UDP socket option value.
  334. *
  335. * The following values can be set:
  336. *
  337. * - #SO_RCVBUF Socket input buffer size (#uint16_t).
  338. *
  339. * \param sock Socket descriptor. This pointer must have been
  340. * retrieved by calling NutUdpCreateSocket().
  341. * \param optname Option to get.
  342. * \param optval Points to a buffer receiving the value.
  343. * \param optlen Length of the value buffer.
  344. *
  345. * \return 0 on success, -1 otherwise.
  346. */
  347. int NutUdpGetSockOpt(UDPSOCKET * sock, int optname, void *optval, int optlen)
  348. {
  349. int rc = -1;
  350. if (sock == 0)
  351. return -1;
  352. switch (optname) {
  353. case SO_RCVBUF:
  354. if (optval != 0 && optlen == sizeof(uint16_t)) {
  355. *((uint16_t *) optval) = sock->so_rx_bsz;
  356. rc = 0;
  357. }
  358. break;
  359. default:
  360. /* sock->so_last_error = ENOPROTOOPT; */
  361. break;
  362. }
  363. return rc;
  364. }
  365. /*!
  366. * \brief Set a UDP socket error.
  367. *
  368. * This function should only be used together (and from) the ICMP input routine
  369. *
  370. * The following values can be set:
  371. *
  372. * - #EHOSTUNREACH Host is unreachable
  373. *
  374. * \param sock Socket descriptor. This pointer must have been
  375. * retrieved by calling NutUdpCreateSocket().
  376. * \param remote_addr Remote IP address in network byte order
  377. * \param remote_port Remote port in network byte order
  378. * \param error Error number.
  379. *
  380. * \return 0 on success, -1 otherwise.
  381. */
  382. int NutUdpSetSocketError(UDPSOCKET * sock, uint32_t remote_addr, uint16_t remote_port, uint16_t error)
  383. {
  384. if (sock == 0)
  385. return -1;
  386. sock->so_remote_addr = remote_addr;
  387. sock->so_remote_port = remote_port;
  388. sock->so_last_error = error;
  389. /* post the event only, if a thread is waiting */
  390. if (sock->so_rx_rdy)
  391. NutEventPost(&sock->so_rx_rdy);
  392. return 0;
  393. }
  394. /*@}*/