#! /usr/bin/env python

import sys
import time
import os
from pcapy import *
from time import gmtime, strftime

#string prekonvertujem po bajtoch do hexa podoby
def str_to_hex(string):
    hexResult = ""
    for char in string: # prejdem kazdy znak zo vstupu
        hexa = hex(ord(char)).replace('0x', '') # ziskam hexa podobu a odstranim znak "0x"
        if len(hexa) == 1: #kazdy bajt musi mat 2 zobrazene znaky
            hexResult += "0"
        hexResult += hexa
    return hexResult

# funkcia vrati zo vstupnych dat ethernet hlavicku
def ether_headerB(data):
    #etherType = str_to_hex(data[12:14])
    # nepodporuje etherType = 0 (velkost headru je 0)
    # pri nahravani cez any nemoze byt VLAN ID 1757 s priority 4
    # pri nahravani cez any musi za L2 byt hned IPv6 header
    if str_to_hex(data[12:14]) == "8100": # 802.1Q VLAN tag na beznom rozhrani (napr. eth0)
        return data[0:18]
    elif str_to_hex(data[12:14]) == "0000": # nahrate cez interface any
        if str_to_hex(data[14:16]) == "86dd": # bez VLAN
            return data[0:16]
        else: # s VLAN
            return data[0:18]
    else: # etherType
        return data[0:14]

# funkcia vrati z ethernet hlavicky zapuzdrene data
def ether_payloadB(data, headerLength):
    return data[headerLength:len(data)]

# funkcia vrati z ethernet hlavicky typ zapuzdreneho protokolu
def ether_typeH(etherHeader):
    length = len(etherHeader)
    return str_to_hex(etherHeader[length-2:length])

# funkcia vyhlada v zretazenych hlavickach ICMPv6 hlavicku
def icmpv6_headerB(data):
    if len(data) < 56: # ochrana proti chybnym packetom, ktorych dlzka nezodpoveda minimu
        return ""
    if str_to_hex(data[6:7]) == "00": # Next header: IPv6 hop-by-hop option (0x00)
        if str_to_hex(data[40:41]) == "3a": # Hop-by-Hop Option> Next header: ICMPv6 (0x3a)
            return data[48:len(data)]
    elif str_to_hex(data[6:7]) == "3a": # Next header: ICMPv6 (0x3a)
        return data[40:len(data)]
    
    return "" # prazdny string znamena, ze sa ICMPv6 hlavicka nenasla

# funkcia vyhlada v ICMPv6 hlavicke polozku Type
def icmpv6_typeH(data):
    return str_to_hex(data[0:1])

#funkcia spracovavajuca vsetky prijate data zo siete
def callback(hdr, data):
    etherHeader = ether_headerB(data) # zistenie ethernet hlavicky
    if ether_typeH(etherHeader) == "86dd": # IPv6
        ipv6Data = ether_payloadB(data, len(etherHeader)) # vysekanie dat IPv6 (odstranenie nizsich vrstev)
        icmpv6Data = icmpv6_headerB(ipv6Data) # najdenie hlavicky ICMPv6
        
        if icmpv6Data != "": # v danom pakete sa nasla ICMPv6 hlavicka
            icmpv6Type = icmpv6_typeH(icmpv6Data) # zistenie parametru Type    
            
            #if icmpv6Type == "82": # Multicast Listener Query (130), smerovac zistuje ci je nekdo v skupine
            print strftime("%d %b %Y %H:%M:%S", time.localtime()) + ": " +str_to_hex(data)
                

def main():
    if os.geteuid() != 0: # kontrola ci je user root
        print "You must be root to run this script."
        exit()
    
    reader = open_live("any", 1500, 0, 100) # zive zachytavanie
    reader.setfilter("")
    reader.loop(0, callback)


if __name__ == "__main__":
    main()
