diff options
Diffstat (limited to 'Semestr 4/sieci/pracownia2/router')
-rw-r--r-- | Semestr 4/sieci/pracownia2/router/config.h | 9 | ||||
-rw-r--r-- | Semestr 4/sieci/pracownia2/router/dist_vector.c | 8 | ||||
-rw-r--r-- | Semestr 4/sieci/pracownia2/router/dist_vector.h | 24 | ||||
-rw-r--r-- | Semestr 4/sieci/pracownia2/router/linked_list.c | 58 | ||||
-rw-r--r-- | Semestr 4/sieci/pracownia2/router/linked_list.h | 38 | ||||
-rw-r--r-- | Semestr 4/sieci/pracownia2/router/network_addr.c | 50 | ||||
-rw-r--r-- | Semestr 4/sieci/pracownia2/router/network_addr.h | 43 | ||||
-rw-r--r-- | Semestr 4/sieci/pracownia2/router/router.c | 27 | ||||
-rw-r--r-- | Semestr 4/sieci/pracownia2/router/router_addr.c | 32 | ||||
-rw-r--r-- | Semestr 4/sieci/pracownia2/router/router_addr.h | 19 | ||||
-rw-r--r-- | Semestr 4/sieci/pracownia2/router/test.c | 40 | ||||
-rw-r--r-- | Semestr 4/sieci/pracownia2/router/utils.c | 28 | ||||
-rw-r--r-- | Semestr 4/sieci/pracownia2/router/utils.h | 17 | ||||
-rw-r--r-- | Semestr 4/sieci/pracownia2/router/vector.h | 1 |
14 files changed, 314 insertions, 80 deletions
diff --git a/Semestr 4/sieci/pracownia2/router/config.h b/Semestr 4/sieci/pracownia2/router/config.h new file mode 100644 index 0000000..3537c03 --- /dev/null +++ b/Semestr 4/sieci/pracownia2/router/config.h @@ -0,0 +1,9 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#define SERVER_PORT 54321 +#define TURN_LEN_S 5 +#define TURN_LEN_MS (1000 * TURN_LEN_S) +#define TURN_LEN_US (1000000 * TURN_LEN_S) + +#endif
\ No newline at end of file diff --git a/Semestr 4/sieci/pracownia2/router/dist_vector.c b/Semestr 4/sieci/pracownia2/router/dist_vector.c new file mode 100644 index 0000000..1e09bff --- /dev/null +++ b/Semestr 4/sieci/pracownia2/router/dist_vector.c @@ -0,0 +1,8 @@ +#include "dist_vector.h" + +bool is_connected_directly(struct vector_item item) { + return (get_network_address(item.network).s_addr == + get_network_address(item.via_ip).s_addr); +} + +void update_distance_vector(list_t *distance_vector, struct vector_item new_item) {}
\ No newline at end of file diff --git a/Semestr 4/sieci/pracownia2/router/dist_vector.h b/Semestr 4/sieci/pracownia2/router/dist_vector.h new file mode 100644 index 0000000..cd1a995 --- /dev/null +++ b/Semestr 4/sieci/pracownia2/router/dist_vector.h @@ -0,0 +1,24 @@ +#ifndef DIST_VECTOR_H +#define DIST_VECTOR_H + +#include "linked_list.h" +#include "network_addr.h" + +/* Item of the distance vector. + * If <<reachable>> is set to 0, then it means that the network is reachable. + * If <<reachable>> has positive value, then it indicates that the network was + * unreachable for <<reachable>> turns. + */ +struct vector_item { + struct network_addr network; + router_addr via_ip; + uint8_t reachable; +}; + +/* Returns true if given distance vector item is connected directly, false otherwise */ +bool is_connected_directly(struct vector_item item); + +/* Updates the distance vector. */ +void update_distance_vector(list_t *distance_vector, struct vector_item new_item); + +#endif
\ No newline at end of file diff --git a/Semestr 4/sieci/pracownia2/router/linked_list.c b/Semestr 4/sieci/pracownia2/router/linked_list.c new file mode 100644 index 0000000..b6b5225 --- /dev/null +++ b/Semestr 4/sieci/pracownia2/router/linked_list.c @@ -0,0 +1,58 @@ +#include "linked_list.h" +#include <stdlib.h> +#include <stdint.h> + +node_t *_next(node_t *node) { + return (node == NULL) ? NULL : node->next; +} + +void _insert(node_t **head, void *data, size_t data_size) { + node_t *new_node = (node_t *)malloc(sizeof(node_t)); + new_node->data = malloc(data_size); + for (int i = 0; i < data_size; i++) + *(uint8_t *)(new_node->data + i) = *(uint8_t *)(data + i); + + new_node->next = *head; + *head = new_node; +} + +void _erase(node_t **head) { + node_t *next_node = _next(*head); + free((*head)->data); + free(*head); + *head = next_node; +} + +void _free_list(node_t *head) { + if (head == NULL) return; + _free_list(head->next); + free(head->data); + free(head); +} + +list_t create_list() { + list_t ret; + ret.head = NULL; + ret.it = NULL; + return ret; +} + +void insert(list_t *list, void *data, size_t data_size) { + _insert(&list->head, data, data_size); +} + +void erase(list_t *list) { + _erase(&list->head); +} + +void iterate(list_t *list) { + list->it = _next(list->it); +} + +void reset(list_t *list) { + list->it = list->head; +} + +void free_list(list_t *list) { + _free_list(list->head); +}
\ No newline at end of file diff --git a/Semestr 4/sieci/pracownia2/router/linked_list.h b/Semestr 4/sieci/pracownia2/router/linked_list.h new file mode 100644 index 0000000..f662dbe --- /dev/null +++ b/Semestr 4/sieci/pracownia2/router/linked_list.h @@ -0,0 +1,38 @@ +#ifndef LINKED_LIST_H +#define LINKED_LIST_H + +#include <stddef.h> + +typedef struct node { + void *data; + struct node *next; +} node_t; + + +typedef struct list_t { + node_t *head; + node_t *it; +} list_t; + +/* Creates an empty list */ +list_t create_list(); + +/* Insert a new node in the begining of a list. */ +void insert(list_t *list, void *data, size_t data_size); + +/* Erases first node from the list. */ +void erase(list_t *list); + +/* Moves iterator one step. */ +void iterate(list_t *list); + +/* Resets the iterator. + * Should execute the function after if you want to itarate unless you didnt insert or erase anything from the list. + */ +void reset(list_t *list); + +/* Deletes the whole list. */ +void free_list(list_t *list); + + +#endif
\ No newline at end of file diff --git a/Semestr 4/sieci/pracownia2/router/network_addr.c b/Semestr 4/sieci/pracownia2/router/network_addr.c new file mode 100644 index 0000000..a65f48c --- /dev/null +++ b/Semestr 4/sieci/pracownia2/router/network_addr.c @@ -0,0 +1,50 @@ +#include "network_addr.h" +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +struct in_addr _get_broadcast_address(struct in_addr addr, uint16_t netmask) { + struct in_addr result = addr; + /* bitshift by more than 31 is UB */ + if (netmask < 32) { + result.s_addr |= ~((1<<netmask) - 1); + } + return result; +} + +struct in_addr _get_network_address(struct in_addr addr, uint16_t netmask) { + struct in_addr result = addr; + if (netmask == 0) { + addr.s_addr = 0; + } + else { + result.s_addr &= ~((1 << (32 - netmask)) - 1); + } + return result; +} + +struct in_addr get_broadcast_address(struct network_addr na) { + return _get_broadcast_address(na.addr, na.netmask); +} + +struct in_addr get_network_address(struct network_addr na) { + return _get_network_address(na.addr, na.netmask); +} + +void pretty_print(struct network_addr na) { + char ip_addr[20]; + inet_ntop(AF_INET, &na.addr, ip_addr, sizeof(ip_addr)); + printf("%s/%d distance %d\n", ip_addr, na.netmask, na.distance); +} + +struct network_addr stora(char *str) { + struct network_addr result; + char addr[20]; + size_t ip_preffix = strcspn(str, "/"); + + strncpy(addr, str, strlen(str)); + addr[ip_preffix] = 0; + inet_pton(AF_INET, addr, &(result.addr)); + result.netmask = atoi(str + ip_preffix + 1); + return result; +} diff --git a/Semestr 4/sieci/pracownia2/router/network_addr.h b/Semestr 4/sieci/pracownia2/router/network_addr.h new file mode 100644 index 0000000..777406a --- /dev/null +++ b/Semestr 4/sieci/pracownia2/router/network_addr.h @@ -0,0 +1,43 @@ +#ifndef ROUTER_ADDR_H +#define ROUTER_ADDR_H + +#include <arpa/inet.h> +#include <stdint.h> +#include <stdbool.h> + +#define INFINITY_DIST 128 + +/* Network address and sitance */ +struct network_addr { + struct in_addr addr; + uint16_t distance; + uint8_t netmask; +}; + +typedef struct network_addr router_addr; + +/* Item of the distance vector. + * If <<reachable>> is set to 0, then it means that the network is reachable. + * If <<reachable>> has positive value, then it indicates that the network was + * unreachable for <<reachable>> turns. + */ +struct vector_item { + struct network_addr network; + struct in_addr via_ip; + uint8_t reachable; +}; + +/* Returns broadcast address of a given network. */ +struct in_addr get_broadcast_address(struct network_addr na); + +/* Returns network address of a given network */ +struct in_addr get_network_address(struct network_addr na); + +/* Prints network_addr via stdio. */ +void pretty_print(struct network_addr na); + +/* Converts string of ip in CIDR notation with a netmask to network_addr. */ +struct network_addr stora(char *str); + + +#endif
\ No newline at end of file diff --git a/Semestr 4/sieci/pracownia2/router/router.c b/Semestr 4/sieci/pracownia2/router/router.c index f68a6a3..031ead8 100644 --- a/Semestr 4/sieci/pracownia2/router/router.c +++ b/Semestr 4/sieci/pracownia2/router/router.c @@ -7,18 +7,13 @@ #include <stdint.h> #include <stdlib.h> #include <unistd.h> -#include "router_addr.h" +#include "network_addr.h" #include "utils.h" -#define SERVER_PORT 54321 -#define TURN_LEN_S 5 -#define TURN_LEN_MS (1000 * TURN_LEN_S) -#define TURN_LEN_US (1000000 * TURN_LEN_S) - -uint16_t read_configuration(struct router_addr** networks) { +uint16_t read_configuration(struct network_addr** networks) { uint16_t n; scanf("%hd", &n); - *networks = malloc(n * sizeof(struct router_addr)); + *networks = malloc(n * sizeof(struct network_addr)); for (int i = 0; i < n; i++) { char addr[20]; char _dist[10]; @@ -30,7 +25,7 @@ uint16_t read_configuration(struct router_addr** networks) { return n; } -void listen_for_routers(int sockfd, int timeout, int networks_number, struct router_addr *netowrks) { +void listen_for_routers(int sockfd, int timeout, int networks_number, struct network_addr *netowrks) { printf("Listening for %dms.\n", timeout); while (poll_socket_modify_timeout(sockfd, &timeout)) { printf("Poll returned, remaining timeout: %dms.\n", timeout); @@ -40,12 +35,6 @@ void listen_for_routers(int sockfd, int timeout, int networks_number, struct rou } int send_distance_vector(int sockfd, struct in_addr network) { - struct sockaddr_in network_address; - bzero (&network_address, sizeof(network_address)); - network_address.sin_family = AF_INET; - network_address.sin_port = htons(SERVER_PORT); - network_address.sin_addr = network; - char* message = "Hello server! My name is S1\n"; ssize_t message_len = strlen(message); int result; @@ -53,12 +42,12 @@ int send_distance_vector(int sockfd, struct in_addr network) { char addr[20]; inet_ntop(AF_INET, &network, addr, sizeof(addr)); printf("Sending datagram to %s\n", addr); - if ((result = sendto(sockfd, message, message_len, 0, (struct sockaddr*) &network_address, sizeof(network_address))) != message_len) { + if ((result = send_message(sockfd, message, message_len, network)) != message_len) { fprintf(stderr, "sendto error: %s\n", strerror(errno)); } } -void propagate_distance_vector(int sockfd, int networks_number, struct router_addr *networks) { +void propagate_distance_vector(int sockfd, int networks_number, struct network_addr *networks) { printf("Propagating distance vector\n"); for (int i = 0; i < networks_number; i++) { struct in_addr broadcast_address = get_broadcast_address(networks[i]); @@ -67,7 +56,7 @@ void propagate_distance_vector(int sockfd, int networks_number, struct router_ad printf("Distance vector propagated.\n\n"); } -void router_loop(int sockfd, int networks_number, struct router_addr *networks) { +void router_loop(int sockfd, int networks_number, struct network_addr *networks) { printf("Starting the router loop...\n"); for (;;) { listen_for_routers(sockfd, TURN_LEN_MS, networks_number, networks); @@ -76,7 +65,7 @@ void router_loop(int sockfd, int networks_number, struct router_addr *networks) } int main() { - struct router_addr* networks; + struct network_addr* networks; int n = read_configuration(&networks); for (int i = 0; i < n; i++) { pretty_print(networks[i]); diff --git a/Semestr 4/sieci/pracownia2/router/router_addr.c b/Semestr 4/sieci/pracownia2/router/router_addr.c deleted file mode 100644 index 1e4c086..0000000 --- a/Semestr 4/sieci/pracownia2/router/router_addr.c +++ /dev/null @@ -1,32 +0,0 @@ -#include "router_addr.h" -#include <stdio.h> -#include <string.h> -#include <stdlib.h> - -struct in_addr get_broadcast_address(struct router_addr ra) { - struct in_addr result = ra.addr; - /* bitshift by more than 31 is UB */ - if (ra.netmask < 32) { - result.s_addr |= ~((1<<ra.netmask) - 1); - } - return result; -} - -void pretty_print(struct router_addr ra) { - char ip_addr[20]; - inet_ntop(AF_INET, &ra.addr, ip_addr, sizeof(ip_addr)); - printf("%s/%d distance %d\n", ip_addr, ra.netmask, ra.distance); -} - -/* converts string of IP with netmask in CIDR notation to router_addr */ -struct router_addr stora(char *str) { - struct router_addr result; - char addr[20]; - size_t ip_preffix = strcspn(str, "/"); - - strncpy(addr, str, strlen(str)); - addr[ip_preffix] = 0; - inet_pton(AF_INET, addr, &(result.addr)); - result.netmask = atoi(str + ip_preffix + 1); - return result; -}
\ No newline at end of file diff --git a/Semestr 4/sieci/pracownia2/router/router_addr.h b/Semestr 4/sieci/pracownia2/router/router_addr.h deleted file mode 100644 index bebb0f5..0000000 --- a/Semestr 4/sieci/pracownia2/router/router_addr.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef ROUTER_ADDR_H -#define ROUTER_ADDR_H - -#include <arpa/inet.h> -#include <stdint.h> - -struct router_addr { - struct in_addr addr; - uint16_t distance; - uint8_t netmask; -}; - -struct in_addr get_broadcast_address(struct router_addr ra); - -void pretty_print(struct router_addr ra); - -struct router_addr stora(char *str); - -#endif
\ No newline at end of file diff --git a/Semestr 4/sieci/pracownia2/router/test.c b/Semestr 4/sieci/pracownia2/router/test.c new file mode 100644 index 0000000..ebc6df1 --- /dev/null +++ b/Semestr 4/sieci/pracownia2/router/test.c @@ -0,0 +1,40 @@ +#include "linked_list.h" +#include <stdlib.h> +#include <stdio.h> + +/* Prints the list of ints to stdio */ +void print_list(list_t list) { + printf("List: "); + reset(&list); + while (list.it != NULL) { + printf("%d, ", *(int *)(list.it->data)); + iterate(&list); + } + printf("\n"); + reset(&list); +} + +int main() { + int n; + scanf("%d", &n); + list_t list = create_list(); + + for (int i = 0; i < n; i++) { + int t; + scanf("%d", &t); + // insert + if (t == 0) { + int val = 0; + scanf("%d", &val); + insert(&list, &val, sizeof(int)); + } + if (t == 1) { + erase(&list); + } + if (t == 2) { + print_list(list); + } + } + + free_list(&list); +}
\ No newline at end of file diff --git a/Semestr 4/sieci/pracownia2/router/utils.c b/Semestr 4/sieci/pracownia2/router/utils.c index 9f008eb..2872a35 100644 --- a/Semestr 4/sieci/pracownia2/router/utils.c +++ b/Semestr 4/sieci/pracownia2/router/utils.c @@ -21,10 +21,12 @@ void bind_to_port(int sockfd, uint16_t port) { server_address.sin_family = AF_INET; server_address.sin_port = htons(port); server_address.sin_addr.s_addr = htonl(INADDR_ANY); + if (bind(sockfd, (struct sockaddr*)&server_address, sizeof(server_address)) < 0) { fprintf(stderr, "Bind error: %s\n", strerror(errno)); exit(EXIT_FAILURE); } + int broadcastPermission = 1; setsockopt (sockfd, SOL_SOCKET, SO_BROADCAST, (void *)&broadcastPermission, sizeof(broadcastPermission)); } @@ -38,16 +40,17 @@ int poll_socket_modify_timeout(int sockfd, int *timeout) { fprintf(stderr, "poll_modify_timeout: timeout is negative.\n"); exit(EXIT_FAILURE); } - + struct pollfd fds; + struct timespec start; + struct timespec finish; + fds.fd = sockfd; fds.events = POLLIN; fds.revents = 0; - - struct timespec start; clock_gettime(CLOCK_REALTIME, &start); - int result = poll(&fds, 1, *timeout); + int result = poll(&fds, 1, *timeout); if (result == -1) { fprintf(stderr, "poll error: %s\n", strerror(errno)); exit(EXIT_FAILURE); @@ -56,15 +59,14 @@ int poll_socket_modify_timeout(int sockfd, int *timeout) { *timeout = 0; return 0; } - struct timespec finish; + clock_gettime(CLOCK_REALTIME, &finish); *timeout -= get_time_interval(start, finish); printf("Timeout: %dms, time waiting: %ldms.\n", *timeout, get_time_interval(start, finish)); return result; } -/* For debug purposes only */ -void recv_and_print(int sockfd, int networks_number, struct router_addr *networks) { +void recv_and_print(int sockfd, int networks_number, struct network_addr *networks) { struct sockaddr_in sender; socklen_t sender_len = sizeof(sender); uint8_t buffer[IP_MAXPACKET + 1]; @@ -87,4 +89,14 @@ void recv_and_print(int sockfd, int networks_number, struct router_addr *network buffer[datagram_len] = 0; printf("%ld-byte message: +%s+\n", datagram_len, buffer); -}
\ No newline at end of file +} + +size_t send_message(int sockfd, char *buffer, int buffer_len, struct in_addr network) { + struct sockaddr_in network_address; + bzero (&network_address, sizeof(network_address)); + network_address.sin_family = AF_INET; + network_address.sin_port = htons(SERVER_PORT); + network_address.sin_addr = network; + + return sendto(sockfd, buffer, buffer_len, 0, (struct sockaddr*) &network_address, sizeof(network_address)); +} diff --git a/Semestr 4/sieci/pracownia2/router/utils.h b/Semestr 4/sieci/pracownia2/router/utils.h index 3d36aed..63ad6fb 100644 --- a/Semestr 4/sieci/pracownia2/router/utils.h +++ b/Semestr 4/sieci/pracownia2/router/utils.h @@ -2,22 +2,35 @@ #define UTILS_H #define UTILS_H +#include "config.h" #include <stdint.h> #include <time.h> #include <poll.h> -#include "router_addr.h" +#include "network_addr.h" #define NS_TO_MS(X) ((long)(X) / (long)1000000) #define S_TO_MS(X) ((long)(X) * (long)1000) +/* Returns a UDP socket. */ int get_socket(); +/* Binds socket to given port and set the broadcast permission. */ void bind_to_port(int sockfd, uint16_t port); +/* Computes the time elapsed between start and finish in miliseconds. */ long get_time_interval(struct timespec start, struct timespec finish); +/* Polls given socket with given timeout and changes the timeout accordingly. */ int poll_socket_modify_timeout(int sockfd, int *timeout); -void recv_and_print(int sockfd, int networks_number, struct router_addr *networks); +/* For debug purposes only. Recieves and prints UDP message. */ +void recv_and_print(int sockfd, int networks_number, struct network_addr *networks); + +/* Sends message in buffer of length buffer_len to addr through given socket. + * IT DOES NOT TERMINATE THE PROGRAM IF SENDTO RETURNS ANY ERRORS! + * One must handle the errors on their own. + */ +size_t send_message(int sockfd, char *buffer, int buffer_len, struct in_addr addr); + #endif
\ No newline at end of file diff --git a/Semestr 4/sieci/pracownia2/router/vector.h b/Semestr 4/sieci/pracownia2/router/vector.h new file mode 100644 index 0000000..4cd0039 --- /dev/null +++ b/Semestr 4/sieci/pracownia2/router/vector.h @@ -0,0 +1 @@ +#ifndef
\ No newline at end of file |