| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833 |
- /**************************************************************************
- * Copyright (c) 2014 by Michael Fischer (www.emb4fun.de).
- * All rights reserved.
- *
- * Some parts are from the original BSD source, therefor:
- *
- * Partial Copyright (c) 1982, 1986, 1988, 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the author nor the names of its contributors may
- * be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- ***************************************************************************
- * History:
- *
- * 26.01.2014 mifi First Version.
- * 27.01.2014 mifi More comments and connect added.
- * 28.01.2014 mifi Backlog functionality added.
- * 02.02.2014 mifi - Backlog does not work correct.
- * - Corrected sendto.
- * - Added support for setsockopt IP_ADD_MEMBERSHIP and
- * IP_DROP_MEMBERSHIP.
- * 04.02.2014 mifi Corrected backlog functionality.
- **************************************************************************/
- #define __BSD_SOCKET_C__
- /*=======================================================================*/
- /* Include */
- /*=======================================================================*/
- #include <stdlib.h>
- #include <string.h>
- #include <stdint.h>
- #include <net/if_var.h>
- #include <sys/semaphore.h>
- #include <sys/bsd_socket.h>
- #include <sys/socket.h>
- /*=======================================================================*/
- /* All Structures and Common Constants */
- /*=======================================================================*/
- /*
- * Wrapper for the BSD socket
- */
- typedef struct _bsd_socket_
- {
- int type; /* Used to distinguish TCP and UDP */
- uint16_t port; /* Used by accept */
- SEM backlog_sem; /* Used by accept and listen */
- int is_listen_sock; /* Used by accept */
- uint32_t udp_rcv_timeo; /* Used by NutUdpReceiveFrom */
- struct _bsd_socket_ *listen; /* Used by accept */
-
- TCPSOCKET *nut_tcp_sock; /* Handle to the NutNET TCP socket */
- UDPSOCKET *nut_udp_sock; /* Handle to the NutNET USP socket */
- } bsd_socket_t;
- /*=======================================================================*/
- /* Definition of all local Data */
- /*=======================================================================*/
- /*=======================================================================*/
- /* Definition of all local Procedures */
- /*=======================================================================*/
- /*=======================================================================*/
- /* All code exported */
- /*=======================================================================*/
- /*************************************************************************/
- /* socket */
- /* */
- /* Create a new unnamed socket for the given domain and type. */
- /* */
- /* In : domain, type, proto */
- /* Out : none */
- /* Return: Socket on success / -1 otherwise */
- /*************************************************************************/
- socket_t socket (int domain, int type, int proto)
- {
- bsd_socket_t *bsd_sock = (bsd_socket_t*)-1;
- TCPSOCKET *tcp_sock;
- UDPSOCKET *udp_sock;
-
- (void)proto; /* Not used */
-
- /* Check for the correct domain */
- if (AF_INET == domain)
- {
- /* Select the type */
- switch (type)
- {
- case SOCK_STREAM:
- {
- /* Create a NutNET socket */
- tcp_sock = NutTcpCreateSocket();
- if (tcp_sock != NULL)
- {
- /* Get memory for the wrapper */
- bsd_sock = (bsd_socket_t*)malloc(sizeof(bsd_socket_t));
- if (bsd_sock != NULL)
- {
- /* Clear the memory first */
- memset(bsd_sock, 0x00, sizeof(bsd_socket_t));
-
- /* Setup wrapper */
- bsd_sock->type = type;
- bsd_sock->nut_tcp_sock = tcp_sock;
- bsd_sock->nut_udp_sock = NULL;
- }
- else
- {
- /* No memory for the wrapper available, close NutNET socket */
- NutTcpCloseSocket(tcp_sock);
- }
- }
- break;
- } /* SOCK_STREAM */
-
- case SOCK_DGRAM:
- {
- /* Create a NutNET socket withg port 0 first, will be changed by bind */
- udp_sock = NutUdpCreateSocket(0);
- if (udp_sock != NULL)
- {
- /* Get memory for the wrapper */
- bsd_sock = (bsd_socket_t*)malloc(sizeof(bsd_socket_t));
- if (bsd_sock != NULL)
- {
- /* Clear the memory first */
- memset(bsd_sock, 0x00, sizeof(bsd_socket_t));
- /* Setup wrapper */
- bsd_sock->type = type;
- bsd_sock->nut_udp_sock = udp_sock;
- bsd_sock->nut_tcp_sock = NULL;
- }
- else
- {
- /* No memory for the wrapper available, close NutNET socket */
- NutUdpDestroySocket(udp_sock);
- }
- }
- break;
- } /* SOCK_DGRAM */
-
- default:
- {
- /* Wrong type */
- bsd_sock = (bsd_socket_t*)-1;
- break;
- }
- } /* end switch (type) */
- } /* end if (AF_INET == domain) */
-
- return( (socket_t)bsd_sock );
- } /* socket */
- /*************************************************************************/
- /* closesocket */
- /* */
- /* Close the socket and release the memory for the wrapper. */
- /* */
- /* Note: The socket may not be immediately destroyed after calling this */
- /* function. However, the application must not use the socket */
- /* after this call. */
- /* */
- /* In : sock */
- /* Out : none */
- /* Return: 0 on success / -1 otherwise */
- /*************************************************************************/
- int closesocket (socket_t sock)
- {
- int rc = -1;
- bsd_socket_t *bsd_sock = (bsd_socket_t*)sock;
-
- /* Select the type */
- switch (bsd_sock->type)
- {
- case SOCK_STREAM:
- {
- /* Check if the socket was not closed before */
- if (bsd_sock->nut_tcp_sock != NULL)
- {
- /* Close NutNET socket */
- rc = NutTcpCloseSocket(bsd_sock->nut_tcp_sock);
- }
-
- /*
- * Check if a listen socket is available, this is the case
- * if this socket was created by an accept. Now the backlog
- * must be handled too. The listen socket will be closed separately.
- */
- if (bsd_sock->listen)
- {
- /* Handle backlog */
- NutSemPost(&bsd_sock->listen->backlog_sem);
-
- /* Clear listen socket info */
- bsd_sock->listen = NULL;
- }
-
- /*
- * Check if this is the listen socket itself. In this
- * case the backlog semaphore must be deleted too.
- */
- if (bsd_sock->is_listen_sock)
- {
- NutSemDestroy(&bsd_sock->backlog_sem);
- }
- /* Clear socket info */
- bsd_sock->nut_tcp_sock = NULL;
-
- /* Free the wrapper memory */
- free(bsd_sock);
- break;
- } /* SOCK_STREAM */
-
- case SOCK_DGRAM:
- {
- /* Check if the socket was not closed before */
- if (bsd_sock->nut_udp_sock != NULL)
- {
- /* Close NutNET socket */
- rc = NutUdpDestroySocket(bsd_sock->nut_udp_sock);
- }
-
- /* Free the wrapper memory */
- free(bsd_sock);
- break;
- } /* SOCK_DGRAM */
-
- default:
- {
- /* Wrong type */
- rc = -1;
- break;
- }
- } /* end switch (bsd_sock->type) */
-
- return(rc);
- } /* closesocket */
- /*************************************************************************/
- /* shutdown */
- /* */
- /* Close one or both direction of the socket. */
- /* */
- /* Note: The socket itself must be still closed with closesocket. */
- /* */
- /* In : sock, how */
- /* Out : none */
- /* Return: 0 on success / -1 otherwise */
- /*************************************************************************/
- int shutdown (socket_t sock, int how)
- {
- (void)sock;
- (void)how;
-
- /*
- * Functionality not supported.
- * But we need the function to setup
- * the linker if the application use it.
- */
-
- return(0);
- } /* shutdown */
- /*************************************************************************/
- /* bind */
- /* */
- /* Bind the local address to the socket. */
- /* */
- /* In : sock, addr, addr_len */
- /* Out : none */
- /* Return: 0 on success / -1 otherwise */
- /*************************************************************************/
- int bind (socket_t sock, struct sockaddr *addr, int addr_len)
- {
- int rc = -1;
- bsd_socket_t *bsd_sock = (bsd_socket_t*)sock;
- struct sockaddr_in *addr_in = (struct sockaddr_in*)addr;
-
- /* Check for correct length */
- if (sizeof(struct sockaddr_in) == addr_len)
- {
- /* Store port info for later use, e.g. accept */
- bsd_sock->port = ntohs(addr_in->sin_port);
-
- /* Correct port in case of UDP */
- if (SOCK_DGRAM == bsd_sock->type)
- {
- /*
- * The UDP socket was created with port 0,
- * set now the correct port.
- */
- bsd_sock->nut_udp_sock->so_local_port = addr_in->sin_port;
- }
-
- rc = 0;
- }
-
- return(rc);
- } /* bind */
- /*************************************************************************/
- /* listen */
- /* */
- /* Prepare a socket to accept incomming connections. */
- /* */
- /* In : sock, backlog */
- /* Out : none */
- /* Return: 0 on success / -1 otherwise */
- /*************************************************************************/
- int listen (socket_t sock, int backlog)
- {
- int rc = -1;
- bsd_socket_t *bsd_sock = (bsd_socket_t*)sock;
-
- /* listen is not supported for UDP */
- if (SOCK_DGRAM == bsd_sock->type)
- {
- return(-1);
- }
- if (backlog > 0)
- {
- /* Mark socket as listen */
- bsd_sock->is_listen_sock = 1;
-
- /* Create backlog semaphore */
- NutSemInit(&bsd_sock->backlog_sem, (short)backlog);
-
- rc = 0;
- }
-
- return(rc);
- } /* listen */
- /*************************************************************************/
- /* accept */
- /* */
- /* Wait for incoming connect from a remote socket. */
- /* */
- /* In : sock, addr, addr_len */
- /* Out : none */
- /* Return: socket on success / -1 otherwise */
- /*************************************************************************/
- socket_t accept (socket_t sock, struct sockaddr *addr, int *addr_len)
- {
- int rc;
- socket_t ClientSocket = -1;
- bsd_socket_t *bsd_sock_listen = (bsd_socket_t*)sock;
- struct sockaddr_in *addr_in = (struct sockaddr_in*)addr;
- bsd_socket_t *bsd_sock_client;
-
- /* accept is not supported for UDP */
- if (SOCK_DGRAM == bsd_sock_listen->type)
- {
- return(-1);
- }
- /* Check for correct length */
- if (sizeof(struct sockaddr_in) == *addr_len)
- {
- /* Clear addr, and set default values */
- memset(addr, 0x00, *addr_len);
- addr_in->sin_family = AF_INET;
- addr_in->sin_len = sizeof(struct sockaddr_in);
-
- /* Check if we could create a new socket */
- NutSemWait(&bsd_sock_listen->backlog_sem);
-
- /* Create a new TCP socket */
- ClientSocket = socket(AF_INET, SOCK_STREAM, 0);
- if (ClientSocket != -1)
- {
- /* Convert to BSD socket */
- bsd_sock_client = (bsd_socket_t *)ClientSocket;
-
- /* Set listen information */
- bsd_sock_client->listen = bsd_sock_listen;
-
- /* Wait for incoming connect from a remote socket */
- rc = NutTcpAccept(bsd_sock_client->nut_tcp_sock, bsd_sock_listen->port);
- if (0 == rc)
- {
- /* Set address information of the remote side */
- addr_in->sin_port = bsd_sock_listen->nut_tcp_sock->so_remote_port;
- addr_in->sin_addr.s_addr = bsd_sock_listen->nut_tcp_sock->so_remote_addr;
- }
- else
- {
- /* Error, This should not happen */
- NutSemPost(&bsd_sock_listen->backlog_sem);
- NutTcpCloseSocket(bsd_sock_client->nut_tcp_sock);
- ClientSocket = -1;
- }
- }
- } /* end if (sizeof(struct sockaddr_in) == *addr_len) */
-
- return(ClientSocket);
- } /* accept */
- /*************************************************************************/
- /* connect */
- /* */
- /* Connect to a remote socket. */
- /* */
- /* In : sock, addr, addr_len */
- /* Out : none */
- /* Return: 0 on success / -1 otherwise */
- /*************************************************************************/
- int connect (socket_t sock, struct sockaddr *addr, int addr_len)
- {
- int rc = -1;
- bsd_socket_t *bsd_sock = (bsd_socket_t*)sock;
- struct sockaddr_in *addr_in = (struct sockaddr_in*)addr;
- uint32_t remote_addr;
- uint16_t remote_port;
-
- /* accept is not supported for UDP */
- if (SOCK_DGRAM == bsd_sock->type)
- {
- return(-1);
- }
-
- /* Check for correct length */
- if (sizeof(struct sockaddr_in) == addr_len)
- {
- remote_addr = addr_in->sin_addr.s_addr;
- remote_port = htons(addr_in->sin_port);
-
- /* Connect to a remote socket */
- rc = NutTcpConnect(bsd_sock->nut_tcp_sock, remote_addr, remote_port);
- }
-
- return(rc);
- } /* connect */
- /*************************************************************************/
- /* recv */
- /* */
- /* Receive data on a connected TCP socket. */
- /* */
- /* In : sock, data, len, flags */
- /* Out : none */
- /* Return: 0 or > 0 on success / -1 otherwise */
- /*************************************************************************/
- int recv (socket_t sock, void *data, size_t len, int flags)
- {
- int rc;
- bsd_socket_t *bsd_sock = (bsd_socket_t*)sock;
- (void)flags;
-
- /* recv is not supported for UDP */
- if (SOCK_DGRAM == bsd_sock->type)
- {
- return(-1);
- }
-
- /* Receive data on a connected TCP socket */
- rc = NutTcpReceive(bsd_sock->nut_tcp_sock, data, (int)len);
-
- return(rc);
- } /* recv */
- /*************************************************************************/
- /* recvfrom */
- /* */
- /* Receive a UDP datagram. */
- /* */
- /* In : sock, data, len, flags, addr, addr_len */
- /* Out : none */
- /* Return: 0 or > 0 on success / -1 otherwise */
- /*************************************************************************/
- int recvfrom (socket_t sock, void *data, size_t len, int flags, struct sockaddr *addr, int *addr_len)
- {
- int rc = -1;
- bsd_socket_t *bsd_sock = (bsd_socket_t*)sock;
- struct sockaddr_in *addr_in = (struct sockaddr_in*)addr;
- uint32_t remote_addr;
- uint16_t remote_port;
- (void)flags;
-
- /* recvfrom is not supported for TCP */
- if (SOCK_STREAM == bsd_sock->type)
- {
- return(-1);
- }
- /* Check for correct length */
- if (sizeof(struct sockaddr_in) == *addr_len)
- {
- /* Clear addr, and set default values */
- memset(addr, 0x00, *addr_len);
- addr_in->sin_family = AF_INET;
- addr_in->sin_len = sizeof(struct sockaddr_in);
- /* Receive a UDP datagram */
- rc = NutUdpReceiveFrom(bsd_sock->nut_udp_sock, &remote_addr, &remote_port,
- data, (int)len, bsd_sock->udp_rcv_timeo);
- if (rc > 0)
- {
- /* Set address information of the remote side */
- addr_in->sin_port = htons(remote_port);
- addr_in->sin_addr.s_addr = remote_addr;
- }
- }
-
- return(rc);
- } /* recvfrom */
- /*************************************************************************/
- /* send */
- /* */
- /* Send data on a connected TCP socket. */
- /* */
- /* In : sock, data, len, flags */
- /* Out : none */
- /* Return: 0 or > 0 on success / -1 otherwise */
- /*************************************************************************/
- int send (socket_t sock, void *data, size_t len, int flags)
- {
- int rc = 0;
- bsd_socket_t *bsd_sock = (bsd_socket_t*)sock;
-
- (void)flags;
-
- /* send is not supported for UDP */
- if (SOCK_DGRAM == bsd_sock->type)
- {
- return(-1);
- }
-
- /* Send data on a connected TCP socket */
- rc = NutTcpSend(bsd_sock->nut_tcp_sock, data, (int)len);
-
- return(rc);
- } /* send */
- /*************************************************************************/
- /* sendto */
- /* */
- /* Send a UDP datagram. */
- /* */
- /* In : sock, data, len, flags, addr, addr_len */
- /* Out : none */
- /* Return: 0 or > 0 on success / -1 otherwise */
- /*************************************************************************/
- int sendto (socket_t sock, void *data, size_t len, int flags, struct sockaddr *addr, int addr_len)
- {
- int rc = -1;
- bsd_socket_t *bsd_sock = (bsd_socket_t*)sock;
- struct sockaddr_in *addr_in = (struct sockaddr_in*)addr;
- uint32_t remote_addr;
- uint16_t remote_port;
- (void)flags;
-
- /* recvfrom is not supported for TCP */
- if (SOCK_STREAM == bsd_sock->type)
- {
- return(-1);
- }
- /* Check for correct length */
- if (sizeof(struct sockaddr_in) == addr_len)
- {
- remote_addr = addr_in->sin_addr.s_addr;
- remote_port = htons(addr_in->sin_port);
-
- /* Send a UDP datagram */
- rc = NutUdpSendTo(bsd_sock->nut_udp_sock, remote_addr, remote_port,
- data, (int)len);
- if (0 == rc)
- {
- rc = (int)len;
- }
- }
- return(rc);
- } /* sendto */
- /*************************************************************************/
- /* getsockname */
- /* */
- /* Return the local address information bound to the socket. */
- /* */
- /* In : sock, addr, addr_len */
- /* Out : none */
- /* Return: 0 on success / -1 otherwise */
- /*************************************************************************/
- int getsockname (socket_t sock, struct sockaddr *addr, int *addr_len)
- {
- int rc = -1;
- bsd_socket_t *bsd_sock = (bsd_socket_t*)sock;
- struct sockaddr_in *addr_in = (struct sockaddr_in*)addr;
- /* Check for correct length */
- if (sizeof(struct sockaddr_in) == *addr_len)
- {
- /* Clear address info first */
- memset(addr, 0x00, *addr_len);
-
- /* Set local address information */
- addr_in->sin_len = sizeof(struct sockaddr_in);
- addr_in->sin_family = AF_INET;
- addr_in->sin_port = bsd_sock->nut_tcp_sock->so_local_port;
- addr_in->sin_addr.s_addr = bsd_sock->nut_tcp_sock->so_local_addr;
-
- rc = 0;
- }
-
- return(rc);
- } /* getsockname */
- /*************************************************************************/
- /* getpeername */
- /* */
- /* Return the remote address information bound to the socket. */
- /* */
- /* In : sock, addr, addr_len */
- /* Out : none */
- /* Return: 0 on success / -1 otherwise */
- /*************************************************************************/
- int getpeername (socket_t sock, struct sockaddr *addr, int *addr_len)
- {
- int rc = -1;
- bsd_socket_t *bsd_sock = (bsd_socket_t*)sock;
- struct sockaddr_in *addr_in = (struct sockaddr_in*)addr;
- /* Check for correct length */
- if (sizeof(struct sockaddr_in) == *addr_len)
- {
- /* Clear address info first */
- memset(addr, 0x00, *addr_len);
- /* Set remote address information */
- addr_in->sin_len = sizeof(struct sockaddr_in);
- addr_in->sin_family = AF_INET;
- addr_in->sin_port = bsd_sock->nut_tcp_sock->so_remote_port;
- addr_in->sin_addr.s_addr = bsd_sock->nut_tcp_sock->so_remote_addr;
-
- rc = 0;
- }
-
- return(rc);
- } /* getpeername */
- /*************************************************************************/
- /* getsockopt */
- /* */
- /* Get a TCP / UDP socket option value. */
- /* */
- /* In : sock, level, optname, optval, optlen */
- /* Out : none */
- /* Return: 0 on success / -1 otherwise */
- /*************************************************************************/
- int getsockopt (socket_t sock, int level, int optname, void *optval, int optlen)
- {
- int rc = -1;
- bsd_socket_t *bsd_sock = (bsd_socket_t*)sock;
-
- /* Check for the correct level */
- if (SOL_SOCKET == level)
- {
- switch (optname)
- {
- case SO_ERROR: /* Last error is available for TCP and UDP */
- {
- /* Get the last error information, and clear it */
- if ((optval != NULL) && (sizeof(int) == optlen))
- {
- /* Last error */
- *((int*)optval) = NutTcpError(bsd_sock->nut_tcp_sock);
-
- /* Clear info */
- bsd_sock->nut_tcp_sock->so_last_error = 0;
-
- rc = 0;
- }
- break;
- } /* SO_ERROR */
-
- default:
- {
- /* Check for stream or datagram */
- if (SOCK_STREAM == bsd_sock->type)
- {
- /* It is a stream socket, get the option value */
- rc = NutTcpGetSockOpt(bsd_sock->nut_tcp_sock, optname, optval, optlen);
- }
- else
- {
- /* It must be a datagram socket */
- if (SO_RCVTIMEO == optname) /* <= special case, receive timeout */
- {
- /* Yes, receive timeout, check optval and optlen */
- if ((optval != NULL) && (sizeof(uint32_t) == optlen))
- {
- /* Get requested information */
- *((uint32_t*)optval) = bsd_sock->udp_rcv_timeo;
- rc = 0;
- }
- }
- else
- {
- /* Get the datagram option value */
- rc = NutUdpGetSockOpt(bsd_sock->nut_udp_sock, optname, optval, optlen);
- }
- }
- break;
- } /* default */
- } /* end switch (optname) */
- } /* end if (SOL_SOCKET == level) */
-
- return(rc);
- } /* getsockopt */
- /*************************************************************************/
- /* setsockopt */
- /* */
- /* Set value of a TCP socket option. */
- /* */
- /* In : sock, level, optname, optval, optlen */
- /* Out : none */
- /* Return: 0 on success / -1 otherwise */
- /*************************************************************************/
- int setsockopt (socket_t sock, int level, int optname, void *optval, int optlen)
- {
- int rc = -1;
- bsd_socket_t *bsd_sock = (bsd_socket_t*)sock;
-
- /* Check for the correct level */
- if (SOL_SOCKET == level)
- {
- /* Check for stream or datagram */
- if (SOCK_STREAM == bsd_sock->type)
- {
- /* It is a stream socket, set the option value */
- rc = NutTcpSetSockOpt(bsd_sock->nut_tcp_sock, optname, optval, optlen);
- }
- else
- {
- /* Check for receive timeout */
- if (SO_RCVTIMEO == optname)
- {
- /* Yes, receive timeout, check optval and optlen */
- if ((optval != NULL) && (sizeof(uint32_t) == optlen))
- {
- /* Set requested information */
- bsd_sock->udp_rcv_timeo = *((uint32_t*)optval);
- rc = 0;
- }
- }
- else
- {
- /* Set the datagram option value */
- rc = NutUdpSetSockOpt(bsd_sock->nut_udp_sock, optname, optval, optlen);
- } /* end if (SO_RCVTIMEO == optname) */
- } /* end if (SOCK_STREAM == bsd_sock->type) */
- } /* end if (SOL_SOCKET == level) */
-
- /* Check for the correct level */
- if (IPPROTO_IP == level)
- {
- switch (optname)
- {
- case IP_ADD_MEMBERSHIP:
- {
- struct ip_mreq *mreq;
-
- if ((optlen == sizeof(struct ip_mreq)) && (optval != NULL))
- {
- mreq = (struct ip_mreq *)optval;
- rc = NutNetIfAddMcastAddr("eth0", mreq->imr_multiaddr.s_addr);
- }
- break;
- } /* IP_ADD_MEMBERSHIP */
-
- case IP_DROP_MEMBERSHIP:
- {
- struct ip_mreq *mreq;
-
- if ((optlen == sizeof(struct ip_mreq)) && (optval != NULL))
- {
- mreq = (struct ip_mreq *)optval;
- rc = NutNetIfDelMcastAddr("eth0", mreq->imr_multiaddr.s_addr);
- }
- break;
- } /* IP_DROP_MEMBERSHIP */
-
- default:
- {
- /* Do nothing */
- break;
- }
- }
- } /* end if (IPPROTO_IP == level) */
-
- return(rc);
- } /* setsockopt */
- /*** EOF ***/
|