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] | |
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 -----
Attachment:
uaddr_ip-v3.patch
Description: Text document
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |