/*
* Copyright (c) 2001 Fenris, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* File: network.c
*
* Purpose: This source file defines the interface for manipulating the
* network object (a structure of 3 lists of lists) Understanding the
* structure of this object and its interface was hard. Read on at your
* own risk.
*
* Basically, to buffer the packet information coming in, a structure was
* needed that could organize the information according to sources,
* destinations, and unique pairs. We need a timestamp for aging and a count
* for rate information. Each of the 3 main lists contains a list of node
* (either src, dst, or pair) along with the count of instances for each unique
* node. Maybe a bit convoluted, but it works nicely now. --Hunter
*
*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "globals.h"
#include "network.h"
#include "resolver.h"
int init_net(Network* net)
{
pthread_mutex_lock(net_mutex);
if ((net->src_list = malloc(sizeof(Net_List))) == NULL)
die("malloc");
if ((net->dst_list = malloc(sizeof(Net_List))) == NULL)
die("malloc");
if ((net->pair_list = malloc(sizeof(Net_List))) == NULL)
die("malloc");
init_net_list(net->src_list);
init_net_list(net->dst_list);
init_net_list(net->pair_list);
net->timeout = 10;
pthread_mutex_unlock(net_mutex);
return 0;
}
void into_net(Network* net, Net_Obj* obj)
{
Net_List * netlist;
Net_List * new_list;
Net_Obj * new_obj;
struct in_addr in;
int flag;
unsigned char msg[NET_TO_RSLV_LEN];
unsigned char *name;
pthread_mutex_lock(net_mutex);
if (net == NULL) {
die("net is null");
}
netlist = net->src_list;
flag = SRC;
if (net_check_sublists(netlist, obj, flag) != 1) {
pthread_mutex_unlock(net_mutex);
if ((new_list = malloc(sizeof(Net_List))) == NULL)
die("malloc");
if ((new_obj = malloc(sizeof(Net_Obj))) == NULL)
die("malloc");
pthread_mutex_lock(net_mutex);
memcpy(new_obj, obj, sizeof(Net_Obj));
init_net_list(new_list);
append_net_list(netlist, new_list);
append_net_list(new_list, new_obj);
if ((name = find_cache_obj(&dnscache, new_obj->src)) == NULL) {
in.s_addr = htonl(new_obj->src);
strncpy(new_list->src, inet_ntoa(in), MAX_HOSTNAME_LEN);
msg[0] = SRC;
msg[1] = new_obj->src >> 24;
msg[2] = (new_obj->src << 8) >> 24;
msg[3] = (new_obj->src << 16) >> 24;
msg[4] = (new_obj->src << 24) >> 24;
write(net_to_rslv[1], &msg, NET_TO_RSLV_LEN);
} else {
strncpy(new_list->src, name, MAX_HOSTNAME_LEN);
}
if ((name = find_cache_obj(&dnscache, new_obj->dst)) == NULL) {
in.s_addr = htonl(new_obj->dst);
strncpy(new_list->dst, inet_ntoa(in), MAX_HOSTNAME_LEN);
} else {
strncpy(new_list->dst, name, MAX_HOSTNAME_LEN);
}
}
netlist = net->dst_list;
flag = DST;
if (net_check_sublists(netlist, obj, flag) != 1) {
pthread_mutex_unlock(net_mutex);
if ((new_list = malloc(sizeof(Net_List))) == NULL)
die("malloc");
if ((new_obj = malloc(sizeof(Net_Obj))) == NULL)
die("malloc");
pthread_mutex_lock(net_mutex);
memcpy(new_obj, obj, sizeof(Net_Obj));
init_net_list(new_list);
append_net_list(netlist, new_list);
append_net_list(new_list, new_obj);
if ((name = find_cache_obj(&dnscache, new_obj->src)) == NULL) {
in.s_addr = htonl(new_obj->src);
strncpy(new_list->src, inet_ntoa(in), MAX_HOSTNAME_LEN);
} else {
strncpy(new_list->src, name, MAX_HOSTNAME_LEN);
}
if ((name = find_cache_obj(&dnscache, new_obj->dst)) == NULL) {
in.s_addr = htonl(new_obj->dst);
strncpy(new_list->dst, inet_ntoa(in), MAX_HOSTNAME_LEN);
msg[0] = DST;
msg[1] = new_obj->dst >> 24;
msg[2] = (new_obj->dst << 8) >> 24;
msg[3] = (new_obj->dst << 16) >> 24;
msg[4] = (new_obj->dst << 24) >> 24;
write(net_to_rslv[1], &msg, NET_TO_RSLV_LEN);
} else {
strncpy(new_list->dst, name, MAX_HOSTNAME_LEN);
}
}
netlist = net->pair_list;
flag = PAIR;
if (net_check_sublists(netlist, obj, flag) != 1) {
pthread_mutex_unlock(net_mutex);
if ((new_list = malloc(sizeof(Net_List))) == NULL)
die("malloc");
pthread_mutex_lock(net_mutex);
init_net_list(new_list);
append_net_list(netlist, new_list);
append_net_list(new_list, obj);
}
pthread_mutex_unlock(net_mutex);
return;
}
int net_check_sublists(Net_List* netlist, Net_Obj* obj, int flag)
{
Net_Node * net_node = NULL;
Net_List * sublist = NULL;
Net_Node * net_sublist_node = NULL;
Net_Obj * sublist_obj = NULL;
Net_Obj * new_obj;
/* verify good non-null ptrs passed to function */
if (netlist == NULL) return -2;
if (obj == NULL) return -3;
/* verify network list (src, dst, pair) not empty_n */
net_node = netlist->head;
if (net_node == NULL) return 0;
/* loop through the nodes in the network list (src, dst, pair) */
while (net_node != NULL) {
/* verify that the sublist exists, if not, then remove the node */
sublist = (Net_List*)net_node->obj;
if (sublist == NULL) {
delete_net_list_node(netlist, net_node);
} else {
/* verify sublist is non-empty_n, if empty_n, then remove the node*/
net_sublist_node = sublist->head;
if (net_sublist_node == NULL) {
delete_net_list_node(netlist, net_node);
} else {
/* verify sublist head has object, if not, delete the node */
sublist_obj = (Net_Obj*)net_sublist_node->obj;
if (sublist_obj == NULL) {
delete_net_list_node(sublist, net_sublist_node);
} else {
switch (flag) {
/* if the sublist head has an object, switch on the flag
(src = 0, dst = 1, pair = 2) for the proper truth statement */
/* In all cases, if the objects match, return 1 (true),
otherwise increment netlist node ptr to next and try again */
case SRC:
if (obj->src == sublist_obj->src) {
if ((new_obj = malloc(sizeof(Net_Obj))) == NULL)
die("malloc");
memcpy(new_obj, obj, sizeof(Net_Obj));
append_net_list(sublist, new_obj);
return 1;
}
break;
case DST:
if (obj->dst == sublist_obj->dst) {
if ((new_obj = malloc(sizeof(Net_Obj))) == NULL)
die("malloc");
memcpy(new_obj, obj, sizeof(Net_Obj));
append_net_list(sublist, new_obj);
return 1;
}
break;
case PAIR:
if ((obj->src == sublist_obj->src) && (obj->dst == sublist_obj->dst)) {
append_net_list(sublist, obj);
return 1;
}
break;
default :
return -4;
}
}
}
}
net_node = net_node->next;
}
/* if all cases failed, then return 0 (false) */
return 0;
}
void refresh_net(Network* net)
{
struct timeval tc;
Net_List * network_list;
Net_Node * network_node;
Net_Node * next;
if (net != NULL) {
gettimeofday(&tc, NULL);
tc.tv_sec = tc.tv_sec - net->timeout;
network_list = net->src_list;
if (network_list != NULL) {
network_node = network_list->head;
while (network_node != NULL) {
next = network_node->next;
net_sublist_clear(network_list, network_node, tc);
network_node = next;
}
}
network_list = net->dst_list;
if (network_list != NULL) {
network_node = network_list->head;
while (network_node != NULL) {
next = network_node->next;
net_sublist_clear(network_list, network_node, tc);
network_node = next;
}
}
network_list = net->pair_list;
if (network_list != NULL) {
network_node = network_list->head;
while (network_node != NULL) {
next = network_node->next;
net_sublist_clear(network_list, network_node, tc);
network_node = next;
}
}
check_resolver(net);
}
return;
}
void check_resolver(Network *net)
{
unsigned char msg[RSLV_TO_NET_LEN];
int rcvd;
int len;
Net_Node *current_net_node;
Net_List *net_sublist;
Net_Node *net_node;
Net_Obj *net_obj;
Name_Obj *name_obj;
char type;
unsigned int addr;
char name[MAX_HOSTNAME_LEN];
int i;
while ((rcvd = read(rslv_to_net[0], &msg, RSLV_TO_NET_LEN)) > 0) {
len = rcvd;
for (i = 0; i < 100 && len < RSLV_TO_NET_LEN; i++) {
rcvd = read(rslv_to_net[0], &msg + len, RSLV_TO_NET_LEN - len);
len += rcvd;
}
if (len == RSLV_TO_NET_LEN) {
type = msg[0];
addr = msg[1];
addr <<= 8;
addr += msg[2];
addr <<= 8;
addr += msg[3];
addr <<= 8;
addr += msg[4];
memcpy(name, msg + 5, MAX_HOSTNAME_LEN);
/* First, append the resolved name to the cache list. */
if ((name_obj = malloc(sizeof(Name_Obj))) == NULL)
die("malloc");
name_obj->address = addr;
if ((name_obj->name = malloc(len + 1)) == NULL)
die("malloc");
strncpy(name_obj->name, name, len);
name_obj->name[len] = '\0';
append_cache_list(&dnscache, name_obj);
/* Update unresolved objects in the net list. */
switch (type) {
case SRC:
if (net->src_list != NULL) {
current_net_node = net->src_list->head;
while (current_net_node != NULL) {
net_sublist = current_net_node->obj;
if (net_sublist != NULL) {
net_node = net_sublist->head;
if (net_node != NULL) {
net_obj = net_node->obj;
if (net_obj->src == addr) {
strncpy(net_sublist->src, name, MAX_HOSTNAME_LEN);
break;
}
}
}
current_net_node = current_net_node->next;
}
}
break;
case DST:
if (net->dst_list != NULL) {
current_net_node = net->dst_list->head;
while (current_net_node != NULL) {
net_sublist = current_net_node->obj;
if (net_sublist != NULL) {
net_node = net_sublist->head;
if (net_node != NULL) {
net_obj = net_node->obj;
if (net_obj->dst == addr) {
strncpy(net_sublist->dst, name, MAX_HOSTNAME_LEN);
break;
}
}
}
current_net_node = current_net_node->next;
}
}
break;
default:
break;
}
}
}
return;
}
void empty_net(Network* net)
{
net->timeout = 0;
refresh_net(net);
}
int net_sublist_clear(Net_List* netlist, Net_Node* net_node, struct timeval tc)
{
Net_List * sublist;
Net_Node * sublist_head;
Net_Obj * obj;
int count;
sublist = net_node->obj;
if (sublist == NULL) {
obj = delete_net_list_node(netlist, net_node);
free(obj);
} else {
sublist_head = sublist->head;
if (sublist_head != NULL) obj = sublist_head->obj;
if (obj == NULL) {
obj = delete_net_list_node(sublist, sublist_head);
free(obj);
} else {
count = 0;
while((sublist_head != NULL) && (obj->ts.tv_sec < tc.tv_sec)) {
++count;
obj = (Net_Obj*)delete_net_list_head(sublist);
sublist_head = sublist->head;
free(obj);
if (sublist_head != NULL) {
obj = sublist_head->obj;
if (obj == NULL) {
obj = delete_net_list_node(sublist, sublist_head);
free(obj);
break;
}
} else break;
}
}
if (sublist_head == NULL) {
free(sublist);
delete_net_list_node(netlist, net_node);
return 1;
}
return 0;
}
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1