(root)/
strace-6.5/
src/
sock.c
       1  /*
       2   * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
       3   * Copyright (c) 1996-2023 The strace developers.
       4   * All rights reserved.
       5   *
       6   * SPDX-License-Identifier: LGPL-2.1-or-later
       7   */
       8  
       9  #include "defs.h"
      10  
      11  #include DEF_MPERS_TYPE(struct_ifconf)
      12  #include DEF_MPERS_TYPE(struct_ifreq)
      13  
      14  #include <sys/socket.h>
      15  #include <net/if.h>
      16  
      17  typedef struct ifconf struct_ifconf;
      18  typedef struct ifreq struct_ifreq;
      19  
      20  #include MPERS_DEFS
      21  
      22  #include <linux/ioctl.h>
      23  #include <linux/sockios.h>
      24  #include <arpa/inet.h>
      25  
      26  #include "xlat/iffflags.h"
      27  
      28  #define XLAT_MACROS_ONLY
      29  #include "xlat/arp_hardware_types.h"
      30  #undef XLAT_MACROS_ONLY
      31  
      32  static void
      33  print_ifr_hwaddr(const typeof_field(struct_ifreq, ifr_hwaddr) *const p)
      34  {
      35  	tprint_struct_begin();
      36  	PRINT_FIELD_XVAL(*p, sa_family, arp_hardware_types, "ARPHRD_???");
      37  	tprint_struct_next();
      38  	PRINT_FIELD_HWADDR_SZ(*p, sa_data, sizeof(p->sa_data), p->sa_family);
      39  	tprint_struct_end();
      40  }
      41  
      42  static void
      43  print_ifr_map(const typeof_field(struct_ifreq, ifr_map) *const p)
      44  {
      45  	tprint_struct_begin();
      46  	PRINT_FIELD_X(*p, mem_start);
      47  	tprint_struct_next();
      48  	PRINT_FIELD_X(*p, mem_end);
      49  	tprint_struct_next();
      50  	PRINT_FIELD_X(*p, base_addr);
      51  	tprint_struct_next();
      52  	PRINT_FIELD_X(*p, irq);
      53  	tprint_struct_next();
      54  	PRINT_FIELD_X(*p, dma);
      55  	tprint_struct_next();
      56  	PRINT_FIELD_X(*p, port);
      57  	tprint_struct_end();
      58  }
      59  
      60  static void
      61  print_ifreq(struct tcb *const tcp, const unsigned int code,
      62  	    const kernel_ulong_t arg, const struct_ifreq *const ifr)
      63  {
      64  	switch (code) {
      65  	case SIOCSIFADDR:
      66  	case SIOCGIFADDR:
      67  		PRINT_FIELD_SOCKADDR(*ifr, ifr_addr, tcp);
      68  		break;
      69  	case SIOCSIFDSTADDR:
      70  	case SIOCGIFDSTADDR:
      71  		PRINT_FIELD_SOCKADDR(*ifr, ifr_dstaddr, tcp);
      72  		break;
      73  	case SIOCSIFBRDADDR:
      74  	case SIOCGIFBRDADDR:
      75  		PRINT_FIELD_SOCKADDR(*ifr, ifr_broadaddr, tcp);
      76  		break;
      77  	case SIOCSIFNETMASK:
      78  	case SIOCGIFNETMASK:
      79  		PRINT_FIELD_SOCKADDR(*ifr, ifr_netmask, tcp);
      80  		break;
      81  	case SIOCADDMULTI:
      82  	case SIOCDELMULTI:
      83  	case SIOCGIFHWADDR:
      84  	case SIOCSIFHWADDR:
      85  	case SIOCSIFHWBROADCAST:
      86  		PRINT_FIELD_OBJ_PTR(*ifr, ifr_hwaddr, print_ifr_hwaddr);
      87  		break;
      88  	case SIOCSIFFLAGS:
      89  	case SIOCGIFFLAGS:
      90  		PRINT_FIELD_FLAGS(*ifr, ifr_flags, iffflags, "IFF_???");
      91  		break;
      92  	case SIOCGIFINDEX:
      93  		PRINT_FIELD_D(*ifr, ifr_ifindex);
      94  		break;
      95  	case SIOCSIFMETRIC:
      96  	case SIOCGIFMETRIC:
      97  		PRINT_FIELD_D(*ifr, ifr_metric);
      98  		break;
      99  	case SIOCSIFMTU:
     100  	case SIOCGIFMTU:
     101  		PRINT_FIELD_D(*ifr, ifr_mtu);
     102  		break;
     103  	case SIOCSIFSLAVE:
     104  	case SIOCGIFSLAVE:
     105  		PRINT_FIELD_CSTRING(*ifr, ifr_slave);
     106  		break;
     107  	case SIOCSIFNAME:
     108  		PRINT_FIELD_CSTRING(*ifr, ifr_newname);
     109  		break;
     110  	case SIOCGIFNAME:
     111  		PRINT_FIELD_CSTRING(*ifr, ifr_name);
     112  		break;
     113  	case SIOCSIFTXQLEN:
     114  	case SIOCGIFTXQLEN:
     115  		PRINT_FIELD_D(*ifr, ifr_qlen);
     116  		break;
     117  	case SIOCSIFMAP:
     118  	case SIOCGIFMAP:
     119  		PRINT_FIELD_OBJ_PTR(*ifr, ifr_map, print_ifr_map);
     120  		break;
     121  	}
     122  }
     123  
     124  static unsigned int
     125  print_ifc_len(int len)
     126  {
     127  	PRINT_VAL_D(len);
     128  
     129  	const unsigned int n = (unsigned int) len / sizeof(struct_ifreq);
     130  	if (len > 0 && n * sizeof(struct_ifreq) == (unsigned int) len) {
     131  		tprint_comment_begin();
     132  		PRINT_VAL_U(n);
     133  		tprints_string(" * sizeof(struct ifreq)");
     134  		tprint_comment_end();
     135  	}
     136  
     137  	return n;
     138  }
     139  
     140  static bool
     141  print_ifconf_ifreq(struct tcb *tcp, void *elem_buf, size_t elem_size,
     142  		   void *dummy)
     143  {
     144  	struct_ifreq *ifr = elem_buf;
     145  
     146  	tprint_struct_begin();
     147  	PRINT_FIELD_CSTRING(*ifr, ifr_name);
     148  	tprint_struct_next();
     149  	PRINT_FIELD_SOCKADDR(*ifr, ifr_addr, tcp);
     150  	tprint_struct_end();
     151  
     152  	return true;
     153  }
     154  
     155  /*
     156   * There are two different modes of operation:
     157   *
     158   * - Get buffer size.  In this case, the callee sets ifc_buf to NULL,
     159   *   and the kernel returns the buffer size in ifc_len.
     160   * - Get actual data.  In this case, the callee specifies the buffer address
     161   *   in ifc_buf and its size in ifc_len.  The kernel fills the buffer with
     162   *   the data, and its amount is returned in ifc_len.
     163   *
     164   * Note that, technically, the whole struct ifconf is overwritten,
     165   * so ifc_buf could be different on exit, but current ioctl handler
     166   * implementation does not touch it.
     167   */
     168  static int
     169  decode_ifconf(struct tcb *const tcp, const kernel_ulong_t addr)
     170  {
     171  	struct_ifconf *entering_ifc = NULL;
     172  	struct_ifconf *ifc =
     173  		entering(tcp) ? malloc(sizeof(*ifc)) : alloca(sizeof(*ifc));
     174  
     175  	if (exiting(tcp)) {
     176  		entering_ifc = get_tcb_priv_data(tcp);
     177  
     178  		if (!entering_ifc) {
     179  			error_func_msg("where is my ifconf?");
     180  			return 0;
     181  		}
     182  	}
     183  
     184  	if (!ifc || umove(tcp, addr, ifc) < 0) {
     185  		if (entering(tcp)) {
     186  			free(ifc);
     187  
     188  			tprint_arg_next();
     189  			printaddr(addr);
     190  		} else {
     191  			/*
     192  			 * We failed to fetch the structure on exiting syscall,
     193  			 * print whatever was fetched on entering syscall.
     194  			 */
     195  			if (!entering_ifc->ifc_buf)
     196  				print_ifc_len(entering_ifc->ifc_len);
     197  
     198  			tprint_struct_next();
     199  			PRINT_FIELD_PTR(*entering_ifc, ifc_buf);
     200  
     201  			tprint_struct_end();
     202  		}
     203  
     204  		return RVAL_IOCTL_DECODED;
     205  	}
     206  
     207  	if (entering(tcp)) {
     208  		tprint_arg_next();
     209  		tprint_struct_begin();
     210  		tprints_field_name("ifc_len");
     211  		if (ifc->ifc_buf)
     212  			print_ifc_len(ifc->ifc_len);
     213  
     214  		set_tcb_priv_data(tcp, ifc, free);
     215  
     216  		return 0;
     217  	}
     218  
     219  	/* exiting */
     220  
     221  	if (entering_ifc->ifc_buf && (entering_ifc->ifc_len != ifc->ifc_len))
     222  		tprint_value_changed();
     223  	if (!entering_ifc->ifc_buf || (entering_ifc->ifc_len != ifc->ifc_len))
     224  		print_ifc_len(ifc->ifc_len);
     225  
     226  	if (!entering_ifc->ifc_buf || syserror(tcp)) {
     227  		tprint_struct_next();
     228  		PRINT_FIELD_PTR(*entering_ifc, ifc_buf);
     229  		if (entering_ifc->ifc_buf != ifc->ifc_buf) {
     230  			tprint_value_changed();
     231  			printaddr(ptr_to_kulong(ifc->ifc_buf));
     232  		}
     233  	} else {
     234  		struct_ifreq ifr;
     235  
     236  		tprint_struct_next();
     237  		tprints_field_name("ifc_buf");
     238  		print_array(tcp, ptr_to_kulong(ifc->ifc_buf),
     239  			    ifc->ifc_len / sizeof(struct_ifreq),
     240  			    &ifr, sizeof(ifr),
     241  			    tfetch_mem, print_ifconf_ifreq, NULL);
     242  	}
     243  
     244  	tprint_struct_end();
     245  
     246  	return RVAL_IOCTL_DECODED;
     247  }
     248  
     249  MPERS_PRINTER_DECL(int, sock_ioctl,
     250  		   struct tcb *tcp, const unsigned int code,
     251  		   const kernel_ulong_t arg)
     252  {
     253  	struct_ifreq ifr;
     254  
     255  	switch (code) {
     256  	case SIOCGIFCONF:
     257  		return decode_ifconf(tcp, arg);
     258  
     259  	case SIOCBRADDBR:
     260  	case SIOCBRDELBR:
     261  		tprint_arg_next();
     262  		printstr_ex(tcp, arg, sizeof(ifr.ifr_name), QUOTE_0_TERMINATED);
     263  		break;
     264  
     265  	case FIOGETOWN:
     266  	case SIOCATMARK:
     267  	case SIOCGIFENCAP:
     268  	case SIOCGPGRP:
     269  #ifdef SIOCOUTQNSD
     270  	case SIOCOUTQNSD:
     271  #endif
     272  		if (entering(tcp))
     273  			return 0;
     274  		ATTRIBUTE_FALLTHROUGH;
     275  
     276  	case FIOSETOWN:
     277  	case SIOCSIFENCAP:
     278  	case SIOCSPGRP:
     279  		tprint_arg_next();
     280  		printnum_int(tcp, arg, "%d");
     281  		break;
     282  
     283  	case SIOCBRADDIF:
     284  	case SIOCBRDELIF:
     285  		tprint_arg_next();
     286  		if (!umove_or_printaddr(tcp, arg, &ifr)) {
     287  			tprint_struct_begin();
     288  			PRINT_FIELD_IFINDEX(ifr, ifr_ifindex);
     289  			tprint_struct_end();
     290  		}
     291  		break;
     292  
     293  	case SIOCADDMULTI:
     294  	case SIOCDELMULTI:
     295  	case SIOCSIFADDR:
     296  	case SIOCSIFBRDADDR:
     297  	case SIOCSIFDSTADDR:
     298  	case SIOCSIFFLAGS:
     299  	case SIOCSIFHWADDR:
     300  	case SIOCSIFHWBROADCAST:
     301  	case SIOCSIFMAP:
     302  	case SIOCSIFMETRIC:
     303  	case SIOCSIFMTU:
     304  	case SIOCSIFNAME:
     305  	case SIOCSIFNETMASK:
     306  	case SIOCSIFSLAVE:
     307  	case SIOCSIFTXQLEN:
     308  		tprint_arg_next();
     309  		if (umove_or_printaddr(tcp, arg, &ifr))
     310  			break;
     311  
     312  		tprint_struct_begin();
     313  		PRINT_FIELD_CSTRING(ifr, ifr_name);
     314  		tprint_arg_next();
     315  		print_ifreq(tcp, code, arg, &ifr);
     316  		tprint_struct_end();
     317  		break;
     318  
     319  	case SIOCGIFADDR:
     320  	case SIOCGIFBRDADDR:
     321  	case SIOCGIFDSTADDR:
     322  	case SIOCGIFFLAGS:
     323  	case SIOCGIFHWADDR:
     324  	case SIOCGIFINDEX:
     325  	case SIOCGIFMAP:
     326  	case SIOCGIFMETRIC:
     327  	case SIOCGIFMTU:
     328  	case SIOCGIFNAME:
     329  	case SIOCGIFNETMASK:
     330  	case SIOCGIFSLAVE:
     331  	case SIOCGIFTXQLEN:
     332  		if (entering(tcp)) {
     333  			tprint_arg_next();
     334  			if (umove_or_printaddr(tcp, arg, &ifr))
     335  				break;
     336  
     337  			if (SIOCGIFNAME == code) {
     338  				tprint_struct_begin();
     339  				PRINT_FIELD_D(ifr, ifr_ifindex);
     340  			} else {
     341  				tprint_struct_begin();
     342  				PRINT_FIELD_CSTRING(ifr, ifr_name);
     343  			}
     344  			return 0;
     345  		} else {
     346  			if (!syserror(tcp) && !umove(tcp, arg, &ifr)) {
     347  				tprint_struct_next();
     348  				print_ifreq(tcp, code, arg, &ifr);
     349  			}
     350  			tprint_struct_end();
     351  			break;
     352  		}
     353  
     354  	case SIOCADDDLCI:
     355  	case SIOCADDRT:
     356  	case SIOCBONDCHANGEACTIVE:
     357  	case SIOCBONDENSLAVE:
     358  	case SIOCBONDINFOQUERY:
     359  	case SIOCBONDRELEASE:
     360  	case SIOCBONDSETHWADDR:
     361  	case SIOCBONDSLAVEINFOQUERY:
     362  	case SIOCDARP:
     363  	case SIOCDELDLCI:
     364  	case SIOCDELRT:
     365  	case SIOCDIFADDR:
     366  	case SIOCDRARP:
     367  	case SIOCETHTOOL:
     368  	case SIOCGARP:
     369  #ifdef SIOCGHWTSTAMP
     370  	case SIOCGHWTSTAMP:
     371  #endif
     372  	case SIOCGIFBR:
     373  	case SIOCGIFCOUNT:
     374  	case SIOCGIFMEM:
     375  	case SIOCGIFPFLAGS:
     376  	case SIOCGIFVLAN:
     377  	case SIOCGMIIPHY:
     378  	case SIOCGMIIREG:
     379  	case SIOCGRARP:
     380  #ifdef SIOCGSKNS
     381  	case SIOCGSKNS:
     382  #endif
     383  #ifdef SIOCGSTAMP_OLD
     384  	case SIOCGSTAMP_OLD:
     385  #endif
     386  #ifdef SIOCGSTAMP_NEW
     387  	case SIOCGSTAMP_NEW:
     388  #endif
     389  #ifdef SIOCGSTAMPNS_OLD
     390  	case SIOCGSTAMPNS_OLD:
     391  #endif
     392  #ifdef SIOCGSTAMPNS_NEW
     393  	case SIOCGSTAMPNS_NEW:
     394  #endif
     395  	case SIOCRTMSG:
     396  	case SIOCSARP:
     397  #ifdef SIOCSHWTSTAMP
     398  	case SIOCSHWTSTAMP:
     399  #endif
     400  	case SIOCSIFBR:
     401  	case SIOCSIFLINK:
     402  	case SIOCSIFMEM:
     403  	case SIOCSIFPFLAGS:
     404  	case SIOCSIFVLAN:
     405  	case SIOCSMIIREG:
     406  	case SIOCSRARP:
     407  	case SIOCWANDEV:
     408  		tprint_arg_next();
     409  		printaddr(arg);
     410  		break;
     411  
     412  	default:
     413  		return RVAL_DECODED;
     414  	}
     415  
     416  	return RVAL_IOCTL_DECODED;
     417  }