/*
* 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.
*/
#include <fcntl.h>
#include <mysql/mysql.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include "db.h"
#include "globals.h"
#include "queue.h"
void into_db(Packet_Headers *p, struct timeval *ts)
{
struct db_item *item;
if ((item = malloc(sizeof(struct db_item))) == NULL)
die("malloc");
item->p = p;
item->ts = *ts;
free(ts);
pthread_mutex_lock(db_mutex);
STAILQ_INSERT_TAIL(&db_q, item, entries);
pthread_mutex_unlock(db_mutex);
return;
}
void init_db(struct db_info **db, char *filename)
{
int fd;
int i;
char str[256];
char *user;
char *pass;
char *host;
char *port;
char *name;
char *type;
if ((*db = malloc(sizeof(struct db_info))) == NULL)
die("malloc");
if (((*db)->user = malloc(DB_INFO_LEN)) == NULL)
die("malloc");
if (((*db)->passwd = malloc(DB_INFO_LEN)) == NULL)
die("malloc");
if (((*db)->host = malloc(DB_INFO_LEN)) == NULL)
die("malloc");
if (((*db)->db = malloc(DB_INFO_LEN)) == NULL)
die("malloc");
(*db)->user = NULL;
(*db)->passwd = NULL;
(*db)->host = NULL;
(*db)->port = 3306;
(*db)->db = "tvark";
(*db)->type = DB_MYSQL;
if (filename == NULL)
return;
if ((fd = open(filename, O_RDONLY)) == -1)
die("open");
read(fd, str, 256);
for (i = 0; i < 256; ++i) {
if (str[i] == '\n') {
str[i] = '\0';
break;
}
}
user = strtok(str, "@");
host = strtok(NULL, " \t");
name = strtok(NULL, "");
if (user != NULL) {
user = strtok(user, ":");
pass = strtok(NULL, "");
}
if (host != NULL) {
host = strtok(host, ":");
port = strtok(NULL, "");
}
if (name != NULL) {
name = strtok(name, " \t");
type = strtok(NULL, "");
}
if (user != NULL) (*db)->user = strdup(user);
if (pass != NULL) (*db)->passwd = strdup(pass);
if (host != NULL) (*db)->host = strdup(host);
if (port != NULL) (*db)->port = atoi(port);
if (name != NULL) (*db)->db = strdup(name);
if (type != NULL) {
if (!strcmp(type, "mysql"))
(*db)->type = DB_MYSQL;
else
die("bad database type");
}
close(fd);
return;
}
void *db_engine(void *arg)
{
struct db_info *db;
struct db_item *item;
MYSQL mysql;
db = arg;
/* Open database connection. */
switch (db->type) {
case DB_MYSQL:
mysql_init(&mysql);
if (mysql_real_connect(&mysql, db->host, db->user,
db->passwd, db->db, db->port, NULL, 0) == NULL)
die("could not connect to database");
break;
default:
die("unknown database type");
}
for (;;) {
while (STAILQ_EMPTY(&db_q));
pthread_mutex_lock(db_mutex);
item = STAILQ_FIRST(&db_q);
STAILQ_REMOVE_HEAD(&db_q, entries);
pthread_mutex_unlock(db_mutex);
/* Switch on db type and insert data from item->p */
switch (db->type) {
case DB_MYSQL:
insert_mysql(&mysql, item);
break;
default:
die("unknown database type");
}
free(item->p);
free(item);
}
/* Close database connection. */
switch (db->type) {
case DB_MYSQL:
mysql_close(&mysql);
break;
default:
die("unknown database type");
}
return NULL;
}
void insert_mysql(MYSQL *mysql, struct db_item *item)
{
Packet_Headers *p;
struct timeval ts;
char query[256];
p = item->p;
ts = item->ts;
snprintf(query, 256,
"insert into eth_header values(%d.%d, "
"\"%02x:%02x:%02x:%02x:%02x:%02x\", "
"\"%02x:%02x:%02x:%02x:%02x:%02x\", %u)",
ts.tv_sec, ts.tv_usec,
p->ll.eth->eth_src[0], p->ll.eth->eth_src[1], p->ll.eth->eth_src[2],
p->ll.eth->eth_src[3], p->ll.eth->eth_src[4], p->ll.eth->eth_src[5],
p->ll.eth->eth_dst[0], p->ll.eth->eth_dst[1], p->ll.eth->eth_dst[2],
p->ll.eth->eth_dst[3], p->ll.eth->eth_dst[4], p->ll.eth->eth_dst[5],
p->ll.eth->eth_typ);
mysql_query(mysql, query);
free(p->ll.eth);
if (p->type == tcp_t || p->type == udp_t
|| p->type == icmp_t || p->type == igmp_t) {
snprintf(query, 256,
"insert into ip_header values(%d.%d, "
"%u, %u, %d, %u, %u, %u, %d, %d, %u, "
"%u, %u, %u, %u, %u, \"\", " /* src */
"%u, %u, %u, %u, %u, \"\")", /* dst */
ts.tv_sec, ts.tv_usec,
p->nl.ip->ip_hdr_len,
p->nl.ip->ip_ver,
p->nl.ip->ip_tos,
p->nl.ip->ip_pkt_len,
p->nl.ip->ip_id,
p->nl.ip->ip_frg_off,
p->nl.ip->ip_ttl,
p->nl.ip->ip_protocol,
p->nl.ip->ip_chksum,
p->nl.ip->ip_src,
p->nl.ip->ip_src >> 24,
p->nl.ip->ip_src << 8 >> 24,
p->nl.ip->ip_src << 16 >> 24,
p->nl.ip->ip_src << 24 >> 24,
p->nl.ip->ip_dst,
p->nl.ip->ip_dst >> 24,
p->nl.ip->ip_dst << 8 >> 24,
p->nl.ip->ip_dst << 16 >> 24,
p->nl.ip->ip_dst << 24 >> 24);
mysql_query(mysql, query);
free(p->nl.ip);
}
switch (p->type) {
case arp_t:
snprintf(query, 256,
"insert into arp_header values(%d.%d, "
"%u, %u, %d, %d, %u, "
"\"%02x:%02x:%02x:%02x:%02x:%02x\", "
"\"%02x:%02x:%02x:%02x:%02x:%02x\", "
"%u, %u)",
ts.tv_sec, ts.tv_usec,
p->nl.arp->arp_hrd_typ,
p->nl.arp->arp_prt_typ,
p->nl.arp->arp_hrd_len,
p->nl.arp->arp_prt_len,
p->nl.arp->arp_typ,
p->nl.arp->arp_sdr_mac[0], p->nl.arp->arp_sdr_mac[1],
p->nl.arp->arp_sdr_mac[2], p->nl.arp->arp_sdr_mac[3],
p->nl.arp->arp_sdr_mac[4], p->nl.arp->arp_sdr_mac[5],
p->nl.arp->arp_tgt_mac[0], p->nl.arp->arp_tgt_mac[1],
p->nl.arp->arp_tgt_mac[2], p->nl.arp->arp_tgt_mac[3],
p->nl.arp->arp_tgt_mac[4], p->nl.arp->arp_tgt_mac[5],
(p->nl.arp->arp_sdr_ip[0] << 24) +
(p->nl.arp->arp_sdr_ip[1] << 16) +
(p->nl.arp->arp_sdr_ip[2] << 8) +
(p->nl.arp->arp_sdr_ip[3]),
(p->nl.arp->arp_tgt_ip[0] << 24) +
(p->nl.arp->arp_tgt_ip[1] << 16) +
(p->nl.arp->arp_tgt_ip[2] << 8) +
(p->nl.arp->arp_tgt_ip[3]));
mysql_query(mysql, query);
free(p->nl.arp);
break;
case tcp_t:
snprintf(query, 256,
"insert into tcp_header values(%d.%d, "
"%u, %u, %u, %u, %u, %u, %u, %u, %u, %u)",
ts.tv_sec, ts.tv_usec,
p->tl.tcp->tcp_src_port,
p->tl.tcp->tcp_dst_port,
p->tl.tcp->tcp_seq_num,
p->tl.tcp->tcp_ack_num,
p->tl.tcp->tcp_reserved,
p->tl.tcp->tcp_hdr_len,
p->tl.tcp->tcp_flags,
p->tl.tcp->tcp_win_siz,
p->tl.tcp->tcp_chksum,
p->tl.tcp->tcp_urg_ptr);
mysql_query(mysql, query);
free(p->tl.tcp);
break;
case udp_t:
snprintf(query, 256,
"insert into udp_header values(%d.%d, "
"%u, %u, %u, %u)",
ts.tv_sec, ts.tv_usec,
p->tl.udp->udp_src_port,
p->tl.udp->udp_dst_port,
p->tl.udp->udp_len,
p->tl.udp->udp_chksum);
mysql_query(mysql, query);
free(p->tl.udp);
break;
case icmp_t:
snprintf(query, 256,
"insert into icmp_header values(%d.%d, "
"%u, %u, %u)",
ts.tv_sec, ts.tv_usec,
p->tl.icmp->icmp_typ,
p->tl.icmp->icmp_code,
p->tl.icmp->icmp_chksum);
mysql_query(mysql, query);
free(p->tl.icmp);
break;
case igmp_t:
snprintf(query, 256,
"insert into igmp_header values(%d.%d, "
"%u, %u, %u, %u)",
ts.tv_sec, ts.tv_usec,
p->tl.igmp->igmp_typ,
p->tl.igmp->igmp_ver,
p->tl.igmp->igmp_chksum,
p->tl.igmp->igmp_addr);
mysql_query(mysql, query);
free(p->tl.igmp);
break;
case unknown_t:
/* FALLTHROUGH */
default:
break;
}
return;
}
syntax highlighted by Code2HTML, v. 0.9.1