// SPDX-License-Identifier: GPL-2.0/* Copyright(c) 2017 - 2018 Intel Corporation. */ #include <errno.h>#include <getopt.h>#include <libgen.h>#include <net/if.h>#include <stdio.h>#include <stdlib.h>#include <sys/socket.h>#include <sys/un.h>#include <unistd.h> #include <bpf/bpf.h>#include <bpf/xsk.h>#include "xdpsock.h" static const char *opt_if = ""; static struct option long_options[] = { {"interface", required_argument, 0, 'i'}, {0, 0, 0, 0}}; static void usage(const char *prog){ const char *str = " Usage: %s [OPTIONS]\n" " Options:\n" " -i, --interface=n Run on interface n\n" "\n"; fprintf(stderr, "%s\n", str); exit(0);} static void parse_command_line(int argc, char **argv){ int option_index, c; opterr = 0; for (;;) { c = getopt_long(argc, argv, "i:", long_options, &option_index); if (c == -1) break; switch (c) { case 'i': opt_if = optarg; break; default: usage(basename(argv[0])); } }} static int send_xsks_map_fd(int sock, int fd){ char cmsgbuf[CMSG_SPACE(sizeof(int))]; struct msghdr msg; struct iovec iov; int value = 0; if (fd == -1) { fprintf(stderr, "Incorrect fd = %d\n", fd); return -1; } iov.iov_base = &value; iov.iov_len = sizeof(int); msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_flags = 0; msg.msg_control = cmsgbuf; msg.msg_controllen = CMSG_LEN(sizeof(int)); struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(int)); *(int *)CMSG_DATA(cmsg) = fd; int ret = sendmsg(sock, &msg, 0); if (ret == -1) { fprintf(stderr, "Sendmsg failed with %s", strerror(errno)); return -errno; } return ret;} intmain(int argc, char **argv){ struct sockaddr_un server; int listening = 1; int rval, msgsock; int ifindex = 0; int flag = 1; int cmd = 0; int sock; int err; int xsks_map_fd; parse_command_line(argc, argv); ifindex = if_nametoindex(opt_if); if (ifindex == 0) { fprintf(stderr, "Unable to get ifindex for Interface %s. Reason:%s", opt_if, strerror(errno)); return -errno; } sock = socket(AF_UNIX, SOCK_STREAM, 0); if (sock < 0) { fprintf(stderr, "Opening socket stream failed: %s", strerror(errno)); return -errno; } server.sun_family = AF_UNIX; strcpy(server.sun_path, SOCKET_NAME); setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(int)); if (bind(sock, (struct sockaddr *)&server, sizeof(struct sockaddr_un))) { fprintf(stderr, "Binding to socket stream failed: %s", strerror(errno)); return -errno; } listen(sock, MAX_NUM_OF_CLIENTS); err = xsk_setup_xdp_prog(ifindex, &xsks_map_fd); if (err) { fprintf(stderr, "Setup of xdp program failed\n"); goto close_sock; } while (listening) { msgsock = accept(sock, 0, 0); if (msgsock == -1) { fprintf(stderr, "Error accepting connection: %s", strerror(errno)); err = -errno; goto close_sock; } err = send_xsks_map_fd(msgsock, xsks_map_fd); if (err <= 0) { fprintf(stderr, "Error %d sending xsks_map_fd\n", err); goto cleanup; } do { rval = read(msgsock, &cmd, sizeof(int)); if (rval < 0) { fprintf(stderr, "Error reading stream message"); } else { if (cmd != CLOSE_CONN) fprintf(stderr, "Recv unknown cmd = %d\n", cmd); listening = 0; break; } } while (rval > 0); } close(msgsock); close(sock); unlink(SOCKET_NAME); /* Unset fd for given ifindex */ err = bpf_set_link_xdp_fd(ifindex, -1, 0); if (err) { fprintf(stderr, "Error when unsetting bpf prog_fd for ifindex(%d)\n", ifindex); return err; } return 0; cleanup: close(msgsock);close_sock: close(sock); unlink(SOCKET_NAME); return err;}
// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2017 - 2018 Intel Corporation. */
#include <errno.h>
#include <getopt.h>
#include <libgen.h>
#include <net/if.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <bpf/bpf.h>
#include <bpf/xsk.h>
#include "xdpsock.h"
static const char *opt_if = "";
static struct option long_options[] = {
{"interface", required_argument, 0, 'i'},
{0, 0, 0, 0}
};
static void usage(const char *prog)
{
const char *str =
" Usage: %s [OPTIONS]\n"
" Options:\n"
" -i, --interface=n Run on interface n\n"
"\n";
fprintf(stderr, "%s\n", str);
exit(0);
}
static void parse_command_line(int argc, char **argv)
{
int option_index, c;
opterr = 0;
for (;;) {
c = getopt_long(argc, argv, "i:",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'i':
opt_if = optarg;
break;
default:
usage(basename(argv[0]));
}
}
}
static int send_xsks_map_fd(int sock, int fd)
{
char cmsgbuf[CMSG_SPACE(sizeof(int))];
struct msghdr msg;
struct iovec iov;
int value = 0;
if (fd == -1) {
fprintf(stderr, "Incorrect fd = %d\n", fd);
return -1;
}
iov.iov_base = &value;
iov.iov_len = sizeof(int);
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_flags = 0;
msg.msg_control = cmsgbuf;
msg.msg_controllen = CMSG_LEN(sizeof(int));
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
*(int *)CMSG_DATA(cmsg) = fd;
int ret = sendmsg(sock, &msg, 0);
if (ret == -1) {
fprintf(stderr, "Sendmsg failed with %s", strerror(errno));
return -errno;
}
return ret;
}
int
main(int argc, char **argv)
{
struct sockaddr_un server;
int listening = 1;
int rval, msgsock;
int ifindex = 0;
int flag = 1;
int cmd = 0;
int sock;
int err;
int xsks_map_fd;
parse_command_line(argc, argv);
ifindex = if_nametoindex(opt_if);
if (ifindex == 0) {
fprintf(stderr, "Unable to get ifindex for Interface %s. Reason:%s",
opt_if, strerror(errno));
return -errno;
}
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
fprintf(stderr, "Opening socket stream failed: %s", strerror(errno));
return -errno;
}
server.sun_family = AF_UNIX;
strcpy(server.sun_path, SOCKET_NAME);
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(int));
if (bind(sock, (struct sockaddr *)&server, sizeof(struct sockaddr_un))) {
fprintf(stderr, "Binding to socket stream failed: %s", strerror(errno));
return -errno;
}
listen(sock, MAX_NUM_OF_CLIENTS);
err = xsk_setup_xdp_prog(ifindex, &xsks_map_fd);
if (err) {
fprintf(stderr, "Setup of xdp program failed\n");
goto close_sock;
}
while (listening) {
msgsock = accept(sock, 0, 0);
if (msgsock == -1) {
fprintf(stderr, "Error accepting connection: %s", strerror(errno));
err = -errno;
goto close_sock;
}
err = send_xsks_map_fd(msgsock, xsks_map_fd);
if (err <= 0) {
fprintf(stderr, "Error %d sending xsks_map_fd\n", err);
goto cleanup;
}
do {
rval = read(msgsock, &cmd, sizeof(int));
if (rval < 0) {
fprintf(stderr, "Error reading stream message");
} else {
if (cmd != CLOSE_CONN)
fprintf(stderr, "Recv unknown cmd = %d\n", cmd);
listening = 0;
break;
}
} while (rval > 0);
}
close(msgsock);
close(sock);
unlink(SOCKET_NAME);
/* Unset fd for given ifindex */
err = bpf_set_link_xdp_fd(ifindex, -1, 0);
if (err) {
fprintf(stderr, "Error when unsetting bpf prog_fd for ifindex(%d)\n", ifindex);
return err;
}
return 0;
cleanup:
close(msgsock);
close_sock:
close(sock);
unlink(SOCKET_NAME);
return err;
}