1032 lines
37 KiB
C
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 *)ð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;
|
|
}
|