2014年1月14日 星期二

socket ioctls

socket 嘛和檔案仝款,有 struct file_operations,ioctl() 系統呼叫時,會執行 sock_ioctl()。[見 Linux /net/socket.c]

long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
其中 file 只用到 file->private_data,其實就是指向 struct socket,然後可取得 socket 其它相關資訊,例如 struct sock、 struct net 等。cmd 是指令編號,定義在 <linux/sockios.h>。argcmd 用的參數,通常指到 user space 的一塊記憶體。

sock_ioctl() 會依據 cmd 設定或讀取 owner/group、bridge、VLAN、DLCI,另外 0x89F? (SIOCDEVPRIVATE) 和 0x8B?? (SIOCIW*) 這兩段是呼叫 dev_ioctl() 交由 device 處理,剩下的呼叫 socket 的 ops->ioctl()。

在 dev_ioctl(),幾乎所有的 cmd 都將 arg 所指的 user space 資料複製到 kernel space 作為 struct ifreq 使用,執行結束後會再複製回 user space,此時 ioctl() 系統呼叫的 arg 所指資料結構需要符合 struct ifreq,才能正確傳遞資訊 [見 Linux /net/core/dev.c,struct ifreq 定義在 <linux/if.h>]。

呼叫 dev_ioctl() 交由 device 處理需要找到特定 device 的資料結構,也就是 struct net_device。struct ifreq 包含 ifr_name,也就是 ifconfig 看到的網路界面名稱,用來找出 struct net_device。程式碼如下:

struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name);
dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd);
/* 註:以前是 dev->do_ioctl */

預留的 cmd
  • SIOCDEVPRIVATE ~ SIOCDEVPRIVATE+15, 共16 個專門給 device 使用。
  • Wireless 預留 SIOCIWFIRST ~ SIOCIWLAST,共 256 個,定義在 <linux/wireless.h>,包括 SIOCIWFIRSTPRIV ~ SIOCIWLASTPRIV 有 32 個。其中奇數是 GET cmd 才能回傳資料給 user space。處理這些 cmd 的函式,可能是 iw_handler_get_iwstats (SIOCGIWSTATS)、 iw_handler_get_private (SIOCGIWPRIV)、或者來自函式表 dev->ieee80211_ptr->wiphy->wext 或 dev->wireless_handlers ,不然就用 ndo_do_ioctl()。
範例:
  • plip 更改內部 timeout 值。
  • ppp-stats 取得 ppp 驅動程式的資訊。
參考:
  1. LDD3 ch17 
  2. Linux 3.3.8 source codes 
延伸閱讀

沒有留言:

張貼留言

SIP header Via

所有 SIP 訊息 都要有 Via,縮寫 v。一開始的 UAC 和後續途經的每個 proxy 都會疊加一個 Via 放傳送的位址,依序作為回應的路徑。 格式 sent-protocol sent-by [ ;branch= branch ][ ; 參數 ...] s...