Add tcp arguments to netlink calls

Since they call tracee-specific socket/sendmsg/recvmsg, we'd like to
pass tcp there.

* defs.h (genl_families_xlat): Add tcp argument.
* netlink.c (decode_nlmsg_type_default, decode_nlmsg_type_generic,
decode_nlmsg_type_netfilter, typedef nlmsg_types_decoder_t): Likewise.
(decode_nlmsg_type): Add tcp argument. Pass tcp to decoder call.
(print_nlmsghdr): Pass tcp to the decode_nlmsg_type call.
* socketutils.c (send_query, receive_responses): Add tcp argument.
(inet_send_query, unix_send_query, netlink_send_query, ): Add tcp argument.
Pass tcp to the send_query call.
(unix_get): Add tcp argument. Pass tcp to the unix_send_query and
receive_responses calls.
(inet_get): Add tcp argument. Pass tcp to the inet_send_query and
receive_responses calls.
(tcp_v4_get, udp_v4_get, tcp_v6_get, udp_v6_get): Add tcp argument. Pass
tcp to the inet_get call.
(netlink_get): Add tcp argument. Pass tcp to the netlink_send_query and
receive_responses calls.
(protocols): Add tcp argument to the get field.
(get_sockaddr_by_inode_uncached): Add tcp argument. Pass tcp to
the protocols[].get calls.
(print_sockaddr_by_inode_uncached): Add tcp argument. Pass tcp to
the get_sockaddr_by_inode_uncached call.
(get_sockaddr_by_inode): Pass tcp to the get_sockaddr_by_inode_uncached
call.
(print_sockaddr_by_inode): Pass tcp to the
print_sockaddr_by_inode_uncached call.
(genl_send_dump_families): Add tcp argument. Pass tcp to the send_query
call.
(genl_families_xlat): Add tcp argument. Pass tcp to the
genl_send_dump_families and receive_responses calls.
This commit is contained in:
Eugene Syromiatnikov 2017-12-26 00:14:14 +01:00 committed by Dmitry V. Levin
parent 562abec971
commit c46fefcad3
3 changed files with 50 additions and 47 deletions

2
defs.h
View File

@ -498,7 +498,7 @@ void dyxlat_free(struct dyxlat *);
const struct xlat *dyxlat_get(const struct dyxlat *);
void dyxlat_add_pair(struct dyxlat *, uint64_t val, const char *str, size_t len);
const struct xlat *genl_families_xlat(void);
const struct xlat *genl_families_xlat(struct tcb *tcp);
extern unsigned long get_pagesize(void);
extern int next_set_bit(const void *bit_array, unsigned cur_bit, unsigned size_bits);

View File

@ -107,7 +107,7 @@ get_fd_nl_family(struct tcb *const tcp, const int fd)
}
static void
decode_nlmsg_type_default(const struct xlat *const xlat,
decode_nlmsg_type_default(struct tcb *tcp, const struct xlat *const xlat,
const uint16_t type,
const char *const dflt)
{
@ -115,11 +115,11 @@ decode_nlmsg_type_default(const struct xlat *const xlat,
}
static void
decode_nlmsg_type_generic(const struct xlat *const xlat,
decode_nlmsg_type_generic(struct tcb *tcp, const struct xlat *const xlat,
const uint16_t type,
const char *const dflt)
{
printxval(genl_families_xlat(), type, dflt);
printxval(genl_families_xlat(tcp), type, dflt);
}
static const struct {
@ -155,7 +155,7 @@ static const struct {
};
static void
decode_nlmsg_type_netfilter(const struct xlat *const xlat,
decode_nlmsg_type_netfilter(struct tcb *tcp, const struct xlat *const xlat,
const uint16_t type,
const char *const dflt)
{
@ -183,7 +183,7 @@ decode_nlmsg_type_netfilter(const struct xlat *const xlat,
tprintf("%#x", msg_type);
}
typedef void (*nlmsg_types_decoder_t)(const struct xlat *,
typedef void (*nlmsg_types_decoder_t)(struct tcb *, const struct xlat *,
uint16_t type,
const char *dflt);
@ -215,7 +215,8 @@ static const struct {
* for family here to filter out -1.
*/
static void
decode_nlmsg_type(const uint16_t type, const unsigned int family)
decode_nlmsg_type(struct tcb *tcp, const uint16_t type,
const unsigned int family)
{
nlmsg_types_decoder_t decoder = decode_nlmsg_type_default;
const struct xlat *xlat = netlink_types;
@ -234,7 +235,7 @@ decode_nlmsg_type(const uint16_t type, const unsigned int family)
dflt = nlmsg_types[family].dflt;
}
decoder(xlat, type, dflt);
decoder(tcp, xlat, type, dflt);
}
static const struct xlat *
@ -443,7 +444,7 @@ print_nlmsghdr(struct tcb *tcp,
tprintf("{len=%u, type=", nlmsghdr->nlmsg_len);
decode_nlmsg_type(nlmsghdr->nlmsg_type, family);
decode_nlmsg_type(tcp, nlmsghdr->nlmsg_type, family);
tprints(", flags=");
decode_nlmsg_flags(nlmsghdr->nlmsg_flags,

View File

@ -87,7 +87,7 @@ print_sockaddr_by_inode_cached(const unsigned long inode)
}
static bool
send_query(const int fd, void *req, size_t req_size)
send_query(struct tcb *tcp, const int fd, void *req, size_t req_size)
{
struct sockaddr_nl nladdr = {
.nl_family = AF_NETLINK
@ -114,7 +114,8 @@ send_query(const int fd, void *req, size_t req_size)
}
static bool
inet_send_query(const int fd, const int family, const int proto)
inet_send_query(struct tcb *tcp, const int fd, const int family,
const int proto)
{
struct {
const struct nlmsghdr nlh;
@ -131,7 +132,7 @@ inet_send_query(const int fd, const int family, const int proto)
.idiag_states = -1
}
};
return send_query(fd, &req, sizeof(req));
return send_query(tcp, fd, &req, sizeof(req));
}
static int
@ -190,7 +191,7 @@ inet_parse_response(const void *const data, const int data_len,
}
static bool
receive_responses(const int fd, const unsigned long inode,
receive_responses(struct tcb *tcp, const int fd, const unsigned long inode,
const unsigned long expected_msg_type,
int (*parser)(const void *, int,
unsigned long, void *),
@ -243,7 +244,7 @@ receive_responses(const int fd, const unsigned long inode,
}
static bool
unix_send_query(const int fd, const unsigned long inode)
unix_send_query(struct tcb *tcp, const int fd, const unsigned long inode)
{
struct {
const struct nlmsghdr nlh;
@ -261,7 +262,7 @@ unix_send_query(const int fd, const unsigned long inode)
.udiag_show = UDIAG_SHOW_NAME | UDIAG_SHOW_PEER
}
};
return send_query(fd, &req, sizeof(req));
return send_query(tcp, fd, &req, sizeof(req));
}
static int
@ -343,7 +344,7 @@ unix_parse_response(const void *data, const int data_len,
}
static bool
netlink_send_query(const int fd, const unsigned long inode)
netlink_send_query(struct tcb *tcp, const int fd, const unsigned long inode)
{
struct {
const struct nlmsghdr nlh;
@ -360,7 +361,7 @@ netlink_send_query(const int fd, const unsigned long inode)
.ndiag_show = NDIAG_SHOW_MEMINFO
}
};
return send_query(fd, &req, sizeof(req));
return send_query(tcp, fd, &req, sizeof(req));
}
static int
@ -398,60 +399,60 @@ netlink_parse_response(const void *data, const int data_len,
}
static const char *
unix_get(const int fd, const unsigned long inode)
unix_get(struct tcb *tcp, const int fd, const unsigned long inode)
{
return unix_send_query(fd, inode)
&& receive_responses(fd, inode, SOCK_DIAG_BY_FAMILY,
return unix_send_query(tcp, fd, inode)
&& receive_responses(tcp, fd, inode, SOCK_DIAG_BY_FAMILY,
unix_parse_response, (void *) "UNIX")
? get_sockaddr_by_inode_cached(inode) : NULL;
}
static const char *
inet_get(const int fd, const int family, const int protocol,
inet_get(struct tcb *tcp, const int fd, const int family, const int protocol,
const unsigned long inode, const char *proto_name)
{
return inet_send_query(fd, family, protocol)
&& receive_responses(fd, inode, SOCK_DIAG_BY_FAMILY,
return inet_send_query(tcp, fd, family, protocol)
&& receive_responses(tcp, fd, inode, SOCK_DIAG_BY_FAMILY,
inet_parse_response, (void *) proto_name)
? get_sockaddr_by_inode_cached(inode) : NULL;
}
static const char *
tcp_v4_get(const int fd, const unsigned long inode)
tcp_v4_get(struct tcb *tcp, const int fd, const unsigned long inode)
{
return inet_get(fd, AF_INET, IPPROTO_TCP, inode, "TCP");
return inet_get(tcp, fd, AF_INET, IPPROTO_TCP, inode, "TCP");
}
static const char *
udp_v4_get(const int fd, const unsigned long inode)
udp_v4_get(struct tcb *tcp, const int fd, const unsigned long inode)
{
return inet_get(fd, AF_INET, IPPROTO_UDP, inode, "UDP");
return inet_get(tcp, fd, AF_INET, IPPROTO_UDP, inode, "UDP");
}
static const char *
tcp_v6_get(const int fd, const unsigned long inode)
tcp_v6_get(struct tcb *tcp, const int fd, const unsigned long inode)
{
return inet_get(fd, AF_INET6, IPPROTO_TCP, inode, "TCPv6");
return inet_get(tcp, fd, AF_INET6, IPPROTO_TCP, inode, "TCPv6");
}
static const char *
udp_v6_get(const int fd, const unsigned long inode)
udp_v6_get(struct tcb *tcp, const int fd, const unsigned long inode)
{
return inet_get(fd, AF_INET6, IPPROTO_UDP, inode, "UDPv6");
return inet_get(tcp, fd, AF_INET6, IPPROTO_UDP, inode, "UDPv6");
}
static const char *
netlink_get(const int fd, const unsigned long inode)
netlink_get(struct tcb *tcp, const int fd, const unsigned long inode)
{
return netlink_send_query(fd, inode)
&& receive_responses(fd, inode, SOCK_DIAG_BY_FAMILY,
return netlink_send_query(tcp, fd, inode)
&& receive_responses(tcp, fd, inode, SOCK_DIAG_BY_FAMILY,
netlink_parse_response, (void *) "NETLINK")
? get_sockaddr_by_inode_cached(inode) : NULL;
}
static const struct {
const char *const name;
const char * (*const get)(int, unsigned long);
const char * (*const get)(struct tcb *, int, unsigned long);
} protocols[] = {
[SOCK_PROTO_UNIX] = { "UNIX", unix_get },
[SOCK_PROTO_TCP] = { "TCP", tcp_v4_get },
@ -474,7 +475,7 @@ get_proto_by_name(const char *const name)
}
static const char *
get_sockaddr_by_inode_uncached(const unsigned long inode,
get_sockaddr_by_inode_uncached(struct tcb *tcp, const unsigned long inode,
const enum sock_proto proto)
{
if ((unsigned int) proto >= ARRAY_SIZE(protocols) ||
@ -487,14 +488,14 @@ get_sockaddr_by_inode_uncached(const unsigned long inode,
const char *details = NULL;
if (proto != SOCK_PROTO_UNKNOWN) {
details = protocols[proto].get(fd, inode);
details = protocols[proto].get(tcp, fd, inode);
} else {
unsigned int i;
for (i = (unsigned int) SOCK_PROTO_UNKNOWN + 1;
i < ARRAY_SIZE(protocols); ++i) {
if (!protocols[i].get)
continue;
details = protocols[i].get(fd, inode);
details = protocols[i].get(tcp, fd, inode);
if (details)
break;
}
@ -505,10 +506,10 @@ get_sockaddr_by_inode_uncached(const unsigned long inode,
}
static bool
print_sockaddr_by_inode_uncached(const unsigned long inode,
print_sockaddr_by_inode_uncached(struct tcb *tcp, const unsigned long inode,
const enum sock_proto proto)
{
const char *details = get_sockaddr_by_inode_uncached(inode, proto);
const char *details = get_sockaddr_by_inode_uncached(tcp, inode, proto);
if (details) {
tprints(details);
@ -531,7 +532,7 @@ get_sockaddr_by_inode(struct tcb *const tcp, const int fd,
{
const char *details = get_sockaddr_by_inode_cached(inode);
return details ? details :
get_sockaddr_by_inode_uncached(inode, getfdproto(tcp, fd));
get_sockaddr_by_inode_uncached(tcp, inode, getfdproto(tcp, fd));
}
/* Given an inode number of a socket, print out its protocol details. */
@ -540,7 +541,8 @@ print_sockaddr_by_inode(struct tcb *const tcp, const int fd,
const unsigned long inode)
{
return print_sockaddr_by_inode_cached(inode) ? true :
print_sockaddr_by_inode_uncached(inode, getfdproto(tcp, fd));
print_sockaddr_by_inode_uncached(tcp, inode,
getfdproto(tcp, fd));
}
#ifdef HAVE_LINUX_GENETLINK_H
@ -554,7 +556,7 @@ print_sockaddr_by_inode(struct tcb *const tcp, const int fd,
* codes are building xlat(dyxlat) at runtime.
*/
static bool
genl_send_dump_families(const int fd)
genl_send_dump_families(struct tcb *tcp, const int fd)
{
struct {
const struct nlmsghdr nlh;
@ -569,7 +571,7 @@ genl_send_dump_families(const int fd)
.cmd = CTRL_CMD_GETFAMILY,
}
};
return send_query(fd, &req, sizeof(req));
return send_query(tcp, fd, &req, sizeof(req));
}
static int
@ -620,7 +622,7 @@ genl_parse_families_response(const void *const data,
}
const struct xlat *
genl_families_xlat(void)
genl_families_xlat(struct tcb *tcp)
{
static struct dyxlat *dyxlat;
@ -631,8 +633,8 @@ genl_families_xlat(void)
if (fd < 0)
goto out;
if (genl_send_dump_families(fd))
receive_responses(fd, 0, GENL_ID_CTRL,
if (genl_send_dump_families(tcp, fd))
receive_responses(tcp, fd, 0, GENL_ID_CTRL,
genl_parse_families_response, dyxlat);
close(fd);
}