This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
Hi. I released new patch... again :). Sorry for lot of spam, but I still learn systemtap in deep. fche and mjw: lot of thanks. On Mon, Dec 02, 2013 at 03:03:43PM +0100, Robin Hack wrote: > Patch is attached here. Sorry. I'm still fighting with mutt. > > On Mon, Dec 02, 2013 at 02:40:13PM +0100, Robin Hack wrote: > > Hi all. > > > > New version of patch is released. > > > > Please, take a look and don't hesitate > > to comment. > > > > This patch (partially?) adds support for pretty print of abstract sockets. > > On this place please look at conv_buf static solution which is not > > good, but I'm not able to use (on x86_64) bigger function frame than > > 512 bytes (-Wframe-larger-than= gcc restriction). > > > > Also I wrote small example (now without documentation). > > > > BTW: What would be nice is to have systemtap function which is not string oriented. > > Function _stp_text_str stops on first NUL char and then does'nt > > print all bytes in memory region. > > > > Have nice day. > > > > PS 2 Frank: No delimters are supported yet. Maybe delimiters aren't > > necessary on this place. > > > > On Sun, Nov 17, 2013 at 11:18:34AM +0100, Robin Hack wrote: > > > On Wed, Nov 13, 2013 at 05:18:35PM -0500, Frank Ch. Eigler wrote: > > > > > > Hi Frank. > > > > > > Thanks again for comments. I did some changes, but comments and changes > > > are still needed. > > > > > > > > Hi, Robin - > > > > > > > > rhack wrote: > > > > > > > > > [...] Then I decided to write this patch. Patch is only draft now > > > > > and comments are very welcome. > > > > > > > > Nice. A few code comments: > > > > > > > > The use of TMP_STAP_RETVALUE / MAXLEN in the embedded-c function is a > > > > little clumsy. Have you considered using ordinarily named variables > > > > to track the remainder base/length of STAP_RETVALUE, > > > It's fixed. > > > > and doing the > > > > RETVALUE_INC_SKIP dance inlined instead of as a macro? > > > I apologize here, but this part is not clear enought for me. > > > > > > > What about delimiters between the data corresponding to multiple SA_* selections? > > > I changed approach. Now I export values direct to probes. > > > Delimiters will be good in tapset library. > > > > > > > > > > > > > Very easy example are attached too. > > > > > > > > It might be even simpler if the related tapset functions all get this > > > > kind of stuff, but perhaps plopped into a macro for easier handling: > > > > > > > > probe syscall.bind = ... { > > > > %( systemtap_v >= "2.5" %? > > > > if (_struct_sockaddr_u_sa_family(my_addr_uaddr, addrlen) =~ "AF_INET.*") { > > > > uaddr_ip = _struct_sockaddr_u_ip_addr(my_addr_uaddr, addrlen) > > > > uaddr_ip_port = ... > > > > } > > > > %) > > > > > > > > where the whole %( %) block could be @defined in a macro, kind of like > > > > _nfs_data_timestamp in tapset/linux/nfs_proc.stpm. > > > > > > > > > > > > > What is not solved in this patch: > > > > > * Error handling if wrong struct is passed - now it's just return empty ("") string. Maybe throw exception will be better. > > > I hope, that this will be part of tapset. > > > > > * Expansion to syscall.connect probe. > > > Done :). > > > > > * Write tapset shell for new internal functions. > > > In progress. > > > > > > > > Yup, plus a test case (e.g., a testsuite/buildok file). > > > I added some tests. > > > > > > > > Thanks! > > > > > > > > - FChE > > > > > diff --git a/tapset/linux/aux_syscalls.stp b/tapset/linux/aux_syscalls.stp > > > index 0f9c9e4..1513150 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 <linux/socket.h> > > > @@ -288,18 +288,75 @@ function _struct_compat_itimerval_u:string(uaddr:long) > > > #include <linux/netlink.h> > > > %} > > > > > > +%{ > > > +// 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 <linux/version.h> > > > #include <linux/in6.h> > > > #include <linux/un.h> > > > #include <linux/if_packet.h> > > > > > > + 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 {stap_retvalue += (n); maxstringlen -= (n - 1);} while (0) > > > + char *stap_retvalue = (char *)(unsigned long)STAP_RETVALUE; > > > + int maxstringlen = 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(stap_retvalue, "AF_INET", maxstringlen); > > > + RETVALUE_INC_SKIP(); > > > + } > > > + > > > + if (what & SA_IP_ADDR) > > > + { > > > +#ifndef NIPQUAD_FMT // kver >= 2.6.36 > > > + n = snprintf(stap_retvalue, maxstringlen, "%pI4", &sin->sin_addr); > > > +#else > > > + n = snprintf(stap_retvalue, maxstringlen, NIPQUAD_FMT, > > > + NIPQUAD(sin->sin_addr)); > > > +#endif > > > + RETVALUE_INC_SKIP(); > > > + } > > > + > > > + if (what & SA_TCP_PORT) > > > + { > > > + n = snprintf(stap_retvalue, maxstringlen, "%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(stap_retvalue, "AF_INET6", maxstringlen); > > > + RETVALUE_INC_SKIP(); > > > + } > > > + > > > + if (what & SA_IP_ADDR) > > > + { > > > +#ifndef NIP6_FMT // kver >= 2.6.36 > > > + n = snprintf(stap_retvalue, maxstringlen, > > > + "%pI6", &sin->sin6_addr); > > > +#else > > > + n = snprintf(stap_retvalue, maxstringlen, > > > + NIP6_FMT, NIP6(sin->sin6_addr)); > > > +#endif > > > + RETVALUE_INC_SKIP(); > > > + } > > > + > > > + if (what & SA_TCP_PORT) > > > + { > > > + n = snprintf(stap_retvalue, maxstringlen, > > > + "%d", _stp_ntohs(sin->sin6_port)); > > > + RETVALUE_INC_SKIP(); > > > + } > > > + > > > + if (what & SA_IPV6_FLOWINFO) > > > + { > > > + n = snprintf(stap_retvalue, maxstringlen, > > > + "%d", sin->sin6_flowinfo); > > > + RETVALUE_INC_SKIP(); > > > + } > > > + > > > + if (what & SA_IPV6_SCOPE_ID) > > > + { > > > + n = snprintf(stap_retvalue, maxstringlen, > > > + "%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..5121751 100644 > > > --- a/tapset/linux/nd_syscalls.stp > > > +++ b/tapset/linux/nd_syscalls.stp > > > @@ -247,6 +247,7 @@ probe nd_syscall.bind = kprobe.function("sys_bind") ? > > > sockfd = int_arg(1) > > > my_addr_uaddr = pointer_arg(2) > > > addrlen = int_arg(3) > > > + @_af_inet_info_u(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 ? > > > @@ -586,6 +587,7 @@ probe nd_syscall.connect = kprobe.function("sys_connect") ? > > > sockfd = int_arg(1) > > > serv_addr_uaddr = pointer_arg(2) > > > addrlen = int_arg(3) > > > + @_af_inet_info_u(serv_addr_uaddr, addrlen) > > > argstr = sprintf("%d, %s, %d", sockfd, _struct_sockaddr_u(serv_addr_uaddr, addrlen), addrlen) > > > } > > > probe nd_syscall.connect.return = kprobe.function("sys_connect").return ? > > > diff --git a/tapset/linux/syscalls.stp b/tapset/linux/syscalls.stp > > > index 13fb92f..d8e1d05 100644 > > > --- a/tapset/linux/syscalls.stp > > > +++ b/tapset/linux/syscalls.stp > > > @@ -199,6 +199,7 @@ probe syscall.bind = kernel.function("sys_bind").call ? > > > sockfd = $fd > > > my_addr_uaddr = $umyaddr > > > addrlen = $addrlen > > > + @_af_inet_info_u(my_addr_uaddr, addrlen) > > > argstr = sprintf("%d, %s, %d", $fd, _struct_sockaddr_u($umyaddr, $addrlen), $addrlen) > > > } > > > probe syscall.bind.return = kernel.function("sys_bind").return ? > > > @@ -472,6 +473,7 @@ probe syscall.connect = kernel.function("sys_connect").call ? > > > sockfd = $fd > > > serv_addr_uaddr = $uservaddr > > > addrlen = $addrlen > > > + @_af_inet_info_u(serv_addr_uaddr, addrlen) > > > argstr = sprintf("%d, %s, %d", $fd, _struct_sockaddr_u($uservaddr, $addrlen), $addrlen) > > > } > > > probe syscall.connect.return = kernel.function("sys_connect").return ? > > > diff --git a/tapset/linux/syscalls.stpm b/tapset/linux/syscalls.stpm > > > new file mode 100644 > > > index 0000000..0ab18ab > > > --- /dev/null > > > +++ b/tapset/linux/syscalls.stpm > > > @@ -0,0 +1,24 @@ > > > +// Macros for syscalls.stp and nd_syscalls.stp > > > +// Copyright (C) 2013 Red Hat > > > +// > > > +// Author : Robin Hack <rhack@redhat.com> > > > +// > > > +// This file is part of systemtap, and is free software. You can > > > +// redistribute it and/or modify it under the terms of the GNU General > > > +// Public License (GPL); either version 2, or (at your option) any > > > +// later version. > > > + > > > +@define _af_inet_info_u(my_addr_uaddr, addrlen) > > > +%( > > > + %( systemtap_v >= "2.5" %? > > > + uaddr_af = _struct_sockaddr_u_sa_family(@my_addr_uaddr, @addrlen) > > > + if (_struct_sockaddr_u_sa_family(@my_addr_uaddr, @addrlen) =~ "AF_INET.*") { > > > + uaddr_ip = _struct_sockaddr_u_ip_addr(@my_addr_uaddr, @addrlen) > > > + uaddr_ip_port = _struct_sockaddr_u_tcp_port(@my_addr_uaddr, @addrlen) > > > + if (_struct_sockaddr_u_sa_family(@my_addr_uaddr, @addrlen) == "AF_INET6") { > > > + uaddr_ipv6_flowinfo = _struct_sockaddr_u_ipv6_flowinfo(@my_addr_uaddr, @addrlen) > > > + uaddr_ipv6_scope_id = _struct_sockaddr_u_ipv6_scope_id(@my_addr_uaddr, @addrlen) > > > + } > > > + } > > > + %) > > > +%) > > > diff --git a/testsuite/buildok/aux_syscalls-embedded.stp b/testsuite/buildok/aux_syscalls-embedded.stp > > > index 1fb5114..51b02c1 100755 > > > --- a/testsuite/buildok/aux_syscalls-embedded.stp > > > +++ b/testsuite/buildok/aux_syscalls-embedded.stp > > > @@ -14,6 +14,14 @@ probe begin { > > > print (_struct_itimerval_u(0)) > > > print (_struct_compat_itimerval_u(0)) > > > print (_struct_sockaddr_u(0,0)) > > > +%( systemtap_v >= "2.5" %? > > > + print (_struct_sockaddr_u_ip_addr(0,0)) > > > + print (_struct_sockaddr_u_tcp_port(0,0)) > > > + print (_struct_sockaddr_u_sa_family(0,0)) > > > + print (_struct_sockaddr_u_ipv6_flowinfo(0,0)) > > > + print (_struct_sockaddr_u_ipv6_scope_id(0,0)) > > > + print (_struct_sockaddr_u_impl(0,0,0)) > > > +%) > > > print (_struct_rlimit_u(0)) > > > print (_fildes_index_u(0, 0)) > > > > > > diff --git a/testsuite/buildok/nd_syscalls-detailed.stp b/testsuite/buildok/nd_syscalls-detailed.stp > > > index 8152f8d..4c9e0ed 100755 > > > --- a/testsuite/buildok/nd_syscalls-detailed.stp > > > +++ b/testsuite/buildok/nd_syscalls-detailed.stp > > > @@ -74,8 +74,13 @@ probe nd_syscall.bdflush.return ? > > > probe nd_syscall.bind > > > { > > > printf("%s, %s\n", name, argstr) > > > +%( systemtap_v >= "2.5" %? > > > + printf("%d, %p, %d, %s\n", sockfd, my_addr_uaddr, addrlen, uaddr_af) > > > +%: > > > printf("%d, %p, %d\n", sockfd, my_addr_uaddr, addrlen) > > > +%) > > > } > > > + > > > probe nd_syscall.bind.return > > > { > > > printf("%s, %s\n", name, retstr) > > > @@ -194,7 +199,11 @@ probe nd_syscall.close.return > > > probe nd_syscall.connect > > > { > > > printf("%s, %s\n", name, argstr) > > > +%( systemtap_v >= "2.5" %? > > > + printf("%d, %p, %d, %s\n", sockfd, serv_addr_uaddr, addrlen, uaddr_af) > > > +%: > > > printf("%d, %p, %d\n", sockfd, serv_addr_uaddr, addrlen) > > > +%) > > > } > > > probe nd_syscall.connect.return > > > { > > > diff --git a/testsuite/buildok/syscalls-detailed.stp b/testsuite/buildok/syscalls-detailed.stp > > > index e1c626c..17544f7 100755 > > > --- a/testsuite/buildok/syscalls-detailed.stp > > > +++ b/testsuite/buildok/syscalls-detailed.stp > > > @@ -74,7 +74,12 @@ probe syscall.bdflush.return ? > > > probe syscall.bind > > > { > > > printf("%s, %s\n", name, argstr) > > > + > > > +%( systemtap_v >= "2.5" %? > > > + printf("%d, %p, %d, %s\n", sockfd, my_addr_uaddr, addrlen, uaddr_af) > > > +%: > > > printf("%d, %p, %d\n", sockfd, my_addr_uaddr, addrlen) > > > +%) > > > } > > > probe syscall.bind.return > > > { > > > @@ -194,7 +199,11 @@ probe syscall.close.return > > > probe syscall.connect > > > { > > > printf("%s, %s\n", name, argstr) > > > +%( systemtap_v >= "2.5" %? > > > + printf("%d, %p, %d, %s\n", sockfd, serv_addr_uaddr, addrlen, uaddr_af) > > > +%: > > > printf("%d, %p, %d\n", sockfd, serv_addr_uaddr, addrlen) > > > +%) > > > } > > > probe syscall.connect.return > > > { > > > > > > diff --git a/tapset/linux/aux_syscalls.stp b/tapset/linux/aux_syscalls.stp > > index 0f9c9e4..7b02628 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 <linux/socket.h> > > @@ -288,27 +288,87 @@ function _struct_compat_itimerval_u:string(uaddr:long) > > #include <linux/netlink.h> > > %} > > > > +%{ > > +// 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 <linux/version.h> > > #include <linux/in6.h> > > #include <linux/un.h> > > #include <linux/if_packet.h> > > > > - 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; > > + sa_dispatch what = (sa_dispatch)STAP_ARG_what; > > + > > + char *ptr = (char *)(unsigned long)STAP_ARG_uaddr; > > + // This helps handle variable lenght sockaddr_un. > > + // Some application - like systemd - sends path string > > + // without ending null character. Kernel will handle this. > > + char buf[128] = {'\0'}; > > + size_t len = STAP_ARG_len < 128 ? STAP_ARG_len: 128; > > + struct sockaddr *sa = (struct sockaddr *)buf; > > + > > + char *stap_retvalue = (char *)(unsigned long)STAP_RETVALUE; > > + int maxstringlen = MAXSTRINGLEN; > > + size_t n; > > + > > + // If this will not be static, then gcc will be unhappy. > > + // There is limit to function frame size. > > + static char conv_buf[MAXSTRINGLEN]; > > > > if (ptr == NULL) > > { > > - strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); > > + strlcpy(STAP_RETVALUE, "NULL", MAXSTRINGLEN); > > return; > > } > > > > if (_stp_copy_from_user(buf, ptr, len)) > > { > > - strlcpy (STAP_RETVALUE, "[...]", MAXSTRINGLEN); > > + strlcpy(STAP_RETVALUE, "[...]", MAXSTRINGLEN); > > return; > > } > > > > @@ -326,54 +386,195 @@ function _struct_sockaddr_u:string(uaddr:long, len:long) > > 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(stap_retvalue, "AF_INET", maxstringlen); > > + // (n - 1) mean: cut of null char > > + stap_retvalue += (n); > > + maxstringlen -= (n - 1); > > + } > > + > > + if (what & SA_IP_ADDR) > > + { > > +#ifndef NIPQUAD_FMT // kver >= 2.6.36 > > + n = snprintf(stap_retvalue, maxstringlen, "%pI4", &sin->sin_addr); > > +#else > > + n = snprintf(stap_retvalue, maxstringlen, NIPQUAD_FMT, > > + NIPQUAD(sin->sin_addr)); > > +#endif > > + // (n - 1) mean: cut of null char > > + stap_retvalue += (n); > > + maxstringlen -= (n - 1); > > + } > > + > > + if (what & SA_TCP_PORT) > > + { > > + n = snprintf(stap_retvalue, maxstringlen, "%d", > > + _stp_ntohs(sin->sin_port)); > > + // (n - 1) mean: cut of null char > > + stap_retvalue += (n); > > + maxstringlen -= (n - 1); > > + } > > } > > + // Why 2 * sizeof (char) here? > > + // Because I want to support abstract sockets with > > + // at least one usable byte after initial \0 char. > > + // Unnamed sockets aren't supported yet. > > 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); > > + && ((len == sizeof(struct sockaddr_un)) > > + || (len >= ((sizeof(sa_family_t)) + (2 * sizeof(char)))))) > > + { > > + struct sockaddr_un *sun = (struct sockaddr_un *)buf; > > + if (what & SA_PRETTY) > > + { > > + > > + // Support for abstract sockets > > + if (sun->sun_path[0] == '\0') > > + { > > + // Abstract sockets aren't string oriented. > > + // We need conversion on this place. > > + // No check of ret value, because _stp_text_str returns > > + // "<unknown>" if bad things happen. > > + // Well. There can be NUL chars inside sun_path. > > + // We just stop at first NUL char. > > + _stp_text_str(conv_buf, &sun->sun_path[1], > > + len - sizeof(sa_family_t), MAXSTRINGLEN - 1, 0, 0); > > + snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{AF_UNIX, \\000%s}", > > + conv_buf); > > + } else > > + { > > + // Just cut path if is too long > > + buf[127] = '\0'; > > + 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)); > > -#endif > > + 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(stap_retvalue, "AF_INET6", maxstringlen); > > + // (n - 1) mean: cut of null char > > + stap_retvalue += (n); > > + maxstringlen -= (n - 1); > > + } > > + > > + if (what & SA_IP_ADDR) > > + { > > +#ifndef NIP6_FMT // kver >= 2.6.36 > > + n = snprintf(stap_retvalue, maxstringlen, > > + "%pI6", &sin->sin6_addr); > > +#else > > + n = snprintf(stap_retvalue, maxstringlen, > > + NIP6_FMT, NIP6(sin->sin6_addr)); > > +#endif > > + // (n - 1) mean: cut of null char > > + stap_retvalue += (n); > > + maxstringlen -= (n - 1); > > + } > > + > > + if (what & SA_TCP_PORT) > > + { > > + n = snprintf(stap_retvalue, maxstringlen, > > + "%d", _stp_ntohs(sin->sin6_port)); > > + // (n - 1) mean: cut of null char > > + stap_retvalue += (n); > > + maxstringlen -= (n - 1); > > + } > > + > > + if (what & SA_IPV6_FLOWINFO) > > + { > > + n = snprintf(stap_retvalue, maxstringlen, > > + "%d", sin->sin6_flowinfo); > > + // (n - 1) mean: cut of null char > > + stap_retvalue += (n); > > + maxstringlen -= (n - 1); > > + } > > + > > + if (what & SA_IPV6_SCOPE_ID) > > + { > > + n = snprintf(stap_retvalue, maxstringlen, > > + "%d", sin->sin6_flowinfo); > > + // (n - 1) mean: cut of null char > > + stap_retvalue += (n); > > + maxstringlen -= (n - 1); > > + } > > } > > 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 > > { > > diff --git a/tapset/linux/nd_syscalls.stp b/tapset/linux/nd_syscalls.stp > > index f2daa01..5121751 100644 > > --- a/tapset/linux/nd_syscalls.stp > > +++ b/tapset/linux/nd_syscalls.stp > > @@ -247,6 +247,7 @@ probe nd_syscall.bind = kprobe.function("sys_bind") ? > > sockfd = int_arg(1) > > my_addr_uaddr = pointer_arg(2) > > addrlen = int_arg(3) > > + @_af_inet_info_u(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 ? > > @@ -586,6 +587,7 @@ probe nd_syscall.connect = kprobe.function("sys_connect") ? > > sockfd = int_arg(1) > > serv_addr_uaddr = pointer_arg(2) > > addrlen = int_arg(3) > > + @_af_inet_info_u(serv_addr_uaddr, addrlen) > > argstr = sprintf("%d, %s, %d", sockfd, _struct_sockaddr_u(serv_addr_uaddr, addrlen), addrlen) > > } > > probe nd_syscall.connect.return = kprobe.function("sys_connect").return ? > > diff --git a/tapset/linux/syscalls.stp b/tapset/linux/syscalls.stp > > index 13fb92f..d8e1d05 100644 > > --- a/tapset/linux/syscalls.stp > > +++ b/tapset/linux/syscalls.stp > > @@ -199,6 +199,7 @@ probe syscall.bind = kernel.function("sys_bind").call ? > > sockfd = $fd > > my_addr_uaddr = $umyaddr > > addrlen = $addrlen > > + @_af_inet_info_u(my_addr_uaddr, addrlen) > > argstr = sprintf("%d, %s, %d", $fd, _struct_sockaddr_u($umyaddr, $addrlen), $addrlen) > > } > > probe syscall.bind.return = kernel.function("sys_bind").return ? > > @@ -472,6 +473,7 @@ probe syscall.connect = kernel.function("sys_connect").call ? > > sockfd = $fd > > serv_addr_uaddr = $uservaddr > > addrlen = $addrlen > > + @_af_inet_info_u(serv_addr_uaddr, addrlen) > > argstr = sprintf("%d, %s, %d", $fd, _struct_sockaddr_u($uservaddr, $addrlen), $addrlen) > > } > > probe syscall.connect.return = kernel.function("sys_connect").return ? > > diff --git a/tapset/linux/syscalls.stpm b/tapset/linux/syscalls.stpm > > new file mode 100644 > > index 0000000..0ab18ab > > --- /dev/null > > +++ b/tapset/linux/syscalls.stpm > > @@ -0,0 +1,24 @@ > > +// Macros for syscalls.stp and nd_syscalls.stp > > +// Copyright (C) 2013 Red Hat > > +// > > +// Author : Robin Hack <rhack@redhat.com> > > +// > > +// This file is part of systemtap, and is free software. You can > > +// redistribute it and/or modify it under the terms of the GNU General > > +// Public License (GPL); either version 2, or (at your option) any > > +// later version. > > + > > +@define _af_inet_info_u(my_addr_uaddr, addrlen) > > +%( > > + %( systemtap_v >= "2.5" %? > > + uaddr_af = _struct_sockaddr_u_sa_family(@my_addr_uaddr, @addrlen) > > + if (_struct_sockaddr_u_sa_family(@my_addr_uaddr, @addrlen) =~ "AF_INET.*") { > > + uaddr_ip = _struct_sockaddr_u_ip_addr(@my_addr_uaddr, @addrlen) > > + uaddr_ip_port = _struct_sockaddr_u_tcp_port(@my_addr_uaddr, @addrlen) > > + if (_struct_sockaddr_u_sa_family(@my_addr_uaddr, @addrlen) == "AF_INET6") { > > + uaddr_ipv6_flowinfo = _struct_sockaddr_u_ipv6_flowinfo(@my_addr_uaddr, @addrlen) > > + uaddr_ipv6_scope_id = _struct_sockaddr_u_ipv6_scope_id(@my_addr_uaddr, @addrlen) > > + } > > + } > > + %) > > +%) > > diff --git a/testsuite/buildok/aux_syscalls-embedded.stp b/testsuite/buildok/aux_syscalls-embedded.stp > > index 1fb5114..51b02c1 100755 > > --- a/testsuite/buildok/aux_syscalls-embedded.stp > > +++ b/testsuite/buildok/aux_syscalls-embedded.stp > > @@ -14,6 +14,14 @@ probe begin { > > print (_struct_itimerval_u(0)) > > print (_struct_compat_itimerval_u(0)) > > print (_struct_sockaddr_u(0,0)) > > +%( systemtap_v >= "2.5" %? > > + print (_struct_sockaddr_u_ip_addr(0,0)) > > + print (_struct_sockaddr_u_tcp_port(0,0)) > > + print (_struct_sockaddr_u_sa_family(0,0)) > > + print (_struct_sockaddr_u_ipv6_flowinfo(0,0)) > > + print (_struct_sockaddr_u_ipv6_scope_id(0,0)) > > + print (_struct_sockaddr_u_impl(0,0,0)) > > +%) > > print (_struct_rlimit_u(0)) > > print (_fildes_index_u(0, 0)) > > > > diff --git a/testsuite/buildok/nd_syscalls-detailed.stp b/testsuite/buildok/nd_syscalls-detailed.stp > > index 8152f8d..4c9e0ed 100755 > > --- a/testsuite/buildok/nd_syscalls-detailed.stp > > +++ b/testsuite/buildok/nd_syscalls-detailed.stp > > @@ -74,8 +74,13 @@ probe nd_syscall.bdflush.return ? > > probe nd_syscall.bind > > { > > printf("%s, %s\n", name, argstr) > > +%( systemtap_v >= "2.5" %? > > + printf("%d, %p, %d, %s\n", sockfd, my_addr_uaddr, addrlen, uaddr_af) > > +%: > > printf("%d, %p, %d\n", sockfd, my_addr_uaddr, addrlen) > > +%) > > } > > + > > probe nd_syscall.bind.return > > { > > printf("%s, %s\n", name, retstr) > > @@ -194,7 +199,11 @@ probe nd_syscall.close.return > > probe nd_syscall.connect > > { > > printf("%s, %s\n", name, argstr) > > +%( systemtap_v >= "2.5" %? > > + printf("%d, %p, %d, %s\n", sockfd, serv_addr_uaddr, addrlen, uaddr_af) > > +%: > > printf("%d, %p, %d\n", sockfd, serv_addr_uaddr, addrlen) > > +%) > > } > > probe nd_syscall.connect.return > > { > > diff --git a/testsuite/buildok/syscalls-detailed.stp b/testsuite/buildok/syscalls-detailed.stp > > index e1c626c..17544f7 100755 > > --- a/testsuite/buildok/syscalls-detailed.stp > > +++ b/testsuite/buildok/syscalls-detailed.stp > > @@ -74,7 +74,12 @@ probe syscall.bdflush.return ? > > probe syscall.bind > > { > > printf("%s, %s\n", name, argstr) > > + > > +%( systemtap_v >= "2.5" %? > > + printf("%d, %p, %d, %s\n", sockfd, my_addr_uaddr, addrlen, uaddr_af) > > +%: > > printf("%d, %p, %d\n", sockfd, my_addr_uaddr, addrlen) > > +%) > > } > > probe syscall.bind.return > > { > > @@ -194,7 +199,11 @@ probe syscall.close.return > > probe syscall.connect > > { > > printf("%s, %s\n", name, argstr) > > +%( systemtap_v >= "2.5" %? > > + printf("%d, %p, %d, %s\n", sockfd, serv_addr_uaddr, addrlen, uaddr_af) > > +%: > > printf("%d, %p, %d\n", sockfd, serv_addr_uaddr, addrlen) > > +%) > > } > > probe syscall.connect.return > > { > > diff --git a/testsuite/systemtap.examples/network/connect_stat.stp b/testsuite/systemtap.examples/network/connect_stat.stp > > new file mode 100644 > > index 0000000..e0b59d0 > > --- /dev/null > > +++ b/testsuite/systemtap.examples/network/connect_stat.stp > > @@ -0,0 +1,31 @@ > > +#! /usr/bin/env stap > > + > > +############################################################ > > +# connect_stat.stp > > +# Author: Robin Hack <rhack@redhat.com> > > +# An example script show process tree of process > > +# which tried to call connect with specific ip address > > +############################################################ > > + > > +function process_tree (ip:string) { > > + cur_proc = task_current(); > > + parent_pid = task_pid(task_parent (cur_proc)); > > + > > + printf ("%s: ", ip); > > + while (parent_pid != 0) { > > + printf ("%s (%d),%d,%d -> ", task_execname(cur_proc), task_pid(cur_proc), task_uid(cur_proc),task_gid (cur_proc)); > > + cur_proc = task_parent(cur_proc); > > + parent_pid = task_pid(task_parent (cur_proc)); > > + } > > + # init process > > + if (task_pid (cur_proc) == 1) { > > + printf ("%s (%d),%d,%d\n", task_execname(cur_proc), task_pid(cur_proc), task_uid(cur_proc),task_gid (cur_proc)); > > + } > > +} > > + > > +probe syscall.connect { > > + if ((uaddr_af !~ "AF_INET*") || (uaddr_ip != @1)) { > > + next; > > + } > > + process_tree (uaddr_ip); > > +} > > > > > > ----- End forwarded message ----- > diff --git a/tapset/linux/aux_syscalls.stp b/tapset/linux/aux_syscalls.stp > index 0f9c9e4..7b02628 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 <linux/socket.h> > @@ -288,27 +288,87 @@ function _struct_compat_itimerval_u:string(uaddr:long) > #include <linux/netlink.h> > %} > > +%{ > +// 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 <linux/version.h> > #include <linux/in6.h> > #include <linux/un.h> > #include <linux/if_packet.h> > > - 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; > + sa_dispatch what = (sa_dispatch)STAP_ARG_what; > + > + char *ptr = (char *)(unsigned long)STAP_ARG_uaddr; > + // This helps handle variable lenght sockaddr_un. > + // Some application - like systemd - sends path string > + // without ending null character. Kernel will handle this. > + char buf[128] = {'\0'}; > + size_t len = STAP_ARG_len < 128 ? STAP_ARG_len: 128; > + struct sockaddr *sa = (struct sockaddr *)buf; > + > + char *stap_retvalue = (char *)(unsigned long)STAP_RETVALUE; > + int maxstringlen = MAXSTRINGLEN; > + size_t n; > + > + // If this will not be static, then gcc will be unhappy. > + // There is limit to function frame size. > + static char conv_buf[MAXSTRINGLEN]; > > if (ptr == NULL) > { > - strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); > + strlcpy(STAP_RETVALUE, "NULL", MAXSTRINGLEN); > return; > } > > if (_stp_copy_from_user(buf, ptr, len)) > { > - strlcpy (STAP_RETVALUE, "[...]", MAXSTRINGLEN); > + strlcpy(STAP_RETVALUE, "[...]", MAXSTRINGLEN); > return; > } > > @@ -326,54 +386,195 @@ function _struct_sockaddr_u:string(uaddr:long, len:long) > 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(stap_retvalue, "AF_INET", maxstringlen); > + // (n - 1) mean: cut of null char > + stap_retvalue += (n); > + maxstringlen -= (n - 1); > + } > + > + if (what & SA_IP_ADDR) > + { > +#ifndef NIPQUAD_FMT // kver >= 2.6.36 > + n = snprintf(stap_retvalue, maxstringlen, "%pI4", &sin->sin_addr); > +#else > + n = snprintf(stap_retvalue, maxstringlen, NIPQUAD_FMT, > + NIPQUAD(sin->sin_addr)); > +#endif > + // (n - 1) mean: cut of null char > + stap_retvalue += (n); > + maxstringlen -= (n - 1); > + } > + > + if (what & SA_TCP_PORT) > + { > + n = snprintf(stap_retvalue, maxstringlen, "%d", > + _stp_ntohs(sin->sin_port)); > + // (n - 1) mean: cut of null char > + stap_retvalue += (n); > + maxstringlen -= (n - 1); > + } > } > + // Why 2 * sizeof (char) here? > + // Because I want to support abstract sockets with > + // at least one usable byte after initial \0 char. > + // Unnamed sockets aren't supported yet. > 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); > + && ((len == sizeof(struct sockaddr_un)) > + || (len >= ((sizeof(sa_family_t)) + (2 * sizeof(char)))))) > + { > + struct sockaddr_un *sun = (struct sockaddr_un *)buf; > + if (what & SA_PRETTY) > + { > + > + // Support for abstract sockets > + if (sun->sun_path[0] == '\0') > + { > + // Abstract sockets aren't string oriented. > + // We need conversion on this place. > + // No check of ret value, because _stp_text_str returns > + // "<unknown>" if bad things happen. > + // Well. There can be NUL chars inside sun_path. > + // We just stop at first NUL char. > + _stp_text_str(conv_buf, &sun->sun_path[1], > + len - sizeof(sa_family_t), MAXSTRINGLEN - 1, 0, 0); > + snprintf(STAP_RETVALUE, MAXSTRINGLEN, "{AF_UNIX, \\000%s}", > + conv_buf); > + } else > + { > + // Just cut path if is too long > + buf[127] = '\0'; > + 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)); > -#endif > + 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(stap_retvalue, "AF_INET6", maxstringlen); > + // (n - 1) mean: cut of null char > + stap_retvalue += (n); > + maxstringlen -= (n - 1); > + } > + > + if (what & SA_IP_ADDR) > + { > +#ifndef NIP6_FMT // kver >= 2.6.36 > + n = snprintf(stap_retvalue, maxstringlen, > + "%pI6", &sin->sin6_addr); > +#else > + n = snprintf(stap_retvalue, maxstringlen, > + NIP6_FMT, NIP6(sin->sin6_addr)); > +#endif > + // (n - 1) mean: cut of null char > + stap_retvalue += (n); > + maxstringlen -= (n - 1); > + } > + > + if (what & SA_TCP_PORT) > + { > + n = snprintf(stap_retvalue, maxstringlen, > + "%d", _stp_ntohs(sin->sin6_port)); > + // (n - 1) mean: cut of null char > + stap_retvalue += (n); > + maxstringlen -= (n - 1); > + } > + > + if (what & SA_IPV6_FLOWINFO) > + { > + n = snprintf(stap_retvalue, maxstringlen, > + "%d", sin->sin6_flowinfo); > + // (n - 1) mean: cut of null char > + stap_retvalue += (n); > + maxstringlen -= (n - 1); > + } > + > + if (what & SA_IPV6_SCOPE_ID) > + { > + n = snprintf(stap_retvalue, maxstringlen, > + "%d", sin->sin6_flowinfo); > + // (n - 1) mean: cut of null char > + stap_retvalue += (n); > + maxstringlen -= (n - 1); > + } > } > 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 > { > diff --git a/tapset/linux/nd_syscalls.stp b/tapset/linux/nd_syscalls.stp > index f2daa01..5121751 100644 > --- a/tapset/linux/nd_syscalls.stp > +++ b/tapset/linux/nd_syscalls.stp > @@ -247,6 +247,7 @@ probe nd_syscall.bind = kprobe.function("sys_bind") ? > sockfd = int_arg(1) > my_addr_uaddr = pointer_arg(2) > addrlen = int_arg(3) > + @_af_inet_info_u(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 ? > @@ -586,6 +587,7 @@ probe nd_syscall.connect = kprobe.function("sys_connect") ? > sockfd = int_arg(1) > serv_addr_uaddr = pointer_arg(2) > addrlen = int_arg(3) > + @_af_inet_info_u(serv_addr_uaddr, addrlen) > argstr = sprintf("%d, %s, %d", sockfd, _struct_sockaddr_u(serv_addr_uaddr, addrlen), addrlen) > } > probe nd_syscall.connect.return = kprobe.function("sys_connect").return ? > diff --git a/tapset/linux/syscalls.stp b/tapset/linux/syscalls.stp > index 13fb92f..d8e1d05 100644 > --- a/tapset/linux/syscalls.stp > +++ b/tapset/linux/syscalls.stp > @@ -199,6 +199,7 @@ probe syscall.bind = kernel.function("sys_bind").call ? > sockfd = $fd > my_addr_uaddr = $umyaddr > addrlen = $addrlen > + @_af_inet_info_u(my_addr_uaddr, addrlen) > argstr = sprintf("%d, %s, %d", $fd, _struct_sockaddr_u($umyaddr, $addrlen), $addrlen) > } > probe syscall.bind.return = kernel.function("sys_bind").return ? > @@ -472,6 +473,7 @@ probe syscall.connect = kernel.function("sys_connect").call ? > sockfd = $fd > serv_addr_uaddr = $uservaddr > addrlen = $addrlen > + @_af_inet_info_u(serv_addr_uaddr, addrlen) > argstr = sprintf("%d, %s, %d", $fd, _struct_sockaddr_u($uservaddr, $addrlen), $addrlen) > } > probe syscall.connect.return = kernel.function("sys_connect").return ? > diff --git a/tapset/linux/syscalls.stpm b/tapset/linux/syscalls.stpm > new file mode 100644 > index 0000000..0ab18ab > --- /dev/null > +++ b/tapset/linux/syscalls.stpm > @@ -0,0 +1,24 @@ > +// Macros for syscalls.stp and nd_syscalls.stp > +// Copyright (C) 2013 Red Hat > +// > +// Author : Robin Hack <rhack@redhat.com> > +// > +// This file is part of systemtap, and is free software. You can > +// redistribute it and/or modify it under the terms of the GNU General > +// Public License (GPL); either version 2, or (at your option) any > +// later version. > + > +@define _af_inet_info_u(my_addr_uaddr, addrlen) > +%( > + %( systemtap_v >= "2.5" %? > + uaddr_af = _struct_sockaddr_u_sa_family(@my_addr_uaddr, @addrlen) > + if (_struct_sockaddr_u_sa_family(@my_addr_uaddr, @addrlen) =~ "AF_INET.*") { > + uaddr_ip = _struct_sockaddr_u_ip_addr(@my_addr_uaddr, @addrlen) > + uaddr_ip_port = _struct_sockaddr_u_tcp_port(@my_addr_uaddr, @addrlen) > + if (_struct_sockaddr_u_sa_family(@my_addr_uaddr, @addrlen) == "AF_INET6") { > + uaddr_ipv6_flowinfo = _struct_sockaddr_u_ipv6_flowinfo(@my_addr_uaddr, @addrlen) > + uaddr_ipv6_scope_id = _struct_sockaddr_u_ipv6_scope_id(@my_addr_uaddr, @addrlen) > + } > + } > + %) > +%) > diff --git a/testsuite/buildok/aux_syscalls-embedded.stp b/testsuite/buildok/aux_syscalls-embedded.stp > index 1fb5114..51b02c1 100755 > --- a/testsuite/buildok/aux_syscalls-embedded.stp > +++ b/testsuite/buildok/aux_syscalls-embedded.stp > @@ -14,6 +14,14 @@ probe begin { > print (_struct_itimerval_u(0)) > print (_struct_compat_itimerval_u(0)) > print (_struct_sockaddr_u(0,0)) > +%( systemtap_v >= "2.5" %? > + print (_struct_sockaddr_u_ip_addr(0,0)) > + print (_struct_sockaddr_u_tcp_port(0,0)) > + print (_struct_sockaddr_u_sa_family(0,0)) > + print (_struct_sockaddr_u_ipv6_flowinfo(0,0)) > + print (_struct_sockaddr_u_ipv6_scope_id(0,0)) > + print (_struct_sockaddr_u_impl(0,0,0)) > +%) > print (_struct_rlimit_u(0)) > print (_fildes_index_u(0, 0)) > > diff --git a/testsuite/buildok/nd_syscalls-detailed.stp b/testsuite/buildok/nd_syscalls-detailed.stp > index 8152f8d..4c9e0ed 100755 > --- a/testsuite/buildok/nd_syscalls-detailed.stp > +++ b/testsuite/buildok/nd_syscalls-detailed.stp > @@ -74,8 +74,13 @@ probe nd_syscall.bdflush.return ? > probe nd_syscall.bind > { > printf("%s, %s\n", name, argstr) > +%( systemtap_v >= "2.5" %? > + printf("%d, %p, %d, %s\n", sockfd, my_addr_uaddr, addrlen, uaddr_af) > +%: > printf("%d, %p, %d\n", sockfd, my_addr_uaddr, addrlen) > +%) > } > + > probe nd_syscall.bind.return > { > printf("%s, %s\n", name, retstr) > @@ -194,7 +199,11 @@ probe nd_syscall.close.return > probe nd_syscall.connect > { > printf("%s, %s\n", name, argstr) > +%( systemtap_v >= "2.5" %? > + printf("%d, %p, %d, %s\n", sockfd, serv_addr_uaddr, addrlen, uaddr_af) > +%: > printf("%d, %p, %d\n", sockfd, serv_addr_uaddr, addrlen) > +%) > } > probe nd_syscall.connect.return > { > diff --git a/testsuite/buildok/syscalls-detailed.stp b/testsuite/buildok/syscalls-detailed.stp > index e1c626c..17544f7 100755 > --- a/testsuite/buildok/syscalls-detailed.stp > +++ b/testsuite/buildok/syscalls-detailed.stp > @@ -74,7 +74,12 @@ probe syscall.bdflush.return ? > probe syscall.bind > { > printf("%s, %s\n", name, argstr) > + > +%( systemtap_v >= "2.5" %? > + printf("%d, %p, %d, %s\n", sockfd, my_addr_uaddr, addrlen, uaddr_af) > +%: > printf("%d, %p, %d\n", sockfd, my_addr_uaddr, addrlen) > +%) > } > probe syscall.bind.return > { > @@ -194,7 +199,11 @@ probe syscall.close.return > probe syscall.connect > { > printf("%s, %s\n", name, argstr) > +%( systemtap_v >= "2.5" %? > + printf("%d, %p, %d, %s\n", sockfd, serv_addr_uaddr, addrlen, uaddr_af) > +%: > printf("%d, %p, %d\n", sockfd, serv_addr_uaddr, addrlen) > +%) > } > probe syscall.connect.return > { > diff --git a/testsuite/systemtap.examples/network/connect_stat.stp b/testsuite/systemtap.examples/network/connect_stat.stp > new file mode 100644 > index 0000000..e0b59d0 > --- /dev/null > +++ b/testsuite/systemtap.examples/network/connect_stat.stp > @@ -0,0 +1,31 @@ > +#! /usr/bin/env stap > + > +############################################################ > +# connect_stat.stp > +# Author: Robin Hack <rhack@redhat.com> > +# An example script show process tree of process > +# which tried to call connect with specific ip address > +############################################################ > + > +function process_tree (ip:string) { > + cur_proc = task_current(); > + parent_pid = task_pid(task_parent (cur_proc)); > + > + printf ("%s: ", ip); > + while (parent_pid != 0) { > + printf ("%s (%d),%d,%d -> ", task_execname(cur_proc), task_pid(cur_proc), task_uid(cur_proc),task_gid (cur_proc)); > + cur_proc = task_parent(cur_proc); > + parent_pid = task_pid(task_parent (cur_proc)); > + } > + # init process > + if (task_pid (cur_proc) == 1) { > + printf ("%s (%d),%d,%d\n", task_execname(cur_proc), task_pid(cur_proc), task_uid(cur_proc),task_gid (cur_proc)); > + } > +} > + > +probe syscall.connect { > + if ((uaddr_af !~ "AF_INET*") || (uaddr_ip != @1)) { > + next; > + } > + process_tree (uaddr_ip); > +}
Attachment:
uaddr_ip-v4.patch
Description: Text document
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |