mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-19 09:35:12 +00:00
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: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
parent
b50861327e
commit
4ff60cd870
4 changed files with 127 additions and 40 deletions
60
include/packet_diag.h
Normal file
60
include/packet_diag.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
#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
|
||||
|
|
|
|||
95
sk-packet.c
95
sk-packet.c
|
|
@ -1,12 +1,16 @@
|
|||
#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;
|
||||
struct packet_sock_desc *sd;
|
||||
|
||||
pr_info("Dumping packet socket fd %d id %#x\n", lfd, id);
|
||||
|
||||
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;
|
||||
|
|
|
|||
10
sockets.c
10
sockets.c
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue