]> granicus.if.org Git - strace/blobdiff - net.c
Remove linux/ptp_clock.h
[strace] / net.c
diff --git a/net.c b/net.c
index ae8e7494daf03198b2998ac7a6a5e7f9b3bf5731..498a6384a041b51464caab80209d265d2b7338b7 100644 (file)
--- a/net.c
+++ b/net.c
@@ -390,8 +390,9 @@ SYS_FUNC(socketpair)
 #include "xlat/getsockipv6options.h"
 #include "xlat/setsockipv6options.h"
 #include "xlat/sockipxoptions.h"
-#include "xlat/sockrawoptions.h"
+#include "xlat/socknetlinkoptions.h"
 #include "xlat/sockpacketoptions.h"
+#include "xlat/sockrawoptions.h"
 #include "xlat/socksctpoptions.h"
 #include "xlat/socktcpoptions.h"
 
@@ -431,6 +432,9 @@ print_sockopt_fd_level_name(struct tcb *tcp, int fd, unsigned int level,
        case SOL_RAW:
                printxval(sockrawoptions, name, "RAW_???");
                break;
+       case SOL_NETLINK:
+               printxval(socknetlinkoptions, name, "NETLINK_???");
+               break;
 
                /* Other SOL_* protocol levels still need work. */
 
@@ -443,19 +447,17 @@ print_sockopt_fd_level_name(struct tcb *tcp, int fd, unsigned int level,
 
 static void
 print_set_linger(struct tcb *const tcp, const kernel_ulong_t addr,
-                const unsigned int len)
+                const int len)
 {
        struct linger linger;
 
-       if (len < sizeof(linger) ||
-           umove(tcp, addr, &linger) < 0) {
+       if (len < (int) sizeof(linger)) {
                printaddr(addr);
-               return;
+       } else if (!umove_or_printaddr(tcp, addr, &linger)) {
+               PRINT_FIELD_D("{", linger, l_onoff);
+               PRINT_FIELD_D(", ", linger, l_linger);
+               tprints("}");
        }
-
-       PRINT_FIELD_D("{", linger, l_onoff);
-       PRINT_FIELD_D(", ", linger, l_linger);
-       tprints("}");
 }
 
 static void
@@ -525,9 +527,9 @@ print_tpacket_stats(struct tcb *const tcp, const kernel_ulong_t addr,
            umove(tcp, addr, &stats) < 0) {
                printaddr(addr);
        } else {
-               tprintf("{packets=%u, drops=%u}",
-                       stats.tp_packets,
-                       stats.tp_drops);
+               PRINT_FIELD_U("{", stats, tp_packets);
+               PRINT_FIELD_U("{", stats, tp_drops);
+               tprints("}");
        }
 }
 #endif /* PACKET_STATISTICS */
@@ -554,27 +556,35 @@ print_icmp_filter(struct tcb *const tcp, const kernel_ulong_t addr, int len)
        tprints(")");
 }
 
+static bool
+print_uint32(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
+{
+       tprintf("%u", *(uint32_t *) elem_buf);
+
+       return true;
+}
+
 static void
 print_getsockopt(struct tcb *const tcp, const unsigned int level,
                 const unsigned int name, const kernel_ulong_t addr,
-                const int len)
+                const int ulen, const int rlen)
 {
        if (addr && verbose(tcp))
        switch (level) {
        case SOL_SOCKET:
                switch (name) {
                case SO_LINGER:
-                       print_get_linger(tcp, addr, len);
+                       print_get_linger(tcp, addr, rlen);
                        return;
 #ifdef SO_PEERCRED
                case SO_PEERCRED:
-                       print_ucred(tcp, addr, len);
+                       print_ucred(tcp, addr, rlen);
                        return;
 #endif
 #ifdef SO_ATTACH_FILTER
                case SO_ATTACH_FILTER:
-                       if (len && (unsigned short) len == (unsigned int) len)
-                               print_sock_fprog(tcp, addr, len);
+                       if (rlen && (unsigned short) rlen == (unsigned int) rlen)
+                               print_sock_fprog(tcp, addr, rlen);
                        else
                                printaddr(addr);
                        return;
@@ -586,7 +596,7 @@ print_getsockopt(struct tcb *const tcp, const unsigned int level,
                switch (name) {
 #ifdef PACKET_STATISTICS
                case PACKET_STATISTICS:
-                       print_tpacket_stats(tcp, addr, len);
+                       print_tpacket_stats(tcp, addr, rlen);
                        return;
 #endif
                }
@@ -595,19 +605,44 @@ print_getsockopt(struct tcb *const tcp, const unsigned int level,
        case SOL_RAW:
                switch (name) {
                case ICMP_FILTER:
-                       print_icmp_filter(tcp, addr, len);
+                       print_icmp_filter(tcp, addr, rlen);
                        return;
                }
                break;
+
+       case SOL_NETLINK:
+               if (ulen < 0 || rlen < 0) {
+                       /*
+                        * As the kernel neither accepts nor returns a negative
+                        * length, in case of successful getsockopt syscall
+                        * invocation these negative values must have come
+                        * from userspace.
+                        */
+                       printaddr(addr);
+                       return;
+               }
+               switch (name) {
+               case NETLINK_LIST_MEMBERSHIPS: {
+                       uint32_t buf;
+                       print_array(tcp, addr, MIN(ulen, rlen) / sizeof(buf),
+                                   &buf, sizeof(buf),
+                                   umoven_or_printaddr, print_uint32, 0);
+                       break;
+                       }
+               default:
+                       printnum_int(tcp, addr, "%d");
+                       break;
+               }
+               return;
        }
 
        /* default arg printing */
 
        if (verbose(tcp)) {
-               if (len == sizeof(int)) {
+               if (rlen == sizeof(int)) {
                        printnum_int(tcp, addr, "%d");
                } else {
-                       printstrn(tcp, addr, len);
+                       printstrn(tcp, addr, rlen);
                }
        } else {
                printaddr(addr);
@@ -640,7 +675,7 @@ SYS_FUNC(getsockopt)
                        tprintf(", [%d]", ulen);
                } else {
                        print_getsockopt(tcp, tcp->u_arg[1], tcp->u_arg[2],
-                                        tcp->u_arg[3], rlen);
+                                        tcp->u_arg[3], ulen, rlen);
                        if (ulen != rlen)
                                tprintf(", [%d->%d]", ulen, rlen);
                        else
@@ -653,64 +688,36 @@ SYS_FUNC(getsockopt)
 #ifdef IP_ADD_MEMBERSHIP
 static void
 print_mreq(struct tcb *const tcp, const kernel_ulong_t addr,
-          const unsigned int len)
+          const int len)
 {
        struct ip_mreq mreq;
 
-       if (len < sizeof(mreq)) {
-               printstrn(tcp, addr, len);
-               return;
+       if (len < (int) sizeof(mreq)) {
+               printaddr(addr);
+       } else if (!umove_or_printaddr(tcp, addr, &mreq)) {
+               PRINT_FIELD_INET4_ADDR("{", mreq, imr_multiaddr);
+               PRINT_FIELD_INET4_ADDR(", ", mreq, imr_interface);
+               tprints("}");
        }
-       if (umove_or_printaddr(tcp, addr, &mreq))
-               return;
-
-       tprintf("{imr_multiaddr=inet_addr(\"%s\")",
-               inet_ntoa(mreq.imr_multiaddr));
-       tprintf(", imr_interface=inet_addr(\"%s\")}",
-               inet_ntoa(mreq.imr_interface));
 }
 #endif /* IP_ADD_MEMBERSHIP */
 
 #ifdef IPV6_ADD_MEMBERSHIP
 static void
 print_mreq6(struct tcb *const tcp, const kernel_ulong_t addr,
-           const unsigned int len)
+           const int len)
 {
        struct ipv6_mreq mreq;
 
-       if (len < sizeof(mreq)) {
-               printstrn(tcp, addr, len);
-               return;
-       }
-       if (umove_or_printaddr(tcp, addr, &mreq))
-               return;
-
-       PRINT_FIELD_INET_ADDR("{", mreq, ipv6mr_multiaddr, AF_INET6);
-
-       tprints(", ipv6mr_interface=");
-       print_ifindex(mreq.ipv6mr_interface);
-       tprints("}");
-}
-#endif /* IPV6_ADD_MEMBERSHIP */
-
-#ifdef MCAST_JOIN_GROUP
-static void
-print_group_req(struct tcb *const tcp, const kernel_ulong_t addr, const int len)
-{
-       struct group_req greq;
-
-       if (len != sizeof(greq) ||
-           umove(tcp, addr, &greq) < 0) {
+       if (len < (int) sizeof(mreq)) {
                printaddr(addr);
-               return;
+       } else if (!umove_or_printaddr(tcp, addr, &mreq)) {
+               PRINT_FIELD_INET_ADDR("{", mreq, ipv6mr_multiaddr, AF_INET6);
+               PRINT_FIELD_IFINDEX(", ", mreq, ipv6mr_interface);
+               tprints("}");
        }
-
-       tprintf("{gr_interface=%u, gr_group=", greq.gr_interface);
-       print_sockaddr(tcp, &greq.gr_group, sizeof(greq.gr_group));
-       tprints("}");
-
 }
-#endif /* MCAST_JOIN_GROUP */
+#endif /* IPV6_ADD_MEMBERSHIP */
 
 #ifdef PACKET_RX_RING
 static void
@@ -722,12 +729,11 @@ print_tpacket_req(struct tcb *const tcp, const kernel_ulong_t addr, const int le
            umove(tcp, addr, &req) < 0) {
                printaddr(addr);
        } else {
-               tprintf("{block_size=%u, block_nr=%u, "
-                       "frame_size=%u, frame_nr=%u}",
-                       req.tp_block_size,
-                       req.tp_block_nr,
-                       req.tp_frame_size,
-                       req.tp_frame_nr);
+               PRINT_FIELD_U("{", req, tp_block_size);
+               PRINT_FIELD_U(", ", req, tp_block_nr);
+               PRINT_FIELD_U(", ", req, tp_frame_size);
+               PRINT_FIELD_U(", ", req, tp_frame_nr);
+               tprints("}");
        }
 }
 #endif /* PACKET_RX_RING */
@@ -746,9 +752,11 @@ print_packet_mreq(struct tcb *const tcp, const kernel_ulong_t addr, const int le
        } else {
                unsigned int i;
 
-               tprintf("{mr_ifindex=%u, mr_type=", mreq.mr_ifindex);
-               printxval(packet_mreq_type, mreq.mr_type, "PACKET_MR_???");
-               tprintf(", mr_alen=%u, mr_address=", mreq.mr_alen);
+               PRINT_FIELD_IFINDEX("{", mreq, mr_ifindex);
+               PRINT_FIELD_XVAL(", ", mreq, mr_type, packet_mreq_type,
+                                "PACKET_MR_???");
+               PRINT_FIELD_U(", ", mreq, mr_alen);
+               tprints(", mr_address=");
                if (mreq.mr_alen > ARRAY_SIZE(mreq.mr_address))
                        mreq.mr_alen = ARRAY_SIZE(mreq.mr_address);
                for (i = 0; i < mreq.mr_alen; ++i)
@@ -815,6 +823,12 @@ print_setsockopt(struct tcb *const tcp, const unsigned int level,
                        print_mreq6(tcp, addr, len);
                        return;
 #endif /* IPV6_ADD_MEMBERSHIP */
+#ifdef MCAST_JOIN_GROUP
+               case MCAST_JOIN_GROUP:
+               case MCAST_LEAVE_GROUP:
+                       print_group_req(tcp, addr, len);
+                       return;
+#endif /* MCAST_JOIN_GROUP */
                }
                break;
 
@@ -844,6 +858,13 @@ print_setsockopt(struct tcb *const tcp, const unsigned int level,
                        return;
                }
                break;
+
+       case SOL_NETLINK:
+               if (len < (int) sizeof(int))
+                       printaddr(addr);
+               else
+                       printnum_int(tcp, addr, "%d");
+               return;
        }
 
        /* default arg printing */