162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#include <stdio.h> 362306a36Sopenharmony_ci#include <assert.h> 462306a36Sopenharmony_ci#include <unistd.h> 562306a36Sopenharmony_ci#include <bpf/bpf.h> 662306a36Sopenharmony_ci#include <bpf/libbpf.h> 762306a36Sopenharmony_ci#include <sys/socket.h> 862306a36Sopenharmony_ci#include <netinet/in.h> 962306a36Sopenharmony_ci#include <arpa/inet.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ciint main(int ac, char **argv) 1262306a36Sopenharmony_ci{ 1362306a36Sopenharmony_ci struct sockaddr_in *serv_addr_in, *mapped_addr_in, *tmp_addr_in; 1462306a36Sopenharmony_ci struct sockaddr serv_addr, mapped_addr, tmp_addr; 1562306a36Sopenharmony_ci int serverfd, serverconnfd, clientfd, map_fd; 1662306a36Sopenharmony_ci struct bpf_link *link = NULL; 1762306a36Sopenharmony_ci struct bpf_program *prog; 1862306a36Sopenharmony_ci struct bpf_object *obj; 1962306a36Sopenharmony_ci socklen_t sockaddr_len; 2062306a36Sopenharmony_ci char filename[256]; 2162306a36Sopenharmony_ci char *ip; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci serv_addr_in = (struct sockaddr_in *)&serv_addr; 2462306a36Sopenharmony_ci mapped_addr_in = (struct sockaddr_in *)&mapped_addr; 2562306a36Sopenharmony_ci tmp_addr_in = (struct sockaddr_in *)&tmp_addr; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci snprintf(filename, sizeof(filename), "%s.bpf.o", argv[0]); 2862306a36Sopenharmony_ci obj = bpf_object__open_file(filename, NULL); 2962306a36Sopenharmony_ci if (libbpf_get_error(obj)) { 3062306a36Sopenharmony_ci fprintf(stderr, "ERROR: opening BPF object file failed\n"); 3162306a36Sopenharmony_ci return 0; 3262306a36Sopenharmony_ci } 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci prog = bpf_object__find_program_by_name(obj, "bpf_prog1"); 3562306a36Sopenharmony_ci if (libbpf_get_error(prog)) { 3662306a36Sopenharmony_ci fprintf(stderr, "ERROR: finding a prog in obj file failed\n"); 3762306a36Sopenharmony_ci goto cleanup; 3862306a36Sopenharmony_ci } 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci /* load BPF program */ 4162306a36Sopenharmony_ci if (bpf_object__load(obj)) { 4262306a36Sopenharmony_ci fprintf(stderr, "ERROR: loading BPF object file failed\n"); 4362306a36Sopenharmony_ci goto cleanup; 4462306a36Sopenharmony_ci } 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci map_fd = bpf_object__find_map_fd_by_name(obj, "dnat_map"); 4762306a36Sopenharmony_ci if (map_fd < 0) { 4862306a36Sopenharmony_ci fprintf(stderr, "ERROR: finding a map in obj file failed\n"); 4962306a36Sopenharmony_ci goto cleanup; 5062306a36Sopenharmony_ci } 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci link = bpf_program__attach(prog); 5362306a36Sopenharmony_ci if (libbpf_get_error(link)) { 5462306a36Sopenharmony_ci fprintf(stderr, "ERROR: bpf_program__attach failed\n"); 5562306a36Sopenharmony_ci link = NULL; 5662306a36Sopenharmony_ci goto cleanup; 5762306a36Sopenharmony_ci } 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci assert((serverfd = socket(AF_INET, SOCK_STREAM, 0)) > 0); 6062306a36Sopenharmony_ci assert((clientfd = socket(AF_INET, SOCK_STREAM, 0)) > 0); 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci /* Bind server to ephemeral port on lo */ 6362306a36Sopenharmony_ci memset(&serv_addr, 0, sizeof(serv_addr)); 6462306a36Sopenharmony_ci serv_addr_in->sin_family = AF_INET; 6562306a36Sopenharmony_ci serv_addr_in->sin_port = 0; 6662306a36Sopenharmony_ci serv_addr_in->sin_addr.s_addr = htonl(INADDR_LOOPBACK); 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci assert(bind(serverfd, &serv_addr, sizeof(serv_addr)) == 0); 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci sockaddr_len = sizeof(serv_addr); 7162306a36Sopenharmony_ci assert(getsockname(serverfd, &serv_addr, &sockaddr_len) == 0); 7262306a36Sopenharmony_ci ip = inet_ntoa(serv_addr_in->sin_addr); 7362306a36Sopenharmony_ci printf("Server bound to: %s:%d\n", ip, ntohs(serv_addr_in->sin_port)); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci memset(&mapped_addr, 0, sizeof(mapped_addr)); 7662306a36Sopenharmony_ci mapped_addr_in->sin_family = AF_INET; 7762306a36Sopenharmony_ci mapped_addr_in->sin_port = htons(5555); 7862306a36Sopenharmony_ci mapped_addr_in->sin_addr.s_addr = inet_addr("255.255.255.255"); 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci assert(!bpf_map_update_elem(map_fd, &mapped_addr, &serv_addr, BPF_ANY)); 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci assert(listen(serverfd, 5) == 0); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci ip = inet_ntoa(mapped_addr_in->sin_addr); 8562306a36Sopenharmony_ci printf("Client connecting to: %s:%d\n", 8662306a36Sopenharmony_ci ip, ntohs(mapped_addr_in->sin_port)); 8762306a36Sopenharmony_ci assert(connect(clientfd, &mapped_addr, sizeof(mapped_addr)) == 0); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci sockaddr_len = sizeof(tmp_addr); 9062306a36Sopenharmony_ci ip = inet_ntoa(tmp_addr_in->sin_addr); 9162306a36Sopenharmony_ci assert((serverconnfd = accept(serverfd, &tmp_addr, &sockaddr_len)) > 0); 9262306a36Sopenharmony_ci printf("Server received connection from: %s:%d\n", 9362306a36Sopenharmony_ci ip, ntohs(tmp_addr_in->sin_port)); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci sockaddr_len = sizeof(tmp_addr); 9662306a36Sopenharmony_ci assert(getpeername(clientfd, &tmp_addr, &sockaddr_len) == 0); 9762306a36Sopenharmony_ci ip = inet_ntoa(tmp_addr_in->sin_addr); 9862306a36Sopenharmony_ci printf("Client's peer address: %s:%d\n", 9962306a36Sopenharmony_ci ip, ntohs(tmp_addr_in->sin_port)); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci /* Is the server's getsockname = the socket getpeername */ 10262306a36Sopenharmony_ci assert(memcmp(&serv_addr, &tmp_addr, sizeof(struct sockaddr_in)) == 0); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cicleanup: 10562306a36Sopenharmony_ci bpf_link__destroy(link); 10662306a36Sopenharmony_ci bpf_object__close(obj); 10762306a36Sopenharmony_ci return 0; 10862306a36Sopenharmony_ci} 109