Fix ordering of operations in network ioctl handling. We need to able to distinguish an error because the command was not recognized vs. other kinds of error

This commit is contained in:
Gregory Nutt 2013-10-05 16:43:10 -06:00
parent 63b6d3bde3
commit 4579819f8e

View File

@ -187,7 +187,35 @@ static void ioctl_ifdown(FAR struct uip_driver_s *dev)
}
/****************************************************************************
* Name: netdev_ioctl
* Name: netdev_ifrdev
*
* Description:
* Verify the struct ifreq and get the Ethernet device.
*
* Parameters:
* req - The argument of the ioctl cmd
*
* Return:
* A pointer to the driver structure on success; NULL on failure.
*
****************************************************************************/
static FAR struct uip_driver_s *netdev_ifrdev(FAR struct ifreq *req)
{
if (!req)
{
return NULL;
}
/* Find the network device associated with the device name
* in the request data.
*/
return netdev_findbyname(req->ifr_name);
}
/****************************************************************************
* Name: netdev_ifrioctl
*
* Description:
* Perform network device specific operations.
@ -208,71 +236,86 @@ static int netdev_ifrioctl(FAR struct socket *psock, int cmd,
FAR struct ifreq *req)
{
FAR struct uip_driver_s *dev;
int ret = OK;
int ret = -EINVAL;
nvdbg("cmd: %d\n", cmd);
if (!req)
{
ret = -EINVAL;
goto errout;
}
/* Find the network device associated with the device name
* in the request data.
*/
dev = netdev_findbyname(req->ifr_name);
if (!dev)
{
ret = -EINVAL;
goto errout;
}
/* Execute the command */
switch (cmd)
{
case SIOCGIFADDR: /* Get IP address */
{
dev = netdev_ifrdev(req);
if (dev)
{
ioctl_getipaddr(&req->ifr_addr, &dev->d_ipaddr);
ret = OK;
}
}
break;
case SIOCSIFADDR: /* Set IP address */
{
dev = netdev_ifrdev(req);
if (dev)
{
ioctl_ifdown(dev);
ioctl_setipaddr(&dev->d_ipaddr, &req->ifr_addr);
ioctl_ifup(dev);
ret = OK;
}
}
break;
case SIOCGIFDSTADDR: /* Get P-to-P address */
{
dev = netdev_ifrdev(req);
if (dev)
{
ioctl_getipaddr(&req->ifr_dstaddr, &dev->d_draddr);
ret = OK;
}
}
break;
case SIOCSIFDSTADDR: /* Set P-to-P address */
{
dev = netdev_ifrdev(req);
if (dev)
{
ioctl_setipaddr(&dev->d_draddr, &req->ifr_dstaddr);
ret = OK;
}
}
break;
case SIOCGIFNETMASK: /* Get network mask */
{
dev = netdev_ifrdev(req);
if (dev)
{
ioctl_getipaddr(&req->ifr_addr, &dev->d_netmask);
ret = OK;
}
}
break;
case SIOCSIFNETMASK: /* Set network mask */
{
dev = netdev_ifrdev(req);
if (dev)
{
ioctl_setipaddr(&dev->d_netmask, &req->ifr_addr);
ret = OK;
}
}
break;
case SIOCGIFMTU: /* Get MTU size */
{
req->ifr_mtu = CONFIG_NET_BUFSIZE;
ret = OK;
}
break;
@ -280,6 +323,9 @@ static int netdev_ifrioctl(FAR struct socket *psock, int cmd,
{
/* Is this a request to bring the interface up? */
dev = netdev_ifrdev(req);
if (dev)
{
if (req->ifr_flags & IF_FLAG_IFUP)
{
/* Yes.. bring the interface up */
@ -296,9 +342,15 @@ static int netdev_ifrioctl(FAR struct socket *psock, int cmd,
ioctl_ifdown(dev);
}
}
ret = OK;
}
break;
case SIOCGIFFLAGS: /* Gets the interface flags */
{
dev = netdev_ifrdev(req);
if (dev)
{
req->ifr_flags = 0;
@ -317,30 +369,50 @@ static int netdev_ifrioctl(FAR struct socket *psock, int cmd,
req->ifr_flags |= IF_FLAG_IFDOWN;
}
}
ret = OK;
}
break;
/* MAC address operations only make sense if Ethernet is supported */
#ifdef CONFIG_NET_ETHERNET
case SIOCGIFHWADDR: /* Get hardware address */
{
dev = netdev_ifrdev(req);
if (dev)
{
req->ifr_hwaddr.sa_family = AF_INETX;
memcpy(req->ifr_hwaddr.sa_data, dev->d_mac.ether_addr_octet, IFHWADDRLEN);
memcpy(req->ifr_hwaddr.sa_data,
dev->d_mac.ether_addr_octet, IFHWADDRLEN);
ret = OK;
}
}
break;
case SIOCSIFHWADDR: /* Set hardware address -- will not take effect until ifup */
{
dev = netdev_ifrdev(req);
if (dev)
{
req->ifr_hwaddr.sa_family = AF_INETX;
memcpy(dev->d_mac.ether_addr_octet, req->ifr_hwaddr.sa_data, IFHWADDRLEN);
memcpy(dev->d_mac.ether_addr_octet,
req->ifr_hwaddr.sa_data, IFHWADDRLEN);
ret = OK;
}
}
break;
#endif
case SIOCDIFADDR: /* Delete IP address */
{
dev = netdev_ifrdev(req);
if (dev)
{
ioctl_ifdown(dev);
memset(&dev->d_ipaddr, 0, sizeof(uip_ipaddr_t));
ret = OK;
}
}
break;
@ -372,10 +444,39 @@ static int netdev_ifrioctl(FAR struct socket *psock, int cmd,
break;;
}
errout:
return ret;
}
/****************************************************************************
* Name: netdev_imsfdev
*
* Description:
* Verify the struct ip_msfilter and get the Ethernet device.
*
* Parameters:
* req - The argument of the ioctl cmd
*
* Return:
* A pointer to the driver structure on success; NULL on failure.
*
****************************************************************************/
#ifdef CONFIG_NET_IGMP
static FAR struct uip_driver_s *netdev_imsfdev(FAR struct ip_msfilter *imsf)
{
if (!imsf)
{
return NULL;
}
/* Find the network device associated with the device name
* in the request data.
*/
return netdev_findbyname(imsf->imsf_name);
}
#endif
/****************************************************************************
* Name: netdev_imsfioctl
*
@ -399,31 +500,18 @@ static int netdev_imsfioctl(FAR struct socket *psock, int cmd,
FAR struct ip_msfilter *imsf)
{
FAR struct uip_driver_s *dev;
int ret = OK;
int ret = -EINVAL;
nvdbg("cmd: %d\n", cmd);
if (!imsf)
{
ret = -EINVAL;
goto errout;
}
/* Find the network device associated with the device name
* in the request data.
*/
dev = netdev_findbyname(imsf->imsf_name);
if (!dev)
{
ret = -EINVAL;
goto errout;
}
/* Execute the command */
switch (cmd)
{
case SIOCSIPMSFILTER: /* Set source filter content */
{
dev = netdev_imsfdev(req);
if (dev)
{
if (imsf->imsf_fmode == MCAST_INCLUDE)
{
@ -435,6 +523,7 @@ static int netdev_imsfioctl(FAR struct socket *psock, int cmd,
ret = igmp_leavegroup(dev, &imsf->imsf_multiaddr);
}
}
}
break;
case SIOCGIPMSFILTER: /* Retrieve source filter addresses */
@ -443,7 +532,6 @@ static int netdev_imsfioctl(FAR struct socket *psock, int cmd,
break;
}
errout:
return ret;
}
#endif
@ -470,20 +558,15 @@ errout:
static int netdev_rtioctl(FAR struct socket *psock, int cmd,
FAR struct rtentry *rtentry)
{
int ret;
/* Return an error if no rtentry structure is provided */
if (!rtentry)
{
return -EINVAL;
}
int ret = -EINVAL;
/* Execute the command */
switch (cmd)
{
case SIOCADDRT: /* Add an entry to the routing table */
{
if (rtentry)
{
uip_ipaddr_t target;
uip_ipaddr_t netmask;
@ -539,9 +622,12 @@ static int netdev_rtioctl(FAR struct socket *psock, int cmd,
#endif
ret = net_addroute(target, netmask, router);
}
}
break;
case SIOCDELRT: /* Delete an entry from the routing table */
{
if (rtentry)
{
uip_ipaddr_t target;
uip_ipaddr_t netmask;
@ -573,6 +659,7 @@ static int netdev_rtioctl(FAR struct socket *psock, int cmd,
#endif
ret = net_delroute(target, netmask);
}
}
break;
default: