1

I'm learning c++ and coming from a Network Engineer background, and it is fun for me to program something that I'm familiar with it on the network side. I started creating a BGP speaker.

Here is my environment:

[mybgp]<------------TCP-Port-179------------->[bird]

Here is my current code.

#include <arpa/inet.h>
#include <unistd.h>
#include <string.h> 
#include <errno.h>
#include <stdio.h> 
#include <sys/socket.h> 
#include <stdlib.h>
#include <netinet/in.h> 

#define BIND_ADDR INADDR_ANY
#define BIND_PORT htons(179)

int createServerSocket(){
    //Create Socket
    int serverSocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
    if (serverSocket < 0) {
        fprintf(stderr, "socket(): %s\n", strerror(errno));
        return 1;
    }
    return serverSocket;
}

int createBind(const int &serverSocket, sockaddr_in &serverAddr){
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = BIND_PORT;
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    int bind_ret = bind(serverSocket, (sockaddr *) &serverAddr, sizeof(serverAddr));
    // if (bind(serverSocket, (struct sockaddr*) &serverAddr, sizeof(serverAddr)) == -1) {
    //     std::cerr << "Can't bind to ip/port";
    //     return -2;
    // }
    if (bind_ret < 0) {
        fprintf(stderr, "bind(): %s\n", strerror(errno));
        close(serverSocket);
        return 1;
    }
    return bind_ret;
}

int createListener(const int &serverSocket){
    int amount;
    int listen_ret = listen(serverSocket, 3);
    if (listen_ret < 0) {
        fprintf(stderr, "listen(): %s\n", strerror(errno));
        close(serverSocket);
        return 1;
    }
    return listen_ret;

}

int acceptConnect(const int &serverSocket, sockaddr_in &clientAddr){
    fprintf(stderr, "waiting for any client...\n");
    char ip_str[INET_ADDRSTRLEN];
    socklen_t caddr_len = sizeof(clientAddr);
    int serverConn = accept(serverSocket, (sockaddr *) &clientAddr, &caddr_len);
    if (serverConn < 0) {
        fprintf(stderr, "accept(): %s\n", strerror(errno));
        close(serverSocket);
        close(serverConn);
        return 1;
    }
    inet_ntop(AF_INET, &(clientAddr.sin_addr), ip_str, INET_ADDRSTRLEN);
    fprintf(stderr, "accept(): new client from %s.\n", ip_str);
    return serverConn;

}

int main(){
    //Create Socket
    int serverSocket = createServerSocket();
    // declare server and client address struct
    // bind socket.
    sockaddr_in serverAddr, clientAddr;
    memset(&serverAddr, 0, sizeof(serverAddr));
    int bind_ret = createBind(serverSocket, serverAddr);
    
    // listening for connection
    int listen_ret = createListener(serverSocket);
    int serverConn = acceptConnect(serverSocket, clientAddr);
    // we only do one at a time, no new client.
    char buffer[4048] = {0};
    char valread;
    valread = read( serverConn , buffer, 4048); 
    printf("%s\n",buffer );
    close(serverSocket);
    return 0;
}

My current state is that I'm able to:

  1. Create Socket
  2. Bind the Socket to IP
  3. Listening
  4. Accept a Single Connection(Single thread for now)
  5. Received Data

At step 5, I received a gibberish TCP Message from the BGP speaker(BIRD). Knowing how the BGP Protocol works, this TCP message is in an OPEN Message Format. To establish BGP peering, mybgp and bird need to go back and for with different types of messages and agree.

For me to be able to accomplish this peering, I have to:

  1. Decode[Received Package]
  2. Encode[send package]

How can I decode/encode the TCP packet so I can start the process of BGP peering.

Community
  • 1
  • 1
amb1s1
  • 1,995
  • 5
  • 22
  • 26
  • 1
    Can you clarify what your exact question is? – Drew Dormann Jan 20 '21 at 02:58
  • Do you have an implementation of BGP your using, the gist shows trival / nominal socket communicae over TCP/IP and no use of a protocol such as BGP is apparent from the given code. see also https://github.com/Nat-Lab/libbgp https://github.com/Nat-Lab/libbgp/blob/master/src/bgp-packet.cc – Jay Jan 20 '21 at 02:58
  • BGP is a protocol that runs on top of TCP which is what I have now a TCP connection running on TCP port 179. I need to able to read the message sent by the BGP peer and to be able to construct my own BGP message to then if both device agree with the parameters in the packet, the devices established BGP peering. – amb1s1 Jan 20 '21 at 03:10
  • So if you can receive data, you implement a parser and feed your data into it. Am I missing something? – Stephen Newell Jan 20 '21 at 03:15
  • Basically, but I need to encode and decode the data and that is what I'm looking. – amb1s1 Jan 20 '21 at 03:22
  • Make sure you're getting all the data you need to interpret the BGP message. Remember TCP is a stream and doesn't differentiate between messages in protocols implemented using it. A common mistake is to call `recv` for an expected number of bytes and then not check that you successfully read that number of bytes. – user4581301 Jan 20 '21 at 03:22
  • 1
    Now that I've migrated your code we can see that other than using `read` instead of `recv`, you've made the mistake I mentioned above. Quoting the man page for `read`, *read() **attempts to read up to count bytes** from file descriptor fd into the buffer starting at buf.* Because you don't properly respect the return value, you have no clue what you've actually read. Could be 0 bytes. Could be 4048 bytes. Could be anything in between. Throwing this into `printf("%s\n",buffer );` without making sure what you've got is complete (and a null-terminated string) results unpredictable output. – user4581301 Jan 20 '21 at 03:36
  • Here's a question that should help you get past this problem: [What is the correct way of reading from a TCP socket in C/C++?](https://stackoverflow.com/questions/666601/what-is-the-correct-way-of-reading-from-a-tcp-socket-in-c-c) – user4581301 Jan 20 '21 at 03:40
  • Will try your suggestion. Thanks – amb1s1 Jan 20 '21 at 03:47
  • You may modify the protocol dealing source code https://gitlab.nic.cz/labs/bird/-/blob/master/proto/bgp/packets.c to encode and decode, or you can implement your encoding/decoding library your self with some high level tools to generate src with protocol rules like this :https://github.com/scylladb/seastar/blob/master/apps/memcached/ascii.rl – prehistoricpenguin Jan 20 '21 at 04:00
  • BGP, in addition to listening on port 179, also actively tries to connect to peers on port 179. And it does this for multiple peers. As a network engineer, I'd suggest reading the Stevens' book(s)--I've found bugs described in his books in production routers. – Andrew Feb 24 '22 at 00:28

0 Answers0