Page MenuHomeFreeBSD
Paste P534

linux_msg_peek.c
ActivePublic

Authored by melifaro on Jan 8 2022, 1:47 PM.
Tags
None
Referenced Files
F34960145: linux_msg_peek.c
Jan 8 2022, 1:47 PM
Subscribers
None
/*
*
*/
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <assert.h>
struct sd {
int family;
int type;
int proto;
struct sockaddr *sa;
int sa_len;
};
static int
bind_socket(struct sd *sd)
{
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
int error, s;
s = socket(sd->family, sd->type, sd->proto);
printf("socket(%d,%d,%d) -> %d | %s\n", sd->family, sd->type, sd->proto, s, strerror(errno));
for (int i = 0; i < 10; i++) {
int port = htons(32768 + random() % 4096);
error = 0;
switch (sd->family) {
case AF_INET:
sin = (struct sockaddr_in *)sd->sa;
memset(sin, 0, sizeof(struct sockaddr_in));
sin->sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", &sin->sin_addr);
sin->sin_port = htons(port);
sd->sa_len = sizeof(struct sockaddr_in);
break;
case AF_INET6:
sin6 = (struct sockaddr_in6 *)sd->sa;
memset(sin6, 0, sizeof(struct sockaddr_in6));
sin6->sin6_family = AF_INET6;
inet_pton(AF_INET6, "::1", &sin6->sin6_addr);
sin6->sin6_port = htons(port);
sd->sa_len = sizeof(struct sockaddr_in6);
break;
}
error = bind(s, sd->sa, sd->sa_len);
printf("bind(fd#%d) -> %d | %s\n", s, error, strerror(errno));
if (error != EADDRINUSE)
break;
}
if (error != 0) {
close(s);
return (0);
}
return (s);
}
static void
test_msg_peek_sd(int s, struct sd *sd)
{
int c = socket(sd->family, sd->type, sd->proto);
int databuf_len = 1024;
char *databuf = malloc(databuf_len);
memset(databuf, 0xFF, databuf_len);
char *rxbuf = malloc(databuf_len);
memset(databuf, 0, databuf_len);
int peek_len = 128;
memset(databuf, 0xEE, peek_len);
int len;
len = sendto(c, databuf, databuf_len, 0, sd->sa, sd->sa_len);
printf("sendto(fd#%d) -> %d\n", c, len);
char sabuf[32];
struct iovec iov = {
.iov_base = rxbuf,
.iov_len = peek_len,
};
struct msghdr msg = {
.msg_name = sabuf,
.msg_namelen = sizeof(sabuf),
.msg_iov = &iov,
.msg_iovlen = 1,
};
errno = 0;
len = recvmsg(s, &msg, MSG_PEEK);
printf("recvmsg(fd#%d) -> %d | errno %s\n", s, len, strerror(errno));
assert(len == peek_len);
assert(memcmp(rxbuf, databuf, len) == 0);
iov.iov_len = databuf_len;
len = recvmsg(s, &msg, 0);
printf("recvmsg(fd#%d) -> %d | errno %s\n", s, len, strerror(errno));
assert(len == databuf_len);
assert(memcmp(rxbuf, databuf, len) == 0);
free(databuf);
free(rxbuf);
}
static void
test_msg_peek()
{
char sa_buffer[32];
struct sd sd = {
.family = AF_INET,
.type = SOCK_DGRAM,
.proto = IPPROTO_UDP,
.sa = (struct sockaddr *)sa_buffer,
};
int s = bind_socket(&sd);
test_msg_peek_sd(s, &sd);
}
int main()
{
test_msg_peek();
return (0);
}