1999-02-19 03:21:36 +03:00
/*
* Copyright ( c ) 1993 , 1994 , 1995 , 1996 Rick Sladkey < jrs @ world . std . com >
2017-05-22 20:14:52 +03:00
* Copyright ( c ) 1996 - 2017 The strace developers .
1999-02-19 03:21:36 +03:00
* All rights reserved .
*
* 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. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ` ` 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 AUTHOR 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 .
*/
# include "defs.h"
2017-07-09 19:04:24 +03:00
# include "print_fields.h"
2016-12-26 17:07:24 +03:00
1999-02-19 03:21:36 +03:00
# include <sys/socket.h>
2016-05-13 23:22:18 +03:00
# if defined ALPHA || defined SH || defined SH64
# include <linux / ioctl.h>
# endif
2004-07-12 11:13:06 +04:00
# include <linux/sockios.h>
# include <arpa/inet.h>
# include <net/if.h>
2016-12-26 17:07:24 +03:00
# include DEF_MPERS_TYPE(struct_ifconf)
# include DEF_MPERS_TYPE(struct_ifreq)
typedef struct ifconf struct_ifconf ;
typedef struct ifreq struct_ifreq ;
# include MPERS_DEFS
2014-04-26 03:30:54 +04:00
# include "xlat/iffflags.h"
2005-02-02 Roland McGrath <roland@redhat.com>
* sock.c (iffflags): New variable, table of IFF_* values.
(print_addr): New function.
(sock_ioctl): Handle SIOCGIFADDR, SIOCGIFDSTADDR, SIOCGIFBRDADDR,
SIOCGIFNETMASK, SIOCGIFFLAGS, SIOCGIFMETRIC, SIOCGIFMTU, SIOCGIFSLAVE,
SIOCGIFHWADDR. Use print_addr for SIOCGIFCONF, SIOCGIFNAME, and
SIOCGIFINDEX, and fix their output.
From Ulrich Drepper <drepper@redhat.com>.
Fixes RH#138223.
2005-02-02 23:25:17 +03:00
2015-01-24 23:58:23 +03:00
static void
print_ifname ( const char * ifname )
{
print_quoted_string ( ifname , IFNAMSIZ + 1 , QUOTE_0_TERMINATED ) ;
}
2015-07-04 14:01:08 +03:00
static void
Change type of ioctl 3rd argument from long to kernel_ureg_t
* defs.h (DECL_IOCTL): Change arg type from long to kernel_ureg_t.
* dm.c (dm_known_ioctl, dm_ioctl): Likewise.
* file_ioctl.c (file_ioctl): Likewise.
* fs_x_ioctl.c (fs_x_ioctl): Likewise.
* ioctl.c (ioctl_decode): Likewise.
* loop.c (decode_loop_info, decode_loop_info64): Change addr type
from long to kernel_ureg_t.
(loop_ioctl): Change arg type from long to kernel_ureg_t.
* ptp.c (ptp_ioctl): Likewise.
* scsi.c (print_sg_io_v3_req, print_sg_io_v3_res, print_sg_io_v4_req,
print_sg_io_v4_res, scsi_ioctl): Likewise.
* sock.c (print_ifreq, sock_ioctl): Likewise.
(decode_ifconf): Change addr type from long to kernel_ureg_t.
* term.c (decode_termios, decode_termio, decode_winsize, decode_ttysize,
decode_modem_flags): Likewise.
(term_ioctl): Change arg type from long to kernel_ureg_t.
* ubi.c (ubi_ioctl): Likewise.
* userfaultfd.c (uffdio_ioctl): Likewise.
2016-12-21 06:03:09 +03:00
print_ifreq ( struct tcb * const tcp , const unsigned int code ,
2016-12-26 17:07:24 +03:00
const kernel_ulong_t arg , const struct_ifreq * const ifr )
2015-07-04 14:01:08 +03:00
{
switch ( code ) {
case SIOCSIFADDR :
case SIOCGIFADDR :
2017-07-09 19:04:24 +03:00
PRINT_FIELD_SOCKADDR ( " " , * ifr , ifr_addr ) ;
2015-07-04 14:01:08 +03:00
break ;
case SIOCSIFDSTADDR :
case SIOCGIFDSTADDR :
2017-07-09 19:04:24 +03:00
PRINT_FIELD_SOCKADDR ( " " , * ifr , ifr_dstaddr ) ;
2015-07-04 14:01:08 +03:00
break ;
case SIOCSIFBRDADDR :
case SIOCGIFBRDADDR :
2017-07-09 19:04:24 +03:00
PRINT_FIELD_SOCKADDR ( " " , * ifr , ifr_broadaddr ) ;
2015-07-04 14:01:08 +03:00
break ;
case SIOCSIFNETMASK :
case SIOCGIFNETMASK :
2017-07-09 19:04:24 +03:00
PRINT_FIELD_SOCKADDR ( " " , * ifr , ifr_netmask ) ;
2015-07-04 14:01:08 +03:00
break ;
case SIOCSIFHWADDR :
case SIOCGIFHWADDR : {
/* XXX Are there other hardware addresses
than 6 - byte MACs ? */
const unsigned char * bytes =
( unsigned char * ) & ifr - > ifr_hwaddr . sa_data ;
tprintf ( " ifr_hwaddr=%02x:%02x:%02x:%02x:%02x:%02x " ,
bytes [ 0 ] , bytes [ 1 ] , bytes [ 2 ] ,
bytes [ 3 ] , bytes [ 4 ] , bytes [ 5 ] ) ;
break ;
}
case SIOCSIFFLAGS :
case SIOCGIFFLAGS :
tprints ( " ifr_flags= " ) ;
2016-05-17 01:05:06 +03:00
printflags ( iffflags , ( unsigned short ) ifr - > ifr_flags , " IFF_??? " ) ;
2015-07-04 14:01:08 +03:00
break ;
case SIOCSIFMETRIC :
case SIOCGIFMETRIC :
tprintf ( " ifr_metric=%d " , ifr - > ifr_metric ) ;
break ;
case SIOCSIFMTU :
case SIOCGIFMTU :
tprintf ( " ifr_mtu=%d " , ifr - > ifr_mtu ) ;
break ;
case SIOCSIFSLAVE :
case SIOCGIFSLAVE :
tprints ( " ifr_slave= " ) ;
print_ifname ( ifr - > ifr_slave ) ;
break ;
case SIOCSIFTXQLEN :
case SIOCGIFTXQLEN :
tprintf ( " ifr_qlen=%d " , ifr - > ifr_qlen ) ;
break ;
case SIOCSIFMAP :
case SIOCGIFMAP :
2016-12-26 17:07:24 +03:00
tprintf ( " ifr_map={mem_start=%# " PRI_klx " , "
" mem_end=%# " PRI_klx " , base_addr=%#x, "
2015-07-04 14:01:08 +03:00
" irq=%u, dma=%u, port=%u} " ,
2016-12-26 17:07:24 +03:00
( kernel_ulong_t ) ifr - > ifr_map . mem_start ,
( kernel_ulong_t ) ifr - > ifr_map . mem_end ,
2015-07-04 14:01:08 +03:00
( unsigned ) ifr - > ifr_map . base_addr ,
( unsigned ) ifr - > ifr_map . irq ,
( unsigned ) ifr - > ifr_map . dma ,
( unsigned ) ifr - > ifr_map . port ) ;
break ;
}
}
static unsigned int
print_ifc_len ( int len )
{
2016-12-26 17:07:24 +03:00
const unsigned int n = ( unsigned int ) len / sizeof ( struct_ifreq ) ;
2015-07-04 14:01:08 +03:00
2016-12-26 17:07:24 +03:00
if ( len < 0 | | n * sizeof ( struct_ifreq ) ! = ( unsigned int ) len )
2015-07-04 14:01:08 +03:00
tprintf ( " %d " , len ) ;
else
tprintf ( " %u * sizeof(struct ifreq) " , n ) ;
return n ;
}
2016-12-23 22:53:22 +03:00
static bool
print_ifconf_ifreq ( struct tcb * tcp , void * elem_buf , size_t elem_size ,
void * dummy )
{
2016-12-26 17:07:24 +03:00
struct_ifreq * ifr = elem_buf ;
2016-12-23 22:53:22 +03:00
tprints ( " {ifr_name= " ) ;
print_ifname ( ifr - > ifr_name ) ;
2017-07-09 19:04:24 +03:00
PRINT_FIELD_SOCKADDR ( " , " , * ifr , ifr_addr ) ;
2016-12-23 22:53:22 +03:00
tprints ( " } " ) ;
return true ;
}
/*
* There are two different modes of operation :
*
* - Get buffer size . In this case , the callee sets ifc_buf to NULL ,
* and the kernel returns the buffer size in ifc_len .
* - Get actual data . In this case , the callee specifies the buffer address
* in ifc_buf and its size in ifc_len . The kernel fills the buffer with
* the data , and its amount is returned in ifc_len .
*
* Note that , technically , the whole struct ifconf is overwritten ,
* so ifc_buf could be different on exit , but current ioctl handler
* implementation does not touch it .
*/
2015-07-04 14:01:08 +03:00
static int
2016-12-26 13:26:03 +03:00
decode_ifconf ( struct tcb * const tcp , const kernel_ulong_t addr )
1999-02-19 03:21:36 +03:00
{
2016-12-26 17:07:24 +03:00
struct_ifconf * entering_ifc = NULL ;
struct_ifconf * ifc =
2016-12-23 22:53:22 +03:00
entering ( tcp ) ? malloc ( sizeof ( * ifc ) ) : alloca ( sizeof ( * ifc ) ) ;
2004-07-12 11:13:06 +04:00
2016-12-23 22:53:22 +03:00
if ( exiting ( tcp ) ) {
entering_ifc = get_tcb_priv_data ( tcp ) ;
if ( ! entering_ifc ) {
error_msg ( " decode_ifconf: where is my ifconf? " ) ;
return 0 ;
2004-07-12 11:13:06 +04:00
}
2015-07-04 14:01:08 +03:00
}
2016-12-23 22:53:22 +03:00
if ( ! ifc | | umove ( tcp , addr , ifc ) < 0 ) {
if ( entering ( tcp ) ) {
free ( ifc ) ;
tprints ( " , " ) ;
2015-07-04 14:01:08 +03:00
printaddr ( addr ) ;
2016-12-23 22:53:22 +03:00
} else {
/*
* We failed to fetch the structure on exiting syscall ,
* print whatever was fetched on entering syscall .
*/
if ( ! entering_ifc - > ifc_buf )
print_ifc_len ( entering_ifc - > ifc_len ) ;
1999-02-19 03:21:36 +03:00
2016-12-23 22:53:22 +03:00
tprints ( " , ifc_buf= " ) ;
printaddr ( ptr_to_kulong ( entering_ifc - > ifc_buf ) ) ;
tprints ( " } " ) ;
}
2015-07-04 14:01:08 +03:00
return RVAL_DECODED | 1 ;
}
2016-12-23 22:53:22 +03:00
if ( entering ( tcp ) ) {
tprints ( " , {ifc_len= " ) ;
if ( ifc - > ifc_buf )
print_ifc_len ( ifc - > ifc_len ) ;
set_tcb_priv_data ( tcp , ifc , free ) ;
return 1 ;
2015-07-04 14:01:08 +03:00
}
2016-12-23 22:53:22 +03:00
/* exiting */
if ( entering_ifc - > ifc_buf & & ( entering_ifc - > ifc_len ! = ifc - > ifc_len ) )
tprints ( " => " ) ;
if ( ! entering_ifc - > ifc_buf | | ( entering_ifc - > ifc_len ! = ifc - > ifc_len ) )
print_ifc_len ( ifc - > ifc_len ) ;
tprints ( " , ifc_buf= " ) ;
if ( ! entering_ifc - > ifc_buf | | syserror ( tcp ) ) {
printaddr ( ptr_to_kulong ( entering_ifc - > ifc_buf ) ) ;
if ( entering_ifc - > ifc_buf ! = ifc - > ifc_buf ) {
tprints ( " => " ) ;
printaddr ( ptr_to_kulong ( ifc - > ifc_buf ) ) ;
}
} else {
2016-12-26 17:07:24 +03:00
struct_ifreq ifr ;
2016-12-23 22:53:22 +03:00
print_array ( tcp , ptr_to_kulong ( ifc - > ifc_buf ) ,
2016-12-26 17:07:24 +03:00
ifc - > ifc_len / sizeof ( struct_ifreq ) ,
2016-12-23 22:53:22 +03:00
& ifr , sizeof ( ifr ) ,
umoven_or_printaddr , print_ifconf_ifreq , NULL ) ;
2015-07-04 14:01:08 +03:00
}
2016-12-23 22:53:22 +03:00
tprints ( " } " ) ;
2015-07-04 14:01:08 +03:00
return RVAL_DECODED | 1 ;
}
2016-12-26 17:07:24 +03:00
MPERS_PRINTER_DECL ( int , sock_ioctl ,
struct tcb * tcp , const unsigned int code ,
const kernel_ulong_t arg )
2015-07-04 14:01:08 +03:00
{
2016-12-26 17:07:24 +03:00
struct_ifreq ifr ;
2015-07-04 14:01:08 +03:00
1999-02-19 03:21:36 +03:00
switch ( code ) {
2015-07-04 14:01:08 +03:00
case SIOCGIFCONF :
return decode_ifconf ( tcp , arg ) ;
# ifdef SIOCBRADDBR
case SIOCBRADDBR :
case SIOCBRDELBR :
tprints ( " , " ) ;
2016-12-20 19:43:26 +03:00
printstr ( tcp , arg ) ;
2015-07-04 14:01:08 +03:00
break ;
1999-02-19 03:21:36 +03:00
# endif
2015-07-04 14:01:08 +03:00
1999-02-19 03:21:36 +03:00
# ifdef FIOSETOWN
case FIOSETOWN :
# endif
# ifdef SIOCSPGRP
case SIOCSPGRP :
2015-07-04 14:01:08 +03:00
# endif
tprints ( " , " ) ;
printnum_int ( tcp , arg , " %d " ) ;
break ;
# ifdef FIOGETOWN
case FIOGETOWN :
1999-02-19 03:21:36 +03:00
# endif
# ifdef SIOCGPGRP
case SIOCGPGRP :
# endif
# ifdef SIOCATMARK
case SIOCATMARK :
# endif
2015-07-04 14:01:08 +03:00
if ( entering ( tcp ) )
return 0 ;
tprints ( " , " ) ;
printnum_int ( tcp , arg , " %d " ) ;
break ;
# ifdef SIOCBRADDIF
case SIOCBRADDIF :
# endif
# ifdef SIOCBRDELIF
case SIOCBRDELIF :
# endif
/* no arguments */
break ;
2014-10-31 22:36:01 +03:00
case SIOCSIFNAME :
2015-07-04 14:01:08 +03:00
case SIOCSIFADDR :
case SIOCSIFDSTADDR :
case SIOCSIFBRDADDR :
case SIOCSIFNETMASK :
case SIOCSIFFLAGS :
case SIOCSIFMETRIC :
case SIOCSIFMTU :
case SIOCSIFSLAVE :
case SIOCSIFHWADDR :
case SIOCSIFTXQLEN :
case SIOCSIFMAP :
tprints ( " , " ) ;
if ( umove_or_printaddr ( tcp , arg , & ifr ) )
break ;
tprints ( " {ifr_name= " ) ;
print_ifname ( ifr . ifr_name ) ;
tprints ( " , " ) ;
if ( code = = SIOCSIFNAME ) {
tprints ( " ifr_newname= " ) ;
print_ifname ( ifr . ifr_newname ) ;
} else {
print_ifreq ( tcp , code , arg , & ifr ) ;
}
tprints ( " } " ) ;
break ;
2004-07-12 11:13:06 +04:00
case SIOCGIFNAME :
case SIOCGIFINDEX :
2005-02-02 Roland McGrath <roland@redhat.com>
* sock.c (iffflags): New variable, table of IFF_* values.
(print_addr): New function.
(sock_ioctl): Handle SIOCGIFADDR, SIOCGIFDSTADDR, SIOCGIFBRDADDR,
SIOCGIFNETMASK, SIOCGIFFLAGS, SIOCGIFMETRIC, SIOCGIFMTU, SIOCGIFSLAVE,
SIOCGIFHWADDR. Use print_addr for SIOCGIFCONF, SIOCGIFNAME, and
SIOCGIFINDEX, and fix their output.
From Ulrich Drepper <drepper@redhat.com>.
Fixes RH#138223.
2005-02-02 23:25:17 +03:00
case SIOCGIFADDR :
case SIOCGIFDSTADDR :
case SIOCGIFBRDADDR :
case SIOCGIFNETMASK :
case SIOCGIFFLAGS :
case SIOCGIFMETRIC :
case SIOCGIFMTU :
case SIOCGIFSLAVE :
case SIOCGIFHWADDR :
2007-03-21 16:52:14 +03:00
case SIOCGIFTXQLEN :
2007-03-21 16:57:50 +03:00
case SIOCGIFMAP :
2015-07-04 14:01:08 +03:00
if ( entering ( tcp ) ) {
tprints ( " , " ) ;
if ( umove_or_printaddr ( tcp , arg , & ifr ) )
break ;
if ( SIOCGIFNAME = = code ) {
tprintf ( " {ifr_index=%d " , ifr . ifr_ifindex ) ;
2014-10-21 16:34:08 +04:00
} else {
2015-07-04 14:01:08 +03:00
tprints ( " {ifr_name= " ) ;
2015-01-24 23:58:23 +03:00
print_ifname ( ifr . ifr_name ) ;
2014-10-21 16:34:08 +04:00
}
2015-07-04 14:01:08 +03:00
return 1 ;
2014-10-21 16:34:08 +04:00
} else {
2015-07-04 14:01:08 +03:00
if ( syserror ( tcp ) ) {
2011-09-01 12:00:28 +04:00
tprints ( " } " ) ;
2005-02-02 Roland McGrath <roland@redhat.com>
* sock.c (iffflags): New variable, table of IFF_* values.
(print_addr): New function.
(sock_ioctl): Handle SIOCGIFADDR, SIOCGIFDSTADDR, SIOCGIFBRDADDR,
SIOCGIFNETMASK, SIOCGIFFLAGS, SIOCGIFMETRIC, SIOCGIFMTU, SIOCGIFSLAVE,
SIOCGIFHWADDR. Use print_addr for SIOCGIFCONF, SIOCGIFNAME, and
SIOCGIFINDEX, and fix their output.
From Ulrich Drepper <drepper@redhat.com>.
Fixes RH#138223.
2005-02-02 23:25:17 +03:00
break ;
}
2009-11-03 17:38:44 +03:00
2015-07-04 14:01:08 +03:00
tprints ( " , " ) ;
if ( umove ( tcp , arg , & ifr ) < 0 ) {
tprints ( " ???} " ) ;
break ;
2009-11-03 17:38:44 +03:00
}
2015-07-04 14:01:08 +03:00
if ( SIOCGIFNAME = = code ) {
tprints ( " ifr_name= " ) ;
print_ifname ( ifr . ifr_name ) ;
} else {
print_ifreq ( tcp , code , arg , & ifr ) ;
2004-07-12 11:13:06 +04:00
}
2011-09-01 12:00:28 +04:00
tprints ( " } " ) ;
2015-07-04 14:01:08 +03:00
break ;
2004-07-12 11:13:06 +04:00
}
2015-07-04 14:01:08 +03:00
1999-02-19 03:21:36 +03:00
default :
2015-07-04 14:01:08 +03:00
return RVAL_DECODED ;
1999-02-19 03:21:36 +03:00
}
2015-07-04 14:01:08 +03:00
return RVAL_DECODED | 1 ;
1999-02-19 03:21:36 +03:00
}