diff options
Diffstat (limited to 'nuttx/net/netdev-ioctl.c')
-rw-r--r-- | nuttx/net/netdev-ioctl.c | 148 |
1 files changed, 140 insertions, 8 deletions
diff --git a/nuttx/net/netdev-ioctl.c b/nuttx/net/netdev-ioctl.c index 3e8c1a933..cdc7c80b8 100644 --- a/nuttx/net/netdev-ioctl.c +++ b/nuttx/net/netdev-ioctl.c @@ -42,12 +42,55 @@ #include <sys/types.h> #include <sys/socket.h> +#include <sys/ioctl.h> +#include <string.h> #include <errno.h> #include <nuttx/net.h> +#include <net/uip/uip-arch.h> +#include <net/uip/uip.h> + #include "net-internal.h" /**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: _get_ipaddr / _set_ipaddr + * + * Description: + * Copy IP addresses into and out of device structure + * + ****************************************************************************/ + +static void _get_ipaddr(struct sockaddr *outaddr, uip_ipaddr_t *inaddr) +{ +#ifdef CONFIG_NET_IPv6 + struct sockaddr_in6 *dest = (struct sockaddr_in6 *)outaddr; + memcpy(&dest->sin6_addr.in6_u, inaddr, IFHWADDRLEN); +#else + struct sockaddr_in *dest = (struct sockaddr_in *)outaddr; + dest->sin_addr.s_addr = *inaddr; +#endif +} + +static void _set_ipaddr(uip_ipaddr_t *outaddr, struct sockaddr *inaddr) +{ +#ifdef CONFIG_NET_IPv6 + struct sockaddr_in6 *src = (struct sockaddr_in6 *)inaddr; + memcpy(outaddr, &src->sin6_addr.in6_u, IFHWADDRLEN); +#else + struct sockaddr_in *src = (struct sockaddr_in *)inaddr; + *outaddr = src->sin_addr.s_addr; +#endif +} + +/**************************************************************************** * Global Functions ****************************************************************************/ @@ -58,7 +101,7 @@ * Perform network device specific operations. * * Parameters: - * fd Socket descriptor of device + * sockfd Socket descriptor of device * cmd The ioctl command * req The argument of the ioctl cmd * @@ -67,23 +110,112 @@ * -1 on failure withi errno set properly: * * EBADF - * 'fd' is not a valid descriptor. + * 'sockfd' is not a valid descriptor. * EFAULT - * 'arg' references an inaccessible memory area. + * 'req' references an inaccessible memory area. * EINVAL - * 'cmd' or 'arg' is not valid. + * 'cmd' or 'req' is not valid. * ENOTTY - * 'fd' is not associated with a character special device. + * 'sockfd' is not associated with a network device. * ENOTTY * The specified request does not apply to the kind of object that the - * descriptor 'fd' references. + * descriptor 'sockfd' references. * ****************************************************************************/ int netdev_ioctl(int sockfd, int cmd, struct ifreq *req) { -#warning "Network ioctls not implemented" - *get_errno_ptr() = ENOSYS; + FAR struct socket *psock = sockfd_socket(sockfd); + FAR struct uip_driver_s *dev; + int err; + + if (!_SIOCVALID(cmd) || !req) + { + err = EINVAL; + goto errout; + } + + /* Verify that the sockfd corresponds to valid, allocated socket */ + + if (!psock || psock->s_crefs <= 0) + { + err = EBADF; + goto errout; + } + + /* Find the network device associated with the device name + * in the request data. + */ + + dev = netdev_find(req->ifr_name); + if (!dev) + { + err = EINVAL; + goto errout; + } + + /* Execute the command */ + + switch (cmd) + { + case SIOCGIFADDR: /* Get IP address */ + _get_ipaddr(&req->ifr_addr, &dev->d_ipaddr); + break; + + case SIOCSIFADDR: /* Set IP address */ + _set_ipaddr(&dev->d_ipaddr, &req->ifr_addr); + break; + + case SIOCGIFDSTADDR: /* Get P-to-P address */ + _get_ipaddr(&req->ifr_dstaddr, &dev->d_draddr); + break; + + case SIOCSIFDSTADDR: /* Set P-to-P address */ + _set_ipaddr(&dev->d_draddr, &req->ifr_dstaddr); + break; + + case SIOCGIFNETMASK: /* Get network mask */ + _get_ipaddr(&req->ifr_addr, &dev->d_netmask); + break; + + case SIOCSIFNETMASK: /* Set network mask */ + _set_ipaddr(&dev->d_netmask, &req->ifr_addr); + break; + + case SIOCGIFMTU: /* Get MTU size */ + req->ifr_mtu = UIP_BUFSIZE; + break; + + case SIOCGIFHWADDR: /* Get hardware address */ + memcpy(req->ifr_hwaddr.sa_data, dev->d_mac.addr, IFHWADDRLEN); + break; + + case SIOCSIFHWADDR: /* Set hardware address */ + memcpy(dev->d_mac.addr, req->ifr_hwaddr.sa_data, IFHWADDRLEN); + break; + + case SIOCDIFADDR: /* Delete IP address */ + memset(&dev->d_ipaddr, 0, sizeof(uip_ipaddr_t)); + break; + + case SIOCGIFCOUNT: /* Get number of devices */ + req->ifr_count = netdev_count(); + break; + + case SIOCGIFBRDADDR: /* Get broadcast IP address */ + case SIOCSIFBRDADDR: /* Set broadcast IP address */ + err = ENOSYS; + goto errout; + + default: + err = EINVAL; + goto errout; + } + + return OK; + +errout: + *get_errno_ptr() = err; return ERROR; } |