// SPDX-License-Identifier: GPL-2.0-or-later /* seitan - Syscall Expressive Interpreter, Transformer and Notifier * * cooker/calls/net.c - Description of known networking system calls * * Copyright 2023 Red Hat GmbH * Author: Stefano Brivio */ /* fd = socket(family, type stream/dgram/..., protocol) fd = connect(fd, addr, addrlen) fd = accept(fd, addr, addrlen) n = sendto(fd, buf, len, flags, dst addr, addrlen) n = recvfrom(fd, buf, len, flags, src addr, addrlen) n = sendmsg(fd, msg, flags) n = recvmsg(fd, msg, flags) e = shutdown(fd, rd/wr/rdwr) e = bind(fd, addr, addrlen) e = listen(fd, backlog) e = getsockname(fd, bound addr, addrlen) e = getpeername(fd, peer addr, addrlen) e = socketpair(family, type stream/dgram/..., sockets[2]) e = setsockopt(fd, level, optname, *optval, optlen) e = getsockopt(fd, level, optname, *optval, *optlen) n = recvmmsg(fd, *msgvec, vlen, flags, *timeout) n = sendmmsg(fd, *msgvec, vlen, flags) */ #include #include #include #include #include #include #include "../cooker.h" #include "../calls.h" static struct num af[] = { { "unix", AF_UNIX }, { "ipv4", AF_INET }, { "ipv6", AF_INET6 }, { "netlink", AF_NETLINK }, { "packet", AF_PACKET }, { "vsock", AF_VSOCK }, { 0 }, }; static struct num socket_types[] = { { "stream", SOCK_STREAM }, { "dgram", SOCK_DGRAM }, { "seq", SOCK_SEQPACKET }, { "raw", SOCK_RAW }, { "packet", SOCK_PACKET }, { 0 }, }; static struct num socket_flags[] = { { "nonblock", SOCK_NONBLOCK }, { "cloexec", SOCK_CLOEXEC }, { 0 }, }; static struct num protocols[] = { { "ip", IPPROTO_IP }, { "icmp", IPPROTO_ICMP }, { "igmp", IPPROTO_IGMP }, { "tcp", IPPROTO_TCP }, { "udp", IPPROTO_UDP }, { "ipv6", IPPROTO_IPV6 }, { "gre", IPPROTO_GRE }, { "esp", IPPROTO_ESP }, { "ah", IPPROTO_AH }, { "sctp", IPPROTO_SCTP }, { "udplite", IPPROTO_UDPLITE }, { "mpls", IPPROTO_MPLS }, { "raw", IPPROTO_RAW }, { "mptcp", IPPROTO_MPTCP }, { "nl_route", NETLINK_ROUTE }, { 0 }, }; static struct arg socket_args[] = { { 0, { "family", INT, 0, 0, 0, { .d_num = af } } }, { 1, { "type", INT, MASK, 0, 0, { .d_num = socket_types } } }, { 1, { "flags", INT, MASK | FLAGS, 0, 0, { .d_num = socket_flags } } }, { 2, { "protocol", INT, 0, 0, 0, { .d_num = protocols } } }, { 0 }, }; static struct field connect_addr_unix[] = { { "path", STRING, 0, offsetof(struct sockaddr_un, sun_path), UNIX_PATH_MAX, { 0 } }, { 0 }, }; static struct field connect_addr_ipv4[] = { { "port", PORT, 0, offsetof(struct sockaddr_in, sin_port), 0, { 0 } }, { "addr", IPV4, 0, offsetof(struct sockaddr_in, sin_addr), 0, { 0 } }, { 0 }, }; static struct field connect_addr_ipv6[] = { { "port", PORT, 0, offsetof(struct sockaddr_in6, sin6_port), 0, { 0 } }, { "addr", IPV6, 0, offsetof(struct sockaddr_in6, sin6_addr), 0, { 0 } }, { 0 }, }; static struct field connect_addr_nl[] = { { "pid", PID, 0, offsetof(struct sockaddr_nl, nl_pid), 0, { 0 } }, { "groups", U32, 0, offsetof(struct sockaddr_nl, nl_groups), 0, { 0 } }, { 0 }, }; static struct field connect_family = { "family", USHORT, 0, offsetof(struct sockaddr, sa_family), 0, { .d_num = af } }; static struct select_num connect_addr_select_family[] = { { AF_UNIX, sizeof(struct sockaddr_un), { 1, { NULL, STRUCT, 0, 0, 0, { .d_struct = connect_addr_unix } } } }, { AF_INET, sizeof(struct sockaddr_in), { 1, { NULL, STRUCT, 0, 0, 0, { .d_struct = connect_addr_ipv4 } } } }, { AF_INET6, sizeof(struct sockaddr_in6), { 1, { NULL, STRUCT, 0, 0, 0, { .d_struct = connect_addr_ipv6 } } } }, { AF_NETLINK, sizeof(struct sockaddr_nl), { 1, { NULL, STRUCT, 0, 0, 0, { .d_struct = connect_addr_nl } } } }, { 0 }, }; static struct select connect_addr_select = { &connect_family, { .d_num = connect_addr_select_family } }; static struct arg connect_args[] = { { 0, { "fd", INT, 0, 0, 0, { 0 }, }, }, { 0, { "path", FDPATH, 0, 0, 0, { 0 }, }, }, { 1, { "addr", SELECT, 0, 0, sizeof(struct sockaddr_storage), { .d_select = &connect_addr_select }, }, }, { 2, { "addrlen", LONG, SIZE, 0, 0, { .d_size = (intptr_t)&connect_addr_select }, }, }, { 0 } }; static struct num send_flags[] = { { "confirm", MSG_CONFIRM }, { "dontroute", MSG_DONTROUTE }, { "dontwait", MSG_DONTWAIT }, { "eor", MSG_EOR }, { "more", MSG_MORE }, { "nosignal", MSG_NOSIGNAL }, { "oob", MSG_OOB }, { "fastopen", MSG_FASTOPEN }, { 0 }, }; static struct arg send_args[] = { { 0, { "fd", INT, 0, 0, 0, { 0 }, }, }, { 1, { "buf", STRING, WBUF, 0, BUFSIZ, { 0 }, }, }, { 2, { "len", LONG, SIZE, 0, 0, { .d_size = (intptr_t)&send_args[1] }, }, }, { 3, { "flags", INT, FLAGS, 0, 0, { .d_num = send_flags } } }, { 0 } }; static struct arg sendto_args[] = { { 0, { "fd", INT, 0, 0, 0, { 0 }, }, }, { 1, { "buf", STRING, WBUF, 0, BUFSIZ, { 0 }, }, }, { 2, { "len", LONG, SIZE, 0, 0, { .d_size = (intptr_t)&sendto_args[1] }, }, }, { 3, { "flags", INT, FLAGS, 0, 0, { .d_num = send_flags } } }, { 4, { "addr", SELECT, 0, 0, sizeof(struct sockaddr_storage), { .d_select = &connect_addr_select }, }, }, { 5, { "addrlen", LONG, SIZE, 0, 0, { .d_size = (intptr_t)&connect_addr_select }, }, }, { 0 } }; static struct select sendmsg_name_select = { &connect_family, { .d_num = connect_addr_select_family } }; static struct field sendmsg_msghdr[] = { { "name", SELECT, 0, offsetof(struct msghdr, msg_name), sizeof(struct sockaddr_storage), { .d_select = &sendmsg_name_select }, }, { "namelen", LONG, SIZE, offsetof(struct msghdr, msg_namelen), 0, { .d_size = (intptr_t)&sendmsg_name_select }, }, { "iov", STRING, WBUF | IOV, offsetof(struct msghdr, msg_iov), BUFSIZ, { .d_iovlen = offsetof(struct msghdr, msg_iovlen) - offsetof(struct msghdr, msg_iov) }, }, { "iovlen", LONG, 0, offsetof(struct msghdr, msg_iovlen), 0, { 0 }, }, { "control", STRING, 0, offsetof(struct msghdr, msg_control), BUFSIZ, { 0 }, }, { "controllen", LONG, SIZE, offsetof(struct msghdr, msg_controllen), 0, { 0 }, }, { "flags", INT, 0, offsetof(struct msghdr, msg_flags), 0, { 0 }, }, { 0 } }; static struct arg sendmsg_args[] = { { 0, { "fd", INT, 0, 0, 0, { 0 }, }, }, { 1, { "msg", STRUCT, 0, 0, sizeof(struct msghdr), { .d_struct = sendmsg_msghdr }, }, }, { 2, { "flags", INT, FLAGS, 0, 0, { .d_num = send_flags } } }, { 0 } }; static struct arg recvmsg_args[] = { { 0, { "fd", INT, 0, 0, 0, { 0 }, }, }, { 1, { "msg", STRUCT, 0, 0, sizeof(struct msghdr), { .d_struct = sendmsg_msghdr }, }, }, { 2, { "flags", INT, FLAGS, 0, 0, { .d_num = send_flags } } }, { 0 } }; static struct arg setsockopt_args[] = { { 0, { "fd", INT, 0, 0, 0, { 0 }, }, }, { 1, { "level", INT, 0, 0, 0, { 0 }, }, }, { 2, { "optname", INT, 0, 0, 0, { 0 }, }, }, { 3, { "optval", INT, 0, 0, BUFSIZ, { 0 }, }, }, { 4, { "optlen", INT, 0, 0, 0, { 0 }, }, }, { 0 } }; struct call syscalls_net[] = { { __NR_connect, "connect", connect_args }, { __NR_bind, "bind", connect_args }, { __NR_socket, "socket", socket_args }, /* { __NR_send, "send", send_args }, */ { __NR_sendto, "sendto", sendto_args }, { __NR_sendmsg, "sendmsg", sendmsg_args }, { __NR_recvmsg, "recvmsg", recvmsg_args }, { __NR_setsockopt, "setsockopt", setsockopt_args }, { 0 }, };