diff mbox

netdevice.7: document SIOCGIFCONF case ifc_req==NULL

Message ID 20140109233018.886FA140064@xenon.ts.pxnet.com
State Not Applicable, archived
Delegated to: David Miller
Headers show

Commit Message

Tilman Schmidt Jan. 9, 2014, 11:30 p.m. UTC
Add the missing description of the possibility to call SIOCGIFCONF
with ifc_req==NULL to determine the needed buffer size, as described
in http://lkml.indiana.edu/hypermail/linux/kernel/0110.1/0506.html
and verified against source files net/core/dev_ioctl.c and
net/ipv4/devinet.c in the current kernel git tree.
This functionality has been present since the beginning of the 2.6
series. It's about time it gets documented.
While I'm at it, also generally clarify the section on SIOCGIFCONF.

Patch prepared against man-pages version 3.55.

Signed-off-by: Tilman Schmidt <tilman@imap.cc>

---
 man7/netdevice.7 |   83 +++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 57 insertions(+), 26 deletions(-)

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Michael Kerrisk \(man-pages\) Jan. 10, 2014, 5:52 p.m. UTC | #1
On 01/10/2014 12:30 PM, Tilman Schmidt wrote:
> Add the missing description of the possibility to call SIOCGIFCONF
> with ifc_req==NULL to determine the needed buffer size, as described
> in http://lkml.indiana.edu/hypermail/linux/kernel/0110.1/0506.html
> and verified against source files net/core/dev_ioctl.c and
> net/ipv4/devinet.c in the current kernel git tree.
> This functionality has been present since the beginning of the 2.6
> series. It's about time it gets documented.
> While I'm at it, also generally clarify the section on SIOCGIFCONF.
> 
> Patch prepared against man-pages version 3.55.
> 
> Signed-off-by: Tilman Schmidt <tilman@imap.cc>

Hello Tilman,

Thanks for the patch. I'm trying to verify this from the code, but 
am having some trouble finding the relevant pieces. Could you point
me more specifically at the points in the kernel source where this
case is handled?

Thanks,

Michael



> ---
>  man7/netdevice.7 |   83 +++++++++++++++++++++++++++++++++++++------------------
>  1 file changed, 57 insertions(+), 26 deletions(-)
> 
> --- a/man7/netdevice.7	2013-12-12 08:42:55.000000000 +0100
> +++ b/man7/netdevice.7	2014-01-09 23:43:23.000000000 +0100
> @@ -15,7 +15,7 @@
>  .\" Modified, 2011-11-02, <bidulock@openss7.org>, added many basic
>  .\"  but missing ioctls, such as SIOCGIFADDR.
>  .\"
> -.TH NETDEVICE  7 2012-04-26 "Linux" "Linux Programmer's Manual"
> +.TH NETDEVICE  7 2014-01-09 "Linux" "Linux Programmer's Manual"
>  .SH NAME
>  netdevice \- low-level access to Linux network devices
>  .SH SYNOPSIS
> @@ -29,7 +29,7 @@
>  Linux supports some standard ioctls to configure network devices.
>  They can be used on any socket's file descriptor regardless of the
>  family or type.
> -They pass an
> +Most of them pass an
>  .I ifreq
>  structure:
>  
> @@ -53,14 +53,6 @@
>          char           *ifr_data;
>      };
>  };
> -
> -struct ifconf {
> -    int                 ifc_len; /* size of buffer */
> -    union {
> -        char           *ifc_buf; /* buffer address */
> -        struct ifreq   *ifc_req; /* array of structures */
> -    };
> -};
>  .fi
>  .in
>  
> @@ -265,30 +257,69 @@
>  means only addresses of the
>  .B AF_INET
>  (IPv4) family for compatibility.
> -The user passes a
> +Unlike the others, this ioctl passes an
>  .I ifconf
> -structure as argument to the ioctl.
> -It contains a pointer to an array of
> -.I ifreq
> -structures in
> +structure:
> +
> +.in +4n
> +.nf
> +struct ifconf {
> +    int                 ifc_len; /* size of buffer */
> +    union {
> +        char           *ifc_buf; /* buffer address */
> +        struct ifreq   *ifc_req; /* array of structures */
> +    };
> +};
> +.fi
> +.in
> +
> +If
>  .I ifc_req
> -and its length in bytes in
> +is NULL,
> +.B SIOCGIFCONF
> +returns the necessary buffer size in bytes
> +for receiving all available addresses in
>  .IR ifc_len .
> -The kernel fills the ifreqs with all current L3 interface addresses that
> -are running:
> +Otherwise
> +.I ifc_req
> +contains a pointer to an array of
> +.I ifreq
> +structures to be filled with all currently active L3 interface addresses.
> +.I ifc_len
> +contains the size of the array in bytes.
> +Within each
> +.I ifreq
> +structure,
>  .I ifr_name
> -contains the interface name (eth0:1 etc.),
> +will receive the interface name, and
>  .I ifr_addr
>  the address.
> -The kernel returns with the actual length in
> +The actual number of bytes transferred is returned in
>  .IR ifc_len .
> -If
> +
> +If the size specified by
> +.I ifc_len
> +is insufficient to store all the addresses,
> +the kernel will skip the exceeding ones and return success.
> +There is no reliable way of detecting this condition once it has occurred.
> +It is therefore recommended to either determine the necessary buffer size
> +beforehand by calling
> +.B SIOCGIFCONF
> +with
> +.I ifc_req
> +set to NULL, or to retry the call with a bigger buffer whenever
>  .I ifc_len
> -is equal to the original length the buffer probably has overflowed
> -and you should retry with a bigger buffer to get all addresses.
> -When no error occurs the ioctl returns 0;
> -otherwise \-1.
> -Overflow is not an error.
> +upon return differs by less than sizeof(struct
> +.IR ifreq )
> +from its original value.
> +
> +If an error occurs accessing the
> +.I ifconf
> +or
> +.I ifreq
> +structures,
> +.B EFAULT
> +will be returned.
>  .\" Slaving isn't supported in 2.2
>  .\" .
>  .\" .TP
>
Tilman Schmidt Jan. 10, 2014, 7:35 p.m. UTC | #2
Hello Michael,

Am 10.01.2014 18:52, schrieb Michael Kerrisk (man-pages):
> On 01/10/2014 12:30 PM, Tilman Schmidt wrote:
>> Add the missing description of the possibility to call SIOCGIFCONF
>> with ifc_req==NULL to determine the needed buffer size, as described
>> in http://lkml.indiana.edu/hypermail/linux/kernel/0110.1/0506.html
>> and verified against source files net/core/dev_ioctl.c and
>> net/ipv4/devinet.c in the current kernel git tree.
[...]>
> Thanks for the patch. I'm trying to verify this from the code, but 
> am having some trouble finding the relevant pieces. Could you point
> me more specifically at the points in the kernel source where this
> case is handled?

Gladly.

Function dev_ifconf() [net/core/dev_ioctl.c line 67ff.] is the main
handler for SIOCGIFCONF. It calls the registered protocol specific
handlers via the table gifconf_list[]. The current kernel has only
one such handler, inet_gifconf() [net/ipv4/devinet.c line 1115ff.]

If ifc.ifc_buf is NULL, dev_ifconf() calls the protocol specific
handlers with NULL as second argument. [net/core/dev_ioctl.c line 96]

If inet_gifconf() is called with NULL as second argument it just
adds up the data sizes, skipping the size check and data transfer.
[net/ipv4/devinet.c line 1127f.]

Best regards,
Tilman
Michael Kerrisk \(man-pages\) Jan. 16, 2014, 4:23 a.m. UTC | #3
On 01/11/2014 08:35 AM, Tilman Schmidt wrote:
> Hello Michael,
> 
> Am 10.01.2014 18:52, schrieb Michael Kerrisk (man-pages):
>> On 01/10/2014 12:30 PM, Tilman Schmidt wrote:
>>> Add the missing description of the possibility to call SIOCGIFCONF
>>> with ifc_req==NULL to determine the needed buffer size, as described
>>> in http://lkml.indiana.edu/hypermail/linux/kernel/0110.1/0506.html
>>> and verified against source files net/core/dev_ioctl.c and
>>> net/ipv4/devinet.c in the current kernel git tree.
> [...]>
>> Thanks for the patch. I'm trying to verify this from the code, but 
>> am having some trouble finding the relevant pieces. Could you point
>> me more specifically at the points in the kernel source where this
>> case is handled?
> 
> Gladly.
> 
> Function dev_ifconf() [net/core/dev_ioctl.c line 67ff.] is the main
> handler for SIOCGIFCONF. It calls the registered protocol specific
> handlers via the table gifconf_list[]. The current kernel has only
> one such handler, inet_gifconf() [net/ipv4/devinet.c line 1115ff.]
> 
> If ifc.ifc_buf is NULL, dev_ifconf() calls the protocol specific
> handlers with NULL as second argument. [net/core/dev_ioctl.c line 96]
> 
> If inet_gifconf() is called with NULL as second argument it just
> adds up the data sizes, skipping the size check and data transfer.
> [net/ipv4/devinet.c line 1127f.]

Thanks. Patch applied.

Cheers,

Michael
diff mbox

Patch

--- a/man7/netdevice.7	2013-12-12 08:42:55.000000000 +0100
+++ b/man7/netdevice.7	2014-01-09 23:43:23.000000000 +0100
@@ -15,7 +15,7 @@ 
 .\" Modified, 2011-11-02, <bidulock@openss7.org>, added many basic
 .\"  but missing ioctls, such as SIOCGIFADDR.
 .\"
-.TH NETDEVICE  7 2012-04-26 "Linux" "Linux Programmer's Manual"
+.TH NETDEVICE  7 2014-01-09 "Linux" "Linux Programmer's Manual"
 .SH NAME
 netdevice \- low-level access to Linux network devices
 .SH SYNOPSIS
@@ -29,7 +29,7 @@ 
 Linux supports some standard ioctls to configure network devices.
 They can be used on any socket's file descriptor regardless of the
 family or type.
-They pass an
+Most of them pass an
 .I ifreq
 structure:
 
@@ -53,14 +53,6 @@ 
         char           *ifr_data;
     };
 };
-
-struct ifconf {
-    int                 ifc_len; /* size of buffer */
-    union {
-        char           *ifc_buf; /* buffer address */
-        struct ifreq   *ifc_req; /* array of structures */
-    };
-};
 .fi
 .in
 
@@ -265,30 +257,69 @@ 
 means only addresses of the
 .B AF_INET
 (IPv4) family for compatibility.
-The user passes a
+Unlike the others, this ioctl passes an
 .I ifconf
-structure as argument to the ioctl.
-It contains a pointer to an array of
-.I ifreq
-structures in
+structure:
+
+.in +4n
+.nf
+struct ifconf {
+    int                 ifc_len; /* size of buffer */
+    union {
+        char           *ifc_buf; /* buffer address */
+        struct ifreq   *ifc_req; /* array of structures */
+    };
+};
+.fi
+.in
+
+If
 .I ifc_req
-and its length in bytes in
+is NULL,
+.B SIOCGIFCONF
+returns the necessary buffer size in bytes
+for receiving all available addresses in
 .IR ifc_len .
-The kernel fills the ifreqs with all current L3 interface addresses that
-are running:
+Otherwise
+.I ifc_req
+contains a pointer to an array of
+.I ifreq
+structures to be filled with all currently active L3 interface addresses.
+.I ifc_len
+contains the size of the array in bytes.
+Within each
+.I ifreq
+structure,
 .I ifr_name
-contains the interface name (eth0:1 etc.),
+will receive the interface name, and
 .I ifr_addr
 the address.
-The kernel returns with the actual length in
+The actual number of bytes transferred is returned in
 .IR ifc_len .
-If
+
+If the size specified by
+.I ifc_len
+is insufficient to store all the addresses,
+the kernel will skip the exceeding ones and return success.
+There is no reliable way of detecting this condition once it has occurred.
+It is therefore recommended to either determine the necessary buffer size
+beforehand by calling
+.B SIOCGIFCONF
+with
+.I ifc_req
+set to NULL, or to retry the call with a bigger buffer whenever
 .I ifc_len
-is equal to the original length the buffer probably has overflowed
-and you should retry with a bigger buffer to get all addresses.
-When no error occurs the ioctl returns 0;
-otherwise \-1.
-Overflow is not an error.
+upon return differs by less than sizeof(struct
+.IR ifreq )
+from its original value.
+
+If an error occurs accessing the
+.I ifconf
+or
+.I ifreq
+structures,
+.B EFAULT
+will be returned.
 .\" Slaving isn't supported in 2.2
 .\" .
 .\" .TP