Commit 4ff60cd8 authored by Pavel Emelyanov's avatar Pavel Emelyanov

packet: Switch to use packet diag module

It's in net-next already and does provide all we currently
need (and more). Implementation is like for inet and unix
sockets.
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent b5086132
#ifndef __PACKET_DIAG_H__
#define __PACKET_DIAG_H__
#include <linux/types.h>
struct packet_diag_req {
__u8 sdiag_family;
__u8 sdiag_protocol;
__u16 pad;
__u32 pdiag_ino;
__u32 pdiag_show;
__u32 pdiag_cookie[2];
};
#define PACKET_SHOW_INFO 0x00000001 /* Basic packet_sk information */
#define PACKET_SHOW_MCLIST 0x00000002 /* A set of packet_diag_mclist-s */
struct packet_diag_msg {
__u8 pdiag_family;
__u8 pdiag_type;
__u16 pdiag_num;
__u32 pdiag_ino;
__u32 pdiag_cookie[2];
};
enum {
PACKET_DIAG_INFO,
PACKET_DIAG_MCLIST,
PACKET_DIAG_MAX,
};
struct packet_diag_info {
__u32 pdi_index;
__u32 pdi_version;
__u32 pdi_reserve;
__u32 pdi_copy_thresh;
__u32 pdi_tstamp;
__u32 pdi_flags;
#define PDI_RUNNING 0x1
#define PDI_AUXDATA 0x2
#define PDI_ORIGDEV 0x4
#define PDI_VNETHDR 0x8
#define PDI_LOSS 0x10
};
#ifndef MAX_ADDR_LEN
#define MAX_ADDR_LEN 32
#endif
struct packet_diag_mclist {
__u32 pdmc_index;
__u16 pdmc_type;
__u16 pdmc_alen;
__u8 pdmc_addr[MAX_ADDR_LEN];
};
#endif
......@@ -13,6 +13,8 @@ int dump_one_packet_sk(struct fd_parms *p, int lfd, const struct cr_fdset *fds);
int collect_packet_sockets(void);
void show_packetsk(int fd, struct cr_options *);
extern int packet_receive_one(struct nlmsghdr *h, void *arg);
#ifndef PACKET_VNET_HDR
#define PACKET_VNET_HDR 15
#endif
......
#include <linux/if_packet.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <unistd.h>
#include <string.h>
#include "crtools.h"
#include "types.h"
#include "files.h"
#include "sockets.h"
#include "libnetlink.h"
#include "sk-packet.h"
#include "packet_diag.h"
#include "protobuf.h"
#include "protobuf/packet-sock.pb-c.h"
......@@ -17,6 +21,13 @@ struct packet_sock_info {
struct file_desc d;
};
struct packet_sock_desc {
struct socket_desc sd;
unsigned int type;
unsigned short proto;
struct packet_diag_info nli;
};
void show_packetsk(int fd, struct cr_options *o)
{
pb_show_plain(fd, PB_PACKETSK);
......@@ -24,19 +35,20 @@ void show_packetsk(int fd, struct cr_options *o)
static int dump_one_packet_fd(int lfd, u32 id, const struct fd_parms *p)
{
int type, yes;
PacketSockEntry psk = PACKET_SOCK_ENTRY__INIT;
SkOptsEntry skopts = SK_OPTS_ENTRY__INIT;
struct sockaddr_ll addr;
socklen_t alen;
pr_info("Dumping packet socket fd %d id %#x\n", lfd, id);
struct packet_sock_desc *sd;
if (dump_opt(lfd, SOL_SOCKET, SO_TYPE, &type))
sd = (struct packet_sock_desc *)lookup_socket(p->stat.st_ino);
if (sd < 0)
return -1;
pr_info("Dumping packet socket fd %d id %#x\n", lfd, id);
BUG_ON(sd->sd.already_dumped);
sd->sd.already_dumped = 1;
psk.id = id;
psk.type = type;
psk.type = sd->type;
psk.flags = p->flags;
psk.fown = (FownEntry *)&p->fown;
psk.opts = &skopts;
......@@ -44,39 +56,15 @@ static int dump_one_packet_fd(int lfd, u32 id, const struct fd_parms *p)
if (dump_socket_opts(lfd, &skopts))
return -1;
alen = sizeof(addr);
if (getsockname(lfd, (struct sockaddr *)&addr, &alen) < 0) {
pr_perror("Can't get packet sock name");
return -1;
}
psk.protocol = addr.sll_protocol;
psk.ifindex = addr.sll_ifindex;
if (dump_opt(lfd, SOL_PACKET, PACKET_VERSION, &psk.version))
return -1;
if (dump_opt(lfd, SOL_PACKET, PACKET_RESERVE, &psk.reserve))
return -1;
if (dump_opt(lfd, SOL_PACKET, PACKET_TIMESTAMP, &psk.timestamp))
return -1;
if (dump_opt(lfd, SOL_PACKET, PACKET_AUXDATA, &yes))
return -1;
psk.aux_data = (yes ? true : false);
if (dump_opt(lfd, SOL_PACKET, PACKET_ORIGDEV, &yes))
return 1;
psk.orig_dev = (yes ? true : false);
if (dump_opt(lfd, SOL_PACKET, PACKET_VNET_HDR, &yes))
return 1;
psk.vnet_hdr = (yes ? true : false);
if (dump_opt(lfd, SOL_PACKET, PACKET_LOSS, &yes))
return 1;
psk.loss = (yes ? true : false);
psk.protocol = sd->proto;
psk.ifindex = sd->nli.pdi_index;
psk.version = sd->nli.pdi_version;
psk.reserve = sd->nli.pdi_reserve;
psk.timestamp = sd->nli.pdi_tstamp;
psk.aux_data = (sd->nli.pdi_flags & PDI_AUXDATA ? true : false);
psk.orig_dev = (sd->nli.pdi_flags & PDI_ORIGDEV ? true : false);
psk.vnet_hdr = (sd->nli.pdi_flags & PDI_VNETHDR ? true : false);
psk.loss = (sd->nli.pdi_flags & PDI_LOSS ? true : false);
return pb_write_one(fdset_fd(glob_fdset, CR_FD_PACKETSK), &psk, PB_PACKETSK);
}
......@@ -91,6 +79,33 @@ int dump_one_packet_sk(struct fd_parms *p, int lfd, const struct cr_fdset *fds)
return do_dump_gen_file(p, lfd, &packet_dump_ops, fds);
}
int packet_receive_one(struct nlmsghdr *hdr, void *arg)
{
struct packet_diag_msg *m;
struct rtattr *tb[PACKET_DIAG_MAX + 1];
struct packet_sock_desc *sd;
m = NLMSG_DATA(hdr);
parse_rtattr(tb, PACKET_DIAG_MAX, (struct rtattr *)(m + 1),
hdr->nlmsg_len - NLMSG_LENGTH(sizeof(*m)));
pr_msg("Collect packet sock %u %u\n", m->pdiag_ino, (unsigned int)m->pdiag_num);
if (!tb[PACKET_DIAG_INFO]) {
pr_err("No packet sock info in nlm\n");
return -1;
}
sd = xmalloc(sizeof(*sd));
if (!sd)
return -1;
sd->type = m->pdiag_type;
sd->proto = htons(m->pdiag_num);
memcpy(&sd->nli, RTA_DATA(tb[PACKET_DIAG_INFO]), sizeof(sd->nli));
return sk_collect_one(m->pdiag_ino, PF_PACKET, &sd->sd);
}
static int open_packet_sk(struct file_desc *d)
{
struct packet_sock_info *psi;
......
......@@ -8,6 +8,7 @@
#include "sockets.h"
#include "unix_diag.h"
#include "inet_diag.h"
#include "packet_diag.h"
#include "files.h"
#include "util-net.h"
#include "sk-packet.h"
......@@ -46,6 +47,7 @@ int sk_collect_one(int ino, int family, struct socket_desc *d)
d->ino = ino;
d->family = family;
d->already_dumped = 0;
chain = &sockets[ino % SK_HASH_SIZE];
d->next = *chain;
......@@ -174,6 +176,7 @@ int collect_sockets(int pid)
union {
struct unix_diag_req u;
struct inet_diag_req_v2 i;
struct packet_diag_req p;
} r;
} req;
......@@ -263,6 +266,13 @@ int collect_sockets(int pid)
if (tmp)
err = tmp;
req.r.p.sdiag_family = AF_PACKET;
req.r.p.sdiag_protocol = 0;
req.r.p.pdiag_show = PACKET_SHOW_INFO;
tmp = do_rtnl_req(nl, &req, sizeof(req), packet_receive_one, NULL);
if (tmp)
err = tmp;
close(nl);
out:
if (rst > 0 && restore_ns(rst, CLONE_NEWNET) < 0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment