diff options
Diffstat (limited to 'nuttx/net/socket')
-rw-r--r-- | nuttx/net/socket/getsockname.c | 295 | ||||
-rw-r--r-- | nuttx/net/socket/socket.c | 131 |
2 files changed, 317 insertions, 109 deletions
diff --git a/nuttx/net/socket/getsockname.c b/nuttx/net/socket/getsockname.c index 34fea0c12..04b96b01b 100644 --- a/nuttx/net/socket/getsockname.c +++ b/nuttx/net/socket/getsockname.c @@ -61,26 +61,14 @@ ****************************************************************************/ /**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Function: getsockname + * Function: get_ipv4_sockname * * Description: * The getsockname() function retrieves the locally-bound name of the - * specified socket, stores this address in the sockaddr structure pointed - * to by the 'addr' argument, and stores the length of this address in the - * object pointed to by the 'addrlen' argument. - * - * If the actual length of the address is greater than the length of the - * supplied sockaddr structure, the stored address will be truncated. - * - * If the socket has not been bound to a local name, the value stored in - * the object pointed to by address is unspecified. + * specified PF_NET socket. * * Parameters: - * sockfd Socket descriptor of socket [in] + * psock Point to the socket structure instance [in] * addr sockaddr structure to receive data [out] * addrlen Length of sockaddr structure [in/out] * @@ -98,56 +86,152 @@ * ****************************************************************************/ -int getsockname(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen) +#ifdef CONFIG_NET_IPv4 +int ipv4_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr, + FAR socklen_t *addrlen) { - FAR struct socket *psock = sockfd_socket(sockfd); FAR struct net_driver_s *dev; - #if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP) -#ifdef CONFIG_NET_IPv6 - FAR struct sockaddr_in6 *outaddr = (FAR struct sockaddr_in6 *)addr; -#else FAR struct sockaddr_in *outaddr = (FAR struct sockaddr_in *)addr; #endif +#ifdef CONFIG_NETDEV_MULTINIC + in_addr_t lipaddr; + in_addr_t ripaddr; #endif - int err; + /* Check if enough space has been provided for the full address */ - /* Verify that the sockfd corresponds to valid, allocated socket */ + if (*addrlen < sizeof(struct sockaddr_in)) + { + /* This function is supposed to return the partial address if + * a smaller buffer has been provided. This support has not + * been implemented. + */ - if (!psock || psock->s_crefs <= 0) + return -ENOSYS; + } + + /* Set the port number */ + + switch (psock->s_type) { - err = EBADF; - goto errout; +#ifdef CONFIG_NET_TCP + case SOCK_STREAM: + { + FAR struct tcp_conn_s *tcp_conn = (FAR struct tcp_conn_s *)psock->s_conn; + outaddr->sin_port = tcp_conn->lport; /* Already in network byte order */ +#ifdef CONFIG_NETDEV_MULTINIC + lipaddr = tcp_conn->lipaddr; + ripaddr = tcp_conn->ripaddr; +#endif + } + break; +#endif + +#ifdef CONFIG_NET_UDP + case SOCK_DGRAM: + { + FAR struct udp_conn_s *udp_conn = (FAR struct udp_conn_s *)psock->s_conn; + outaddr->sin_port = udp_conn->lport; /* Already in network byte order */ +#ifdef CONFIG_NETDEV_MULTINIC + lipaddr = udp_conn->lipaddr; + ripaddr = udp_conn->ripaddr; +#endif + } + break; +#endif + + default: + return -EOPNOTSUPP; } - /* Some sanity checking... Shouldn't need this on a buckled up embedded - * system (?) + /* The socket/connection does not know its IP address unless + * CONFIG_NETDEV_MULTINIC is selected. Otherwise the design supports only + * a single network device and only the network device knows the IP address. */ -#ifdef CONFIG_DEBUG - if (!addr || !addrlen) + netdev_semtake(); + +#ifdef CONFIG_NETDEV_MULTINIC + /* Find the device matching the IPv4 address in the connection structure */ + + dev = netdev_findby_ipv4addr(lipaddr, ripaddr); +#else + /* There is only one, the first network device in the list. */ + + dev = g_netdevices; +#endif + + if (!dev) { - err = EINVAL; - goto errout; + netdev_semgive(); + return -EINVAL; } + + /* Set the address family and the IP address */ + +#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP) + outaddr->sin_family = AF_INET; + outaddr->sin_addr.s_addr = dev->d_ipaddr; + *addrlen = sizeof(struct sockaddr_in); #endif + netdev_semgive(); - /* Check if enough space has been provided for the full address */ + /* Return success */ + + return OK; +} +#endif + +/**************************************************************************** + * Function: ipv6_getsockname + * + * Description: + * The getsockname() function retrieves the locally-bound name of the + * specified PF_NET6 socket. + * + * Parameters: + * psock Point to the socket structure instance [in] + * addr sockaddr structure to receive data [out] + * addrlen Length of sockaddr structure [in/out] + * + * Returned Value: + * On success, 0 is returned, the 'addr' argument points to the address + * of the socket, and the 'addrlen' argument points to the length of the + * address. Otherwise, -1 is returned and errno is set to indicate the error. + * Possible errno values that may be returned include: + * + * EBADF - The socket argument is not a valid file descriptor. + * EOPNOTSUPP - The operation is not supported for this socket's protocol. + * EINVAL - The socket has been shut down. + * + * Assumptions: + * + ****************************************************************************/ #ifdef CONFIG_NET_IPv6 - if (*addrlen < sizeof(struct sockaddr_in6)) -#else - if (*addrlen < sizeof(struct sockaddr_in)) +int ipv6_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr, + FAR socklen_t *addrlen) +{ + FAR struct net_driver_s *dev; +#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP) + FAR struct sockaddr_in6 *outaddr = (FAR struct sockaddr_in6 *)addr; +#endif +#ifdef CONFIG_NETDEV_MULTINIC + net_ipv6addr_t *lipaddr; + net_ipv6addr_t *ripaddr; #endif + + /* Check if enough space has been provided for the full address */ + + if (*addrlen < sizeof(struct sockaddr_in6)) { /* This function is supposed to return the partial address if * a smaller buffer has been provided. This support has not * been implemented. */ - err = ENOSYS; - goto errout; + return -ENOSYS; } /* Set the port number */ @@ -159,6 +243,10 @@ int getsockname(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen) { FAR struct tcp_conn_s *tcp_conn = (FAR struct tcp_conn_s *)psock->s_conn; outaddr->sin_port = tcp_conn->lport; /* Already in network byte order */ +#ifdef CONFIG_NETDEV_MULTINIC + lipaddr = tcp_conn->lipaddr; + ripaddr = tcp_conn->ripaddr; +#endif } break; #endif @@ -168,6 +256,10 @@ int getsockname(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen) { FAR struct udp_conn_s *udp_conn = (FAR struct udp_conn_s *)psock->s_conn; outaddr->sin_port = udp_conn->lport; /* Already in network byte order */ +#ifdef CONFIG_NETDEV_MULTINIC + lipaddr = &udp_conn->lipaddr; + ripaddr = &udp_conn->ripaddr; +#endif } break; #endif @@ -177,42 +269,139 @@ int getsockname(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen) goto errout; } - /* ISSUE: As of this writing, the socket/connection does not know its IP - * address. This is because the uIP design is only intended to support - * a single network device and, therefore, only the network device knows - * the IP address. - * - * Right now, we can just pick the first network device. But that may - * not work in the future. + /* The socket/connection does not know its IP address unless + * CONFIG_NETDEV_MULTINIC is selected. Otherwise the design supports only + * a single network device and only the network device knows the IP address. */ netdev_semtake(); + +#ifdef CONFIG_NETDEV_MULTINIC + /* Find the device matching the IPv6 address in the connection structure */ + + dev = netdev_findby_ipv6addr(*lipaddr, *ripaddr); +#else + /* There is only one, the first network device in the list. */ + dev = g_netdevices; +#endif + if (!dev) { netdev_semgive(); - err = EINVAL; - goto errout; + return -EINVAL; } /* Set the address family and the IP address */ #if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP) -#ifdef CONFIG_NET_IPv6 outaddr->sin_family = AF_INET6; memcpy(outaddr->sin6_addr.in6_u.u6_addr8, dev->d_ipaddr, 16); *addrlen = sizeof(struct sockaddr_in6); -#else - outaddr->sin_family = AF_INET; - outaddr->sin_addr.s_addr = dev->d_ipaddr; - *addrlen = sizeof(struct sockaddr_in); -#endif #endif netdev_semgive(); /* Return success */ return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: getsockname + * + * Description: + * The getsockname() function retrieves the locally-bound name of the + * specified socket, stores this address in the sockaddr structure pointed + * to by the 'addr' argument, and stores the length of this address in the + * object pointed to by the 'addrlen' argument. + * + * If the actual length of the address is greater than the length of the + * supplied sockaddr structure, the stored address will be truncated. + * + * If the socket has not been bound to a local name, the value stored in + * the object pointed to by address is unspecified. + * + * Parameters: + * sockfd Socket descriptor of socket [in] + * addr sockaddr structure to receive data [out] + * addrlen Length of sockaddr structure [in/out] + * + * Returned Value: + * On success, 0 is returned, the 'addr' argument points to the address + * of the socket, and the 'addrlen' argument points to the length of the + * address. Otherwise, -1 is returned and errno is set to indicate the error. + * Possible errno values that may be returned include: + * + * EBADF - The socket argument is not a valid file descriptor. + * EOPNOTSUPP - The operation is not supported for this socket's protocol. + * EINVAL - The socket has been shut down. + * + * Assumptions: + * + ****************************************************************************/ + +int getsockname(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen) +{ + FAR struct socket *psock = sockfd_socket(sockfd); + int ret; + int err; + + /* Verify that the sockfd corresponds to valid, allocated socket */ + + if (!psock || psock->s_crefs <= 0) + { + err = EBADF; + goto errout; + } + + /* Some sanity checking... Shouldn't need this on a buckled up embedded + * system (?) + */ + +#ifdef CONFIG_DEBUG + if (!addr || !addrlen) + { + err = EINVAL; + goto errout; + } +#endif + + /* Handle by address domain */ + + switch (psock->s_domain) + { +#ifdef CONFIG_NET_IPv4 + case PF_INET: + ret = ipv4_getsockname(psock, addr, addrlen); + break; +#endif + +#ifdef CONFIG_NET_IPv6 + case PF_INET6: + ret = ipv6_getsockname(psock, addr, addrlen); + break; +#endif + + case PF_PACKET: + default: + err = EAFNOSUPPORT; + goto errout; + } + + /* Check for failure */ + + if (ret < 0) + { + err = -ret; + goto errout; + } + + return OK; errout: set_errno(err); diff --git a/nuttx/net/socket/socket.c b/nuttx/net/socket/socket.c index 505dbfc0e..6dadf79d3 100644 --- a/nuttx/net/socket/socket.c +++ b/nuttx/net/socket/socket.c @@ -1,7 +1,7 @@ /**************************************************************************** * net/socket/socket.c * - * Copyright (C) 2007-2009, 2012, 2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009, 2012, 2014-2015 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without @@ -96,66 +96,85 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock) { + bool ipdomain = false; int err; /* Only PF_INET, PF_INET6 or PF_PACKET domains supported */ - if ( -#if defined(CONFIG_NET_IPv6) - domain != PF_INET6 -#else - domain != PF_INET + switch (domain) + { +#ifdef CONFIG_NET_IPv4 + case PF_INET: + ipdomain = true; + break; #endif -#if defined(CONFIG_NET_PKT) - && domain != PF_PACKET + +#ifdef CONFIG_NET_IPv6 + case PF_INET6: + ipdomain = true; + break; #endif - ) - { + +#ifdef CONFIG_NET_PKT + case PF_PACKET: + break; +#endif + + default: err = EAFNOSUPPORT; goto errout; } /* Only SOCK_STREAM, SOCK_DGRAM and possible SOCK_RAW are supported */ - if ( -#if defined(CONFIG_NET_TCP) - (type == SOCK_STREAM && protocol != 0 && protocol != IPPROTO_TCP) || -#endif -#if defined(CONFIG_NET_UDP) - (type == SOCK_DGRAM && protocol != 0 && protocol != IPPROTO_UDP) || -#endif - ( -#if defined(CONFIG_NET_TCP) -#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_PKT) - type != SOCK_STREAM && -#else - type != SOCK_STREAM -#endif -#endif -#if defined(CONFIG_NET_UDP) -#if defined(CONFIG_NET_PKT) - type != SOCK_DGRAM && -#else - type != SOCK_DGRAM + switch (type) + { +#ifdef CONFIG_NET_TCP + case SOCK_STREAM: + if ((protocol != 0 && protocol != IPPROTO_TCP) || !ipdomain) + { + err = EPROTONOSUPPORT; + goto errout; + } + + break; #endif + +#ifdef CONFIG_NET_UDP + case SOCK_DGRAM: + if ((protocol != 0 && protocol != IPPROTO_UDP) || !ipdomain) + { + err = EPROTONOSUPPORT; + goto errout; + } + + break; #endif -#if defined(CONFIG_NET_PKT) - type != SOCK_RAW + +#ifdef CONFIG_NET_PKT + case SOCK_RAW: + if (ipdomain) + { + err = EPROTONOSUPPORT; + goto errout; + } + + break; #endif - ) - ) - { - err = EPROTONOSUPPORT; - goto errout; + + default: + err = EPROTONOSUPPORT; + goto errout; } /* Everything looks good. Initialize the socket structure */ /* Save the protocol type */ - psock->s_type = type; - psock->s_conn = NULL; + psock->s_domain = domain; + psock->s_type = type; + psock->s_conn = NULL; #ifdef CONFIG_NET_TCP_WRITE_BUFFERS - psock->s_sndcb = NULL; + psock->s_sndcb = NULL; #endif /* Allocate the appropriate connection structure. This reserves the @@ -166,19 +185,19 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock) err = ENOMEM; /* Assume failure to allocate connection instance */ switch (type) { -#ifdef CONFIG_NET_PKT - case SOCK_RAW: +#ifdef CONFIG_NET_TCP + case SOCK_STREAM: { - /* Allocate the packet socket connection structure and save - * in the new socket instance. + /* Allocate the TCP connection structure and save in the new + * socket instance. */ - FAR struct pkt_conn_s *conn = pkt_alloc(); + FAR struct tcp_conn_s *conn = tcp_alloc(); if (!conn) { /* Failed to reserve a connection structure */ - goto errout; + goto errout; /* With err == ENFILE or ENOMEM */ } /* Set the reference count on the connection structure. This @@ -193,14 +212,14 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock) break; #endif -#ifdef CONFIG_NET_TCP - case SOCK_STREAM: +#ifdef CONFIG_NET_UDP + case SOCK_DGRAM: { - /* Allocate the TCP connection structure and save in the new + /* Allocate the UDP connection structure and save in the new * socket instance. */ - FAR struct tcp_conn_s *conn = tcp_alloc(); + FAR struct udp_conn_s *conn = udp_alloc(); if (!conn) { /* Failed to reserve a connection structure */ @@ -220,19 +239,19 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock) break; #endif -#ifdef CONFIG_NET_UDP - case SOCK_DGRAM: +#ifdef CONFIG_NET_PKT + case SOCK_RAW: { - /* Allocate the UDP connection structure and save in the new - * socket instance. + /* Allocate the packet socket connection structure and save + * in the new socket instance. */ - FAR struct udp_conn_s *conn = udp_alloc(); + FAR struct pkt_conn_s *conn = pkt_alloc(); if (!conn) { /* Failed to reserve a connection structure */ - goto errout; /* With err == ENFILE or ENOMEM */ + goto errout; } /* Set the reference count on the connection structure. This |