[CRIU] [PATCH 12/12] unix: Add a method for choosing sender of packet in promiscous DGRAM queue
Kirill Tkhai
ktkhai at virtuozzo.com
Fri Apr 29 07:37:48 PDT 2016
Iterate over foreign sockets and find the right one to restore a packet.
This allows to restore promiscous DGRAM queue with correct msg_names.
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
criu/sk-unix.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 72 insertions(+)
diff --git a/criu/sk-unix.c b/criu/sk-unix.c
index 048d778..0ae0e61 100644
--- a/criu/sk-unix.c
+++ b/criu/sk-unix.c
@@ -908,6 +908,75 @@ static int prep_unix_sk_cwd(struct unix_sk_info *ui, int *prev_cwd_fd)
return 0;
}
+static int unix_get_fd(int *fds, int num, SkPacketEntry *pkt, struct sockaddr **addr,
+ socklen_t *addrlen, void *data)
+{
+ struct unix_sk_info *send, *recv = (struct unix_sk_info *)data;
+ struct sockaddr_un *un;
+ int i, ret;
+
+ *addr = xmalloc(sizeof(struct sockaddr_un));
+ if (!*addr)
+ return -1;
+ un = (struct sockaddr_un *)*addr;
+
+ if (!pkt->has_sender_ino) {
+ ret = -1;
+ goto populate;
+ }
+
+ send = find_unix_sk_by_ino(pkt->sender_ino);
+ if (!send) {
+ pr_err("Can't find socket with ino=%d\n", pkt->sender_ino);
+ goto free;
+ }
+ /*
+ * Since foreign fd is sent after it's bound,
+ * we don't have to wait send->prepared here.
+ */
+ for (i = 0; i < num; i++) {
+ *addrlen = sizeof(struct sockaddr_un);
+ ret = getsockname(fds[i], *addr, addrlen);
+ if (ret < 0) {
+ pr_err("Can't get socket name\n");
+ goto free;
+ }
+ *addrlen -= sizeof(un->sun_family);
+
+ if (*addrlen == send->ue->name.len &&
+ memcmp(un->sun_path, send->ue->name.data, *addrlen) == 0) {
+ ret = fds[i];
+populate:
+ /* Reuse *addr to return receiver address */
+ *addrlen = recv->ue->name.len + sizeof(un->sun_family);
+ memcpy(un->sun_path, recv->ue->name.data, recv->ue->name.len);
+ un->sun_family = AF_UNIX;
+ return ret;
+ }
+ }
+
+ pr_err("Do not owe socket with ino=%u\n", pkt->sender_ino);
+free:
+ xfree(*addr);
+ *addr = NULL;
+ return -1;
+}
+
+static int restore_promisc_queue(struct unix_sk_info *ui, int fd)
+{
+ int *ffds = ui->foreign_fds, i;
+
+ if (restore_sk_queue(ffds, ui->nr_senders, unix_get_fd, ui->ue->id, ui) < 0) {
+ pr_err("Can't restore rcv queue\n");
+ return -1;
+ }
+
+ for (i = 0; i < ui->nr_senders; i++)
+ close(ffds[i]);
+
+ return 0;
+}
+
static int post_open_unix_sk(struct file_desc *d, int fd)
{
struct unix_sk_info *ui;
@@ -919,6 +988,9 @@ static int post_open_unix_sk(struct file_desc *d, int fd)
if (ui->flags & (USK_PAIR_MASTER | USK_PAIR_SLAVE))
return 0;
+ if (ui->nr_senders && restore_promisc_queue(ui, fd))
+ return -1;
+
peer = ui->peer;
if (peer == NULL)
More information about the CRIU
mailing list