Помогите с программой на С
Добавлено: 2011-07-11 9:53:57
Есть в сетке такие девайсы как пинговалки, они шлют на сервак UDP пакеты с определенным битом (наличие питалова/открытие дверцы) и если долго нет пакетов заноситься запись таблицу Mysql и потом отправляеться СМС. Я не знаком с языком СИ написал по книгам всё работает, только процесс периодически вешается. Я не знаком с отладкой. Народ взгляните на код, может куда эксепшены вставить. или какие то мои действия вызывают переполнение чего нить.
Вот код.
Компилиться Всё это барахло мэйкфайлом
Базы
Может где то откровенный бред (Например в функции get_local_ips, ну не знал я как получить средствами си все айпишки во Фре)...
Ткните плиз где тут бред написан и отчего программка может зависать
Вот код.
Код: Выделить всё
#include <pcap.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <net/ethernet.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <my_global.h>
#include <mysql.h>
#include <errmsg.h>
#include <mysqld_error.h>
#include <time.h>
#include <string.h>
#define INTERVAL 10
int howmany = 0;
const char *server = "xxxxxxxx";
const char *user = "xxxxx";
const char *password = "xxxxxxxx";
const char *database = "xxxxxxx";
MYSQL conn;
void dispatcher_handler(u_char *dumpfile,const struct pcap_pkthdr *header, const u_char *pkt_data);
void puterror(const char * str);
void alarm_wakeup (int i);
void exit_func (int i);
char * get_local_ips(char * filter);
int main(int argc, char *argv[])
{
pcap_t *handle; /* Session handle */
char *dev; /* The device to sniff on */
char *somedev;
char errbuf[PCAP_ERRBUF_SIZE]; /* Error string */
struct bpf_program fp; /* The compiled filter */
char filter_exp[1024] = "udp dst port 4000"; /* The filter expression */
bpf_u_int32 mask; /* Our netmask */
bpf_u_int32 net; /* Our IP */
struct pcap_pkthdr header; /* The header that pcap gives us */
const u_char *packet; /* The actual packet */
struct itimerval tout_val;
tout_val.it_interval.tv_sec = 0;
tout_val.it_interval.tv_usec = 0;
tout_val.it_value.tv_sec = INTERVAL; /* 10 seconds timer */
tout_val.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &tout_val,0);
signal(SIGALRM,alarm_wakeup); /* set the Alarm signal capture */
signal(SIGINT,exit_func);
get_local_ips(filter_exp);
//printf("%s\n", filter_exp);
if(!mysql_init(&conn)) puterror("Error: can't create MySQL-descriptor\n");
if(!mysql_real_connect(&conn, server, user, password, database, 0, NULL, 0)) puterror("Error: can't connect to MySQL server\n");
if(mysql_query(&conn, "SET NAMES 'cp1251'") != 0)
{
// Если кодировку установить невозможно - выводим сообщение об ошибке
fprintf(stderr, "Error: can't set character set\n");
}
dev = pcap_lookupdev(errbuf);
if (dev == NULL)
{
fprintf(stderr, "Couldn't find default device: %s\n", errbuf);
return(2);
}
/* Find the properties for the device */
if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1)
{
fprintf(stderr, "Couldn't get netmask for device %s: %s\n", dev, errbuf);
net = 0;
mask = 0;
}
/* Open the session in promiscuous mode */
handle = pcap_open_live(dev, BUFSIZ, 1, 1000, errbuf);
if (handle == NULL)
{
fprintf(stderr, "Couldn't open device %s: %s\n", somedev, errbuf);
return(2);
}
/* Compile and apply the filter */
if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1)
{
fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
return(2);
}
if (pcap_setfilter(handle, &fp) == -1)
{
fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle));
return(2);
}
pcap_loop(handle, -1, dispatcher_handler, NULL);
return(0);
}
void dispatcher_handler(u_char *dumpfile,
const struct pcap_pkthdr *header, const u_char *pkt_data)
{
struct ether_header *eptr;
u_char *ptr;
u_int i=0;
u_int datalen=0;
u_int size_ip=0;
u_int size_udp=0;
struct ip *ips;
struct udphdr *udp;
char *addr;
char *dt;
struct timeval timev;
char sql[4096];
char sms[4096];
MYSQL_RES *res;
MYSQL_ROW row;
time_t rawtime;
time (&rawtime);
struct tm * timeinfo;
timeinfo = localtime (&rawtime) ; /* to access LOCAL date/time info*/
char cur_time [128] ;
eptr = (struct ether_header *) pkt_data;
ips = (struct ip*)(pkt_data + sizeof(struct ether_header));
udp = (struct udphdr*)(pkt_data + sizeof(struct ether_header) + sizeof(struct ip));
dt = (char*)(pkt_data + sizeof(struct ether_header) + sizeof(struct ip) + sizeof(struct udphdr));
timev = header->ts;
//printf("%d.%d %s %d\n", timev.tv_sec, timev.tv_usec, inet_ntoa(ips->ip_src), (unsigned char)dt[i]);
//-------------------------------------------------------------------------
snprintf(sql, sizeof(sql), "SELECT * FROM pingovalka_main WHERE ip='%s'", inet_ntoa(ips->ip_src));
if(mysql_query(&conn, sql) != 0)
{
fprintf(stderr, "%s\n", mysql_error(&conn));
puterror("Error: can't execute SQL-query\n");
}
// Получаем дескриптор результирующей таблицы
res = mysql_store_result(&conn);
if(res == NULL) puterror("Error: can't get the result description\n");
// Если нашли пинговалку идем дальше
if(mysql_num_rows(res) > 0)
{
// В цикле перебираем все записи результирующей таблицы
while((row = mysql_fetch_row(res)) != NULL)
{
//Сначала проверим если открытая сессия... А то вдруг наша пинговалка восстала из мертвых
int status = atoi(row[6]); // on_line 0 or 1
int sendsms = atoi(row[5]); //А нужно ли слать смску
if (status!=1) //если мы не on_line то делаем новую сессию
{
snprintf(sql, sizeof(sql), "INSERT INTO pingovalka_sessions (ping_id, session_begin, bit) VALUES ('%s', '%d', '%d')", row[0], timev.tv_sec, (unsigned char)dt[i]);
if(mysql_query(&conn, sql) != 0)
{
fprintf(stderr, "Error: can't create new session\n");
}
//Send SMS UP
if (sendsms !=0) //Нужно
{
snprintf(sql, sizeof(sql), "INSERT INTO pingovalka_sms_send (time, phone, text) SELECT NOW(), \
user_phone, '%s UP' FROM pingovalka_sms ps, tbl_members tm \
WHERE ps.member_id=tm.user_id AND ps.ping_id='%s'", row[1], row[0]);
if(mysql_query(&conn, sql) != 0)
{
fprintf(stderr, "Error: can't insert SMS task\n");
}
}
//End SMS
}
//Сморим не изменился ли BIT у данной пинговалки
int new_bits=(unsigned char)dt[i];
int old_bits = atoi(row[4]); // int atoi(const char* str)
if( old_bits != new_bits)
{
//Если биты не совпали то закрываем текущую сессию
snprintf(sql, sizeof(sql), "UPDATE pingovalka_sessions SET session_end='%d' \
WHERE ping_id='%s' AND session_end=''", timev.tv_sec, row[0]);
if(mysql_query(&conn, sql) != 0)
{
fprintf(stderr, "Error: can't close session by bits\n");
}
//А теперь открываем новую с новым битом
snprintf(sql, sizeof(sql), "INSERT INTO pingovalka_sessions (ping_id, session_begin, bit) \
VALUES ('%s', '%d', '%d')", row[0], timev.tv_sec, (unsigned char)dt[i]);
if(mysql_query(&conn, sql) != 0)
{
fprintf(stderr, "Error: can't create new session\n");
}
if (sendsms !=0) //Нужно
{
///Send SMS
int BIT1 = 1;
int BIT2 = 1 << 1;
int BIT3 = 1 << 2;
int BIT4 = 1 << 3;
if((old_bits & BIT3)!=(new_bits & BIT3))
{
if (new_bits & BIT3)
{
strcat(sms, "Door Close ");
}
else
{
strcat(sms, "Door Open ");
}
}
if((old_bits & BIT4)!=(new_bits & BIT4))
{
if (new_bits & BIT4)
{
strcat(sms, "Power UP");
}
else
{
strcat(sms, "Power DOWN");
}
}
//Send SMS UP
snprintf(sql, sizeof(sql), "INSERT INTO pingovalka_sms_send (time, phone, text) SELECT NOW(), \
user_phone, '%s %s' FROM pingovalka_sms ps, tbl_members tm \
WHERE ps.member_id=tm.user_id AND ps.ping_id='%s'", row[1], sms, row[0]);
if(mysql_query(&conn, sql) != 0)
{
fprintf(stderr, "Error: can't close session by time\n");
}
strcpy(sms,"");
///END OF SEND SMS
}
}
//Если биты совпали то просто обновляем данные по пинговалке
snprintf(sql, sizeof(sql), "UPDATE pingovalka_main SET last_packet_time='%d', on_line=1, bit='%d' \
WHERE id='%s'", timev.tv_sec, (unsigned char)dt[i], row[0]);
if(mysql_query(&conn, sql) != 0)
{
fprintf(stderr, "Error: can't update pingovalka info\n");
}
}
}
else
{
//Если пинговалки нет то создаём её
strftime (cur_time, 128 , "%Y-%m-%d" , timeinfo);
snprintf(sql, sizeof(sql), "INSERT INTO pingovalka_main (adress, ip, last_packet_time, bit, sendsms, on_line, hiden) \
VALUES ('AUTO-%s', '%s', '%d', '%d','1', '1', '0')", cur_time, inet_ntoa(ips->ip_src), timev.tv_sec, (unsigned char)dt[i]);
if(mysql_query(&conn, sql) != 0)
{
fprintf(stderr, "Error: can't execute INSERT-query\n");
fprintf (stderr, sql);
}
//Создали в таблице pingovalka_main
//Получаем id только что вставленной записи
snprintf(sql, sizeof(sql), "SELECT id FROM pingovalka_main WHERE ip='%s' LIMIT 1", inet_ntoa(ips->ip_src));
if(mysql_query(&conn, sql) != 0) puterror("Error: can't execute SQL-query Select ID NEW\n");
// Получаем дескриптор результирующей таблицы
res = mysql_store_result(&conn);
if(res == NULL) puterror("Error: can't get the result description\n");
row = mysql_fetch_row(res);
//И создаём для неё сессию с временем начала её работы
snprintf(sql, sizeof(sql), "INSERT INTO pingovalka_sessions (ping_id, session_begin, bit) VALUES ('%s', '%d', '%d')", row[0], timev.tv_sec, (unsigned char)dt[i]);
if(mysql_query(&conn, sql) != 0)
{
fprintf(stderr, "Error: can't execute INSERT-query\n");
}
}
mysql_free_result(res);
//-------------------------------------------------------------------------
datalen = ntohs(ips->ip_len) - sizeof(struct ip) - sizeof(struct udphdr);
}
void puterror(const char * str)
{
fprintf(stderr, str);
}
void alarm_wakeup (int i)
{
struct itimerval tout_val;
char sql[4096];
MYSQL conn_timer;
MYSQL_RES *res_timer;
MYSQL_ROW row_timer;
signal(SIGALRM,alarm_wakeup);
howmany += INTERVAL;
if(!mysql_init(&conn_timer)) puterror("Error: can't create MySQL-descriptor\n");
if(!mysql_real_connect(&conn_timer, server, user, password, database, 0, NULL, 0)) puterror("Error: can't connect to MySQL server\n");
if(mysql_query(&conn_timer, "SET NAMES 'cp1251'") != 0)
{
// Если кодировку установить невозможно - выводим сообщение об ошибке
fprintf(stderr, "Error: can't set character set\n");
}
//Теперь смотрим если у какой то пинговалки не было в течении 2-х минут ни одного пакета, то присваиваем ей статус offline и закрываем сессию
if(mysql_query(&conn_timer, "SELECT * FROM pingovalka_main WHERE (last_packet_time < (unix_timestamp()-130)) AND on_line=1") != 0)
puterror("Error: can't get offline ping\n");
// Получаем дескриптор результирующей таблицы
res_timer = mysql_store_result(&conn_timer);
if(res_timer == NULL) puterror("Error: can't get the result description\n");
// Если нашли пинговалку идем дальше
if(mysql_num_rows(res_timer) > 0)
{
// В цикле перебираем все записи результирующей таблицы
while((row_timer = mysql_fetch_row(res_timer)) != NULL)
{
int sendsms = atoi(row_timer[5]); //А нужно ли слать смску
//присваиваем ей статус offline
snprintf(sql, sizeof(sql), "UPDATE pingovalka_main SET on_line=0 WHERE id='%s'", row_timer[0]);
if(mysql_query(&conn_timer, sql) != 0)
{
fprintf(stderr, "Error: can't execute INSERT-query\n");
}
//Закрываем её текущую сессию
snprintf(sql, sizeof(sql), "UPDATE pingovalka_sessions SET session_end=UNIX_TIMESTAMP() \
WHERE ping_id='%s' AND session_end=''", row_timer[0]);
if(mysql_query(&conn_timer, sql) != 0)
{
fprintf(stderr, "Error: can't close session by time\n");
}
if (sendsms !=0) //Нужно
{
//Add record to send sms
snprintf(sql, sizeof(sql), "INSERT INTO pingovalka_sms_send (time, phone, text) SELECT NOW(), \
user_phone, '%s Down' FROM pingovalka_sms ps, tbl_members tm \
WHERE ps.member_id=tm.user_id AND ps.ping_id='%s'",row_timer[1], row_timer[0]);
if(mysql_query(&conn_timer, sql) != 0)
{
fprintf(stderr, "Error: can't close session by time\n");
}
}
}
}
mysql_free_result(res_timer);
mysql_close(&conn_timer);
tout_val.it_interval.tv_sec = 0;
tout_val.it_interval.tv_usec = 0;
tout_val.it_value.tv_sec = INTERVAL;
tout_val.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &tout_val,0);
}
void exit_func (int i)
{
signal(SIGINT,exit_func);
mysql_close(&conn);
printf("\nBye Bye!!!\n");
exit(0);
}
char * get_local_ips(char * filter)
{
FILE *fpipe;
char *command="ifconfig | grep -E 'inet.[0-9]' | awk '{ print $2}'";
char local_ip[256];
if (!(fpipe = (FILE*)popen(command,"r")))
{
perror("Problems with pipe");
}
while(fgets(local_ip, sizeof local_ip, fpipe))
{
strcat(filter, " and not src host ");
local_ip[strlen(local_ip)-1]=0;
strcat(filter, local_ip);
}
pclose(fpipe);
return filter;
}
Код: Выделить всё
link_flags:= -I/usr/local/include/mysql
ping_d: ping_d.o
g++ ping_d.o -o ping_d -lpcap -L/usr/local/lib/mysql -lmysqlclient
ping_d.o: ping_d.cpp
g++ -c $(link_flags) ping_d.cpp
clean:
rm *.o
Код: Выделить всё
mysql> DESCRIBE pingovalka_main;
+------------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+------------------+------+-----+---------+----------------+
| id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| adress | varchar(255) | NO | | NULL | |
| ip | varchar(18) | NO | | NULL | |
| last_packet_time | varchar(255) | NO | | NULL | |
| bit | int(2) | NO | | 0 | |
| sendsms | tinyint(1) | NO | | NULL | |
| on_line | tinyint(1) | NO | | 0 | |
| hiden | tinyint(1) | NO | | 0 | |
| def_bit | int(2) | NO | | 0 | |
+------------------+------------------+------+-----+---------+----------------+
mysql> DESCRIBE pingovalka_sessions;
+---------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------------+------+-----+---------+----------------+
| session_id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| ping_id | int(11) | NO | | NULL | |
| session_begin | varchar(255) | NO | | NULL | |
| session_end | varchar(255) | NO | | NULL | |
| bit | tinyint(2) | NO | | NULL | |
+---------------+------------------+------+-----+---------+----------------+
mysql> DESCRIBE pingovalka_sms;
+-----------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+----------------+
| id_record | int(11) | NO | PRI | NULL | auto_increment |
| ping_id | int(11) | NO | | NULL | |
| member_id | int(11) | NO | | NULL | |
+-----------+---------+------+-----+---------+----------------+
mysql> DESCRIBE pingovalka_sms_send;
+--------+----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+----------------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| time | varchar(100) | NO | | NULL | |
| phone | varchar(20) | NO | | NULL | |
| text | varchar(160) | NO | | NULL | |
| status | smallint(1) unsigned | NO | | 0 | |
+--------+----------------------+------+-----+---------+----------------+
Ткните плиз где тут бред написан и отчего программка может зависать