#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: %liB\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: %liB\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: %liB\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: %liB\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: %liB\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; }