A simple BGP speaker listen on TCP 0.0.0.0:179, wait for a peer, and print all BGP messages sent/received with BgpFsm.
#include <libbgp/bgp-fsm.h>
#include <libbgp/bgp-config.h>
#include <libbgp/fd-out-handler.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <condition_variable>
#include <thread>
#include <chrono>
#define ROUTER_ID "172.30.0.1"
#define BIND_ADDR INADDR_ANY
#define BIND_PORT 179
#define MY_ASN 65000
bool running = false;
std::condition_variable cv;
std::mutex ticker_mtx;
fprintf(stderr, "ticker(): ticker started.\n");
while (true) {
if (!running) break;
std::unique_lock<std::mutex> lock(ticker_mtx);
if (cv.wait_for(lock, std::chrono::seconds(1)) == std::cv_status::timeout) {
} else break;
}
fprintf(stderr, "ticker(): ticker stopped.\n");
}
int main(void) {
int fd_sock = -1, fd_conn = -1;
struct sockaddr_in server_addr, client_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = BIND_ADDR;
server_addr.sin_port = htons(BIND_PORT);
fd_sock = socket(AF_INET, SOCK_STREAM, 0);
if (fd_sock < 0) {
fprintf(stderr, "socket(): %s\n", strerror(errno));
return 1;
}
int bind_ret = bind(fd_sock, (struct sockaddr *) &server_addr, sizeof(server_addr));
if (bind_ret < 0) {
fprintf(stderr, "bind(): %s\n", strerror(errno));
close(fd_sock);
return 1;
}
int listen_ret = listen(fd_sock, 1);
if (listen_ret < 0) {
fprintf(stderr, "listen(): %s\n", strerror(errno));
close(fd_sock);
return 1;
}
fprintf(stderr, "waiting for any client...\n");
char ip_str[INET_ADDRSTRLEN];
socklen_t caddr_len = sizeof(client_addr);
fd_conn = accept(fd_sock, (struct sockaddr *) &client_addr, &caddr_len);
if (fd_conn < 0) {
fprintf(stderr, "accept(): %s\n", strerror(errno));
close(fd_sock);
close(fd_conn);
return 1;
}
inet_ntop(AF_INET, &(client_addr.sin_addr), ip_str, INET_ADDRSTRLEN);
fprintf(stderr, "accept(): new client from %s.\n", ip_str);
close(fd_sock);
inet_pton(AF_INET, ROUTER_ID, &config.
router_id);
running = true;
std::thread ticker_thread(ticker, std::ref(fsm));
uint8_t *read_buffer = (uint8_t *) malloc(65536);
while (true) {
ssize_t read_ret = read(fd_conn, read_buffer, 65536);
if (read_ret < 0) {
fprintf(stderr, "read(): %s.\n", strerror(errno));
break;
}
if (read_ret == 0) {
fprintf(stderr, "read(): peer gone.\n");
break;
}
int fsm_ret = fsm.
run(read_buffer, (
size_t) read_ret);
if (fsm_ret <= 0 || fsm_ret == 2) break;
}
running = false;
cv.notify_all();
if (ticker_thread.joinable()) {
fprintf(stderr, "waiting for the ticker thread to stop...\n");
ticker_thread.join();
}
fprintf(stderr, "closing socket & clean up...\n");
free(read_buffer);
close(fd_conn);
return 0;
}