diff --git a/src/install.sh b/src/install.sh new file mode 100755 index 0000000..bf11d28 --- /dev/null +++ b/src/install.sh @@ -0,0 +1 @@ +sudo apt-get install libssl-dev \ No newline at end of file diff --git a/src/misc.c b/src/misc.c new file mode 100644 index 0000000..45de1b2 --- /dev/null +++ b/src/misc.c @@ -0,0 +1,27 @@ +#include "misc.h" + +char *hash_data(pub_data *data) { + // Copy data to buf to pass it as string argument + char cpy_data[data->length + 1]; + memcpy(cpy_data, data->data, data->length); + cpy_data[data->length] = '\0'; + + // All three fields are concatenated into a single buf + char *concat_data = concat(3, data->id, data->seqno, data->data); + + // The resulting buf is hashed + char *hash = SHA256(concat_data, data->length + 10, 0); + + // Free the concatenated buf + free(concat_data); + + return hash_trunc(hash); +} + +char *hash_network(list *data_list) { + +} + +char *hash_trunc(char *hash256bit); + +char *concat(int argc, ...); \ No newline at end of file diff --git a/src/misc.h b/src/misc.h new file mode 100644 index 0000000..737b5d0 --- /dev/null +++ b/src/misc.h @@ -0,0 +1,23 @@ +#ifndef MISC_H +#define MISC_H + +#include +#include +#include "node.h" +#include "tlv.h" + +// General list +typedef struct list { + void *data; + void *next; +} list; + +// Hash functions +char *hash_data(pub_data *data); +char *hash_network(list *data_list); +char *hash_trunc(char *hash256bit); +char *concat(int argc, ...); + + + +#endif \ No newline at end of file diff --git a/src/node.c b/src/node.c index 79aa5e9..fe718a3 100644 --- a/src/node.c +++ b/src/node.c @@ -1,50 +1,248 @@ // This is the main file of the Dazibao project. It represents the node, and // handles all of the main logic, including the network connexions. +#include +#include +#include +#include +#include +#include +#include "tlv.h" +#include "node.h" -// Will return a packet when we receive one that's valid. -packet listen_for_packets(){ +// For every packet recivied, +// then we make sure it's conform +// We then extract the data from it to make it easy to work with +int check_header(char * req[], int buffer_size, packet * packet_to_return){ + packet * packet_to_return = (packet*) req; + + // We need to check a few things ; + // The first byte must be worth 95, + if (packet_to_return->magic != 95) { + perror(">> The magic number of the packet is no good."); + return -1; + } + + // The second byte must be worth 1, + if (packet_to_return->version != 1) { + perror(">> The version number of the packet is no good."); + return -1; + } + + if (packet_to_return.length + 4 > buffer_size ) { + perror(">> The packet length is bigger than the UDP datagram, which is not possible with the current laws of physics."); + return -1; + } + + return 0; } +// We listen forever for new paquets; +void listen_for_packets(){ + + // Create new socket for UDP + int s = socket(AF_INET6, SOCK_DGRAM, 0); + + if(s < 0) { + perror(">> Error, cannot create socket."); + perror(">> Exiting...") + exit(1); + } + + struct sockaddr_in6 server; + memset(&server, 0, sizeof(server)); + + server.sin6_family = AF_INET6; + server.sin6_port = htons(LISTEN_PORT); + int rc = bind(s, (struct sockaddr*)&server, sizeof(server)); + if(rc < 0) { + perror(">> Error, cannot bind socket to choosen port."); + perror(">> Exiting...") + exit(1); + } + + // A paquet has at most a length of 1024 bytes + char req[1024]; + struct sockaddr_in6 client; + struct iovec io = { .iov_len = 1024, .iov_base = req }; + struct msghdr msg_to_receive = { + .msg_name = &client, + .msg_namelen = sizeof(client), + .msg_iov = &io, + .msg_iovlen = 1 + }; + while(1){ + memset(req, '\0', 1024); + + struct sockaddr_in6 client; + unsigned int client_len = sizeof(client); + + rc = recvmsg(s, &msg_to_receive, 0); + if(rc < 0) { + perror(">> Error while receiving a new datagram."); + perror(">> Ignoring, continuing...") + continue; + } + + printf(">> New paquet received :\n"); + printf("%s\n", req); + + // We verify the received packet is well formated, + // and we return it in the struct designed to work with it. + struct packet * formated_rec_datagram; + if(check_header(&req, 1024, formated_rec_datagram) < 0){ + perror(">> Error while checking the header, aborting this packet, by choice, and conviction."); + continue; + } + + struct tlv_list received_tlvs; + if (validate_tlvs(formated_rec_datagram) < 0) { + + /* code */ + } + } +} + + + + +// If the sender is not in the neighbourhood, and we have 15 neighbours, we +// ignore the packet. Otherwise, we add him to the neighbourhood, marked as +// temporary. +int update_neighbours(){ + +}; + // We need to make sure the TLV announces a length that will no go onto // another tlv, as we might end up reading bullshit. -int validate_tlv(unsigned char *data, int pos){ - switch(data[pos]) { - case 0: - break; - case 1: - break; - case 2: - if(data[pos+1] != 0) return 0; - break; - case 3: - if(data[pos+1] != 18) return 0; - break; - case 4: - if(data[pos+1] != 16) return 0; - break; - case 5: - if(data[pos+1] != 0) return 0; - break; - case 6: - if(data[pos+1] != 26) return 0; - break; - case 7: - if(data[pos+1] != 8) return 0; - break; - case 8: - if(data[pos+1] < 26 || data[pos+1] > 218) return 0; - break; - case 9: - break; - default: - return 0; - } +int validate_tlv(char *data, int pos, short packet_len){ + char type = data[pos]; - return 1; + // Nothing to do in this case + if(type == 0) + return 0; + + // Check that we can read a length + if(pos + 1 >= packet_len) + return -1; + + unsigned char tlv_len = data[pos+1]; + + // Check that the tlv does not exceed the packet length + if(pos + length >= packet_len) + return -1; + + // Returns the type of the tlv or -1 if something went wrong + switch(type) { + case 1: + return 1; + case 2: + if(tlv_len != LEN_NEIGHBOUR_REQ) return -1; + return 2; + case 3: + if(tlv_len != LEN_NEIGHBOUR) return -1; + return 3; + case 4: + if(tlv_len != LEN_NETWORK_HASH) return -1; + return 4; + case 5: + if(tlv_len != LEN_NETWORK_STATE_REQ) return -1; + return 5; + case 6: + if(tlv_len != LEN_NODE_HASH) return -1; + return 6; + case 7: + if(tlv_len != LEN_NODE_STATE_REQ) return -1; + return 7; + case 8: + if(tlv_len < MIN_LEN_NODE_STATE || tlv_len > MAX_LEN_NODE_STATE) return -1; + return 8; + case 9: + return 9; + default: + return -1; + } } +// We then look at the differents TLVs in the packet. +void work_with_tlvs(char *data, short packet_len){ + int pos = 0; + unsigned char tlv_len; + tlv tmp_tlv; + + while(pos < packet_len) { + switch(validate_tlv(data, pos, packet_len)) { + case 0: + // We received a padding tlv so it is ignored + pos += 1; + break; + case 1: + // We received a padding tlv so it is ignored + tlv_len = data[pos+1]; + pos += tlv_len + 2; + break; + case 2: + // We received a neighbour request so a neighbor tlv has to be sent + tlv_len = data[pos+1]; + pos += tlv_len + 2; + + // NOT FINISHED - Where are ip and seqno stored? + build_neighbour(&tmp_tlv, ip, seqno); + // NOT FINISHED - What packet is it added to? + add_tlv(packet, &tmp_tlv, 3); + break; + case 3: + // We received a neighbour tlv so a tlv network hash is sent to that address + tlv_len = data[pos+1]; + pos += tlv_len + 2; + + tlv.neighbour = (neighbour*) (data + pos); + break; + case 4: + // We reveived a network hash tlv so + tlv_len = data[pos+1]; + pos += tlv_len +2; + + // NOT FINISHED - Where is network_hash? + build_neighbour(&tmp_tlv, network_hash); + // NOT FINISHED - What packet is it added to? + add_tlv(packet, &tmp_tlv, 4); + break; + case 5: + // We received a network state request tlv so a series of tlv node hash have to be sent for each data known + pos += 2; + + // NOT FINISHED - for each known data + list *tmp_list = data_list; + pub_data *tmp_data; + + while(tmp_list != NULL) { + tmp_data = (pub_data*) tmp_list->data; + build_node_hash(&tmp_tlv, tmp_data->id, tmp_data->seqno); + } + + break; + case 6: + // We received a node hash tlv + break; + case 7: + // We received a node state request tlv + break; + case 8: + // We received a node state tlv + break; + case 9: + // We received a warning tlv so it's message is printed + break; + default: + return ; + } + } +} + + + void work_with_tlvs(struct tlvs_list receivied_tlvs){ // For every TLV, @@ -84,10 +282,10 @@ void work_with_tlvs(struct tlvs_list receivied_tlvs){ // we store the entry in our data table. } -int main(int argc, char const *argv[]) { - int continue = 1; - - while(continue){ +int main(int argc, const char *argv[]) { + int cont = 1; + + while(cont){ // We create the neighbourhood table neighbour_peer neighbour_list[NEIGHBOUR_MAX]; @@ -97,17 +295,8 @@ int main(int argc, char const *argv[]) { // Listen for incoming packets listen_for_packets(); - // For every packet recivied, we fork, - // then we make sure it's conform - // We then extract the data from it to make it easy to work with - check_header(); - // If the sender is not in the neighbourhood, and we have 15 neighbours, we - // ignore the packet. Otherwise, we add him to the neighbourhood, marked as - // temporary. - update_neighbours(); - // We then look at the differents TLVs in the packet. - work_with_tlvs(); + // This is in it's own fork. time_t delay = time(NULL) + 20; while(! (delay < time(NULL)){ // Theses functions are there for general book-keeping,and run in there own diff --git a/src/node.h b/src/node.h index f7680ad..db3eb83 100644 --- a/src/node.h +++ b/src/node.h @@ -3,6 +3,12 @@ #ifndef NODE_H #define NODE_H +#include "tlv.h" +#include "misc.h" + +// On which port do we listen to +#define LISTEN_PORT 1212 + // The node ID #define NODE_ID 203242402519736214145149136169422092269247115186189140178187251487819615911212154252117172522111472481308026129190139512419121015210238252292031613214452118122204415160254 @@ -29,24 +35,31 @@ typedef struct neighbour_peer { * Di : the data of the message 192 bytes */ -typedef struct message { - long node_id_publisher; +typedef struct pub_data { + unsigned char length; + long id; short seqno; char *data; -} message; +} pub_data; + +// static lists +static list *data_list; +static list *neighbour_list; // TODO // fonctions signatures void listen_for_packets(); -void check_header(); +int check_header(char * received_datagram[], int len, packet pack); -void update_neighbours(); +int update_neighbours(); + +int validate_tlv(unsigned char *data, int pos); void work_with_tlvs(); -int validate_tlv(unsigned char *data, int pos); +void add_tlv(packet *packet, tlv *tlv, char type); // threaded functions diff --git a/src/tlv.h b/src/tlv.h index bc21737..a49a8f7 100644 --- a/src/tlv.h +++ b/src/tlv.h @@ -6,6 +6,15 @@ #ifndef TLV_H #define TLV_H +#define LEN_NEIGHBOUR_REQ 0 +#define LEN_NEIGHBOUR 18 +#define LEN_NETWORK_HASH 16 +#define LEN_NETWORK_STATE_REQ 0 +#define LEN_NODE_HASH 26 +#define LEN_NODE_STATE_REQ 8 +#define MIN_LEN_NODE_STATE 26 +#define MAX_LEN_NODE_STATE 218 + // 8 octets min (struct pointer 4 octets), 1024 octets max typedef struct packet { unsigned char magic; // 95 (si autre, ignorer) @@ -99,11 +108,10 @@ typedef union tlv { warning *warning; } tlv; - -// creer un tlv +// build tlv from token int build_tlv(tlv *tlv, cmd_token token); -// creer un tlv specifique +// build specific tlv int build_pad1(tlv *tlv); int build_padn(tlv *tlv, size_t len); int build_neighbour_req(tlv *tlv);