122 lines
3.3 KiB
C++
122 lines
3.3 KiB
C++
#include <sys/socket.h> //socket, inet_aton
|
|
#include <netinet/in.h> //socket, inet_aton
|
|
#include <netinet/udp.h> //socket
|
|
#include <arpa/inet.h> //htons, ntohs, htonl, ntohl, inet_aton
|
|
#include <signal.h> //signal
|
|
#include <stdio.h> //fprintf
|
|
#include <errno.h> //perror
|
|
#include <stdlib.h> //strtol
|
|
#include <unistd.h> //close
|
|
|
|
/*PROTOTYPES*/
|
|
void bail(int code);
|
|
void sig_handler(int signum);
|
|
void usage(char* name);
|
|
|
|
/*DEFINES*/
|
|
//Magic Number used to distinguish our UDP Packets (First 8 Bytes of Payload)
|
|
#define MAGIC 0xDEADBEEFCAFEFEED
|
|
//Receive Buffer Size
|
|
#define BUFFER_SIZE 1000
|
|
|
|
/*GLOBAL VARIABLES*/
|
|
long port = 0;
|
|
int sock_fd = -1;
|
|
struct sockaddr_in src_addr;
|
|
|
|
int main(int argc, char **argv){
|
|
|
|
/*Parse Arguments*/
|
|
if (argc < 3) {
|
|
fprintf(stderr, "Insufficient arguments\n");
|
|
usage(argv[0]);
|
|
}
|
|
|
|
//Source Address
|
|
in_addr_t src_ip_addr = inet_addr(argv[1]);
|
|
if (src_ip_addr == INADDR_NONE) {
|
|
fprintf(stderr, "Invalid SRC IP Address\n");
|
|
usage(argv[0]);
|
|
}
|
|
|
|
//Port Number
|
|
errno = 0;
|
|
port = strtol(argv[2], NULL, 10);
|
|
if (errno != 0) {
|
|
fprintf(stderr, "Invalid Port Number\n");
|
|
usage(argv[0]);
|
|
}
|
|
|
|
/*MISC MAIN THREAD*/
|
|
//Register Signal Handling
|
|
signal(SIGHUP, sig_handler);
|
|
signal(SIGINT, sig_handler);
|
|
signal(SIGQUIT, sig_handler);
|
|
signal(SIGABRT, sig_handler);
|
|
|
|
/*SOCKET OPERATIONS*/
|
|
src_addr = {AF_INET, htons(port), {src_ip_addr}};
|
|
|
|
//Open Socket
|
|
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
//Bind Socket
|
|
if (bind(sock_fd, (const struct sockaddr*) &src_addr, sizeof(src_addr)) < 0) {
|
|
perror("Bind failed");
|
|
bail(EXIT_FAILURE);
|
|
}
|
|
//Set Receive Timeout
|
|
const struct timeval tv = {.tv_usec = 1000}; //1 ms
|
|
setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
|
|
|
|
char buffer[BUFFER_SIZE];
|
|
uint64_t* p = (uint64_t*) buffer;
|
|
socklen_t addrlen;
|
|
struct sockaddr_in src;
|
|
int n;
|
|
|
|
printf("Entering Main loop\n");
|
|
|
|
while(true){
|
|
//Receive Packet
|
|
n = recvfrom(sock_fd, buffer, BUFFER_SIZE, MSG_TRUNC, (struct sockaddr*) &src, &addrlen);
|
|
if (n < 0){
|
|
// Error
|
|
if (errno != EAGAIN && errno != EWOULDBLOCK) {
|
|
perror("rcvfrom() error");
|
|
}
|
|
continue;
|
|
}
|
|
//Packet not relevant
|
|
if (src.sin_family != src_addr.sin_family && src.sin_port != src_addr.sin_port && n >= 8 && p[0] != MAGIC){
|
|
continue;
|
|
}
|
|
//Sent Packet Back
|
|
if (sendto(sock_fd, buffer, n, 0, (const struct sockaddr*) &src, addrlen) < 0) {
|
|
perror("sendto failed");
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void bail(int code){
|
|
//Close Sockets
|
|
if (sock_fd != -1) {
|
|
close(sock_fd);
|
|
}
|
|
//DONE
|
|
exit(code);
|
|
}
|
|
|
|
void sig_handler(int signum){
|
|
fprintf(stderr, "Received Signal %d.\n Exiting...\n", signum);
|
|
bail(EXIT_SUCCESS);
|
|
}
|
|
|
|
void usage(char* name){
|
|
printf("USAGE: %s SRC_ADDRESS PORT\n", name);
|
|
printf("SRC_ADDRESS The local source IPv4 Address from which to send and listen to (In x.x.x.x format)\n");
|
|
printf("PORT The port number of the Addresses\n");
|
|
|
|
bail(EXIT_SUCCESS);
|
|
}
|