SPXstack/ipxstack.c
Matjaz Mesnjak c1e8ab1593 Initial commit.
2022-01-14 20:42:16 +01:00

1032 lines
37 KiB
C

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/un.h>
#include <string.h>
#include <strings.h>
#include <signal.h>
#include <errno.h>
#include <pcap.h>
#include <sys/poll.h>
#include <arpa/inet.h>
#include <fcntl.h>
#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 *)&ethernet->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 *)&ethernet->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(&ethernet_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 *)&ethernet->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 *)&ethernet->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(&ethernet_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 *)&ethernet->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 *)&ethernet->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(&ethernet_packet->ipxpacket, ipx_header, sizeof(ipx_frame_t));
memcpy(&ethernet_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 *)&ethernet->ipxpacket, ntohs(ethernet->ipxpacket.length));
// if(write(newsockfd3, (void *)&ethernet->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;
}