]> granicus.if.org Git - strace/blobdiff - sock.c
tests: add a test for -yy option
[strace] / sock.c
diff --git a/sock.c b/sock.c
index 7d1f244a59908636f89aa2a90e58d2c4fc6954ac..dca9bfd4713a45857c1391e011bc90d1bdfefaf4 100644 (file)
--- a/sock.c
+++ b/sock.c
  * 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.
- *
- *     $Id$
  */
 
 #include "defs.h"
-
-#ifdef LINUX
 #include <sys/socket.h>
-#else
-#include <sys/sockio.h>
+#include <linux/sockios.h>
+#include <arpa/inet.h>
+#if defined(ALPHA) || defined(SH) || defined(SH64)
+# if defined(HAVE_SYS_IOCTL_H)
+#  include <sys/ioctl.h>
+# elif defined(HAVE_IOCTLS_H)
+#  include <ioctls.h>
+# endif
 #endif
+#include <net/if.h>
 
-#if defined (ALPHA) || defined(SH) || defined(SH64)
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#elif defined(HAVE_IOCTLS_H)
-#include <ioctls.h>
-#endif
-#endif
+#include "xlat/iffflags.h"
+
+static void
+print_addr(struct tcb *tcp, long addr, struct ifreq *ifr)
+{
+       if (ifr->ifr_addr.sa_family == AF_INET) {
+               struct sockaddr_in *sinp;
+               sinp = (struct sockaddr_in *) &ifr->ifr_addr;
+               tprintf("inet_addr(\"%s\")", inet_ntoa(sinp->sin_addr));
+       } else
+               printstr(tcp, addr, sizeof(ifr->ifr_addr.sa_data));
+}
 
 int
-sock_ioctl(tcp, code, arg)
-struct tcb *tcp;
-long code, arg;
+sock_ioctl(struct tcb *tcp, long code, long arg)
 {
-       if (entering(tcp))
+       struct ifreq ifr;
+       struct ifconf ifc;
+       const char *str = NULL;
+       unsigned char *bytes;
+
+       if (entering(tcp)) {
+               if (code == SIOCGIFCONF) {
+                       if (umove(tcp, tcp->u_arg[2], &ifc) >= 0
+                           && ifc.ifc_buf == NULL)
+                               tprintf(", {%d -> ", ifc.ifc_len);
+                       else
+                               tprints(", {");
+               }
                return 0;
+       }
 
        switch (code) {
 #ifdef SIOCSHIWAT
@@ -81,7 +100,171 @@ long code, arg;
 #endif
                printnum(tcp, arg, ", %#d");
                return 1;
+       case SIOCGIFNAME:
+       case SIOCSIFNAME:
+       case SIOCGIFINDEX:
+       case SIOCGIFADDR:
+       case SIOCSIFADDR:
+       case SIOCGIFDSTADDR:
+       case SIOCSIFDSTADDR:
+       case SIOCGIFBRDADDR:
+       case SIOCSIFBRDADDR:
+       case SIOCGIFNETMASK:
+       case SIOCSIFNETMASK:
+       case SIOCGIFFLAGS:
+       case SIOCSIFFLAGS:
+       case SIOCGIFMETRIC:
+       case SIOCSIFMETRIC:
+       case SIOCGIFMTU:
+       case SIOCSIFMTU:
+       case SIOCGIFSLAVE:
+       case SIOCSIFSLAVE:
+       case SIOCGIFHWADDR:
+       case SIOCSIFHWADDR:
+       case SIOCGIFTXQLEN:
+       case SIOCSIFTXQLEN:
+       case SIOCGIFMAP:
+       case SIOCSIFMAP:
+               if (umove(tcp, tcp->u_arg[2], &ifr) < 0)
+                       tprintf(", %#lx", tcp->u_arg[2]);
+               else if (syserror(tcp)) {
+                       if (code == SIOCGIFNAME || code == SIOCSIFNAME)
+                               tprintf(", {ifr_index=%d, ifr_name=???}", ifr.ifr_ifindex);
+                       else
+                               tprintf(", {ifr_name=\"%s\", ???}", ifr.ifr_name);
+               } else if (code == SIOCGIFNAME || code == SIOCSIFNAME)
+                       tprintf(", {ifr_index=%d, ifr_name=\"%s\"}",
+                               ifr.ifr_ifindex, ifr.ifr_name);
+               else {
+                       tprintf(", {ifr_name=\"%s\", ", ifr.ifr_name);
+                       switch (code) {
+                       case SIOCGIFINDEX:
+                               tprintf("ifr_index=%d", ifr.ifr_ifindex);
+                               break;
+                       case SIOCGIFADDR:
+                       case SIOCSIFADDR:
+                               str = "ifr_addr";
+                       case SIOCGIFDSTADDR:
+                       case SIOCSIFDSTADDR:
+                               if (!str)
+                                       str = "ifr_dstaddr";
+                       case SIOCGIFBRDADDR:
+                       case SIOCSIFBRDADDR:
+                               if (!str)
+                                       str = "ifr_broadaddr";
+                       case SIOCGIFNETMASK:
+                       case SIOCSIFNETMASK:
+                               if (!str)
+                                       str = "ifr_netmask";
+                               tprintf("%s={", str);
+                               printxval(addrfams,
+                                         ifr.ifr_addr.sa_family,
+                                         "AF_???");
+                               tprints(", ");
+                               print_addr(tcp, ((long) tcp->u_arg[2]
+                                                + offsetof(struct ifreq,
+                                                            ifr_addr.sa_data)),
+                                          &ifr);
+                               tprints("}");
+                               break;
+                       case SIOCGIFHWADDR:
+                       case SIOCSIFHWADDR:
+                               /* XXX Are there other hardware addresses
+                                  than 6-byte MACs?  */
+                               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 SIOCGIFFLAGS:
+                       case SIOCSIFFLAGS:
+                               tprints("ifr_flags=");
+                               printflags(iffflags, ifr.ifr_flags, "IFF_???");
+                               break;
+                       case SIOCGIFMETRIC:
+                       case SIOCSIFMETRIC:
+                               tprintf("ifr_metric=%d", ifr.ifr_metric);
+                               break;
+                       case SIOCGIFMTU:
+                       case SIOCSIFMTU:
+                               tprintf("ifr_mtu=%d", ifr.ifr_mtu);
+                               break;
+                       case SIOCGIFSLAVE:
+                       case SIOCSIFSLAVE:
+                               tprintf("ifr_slave=\"%s\"", ifr.ifr_slave);
+                               break;
+                       case SIOCGIFTXQLEN:
+                       case SIOCSIFTXQLEN:
+                               tprintf("ifr_qlen=%d", ifr.ifr_qlen);
+                               break;
+                       case SIOCGIFMAP:
+                       case SIOCSIFMAP:
+                               tprintf("ifr_map={mem_start=%#lx, "
+                                       "mem_end=%#lx, base_addr=%#x, "
+                                       "irq=%u, dma=%u, port=%u}",
+                                       ifr.ifr_map.mem_start,
+                                       ifr.ifr_map.mem_end,
+                                       (unsigned) ifr.ifr_map.base_addr,
+                                       (unsigned) ifr.ifr_map.irq,
+                                       (unsigned) ifr.ifr_map.dma,
+                                       (unsigned) ifr.ifr_map.port);
+                               break;
+                       }
+                       tprints("}");
+               }
+               return 1;
+       case SIOCGIFCONF:
+               if (umove(tcp, tcp->u_arg[2], &ifc) < 0) {
+                       tprints("???}");
+                       return 1;
+               }
+               tprintf("%d, ", ifc.ifc_len);
+               if (syserror(tcp)) {
+                       tprintf("%lx", (unsigned long) ifc.ifc_buf);
+               } else if (ifc.ifc_buf == NULL) {
+                       tprints("NULL");
+               } else {
+                       unsigned int i;
+                       unsigned int nifra = ifc.ifc_len / sizeof(struct ifreq);
+                       struct ifreq ifra[nifra];
+
+                       if (umoven(tcp, (unsigned long) ifc.ifc_buf,
+                               sizeof(ifra), (char *) ifra) < 0) {
+                               tprintf("%lx}", (unsigned long) ifc.ifc_buf);
+                               return 1;
+                       }
+                       tprints("{");
+                       for (i = 0; i < nifra; ++i ) {
+                               if (i > 0)
+                                       tprints(", ");
+                               tprintf("{\"%s\", {",
+                                       ifra[i].ifr_name);
+                               if (verbose(tcp)) {
+                                       printxval(addrfams,
+                                                 ifra[i].ifr_addr.sa_family,
+                                                 "AF_???");
+                                       tprints(", ");
+                                       print_addr(tcp, ((long) tcp->u_arg[2]
+                                                        + offsetof(struct ifreq,
+                                                                    ifr_addr.sa_data)
+                                                        + ((char *) &ifra[i]
+                                                           - (char *) &ifra[0])),
+                                                  &ifra[i]);
+                               } else
+                                       tprints("...");
+                               tprints("}}");
+                       }
+                       tprints("}");
+               }
+               tprints("}");
+               return 1;
        default:
                return 0;
        }
 }
+
+int
+sys_socketcall(struct tcb *tcp)
+{
+       return printargs(tcp);
+}