diff --git a/tapset/linux/aux_syscalls.stp b/tapset/linux/aux_syscalls.stp index 0f9c9e4..a278e0c 100644 --- a/tapset/linux/aux_syscalls.stp +++ b/tapset/linux/aux_syscalls.stp @@ -280,7 +280,7 @@ function _struct_compat_itimerval_u:string(uaddr:long) %} %{ -// Needed for function _struct_sockaddr_u. Unfortunately cannot be +// Needed for function _struct_sockaddr_u_impl. Unfortunately cannot be // inlined into the function since these header files define static // functions themselves. #include @@ -288,18 +288,75 @@ function _struct_compat_itimerval_u:string(uaddr:long) #include %} +%{ +// Enum for _struct_sockaddr_u_* functions. +typedef enum { + SA_PRETTY = 1, + SA_IP_ADDR = 2, + SA_TCP_PORT = 4, + SA_FAMILY = 8, + SA_IPV6_FLOWINFO = 16, + SA_IPV6_SCOPE_ID = 32, +} sa_dispatch; +%} + +function _struct_sockaddr_u_ip_addr:string(uaddr:long, len:long) +{ + return _struct_sockaddr_u_impl(uaddr, len, %{ SA_IP_ADDR %}); +} + +function _struct_sockaddr_u_tcp_port:string(uaddr:long, len:long) +{ + return _struct_sockaddr_u_impl(uaddr, len, %{ SA_TCP_PORT %}); +} + +function _struct_sockaddr_u_ip_addr_tcp_port:string(uaddr:long, len:long) +{ + return _struct_sockaddr_u_impl(uaddr, len, %{ SA_IP_ADDR | SA_TCP_PORT %}); +} + +function _struct_sockaddr_u_sa_family:string(uaddr:long, len:long) +{ + return _struct_sockaddr_u_impl(uaddr, len, %{ SA_FAMILY %}); +} + +function _struct_sockaddr_u_ipv6_flowinfo:string(uaddr:long, len:long) +{ + return _struct_sockaddr_u_impl(uaddr, len, %{ SA_IPV6_FLOWINFO %}); +} + +function _struct_sockaddr_u_ipv6_scope_id:string(uaddr:long, len:long) +{ + return _struct_sockaddr_u_impl(uaddr, len, %{ SA_IPV6_SCOPE_ID %}); +} + function _struct_sockaddr_u:string(uaddr:long, len:long) +{ + return _struct_sockaddr_u_impl(uaddr, len, %{ SA_PRETTY %}); +} + +function _struct_sockaddr_u_impl:string(uaddr:long, len:long, what:long) %{ /* pure */ #include #include #include #include + sa_dispatch what = (sa_dispatch)STAP_ARG_what; + char *ptr = (char *)(unsigned long)STAP_ARG_uaddr; char buf[128]; size_t len = STAP_ARG_len < 128 ? STAP_ARG_len : 128; struct sockaddr *sa = (struct sockaddr *)buf; +// Don't use this macro outside of if (what & ... ) statement! +// (n - 1) mean: cut of null char +#define RETVALUE_INC_SKIP() do {TMP_STAP_RETVALUE += (n); MAXLEN -= (n - 1);} while (0) + char *TMP_STAP_RETVALUE = (char *)(unsigned long)STAP_RETVALUE; + int MAXLEN = MAXSTRINGLEN; + size_t n; + + if (ptr == NULL) { strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); @@ -320,60 +377,163 @@ function _struct_sockaddr_u:string(uaddr:long, len:long) #define DADDR (&inet->daddr) #endif + // Use kernel builtin instead of picking up user space ntohs (function). #define _stp_ntohs be16_to_cpu if ((sa->sa_family == AF_INET) && (len == sizeof(struct sockaddr_in))) { struct sockaddr_in *sin = (struct sockaddr_in *)buf; -#ifndef NIPQUAD_FMT // kver >= 2.6.36 - snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{AF_INET, %pI4, %d}", - &sin->sin_addr, _stp_ntohs(sin->sin_port)); + + if (what & SA_PRETTY) + { +#ifndef NIPQUAD_FMT // kver >= 2.6.36 + snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{AF_INET, %pI4, %d}", + &sin->sin_addr, _stp_ntohs(sin->sin_port)); #else - snprintf(STAP_RETVALUE, MAXSTRINGLEN, - "{AF_INET, " NIPQUAD_FMT ", %d}", - NIPQUAD(sin->sin_addr), _stp_ntohs(sin->sin_port)); -#endif + snprintf(STAP_RETVALUE, MAXSTRINGLEN, + "{AF_INET, " NIPQUAD_FMT ", %d}", + NIPQUAD(sin->sin_addr), _stp_ntohs(sin->sin_port)); +#endif + return; + } + + if (what & SA_FAMILY) + { + n = strlcpy(TMP_STAP_RETVALUE, "AF_INET", MAXLEN); + RETVALUE_INC_SKIP(); + } + + if (what & SA_IP_ADDR) + { +#ifndef NIPQUAD_FMT // kver >= 2.6.36 + n = snprintf(TMP_STAP_RETVALUE, MAXLEN, "%pI4", &sin->sin_addr); +#else + n = snprintf(TMP_STAP_RETVALUE, MAXLEN, NIPQUAD_FMT, + NIPQUAD(sin->sin_addr)); +#endif + RETVALUE_INC_SKIP(); + } + + if (what & SA_TCP_PORT) + { + n = snprintf(TMP_STAP_RETVALUE, MAXLEN, "%d", + _stp_ntohs(sin->sin_port)); + RETVALUE_INC_SKIP(); + } } else if ((sa->sa_family == AF_UNIX) && (len == sizeof(struct sockaddr_un))) - { - struct sockaddr_un *sun = (struct sockaddr_un *)buf; - snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{AF_UNIX, %s}", - sun->sun_path); + { + struct sockaddr_un *sun = (struct sockaddr_un *)buf; + + if (what & SA_PRETTY) + { + snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{AF_UNIX, %s}", + sun->sun_path); + } else if (what & SA_FAMILY) + { + strlcpy(STAP_RETVALUE, "AF_UNIX", MAXSTRINGLEN); + } else + { + strlcpy(STAP_RETVALUE, "", MAXSTRINGLEN); + } } else if ((sa->sa_family == AF_NETLINK) && (len == sizeof(struct sockaddr_nl))) { struct sockaddr_nl *nl = (struct sockaddr_nl *)buf; - snprintf(STAP_RETVALUE, MAXSTRINGLEN, - "{AF_NETLINK, pid=%d, groups=%08x}", - nl->nl_pid, nl->nl_groups); + + if (what & SA_PRETTY) { + snprintf(STAP_RETVALUE, MAXSTRINGLEN, + "{AF_NETLINK, pid=%d, groups=%08x}", + nl->nl_pid, nl->nl_groups); + } else if (what & SA_FAMILY) + { + strlcpy(STAP_RETVALUE, "AF_NETLINK", MAXSTRINGLEN); + } else + { + strlcpy(STAP_RETVALUE, "", MAXSTRINGLEN); + } } else if ((sa->sa_family == AF_INET6) && (len == sizeof(struct sockaddr_in6))) { struct sockaddr_in6 *sin = (struct sockaddr_in6 *)buf; + + if (what & SA_PRETTY) + { #ifndef NIP6_FMT // kver >= 2.6.36 - snprintf(STAP_RETVALUE, MAXSTRINGLEN, - "{AF_INET6, %pI6, %d}", &sin->sin6_addr, - _stp_ntohs(sin->sin6_port)); + snprintf(STAP_RETVALUE, MAXSTRINGLEN, + "{AF_INET6, %pI6, %d}", &sin->sin6_addr, + _stp_ntohs(sin->sin6_port)); #else - snprintf(STAP_RETVALUE, MAXSTRINGLEN, - "{AF_INET6, " NIP6_FMT ", %d}", NIP6(sin->sin6_addr), - _stp_ntohs(sin->sin6_port)); + snprintf(STAP_RETVALUE, MAXSTRINGLEN, + "{AF_INET6, " NIP6_FMT ", %d}", NIP6(sin->sin6_addr), + _stp_ntohs(sin->sin6_port)); #endif + return; + } + + if (what & SA_FAMILY) + { + n = strlcpy(TMP_STAP_RETVALUE, "AF_INET6", MAXLEN); + RETVALUE_INC_SKIP(); + } + + if (what & SA_IP_ADDR) + { +#ifndef NIP6_FMT // kver >= 2.6.36 + n = snprintf(TMP_STAP_RETVALUE, MAXLEN, + "%pI6", &sin->sin6_addr); +#else + n = snprintf(TMP_STAP_RETVALUE, MAXLEN, + NIP6_FMT, NIP6(sin->sin6_addr)); +#endif + RETVALUE_INC_SKIP(); + } + + if (what & SA_TCP_PORT) + { + n = snprintf(TMP_STAP_RETVALUE, MAXLEN, + "%d", _stp_ntohs(sin->sin6_port)); + RETVALUE_INC_SKIP(); + } + + if (what & SA_IPV6_FLOWINFO) + { + n = snprintf(TMP_STAP_RETVALUE, MAXLEN, + "%d", sin->sin6_flowinfo); + RETVALUE_INC_SKIP(); + } + + if (what & SA_IPV6_SCOPE_ID) + { + n = snprintf(TMP_STAP_RETVALUE, MAXLEN, + "%d", sin->sin6_flowinfo); + RETVALUE_INC_SKIP(); + } } else if ((sa->sa_family == AF_PACKET) - && (len == sizeof(struct sockaddr_ll))) + && (len == sizeof(struct sockaddr_ll))) { struct sockaddr_ll *sll = (struct sockaddr_ll *)buf; - snprintf(STAP_RETVALUE, MAXSTRINGLEN, - "{AF_PACKET, proto=%d, ind=%d, hatype=%d, pkttype=%d, halen=%d, addr=0x%llx}", - (int)sll->sll_protocol, sll->sll_ifindex, - (int)sll->sll_hatype, (int)sll->sll_pkttype, - (int)sll->sll_halen, - (long long)(*(uint64_t *)sll->sll_addr)); + + if (what & SA_PRETTY) + { + snprintf(STAP_RETVALUE, MAXSTRINGLEN, + "{AF_PACKET, proto=%d, ind=%d, hatype=%d, pkttype=%d, halen=%d, addr=0x%llx}", + (int)sll->sll_protocol, sll->sll_ifindex, + (int)sll->sll_hatype, (int)sll->sll_pkttype, + (int)sll->sll_halen, + (long long)(*(uint64_t *)sll->sll_addr)); + } else if (what & SA_FAMILY) + { + strlcpy(STAP_RETVALUE, "AF_PACKET", MAXSTRINGLEN); + } else + { + strlcpy(STAP_RETVALUE, "", MAXSTRINGLEN); + } } else { @@ -389,6 +549,8 @@ function _struct_sockaddr_u:string(uaddr:long, len:long) "{unknown sockaddr with salen=%d}", (int)len); } } + +#undef RETVALUE_INC_SKIP %} function _struct_rlimit_u:string(uaddr:long) diff --git a/tapset/linux/nd_syscalls.stp b/tapset/linux/nd_syscalls.stp index f2daa01..9c813c6 100644 --- a/tapset/linux/nd_syscalls.stp +++ b/tapset/linux/nd_syscalls.stp @@ -247,6 +247,9 @@ probe nd_syscall.bind = kprobe.function("sys_bind") ? sockfd = int_arg(1) my_addr_uaddr = pointer_arg(2) addrlen = int_arg(3) +%( systemtap_v >= "2.5" %? + uaddr_ip = _struct_sockaddr_u_ip_addr(my_addr_uaddr, addrlen) +%) argstr = sprintf("%d, %s, %d", sockfd, _struct_sockaddr_u(my_addr_uaddr, addrlen), addrlen) } probe nd_syscall.bind.return = kprobe.function("sys_bind").return ? diff --git a/tapset/linux/syscalls.stp b/tapset/linux/syscalls.stp index 13fb92f..449ec20 100644 --- a/tapset/linux/syscalls.stp +++ b/tapset/linux/syscalls.stp @@ -199,6 +199,9 @@ probe syscall.bind = kernel.function("sys_bind").call ? sockfd = $fd my_addr_uaddr = $umyaddr addrlen = $addrlen +%( systemtap_v >= "2.5" %? + uaddr_ip = _struct_sockaddr_u_ip_addr($umyaddr, $addrlen) +%) argstr = sprintf("%d, %s, %d", $fd, _struct_sockaddr_u($umyaddr, $addrlen), $addrlen) } probe syscall.bind.return = kernel.function("sys_bind").return ?