mdsingh
mdsingh

Reputation: 1113

Which driver is handling my IOCTL

I am opening a socket like this: skfd = socket( AF_INET, SOCK_DGRAM, 0 ); and then doing an ioctl on skfd like: ioctl(skfd, SIOCETHTOOL, &ifr)
I want to know which driver is handling this IOCTL in my kernel.
I know that had it been a character driver, I could have looked up for the major number of the file I am opening and then do a cat /proc/devices to find which driver is registered with that major number.
Must be some similar way here.

Upvotes: 3

Views: 4270

Answers (1)

Krzysztof Adamski
Krzysztof Adamski

Reputation: 2079

The fish

You are calling ioctl on a filedescriptor that is representing socket. If you examine net/socket.c file, you will find socket_file_ops structure that defines sock_ioctl as a ioctl callback. For SIOCETHTOOL, this function will call sock_do_ioctl which in turn (after checking that this particular socket type (AF_INET - af_inet.c, inet_ioctl function) does not handle this ioctl by itself) will call dev_ioctl which can handle SIOCETHTOOL by calling dev_ethtool. If your driver defines ethtool_ops, this should be supported.

Now finding which device driver supports your network interface is another thing but this isn't really hard. One way to do this is to use sysfs, just check what is this symlink pointing to (substituting eth0 with your interface name):

readlink /sys/class/net/eth0/device/driver/module
../../../../module/e1000e

So my ethernet card is driven by module e1000e.

The fishing rod

Now I found this out by reading the code. I do know something about kernel code so I knew where I should look. If I wouldn't, however, there's other way to find this out - tracing. Now I'm not sure if all this works on 2.6.32, but at least I tested this on kernel 3.2 (which isn't that much different). I won't go into details on how to configure your kernel to have all those functionalities. Ubuntu 12.04 has all that is needed and if you're interested google for ftrace:

You need debugfs mounted and a script like this:

#!/bin/sh
DEBUGFS=`/sys/kernel/debug/`
echo $$ > $DEBUGFS/tracing/set_ftrace_pid
echo function > $DEBUGFS/tracing/current_tracer
exec $*

This script will set ftrace to only care about current PID, enable function tracer and exec the command specified as an argument (without forking as that would change the PID).

Now, if your application that is using this ioctl is /tmp/a.out, you can call:

~/bin/ftraceme.sh /tmp/a.out
echo -n "" > /sys/kernel/debug/tracing/current_tracer
grep ioctl /sys/kernel/debug/tracing/trace

In my case, I've got:

<...>-11009 [007] 596251.750675: sys_ioctl <-system_call_fastpath    (1)
<...>-11009 [007] 596251.750675: fget_light <-sys_ioctl
<...>-11009 [007] 596251.750675: security_file_ioctl <-sys_ioctl
<...>-11009 [007] 596251.750676: cap_file_ioctl <-security_file_ioctl
<...>-11009 [007] 596251.750676: do_vfs_ioctl <-sys_ioctl
<...>-11009 [007] 596251.750676: sock_ioctl <-do_vfs_ioctl           (2)
<...>-11009 [007] 596251.750677: sock_do_ioctl <-sock_ioctl          (3)
<...>-11009 [007] 596251.750677: inet_ioctl <-sock_do_ioctl          (4)
<...>-11009 [007] 596251.750677: udp_ioctl <-inet_ioctl
<...>-11009 [007] 596251.750678: dev_ioctl <-sock_do_ioctl           (5)
<...>-11009 [007] 596251.750678: _cond_resched <-dev_ioctl
<...>-11009 [007] 596251.750679: dev_load <-dev_ioctl
<...>-11009 [007] 596251.750680: rtnl_lock <-dev_ioctl
<...>-11009 [007] 596251.750680: dev_ethtool <-dev_ioctl             (6)
<...>-11009 [007] 596251.750684: rtnl_unlock <-dev_ioctl
<...>-11009 [007] 596251.750685: _cond_resched <-dev_ioctl

Which proves what I wrote above.

Upvotes: 7

Related Questions