Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

crit: parse data fields in files.img #144

Open
rst0git opened this issue Aug 2, 2023 · 9 comments
Open

crit: parse data fields in files.img #144

rst0git opened this issue Aug 2, 2023 · 9 comments

Comments

@rst0git
Copy link
Member

rst0git commented Aug 2, 2023

The Go version of CRIT currently outputs raw data decoded from files.img. However, it would be more user-friendly if we map constants used in certain fields to human readable strings and decode the value used for IP address. The following example shows a comparison between the output of the Go and Python versions of CRIT:

  • Go version of CRIT
        {
            "type": "INETSK",
            "id": 36,
            "isk": {
                "id": 36,
                "ino": 106886,
                "family": 2,
                "type": 1,
                "proto": 6,
                "state": 7,
                "srcPort": 0,
                "dstPort": 0,
                "flags": 2,
                "backlog": 0,
                "srcAddr": [
                    0
                ],
                "dstAddr": [
                    0 
                ],
                "fown": {
                    "uid": 0,
                    "euid": 0,
                    "signum": 0,
                    "pidType": 0,
                    "pid": 0
                },
  • Python version of CRIT
        {
            "type": "INETSK",
            "id": 36,
            "isk": {
                "id": 36,
                "ino": 106886,
                "family": "INET",
                "type": "STREAM",
                "proto": "TCP",
                "state": "CLOSE",
                "src_port": 0,
                "dst_port": 0,
                "flags": "0x2",
                "backlog": 0,
                "src_addr": [
                    "0.0.0.0"
                ],
                "dst_addr": [
                    "0.0.0.0"
                ],
                "fown": {
                    "uid": 0,
                    "euid": 0,
                    "signum": 0,
                    "pid_type": 0,
                    "pid": 0
                },
@snprajwal
Copy link
Member

Hmm, this will require some reworking of the marshaling and unmarshaling logic that we're using currently. We'll probably have to replace protojson.Marshal with our own custom logic to marshal it field by field. I'll look into this.

@Parthiba-Hazra
Copy link

@rst0git if this issue is still on, can I work on this?

@rst0git
Copy link
Member Author

rst0git commented Jan 10, 2024

@Parthiba-Hazra sure, please feel free to open a pull request!

@Parthiba-Hazra
Copy link

@rst0git is there any documentations for all types of constants ? -

// Constants for families
const (
	AF_INET  = 2
	AF_INET6 = 10
)

// Constants for socket types
const (
	SOCK_STREAM = 1
	SOCK_DGRAM  = 2
)

// Constants for protocols
const (
	IPPROTO_TCP = 6
	IPPROTO_UDP = 17
)

// Constants for socket states
const (
	TCP_CLOSE    = 1
	TCP_LISTEN   = 2
	TCP_SYN_SENT = 3
)

@rst0git
Copy link
Member Author

rst0git commented Feb 9, 2024

@rst0git is there any documentations for all types of constants ?

  • man 2 socket provides information about socket families and types
  • man 7 ip provides information about the IP protocol
  • TCP states are listed in include/net/tcp_states.h (and also described here).

@Parthiba-Hazra
Copy link

@rst0git should we update the proto file for this or write our own logic .. also we are using proto2 and I think there are many changes in proto3 as I am getting trouble to generate the go code.

I updated the sk-inet.proto like this -

// SPDX-License-Identifier: MIT

syntax = "proto2";

import "opts.proto";
import "fown.proto";
import "sk-opts.proto";

enum AddressFamily {
  UNSPEC = 0;
  LOCAL = 1;
  INET = 2;
  AX25 = 3;
  IPX = 4;
  APPLETALK = 5;
  NETROM = 6;
  BRIDGE = 7;
  ATMPVC = 8;
  X25 = 9;
  INET6 = 10;
  ROSE = 11;
  DECnet = 12;
  NETBEUI = 13;
  SECURITY = 14;
  KEY = 15;
  NETLINK = 16;
  PACKET = 17;
  ASH = 18;
  ECONET = 19;
  ATMSVC = 20;
  RDS = 21;
  SNA = 22;
  IRDA = 23;
  PPPOX = 24;
  WANPIPE = 25;
  LLC = 26;
  IB = 27;
  MPLS = 28;
  CAN = 29;
  TIPC = 30;
  BLUETOOTH = 31;
  IUCV = 32;
  RXRPC = 33;
  ISDN = 34;
  PHONET = 35;
  IEEE802154 = 36;
  CAIF = 37;
  ALG = 38;
  NFC = 39;
  VSOCK = 40;
  KCM = 41;
  QIPCRTR = 42;
  SMC = 43;
  XDP = 44;
  MCTP = 45;
  MAX = 46;
}

enum SocketType {
  STREAM = 1;
  DGRAM = 2;
  RAW = 3;
}

enum Protocol {
  ICMP = 1;
  IGMP = 2;
  TCP = 6;
  UDP = 17;
  IPv6 = 41;
  OSPF = 89;
}

enum State {
  UNKNOWN = 0;
  LISTEN = 1;
  SYN_SENT = 2;
  SYN_RECV = 3;
  ESTABLISHED = 4;
  FIN_WAIT1 = 5;
  FIN_WAIT2 = 6;
  CLOSE = 7;
  CLOSE_WAIT = 8;
  LAST_ACK = 9;
  TIME_WAIT = 10;
  CLOSED = 11;
}

message ip_opts_raw_entry {
  optional bool hdrincl = 1;
  optional bool nodefrag = 2;
  optional bool checksum = 3;
  repeated uint32 icmpv_filter = 4;
}

message ip_opts_entry {
  optional bool freebind = 1;
  // Fields 2 and 3 are reserved for vz7 use
  optional ip_opts_raw_entry raw = 4;
  optional bool pktinfo = 5;
}

message inet_sk_entry {
	/*
	 * We have two IDs here -- id and ino. The first one
	 * is used when restoring socket behind a file descriprot.
	 * The fdinfo image's id is it. The second one is used
	 * in sk-inet.c internally, in particular we identify
	 * a TCP stream to restore into this socket using the
	 * ino value.
	 */
	required uint32			id		=  1;
	required uint32			ino		=  2;
	required AddressFamily			family		=  3 [(criu).dict = "sk"];
	required SocketType			type		=  4 [(criu).dict = "sk"];
	required Protocol			proto		=  5 [(criu).dict = "sk"];
	required State			state		=  6 [(criu).dict = "sk"];
	required uint32			src_port	=  7;
	required uint32			dst_port	=  8;
	required uint32			flags		=  9 [(criu).hex = true];
	required uint32			backlog		= 10;

	repeated uint32			src_addr	= 11 [(criu).ipadd = true];
	repeated uint32			dst_addr	= 12 [(criu).ipadd = true];

	required fown_entry		fown		= 13;
	required sk_opts_entry		opts		= 14;
	optional bool			v6only		= 15;
	optional ip_opts_entry		ip_opts		= 16;

	/* for ipv6, we need to send the ifindex to bind(); we keep the ifname
	 * here and convert it on restore */
	optional string			ifname		= 17;
	optional uint32			ns_id		= 18;
	optional sk_shutdown		shutdown	= 19;
}

@adrianreber
Copy link
Member

@Parthiba-Hazra Unfortunately it is not possible to change the proto files. Those files are imported from CRIU and can only be changed in the CRIU repository. We just copy those files.

@Parthiba-Hazra
Copy link

@adrianreber ohh I see, then we have to change the unmarshal logic here.

@Parthiba-Hazra
Copy link

Parthiba-Hazra commented Feb 16, 2024

@rst0git I was using map[string]interface{} for unmarshaling the each types(eg; "isk", "reg") and change the necessary fields into human readable format by replacing the integer value with its actual value, but the problem is that the order of json fields are changed after marshaling it again in json bytes cause map store the key value pair in alphabetic order, I think it maybe possible to preserve the order as before. the question is it necessary to keep the order same as before or should we use custom struct instead of map?

edit- another idea could be copy the structs(eg; RegFileEntry{}, inetSkEntry{}) from .proto files for each types and make the each fields of struct to json.RawMessage type .. or it's comfortable type, then we can unmarshal the json bytes into something similar to FileEntry{} struct

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants