Networking: More detangling of IPv6 logic. Next steps will be more invasive and will get moved to a branch
This commit is contained in:
parent
b1a7113fdd
commit
fe8b3c5220
8 changed files with 567 additions and 176 deletions
|
|
@ -96,7 +96,8 @@ struct devif_callback_s; /* Forward reference */
|
|||
|
||||
struct socket
|
||||
{
|
||||
int s_crefs; /* Reference count on the socket */
|
||||
int16_t s_crefs; /* Reference count on the socket */
|
||||
uint8_t s_domain; /* Domain: PF_INET, PF_INET6, or PF_PACKET */
|
||||
uint8_t s_type; /* Protocol type: Only SOCK_STREAM or SOCK_DGRAM */
|
||||
uint8_t s_flags; /* See _SF_* definitions */
|
||||
|
||||
|
|
|
|||
|
|
@ -223,9 +223,9 @@ int arp_send(in_addr_t ipaddr)
|
|||
/* Get the device that can route this request */
|
||||
|
||||
#ifdef CONFIG_NET_MULTILINK
|
||||
dev = netdev_findbyaddr(g_allzeroaddr, ipaddr);
|
||||
dev = netdev_findby_ipv4addr(g_allzeroaddr, ipaddr);
|
||||
#else
|
||||
dev = netdev_findbyaddr(ipaddr);
|
||||
dev = netdev_findby_ipv4addr(ipaddr);
|
||||
#endif
|
||||
if (!dev)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -94,11 +94,22 @@ FAR struct net_driver_s *netdev_findbyname(FAR const char *ifname);
|
|||
/* netdev_findbyaddr.c *******************************************************/
|
||||
|
||||
#if CONFIG_NSOCKET_DESCRIPTORS > 0
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
#ifdef CONFIG_NET_MULTILINK
|
||||
FAR struct net_driver_s *netdev_findbyaddr(const net_ipaddr_t lipaddr,
|
||||
const net_ipaddr_t ripaddr);
|
||||
FAR struct net_driver_s *netdev_findby_ipv4addr(in_addr_t lipaddr,
|
||||
in_addr_t ripaddr);
|
||||
#else
|
||||
FAR struct net_driver_s *netdev_findbyaddr(const net_ipaddr_t ripaddr);
|
||||
FAR struct net_driver_s *netdev_findby_ipv4addr(in_addr_t ripaddr);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
#ifdef CONFIG_NET_MULTILINK
|
||||
FAR struct net_driver_s *netdev_findby_ipv6addr(const net_ipv6addr_t lipaddr,
|
||||
const net_ipv6addr_t ripaddr);
|
||||
#else
|
||||
FAR struct net_driver_s *netdev_findby_ipv6addr(const net_ipv6addr_t ripaddr);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@
|
|||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Function: netdev_finddevice
|
||||
* Function: netdev_finddevice_ipv4addr
|
||||
*
|
||||
* Description:
|
||||
* Find a previously registered network device by matching a local address
|
||||
|
|
@ -91,7 +91,8 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
static FAR struct net_driver_s *netdev_finddevice(const net_ipaddr_t ripaddr)
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
static FAR struct net_driver_s *netdev_finddevice_ipv4addr(in_addr_t ripaddr)
|
||||
{
|
||||
FAR struct net_driver_s *dev;
|
||||
|
||||
|
|
@ -121,17 +122,71 @@ static FAR struct net_driver_s *netdev_finddevice(const net_ipaddr_t ripaddr)
|
|||
netdev_semgive();
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv4 */
|
||||
|
||||
/****************************************************************************
|
||||
* Function: netdev_finddevice_ipv6addr
|
||||
*
|
||||
* Description:
|
||||
* Find a previously registered network device by matching a local address
|
||||
* with the subnet served by the device. Only "up" devices are considered
|
||||
* (since a "down" device has no meaningful address).
|
||||
*
|
||||
* Parameters:
|
||||
* ripaddr - Remote address of a connection to use in the lookup
|
||||
*
|
||||
* Returned Value:
|
||||
* Pointer to driver on success; null on failure
|
||||
*
|
||||
* Assumptions:
|
||||
* Called from normal user mode
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
static FAR struct net_driver_s *
|
||||
netdev_finddevice_ipv6addr(const net_ipv6addr_t ripaddr)
|
||||
{
|
||||
FAR struct net_driver_s *dev;
|
||||
|
||||
/* Examine each registered network device */
|
||||
|
||||
netdev_semtake();
|
||||
for (dev = g_netdevices; dev; dev = dev->flink)
|
||||
{
|
||||
/* Is the interface in the "up" state? */
|
||||
|
||||
if ((dev->d_flags & IFF_UP) != 0)
|
||||
{
|
||||
/* Yes.. check for an address match (under the netmask) */
|
||||
|
||||
if (net_ipaddr_maskcmp(dev->d_ipv6ipaddr, ripaddr, dev->d_ipv6netmask))
|
||||
{
|
||||
/* Its a match */
|
||||
|
||||
netdev_semgive();
|
||||
return dev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* No device with the matching address found */
|
||||
|
||||
netdev_semgive();
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv6 */
|
||||
|
||||
/****************************************************************************
|
||||
* Global Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Function: netdev_findbyaddr
|
||||
* Function: netdev_findby_ipv4addr
|
||||
*
|
||||
* Description:
|
||||
* Find a previously registered network device by matching an arbitrary
|
||||
* IP address.
|
||||
* IPv4 address.
|
||||
*
|
||||
* Parameters:
|
||||
* lipaddr - Local, bound address of a connection. Used only if ripaddr
|
||||
|
|
@ -146,11 +201,12 @@ static FAR struct net_driver_s *netdev_finddevice(const net_ipaddr_t ripaddr)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
#ifdef CONFIG_NET_MULTILINK
|
||||
FAR struct net_driver_s *netdev_findbyaddr(const net_ipaddr_t lipaddr,
|
||||
const net_ipaddr_t ripaddr)
|
||||
FAR struct net_driver_s *netdev_findby_ipv4addr(in_addr_t lipaddr,
|
||||
in_addr_t ripaddr)
|
||||
#else
|
||||
FAR struct net_driver_s *netdev_findbyaddr(const net_ipaddr_t ripaddr)
|
||||
FAR struct net_driver_s *netdev_findby_ipv4addr(in_addr_t ripaddr)
|
||||
#endif
|
||||
{
|
||||
struct net_driver_s *dev;
|
||||
|
|
@ -161,12 +217,12 @@ FAR struct net_driver_s *netdev_findbyaddr(const net_ipaddr_t ripaddr)
|
|||
|
||||
/* First, check if this is the broadcast IP address */
|
||||
|
||||
if (net_ipaddr_cmp(ripaddr, g_alloneaddr))
|
||||
if (net_ipv4addr_cmp(ripaddr, g_alloneaddr))
|
||||
{
|
||||
#ifdef CONFIG_NET_MULTILINK
|
||||
/* Yes.. Check the local, bound address. Is it INADDR_ANY? */
|
||||
|
||||
if (net_ipaddr_cmp(lipaddr, g_allzeroaddr))
|
||||
if (net_ipv4addr_cmp(lipaddr, g_allzeroaddr))
|
||||
{
|
||||
/* Yes.. In this case, I think we are supposed to send the
|
||||
* broadcast packet out ALL local networks. I am not sure
|
||||
|
|
@ -180,7 +236,7 @@ FAR struct net_driver_s *netdev_findbyaddr(const net_ipaddr_t ripaddr)
|
|||
{
|
||||
/* Return the device associated with the local address */
|
||||
|
||||
return netdev_finddevice(lipaddr);
|
||||
return netdev_finddevice_ipv4addr(lipaddr);
|
||||
}
|
||||
#else
|
||||
/* If there is only a single, registered network interface, then the
|
||||
|
|
@ -193,7 +249,7 @@ FAR struct net_driver_s *netdev_findbyaddr(const net_ipaddr_t ripaddr)
|
|||
|
||||
/* Check if the address maps to a local network */
|
||||
|
||||
dev = netdev_finddevice(ripaddr);
|
||||
dev = netdev_finddevice_ipv4addr(ripaddr);
|
||||
if (dev)
|
||||
{
|
||||
return dev;
|
||||
|
|
@ -206,18 +262,14 @@ FAR struct net_driver_s *netdev_findbyaddr(const net_ipaddr_t ripaddr)
|
|||
* address of a router that can forward packets to the external network.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
ret = net_router(ripaddr, router);
|
||||
#else
|
||||
ret = net_router(ripaddr, &router);
|
||||
#endif
|
||||
if (ret >= 0)
|
||||
{
|
||||
/* Success... try to find the network device associated with the local
|
||||
* router address
|
||||
*/
|
||||
|
||||
dev = netdev_finddevice(router);
|
||||
dev = netdev_finddevice_ipv4addr(router);
|
||||
if (dev)
|
||||
{
|
||||
return dev;
|
||||
|
|
@ -245,5 +297,124 @@ FAR struct net_driver_s *netdev_findbyaddr(const net_ipaddr_t ripaddr)
|
|||
|
||||
return dev;
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv4 */
|
||||
|
||||
/****************************************************************************
|
||||
* Function: netdev_findby_ipv6addr
|
||||
*
|
||||
* Description:
|
||||
* Find a previously registered network device by matching an arbitrary
|
||||
* IPv6 address.
|
||||
*
|
||||
* Parameters:
|
||||
* lipaddr - Local, bound address of a connection. Used only if ripaddr
|
||||
* is the broadcast address. Used only if CONFIG_NET_MULTILINK.
|
||||
* ripaddr - Remote address of a connection to use in the lookup
|
||||
*
|
||||
* Returned Value:
|
||||
* Pointer to driver on success; null on failure
|
||||
*
|
||||
* Assumptions:
|
||||
* Called from normal user mode
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
#ifdef CONFIG_NET_MULTILINK
|
||||
FAR struct net_driver_s *netdev_findby_ipv6addr(const net_ipv6addr_t lipaddr,
|
||||
const net_ipv6addr_t ripaddr)
|
||||
#else
|
||||
FAR struct net_driver_s *netdev_findby_ipv6addr(const net_ipv6addr_t ripaddr)
|
||||
#endif
|
||||
{
|
||||
struct net_driver_s *dev;
|
||||
#ifdef CONFIG_NET_ROUTE
|
||||
net_ipaddr_t router;
|
||||
int ret;
|
||||
#endif
|
||||
|
||||
/* First, check if this is the broadcast IP address */
|
||||
|
||||
if (net_ipv6addr_cmp(ripaddr, g_alloneaddr))
|
||||
{
|
||||
#ifdef CONFIG_NET_MULTILINK
|
||||
/* Yes.. Check the local, bound address. Is it INADDR_ANY? */
|
||||
|
||||
if (net_ipv6addr_cmp(lipaddr, g_allzeroaddr))
|
||||
{
|
||||
/* Yes.. In this case, I think we are supposed to send the
|
||||
* broadcast packet out ALL local networks. I am not sure
|
||||
* of that and, in any event, there is nothing we can do
|
||||
* about that here.
|
||||
*/
|
||||
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Return the device associated with the local address */
|
||||
|
||||
return netdev_finddevice_ipv6addr(lipaddr);
|
||||
}
|
||||
#else
|
||||
/* If there is only a single, registered network interface, then the
|
||||
* decision is pretty easy.
|
||||
*/
|
||||
|
||||
return g_netdevices;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Check if the address maps to a local network */
|
||||
|
||||
dev = netdev_finddevice_ipv6addr(ripaddr);
|
||||
if (dev)
|
||||
{
|
||||
return dev;
|
||||
}
|
||||
|
||||
/* No.. The address lies on an external network */
|
||||
|
||||
#ifdef CONFIG_NET_ROUTE
|
||||
/* If we have a routing table, then perhaps we can find the local
|
||||
* address of a router that can forward packets to the external network.
|
||||
*/
|
||||
|
||||
ret = net_router(ripaddr, router);
|
||||
if (ret >= 0)
|
||||
{
|
||||
/* Success... try to find the network device associated with the local
|
||||
* router address
|
||||
*/
|
||||
|
||||
dev = netdev_finddevice_ipv6addr(router);
|
||||
if (dev)
|
||||
{
|
||||
return dev;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_NET_ROUTE */
|
||||
|
||||
/* The above lookup will fail if the packet is being sent out of our
|
||||
* out subnet to a router and there is no routing information.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_NET_MULTILINK
|
||||
/* If there is only a single, registered network interface, then the
|
||||
* decision is pretty easy. Use that device and its default router
|
||||
* address.
|
||||
*/
|
||||
|
||||
dev = g_netdevices;
|
||||
#endif
|
||||
|
||||
/* If we will did not find the network device, then we might as well fail
|
||||
* because we are not configured properly to determine the route to the
|
||||
* destination.
|
||||
*/
|
||||
|
||||
return dev;
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv6 */
|
||||
|
||||
#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS */
|
||||
|
|
|
|||
|
|
@ -102,9 +102,9 @@ void netdev_rxnotify(const net_ipaddr_t ripaddr)
|
|||
/* Find the device driver that serves the subnet of the remote address */
|
||||
|
||||
#ifdef CONFIG_NET_MULTILINK
|
||||
dev = netdev_findbyaddr(lipaddr, ripaddr);
|
||||
dev = netdev_findby_ipv4addr(lipaddr, ripaddr);
|
||||
#else
|
||||
dev = netdev_findbyaddr(ripaddr);
|
||||
dev = netdev_findby_ipv4addr(ripaddr);
|
||||
#endif
|
||||
|
||||
if (dev && dev->d_rxavail)
|
||||
|
|
|
|||
|
|
@ -102,9 +102,9 @@ void netdev_txnotify(const net_ipaddr_t ripaddr)
|
|||
/* Find the device driver that serves the subnet of the remote address */
|
||||
|
||||
#ifdef CONFIG_NET_MULTILINK
|
||||
dev = netdev_findbyaddr(lipaddr, ripaddr);
|
||||
dev = netdev_findby_ipv4addr(lipaddr, ripaddr);
|
||||
#else
|
||||
dev = netdev_findbyaddr(ripaddr);
|
||||
dev = netdev_findby_ipv4addr(ripaddr);
|
||||
#endif
|
||||
|
||||
if (dev && dev->d_txavail)
|
||||
|
|
|
|||
|
|
@ -60,6 +60,253 @@
|
|||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Function: get_ipv4_sockname
|
||||
*
|
||||
* Description:
|
||||
* The getsockname() function retrieves the locally-bound name of the
|
||||
* specified PF_NET 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_IPv4
|
||||
int ipv4_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_in *outaddr = (FAR struct sockaddr_in *)addr;
|
||||
#endif
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
in_addr_t lipaddr;
|
||||
in_addr_t ripaddr;
|
||||
#endif
|
||||
|
||||
/* Check if enough space has been provided for the full address */
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/* Set the port number */
|
||||
|
||||
switch (psock->s_type)
|
||||
{
|
||||
#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;
|
||||
}
|
||||
|
||||
/* 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 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)
|
||||
{
|
||||
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();
|
||||
|
||||
/* 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
|
||||
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.
|
||||
*/
|
||||
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/* Set the port number */
|
||||
|
||||
switch (psock->s_type)
|
||||
{
|
||||
#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:
|
||||
err = EOPNOTSUPP;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* 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();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Set the address family and the IP address */
|
||||
|
||||
#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP)
|
||||
outaddr->sin_family = AF_INET6;
|
||||
memcpy(outaddr->sin6_addr.in6_u.u6_addr8, dev->d_ipaddr, 16);
|
||||
*addrlen = sizeof(struct sockaddr_in6);
|
||||
#endif
|
||||
netdev_semgive();
|
||||
|
||||
/* Return success */
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
|
@ -101,16 +348,7 @@
|
|||
int getsockname(int sockfd, 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
|
||||
#endif
|
||||
|
||||
int ret;
|
||||
int err;
|
||||
|
||||
/* Verify that the sockfd corresponds to valid, allocated socket */
|
||||
|
|
@ -133,84 +371,35 @@ int getsockname(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Check if enough space has been provided for the full address */
|
||||
/* 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
|
||||
if (*addrlen < sizeof(struct sockaddr_in6))
|
||||
#else
|
||||
if (*addrlen < sizeof(struct sockaddr_in))
|
||||
#endif
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* Set the port number */
|
||||
|
||||
switch (psock->s_type)
|
||||
{
|
||||
#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 */
|
||||
}
|
||||
break;
|
||||
case PF_INET6:
|
||||
ret = ipv6_getsockname(psock, addr, addrlen);
|
||||
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 */
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
err = EOPNOTSUPP;
|
||||
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.
|
||||
*/
|
||||
|
||||
netdev_semtake();
|
||||
dev = g_netdevices;
|
||||
if (!dev)
|
||||
{
|
||||
netdev_semgive();
|
||||
err = EINVAL;
|
||||
case PF_PACKET:
|
||||
default:
|
||||
err = EAFNOSUPPORT;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Set the address family and the IP address */
|
||||
/* Check for failure */
|
||||
|
||||
#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 */
|
||||
if (ret < 0)
|
||||
{
|
||||
err = -ret;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
#endif
|
||||
#if defined(CONFIG_NET_PKT)
|
||||
&& domain != PF_PACKET
|
||||
#endif
|
||||
)
|
||||
switch (domain)
|
||||
{
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
case PF_INET:
|
||||
ipdomain = true;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#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
|
||||
#endif
|
||||
#endif
|
||||
#if defined(CONFIG_NET_PKT)
|
||||
type != SOCK_RAW
|
||||
#endif
|
||||
)
|
||||
)
|
||||
switch (type)
|
||||
{
|
||||
err = EPROTONOSUPPORT;
|
||||
goto errout;
|
||||
#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
|
||||
|
||||
#ifdef CONFIG_NET_PKT
|
||||
case SOCK_RAW:
|
||||
if (ipdomain)
|
||||
{
|
||||
err = EPROTONOSUPPORT;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
break;
|
||||
#endif
|
||||
|
||||
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,33 +185,6 @@ 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:
|
||||
{
|
||||
/* Allocate the packet socket connection structure and save
|
||||
* in the new socket instance.
|
||||
*/
|
||||
|
||||
FAR struct pkt_conn_s *conn = pkt_alloc();
|
||||
if (!conn)
|
||||
{
|
||||
/* Failed to reserve a connection structure */
|
||||
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Set the reference count on the connection structure. This
|
||||
* reference count will be increment only if the socket is
|
||||
* dup'ed
|
||||
*/
|
||||
|
||||
DEBUGASSERT(conn->crefs == 0);
|
||||
psock->s_conn = conn;
|
||||
conn->crefs = 1;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_TCP
|
||||
case SOCK_STREAM:
|
||||
{
|
||||
|
|
@ -247,6 +239,33 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
|
|||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_PKT
|
||||
case SOCK_RAW:
|
||||
{
|
||||
/* Allocate the packet socket connection structure and save
|
||||
* in the new socket instance.
|
||||
*/
|
||||
|
||||
FAR struct pkt_conn_s *conn = pkt_alloc();
|
||||
if (!conn)
|
||||
{
|
||||
/* Failed to reserve a connection structure */
|
||||
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Set the reference count on the connection structure. This
|
||||
* reference count will be increment only if the socket is
|
||||
* dup'ed
|
||||
*/
|
||||
|
||||
DEBUGASSERT(conn->crefs == 0);
|
||||
psock->s_conn = conn;
|
||||
conn->crefs = 1;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue