Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
net_ioctl [2018/09/03 15:55] – [net/core/dev_ioctl.c] rpjdaynet_ioctl [2018/09/04 10:31] (current) – [send_ioctl()] rpjday
Line 18: Line 18:
       * [[https://github.com/torvalds/linux/blob/master/net/core/dev_ioctl.c|dev_ioctl.c]]       * [[https://github.com/torvalds/linux/blob/master/net/core/dev_ioctl.c|dev_ioctl.c]]
  
-===== Sample userspace call =====+===== Sample userspace call: ethtool =====
  
-From ''ethtool'', which has a ''send_ioctl()'' wrapper:+Git repo is [[https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/|here]]. 
 + 
 +==== send_ioctl() ==== 
 + 
 +From ''ethtool.c'',simple wrapper around the ''ioctl()'' call:
  
 <code> <code>
Line 26: Line 30:
 int send_ioctl(struct cmd_context *ctx, void *cmd) int send_ioctl(struct cmd_context *ctx, void *cmd)
 { {
-        ctx->ifr.ifr_data = cmd;+        ctx->ifr.ifr_data = cmd;        // command-specific structure
         return ioctl(ctx->fd, SIOCETHTOOL, &ctx->ifr);         return ioctl(ctx->fd, SIOCETHTOOL, &ctx->ifr);
 } }
 #endif #endif
 +</code>
 +
 +QUESTION: What is returned in ifreq%%->%%cmd?
 +
 +==== struct cmd_context ====
 +
 +From ''internal.h'', ''struct cmd_context'' showing the embedded ''struct ifreq'':
 +
 +<code>
 +/* Context for sub-commands */
 +struct cmd_context {
 +        const char *devname;    /* net device name */
 +        int fd;                 /* socket suitable for ethtool ioctl */
 +        struct ifreq ifr;       /* ifreq suitable for ethtool ioctl */
 +        int argc;               /* number of arguments to the sub-command */
 +        char **argp;            /* arguments to the sub-command */
 +};
 +
 +</code>
 +
 +==== struct ifreq ====
 +
 +From ''include/uapi/linux/if.h'', the unsigned long arg passed with ''ioctl()'':
 +
 +<code>
 +#if __UAPI_DEF_IF_IFREQ
 +struct ifreq {
 +#define IFHWADDRLEN     6
 +        union
 +        {
 +                char    ifrn_name[IFNAMSIZ];            /* if name, e.g. "en0" */
 +        } ifr_ifrn;
 +
 +        union {
 +                struct  sockaddr ifru_addr;
 +                struct  sockaddr ifru_dstaddr;
 +                struct  sockaddr ifru_broadaddr;
 +                struct  sockaddr ifru_netmask;
 +                struct  sockaddr ifru_hwaddr;
 +                short   ifru_flags;
 +                int     ifru_ivalue;
 +                int     ifru_mtu;
 +                struct  ifmap ifru_map;
 +                char    ifru_slave[IFNAMSIZ];   /* Just fits the size */
 +                char    ifru_newname[IFNAMSIZ];
 +                void __user *   ifru_data;
 +                struct  if_settings ifru_settings;
 +        } ifr_ifru;
 +};
 +#endif /* __UAPI_DEF_IF_IFREQ */
 +
 +#define ifr_name        ifr_ifrn.ifrn_name      /* interface name       */
 +#define ifr_hwaddr      ifr_ifru.ifru_hwaddr    /* MAC address          */
 +#define ifr_addr        ifr_ifru.ifru_addr      /* address              */
 +#define ifr_dstaddr     ifr_ifru.ifru_dstaddr   /* other end of p-p lnk */
 +#define ifr_broadaddr   ifr_ifru.ifru_broadaddr /* broadcast address    */
 +#define ifr_netmask     ifr_ifru.ifru_netmask   /* interface net mask   */
 +#define ifr_flags       ifr_ifru.ifru_flags     /* flags                */
 +#define ifr_metric      ifr_ifru.ifru_ivalue    /* metric               */
 +#define ifr_mtu         ifr_ifru.ifru_mtu       /* mtu                  */
 +#define ifr_map         ifr_ifru.ifru_map       /* device map           */
 +#define ifr_slave       ifr_ifru.ifru_slave     /* slave device         */
 +#define ifr_data        ifr_ifru.ifru_data      /* for use by interface */
 +#define ifr_ifindex     ifr_ifru.ifru_ivalue    /* interface index      */
 +#define ifr_bandwidth   ifr_ifru.ifru_ivalue    /* link bandwidth       */
 +#define ifr_qlen        ifr_ifru.ifru_ivalue    /* Queue length         */
 +#define ifr_newname     ifr_ifru.ifru_newname   /* New name             */
 +#define ifr_settings    ifr_ifru.ifru_settings  /* Device/proto settings*/
 </code> </code>
  
Line 62: Line 134:
 ==== sock_ioctl() ==== ==== sock_ioctl() ====
  
-Also from ''net/socket.c'':+Also from ''net/socket.c'' -- anything related to ''SIOCDEVPRIVATE'' is seriously deprecated (see [[https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/sockios.h#L135|here]]):
  
 <code> <code>
Line 86: Line 158:
                                 return -EFAULT;                                 return -EFAULT;
         } else         } else
 +</code>
 +
 +This reflects wireless extensions, which should not be relevant:
 +
 +<code>
 #ifdef CONFIG_WEXT_CORE #ifdef CONFIG_WEXT_CORE
         if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {         if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
Line 91: Line 168:
         } else         } else
 #endif #endif
 +</code>
 +
 +Finally, this is where we should end up:
 +
 +<code>
                 switch (cmd) {                 switch (cmd) {
                 case FIOSETOWN:                 case FIOSETOWN:
  • net_ioctl.1535990133.txt.gz
  • Last modified: 2018/09/03 15:55
  • by rpjday