bsd_socket.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833
  1. /**************************************************************************
  2. * Copyright (c) 2014 by Michael Fischer (www.emb4fun.de).
  3. * All rights reserved.
  4. *
  5. * Some parts are from the original BSD source, therefor:
  6. *
  7. * Partial Copyright (c) 1982, 1986, 1988, 1990, 1993
  8. * The Regents of the University of California. All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. *
  14. * 1. Redistributions of source code must retain the above copyright
  15. * notice, this list of conditions and the following disclaimer.
  16. * 2. Redistributions in binary form must reproduce the above copyright
  17. * notice, this list of conditions and the following disclaimer in the
  18. * documentation and/or other materials provided with the distribution.
  19. * 3. Neither the name of the author nor the names of its contributors may
  20. * be used to endorse or promote products derived from this software
  21. * without specific prior written permission.
  22. *
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  24. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  25. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  26. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  27. * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  28. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  29. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  30. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  31. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  32. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  33. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34. * SUCH DAMAGE.
  35. *
  36. ***************************************************************************
  37. * History:
  38. *
  39. * 26.01.2014 mifi First Version.
  40. * 27.01.2014 mifi More comments and connect added.
  41. * 28.01.2014 mifi Backlog functionality added.
  42. * 02.02.2014 mifi - Backlog does not work correct.
  43. * - Corrected sendto.
  44. * - Added support for setsockopt IP_ADD_MEMBERSHIP and
  45. * IP_DROP_MEMBERSHIP.
  46. * 04.02.2014 mifi Corrected backlog functionality.
  47. **************************************************************************/
  48. #define __BSD_SOCKET_C__
  49. /*=======================================================================*/
  50. /* Include */
  51. /*=======================================================================*/
  52. #include <stdlib.h>
  53. #include <string.h>
  54. #include <stdint.h>
  55. #include <net/if_var.h>
  56. #include <sys/semaphore.h>
  57. #include <sys/bsd_socket.h>
  58. #include <sys/socket.h>
  59. /*=======================================================================*/
  60. /* All Structures and Common Constants */
  61. /*=======================================================================*/
  62. /*
  63. * Wrapper for the BSD socket
  64. */
  65. typedef struct _bsd_socket_
  66. {
  67. int type; /* Used to distinguish TCP and UDP */
  68. uint16_t port; /* Used by accept */
  69. SEM backlog_sem; /* Used by accept and listen */
  70. int is_listen_sock; /* Used by accept */
  71. uint32_t udp_rcv_timeo; /* Used by NutUdpReceiveFrom */
  72. struct _bsd_socket_ *listen; /* Used by accept */
  73. TCPSOCKET *nut_tcp_sock; /* Handle to the NutNET TCP socket */
  74. UDPSOCKET *nut_udp_sock; /* Handle to the NutNET USP socket */
  75. } bsd_socket_t;
  76. /*=======================================================================*/
  77. /* Definition of all local Data */
  78. /*=======================================================================*/
  79. /*=======================================================================*/
  80. /* Definition of all local Procedures */
  81. /*=======================================================================*/
  82. /*=======================================================================*/
  83. /* All code exported */
  84. /*=======================================================================*/
  85. /*************************************************************************/
  86. /* socket */
  87. /* */
  88. /* Create a new unnamed socket for the given domain and type. */
  89. /* */
  90. /* In : domain, type, proto */
  91. /* Out : none */
  92. /* Return: Socket on success / -1 otherwise */
  93. /*************************************************************************/
  94. socket_t socket (int domain, int type, int proto)
  95. {
  96. bsd_socket_t *bsd_sock = (bsd_socket_t*)-1;
  97. TCPSOCKET *tcp_sock;
  98. UDPSOCKET *udp_sock;
  99. (void)proto; /* Not used */
  100. /* Check for the correct domain */
  101. if (AF_INET == domain)
  102. {
  103. /* Select the type */
  104. switch (type)
  105. {
  106. case SOCK_STREAM:
  107. {
  108. /* Create a NutNET socket */
  109. tcp_sock = NutTcpCreateSocket();
  110. if (tcp_sock != NULL)
  111. {
  112. /* Get memory for the wrapper */
  113. bsd_sock = (bsd_socket_t*)malloc(sizeof(bsd_socket_t));
  114. if (bsd_sock != NULL)
  115. {
  116. /* Clear the memory first */
  117. memset(bsd_sock, 0x00, sizeof(bsd_socket_t));
  118. /* Setup wrapper */
  119. bsd_sock->type = type;
  120. bsd_sock->nut_tcp_sock = tcp_sock;
  121. bsd_sock->nut_udp_sock = NULL;
  122. }
  123. else
  124. {
  125. /* No memory for the wrapper available, close NutNET socket */
  126. NutTcpCloseSocket(tcp_sock);
  127. }
  128. }
  129. break;
  130. } /* SOCK_STREAM */
  131. case SOCK_DGRAM:
  132. {
  133. /* Create a NutNET socket withg port 0 first, will be changed by bind */
  134. udp_sock = NutUdpCreateSocket(0);
  135. if (udp_sock != NULL)
  136. {
  137. /* Get memory for the wrapper */
  138. bsd_sock = (bsd_socket_t*)malloc(sizeof(bsd_socket_t));
  139. if (bsd_sock != NULL)
  140. {
  141. /* Clear the memory first */
  142. memset(bsd_sock, 0x00, sizeof(bsd_socket_t));
  143. /* Setup wrapper */
  144. bsd_sock->type = type;
  145. bsd_sock->nut_udp_sock = udp_sock;
  146. bsd_sock->nut_tcp_sock = NULL;
  147. }
  148. else
  149. {
  150. /* No memory for the wrapper available, close NutNET socket */
  151. NutUdpDestroySocket(udp_sock);
  152. }
  153. }
  154. break;
  155. } /* SOCK_DGRAM */
  156. default:
  157. {
  158. /* Wrong type */
  159. bsd_sock = (bsd_socket_t*)-1;
  160. break;
  161. }
  162. } /* end switch (type) */
  163. } /* end if (AF_INET == domain) */
  164. return( (socket_t)bsd_sock );
  165. } /* socket */
  166. /*************************************************************************/
  167. /* closesocket */
  168. /* */
  169. /* Close the socket and release the memory for the wrapper. */
  170. /* */
  171. /* Note: The socket may not be immediately destroyed after calling this */
  172. /* function. However, the application must not use the socket */
  173. /* after this call. */
  174. /* */
  175. /* In : sock */
  176. /* Out : none */
  177. /* Return: 0 on success / -1 otherwise */
  178. /*************************************************************************/
  179. int closesocket (socket_t sock)
  180. {
  181. int rc = -1;
  182. bsd_socket_t *bsd_sock = (bsd_socket_t*)sock;
  183. /* Select the type */
  184. switch (bsd_sock->type)
  185. {
  186. case SOCK_STREAM:
  187. {
  188. /* Check if the socket was not closed before */
  189. if (bsd_sock->nut_tcp_sock != NULL)
  190. {
  191. /* Close NutNET socket */
  192. rc = NutTcpCloseSocket(bsd_sock->nut_tcp_sock);
  193. }
  194. /*
  195. * Check if a listen socket is available, this is the case
  196. * if this socket was created by an accept. Now the backlog
  197. * must be handled too. The listen socket will be closed separately.
  198. */
  199. if (bsd_sock->listen)
  200. {
  201. /* Handle backlog */
  202. NutSemPost(&bsd_sock->listen->backlog_sem);
  203. /* Clear listen socket info */
  204. bsd_sock->listen = NULL;
  205. }
  206. /*
  207. * Check if this is the listen socket itself. In this
  208. * case the backlog semaphore must be deleted too.
  209. */
  210. if (bsd_sock->is_listen_sock)
  211. {
  212. NutSemDestroy(&bsd_sock->backlog_sem);
  213. }
  214. /* Clear socket info */
  215. bsd_sock->nut_tcp_sock = NULL;
  216. /* Free the wrapper memory */
  217. free(bsd_sock);
  218. break;
  219. } /* SOCK_STREAM */
  220. case SOCK_DGRAM:
  221. {
  222. /* Check if the socket was not closed before */
  223. if (bsd_sock->nut_udp_sock != NULL)
  224. {
  225. /* Close NutNET socket */
  226. rc = NutUdpDestroySocket(bsd_sock->nut_udp_sock);
  227. }
  228. /* Free the wrapper memory */
  229. free(bsd_sock);
  230. break;
  231. } /* SOCK_DGRAM */
  232. default:
  233. {
  234. /* Wrong type */
  235. rc = -1;
  236. break;
  237. }
  238. } /* end switch (bsd_sock->type) */
  239. return(rc);
  240. } /* closesocket */
  241. /*************************************************************************/
  242. /* shutdown */
  243. /* */
  244. /* Close one or both direction of the socket. */
  245. /* */
  246. /* Note: The socket itself must be still closed with closesocket. */
  247. /* */
  248. /* In : sock, how */
  249. /* Out : none */
  250. /* Return: 0 on success / -1 otherwise */
  251. /*************************************************************************/
  252. int shutdown (socket_t sock, int how)
  253. {
  254. (void)sock;
  255. (void)how;
  256. /*
  257. * Functionality not supported.
  258. * But we need the function to setup
  259. * the linker if the application use it.
  260. */
  261. return(0);
  262. } /* shutdown */
  263. /*************************************************************************/
  264. /* bind */
  265. /* */
  266. /* Bind the local address to the socket. */
  267. /* */
  268. /* In : sock, addr, addr_len */
  269. /* Out : none */
  270. /* Return: 0 on success / -1 otherwise */
  271. /*************************************************************************/
  272. int bind (socket_t sock, struct sockaddr *addr, int addr_len)
  273. {
  274. int rc = -1;
  275. bsd_socket_t *bsd_sock = (bsd_socket_t*)sock;
  276. struct sockaddr_in *addr_in = (struct sockaddr_in*)addr;
  277. /* Check for correct length */
  278. if (sizeof(struct sockaddr_in) == addr_len)
  279. {
  280. /* Store port info for later use, e.g. accept */
  281. bsd_sock->port = ntohs(addr_in->sin_port);
  282. /* Correct port in case of UDP */
  283. if (SOCK_DGRAM == bsd_sock->type)
  284. {
  285. /*
  286. * The UDP socket was created with port 0,
  287. * set now the correct port.
  288. */
  289. bsd_sock->nut_udp_sock->so_local_port = addr_in->sin_port;
  290. }
  291. rc = 0;
  292. }
  293. return(rc);
  294. } /* bind */
  295. /*************************************************************************/
  296. /* listen */
  297. /* */
  298. /* Prepare a socket to accept incomming connections. */
  299. /* */
  300. /* In : sock, backlog */
  301. /* Out : none */
  302. /* Return: 0 on success / -1 otherwise */
  303. /*************************************************************************/
  304. int listen (socket_t sock, int backlog)
  305. {
  306. int rc = -1;
  307. bsd_socket_t *bsd_sock = (bsd_socket_t*)sock;
  308. /* listen is not supported for UDP */
  309. if (SOCK_DGRAM == bsd_sock->type)
  310. {
  311. return(-1);
  312. }
  313. if (backlog > 0)
  314. {
  315. /* Mark socket as listen */
  316. bsd_sock->is_listen_sock = 1;
  317. /* Create backlog semaphore */
  318. NutSemInit(&bsd_sock->backlog_sem, (short)backlog);
  319. rc = 0;
  320. }
  321. return(rc);
  322. } /* listen */
  323. /*************************************************************************/
  324. /* accept */
  325. /* */
  326. /* Wait for incoming connect from a remote socket. */
  327. /* */
  328. /* In : sock, addr, addr_len */
  329. /* Out : none */
  330. /* Return: socket on success / -1 otherwise */
  331. /*************************************************************************/
  332. socket_t accept (socket_t sock, struct sockaddr *addr, int *addr_len)
  333. {
  334. int rc;
  335. socket_t ClientSocket = -1;
  336. bsd_socket_t *bsd_sock_listen = (bsd_socket_t*)sock;
  337. struct sockaddr_in *addr_in = (struct sockaddr_in*)addr;
  338. bsd_socket_t *bsd_sock_client;
  339. /* accept is not supported for UDP */
  340. if (SOCK_DGRAM == bsd_sock_listen->type)
  341. {
  342. return(-1);
  343. }
  344. /* Check for correct length */
  345. if (sizeof(struct sockaddr_in) == *addr_len)
  346. {
  347. /* Clear addr, and set default values */
  348. memset(addr, 0x00, *addr_len);
  349. addr_in->sin_family = AF_INET;
  350. addr_in->sin_len = sizeof(struct sockaddr_in);
  351. /* Check if we could create a new socket */
  352. NutSemWait(&bsd_sock_listen->backlog_sem);
  353. /* Create a new TCP socket */
  354. ClientSocket = socket(AF_INET, SOCK_STREAM, 0);
  355. if (ClientSocket != -1)
  356. {
  357. /* Convert to BSD socket */
  358. bsd_sock_client = (bsd_socket_t *)ClientSocket;
  359. /* Set listen information */
  360. bsd_sock_client->listen = bsd_sock_listen;
  361. /* Wait for incoming connect from a remote socket */
  362. rc = NutTcpAccept(bsd_sock_client->nut_tcp_sock, bsd_sock_listen->port);
  363. if (0 == rc)
  364. {
  365. /* Set address information of the remote side */
  366. addr_in->sin_port = bsd_sock_listen->nut_tcp_sock->so_remote_port;
  367. addr_in->sin_addr.s_addr = bsd_sock_listen->nut_tcp_sock->so_remote_addr;
  368. }
  369. else
  370. {
  371. /* Error, This should not happen */
  372. NutSemPost(&bsd_sock_listen->backlog_sem);
  373. NutTcpCloseSocket(bsd_sock_client->nut_tcp_sock);
  374. ClientSocket = -1;
  375. }
  376. }
  377. } /* end if (sizeof(struct sockaddr_in) == *addr_len) */
  378. return(ClientSocket);
  379. } /* accept */
  380. /*************************************************************************/
  381. /* connect */
  382. /* */
  383. /* Connect to a remote socket. */
  384. /* */
  385. /* In : sock, addr, addr_len */
  386. /* Out : none */
  387. /* Return: 0 on success / -1 otherwise */
  388. /*************************************************************************/
  389. int connect (socket_t sock, struct sockaddr *addr, int addr_len)
  390. {
  391. int rc = -1;
  392. bsd_socket_t *bsd_sock = (bsd_socket_t*)sock;
  393. struct sockaddr_in *addr_in = (struct sockaddr_in*)addr;
  394. uint32_t remote_addr;
  395. uint16_t remote_port;
  396. /* accept is not supported for UDP */
  397. if (SOCK_DGRAM == bsd_sock->type)
  398. {
  399. return(-1);
  400. }
  401. /* Check for correct length */
  402. if (sizeof(struct sockaddr_in) == addr_len)
  403. {
  404. remote_addr = addr_in->sin_addr.s_addr;
  405. remote_port = htons(addr_in->sin_port);
  406. /* Connect to a remote socket */
  407. rc = NutTcpConnect(bsd_sock->nut_tcp_sock, remote_addr, remote_port);
  408. }
  409. return(rc);
  410. } /* connect */
  411. /*************************************************************************/
  412. /* recv */
  413. /* */
  414. /* Receive data on a connected TCP socket. */
  415. /* */
  416. /* In : sock, data, len, flags */
  417. /* Out : none */
  418. /* Return: 0 or > 0 on success / -1 otherwise */
  419. /*************************************************************************/
  420. int recv (socket_t sock, void *data, size_t len, int flags)
  421. {
  422. int rc;
  423. bsd_socket_t *bsd_sock = (bsd_socket_t*)sock;
  424. (void)flags;
  425. /* recv is not supported for UDP */
  426. if (SOCK_DGRAM == bsd_sock->type)
  427. {
  428. return(-1);
  429. }
  430. /* Receive data on a connected TCP socket */
  431. rc = NutTcpReceive(bsd_sock->nut_tcp_sock, data, (int)len);
  432. return(rc);
  433. } /* recv */
  434. /*************************************************************************/
  435. /* recvfrom */
  436. /* */
  437. /* Receive a UDP datagram. */
  438. /* */
  439. /* In : sock, data, len, flags, addr, addr_len */
  440. /* Out : none */
  441. /* Return: 0 or > 0 on success / -1 otherwise */
  442. /*************************************************************************/
  443. int recvfrom (socket_t sock, void *data, size_t len, int flags, struct sockaddr *addr, int *addr_len)
  444. {
  445. int rc = -1;
  446. bsd_socket_t *bsd_sock = (bsd_socket_t*)sock;
  447. struct sockaddr_in *addr_in = (struct sockaddr_in*)addr;
  448. uint32_t remote_addr;
  449. uint16_t remote_port;
  450. (void)flags;
  451. /* recvfrom is not supported for TCP */
  452. if (SOCK_STREAM == bsd_sock->type)
  453. {
  454. return(-1);
  455. }
  456. /* Check for correct length */
  457. if (sizeof(struct sockaddr_in) == *addr_len)
  458. {
  459. /* Clear addr, and set default values */
  460. memset(addr, 0x00, *addr_len);
  461. addr_in->sin_family = AF_INET;
  462. addr_in->sin_len = sizeof(struct sockaddr_in);
  463. /* Receive a UDP datagram */
  464. rc = NutUdpReceiveFrom(bsd_sock->nut_udp_sock, &remote_addr, &remote_port,
  465. data, (int)len, bsd_sock->udp_rcv_timeo);
  466. if (rc > 0)
  467. {
  468. /* Set address information of the remote side */
  469. addr_in->sin_port = htons(remote_port);
  470. addr_in->sin_addr.s_addr = remote_addr;
  471. }
  472. }
  473. return(rc);
  474. } /* recvfrom */
  475. /*************************************************************************/
  476. /* send */
  477. /* */
  478. /* Send data on a connected TCP socket. */
  479. /* */
  480. /* In : sock, data, len, flags */
  481. /* Out : none */
  482. /* Return: 0 or > 0 on success / -1 otherwise */
  483. /*************************************************************************/
  484. int send (socket_t sock, void *data, size_t len, int flags)
  485. {
  486. int rc = 0;
  487. bsd_socket_t *bsd_sock = (bsd_socket_t*)sock;
  488. (void)flags;
  489. /* send is not supported for UDP */
  490. if (SOCK_DGRAM == bsd_sock->type)
  491. {
  492. return(-1);
  493. }
  494. /* Send data on a connected TCP socket */
  495. rc = NutTcpSend(bsd_sock->nut_tcp_sock, data, (int)len);
  496. return(rc);
  497. } /* send */
  498. /*************************************************************************/
  499. /* sendto */
  500. /* */
  501. /* Send a UDP datagram. */
  502. /* */
  503. /* In : sock, data, len, flags, addr, addr_len */
  504. /* Out : none */
  505. /* Return: 0 or > 0 on success / -1 otherwise */
  506. /*************************************************************************/
  507. int sendto (socket_t sock, void *data, size_t len, int flags, struct sockaddr *addr, int addr_len)
  508. {
  509. int rc = -1;
  510. bsd_socket_t *bsd_sock = (bsd_socket_t*)sock;
  511. struct sockaddr_in *addr_in = (struct sockaddr_in*)addr;
  512. uint32_t remote_addr;
  513. uint16_t remote_port;
  514. (void)flags;
  515. /* recvfrom is not supported for TCP */
  516. if (SOCK_STREAM == bsd_sock->type)
  517. {
  518. return(-1);
  519. }
  520. /* Check for correct length */
  521. if (sizeof(struct sockaddr_in) == addr_len)
  522. {
  523. remote_addr = addr_in->sin_addr.s_addr;
  524. remote_port = htons(addr_in->sin_port);
  525. /* Send a UDP datagram */
  526. rc = NutUdpSendTo(bsd_sock->nut_udp_sock, remote_addr, remote_port,
  527. data, (int)len);
  528. if (0 == rc)
  529. {
  530. rc = (int)len;
  531. }
  532. }
  533. return(rc);
  534. } /* sendto */
  535. /*************************************************************************/
  536. /* getsockname */
  537. /* */
  538. /* Return the local address information bound to the socket. */
  539. /* */
  540. /* In : sock, addr, addr_len */
  541. /* Out : none */
  542. /* Return: 0 on success / -1 otherwise */
  543. /*************************************************************************/
  544. int getsockname (socket_t sock, struct sockaddr *addr, int *addr_len)
  545. {
  546. int rc = -1;
  547. bsd_socket_t *bsd_sock = (bsd_socket_t*)sock;
  548. struct sockaddr_in *addr_in = (struct sockaddr_in*)addr;
  549. /* Check for correct length */
  550. if (sizeof(struct sockaddr_in) == *addr_len)
  551. {
  552. /* Clear address info first */
  553. memset(addr, 0x00, *addr_len);
  554. /* Set local address information */
  555. addr_in->sin_len = sizeof(struct sockaddr_in);
  556. addr_in->sin_family = AF_INET;
  557. addr_in->sin_port = bsd_sock->nut_tcp_sock->so_local_port;
  558. addr_in->sin_addr.s_addr = bsd_sock->nut_tcp_sock->so_local_addr;
  559. rc = 0;
  560. }
  561. return(rc);
  562. } /* getsockname */
  563. /*************************************************************************/
  564. /* getpeername */
  565. /* */
  566. /* Return the remote address information bound to the socket. */
  567. /* */
  568. /* In : sock, addr, addr_len */
  569. /* Out : none */
  570. /* Return: 0 on success / -1 otherwise */
  571. /*************************************************************************/
  572. int getpeername (socket_t sock, struct sockaddr *addr, int *addr_len)
  573. {
  574. int rc = -1;
  575. bsd_socket_t *bsd_sock = (bsd_socket_t*)sock;
  576. struct sockaddr_in *addr_in = (struct sockaddr_in*)addr;
  577. /* Check for correct length */
  578. if (sizeof(struct sockaddr_in) == *addr_len)
  579. {
  580. /* Clear address info first */
  581. memset(addr, 0x00, *addr_len);
  582. /* Set remote address information */
  583. addr_in->sin_len = sizeof(struct sockaddr_in);
  584. addr_in->sin_family = AF_INET;
  585. addr_in->sin_port = bsd_sock->nut_tcp_sock->so_remote_port;
  586. addr_in->sin_addr.s_addr = bsd_sock->nut_tcp_sock->so_remote_addr;
  587. rc = 0;
  588. }
  589. return(rc);
  590. } /* getpeername */
  591. /*************************************************************************/
  592. /* getsockopt */
  593. /* */
  594. /* Get a TCP / UDP socket option value. */
  595. /* */
  596. /* In : sock, level, optname, optval, optlen */
  597. /* Out : none */
  598. /* Return: 0 on success / -1 otherwise */
  599. /*************************************************************************/
  600. int getsockopt (socket_t sock, int level, int optname, void *optval, int optlen)
  601. {
  602. int rc = -1;
  603. bsd_socket_t *bsd_sock = (bsd_socket_t*)sock;
  604. /* Check for the correct level */
  605. if (SOL_SOCKET == level)
  606. {
  607. switch (optname)
  608. {
  609. case SO_ERROR: /* Last error is available for TCP and UDP */
  610. {
  611. /* Get the last error information, and clear it */
  612. if ((optval != NULL) && (sizeof(int) == optlen))
  613. {
  614. /* Last error */
  615. *((int*)optval) = NutTcpError(bsd_sock->nut_tcp_sock);
  616. /* Clear info */
  617. bsd_sock->nut_tcp_sock->so_last_error = 0;
  618. rc = 0;
  619. }
  620. break;
  621. } /* SO_ERROR */
  622. default:
  623. {
  624. /* Check for stream or datagram */
  625. if (SOCK_STREAM == bsd_sock->type)
  626. {
  627. /* It is a stream socket, get the option value */
  628. rc = NutTcpGetSockOpt(bsd_sock->nut_tcp_sock, optname, optval, optlen);
  629. }
  630. else
  631. {
  632. /* It must be a datagram socket */
  633. if (SO_RCVTIMEO == optname) /* <= special case, receive timeout */
  634. {
  635. /* Yes, receive timeout, check optval and optlen */
  636. if ((optval != NULL) && (sizeof(uint32_t) == optlen))
  637. {
  638. /* Get requested information */
  639. *((uint32_t*)optval) = bsd_sock->udp_rcv_timeo;
  640. rc = 0;
  641. }
  642. }
  643. else
  644. {
  645. /* Get the datagram option value */
  646. rc = NutUdpGetSockOpt(bsd_sock->nut_udp_sock, optname, optval, optlen);
  647. }
  648. }
  649. break;
  650. } /* default */
  651. } /* end switch (optname) */
  652. } /* end if (SOL_SOCKET == level) */
  653. return(rc);
  654. } /* getsockopt */
  655. /*************************************************************************/
  656. /* setsockopt */
  657. /* */
  658. /* Set value of a TCP socket option. */
  659. /* */
  660. /* In : sock, level, optname, optval, optlen */
  661. /* Out : none */
  662. /* Return: 0 on success / -1 otherwise */
  663. /*************************************************************************/
  664. int setsockopt (socket_t sock, int level, int optname, void *optval, int optlen)
  665. {
  666. int rc = -1;
  667. bsd_socket_t *bsd_sock = (bsd_socket_t*)sock;
  668. /* Check for the correct level */
  669. if (SOL_SOCKET == level)
  670. {
  671. /* Check for stream or datagram */
  672. if (SOCK_STREAM == bsd_sock->type)
  673. {
  674. /* It is a stream socket, set the option value */
  675. rc = NutTcpSetSockOpt(bsd_sock->nut_tcp_sock, optname, optval, optlen);
  676. }
  677. else
  678. {
  679. /* Check for receive timeout */
  680. if (SO_RCVTIMEO == optname)
  681. {
  682. /* Yes, receive timeout, check optval and optlen */
  683. if ((optval != NULL) && (sizeof(uint32_t) == optlen))
  684. {
  685. /* Set requested information */
  686. bsd_sock->udp_rcv_timeo = *((uint32_t*)optval);
  687. rc = 0;
  688. }
  689. }
  690. else
  691. {
  692. /* Set the datagram option value */
  693. rc = NutUdpSetSockOpt(bsd_sock->nut_udp_sock, optname, optval, optlen);
  694. } /* end if (SO_RCVTIMEO == optname) */
  695. } /* end if (SOCK_STREAM == bsd_sock->type) */
  696. } /* end if (SOL_SOCKET == level) */
  697. /* Check for the correct level */
  698. if (IPPROTO_IP == level)
  699. {
  700. switch (optname)
  701. {
  702. case IP_ADD_MEMBERSHIP:
  703. {
  704. struct ip_mreq *mreq;
  705. if ((optlen == sizeof(struct ip_mreq)) && (optval != NULL))
  706. {
  707. mreq = (struct ip_mreq *)optval;
  708. rc = NutNetIfAddMcastAddr("eth0", mreq->imr_multiaddr.s_addr);
  709. }
  710. break;
  711. } /* IP_ADD_MEMBERSHIP */
  712. case IP_DROP_MEMBERSHIP:
  713. {
  714. struct ip_mreq *mreq;
  715. if ((optlen == sizeof(struct ip_mreq)) && (optval != NULL))
  716. {
  717. mreq = (struct ip_mreq *)optval;
  718. rc = NutNetIfDelMcastAddr("eth0", mreq->imr_multiaddr.s_addr);
  719. }
  720. break;
  721. } /* IP_DROP_MEMBERSHIP */
  722. default:
  723. {
  724. /* Do nothing */
  725. break;
  726. }
  727. }
  728. } /* end if (IPPROTO_IP == level) */
  729. return(rc);
  730. } /* setsockopt */
  731. /*** EOF ***/