Newer
Older
/****************************************************************************
* Copyright (C) 2007-2010 Gregory Nutt. All rights reserved.
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* 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 NuttX 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <string.h>
#include <net/ethernet.h>
#include <net/uip/uip-arch.h>
#include <net/uip/uip.h>
#ifdef CONFIG_NET_IGMP
# include "sys/sockio.h"
# include "net/uip/uip-igmp.h"
#endif
/****************************************************************************
patacongo
committed
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_NET_IPv6
# define AF_INETX AF_INET6
#else
# define AF_INETX AF_INET
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
*
* Description:
* Copy IP addresses into and out of device structure
*
****************************************************************************/
static void ioctl_getipaddr(struct sockaddr *outaddr, uip_ipaddr_t *inaddr)
{
#ifdef CONFIG_NET_IPv6
struct sockaddr_in6 *dest = (struct sockaddr_in6 *)outaddr;
dest->sin_family = AF_INET6;
dest->sin_port = 0;
memcpy(dest->sin6_addr.in6_u.u6_addr8, inaddr, 16);
#else
struct sockaddr_in *dest = (struct sockaddr_in *)outaddr;
dest->sin_family = AF_INET;
dest->sin_port = 0;
dest->sin_addr.s_addr = *inaddr;
#endif
}
static void ioctl_setipaddr(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.u6_addr8, 16);
#else
struct sockaddr_in *src = (struct sockaddr_in *)inaddr;
*outaddr = src->sin_addr.s_addr;
#endif
}
/****************************************************************************
* Name: ioctl_ifup / ioctl_ifdown
*
* Description:
* Bring the interface up/down
*
****************************************************************************/
static inline void ioctl_ifup(FAR struct uip_driver_s *dev)
/****************************************************************************
* Name: netdev_ioctl
*
* Description:
* Perform network device specific operations.
*
* Parameters:
* psock Socket structure
* dev Ethernet driver device structure
* cmd The ioctl command
* req The argument of the ioctl cmd
*
* Return:
* >=0 on success (positive non-zero values are cmd-specific)
*
****************************************************************************/
static int netdev_ifrioctl(FAR struct socket *psock, int cmd, struct ifreq *req)
FAR struct uip_driver_s *dev;
/* Find the network device associated with the device name
* in the request data.
*/
if (!dev)
{
goto errout;
}
/* Execute the command */
switch (cmd)
{
case SIOCGIFADDR: /* Get IP address */
break;
case SIOCSIFADDR: /* Set IP address */
ioctl_ifdown(dev);
ioctl_setipaddr(&dev->d_ipaddr, &req->ifr_addr);
ioctl_ifup(dev);
break;
case SIOCGIFDSTADDR: /* Get P-to-P address */
break;
case SIOCSIFDSTADDR: /* Set P-to-P address */
break;
case SIOCGIFNETMASK: /* Get network mask */
break;
case SIOCSIFNETMASK: /* Set network mask */
break;
case SIOCGIFMTU: /* Get MTU size */
break;
case SIOCGIFHWADDR: /* Get hardware address */
req->ifr_hwaddr.sa_family = AF_INETX;
memcpy(req->ifr_hwaddr.sa_data, dev->d_mac.ether_addr_octet, IFHWADDRLEN);
break;
case SIOCSIFHWADDR: /* Set hardware address -- will not take effect until ifup */
req->ifr_hwaddr.sa_family = AF_INETX;
memcpy(dev->d_mac.ether_addr_octet, 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();
case SIOCGIFBRDADDR: /* Get broadcast IP address */
case SIOCSIFBRDADDR: /* Set broadcast IP address */
#ifdef CONFIG_NET_ARPIOCTLS
case SIOCSARP: /* Set a ARP mapping */
case SIOCDARP: /* Delete an ARP mapping */
case SIOCGARP: /* Get an ARP mapping */
# error "IOCTL Commands not implemented"
#endif
default:
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
ret = -EINVAL;
break;;
}
errout:
return ret;
}
/****************************************************************************
* Name: netdev_imsfioctl
*
* Description:
* Perform network device specific operations.
*
* Parameters:
* psock Socket structure
* dev Ethernet driver device structure
* cmd The ioctl command
* imsf The argument of the ioctl cmd
*
* Return:
* >=0 on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
#ifdef CONFIG_NET_IGMP
static int netdev_imsfioctl(FAR struct socket *psock, int cmd, struct ip_msfilter *imsf)
{
FAR struct uip_driver_s *dev;
int ret = OK;
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
/* 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 */
{
if (imsf->imsf_fmode == MCAST_INCLUDE)
{
ret = igmp_joingroup(dev, &imsf->imsf_multiaddr);
}
else
{
DEBUGASSERT(imsf->imsf_fmode == MCAST_EXCLUDE);
ret = igmp_leavegroup(dev, &imsf->imsf_multiaddr);
}
}
break;
case SIOCGIPMSFILTER: /* Retrieve source filter addresses */
default:
ret = -EINVAL;
break;
}
errout:
return ret;
}
#endif
/****************************************************************************
* Global Functions
****************************************************************************/
/****************************************************************************
* Name: netdev_ioctl
*
* Description:
* Perform network device specific operations.
*
* Parameters:
* sockfd Socket descriptor of device
* cmd The ioctl command
* req The argument of the ioctl cmd
*
* Return:
* >=0 on success (positive non-zero values are cmd-specific)
* On a failure, -1 is returned with errno set appropriately
*
* EBADF
* 'sockfd' is not a valid descriptor.
* EFAULT
* 'req' references an inaccessible memory area.
* EINVAL
* 'cmd' or 'req' is not valid.
* ENOTTY
* 'sockfd' is not associated with a network device.
* ENOTTY
* The specified request does not apply to the kind of object that the
* descriptor 'sockfd' references.
*
****************************************************************************/
int netdev_ioctl(int sockfd, int cmd, unsigned long arg)
{
FAR struct socket *psock = sockfd_socket(sockfd);
int ret;
/* Check if this is a valid command. In all cases, arg is a pointer that has
* been cast to unsigned long. Verify that the value of the to-be-pointer is
* non-NULL.
*/
if (!_SIOCVALID(cmd) || !arg)
{
ret = -EINVAL;
goto errout;
}
/* Verify that the sockfd corresponds to valid, allocated socket */
if (!psock || psock->s_crefs <= 0)
{
ret = -EBADF;
goto errout;
}
/* Execute the command */
ret = netdev_ifrioctl(psock, cmd, (FAR struct ifreq*)arg);
#ifdef CONFIG_NET_IGMP
if (ret == -EINVAL)
{
ret = netdev_imsfioctl(psock, cmd, (FAR struct ip_msfilter*)arg);
}
#endif
/* Check for success or failure */
if (ret >= 0)
{
return ret;
}
errout: