bypass4netns
bypass4netns copied to clipboard
Handle socket(2)'s arguments
Some applications call socket(2)
with SOCK_CLOEXEC
or SOCK_NONBLOCK
.
getsockopt(fd, SOL_SOCKET, SO_TYPE, ...)
returns only its actual type SOCK_STREAM
and these flags are ignored.
These flags must be checked and included in host-side socket creation.
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
int main() {
int sock_flags[3] = {SOCK_STREAM, SOCK_STREAM|SOCK_CLOEXEC, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK};
char* sock_flags_str[3] = {"SOCK_STREAM", "SOCK_STREMA|SOCK_CLOEXEC", "SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK"};
for (int i = 0; i < 3; i++) {
int sock_flag = sock_flags[i];
printf("socket %s flags=0x%x\n", sock_flags_str[i], sock_flags[i]);
int sock = socket(AF_INET, sock_flag, 0);
if (sock == -1)
{
perror("socket");
return -1;
}
int opt;
int opt_len = sizeof(opt);
int err = getsockopt(sock, SOL_SOCKET, SO_TYPE, &opt, &opt_len);
if (err == -1)
{
perror("getsockopt");
return -1;
}
printf("SOL_SOCKET SO_TYPE=0x%x\n", opt);
int flags = fcntl(sock, F_GETFD);
printf("F_GETFD flags=0x%x\n", flags);
printf("CLOEXEC=%d\n", (flags & FD_CLOEXEC) > 0);
flags = fcntl(sock, F_GETFL);
printf("F_GETFL flags=0x%x\n", flags);
printf("NON_BLOCK=%d\n", (flags & O_NONBLOCK) > 0);
printf("\n");
close(sock);
}
}
$ ./check_sock
socket SOCK_STREAM flags=0x1
SOL_SOCKET SO_TYPE=0x1
F_GETFD flags=0x0
CLOEXEC=0
F_GETFL flags=0x2
NON_BLOCK=0
socket SOCK_STREMA|SOCK_CLOEXEC flags=0x80001
SOL_SOCKET SO_TYPE=0x1
F_GETFD flags=0x1
CLOEXEC=1
F_GETFL flags=0x2
NON_BLOCK=0
socket SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK flags=0x80801
SOL_SOCKET SO_TYPE=0x1
F_GETFD flags=0x1
CLOEXEC=1
F_GETFL flags=0x802
NON_BLOCK=1