Why is netcat unable to receive the second broadcast message?
Asked Answered
B

1

11

While experimenting with broadcast messages (on a Debian 8.3 VM running on VirtualBox 5.0.14 on a Windows 7 laptop) I found that netcat (nc) receives only the first broadcast message. It does not receive the second broadcast message.

Programs

Here is the client program.

// client.c
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>

int main()
{
    int sockfd;
    int ret;
    char buffer[1024];
    ssize_t bytes;
    int yes = 1;
    struct addrinfo hints, *ai, *aii;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_DGRAM;

    if ((ret = getaddrinfo("255.255.255.255", "9090", &hints, &ai)) == -1) {
        fprintf(stderr, "client: getaddrinfo() error: %s\n", gai_strerror(ret));
        return EXIT_FAILURE;
    }

    for (aii = ai; aii != NULL; aii = aii->ai_next) {
        sockfd = socket(aii->ai_family, aii->ai_socktype, aii->ai_protocol);
        if (sockfd == -1) {
            perror("client: socket()");
            continue;
        }
        break;
    }

    freeaddrinfo(ai);

    if (aii == NULL) {
        fprintf(stderr, "client: cannot create socket\n");
        return EXIT_FAILURE;
    }

    if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &yes, sizeof yes) == -1) {
        perror("client: setsockopt()");
        return EXIT_FAILURE;
    }

    // 1st sendto().
    strncpy(buffer, "hello from client\n", sizeof buffer);
    bytes = sendto(sockfd, buffer, strlen(buffer), 0,
                   aii->ai_addr, aii->ai_addrlen);
    printf("client: sent %jd bytes\n", (intmax_t) bytes);

    // 2nd sendto().
    strncpy(buffer, "bye from client\n", sizeof buffer);
    bytes = sendto(sockfd, buffer, strlen(buffer), 0,
                   aii->ai_addr, aii->ai_addrlen);
    printf("client: sent %jd bytes\n", (intmax_t) bytes);

    close(sockfd);
    return EXIT_SUCCESS;
}

Here is the server program.

// server.c
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>

int main()
{
    int sockfd;
    int ret;
    struct addrinfo hints, *ai, *aii;
    char ip[INET_ADDRSTRLEN];
    struct sockaddr_in *sa;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_DGRAM;
    hints.ai_flags = AI_PASSIVE;

    if ((ret = getaddrinfo(NULL, "9090", &hints, &ai)) == -1) {
        fprintf(stderr, "server: getaddrinfo() error: %s\n", gai_strerror(ret));
        return EXIT_FAILURE;
    }

    for (aii = ai; aii != NULL; aii = aii->ai_next) {

        sockfd = socket(aii->ai_family, aii->ai_socktype, aii->ai_protocol);
        if (sockfd == -1) {
            perror("socket()");
            continue;
        }

        if (bind(sockfd, aii->ai_addr, aii->ai_addrlen) == -1) {
            perror("bind()");
            close(sockfd);
            continue;
        }

        break;
    }

    if (aii == NULL) {
        fprintf(stderr, "server: error: could not bind to any address\n");
        return EXIT_FAILURE;
    }

    sa = (struct sockaddr_in *) aii->ai_addr;
    inet_ntop(AF_INET, &sa->sin_addr, ip, sizeof ip);
    printf("Bound to %s:%d.\n", ip, ntohs(sa->sin_port));

    freeaddrinfo(ai);

    /* recvfrom() loop */
    while (1) {
        struct sockaddr_storage conn_addr;
        socklen_t conn_addrlen = sizeof conn_addr;
        char buffer[1024];
        ssize_t bytes;

        bytes = recvfrom(sockfd, buffer, sizeof buffer, 0,
                         (struct sockaddr *) &conn_addr, &conn_addrlen);

        if (bytes <= 0)
            break;

        sa = (struct sockaddr_in *) &conn_addr;
        inet_ntop(AF_INET, &sa->sin_addr, ip, sizeof ip);

        printf("server: recvfrom() %jd bytes from %s:%d: %.*s",
               (intmax_t) bytes, ip, ntohs(sa->sin_port), (int) bytes,
               buffer);
    }

    close(sockfd);
    return EXIT_FAILURE;
}

The programs were compiled.

gcc -std=c99 -pedantic -Wall -Wextra -D_POSIX_C_SOURCE=200112L client.c -o client
gcc -std=c99 -pedantic -Wall -Wextra -D_POSIX_C_SOURCE=200112L server.c -o server

Experiment 1: client => server (broadcast)

The client program shows the following output.

$ ./client
client: sent 18 bytes
client: sent 16 bytes

Both broadcast messages are received by the server program.

$ ./server 
Bound to 0.0.0.0:9090.
server: recvfrom() 18 bytes from 10.0.2.15:45807: hello from client
server: recvfrom() 16 bytes from 10.0.2.15:45807: bye from client

Experiment 2: client => nc (broadcast)

However, if netcat is run instead as the listener on port 9090, it receives only the first broadcast message.

Here is the output from the client program.

$ ./client
client: sent 18 bytes
client: sent 16 bytes

The server program does not receive the second broadcast message.

$ nc -vvnulp 9090
listening on [any] 9090 ...
connect to [10.0.2.15] from (UNKNOWN) [10.0.2.15] 39126
hello from client

Experiment 3: client => nc (unicast)

Next the client program client.c is modified to create a new program client2.c such that it does unicast.

$ diff -u client.c client2.c
--- client.c    2016-10-22 16:13:46.637123187 +0530
+++ client2.c   2016-10-22 16:13:41.313123187 +0530
@@ -16,14 +16,13 @@
     int ret;
     char buffer[1024];
     ssize_t bytes;
-    int yes = 1;
     struct addrinfo hints, *ai, *aii;

     memset(&hints, 0, sizeof hints);
     hints.ai_family = AF_INET;
     hints.ai_socktype = SOCK_DGRAM;

-    if ((ret = getaddrinfo("255.255.255.255", "9090", &hints, &ai)) == -1) {
+    if ((ret = getaddrinfo("10.0.2.15", "9090", &hints, &ai)) == -1) {
         fprintf(stderr, "client: getaddrinfo() error: %s\n", gai_strerror(ret));
         return EXIT_FAILURE;
     }
@@ -44,11 +43,6 @@
         return EXIT_FAILURE;
     }

-    if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &yes, sizeof yes) == -1) {
-        perror("client: setsockopt()");
-        return EXIT_FAILURE;
-    }
-
     // 1st sendto().
     strncpy(buffer, "hello from client\n", sizeof buffer);
     bytes = sendto(sockfd, buffer, strlen(buffer), 0,

Here is the output from the client program.

$ gcc -std=c99 -pedantic -Wall -Wextra -D_POSIX_C_SOURCE=200112L client2.c -o client2
$ ./client2 
client: sent 18 bytes
client: sent 16 bytes

This time netcat receives both unicast messages.

$ nc -vvnulp 9090                                                                                                                                   
listening on [any] 9090 ...
connect to [10.0.2.15] from (UNKNOWN) [10.0.2.15] 55522
hello from client
bye from client

System Call Trace

Here is the system call trace for netcat in experiment 2.

$ strace nc -vvnulp 9090
execve("/bin/nc", ["nc", "-vvnulp", "9090"], [/* 39 vars */]) = 0
brk(0)                                  = 0xc19000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2fcd7ed000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=76016, ...}) = 0
mmap(NULL, 76016, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f2fcd7da000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\34\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1738176, ...}) = 0
mmap(NULL, 3844640, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f2fcd224000
mprotect(0x7f2fcd3c6000, 2093056, PROT_NONE) = 0
mmap(0x7f2fcd5c5000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1a1000) = 0x7f2fcd5c5000
mmap(0x7f2fcd5cb000, 14880, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f2fcd5cb000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2fcd7d9000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2fcd7d8000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2fcd7d7000
arch_prctl(ARCH_SET_FS, 0x7f2fcd7d8700) = 0
mprotect(0x7f2fcd5c5000, 16384, PROT_READ) = 0
mprotect(0x605000, 4096, PROT_READ)     = 0
mprotect(0x7f2fcd7ef000, 4096, PROT_READ) = 0
munmap(0x7f2fcd7da000, 76016)           = 0
getpid()                                = 4161
brk(0)                                  = 0xc19000
brk(0xc3a000)                           = 0xc3a000
open("/etc/resolv.conf", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=248, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2fcd7ec000
read(3, "# Generated by NetworkManager\nna"..., 4096) = 248
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0x7f2fcd7ec000, 4096)            = 0
uname({sys="Linux", node="debian1", ...}) = 0
rt_sigaction(SIGINT, {0x4025d0, [INT], SA_RESTORER|SA_RESTART, 0x7f2fcd2590e0}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGQUIT, {0x4025d0, [QUIT], SA_RESTORER|SA_RESTART, 0x7f2fcd2590e0}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGTERM, {0x4025d0, [TERM], SA_RESTORER|SA_RESTART, 0x7f2fcd2590e0}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGURG, {SIG_IGN, [URG], SA_RESTORER|SA_RESTART, 0x7f2fcd2590e0}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7f2fcd2590e0}, {SIG_DFL, [], 0}, 8) = 0
socket(PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
connect(3, {sa_family=AF_LOCAL, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
close(3)                                = 0
socket(PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
connect(3, {sa_family=AF_LOCAL, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
close(3)                                = 0
open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=529, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2fcd7ec000
read(3, "# /etc/nsswitch.conf\n#\n# Example"..., 4096) = 529
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0x7f2fcd7ec000, 4096)            = 0
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=76016, ...}) = 0
mmap(NULL, 76016, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f2fcd7da000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/tls/x86_64/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/lib/x86_64-linux-gnu/tls/x86_64", 0x7ffe5c622430) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/tls/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/lib/x86_64-linux-gnu/tls", 0x7ffe5c622430) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/x86_64/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/lib/x86_64-linux-gnu/x86_64", 0x7ffe5c622430) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/lib/x86_64-linux-gnu", {st_mode=S_IFDIR|0755, st_size=12288, ...}) = 0
open("/usr/lib/x86_64-linux-gnu/tls/x86_64/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/x86_64-linux-gnu/tls/x86_64", 0x7ffe5c622430) = -1 ENOENT (No such file or directory)
open("/usr/lib/x86_64-linux-gnu/tls/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/x86_64-linux-gnu/tls", 0x7ffe5c622430) = -1 ENOENT (No such file or directory)
open("/usr/lib/x86_64-linux-gnu/x86_64/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/x86_64-linux-gnu/x86_64", 0x7ffe5c622430) = -1 ENOENT (No such file or directory)
open("/usr/lib/x86_64-linux-gnu/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/x86_64-linux-gnu", {st_mode=S_IFDIR|0755, st_size=49152, ...}) = 0
open("/lib/tls/x86_64/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/lib/tls/x86_64", 0x7ffe5c622430) = -1 ENOENT (No such file or directory)
open("/lib/tls/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/lib/tls", 0x7ffe5c622430)        = -1 ENOENT (No such file or directory)
open("/lib/x86_64/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/lib/x86_64", 0x7ffe5c622430)     = -1 ENOENT (No such file or directory)
open("/lib/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/lib", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
open("/usr/lib/tls/x86_64/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/tls/x86_64", 0x7ffe5c622430) = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/tls", 0x7ffe5c622430)    = -1 ENOENT (No such file or directory)
open("/usr/lib/x86_64/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/x86_64", 0x7ffe5c622430) = -1 ENOENT (No such file or directory)
open("/usr/lib/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib", {st_mode=S_IFDIR|0755, st_size=12288, ...}) = 0
munmap(0x7f2fcd7da000, 76016)           = 0
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=76016, ...}) = 0
mmap(NULL, 76016, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f2fcd7da000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\240\"\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=47712, ...}) = 0
mmap(NULL, 2144392, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f2fcd018000
mprotect(0x7f2fcd023000, 2093056, PROT_NONE) = 0
mmap(0x7f2fcd222000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xa000) = 0x7f2fcd222000
close(3)                                = 0
mprotect(0x7f2fcd222000, 4096, PROT_READ) = 0
munmap(0x7f2fcd7da000, 76016)           = 0
open("/etc/services", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=19605, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2fcd7ec000
read(3, "# Network services, Internet sty"..., 4096) = 4096
read(3, "\t\t# IPX\nipx\t\t213/udp\nimap3\t\t220/"..., 4096) = 4096
read(3, "nessus\t\t1241/tcp\t\t\t# Nessus vuln"..., 4096) = 4096
read(3, "347/tcp\t\t\t# gnutella\ngnutella-rt"..., 4096) = 4096
read(3, "ureg\t779/udp\t\tmoira_ureg\t# Moira"..., 4096) = 3221
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0x7f2fcd7ec000, 4096)            = 0
socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP) = 3
setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
setsockopt(3, SOL_SOCKET, SO_REUSEPORT, [1], 4) = 0
bind(3, {sa_family=AF_INET, sin_port=htons(9090), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
getsockname(3, {sa_family=AF_INET, sin_port=htons(9090), sin_addr=inet_addr("0.0.0.0")}, [16]) = 0
write(2, "listening on [any] 9090 ...", 27listening on [any] 9090 ...) = 27
write(2, "\n", 1
)                       = 1
rt_sigaction(SIGALRM, {SIG_IGN, [ALRM], SA_RESTORER|SA_RESTART, 0x7f2fcd2590e0}, {SIG_DFL, [], 0}, 8) = 0
alarm(0)                                = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
recvfrom(3, "hello from client\n", 8192, MSG_PEEK, {sa_family=AF_INET, sin_port=htons(44926), sin_addr=inet_addr("10.0.2.15")}, [16]) = 18
rt_sigaction(SIGALRM, {SIG_IGN, [ALRM], SA_RESTORER|SA_RESTART, 0x7f2fcd2590e0}, {SIG_IGN, [ALRM], SA_RESTORER|SA_RESTART, 0x7f2fcd2590e0}, 8) = 0
alarm(0)                                = 0
connect(3, {sa_family=AF_INET, sin_port=htons(44926), sin_addr=inet_addr("10.0.2.15")}, 16) = 0
getsockopt(3, SOL_IP, IP_OPTIONS, "", [0]) = 0
getsockname(3, {sa_family=AF_INET, sin_port=htons(9090), sin_addr=inet_addr("10.0.2.15")}, [16]) = 0
write(2, "connect to [10.0.2.15] from (UNK"..., 55connect to [10.0.2.15] from (UNKNOWN) [10.0.2.15] 44926) = 55
write(2, "\n", 1
)                       = 1
select(4, [0 3], NULL, NULL, NULL)      = 1 (in [3])
read(3, "hello from client\n", 8192)    = 18
write(1, "hello from client\n", 18hello from client
)     = 18
select(4, [0 3], NULL, NULL, NULL

Here is the system call trace for netcat in experiment 3.

$ strace nc -vvnulp 9090
execve("/bin/nc", ["nc", "-vvnulp", "9090"], [/* 39 vars */]) = 0
brk(0)                                  = 0x198e000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fcec1035000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=76016, ...}) = 0
mmap(NULL, 76016, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fcec1022000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\34\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1738176, ...}) = 0
mmap(NULL, 3844640, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fcec0a6c000
mprotect(0x7fcec0c0e000, 2093056, PROT_NONE) = 0
mmap(0x7fcec0e0d000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1a1000) = 0x7fcec0e0d000
mmap(0x7fcec0e13000, 14880, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fcec0e13000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fcec1021000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fcec1020000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fcec101f000
arch_prctl(ARCH_SET_FS, 0x7fcec1020700) = 0
mprotect(0x7fcec0e0d000, 16384, PROT_READ) = 0
mprotect(0x605000, 4096, PROT_READ)     = 0
mprotect(0x7fcec1037000, 4096, PROT_READ) = 0
munmap(0x7fcec1022000, 76016)           = 0
getpid()                                = 4181
brk(0)                                  = 0x198e000
brk(0x19af000)                          = 0x19af000
open("/etc/resolv.conf", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=248, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fcec1034000
read(3, "# Generated by NetworkManager\nna"..., 4096) = 248
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0x7fcec1034000, 4096)            = 0
uname({sys="Linux", node="debian1", ...}) = 0
rt_sigaction(SIGINT, {0x4025d0, [INT], SA_RESTORER|SA_RESTART, 0x7fcec0aa10e0}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGQUIT, {0x4025d0, [QUIT], SA_RESTORER|SA_RESTART, 0x7fcec0aa10e0}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGTERM, {0x4025d0, [TERM], SA_RESTORER|SA_RESTART, 0x7fcec0aa10e0}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGURG, {SIG_IGN, [URG], SA_RESTORER|SA_RESTART, 0x7fcec0aa10e0}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [PIPE], SA_RESTORER|SA_RESTART, 0x7fcec0aa10e0}, {SIG_DFL, [], 0}, 8) = 0
socket(PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
connect(3, {sa_family=AF_LOCAL, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
close(3)                                = 0
socket(PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
connect(3, {sa_family=AF_LOCAL, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
close(3)                                = 0
open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=529, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fcec1034000
read(3, "# /etc/nsswitch.conf\n#\n# Example"..., 4096) = 529
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0x7fcec1034000, 4096)            = 0
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=76016, ...}) = 0
mmap(NULL, 76016, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fcec1022000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/tls/x86_64/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/lib/x86_64-linux-gnu/tls/x86_64", 0x7ffcde8fa140) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/tls/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/lib/x86_64-linux-gnu/tls", 0x7ffcde8fa140) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/x86_64/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/lib/x86_64-linux-gnu/x86_64", 0x7ffcde8fa140) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/lib/x86_64-linux-gnu", {st_mode=S_IFDIR|0755, st_size=12288, ...}) = 0
open("/usr/lib/x86_64-linux-gnu/tls/x86_64/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/x86_64-linux-gnu/tls/x86_64", 0x7ffcde8fa140) = -1 ENOENT (No such file or directory)
open("/usr/lib/x86_64-linux-gnu/tls/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/x86_64-linux-gnu/tls", 0x7ffcde8fa140) = -1 ENOENT (No such file or directory)
open("/usr/lib/x86_64-linux-gnu/x86_64/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/x86_64-linux-gnu/x86_64", 0x7ffcde8fa140) = -1 ENOENT (No such file or directory)
open("/usr/lib/x86_64-linux-gnu/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/x86_64-linux-gnu", {st_mode=S_IFDIR|0755, st_size=49152, ...}) = 0
open("/lib/tls/x86_64/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/lib/tls/x86_64", 0x7ffcde8fa140) = -1 ENOENT (No such file or directory)
open("/lib/tls/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/lib/tls", 0x7ffcde8fa140)        = -1 ENOENT (No such file or directory)
open("/lib/x86_64/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/lib/x86_64", 0x7ffcde8fa140)     = -1 ENOENT (No such file or directory)
open("/lib/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/lib", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
open("/usr/lib/tls/x86_64/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/tls/x86_64", 0x7ffcde8fa140) = -1 ENOENT (No such file or directory)
open("/usr/lib/tls/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/tls", 0x7ffcde8fa140)    = -1 ENOENT (No such file or directory)
open("/usr/lib/x86_64/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/x86_64", 0x7ffcde8fa140) = -1 ENOENT (No such file or directory)
open("/usr/lib/libnss_db.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib", {st_mode=S_IFDIR|0755, st_size=12288, ...}) = 0
munmap(0x7fcec1022000, 76016)           = 0
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=76016, ...}) = 0
mmap(NULL, 76016, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fcec1022000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\240\"\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=47712, ...}) = 0
mmap(NULL, 2144392, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fcec0860000
mprotect(0x7fcec086b000, 2093056, PROT_NONE) = 0
mmap(0x7fcec0a6a000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xa000) = 0x7fcec0a6a000
close(3)                                = 0
mprotect(0x7fcec0a6a000, 4096, PROT_READ) = 0
munmap(0x7fcec1022000, 76016)           = 0
open("/etc/services", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=19605, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fcec1034000
read(3, "# Network services, Internet sty"..., 4096) = 4096
read(3, "\t\t# IPX\nipx\t\t213/udp\nimap3\t\t220/"..., 4096) = 4096
read(3, "nessus\t\t1241/tcp\t\t\t# Nessus vuln"..., 4096) = 4096
read(3, "347/tcp\t\t\t# gnutella\ngnutella-rt"..., 4096) = 4096
read(3, "ureg\t779/udp\t\tmoira_ureg\t# Moira"..., 4096) = 3221
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0x7fcec1034000, 4096)            = 0
socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP) = 3
setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
setsockopt(3, SOL_SOCKET, SO_REUSEPORT, [1], 4) = 0
bind(3, {sa_family=AF_INET, sin_port=htons(9090), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
getsockname(3, {sa_family=AF_INET, sin_port=htons(9090), sin_addr=inet_addr("0.0.0.0")}, [16]) = 0
write(2, "listening on [any] 9090 ...", 27listening on [any] 9090 ...) = 27
write(2, "\n", 1
)                       = 1
rt_sigaction(SIGALRM, {SIG_IGN, [ALRM], SA_RESTORER|SA_RESTART, 0x7fcec0aa10e0}, {SIG_DFL, [], 0}, 8) = 0
alarm(0)                                = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
recvfrom(3, "hello from client\n", 8192, MSG_PEEK, {sa_family=AF_INET, sin_port=htons(50392), sin_addr=inet_addr("10.0.2.15")}, [16]) = 18
rt_sigaction(SIGALRM, {SIG_IGN, [ALRM], SA_RESTORER|SA_RESTART, 0x7fcec0aa10e0}, {SIG_IGN, [ALRM], SA_RESTORER|SA_RESTART, 0x7fcec0aa10e0}, 8) = 0
alarm(0)                                = 0
connect(3, {sa_family=AF_INET, sin_port=htons(50392), sin_addr=inet_addr("10.0.2.15")}, 16) = 0
getsockopt(3, SOL_IP, IP_OPTIONS, "", [0]) = 0
getsockname(3, {sa_family=AF_INET, sin_port=htons(9090), sin_addr=inet_addr("10.0.2.15")}, [16]) = 0
write(2, "connect to [10.0.2.15] from (UNK"..., 55connect to [10.0.2.15] from (UNKNOWN) [10.0.2.15] 50392) = 55
write(2, "\n", 1
)                       = 1
select(4, [0 3], NULL, NULL, NULL)      = 1 (in [3])
read(3, "hello from client\n", 8192)    = 18
write(1, "hello from client\n", 18hello from client
)     = 18
select(4, [0 3], NULL, NULL, NULL)      = 1 (in [3])
read(3, "bye from client\n", 8192)      = 16
write(1, "bye from client\n", 16bye from client
)       = 16
select(4, [0 3], NULL, NULL, NULL

Question

Why doesn't netcat receive both broadcast messages in experiment 2?

Brusque answered 22/10, 2016 at 17:20 Comment(2)
Please state whether @bjorn-a's answer solves your problemEnhance
@BodoThiesen Bjorn's answer did not work for me in my environment. I have added a comment to his answer to note this.Brusque
I
4

Below is a modified copy of your client program. I added a few missing include-statements, removed some casts, added more error checking, and, the important change, moved the call to freeaddrinfo() down. A lot. The aii pointer, which pointed into ai, was used in the calls to sendto(), that's not a good idea.

Now netcat sees both messages sent, at least on my machine, which runs Fedora 24. The original client program actually reported an error on the second call to sendto().

HTH

PS: Cudos for a very well formulated question.

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{
    int sockfd;
    int ret;
    ssize_t bytes;
    int yes = 1;
    struct addrinfo hints, *ai, *aii;
    char *msg;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_DGRAM;

    if ((ret = getaddrinfo("255.255.255.255", "9090", &hints, &ai)) == -1) {
        fprintf(stderr, "client: getaddrinfo() error: %s\n", gai_strerror(ret));
        return EXIT_FAILURE;
    }

    for (aii = ai; aii != NULL; aii = aii->ai_next) {
        sockfd = socket(aii->ai_family, aii->ai_socktype, aii->ai_protocol);
        if (sockfd == -1) {
            perror("client: socket()");
            continue;
        }
        break;
    }

    if (aii == NULL) {
        fprintf(stderr, "client: cannot create socket\n");
        return EXIT_FAILURE;
    }

    if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &yes, sizeof yes) == -1) {
        perror("client: setsockopt()");
        return EXIT_FAILURE;
    }

    // 1st sendto().
    msg = "hello from client\n";
    bytes = sendto(sockfd, msg, strlen(msg), 0, aii->ai_addr, aii->ai_addrlen);
    if (bytes == -1) {
        perror("sendto 1");
        return EXIT_FAILURE;
    }
    printf("client: sent %zd bytes\n", bytes);

    // 2nd sendto().
    msg = "bye from client\n";
    bytes = sendto(sockfd, msg, strlen(msg), 0, aii->ai_addr, aii->ai_addrlen);
    if (bytes == -1) {
        perror("sendto 2");
        return EXIT_FAILURE;
    }

    printf("client: sent %zd bytes\n", bytes);

    close(sockfd);
    freeaddrinfo(ai);
    return EXIT_SUCCESS;
}
Idler answered 26/10, 2016 at 15:11 Comment(2)
Thank you for the detailed answer. I copied your program to a file named foo.c and ran gcc -std=c99 -pedantic -Wall -Wextra -D_POSIX_C_SOURCE=200112L foo.c && ./a.out while nc -vvnulp 9090 was already running on another terminal. Althought ./a.out shows that two messages are sent, nc shows that only the first message is received. So this solution did not work for me on my Debian 8.3 VM running on VirtualBox 5.0.14 on a Windows 7 laptop.Brusque
I have awarded the bounty to your answer because your answer is well written and addresses the problem for your specific environment (Fedora 24). However, I am leaving my question as unanswered, so that someone who stumbles upon this question is encouraged to post an answer that addresses the problem for my specific environment (Debian 8.3). I may start another bounty for this question in future.Brusque

© 2022 - 2024 — McMap. All rights reserved.