Пример кода для учета трафика пересылаемого через ipfw divert (traffic isp log freebsd ipfw divert)
Ключевые слова: traffic, isp, log, freebsd, ipfw, divert, (найти похожие документы)
Date: Tue, 30 Mar 2004 11:46:27 +0600
From: Denis Sotchenko <[email protected]>
Newsgroups: ftn.ru.unix.prog
Subject: Пример кода для учета трафика пересылаемого через ipfw divert
SM> Hе подскажешь ли, где можно посмотреть исходные тексты или
SM> примеры программ или их частей, осуществляющих подсчет
SM> интернет - трафика и упраление им?
Пример реализации из моего биллинга:
(FreeBSD)
=== cut ===
trafficd()
{
while(1)
{
byte checkbuf[20000];
struct sockaddr_in divertaddr;
int bytes, divertaddrSize = sizeof(divertaddr);
if((bytes = recvfrom (divertsock, checkbuf, sizeof(checkbuf),
0, (struct sockaddr*) &divertaddr, &divertaddrSize)) > 20)
{
struct clientry *clientsrc = getaddrblock(&checkbuf[12]);
struct clientry *clientdst = getaddrblock(&checkbuf[16]);
if((clientsrc || clientdst) && !(clientsrc && clientdst))
{
byte *sideip = clientsrc?&checkbuf[16]:&checkbuf[12];
struct clientry *client = clientsrc?clientsrc:clientdst;
struct network *network = client->network;
struct tariff *tariff = client->tariff;
int whiteaddrcount = whiteaddrnum, whiteaddr = 0;
while(whiteaddrcount--)
{
if(!memcmp(sideip,&whiteaddrs[whiteaddrcount],4))
{
whiteaddr = 1;
}
}
if(whiteaddr)
{
sendto(divertsock, checkbuf, bytes, 0,
(struct sockaddr*)&divertaddr, divertaddrSize);
continue;
}
if(!((*sideip == 10) ||
((*sideip == 192) &&
(*(sideip+1) == 168)) ||
((*sideip == 172) &&
((*(sideip+1) & 0xF0) == 16))))
{
if((client->balance > client->threshold) ||
((!tariff->prepay) &&
(client->in_current < tariff->in_overpay[0]) &&
(client->out_current < tariff->out_overpay[0])))
{
sendto(divertsock, checkbuf, bytes, 0,
(struct sockaddr*)&divertaddr, divertaddrSize);
if(clientdst)
{
network->in_current += bytes;
client->in_current += bytes;
if(client->in_current >= client->in_threshold)
{
client->in_threshold += tariff->in_overpay[0];
if(++client->in_trafpay > client->out_trafpay)
{
client->balance--;
}
}
}
else
{
network->out_current += bytes;
client->out_current += bytes;
if(client->out_current >= client->out_threshold)
{
client->out_threshold += tariff->out_overpay[0];
if(++client->out_trafpay > client->in_trafpay)
{
client->balance--;
}
}
}
}
}
}
}
}
}
=== cut ===
struct clientry содержит все данные по пользователю.
getaddrblock даёт указатель на неё по IP-адресу.
whiteaddrs - адреса без тарификации, например страница статистики.
открывается сокет так:
=== cut ===
if((divertsock = socket(PF_INET, SOCK_RAW, IPPROTO_DIVERT)) > 0)
{
struct sockaddr_in trafficaddr;
memset(&trafficaddr,0,sizeof(trafficaddr));
trafficaddr.sin_family = AF_INET;
trafficaddr.sin_port = htons(_PORT);
trafficaddr.sin_addr.s_addr = INADDR_ANY;
if(!bind(divertsock, (struct sockaddr *)
&trafficaddr,sizeof(trafficaddr)))
{
if(-1 != rfork_thread(RFPROC|RFNOWAIT|RFMEM|RFSIGSHARE,
&trafstack[TRAFSTACKSIZE],trafficd,0))
{
[обработка соединений от CGI-программы]
}
}
}
=== cut ===
Траффик направляется в этот сокет при помощи ipfw divert.