From c1e8ab159304866d96f27abc200658dfecc96ae2 Mon Sep 17 00:00:00 2001 From: Matjaz Mesnjak Date: Fri, 14 Jan 2022 20:42:16 +0100 Subject: [PATCH] Initial commit. --- client-socket.c | 198 +++++++++ client-spx.c | 229 +++++++++++ client-stream.c | 173 ++++++++ color.h | 34 ++ ipx.h | 105 +++++ ipxstack.c | 1031 +++++++++++++++++++++++++++++++++++++++++++++++ ipxstack.h | 37 ++ ipxstack.ini | 17 + makefile | 52 +++ 9 files changed, 1876 insertions(+) create mode 100644 client-socket.c create mode 100644 client-spx.c create mode 100644 client-stream.c create mode 100644 color.h create mode 100644 ipx.h create mode 100644 ipxstack.c create mode 100644 ipxstack.h create mode 100644 ipxstack.ini create mode 100644 makefile diff --git a/client-socket.c b/client-socket.c new file mode 100644 index 0000000..d852828 --- /dev/null +++ b/client-socket.c @@ -0,0 +1,198 @@ +/* a client in the unix domain */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ipx.h" +#include "ipxstack.h" + +void *mmData = "AK> hello \0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxM"; +ipx_response_t *conn; + +void error(const char *); + +int main(int argc, char *argv[]) +{ + int sockfd, servlen,n; + int sockfd2, servlen2; + int sockfd3, servlen3; + struct sockaddr_un serv_addr; + struct sockaddr_un serv_addr2; + struct sockaddr_un serv_addr3; + ipx_frame_t *ipx_packet; + char buffer[1024]; +// uint32_t conn_pid; + + ipx_request_t *init_connection; + ipx_request_t *close_connection; + + init_connection = malloc(sizeof(ipx_request_t)); + if(!init_connection) + error("Out of memory: init_connection"); + close_connection = malloc(sizeof(ipx_request_t)); + if(!close_connection) + error("Out of memory: close_connection"); + +// ethernet_frame_t *ethernet; + ipx_frame_t *ipx; + void *ipx_data; + + size_t data_size = 512; + size_t packet_size = sizeof(ipx_frame_t) + data_size; + ipx_packet = malloc(packet_size); + if(!ipx_packet) { + error("Out of memory"); + exit(2); + } + + ipx_packet->checksum = 0xffff; + ipx_packet->length = htons(packet_size); + ipx_packet->hops = 0; + ipx_packet->type = 0x05; + ipx_packet->dest_net = 0; + ipx_packet->dest_node[0] = 0xffff; + ipx_packet->dest_node[1] = 0xffff; + ipx_packet->dest_node[2] = 0xffff; + ipx_packet->dest_socket = htons(0x869b); + ipx_packet->src_net = 0; + ipx_packet->src_node[0] = htons(0x984b); + ipx_packet->src_node[1] = htons(0xe108); + ipx_packet->src_node[2] = htons(0x8847); + ipx_packet->src_socket = htons(0x869b); + memcpy(ipx_packet->data, mmData, data_size); + + bzero((char *)&serv_addr,sizeof(serv_addr)); + serv_addr.sun_family = AF_UNIX; + strcpy(serv_addr.sun_path, argv[1]); + servlen = strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family); + if ((sockfd = socket(AF_UNIX, SOCK_STREAM,0)) < 0) + error("Creating socket"); + + if (connect(sockfd, (struct sockaddr *) &serv_addr, servlen) < 0) + error("Connecting"); + +// printf("Please enter your message: "); + bzero(buffer,1002); + init_connection->request_type = OPEN_SOCKET; + init_connection->src_socket = 0x1234; + init_connection->dest_net = 0x00000000; + init_connection->dest_node[0] = 0xffff; + init_connection->dest_node[1] = 0xffff; + init_connection->dest_node[2] = 0xffff; + init_connection->dest_socket = 0x869b; +// init_connection->pid = 1234; +// printf("Init connection: request_type=%i; src_socket=%0x; pid=%i\n", init_connection->request_type, init_connection->src_socket, init_connection->pid); + memcpy(buffer, init_connection, sizeof(ipx_request_t)); +/* memcpy(buffer, frame, 1000);*/ + //fgets(buffer,80,stdin); +/* + ethernet = (ethernet_frame_t *) &buffer; + ipx = (ipx_frame_t *) ðernet->ipxpacket; + ipx_data = (void *)ipx->data; + printf("data: %s", ipx_data); +*/ +// write(sockfd,buffer,1000); + printf("Setting up the Connection\n"); + write(sockfd, init_connection, sizeof(ipx_request_t)); + printf("Waiting for ansver\n"); + n=read(sockfd,buffer,280); + printf("The return message was\n"); + + conn = (ipx_response_t *)buffer; + if(conn->error != NO_ERROR) { + printf("Error: socket is already opened\n"); + exit(2); + } +// printf("My connection: socket=%0x; socket name=%s; pid=%i\n", conn->src_socket, conn->socket_name, conn->pid); +// conn_pid = conn->pid; + write(1,buffer,n); + + close(sockfd); + +/////////////////////////////////////////////////////////////////////////////////////////////////////// +// +/////////////////////////////////////////////////////////////////////////////////////////////////////// + sleep(2); + + char input_string[200]; + int loop = 1; + + printf("Sending data on data sockeet\n"); + bzero(buffer, 1002); + bzero((char *)&serv_addr3, sizeof(serv_addr3)); + serv_addr3.sun_family = AF_UNIX; + strcpy(serv_addr3.sun_path, "./socket.1234"); + servlen3 = strlen(serv_addr3.sun_path) + sizeof(serv_addr3.sun_family); + if((sockfd3 = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + error("Creating data socket"); + + if(connect(sockfd3, (struct sockaddr *) &serv_addr3, servlen3) < 0) + error("Connecting data socket"); + + while(loop) { + bzero(buffer, 1002); + gets(input_string); + if(strncmp(input_string, "exit", 4) == 0) + { + loop = 0; + } + strncpy(buffer+6, input_string, sizeof(input_string)); + memcpy(ipx_packet->data, buffer, 512); + write(sockfd3, ipx_packet, 1000); + } + close(sockfd3); + +/////////////////////////////////////////////////////////////////////////////////////////////////////// +// +/////////////////////////////////////////////////////////////////////////////////////////////////////// + + sleep(2); + printf("Closing connection.\n"); + bzero(buffer, 1002); + close_connection->request_type = CLOSE_SOCKET; + close_connection->src_socket = 0x1234; +// close_connection->pid = conn_pid; +// printf("Closing connection: request_type=%i; src_socket=%0x; pid=%i\n", close_connection->request_type, close_connection->src_socket, close_connection->pid); + + bzero((char *)&serv_addr2,sizeof(serv_addr2)); + serv_addr2.sun_family = AF_UNIX; + strcpy(serv_addr2.sun_path, argv[1]); + servlen2 = strlen(serv_addr2.sun_path) + sizeof(serv_addr2.sun_family); + if ((sockfd2 = socket(AF_UNIX, SOCK_STREAM,0)) < 0) + error("Creating socket"); + + if (connect(sockfd2, (struct sockaddr *) &serv_addr2, servlen2) < 0) + error("Connecting"); + + bzero(buffer,1002); + memcpy(buffer, close_connection, sizeof(ipx_request_t)); + printf("Closing connection.....\n"); + + + write(sockfd2,buffer,1000); + printf("Closing connection......\n"); + +// sleep(2); + + close(sockfd2); + free(init_connection); + free(close_connection); + return 0; +} + +void error(const char *msg) +{ + perror(msg); + exit(0); +} + diff --git a/client-spx.c b/client-spx.c new file mode 100644 index 0000000..882e74d --- /dev/null +++ b/client-spx.c @@ -0,0 +1,229 @@ +/* a client in the unix domain */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ipx.h" +#include "ipxstack.h" + +void *mmData = "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\ +$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"; + +ipx_response_t *conn; + +void error(const char *); + +int main(int argc, char *argv[]) +{ + int sockfd, servlen,n; + int sockfd2, servlen2; + int sockfd3, servlen3; + struct sockaddr_un serv_addr; + struct sockaddr_un serv_addr2; + struct sockaddr_un serv_addr3; + spx_frame_t *ipx_packet; + char buffer[2048]; + +// uint32_t conn_pid; + + ipx_request_t *init_connection; + ipx_request_t *close_connection; + + init_connection = malloc(sizeof(ipx_request_t)); + if(!init_connection) + error("Out of memory: init_connection"); + close_connection = malloc(sizeof(ipx_request_t)); + if(!close_connection) + error("Out of memory: close_connection"); + + size_t data_size = 128; + size_t packet_size = sizeof(spx_frame_t) + data_size; + ipx_packet = malloc(packet_size); + if(!ipx_packet) { + + error("Out of memory"); + exit(2); + } + + ipx_packet->checksum = 0xffff; + ipx_packet->length = htons(packet_size); + ipx_packet->hops = 0; + ipx_packet->type = 0x05; + ipx_packet->dest_net = 0; + ipx_packet->dest_node[0] = htons(0x0800); + ipx_packet->dest_node[1] = htons(0x2750); + ipx_packet->dest_node[2] = htons(0xb177); + ipx_packet->dest_socket = htons(0x869b); + ipx_packet->src_net = 0; + ipx_packet->src_node[0] = htons(0xb827); + ipx_packet->src_node[1] = htons(0xeb02); + ipx_packet->src_node[2] = htons(0xd221); + ipx_packet->src_socket = htons(0x869b); + + ipx_packet->conn_control = 0xc0; + ipx_packet->datastream_type = 0; + ipx_packet->src_conn_id = htons(0x1234); + ipx_packet->dest_conn_id = htons(0xffff); + ipx_packet->seq_no = 0; + ipx_packet->ack_no = 0; + ipx_packet->alloc_no = htons(3); + + + + bzero((char *)&serv_addr,sizeof(serv_addr)); + serv_addr.sun_family = AF_UNIX; + strcpy(serv_addr.sun_path, argv[1]); + servlen = strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family); + if ((sockfd = socket(AF_UNIX, SOCK_STREAM,0)) < 0) + error("Creating socket"); + + if (connect(sockfd, (struct sockaddr *) &serv_addr, servlen) < 0) + error("Connecting"); + +// printf("Please enter your message: "); + bzero(buffer,2048); + init_connection->request_type = OPEN_SPX_SOCKET; + init_connection->src_socket = 0x1234; + init_connection->dest_net = 0x00000000; + init_connection->dest_node[0] = htons(0x0800); + init_connection->dest_node[1] = htons(0x2750); + init_connection->dest_node[2] = htons(0xb177); + init_connection->dest_socket = htons(0x7171); + +// init_connection->pid = 1234; +// printf("Init connection: request_type=%i; src_socket=%0x; pid=%i\n", init_connection->request_type, init_connection->src_socket, init_connection->pid); + memcpy(buffer, init_connection, sizeof(ipx_request_t)); +/* memcpy(buffer, frame, 1000);*/ + //fgets(buffer,80,stdin); +/* + ethernet = (ethernet_frame_t *) &buffer; + ipx = (ipx_frame_t *) ðernet->ipxpacket; + ipx_data = (void *)ipx->data; + printf("data: %s", ipx_data); +*/ +// write(sockfd,buffer,1000); + printf("Setting up the Connection\n"); + write(sockfd, init_connection, sizeof(ipx_request_t)); + printf("Waiting for ansver\n"); + n=read(sockfd,buffer,280); + printf("The return message was\n"); + + conn = (ipx_response_t *)buffer; + if(conn->error != NO_ERROR) { + printf("Error: socket is already opened\n"); + exit(2); + } +// printf("My connection: socket=%0x; socket name=%s; pid=%i\n", conn->src_socket, conn->socket_name, conn->pid); +// conn_pid = conn->pid; + write(1,buffer,n); + + close(sockfd); + +/////////////////////////////////////////////////////////////////////////////////////////////////////// +// +/////////////////////////////////////////////////////////////////////////////////////////////////////// + sleep(1); + + spx_frame_t *spx_packet; + int loop = 1; + + printf("Waiting for data\n"); + bzero(buffer, 2048); + bzero((char *)&serv_addr3, sizeof(serv_addr3)); + serv_addr3.sun_family = AF_UNIX; + strcpy(serv_addr3.sun_path, "./socket.1234"); + servlen3 = strlen(serv_addr3.sun_path) + sizeof(serv_addr3.sun_family); + if((sockfd3 = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + error("Creating data socket"); + + if(connect(sockfd3, (struct sockaddr *) &serv_addr3, servlen3) < 0) + error("Connecting data socket"); + + int seq_no; + + seq_no = 0; + + while(loop) { + printf("Read %i bytes.\n", read(sockfd3, buffer, 2048)); + spx_packet = (spx_frame_t *)&buffer; + printf((const char *)&spx_packet->data); + ipx_packet->checksum = 0xffff; + ipx_packet->length = htons(packet_size); + ipx_packet->hops = 0; + ipx_packet->type = 5; + ipx_packet->dest_net = spx_packet->src_net; + ipx_packet->dest_node[0] = spx_packet->src_node[0]; + ipx_packet->dest_node[1] = spx_packet->src_node[1]; + ipx_packet->dest_node[2] = spx_packet->src_node[2]; + ipx_packet->src_net = spx_packet->dest_net; + ipx_packet->src_node[0] = spx_packet->dest_node[0]; + ipx_packet->src_node[1] = spx_packet->dest_node[1]; + ipx_packet->src_node[2] = spx_packet->dest_node[2]; + ipx_packet->conn_control = 0b01010000; + ipx_packet->datastream_type = 0; + ipx_packet->src_conn_id = htons(conn->pid); + ipx_packet->dest_conn_id = spx_packet->src_conn_id; + ipx_packet->seq_no = htons(seq_no); + ipx_packet->ack_no = htons(ntohs(spx_packet->seq_no) + 1); + ipx_packet->alloc_no = htons(3); + memcpy(ipx_packet->data, mmData, 128); + bzero(buffer, 2048); + memcpy(buffer, ipx_packet, packet_size); + write(sockfd3, buffer, packet_size); + printf("Packet size: %ib\n", packet_size); + bzero(buffer, 2048); + loop = 0; + } + sleep(5); + close(sockfd3); + +/////////////////////////////////////////////////////////////////////////////////////////////////////// +// +/////////////////////////////////////////////////////////////////////////////////////////////////////// + + sleep(2); + printf("Closing connection.\n"); + bzero(buffer, 1002); + close_connection->request_type = CLOSE_SOCKET; + close_connection->src_socket = 0x1234; +// close_connection->pid = conn_pid; +// printf("Closing connection: request_type=%i; src_socket=%0x; pid=%i\n", close_connection->request_type, close_connection->src_socket, close_connection->pid); + + bzero((char *)&serv_addr2,sizeof(serv_addr2)); + serv_addr2.sun_family = AF_UNIX; + strcpy(serv_addr2.sun_path, argv[1]); + servlen2 = strlen(serv_addr2.sun_path) + sizeof(serv_addr2.sun_family); + if ((sockfd2 = socket(AF_UNIX, SOCK_STREAM,0)) < 0) + error("Creating socket"); + + if (connect(sockfd2, (struct sockaddr *) &serv_addr2, servlen2) < 0) + error("Connecting"); + + bzero(buffer,1002); + memcpy(buffer, close_connection, sizeof(ipx_request_t)); + printf("Closing connection.....\n"); + + + write(sockfd2,buffer,1000); + printf("Closing connection......\n"); + +// sleep(2); + + close(sockfd2); + free(init_connection); + free(close_connection); + return 0; +} + +void error(const char *msg) +{ + perror(msg); + exit(0); +} + diff --git a/client-stream.c b/client-stream.c new file mode 100644 index 0000000..be860cb --- /dev/null +++ b/client-stream.c @@ -0,0 +1,173 @@ +/* a client in the unix domain */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ipx.h" +#include "ipxstack.h" + +void *mmData = "AK> hello \0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxM"; +ipx_response_t *conn; + +void error(const char *); + +int main(int argc, char *argv[]) +{ + int sockfd, servlen,n; + int sockfd2, servlen2; + int sockfd3, servlen3; + struct sockaddr_un serv_addr; + struct sockaddr_un serv_addr2; + struct sockaddr_un serv_addr3; + char buffer[1024]; +// uint32_t conn_pid; + + ipx_request_t *init_connection; + ipx_request_t *close_connection; + + init_connection = malloc(sizeof(ipx_request_t)); + if(!init_connection) + error("Out of memory: init_connection"); + close_connection = malloc(sizeof(ipx_request_t)); + if(!close_connection) + error("Out of memory: close_connection"); + bzero((char *)&serv_addr,sizeof(serv_addr)); + serv_addr.sun_family = AF_UNIX; + strcpy(serv_addr.sun_path, argv[1]); + servlen = strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family); + if ((sockfd = socket(AF_UNIX, SOCK_STREAM,0)) < 0) + error("Creating socket"); + + if (connect(sockfd, (struct sockaddr *) &serv_addr, servlen) < 0) + error("Connecting"); + +// printf("Please enter your message: "); + bzero(buffer,1002); + init_connection->request_type = OPEN_STREAM; + init_connection->src_socket = 0x1453; + init_connection->dest_net = 0x00000000; + init_connection->dest_node[0] = 0xffff; + init_connection->dest_node[1] = 0xffff; + init_connection->dest_node[2] = 0xffff; + init_connection->dest_socket = 0x869b; +// init_connection->pid = 1234; +// printf("Init connection: request_type=%i; src_socket=%0x; pid=%i\n", init_connection->request_type, init_connection->src_socket, init_connection->pid); + memcpy(buffer, init_connection, sizeof(ipx_request_t)); +/* memcpy(buffer, frame, 1000);*/ + //fgets(buffer,80,stdin); +/* + ethernet = (ethernet_frame_t *) &buffer; + ipx = (ipx_frame_t *) ðernet->ipxpacket; + ipx_data = (void *)ipx->data; + printf("data: %s", ipx_data); +*/ +// write(sockfd,buffer,1000); + printf("Setting up the Connection\n"); + write(sockfd, init_connection, sizeof(ipx_request_t)); + printf("Waiting for ansver\n"); + n=read(sockfd,buffer,280); + printf("The return message was\n"); + + conn = (ipx_response_t *)buffer; + if(conn->error != NO_ERROR) { + printf("Error: socket is already opened\n"); + exit(2); + } +// printf("My connection: socket=%0x; socket name=%s; pid=%i\n", conn->src_socket, conn->socket_name, conn->pid); +// conn_pid = conn->pid; + write(1,buffer,n); + + close(sockfd); + +/////////////////////////////////////////////////////////////////////////////////////////////////////// +// +/////////////////////////////////////////////////////////////////////////////////////////////////////// + sleep(2); + + char input_string[200]; + int loop = 1; + ipx_frame_t *ipx_packet; + + printf("Sending data on data sockeet\n"); + bzero(buffer, 1002); + bzero((char *)&serv_addr3, sizeof(serv_addr3)); + serv_addr3.sun_family = AF_UNIX; + strcpy(serv_addr3.sun_path, "./socket.1453"); + servlen3 = strlen(serv_addr3.sun_path) + sizeof(serv_addr3.sun_family); + if((sockfd3 = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + error("Creating data socket"); + + if(connect(sockfd3, (struct sockaddr *) &serv_addr3, servlen3) < 0) + error("Connecting data socket"); + + while(loop) { + bzero(buffer, 1002); + gets(input_string); + if(strncmp(input_string, "exit", 4) == 0) + { + loop = 0; + } + strncpy(buffer+6, input_string, sizeof(input_string)); + write(sockfd3, buffer, 1000); +/* bzero(buffer, 1002); + read(sockfd3, buffer, 1000); + ipx_packet = (ipx_frame_t *)buffer; + printf((char *)ipx_packet->data + 6);*/ + } + close(sockfd3); + +/////////////////////////////////////////////////////////////////////////////////////////////////////// +// +/////////////////////////////////////////////////////////////////////////////////////////////////////// + + sleep(2); + printf("Closing connection.\n"); + bzero(buffer, 1002); + close_connection->request_type = CLOSE_SOCKET; + close_connection->src_socket = 0x1453; +// close_connection->pid = conn_pid; +// printf("Closing connection: request_type=%i; src_socket=%0x; pid=%i\n", close_connection->request_type, close_connection->src_socket, close_connection->pid); + + bzero((char *)&serv_addr2,sizeof(serv_addr2)); + serv_addr2.sun_family = AF_UNIX; + strcpy(serv_addr2.sun_path, argv[1]); + servlen2 = strlen(serv_addr2.sun_path) + sizeof(serv_addr2.sun_family); + if ((sockfd2 = socket(AF_UNIX, SOCK_STREAM,0)) < 0) + error("Creating socket"); + + if (connect(sockfd2, (struct sockaddr *) &serv_addr2, servlen2) < 0) + error("Connecting"); + + bzero(buffer,1002); + memcpy(buffer, close_connection, sizeof(ipx_request_t)); + printf("Closing connection.....\n"); + + + write(sockfd2,buffer,1000); + printf("Closing connection......\n"); + +// sleep(2); + + close(sockfd2); + free(init_connection); + free(close_connection); + return 0; +} + +void error(const char *msg) +{ + perror(msg); + exit(0); +} + diff --git a/color.h b/color.h new file mode 100644 index 0000000..e603fcc --- /dev/null +++ b/color.h @@ -0,0 +1,34 @@ +#ifndef COLOR_H +#define COLOR_H + +//foreground +#define FBLACK "\033[30;" +#define FRED "\033[31;" +#define FGREEN "\033[32;" +#define FYELLOW "\033[33;" +#define FBLUE "\033[34;" +#define FPURPLE "\033[35;" +#define D_FGREEN "\033[6;" +#define FWHITE "\033[7;" +#define FCYAN "\x1b[36m" + +//background +#define BBLACK "40m" +#define BRED "41m" +#define BGREEN "42m" +#define BYELLOW "43m" +#define BBLUE "44m" +#define BPURPLE "45m" +#define D_BGREEN "46m" +#define BWHITE "47m" + +//font control +#define BOLD "\033[1m" +#define BOLDOFF "\033[0m" +#define BLINK "\033[5m" +#define REVERSE "7;" + +//end color +#define NONE "\033[0m" + +#endif /* COLOR_H */ diff --git a/ipx.h b/ipx.h new file mode 100644 index 0000000..2dadc8e --- /dev/null +++ b/ipx.h @@ -0,0 +1,105 @@ +#ifndef IPX_H +#define IPX_H + +typedef struct spx_frame spx_frame_t; +struct spx_frame { + uint16_t checksum; + uint16_t length; + uint8_t hops; + uint8_t type; + + uint32_t dest_net; + uint16_t dest_node[3]; + uint16_t dest_socket; + + uint32_t src_net; + uint16_t src_node[3]; + uint16_t src_socket; + + uint8_t conn_control; + uint8_t datastream_type; + uint16_t src_conn_id; + uint16_t dest_conn_id; + uint16_t seq_no; + uint16_t ack_no; + uint16_t alloc_no; + + unsigned char data[0]; +}__attribute__((__packed__, aligned(1))); + +typedef struct spx_header spx_header_t; +struct spx_header { + uint8_t conn_control; + uint8_t datastream_type; + uint16_t src_conn_id; + uint16_t dest_conn_id; + uint16_t seq_no; + uint16_t ack_no; + uint16_t alloc_no; +}__attribute__((__packed__, aligned(1))); + +typedef struct ipx_frame ipx_frame_t; +struct ipx_frame { + uint16_t checksum; + uint16_t length; + uint8_t hops; + uint8_t type; + + uint32_t dest_net; + uint16_t dest_node[3]; + uint16_t dest_socket; + + uint32_t src_net; + uint16_t src_node[3]; + uint16_t src_socket; + + unsigned char data[0]; +} __attribute__((__packed__, aligned(1))); + +typedef struct ethernet_frame ethernet_frame_t; +struct ethernet_frame +{ + uint16_t dest_mac[3]; + uint16_t src_mac[3]; + uint16_t ethertype; + + ipx_frame_t ipxpacket; +} __attribute__((__packed__, aligned(1))); + +typedef struct ethernet_spx_frame ethernet_spx_frame_t; +struct ethernet_spx_frame +{ + uint16_t dest_mac[3]; + uint16_t src_mac[3]; + uint16_t ethertype; + + spx_frame_t spxpacket; +} __attribute__((__packed__, aligned(1))); + + +typedef struct IEEE8023_frame IEEE8023_frame_t; +struct IEEE8023_frame +{ + uint16_t dest_mac[3]; + uint16_t src_mac[3]; + uint16_t length; + uint8_t DSAP; + uint8_t SSAP; + uint8_t ctrl; + + ipx_frame_t ipxpacket; +} __attribute__((__packed__, aligned(1))); + +/* Packet types */ + +#define PACKET_UNKNOWN 0 +#define PACKET_RIP 1 +#define PACKET_ECHO 2 +#define PACKET_ERROR 3 +#define PACKET_IPX 4 // also SAP Packet +#define PACKET_SPX 5 +#define PACKET_NCP 17 +#define PACKET_NETBIOS 20 + +#endif /* IPX_H */ + diff --git a/ipxstack.c b/ipxstack.c new file mode 100644 index 0000000..f44138f --- /dev/null +++ b/ipxstack.c @@ -0,0 +1,1031 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ipx.h" +#include "ipxstack.h" +#include "color.h" +#include "../libconfigini/src/configini.h" + +#define MAX_COUNT 2 +#define BUF_SIZE 1648 +#define CONFIGFILE "ipxstack.ini" +#define ETHERTYPE_IPXNEW 0x8037 /* IPX (Novell Netware?) */ +#define ETHERTYPE_IPX 0x8137 /* Novell (old) NetWare IPX (ECONFIG E option) */ +#define ETHERTYPE_NOVELL 0x8138 /* Novell, Inc. */ + +void error(const char *); +bool is_ipx_packet(const struct ethernet_frame *packet); +bool is_ipx_packet_for_socket(ethernet_frame_t *packet, uint16_t socket); +uint8_t is_socket_in_use(uint16_t socket); +int kill_fork(uint16_t socket, char *MSOCKET); +signed int get_free_spot(); +bool file_exists(const char *fname); +int hex2int(char *hex); + +uint32_t pids[250]; +uint16_t used_sockets[250]; +int number_of_used_sockets; + +struct Device { + char device[50]; + uint32_t network; + char network_str[9]; + char mac_str[15]; + uint16_t mac[3]; + pcap_t *handle; +} device; + +int main(int argc, char *argv[]) +{ + int sockfd, newsockfd, servlen, n; + int sockfd2, newsockfd2, servlen2; + int sockfd3, newsockfd3, servlen3; + socklen_t clilen; + socklen_t clilen2; + socklen_t clilen3; + struct sockaddr_un cli_addr, serv_addr; + struct sockaddr_un cli_addr2, serv_addr2; + struct sockaddr_un cli_addr3, serv_addr3; + + char buf[BUF_SIZE]; + + ipx_request_t *request; + int j; + + char MSOCKET[250]; + bool USE_PCAP_FILTER; + int PCAP_READ_TIMEOUT; + int POLL_TIMEOUT; + + number_of_used_sockets = 0; + + Config *cfg = NULL; + if (ConfigReadFile(CONFIGFILE, &cfg) != CONFIG_OK) { + fprintf(stderr, "ConfigOpenFile failed for %s\n", CONFIGFILE); + exit(2); + } + + ConfigReadString(cfg, "PROGRAM", "socket", MSOCKET, sizeof(MSOCKET)+1, "./socket"); + ConfigReadString(cfg, "ADAPTER", "device", device.device, sizeof(device.device), "bge0"); + ConfigReadString(cfg, "ADAPTER", "network", device.network_str, sizeof(device.network_str), 0); + ConfigReadString(cfg, "ADAPTER", "address", device.mac_str, sizeof(device.mac_str), 0); + ConfigReadBool(cfg, "PROGRAM", "use_pcap_filter", &USE_PCAP_FILTER, false); + ConfigReadInt(cfg, "PROGRAM", "pcap_read_timeout", &PCAP_READ_TIMEOUT, 1000); + ConfigReadInt(cfg, "PROGRAM", "poll_timeout", &POLL_TIMEOUT, 1000); + device.network = hex2int(device.network_str); + + printf("My network number: %08x\n", device.network); + + uint16_t bytes[3]; + uint16_t values[3]; + int i; + + if(3 == sscanf(device.mac_str, "%x:%x:%x", (int *)&values[0], (int *)&values[1], (int *)&values[2])) + { + /* convert to uint16_t */ + for(i = 0; i < 3; ++i) + device.mac[i] = (uint16_t) values[i]; + } else { + /* invalid mac */ + } + printf("My MAC Address: %04x:%04x:%04x\n", device.mac[0], device.mac[1], device.mac[2]); + + ConfigFree(cfg); + + unlink(MSOCKET); + + if ((sockfd = socket(AF_UNIX,SOCK_STREAM,0)) < 0) { + error("Creating socket"); + } + + bzero((char *) &serv_addr, sizeof(serv_addr)); + serv_addr.sun_family = AF_UNIX; + strcpy(serv_addr.sun_path, MSOCKET); + servlen=strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family); + if(bind(sockfd,(struct sockaddr *)&serv_addr,servlen)<0) { + error("binding socket sockfd"); + } + + listen(sockfd,5); + clilen = sizeof(cli_addr); + char buf2[BUF_SIZE]; + char buf3[BUF_SIZE]; + + char errbuf[PCAP_ERRBUF_SIZE]; + int pcapsock; + + /* + * Mother loop + */ + while(1) { + newsockfd = accept(sockfd,(struct sockaddr *)&cli_addr,&clilen); + if (newsockfd < 0) { + error("Accepting connection"); + } + n=read(newsockfd,buf,BUF_SIZE); + printf("Socket read %i bytes.\n", n); + + request = (ipx_request_t *) &buf; + + printf("Recieved new request: request_type=0x%0x; src_socket=0x%0x\n", request->request_type, request->src_socket); + + uint16_t src_socket; + ipx_response_t *conn = malloc(sizeof(ipx_response_t)); + ipx_response_t *conn_error = malloc(sizeof(ipx_response_t)); + if(!conn) { + error("Error: out of memory"); + } + if(!conn_error) { + error("Error: out of memory"); + } + bzero(&conn->socket_name, 100); + bzero(&conn_error->socket_name, 100); + char socket_name[150]; + uint32_t dest_net; + uint16_t dest_node[3]; + uint16_t dest_socket; + char socket_buffer[20]; + uint32_t mpid; + + struct bpf_program filter; + char filter_app[] = "ipx"; + bpf_u_int32 mask; + bpf_u_int32 net; + + printf("Request type: %i\n", request->request_type); + + switch(request->request_type) { +//////////////////////////////////////////////////////////////////////////////////////////////////// +// // +// Open IPX stream // +// // +//////////////////////////////////////////////////////////////////////////////////////////////////// + case OPEN_STREAM: + + src_socket = request->src_socket; + dest_net = request->dest_net; + dest_node[0] = request->dest_node[0]; + dest_node[1] = request->dest_node[1]; + dest_node[2] = request->dest_node[2]; + dest_socket = request->dest_socket; + + printf("Destination Address: %08x:%04x:%04x:%04x:%04x\n", dest_net, dest_node[0], dest_node[1], dest_node[2], dest_socket); + + strcpy(socket_name, MSOCKET); + strcat(socket_name, "."); + sprintf(socket_buffer, "%04x", src_socket); + strcat(socket_name, socket_buffer); + + mpid = fork(); + /* + * only if we are in a forked process + */ + if(mpid == 0) { +// bzero(&conn, 50); + conn->src_socket = src_socket; + strcpy(conn->socket_name, socket_name); + conn->pid = getpid(); + conn->error = NO_ERROR; + printf("Prepared socket: src_socket=0x%0x; socket_name=%s, pid=%i\n", conn->src_socket, conn->socket_name, conn->pid); + + if(is_socket_in_use(src_socket) == 1) { + conn_error->src_socket = src_socket; + conn_error->error = ERROR_SOCKET_OPENED; + strcpy(conn_error->socket_name, "ERROR"); + write(newsockfd, conn_error, sizeof(*conn_error) + 100); + exit(2); + } + close(sockfd); + //printf("Mother socket closed\n"); + + if((sockfd2 = socket(AF_UNIX,SOCK_STREAM,0)) < 0) + error("creating socket"); + bzero((char *)&serv_addr2, sizeof(serv_addr2)); + serv_addr2.sun_family = AF_UNIX; + strcpy(serv_addr2.sun_path, conn->socket_name); + servlen2=strlen(serv_addr2.sun_path) + sizeof(serv_addr2.sun_family); + if(bind(sockfd2, (struct sockaddr *)&serv_addr2,servlen2)<0) { + error("binding socket sockfd2"); + } + + write(newsockfd, conn, sizeof(ipx_response_t)); + close(newsockfd); + + //fcntl(sockfd2, F_SETFL, O_NONBLOCK); + + listen(sockfd2,5); + clilen2 = sizeof(cli_addr2); +/* newsockfd2 = accept(sockfd2,(struct sockaddr *)&cli_addr2,&clilen2); + if (newsockfd2 < 0) { + error("Accepting connection"); + } +*/ + //process_connection(&newsockfd2, conn, mpid); +/////////////////////////////////////////////////////////////////////////////////////////////////// +// +/////////////////////////////////////////////////////////////////////////////////////////////////// + printf("process_connection ... pid=%i\n", mpid); + + pcap_lookupnet(device.device, &net, &mask, errbuf); + if(device.device == NULL) { + error("pcap_lookupnet failed"); + exit(2); + } + + if((device.handle = pcap_open_live(device.device, // name of device + 2048, // portition of packet to capture + 0, // promiscuous mode + PCAP_READ_TIMEOUT, // read timeout + errbuf // error buffer + )) == NULL) + { + printf("Unable to open the adapter. %s is not supported by Pcap\n", device.device); + exit(2); + } + + if(USE_PCAP_FILTER) { +// if(pcap_compile(device.handle, &filter, filter_app, 0, mask) == -1) { +// error("pcap_compile failed"); +// exit(2); +// } + +// if(pcap_setfilter(device.handle, &filter) == -1) { +// error("pcap_setfilter failed"); +// exit(2); +// } + } + + if(pcap_setnonblock(device.handle, 1, errbuf) == -1) { + error("pcap_setnonblock failed"); + exit(2); + } + + size_t data_size = 512; + size_t packet_size = sizeof(ipx_frame_t) + data_size; + size_t frame_size = sizeof(ethernet_frame_t) + data_size; + ethernet_frame_t *frame = malloc(frame_size); + if(!frame) { + error("Out of memory"); + } + frame->dest_mac[0] = htons(dest_node[0]); + frame->dest_mac[1] = htons(dest_node[1]); + frame->dest_mac[2] = htons(dest_node[2]); + frame->src_mac[0] = htons(device.mac[0]); + frame->src_mac[1] = htons(device.mac[1]); + frame->src_mac[2] = htons(device.mac[2]); + frame->ethertype = htons(0x8137); + frame->ipxpacket.checksum = 0xffff; + frame->ipxpacket.length = htons(packet_size); + frame->ipxpacket.hops = 0x00; + frame->ipxpacket.type = 0x00; + frame->ipxpacket.dest_net = htonl(dest_net); + frame->ipxpacket.dest_node[0] = htons(dest_node[0]); + frame->ipxpacket.dest_node[1] = htons(dest_node[1]); + frame->ipxpacket.dest_node[2] = htons(dest_node[2]); + frame->ipxpacket.dest_socket = htons(dest_socket); + frame->ipxpacket.src_net = htonl(device.network); + frame->ipxpacket.src_node[0] = htons(device.mac[0]); + frame->ipxpacket.src_node[1] = htons(device.mac[1]); + frame->ipxpacket.src_node[2] = htons(device.mac[2]); + frame->ipxpacket.src_socket = htons(src_socket); + + int rv; + struct pollfd ufds[2]; + pcapsock = pcap_get_selectable_fd(device.handle); + ufds[0].fd = newsockfd2; + ufds[0].events = POLLIN; // check for normal or out-of-band + ufds[1].fd = pcapsock; + ufds[1].events = POLLIN; + + const u_char *packet; + struct pcap_pkthdr header; + const ethernet_frame_t *ethernet; /* The ethernet header */ + + printf("Data waiting on socket:\n"); + while(newsockfd2 = accept(sockfd2,(struct sockaddr *)&cli_addr2,&clilen2) > 0) { + // wait for events on the sockets, 3.5 second timeout + rv = poll(ufds, 2, POLL_TIMEOUT); + if (rv == -1) { + error("poll"); + } else if(rv == 0) { +// printf(FRED BBLACK"Timeout occurred! No data after 3.5 seconds.\n"NONE); + } else { + if(ufds[0].revents & POLLIN) { +// printf(FBLUE BBLACK"->Local socket: POLLIN\n"NONE); + n = read(newsockfd2, buf2, 512); + if(n == -1) { + printf("Error: %i\n", errno); + } + if(n != 0) { + printf(FYELLOW BBLACK"Data read on data socket: %iB\n"NONE, n); + memcpy(frame->ipxpacket.data, buf2, n); + //frame_size = frame_size - (512 - n); + if((pcap_inject(device.handle, (void*)frame, frame_size)) != -1) { + usleep(100000); + printf(FPURPLE BBLACK"Frame sent: %iB\n"NONE, frame_size); + } else { + printf("Frame not sent\n"); + } + } + } else if(ufds[1].revents & POLLIN) { + packet = pcap_next(device.handle, &header); + ethernet = (const ethernet_frame_t *) packet; + /*if(USE_PCAP_FILTER) { + printf("%s\n", ethernet->ipxpacket.data + 6); + if(write(newsockfd2, (void *)ðernet->ipxpacket, ntohs(ethernet->ipxpacket.length)) == ntohs(ethernet->ipxpacket.length)) { + printf(D_FGREEN BBLACK"Packet recieved\n"NONE); + } else { + printf(FRED BBLACK"Packet partially recieved\n"NONE); + } + } + else { */ + if(ntohs(ethernet->ethertype) == 0x8137) { + printf("Recieved ethernet frame: 0x%04x type: 0x%04x\n", ntohs(ethernet->ethertype), ethernet->ipxpacket.type); + printf("%s\n", ethernet->ipxpacket.data + 6); + if(ethernet->ipxpacket.checksum == 0xffff) { + printf("ipx packet type: %i\n", ethernet->ipxpacket.type); + if(ethernet->ipxpacket.type == 5) { + printf("Detected SPX packet\n"); + } else { + if(write(newsockfd2, (void *)ðernet->ipxpacket, ntohs(ethernet->ipxpacket.length)) == ntohs(ethernet->ipxpacket.length)) { + printf(D_FGREEN BBLACK"Packet recieved\n"NONE); + } else { + printf(FRED BBLACK"Packet partially recieved\n"NONE); + } + } + } + } + //} + } + } + } +/////////////////////////////////////////////////////////////////////////////////////////////////// +// +/////////////////////////////////////////////////////////////////////////////////////////////////// + } + /* + * we are back in mother process. + */ + if(is_socket_in_use(src_socket) != 1) { + int k; + k = get_free_spot(); + pids[k] = mpid; + used_sockets[k] = src_socket; + for(j = 0; j <= number_of_used_sockets; j++) + { + printf("ID: %i\tSocket: %0x\tPID: %i\n", j, used_sockets[j], pids[j]); + } + number_of_used_sockets++; + } + break; +//////////////////////////////////////////////////////////////////////////////////////////////////// +// // +// Open IPX socket // +// // +//////////////////////////////////////////////////////////////////////////////////////////////////// + case OPEN_SOCKET: + src_socket = request->src_socket; + strcpy(socket_name, MSOCKET); + strcat(socket_name, "."); + sprintf(socket_buffer, "%x", src_socket); + strcat(socket_name, socket_buffer); + + mpid = fork(); + /* + * only if we are in a forked process + */ + if(mpid == 0) { + conn->src_socket = src_socket; + conn->error = NO_ERROR; + strcpy(conn->socket_name, socket_name); + conn->pid = getpid(); + printf("Prepared socket: src_socket=0x%0x; socket_name=%s, pid=%i\n", conn->src_socket, conn->socket_name, conn->pid); + + if(is_socket_in_use(src_socket) == 1) { + conn_error->src_socket = src_socket; + conn_error->error = ERROR_SOCKET_OPENED; + strcpy(conn_error->socket_name, "ERROR"); + write(newsockfd, conn_error, sizeof(*conn_error) + 100); + exit(2); + } + close(sockfd); + //printf("Mother socket closed\n"); + + if((sockfd3 = socket(AF_UNIX,SOCK_STREAM,0)) < 0) { + error("creating socket"); + } + bzero((char *)&serv_addr3, sizeof(serv_addr3)); + serv_addr3.sun_family = AF_UNIX; + strcpy(serv_addr3.sun_path, conn->socket_name /*"socket1.1234"*/); + servlen3=strlen(serv_addr3.sun_path) + sizeof(serv_addr3.sun_family); + if(bind(sockfd3, (struct sockaddr *)&serv_addr3,servlen3)<0) { + error("binding socket sockfd3"); + } + + write(newsockfd, conn, sizeof(ipx_response_t)); + close(newsockfd); + + + //fcntl(sockfd3, F_SETFL, O_NONBLOCK); + + listen(sockfd3,5); + clilen3 = sizeof(cli_addr3); + newsockfd3 = accept(sockfd3,(struct sockaddr *)&cli_addr3,&clilen3); + if (newsockfd3 < 0) { + error("Accepting connection"); + } + + //process_connection(&newsockfd3, conn, mpid); +/////////////////////////////////////////////////////////////////////////////////////////////////// +// +/////////////////////////////////////////////////////////////////////////////////////////////////// + printf("process_connection ... pid=%i\n", mpid); + + pcap_lookupnet(device.device, &net, &mask, errbuf); + if(device.device == NULL) { + error("pcap_lookupnet failed"); + exit(2); + } + + if((device.handle = pcap_open_live(device.device, // name of device + 2048, // portition of packet to capture + 0, // promiscuous mode + PCAP_READ_TIMEOUT, // read timeout + errbuf // error buffer + )) == NULL) + { + printf("Unable to open the adapter. %s is not supported by Pcap\n", device.device); + exit(2); + } + + if(USE_PCAP_FILTER) { +// if(pcap_compile(device.handle, &filter, filter_app, 0, mask) == -1) { +// error("pcap_compile failed"); +// exit(2); +// } + +// if(pcap_setfilter(device.handle, &filter) == -1) { +// error("pcap_setfilter failed"); +// exit(2); +// } + } + + if(pcap_setnonblock(device.handle, 1, errbuf) == -1) { + error("pcap_setnonblock failed"); + exit(2); + } + + int rv; + struct pollfd ufds[2]; + pcapsock = pcap_get_selectable_fd(device.handle); + ufds[0].fd = newsockfd3; + ufds[0].events = POLLIN; // check for normal + ufds[1].fd = pcapsock; + ufds[1].events = POLLIN; + + const u_char *packet; + struct pcap_pkthdr header; + const struct ethernet_frame *ethernet; /* The ethernet header */ + ipx_frame_t *ipx_packet; + size_t ipx_packet_size; + size_t ethernet_size; + ethernet_frame_t *ethernet_packet; + ipx_frame_t *ipx_header; + + ethernet_packet = malloc(1024); + if(!ethernet_packet) { + error("Out of memory."); + } + ipx_header = malloc(sizeof(ipx_frame_t)); + if(!ipx_header) { + error("Out of memory."); + } + + printf("Data waiting on socket:\n"); + while(1) { + // wait for events on the sockets, 3.5 second timeout + rv = poll(ufds, 2, POLL_TIMEOUT); + if (rv == -1) { + error("poll"); + } else if(rv == 0) { +// printf(FRED BBLACK"Timeout occurred! No data after 3.5 seconds.\n"NONE); + } else { + fflush(stdout); + if(ufds[0].revents & POLLIN) { +// printf(FBLUE BBLACK"->Local socket: POLLIN\n"NONE); + n = read(newsockfd3, buf3, 1024); + if(n == -1) { + printf("Error: %i\n", errno); + } + if(n != 0) { + printf(FYELLOW BBLACK"Data read on data socket: %iB\n"NONE, n); + ipx_packet = (ipx_frame_t *)buf3; + printf("Preparing to transmit packet: %x\n", ipx_packet->checksum); + ipx_packet_size = (size_t)ntohs(ipx_packet->length); + printf("IPX packet size: %iB\n", ipx_packet_size); + memcpy(ðernet_packet->ipxpacket, ipx_packet, ipx_packet_size); +// ethernet_packet->dest_mac[0] = ipx_packet->dest_node[0]; +// ethernet_packet->dest_mac[1] = ipx_packet->dest_node[1]; +// ethernet_packet->dest_mac[2] = ipx_packet->dest_node[2]; + ethernet_packet->dest_mac[0] = htons(request->dest_node[0]); + ethernet_packet->dest_mac[1] = htons(request->dest_node[1]); + ethernet_packet->dest_mac[2] = htons(request->dest_node[2]); + ethernet_packet->src_mac[0] = ipx_packet->src_node[0]; + ethernet_packet->src_mac[1] = ipx_packet->src_node[1]; + ethernet_packet->src_mac[2] = ipx_packet->src_node[2]; + ethernet_packet->ethertype = htons(0x8137); + ethernet_size = sizeof(ethernet_frame_t) + ipx_packet_size; + printf("Size of ethernet packet: %iB\n", ethernet_size); + + if((pcap_inject(device.handle, (void*)ethernet_packet, ethernet_size)) != -1) { + usleep(100000); + printf(FPURPLE BBLACK"Frame sent\n"NONE); + } else { + printf("Frame not sent\n"); + } + } + } else if(ufds[1].revents & POLLIN) { + packet = pcap_next(device.handle, &header); +// printf("Packet: %i\n", packet); + ethernet = (const struct ethernet_frame *) packet; + if(USE_PCAP_FILTER) { + printf("Recieved ethernet frame: 0x%04x\n", ntohs(ethernet->ethertype)); + printf("%s\n", ethernet->ipxpacket.data + 6); + if(write(newsockfd3, (void *)ðernet->ipxpacket, ntohs(ethernet->ipxpacket.length)) == ntohs(ethernet->ipxpacket.length)) { + printf(D_FGREEN BBLACK"Packet recieved\n"NONE); + } else { + printf(FRED BBLACK"Packet partially recieved\n"NONE); + } + } else { + if(ntohs(ethernet->ethertype) == 0x8137) { + printf("Recieved ethernet frame: 0x%04x\n", ntohs(ethernet->ethertype)); + printf("%s\n", ethernet->ipxpacket.data + 6); + if(ethernet->ipxpacket.checksum == 0xffff) { + printf("IPX packet type: %i\n", ethernet->ipxpacket.type); + if(write(newsockfd3, (void *)ðernet->ipxpacket, ntohs(ethernet->ipxpacket.length)) == ntohs(ethernet->ipxpacket.length)) { + printf(D_FGREEN BBLACK"Packet recieved\n"NONE); + } else { + printf(FRED BBLACK"Packet partially recieved\n"NONE); + } + } + } + } + } + } + } +//////////////////////////////////////////////////////////////////////////////////////////////// +// +//////////////////////////////////////////////////////////////////////////////////////////////// + } + /* + * we are back in mother process. + */ + if(is_socket_in_use(src_socket) != 1) { + int k; + k = get_free_spot(); + pids[k] = mpid; + used_sockets[k] = src_socket; + for(j = 0; j <= number_of_used_sockets; j++) + { + printf("ID: %i\tSocket: %0x\tPID: %i\n", j, used_sockets[j], pids[j]); + } + number_of_used_sockets++; + } + break; +//////////////////////////////////////////////////////////////////////////////////////////////////// +// // +// Open SPX socket // +// // +//////////////////////////////////////////////////////////////////////////////////////////////////// + case OPEN_SPX_SOCKET: + src_socket = request->src_socket; + strcpy(socket_name, MSOCKET); + strcat(socket_name, "."); + sprintf(socket_buffer, "%x", src_socket); + strcat(socket_name, socket_buffer); + + mpid = fork(); + /* + * only if we are in a forked process + */ + if(mpid == 0) { + conn->src_socket = src_socket; + conn->error = NO_ERROR; + strcpy(conn->socket_name, socket_name); + conn->pid = getpid(); + printf("Prepared socket: src_socket=0x%0x; socket_name=%s, pid=%i\n", conn->src_socket, conn->socket_name, conn->pid); + + if(is_socket_in_use(src_socket) == 1) { + conn_error->src_socket = src_socket; + conn_error->error = ERROR_SOCKET_OPENED; + strcpy(conn_error->socket_name, "ERROR"); + write(newsockfd, conn_error, sizeof(*conn_error) + 100); + exit(2); + } + close(sockfd); + //printf("Mother socket closed\n"); + + if((sockfd3 = socket(AF_UNIX,SOCK_STREAM,0)) < 0) { + error("creating socket"); + } + bzero((char *)&serv_addr3, sizeof(serv_addr3)); + serv_addr3.sun_family = AF_UNIX; + strcpy(serv_addr3.sun_path, conn->socket_name /*"socket1.1234"*/); + servlen3=strlen(serv_addr3.sun_path) + sizeof(serv_addr3.sun_family); + if(bind(sockfd3, (struct sockaddr *)&serv_addr3,servlen3)<0) { + error("binding socket sockfd3"); + } + + write(newsockfd, conn, sizeof(ipx_response_t)); + close(newsockfd); + + + //fcntl(sockfd3, F_SETFL, O_NONBLOCK); + + listen(sockfd3,5); + clilen3 = sizeof(cli_addr3); + newsockfd3 = accept(sockfd3,(struct sockaddr *)&cli_addr3,&clilen3); + if (newsockfd3 < 0) { + error("Accepting connection"); + } + + //process_connection(&newsockfd3, conn, mpid); +/////////////////////////////////////////////////////////////////////////////////////////////////// +// +/////////////////////////////////////////////////////////////////////////////////////////////////// + printf("process_connection ... pid=%i\n", mpid); + + pcap_lookupnet(device.device, &net, &mask, errbuf); + if(device.device == NULL) { + error("pcap_lookupnet failed"); + exit(2); + } + + if((device.handle = pcap_open_live(device.device, // name of device + 2048, // portition of packet to capture + 0, // promiscuous mode + PCAP_READ_TIMEOUT, // read timeout + errbuf // error buffer + )) == NULL) + { + printf("Unable to open the adapter. %s is not supported by Pcap\n", device.device); + exit(2); + } + + if(USE_PCAP_FILTER) { + if(pcap_compile(device.handle, &filter, filter_app, 0, mask) == -1) { + error("pcap_compile failed"); + exit(2); + } + + if(pcap_setfilter(device.handle, &filter) == -1) { + error("pcap_setfilter failed"); + exit(2); + } + } + + if(pcap_setnonblock(device.handle, 1, errbuf) == -1) { + error("pcap_setnonblock failed"); + exit(2); + } + + int rv; + struct pollfd ufds[2]; + pcapsock = pcap_get_selectable_fd(device.handle); + ufds[0].fd = newsockfd3; + ufds[0].events = POLLIN; // check for normal + ufds[1].fd = pcapsock; + ufds[1].events = POLLIN; + + const u_char *packet; + struct pcap_pkthdr header; + const struct ethernet_frame *ethernet; /* The ethernet header */ + const struct IEEE8023_frame *ieee; + ipx_frame_t *ipx_packet; + spx_frame_t *spx_packet; + size_t ipx_packet_size; + size_t ethernet_size; + ethernet_frame_t *ethernet_packet; + spx_header_t *spx_ack; + ipx_frame_t *ipx_header; + + ethernet_packet = malloc(1024); + if(!ethernet_packet) { + error("Out of memory."); + } + ipx_header = malloc(sizeof(ipx_frame_t)); + if(!ipx_header) { + error("Out of memory."); + } + spx_ack = malloc(sizeof(spx_header_t)); + if(!spx_ack) { + error("Out of memory."); + } + + printf("Data waiting on socket:\n"); + while(1) { + // wait for events on the sockets, 3.5 second timeout + rv = poll(ufds, 2, POLL_TIMEOUT); + if (rv == -1) { + error("poll"); + } else if(rv == 0) { +// printf(FRED BBLACK"Timeout occurred! No data after 3.5 seconds.\n"NONE); + } else { + if(ufds[0].revents & POLLIN) { +// printf(FBLUE BBLACK"->Local socket: POLLIN\n"NONE); + n = read(newsockfd3, buf3, 1024); + if(n == -1) { + printf("Error: %i\n", errno); + } + else if(n != 0) { + printf(FYELLOW BBLACK"Data read on data socket: %iB\n"NONE, n); + ipx_packet = (ipx_frame_t *)buf3; + spx_packet = (spx_frame_t *)buf3; + printf("Preparing to transmit packet: %x\n", spx_packet->checksum); + ipx_packet_size = (size_t)ntohs(spx_packet->length); + printf("IPX packet size: %iB\n", ipx_packet_size); + memcpy(ðernet_packet->ipxpacket, ipx_packet, ipx_packet_size); + ethernet_packet->dest_mac[0] = ipx_packet->dest_node[0]; + ethernet_packet->dest_mac[1] = ipx_packet->dest_node[1]; + ethernet_packet->dest_mac[2] = ipx_packet->dest_node[2]; +// ethernet_packet->dest_mac[0] = htons(request->dest_node[0]); +// ethernet_packet->dest_mac[1] = htons(request->dest_node[1]); +// ethernet_packet->dest_mac[2] = htons(request->dest_node[2]); + ethernet_packet->src_mac[0] = ipx_packet->src_node[0]; + ethernet_packet->src_mac[1] = ipx_packet->src_node[1]; + ethernet_packet->src_mac[2] = ipx_packet->src_node[2]; + ethernet_packet->ethertype = htons(0x8137); + ethernet_size = sizeof(ethernet_frame_t) + ipx_packet_size; + printf("Size of ethernet packet: %iB\n", ethernet_size); + + if((pcap_inject(device.handle, (void*)ethernet_packet, ethernet_size)) != -1) { + usleep(100000); + printf(FPURPLE BBLACK"Frame sent\n"NONE); + } else { + printf("Frame not sent\n"); + } + } + } else if(ufds[1].revents & POLLIN) { + packet = pcap_next(device.handle, &header); +// printf("Packet: %i\n", packet); + ethernet = (const struct ethernet_frame *) packet; +// ieee = (const struct IEEE8023_frame *) packet; +/* if(ethernet->ethertype == ntohs(0x8137)) { + printf("Ethernet Frame!\n"); + } else if ((ieee->DSAP == 0xe0) && (ieee->SSAP == 0xe0)) { + printf("IEEE 802.3 Frame!\n"); + } +*/ + if(USE_PCAP_FILTER) { + /*printf("Recieved ethernet frame: 0x%04x\n", ntohs(ethernet->ethertype)); + printf("Recieved ethernet frame: 0x%04x\n", ntohs(ethernet->ethertype)); + printf("%s\n", ethernet->ipxpacket.data + 6); + if(write(newsockfd3, (void *)ðernet->ipxpacket, ntohs(ethernet->ipxpacket.length)) == ntohs(ethernet->ipxpacket.length)) { + printf(D_FGREEN BBLACK"Packet recieved\n"NONE); + } else { + printf(FRED BBLACK"Packet partially recieved\n"NONE); + }*/ + } else { /* not USE_PCAP_FILTER */ + if(ntohs(ethernet->ethertype) == 0x8137) { + printf("Recieved ethernet frame: 0x%04x\n", ntohs(ethernet->ethertype)); + printf("%s\n", ethernet->ipxpacket.data + 6); + if(ethernet->ipxpacket.checksum == 0xffff) { + printf("IPX packet type: %i\n", ethernet->ipxpacket.type); + spx_packet = (spx_frame_t *)ðernet->ipxpacket; + if(spx_packet->type == 5) { + printf("SPX packet detected!\n"); + if((spx_packet->conn_control & 0b10000000) != 0) { + printf("System packet\n"); + } + if((spx_packet->conn_control & 0b01000000) != 0) { + printf("Send ACK\n"); + } + if((spx_packet->conn_control & 0b00100000) != 0) { + printf("Attention\n"); + } + if((spx_packet->conn_control & 0b00010000) != 0) { + printf("End of message\n"); + } + if((spx_packet->conn_control & 0b00001000) != 0) { + printf("SPX II\n"); + } + if((spx_packet->conn_control & 0b00000100) != 0) { + printf("Negotiate size\n"); + } + if((spx_packet->conn_control & 0b00000010) != 0) { + printf("Reserved (0)\n"); + } + if((spx_packet->conn_control & 0b00000001) != 0) { + printf("SPX II extended header\n"); + } + /* If ACK is required */ + if((spx_packet->conn_control & 0b01000000) != 0) { + uint16_t ack_num; + uint16_t seq_num; + uint8_t datastream_type; + datastream_type = 0; + /* informed disconnect */ + if(spx_packet->datastream_type == 0xfe) { + datastream_type = 0xff; + seq_num = 0; + ack_num++; + } + ack_num = ntohs(spx_packet->seq_no); + /* System Packet == False */ + if((spx_packet->conn_control & 0b10000000) == 0) { + ack_num++; + } + printf("Bitmask con_ctrl: %i\n", (spx_packet->conn_control & 0b01000000)); + + ethernet_packet->dest_mac[0] = ethernet->src_mac[0]; + ethernet_packet->dest_mac[1] = ethernet->src_mac[1]; + ethernet_packet->dest_mac[2] = ethernet->src_mac[2]; + ethernet_packet->src_mac[0] = ethernet->dest_mac[0]; + ethernet_packet->src_mac[1] = ethernet->dest_mac[1]; + ethernet_packet->src_mac[2] = ethernet->dest_mac[2]; + ethernet_packet->ethertype = htons(0x8137); + + ipx_header->checksum = 0xffff; + ipx_header->length = htons(sizeof(ipx_frame_t) + sizeof(spx_header_t)); + ipx_header->hops = 0x00; + ipx_header->type = 0x05; + ipx_header->dest_net = spx_packet->src_net; + ipx_header->dest_node[0] = spx_packet->src_node[0]; + ipx_header->dest_node[1] = spx_packet->src_node[1]; + ipx_header->dest_node[2] = spx_packet->src_node[2]; + ipx_header->src_net = spx_packet->dest_net; + ipx_header->src_node[0] = spx_packet->dest_node[0]; + ipx_header->src_node[1] = spx_packet->dest_node[1]; + ipx_header->src_node[2] = spx_packet->dest_node[2]; + ipx_header->src_socket = spx_packet->src_net; + + spx_ack->conn_control = 0b10000000; + spx_ack->datastream_type = datastream_type; + spx_ack->src_conn_id = htons(getpid()); + spx_ack->dest_conn_id = spx_packet->src_conn_id; + spx_ack->seq_no = 0; + spx_ack->ack_no = htons(ack_num); + spx_ack->alloc_no = htons(3); + + memcpy(ðernet_packet->ipxpacket, ipx_header, sizeof(ipx_frame_t)); + memcpy(ðernet_packet->ipxpacket.data, spx_ack, sizeof(spx_header_t)); + + if((pcap_inject(device.handle, (void*)ethernet_packet, sizeof(spx_frame_t) + sizeof(ethernet_frame_t))) !=-1) { + usleep(100000); + printf(FPURPLE BBLACK"SPX ACK sent\n"NONE); + } else { + printf("SPX ACK not sent\n"); + } + } + /* If it is not a system package, we write it to the local socket */ + if((spx_packet->conn_control & 0b10000000) == 0) { + char spx_ret_buf[2048]; + bzero(spx_ret_buf, 2048); + memcpy(spx_ret_buf, (void *)ðernet->ipxpacket, ntohs(ethernet->ipxpacket.length)); +// if(write(newsockfd3, (void *)ðernet->ipxpacket, ntohs(ethernet->ipxpacket.length)) == ntohs(ethernet->ipxpacket.length)) { + if(write(newsockfd3, spx_ret_buf, 2048) == 2048) { + printf(D_FGREEN BBLACK"Packet recieved\n"NONE); + } else { + printf(FRED BBLACK"Packet partially recieved\n"NONE); + } + } + } + } + } + } + } + } + } +//////////////////////////////////////////////////////////////////////////////////////////////// +// +//////////////////////////////////////////////////////////////////////////////////////////////// + } + /* + * we are back in mother process. + */ + if(is_socket_in_use(src_socket) != 1) { + int k; + k = get_free_spot(); + pids[k] = mpid; + used_sockets[k] = src_socket; + for(j = 0; j <= number_of_used_sockets; j++) + { + printf("ID: %i\tSocket: %0x\tPID: %i\n", j, used_sockets[j], pids[j]); + } + number_of_used_sockets++; + } + break; + case CLOSE_SOCKET: + if(kill_fork(request->src_socket, MSOCKET) == 0) { + printf("Kill succeded: %i\n", mpid); + } + break; + default: + break; + } + } + close(sockfd); + return 0; +} + +uint8_t is_socket_in_use(uint16_t socket) { + int i; + for(i = 0; i<= 250; i++) { + if(used_sockets[i] == socket) { + printf("used_sockets=%0x; socket=%0x\n", used_sockets[i], socket); + return 1; + } + } + return 0; +} + +void error(const char *msg) +{ + perror(msg); + exit(0); +} + +bool is_ipx_packet(const struct ethernet_frame *packet) { + if(ntohs(packet->ethertype) == 0x8137) + { + printf("Paket: %04x\n", ntohs(packet->ethertype)); + return true; + } + else + return false; +} + +bool is_ipx_packet_for_socket(ethernet_frame_t *packet, uint16_t socket) { + const ipx_frame_t ipx = (ipx_frame_t)packet->ipxpacket; + if(ipx.dest_socket == socket) { + return true; + } else { + return false; + } +} + +int kill_fork(uint16_t socket, char *MSOCKET) { + signed int i; + char socket_name[150]; + char socket_buffer[20]; + strcpy(socket_name, MSOCKET); + strcat(socket_name, "."); + sprintf(socket_buffer, "%x", socket); + strcat(socket_name, socket_buffer); + + + for(i = -1; i < 250; i++) { + if(used_sockets[i] == socket) { + kill(pids[i], SIGKILL); +// printf("unlink: %s\n", socket_name); + if(unlink(socket_name) != 0) { + printf("Unlink error: %i\n", errno); + } + used_sockets[i]=0; + pids[i]=0; + number_of_used_sockets--; + return 0; + } + } + return 1; +} + +signed int get_free_spot() { + int i; + for(i = 0; i < 250; i++) { + if(pids[i] == 0) + return i; + } + return -1; +} + +bool file_exists(const char *fname) +{ + FILE *file; + if((file = fopen(fname, "r")) != NULL) + { + fclose(file); + return true; + } + return false; +} + +int hex2int(char hex[10]) { + int num; + char temp_str[12] = "0x"; + + strcat(temp_str, hex); + sscanf(temp_str, "%x", &num); + return num; +} diff --git a/ipxstack.h b/ipxstack.h new file mode 100644 index 0000000..aecefd5 --- /dev/null +++ b/ipxstack.h @@ -0,0 +1,37 @@ +#ifndef IPXSTACK_H +#define IPXSTACK_H + +#define OPEN_SOCKET 1 +#define OPEN_STREAM 2 +#define OPEN_SPX_SOCKET 3 +#define CLOSE_SOCKET 4 + +#define NO_ERROR 0 +#define ERROR_SOCKET_OPENED 1 +/* + * Client sends struct to ipxstack on its socket. Ipxstack opens a new socket for + * clients communication with network. + */ +typedef struct ipx_request ipx_request_t; +struct ipx_request { + uint16_t request_type; + uint16_t src_socket; + uint32_t dest_net; + uint16_t dest_node[3]; + uint16_t dest_socket; + uint32_t pid; +} __attribute__((__packed__, aligned(1))); + +/* + * Ipxstack responds to the clients's request to open new connection. It sends + * struct containing info about connection socket. + */ +typedef struct ipx_response ipx_response_t; +struct ipx_response { + uint16_t src_socket; + char socket_name[100]; + uint32_t pid; + uint16_t error; +} __attribute__((__packed__, aligned(1))); + +#endif /* IPXSTACK_H */ diff --git a/ipxstack.ini b/ipxstack.ini new file mode 100644 index 0000000..22c3268 --- /dev/null +++ b/ipxstack.ini @@ -0,0 +1,17 @@ +# +# Config file for IPXstack +# + +[PROGRAM] +socket=socket +use_pcap_filter=false +pcap_read_timeout=500 +poll_timeout=100 + +[ADAPTER] +# device=eth0 +device=bge0 +network=00000000 +# address=b827:eb02:d221 +address=984b:e108:8847 +# address=c4b3:018e:1d80 diff --git a/makefile b/makefile new file mode 100644 index 0000000..5a85766 --- /dev/null +++ b/makefile @@ -0,0 +1,52 @@ +# Makefile +# +# +CC = gcc +DEPS = ipx.h ipxstack.h + +# Flags for C compiler +# -g adds debugging information to the executable file +# -Wall turns on most, but not all, compiler warnings +CFLAGS = -ggdb -Wall +LDFLAGS= -lxnet + +all: ipxstack client-socket client-stream client-spx + +ipxstack: ipxstack.o configini.o + $(CC) ipxstack.o configini.o $(LDFLAGS) -o ipxstack -lpcap + +configini.o: ../libconfigini/src/configini.c ../libconfigini/src/configini.h ../libconfigini/src/queue.h + $(CC) -c ../libconfigini/src/configini.c $(LDFLAGS) -o configini.o + +ipxstack.o: ipxstack.c $(DEPS) + $(CC) -c ipxstack.c $(CFLAGS) -o ipxstack.o + +client-spx: client-spx.o + $(CC) client-spx.o $(LDFLAGS) -o client-spx + +client-spx.o: client-spx.c + $(CC) -c client-spx.c $(CFLAGS) -o client-spx.o + +client-socket: client-socket.o + $(CC) client-socket.o $(LDFLAGS) -o client-socket + +client-stream: client-stream.o + $(CC) client-stream.o $(LDFLAGS) -o client-stream + +client-socket.o: client-socket.c $(DEPS) + $(CC) -c client-socket.c $(CFLAGS) -o client-socket.o + +client-stream.o: client-stream.c $(DEPS) + $(CC) -c client-stream.c $(CFLAGS) -o client-stream.o + +clean: + $(RM) ipxstack + $(RM) client-stream + $(RM) client-socket + $(RM) client-spx + $(RM) *.o + $(RM) socket* + pkill ipxstack + $(RM) core + +