#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <time.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <linux/in.h>
#include <linux/if_ether.h>
#include <net/if.h>
#include <netpacket/packet.h>
#include <mysql/mysql.h>
#include "thread_pool.h"
#include "get_string.h"
//#include "get_profile.h"
#define STRING_HTTP "HTTP"
#define STRING_HOST "Host: "
#define STRING_REFERER "Referer: "
//static char Host_Name[256];
int setnonblock(int fd)
{
int oldoption = fcntl(fd, F_GETFL);
int newoption = oldoption | O_NONBLOCK;
if (fcntl(fd, F_SETFL, newoption) == -1)
{ // 设置失败
perror("fcnt");
close(fd);
return -1;
}
return oldoption;
}
void insert_new_data(MYSQL DbObj, unsigned long lIp, const char *Time_String, struct tm *tblock)
{
char username[20], password[20], database[20];
char strsql[5000];
sprintf(username, "root");
sprintf(password, "1ac35de609");
sprintf(database, "count_web");
mysql_init(&DbObj);
if (NULL == mysql_real_connect(&DbObj, "localhost", username, password, database, 0, NULL, 0))
{
fprintf(stderr, "Failed to connect to database: Error:%s\n", mysql_error(&DbObj));
mysql_close(&DbObj);
exit(1);
}
sprintf(strsql, "insert visit_web_data (ip, visit_date, visit_count) values ('%ld', '%s %02d:%02d:%02d', '1')", lIp, Time_String, tblock->tm_hour, tblock->tm_min, tblock->tm_sec);
mysql_query(&DbObj, strsql);
mysql_close(&DbObj);
}
void update_count(MYSQL DbObj, unsigned long lIp, const char *Time_String, struct tm *tblock)
{
char username[20], password[20], database[20];
char strsql[5000];
MYSQL_RES *pRes; // result
MYSQL_ROW sqlrow; // row
sprintf(username, "root");
sprintf(password, "1ac35de609");
sprintf(database, "count_web");
mysql_init(&DbObj);
if (NULL == mysql_real_connect(&DbObj, "localhost", username, password, database, 0, NULL, 0))
{
fprintf(stderr, "Failed to connect to database: Error:%s\n", mysql_error(&DbObj));
mysql_close(&DbObj);
return;
}
sprintf(strsql, "select visit_date, visit_count from visit_web_data where ip = %ld", lIp);
int res = mysql_query(&DbObj, strsql);
if (res)
fprintf(stderr, "select error: %s\n", mysql_error(&DbObj));
else
{
pRes = mysql_use_result(&DbObj);
if (pRes)
{
unsigned long lCount;
char visit_date[32];
while (sqlrow = mysql_fetch_row(pRes))
{
lCount = atol(sqlrow[1]);
strcpy(visit_date, sqlrow[0]);
}
lCount++;
sprintf(strsql, "update visit_web_data set visit_count = %ld where ((ip = %ld) and (visit_date = '%s'))", lCount, lIp, visit_date);
mysql_query(&DbObj, strsql);
if((sqlrow = mysql_fetch_row(pRes)) != NULL)
{
mysql_free_result(pRes); //释放记录集
printf("Ok.\n");
}
mysql_close(&DbObj);
return;
}
else
{
insert_new_data(DbObj, lIp, Time_String, tblock);
return;
}
}
mysql_close(&DbObj);
return;
}
void *do_packet(void *arg)
{
int *psock = (int *)arg;
unsigned char buf[2048];
unsigned short wPort;
time_t timer = time(NULL);
struct tm *tblock;
unsigned long lIp, n;
char Time_String[11], *Http_Buf, *s;
MYSQL DbObj; // handle
bzero(buf, 2048);
n = recvfrom(*psock, buf, 2048, 0, NULL, NULL);
/* Check to see if the packet contains at least
* complete Ethernet (14), IP (20) and TCP/UDP
* (8) headers.
*/
if (n < 42)
{
perror("recvfrom():");
printf("Incomplete packet (errno is %d)\n", errno);
close(*psock);
exit(0);
}
if (n < 54)
return;
if ((buf[14] == 0x45) && (buf[23] == 6)) // TCP协议
{
wPort = (buf[36] << 8) + buf[37];
if (wPort == 80)
{
Http_Buf = buf + 66;
if (strstr(Http_Buf, STRING_HTTP) != NULL) // HTTP协议
{
if (strstr(Http_Buf, STRING_HOST) == NULL)
return;
tblock = localtime(&timer);
memcpy(&lIp, &buf[26], 4);
sprintf(Time_String, "%04d-", tblock->tm_year + 1900);
sprintf(Time_String + 5, "%02d-", tblock->tm_mon + 1);
sprintf(Time_String + 8, "%02d", tblock->tm_mday);
s = right_string(Http_Buf, (int)(strstr(Http_Buf, STRING_HOST) + strlen(STRING_HOST) - Http_Buf));
if (strcmp(s, Host_Name) == 0)
{
free(s);
if (strstr(Http_Buf, STRING_REFERER) != NULL)
{
s = right_string(Http_Buf, (int)(strstr(Http_Buf, STRING_REFERER) + strlen(STRING_REFERER) - Http_Buf));
if (strstr(s, Host_Name) == NULL)
{
free(s);
insert_new_data(DbObj, lIp, Time_String, tblock);
return;
}
}
else
{
insert_new_data(DbObj, lIp, Time_String, tblock);
return;
}
update_count(DbObj, lIp, Time_String, tblock);
}
free(s);
if (strstr(Http_Buf, STRING_REFERER) == NULL) // 没有REFERER,放弃
return;
s = right_string(Http_Buf, (int)(strstr(Http_Buf, STRING_REFERER) + strlen(STRING_REFERER) - Http_Buf));
if (strstr(s, Host_Name) != NULL) // REFERER不为HOST_NAME,放弃
{
free(s);
update_count(DbObj, lIp, Time_String, tblock);
}
}
}
}
}
int main(int argc, char *argv[])
{
int sock;
char EthernetCard_Name[256];
struct threadpool *pool;
struct ifreq ethreq;
int iRet = -1;
struct sockaddr_ll stLocal = {0};
if ((sock=socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP))) < 0)
{
perror("socket");
return 1;
}
if (argc != 2)
{
printf("have not enough parameters\n");
return 1;
}
strcpy(EthernetCard_Name, argv[1]);
// strcpy(Host_Name, argv[2]);
/* Set the network card in promiscuos mode */
strncpy(ethreq.ifr_name, EthernetCard_Name, IFNAMSIZ);
if (ioctl(sock, SIOCGIFFLAGS, ðreq) == -1)
{
perror("ioctl");
close(sock);
exit(1);
}
ethreq.ifr_flags |= IFF_PROMISC;
if (ioctl(sock, SIOCSIFFLAGS, ðreq) == -1)
{
perror("ioctl");
close(sock);
exit(1);
}
// if (setnonblock(sock) == -1)
// exit(1);
iRet = ioctl(sock, SIOCGIFINDEX, ðreq);
if (0 > iRet)
{
perror("[Error]Ioctl operation");
close(sock);
return -1;
}
/* 绑定物理网卡 */
stLocal.sll_family = PF_PACKET;
stLocal.sll_ifindex = ethreq.ifr_ifindex;
stLocal.sll_protocol = htons(ETH_P_ALL);
iRet = bind(sock, (struct sockaddr *)&stLocal, sizeof(stLocal));
if (0 > iRet)
{
perror("[Error]Bind the interface");
close(sock);
return -1;
}
// pool = threadpool_init(100, 20);
while (1)
{
// threadpool_add_job(pool, do_packet, &sock);
do_packet(&sock);
}
sleep(5);
// if (pool != NULL)
// threadpool_destroy(pool);
clo