[PHP] Tijdafhankelijke IP-to-ID vervanger

Pagina: 1
Acties:

  • DRvDijk
  • Registratie: Juni 2001
  • Laatst online: 08-09 17:10
Ik zit met een IP-to-ID probleem. Ik heb grote log-files (4000 regels per dag), en die wil ik korter in een database proppen. In die database moet echter geen IP komen te staan, maar een ID. In de tabel hosts staan de IP(-mask)s + tijden van welke ID welke IP had:
code:
1
2
3
4
5
6
7
8
  Hosts data
* id       * id
* ip1     * date
* ip2     * hits
* ip3
* ip4
* startdate
* enddate

De logbestanden worden ongeveer zo aangeleverd:

Log-bestanden
date
ip
hits

Wat de PHP dus moet doen:
Logbestand openen
IP eruit vissen
Vervangen door de desbetreffende ID (als die niet gedefinieerd is ID 0)
In de DB proppen

Dit kan ik doen met een lang loopje per regel, maar zoals ik al zei: de logbestanden zijn zo'n 4000 regels per dág, en het gaat al om een jaar of 2 aan logbestanden. Ik ben dus erg hard op zoek naar een beter algoritme, maar zou niet meer weten hoe ik de data uit de logfiles snél controleer..

PS: De IP's zijn opgedeeld in 4 stukken (TINYINT UNSIGNED), zodat ik dubbele IP's kan vangen: SELECT * from hosts order by ip4 desc, ip3 desc, ip2 desc, ip1, desc; Dan krijg ik het in de goeie volgorde terug: Degene met de eerste match is het specifiekste; als er een entry bestaat voor 192.168.0.2 komt die boven de entry 192.168.0.null te staan.

Ik hoop dat deze zut een beetje duidelijk is, anders wil ik het graag herformuleren :) Thenkz!

  • Grum
  • Registratie: Juni 2001
  • Niet online
ip's wil je liever opslaan in hun 'long' formaat opslaan

zie: http://www.mysql.com/doc/M/i/Miscellaneous_functions.html
INET_NTOA(expr)
Given a numeric network address (4 or 8 byte), returns the dotted-quad representation of the address as a string:
code:
1
2
mysql> select INET_NTOA(3520061480);
     ->  "209.207.224.40"

INET_ATON(expr)
Given the dotted-quad representation of a network address as a string, returns an integer that represents the numeric value of the address. Addresses may be 4 or 8 byte addresses:
code:
1
2
mysql> select INET_ATON("209.207.224.40");
     ->  3520061480

The generated number is always in network byte order; For example the above number is calculated as 209*256^3 + 207*256^2 + 224*256 +40.

  • DRvDijk
  • Registratie: Juni 2001
  • Laatst online: 08-09 17:10
Ik zit even te denken aan die longip.. Het is inderdaad zeer handig, maar niet voor mijn toepassing in dit geval denk ik, of er moeten andere ideeën zijn?

Ik wil masks aan een ID hangen. Met mijn manier van opslaan is het makkelijk dubbele entry's te ontlopen. ip1, ip2, ip3 en ip4. Stel daar zitten de IP-adressen 192.168.0. en 192.168.0.2 in. Dan doe ik in de query:
SELECT * FROM hosts ORDER BY ip4 DESC, ip3 DESC, ip2 DESC, ip1 DESC;
Dan krijg ik:
192 168 0 2
192 168 0
Het COMPLETE IP komt BOVEN de mask te staan. Zo kan ik in de hosts-tabel masks invoegen die single IP's overlappen, maar toch goed gaan. Bij het assignen check ik het in de volgorde dat ik in de gegeven query terugkrijg. Bij de eerste hit breakt ie. Losse IP's zijn op deze manier specifieker dan masks, en da's exact de bedoeling.

Tijdens mijn brainstorm hier kreeg ik niet spontaan een idee hoe ik dat moet doen met long-ip's. Iemand anders wel?

  • DRvDijk
  • Registratie: Juni 2001
  • Laatst online: 08-09 17:10
Hmm brainstorm gaat door :)

Me hosts-tabel zou er dan zo uitzien:
ID, startIP, endIP, startdate, enddate

IP's in long format. Een enkel IP zou dan een gelijk startIP als endIP hebben.

Om de volgorde in de query alsnog goed te krijgen dacht ik ineens aan een query als:
SELECT * FROM hosts ORDER BY (endIP - beginIP);
Zit ik hier alleen op me werk achter een héérlijke proxy die geen ander verkeer doorlaat dan poort 80.. Dus kan ik het niet testen. Dat doe ik vanaaf dan wel, of jullie moeten het verlossende woord geven :)

  • DRvDijk
  • Registratie: Juni 2001
  • Laatst online: 08-09 17:10
Koel Grum! :) Volgens mij moet het kunnen gaan werken! :D Ik kan het alleen niet testen, maar dat doe ik vanaaf wel even :) Ik plak hier ff de code neer, mochten er mensen zijn die het willen zien, en voor mezelf voor vanavond.
PHP:
1
<?function getid ($longip, $timestamp) {  // get the hosts from the db  if (!$gothosts) {    $result = mysql_query ("SELECT id, startip, endip, startdate, enddate FROM hosts ORDER BY (endip - startip)");    while ($temp = mysql_fetch_array ($result) {      $hosts[$temp[0]][0] = $temp[1];      $hosts[$temp[0]][1] = $temp[2];      $hosts[$temp[0]][2] = $temp[3];      $hosts[$temp[0]][3] = $temp[4];    }    $gothosts = true;  }  // search the correct id  foreach ($hosts as $key, $value) {    if (($longip => $value[0]) &amp;&amp; ($longip =< $value[1]) &amp;&amp; ($timestamp => $value[2]) &amp;&amp; (($timestamp =< $value[3]) || ($value[3] == 0))) {      return ($key);    }    else { return 0; }  }}?>

de database-tabel hosts:
id [smallint unsigned not null]
startip [int unsigned not null]
endip [int unsigned not null]
startdate [timestamp]
enddate [timestamp]

Daarin zitten bijvooreeld de rows:
1,3232235520,3232235775,0,0
2,3232235522,3232235522,0,0

De query zou terug moeten geven:
2,3232235522,3232235522,0,0
1,3232235520,3232235775,0,0

De functie getid die aangeroepen is volgens getid(3232235521, <hum, unix_timestamp>) zou dan moeten teruggeven: 1

*D :) *D :) *D Kan al niet wachten tot 5 over 5 als ik weer thusi ben *D