next up previous contents
Next: Listing von mib_gets.pl Up: Listings zum Subagenten Previous: Listing von subagent_start

Listing von subagent_standard.pl

# snmp - Subagent in Perl implementiert

sub Subagent {

########################################################
# Beginn des Hauptprogramms
########################################################

&initial_MIB;    # Intialisiere die MIB fuer den Subagenten

# Ermitteln des TCP-Port's, der fuer die DPI-Kommunikation
# mit dem Agenten benutzt werden soll.
$Port = &qDPIport;
print "Port:$Port\n";

# Ueber den ermittelten Port eine TCP-Verbindung zum Agenten
# aufbauen (fuer die DPI-Kommunikation) => Handle: DPI_Anschluss
&TCPConnect($Port);

# Oeffnen der DPI-Verbindung
&DPI_Open;
sleep 1;

# Registrieren des Teilbaums
&DPI_Register; 

#--------------------------------------------------------------
# Warten auf eine Anfrage 
while(!($Wert{'99.0'} == 0))    # Warten auf DPI-Anfragen des Agenten
    {
    if ($Wert{'99.0'} == 2)    # Falls www-Skript starten
        {        # zuerst Tabelle zuruecksetzen
        @Links = keys(%Links);
        foreach (@Links)
            {
            delete $Links{$_};
            }
        foreach (@MIB)
            {
            delete $MIB{$_};
            }
        &initial_MIB;
        $Wert{'99.0'} = 1;
        $WertTemp{'99.0'}=1;    
        unless (fork)    # Parallel f starten
            {
            exec($ProgDatei);
            exit;
            }
        }        

    recv(DPI_Anschluss,$Laenge,2,0);
    $Laenge = unpack("n",$Laenge);
    recv(DPI_Anschluss,$dpi_packet,$Laenge,0);    
    @dpi_header = unpack("H2H2H2nH2",$dpi_packet);    # Header auslesen
    
    if ($dpi_header[4] eq "01")    # Falls get-Request
        {
        print "Get-Request empfangen\n";
        &answer_get;        # Beantworte get-Request
        }
    elsif ($dpi_header[4] eq "02")    # falls getnext-Request
        {
        print "Getnext-Request empfangen\n";
        &answer_getnext;    # Beantworte getnext-Request
        }    
    elsif ($dpi_header[4] eq "03" || $dpi_header[4] eq "0a" || $dpi_header[4] eq "0b")
        {    # falls set-Request Gruppe
        &answer_setgrp($dpi_header[4]);    
        }
    elsif ($dpi_header[4] eq "05")    # falls Response
        {
        print "Response empfangen\n";
        next;
        }    
    else
        {
        print "Undefinierbare Nachricht empfangen\n";
        print "gemeldeter Packettyp: $dpi_header[5]\n";
        }
    } 
#--------------------------------------------------------------
# Unregistrieren des Teilbaums
&DPI_UnRegister;

# Schliessen der DPI-Verbindung
&DPI_Close;

# Schliessen des Handles fuer die TCP-Verbindung zum Agenten
close(DPI_Anschluss);
} 
########################################################
# Ende des Hauptprogramms
########################################################

############################################################
# answer_setgrp(Art)
# Zerlegen des jeweiligen Packets und wenn moeglich Beantwortung
# Parameter: Art,    Set ="03", Commit="0a", Undo="0b"
############################################################
sub answer_setgrp
    {
    # Uebernahme der Parameter
    local($Art)=@_;
    # Lokale Variablen
    local($GID,$GID_Laenge,$InstID,$InstID_Laenge,$WertTemp);    

    @dpi_get = unpack("H2H2H2nH2n",$dpi_packet);
    $dpi_get_packet_id = $dpi_get[3]; # Fuer Antwort merken        
    $ComNameLaenge = $dpi_get[5];
    if ($ComNameLaenge)    # Falls ein Community-Name vorhanden
        {
        $Position = 7;    # Beginn der GID im Array
        $UnpackString = "H2H2H2nH2nA$dpi_get[5]"."H2" x ($Laenge-8-$ComNameLaenge);
        }
    else            # Falls kein Community-Name vorhanden
        {
        $Position = 6;    # Beginn der GID im Array
        $UnpackString = "H2H2H2nH2n"."H2" x ($Laenge-8);
        }        

    @dpi_get = unpack($UnpackString,$dpi_packet);    
    while (!($dpi_get[$Position] eq "00")) # GID ermitteln (vorerst hex)
        {
        $GID_Laenge++;
        $NewGID = unpack("A",pack("H2",$dpi_get[$Position]));
        $GID = $GID.$NewGID;
        $Position++;
        }
    $Position++;
    while (!($dpi_get[$Position] eq "00")) 
        {
        $InstID_Laenge++;
        $NewInstID = unpack("A",pack("H2",$dpi_get[$Position]));
        $InstID = $InstID.$NewInstID;
        $Position++;
        }
    $Position++;
    $Set_Typ = $dpi_get[$Position];
    $Position++;
    $Set_Laenge = hex($dpi_get[$Position])*16 + hex($dpi_get[$Position+1]);
    $Position = $Position + 2;
    for ($i = $Position; $i <= @dpi_get; $i++)
        {
        $Set_Wert[$i-$Position] = $dpi_get[$i];
        }

    &answer_set2($GID,$InstID,$Art,$dpi_get_packet_id,$Set_Typ,$Set_Laenge,
                                                                  @Set_Wert);    
    }
    
############################################################
# answer_get
# Zerlegen des get-Packets und wenn moeglich Beantwortung
############################################################
sub answer_get
    {
    # Lokale Variablen
    local($GID,$GID_Laenge,$InstID,$InstID_Laenge);    

    @dpi_get = unpack("H2H2H2nH2n",$dpi_packet);
    $dpi_get_packet_id = $dpi_get[3]; # Fuer Antwort merken        
    $ComNameLaenge = $dpi_get[5];
    if ($ComNameLaenge)    # Falls ein Community-Name vorhanden
        {
        $Position = 7;    # Beginn der GID im Array
        $UnpackString = "H2H2H2nH2nA$dpi_get[5]"."H2" x ($Laenge-8-
                                                            $ComNameLaenge);
        }
    else            # Falls kein Community-Name vorhanden
        {
        $Position = 6;    # Beginn der GID im Array
        $UnpackString = "H2H2H2nH2n"."H2" x ($Laenge-8);
        }        

    @dpi_get = unpack($UnpackString,$dpi_packet);    
    while (!($dpi_get[$Position] eq "00")) # GID ermitteln (vorerst hex)
        {
        $GID_Laenge++;
        $NewGID = unpack("A",pack("H2",$dpi_get[$Position]));
        $GID = $GID.$NewGID;
        $Position++;
        }
    $Position++;
    while (!($dpi_get[$Position] eq "00")) 
        {
        $InstID_Laenge++;
        $NewInstID = unpack("A",pack("H2",$dpi_get[$Position]));
        $InstID = $InstID.$NewInstID;
        $Position++;
        }
    print "$GID   ";        
    print "$InstID\n";
    &answer_get2($GID,$InstID,$dpi_get_packet_id); # Auf ermittelte Anfrage antw.
    }

############################################################
# answer_getnext
# Zerlegen des getnext-Packets und wenn moeglich Beantwortung
############################################################
sub answer_getnext
    {
    # Lokale Variablen
    local($GID,$GID_Laenge,$InstID,$InstID_Laenge,$MIBInst);    

    @dpi_get = unpack("H2H2H2nH2n",$dpi_packet);
    $dpi_get_packet_id = $dpi_get[3]; # Fuer Antwort merken        
    $ComNameLaenge = $dpi_get[5];
    if ($ComNameLaenge)    # Falls ein Community-Name vorhanden
        {
        $Position = 7;    # Beginn der GID im Array
        $UnpackString = "H2H2H2nH2nA$dpi_get[5]"."H2" x ($Laenge-8-$ComNameLaenge);
        }
    else            # Falls kein Community-Name vorhanden
        {
        $Position = 6;    # Beginn der GID im Array
        $UnpackString = "H2H2H2nH2n"."H2" x ($Laenge-8);
        }        

    @dpi_get = unpack($UnpackString,$dpi_packet);    
    while (!($dpi_get[$Position] eq "00")) # GID ermitteln (vorerst hex)
        {
        $GID_Laenge++;
        $NewGID = unpack("A",pack("H2",$dpi_get[$Position]));
        $GID = $GID.$NewGID;
        $Position++;
        }
    $Position++;
    while (!($dpi_get[$Position] eq "00")) 
        {
        $InstID_Laenge++;
        $NewInstID = unpack("A",pack("H2",$dpi_get[$Position]));
        $InstID = $InstID.$NewInstID;
        $Position++;
        }
    print "$GID";        
    print "   $InstID\n";

    #################################################################
    # Gesuchten Wert ermitteln
    if (!($GID eq $GROUPID))    # Falls der Subagent fuer diese Group-ID
        {             # nicht zustaendig
        &ResponseError($dpi_get_packet_id,"05") # Allgemeiner Fehler
        }

    $NextID = "";

    foreach $MIBInst (@MIB)
        {
        if (&less_by_hierarchy($MIBInst,$InstID) <= 0)
            {
            next;
            }

        $NextID = $MIBInst;
        last;
        }
    if ($NextID eq "")
        {
        $Next = "11";    # SNMP_TYPE_endOfMibView
        }
    else
        {
        $Next = undef;    
        }
    &answer_get2($GID,$NextID,$dpi_get_packet_id,$Next);#Auf ermittelte Anfr. antw.
    }

######################################################################
# ResponseSuccess(Paket-Id,GID,InstID,Typ,Wert)
# Aufbauen eines Response-Pakets als Antwort auf eine Anfrage.
# Parameter:    Paket-Id, Paket-ID der Anfrage
#        GID,      Group-ID nach der gefragt wurde
#        InstID,   Instanz-ID nach der gefragt wurde
#        Typ,      Typ des Rueckgabewerts, vgl. RFC1592,Tab.17 aber hex
#        Wert,      Rueckgabewert       
######################################################################
sub ResponseSuccess
    {
    # Uebernahme der Parameter
    local($dpi_Packet_ID,$GID,$InstID,$Wert) = @_;

    if(!($Wert eq "ENDofMIB"))
        {
        $Typ = $MIB{$InstID};
        }
    else
        {
        $Typ = "11";
        }

    # Bestimmen der Laengen der Strings (auch abhaengig vom Typ)
    $GID_Laenge = length($GID);
    $Inst_Laenge = length($InstID);
    if ($Typ eq "02")    # Falls Typ = SNMP_TYPE_OCTET_STRING
        {
        $Wert_Laenge = length($Wert);
        $Wert_PackString = "A".$Wert_Laenge;
        }
    elsif ($Typ eq "03")    # Falls Typ = SNMP_TYPE_OBJECT_IDENTIFIER
        {
        $Wert_Laenge = length($Wert);
        $Wert_PackString = "A".$Wert_Laenge;
        }
    elsif ($Typ eq "11")    # Falls Typ = SNMP_TYPE_endOfMibView
        {
        print "EndofMib\n";
        $Wert_Laenge = 0;
        $Wert_PackString = "";
        }
    elsif ($Typ eq "81")    # Falls Typ = SNMP_TYPE_Integer32
        {
        $Wert_Laenge = 4;
        $Wert_PackString = "N";
        }
    else            # Falls unbekannter Typ
        {
        print "Unbekannter Typ: $Typ\n";
        return;
        }
    
    # Aufbauen des Pack-Strings
    $PackString = "H2H2H2nH2H2H8A".$GID_Laenge."xA".$Inst_Laenge."xH2n".
                                                             $Wert_PackString;

    ####################################################
    # Paket ohne Feld Paketlaenge zusammensetzen
    $dpi_Packet = pack($PackString,
                # Head-Beginn
                "02",    # Protokol Haupt Version
                "02",    # Protokol Niedere Version
                "00",    # Protokol Release
                $dpi_Packet_ID,
                "05",    # Typ: Response-Packet
                # Head-Ende
                "00",    # Fehlercode
                "00000000",    # Fehlerindex
                $GID,    # Group-ID
                $InstID,# Instanz-ID
                $Typ,    # Typ der Variablen
                $Wert_Laenge,    # Laenge des Werts
                $Wert    # Rueckgabewert             
               );
    ####################################################
    # Paketlaenge ermitteln
    $Laenge = length($dpi_Packet);        # Laenge des Packets ermitteln  
    $dpi_Packet_Length = pack("n",$Laenge);# Laenge des Packets in 
                                           # eigenes Paket legen
        
    # Pakete verschicken
    print DPI_Anschluss $dpi_Packet_Length.$dpi_Packet;
    print "Success-Response verschickt\n";
    }

######################################################################
# SendTrap(GenTrapCode,SpecTrapCode,Enterprise,GID,InstID,Typ,Wert)
# Aufbauen eines Trap-Pakets und senden desselben.
# Parameter:    GenTrapCode,     Allgemeiner Trap Code
#        SpecTrapCode,    Spezieller Trap Code
#        Enterprise,    Optionale Enterprise-ID
#        GID,          Group-ID der Trap-Variablen
#        InstID,       Instanz-ID der Trap-Variablen
#        Typ,          Typ des Rueckgabewerts, vgl. RFC1592,Tab.17 aber hex
#        Wert,          Rueckgabewert       
######################################################################
sub SendTrap
    {
    # Uebernahme der Parameter
    local($GenTrapCode,$SpecTrapCode,$EnterpID,$GID,$InstID,$Typ,$Wert) = @_;

    $dpi_Packet_ID++;    # Packet-ID hochzaehlen 
    # Bestimmen der Laengen der Strings (auch abhaengig vom Typ)
    $EnterpID_Laenge = length($EnterpID);
    $GID_Laenge = length($GID);
    $Inst_Laenge = length($InstID);
    if ($Typ eq "02")    # Falls Typ = SNMP_TYPE_OCTET_STRING
        {
        $Wert_Laenge = length($Wert);
        $Wert_PackString = "A".$Wert_Laenge;
        }
    elsif ($Typ eq "03")    # Falls Typ = SNMP_TYPE_OBJECT_IDENTIFIER
        {
        $Wert_Laenge = length($Wert);
        $Wert_PackString = "A".$Wert_Laenge;
        }
    elsif ($Typ eq "11")    # Falls Typ = SNMP_TYPE_endOfMibView
        {
        print "EndofMib\n";
        $Wert_Laenge = 0;
        $Wert_PackString = "";
        }
    elsif ($Typ eq "81")    # Falls Typ = SNMP_TYPE_Integer32
        {
        $Wert_Laenge = 4;
        $Wert_PackString = "N";
        }
    else            # Falls unbekannter Typ
        {
        print "Unbekannter Typ: $Typ\n";
        return;
        }
    if ($EnterpID)
        {
        # Aufbauen des Pack-Strings mit EnterpriseID
        $PackString = "H2H2H2nH2nnA".$EnterpID_Laenge."xA".$GID_Laenge."xA".
                                           $Inst_Laenge."xH2n".$Wert_PackString;
        }
    else     
        {
        # Aufbauen des Pack-Strings ohne EnterpriseID
        $PackString = "H2H2H2nH2nnA1A".$GID_Laenge."xA".$Inst_Laenge."xH2n".
                                           $Wert_PackString;
        $EnterpID = "\0";
        }
    ####################################################
    # Paket ohne Feld Paketlaenge zusammensetzen
    $dpi_Packet = pack($PackString,
                # Head-Beginn
                "02",    # Protokol Haupt Version
                "02",    # Protokol Niedere Version
                "00",    # Protokol Release
                $dpi_Packet_ID,
                "04",    # Typ: Trap-Packet
                # Head-Ende
                $GenTrapCode,    # Allgemeiner Trap-Code
                $SpecTrapCode,    # Spezieller Trap-Code
                $EnterpID,    # optional Enterprise ID
                $GID,    # Group-ID
                $InstID,# Instanz-ID
                $Typ,    # Typ der Variablen
                $Wert_Laenge,    # Laenge des Werts
                $Wert    # Rueckgabewert             
               );
    ####################################################
    # Paketlaenge ermitteln
    $Laenge = length($dpi_Packet);        # Laenge des Packets ermitteln  
    $dpi_Packet_Length = pack("n",$Laenge); # Laenge des Packets in 
                                            # eigenes Paket legen
        
    # Pakete verschicken
    print DPI_Anschluss $dpi_Packet_Length.$dpi_Packet;
    print "Success-Response verschickt\n";
    }

#############################################################
# ResponseError(Paket-Id,Fehlercode in hex)
# Aufbauen eines Response wegen Fehler und verschicken dieses.
# Parameter:    Paket-Id, Paket-id der Anfrage, die fehlerhaft
#              war
#        Fehlercode in hex, vgl. rfc1592 Tab. 18
#############################################################
sub ResponseError
    {
    # Uebernahme der Parameter
    local($dpi_Packet_ID,$Error) = @_;

    ####################################################
    # Paket ohne Feld Paketlaenge zusammensetzen
    $dpi_Packet = pack("H2H2H2nH2H2n",
                # Head-Beginn
                "02",    # Protokol Haupt Version
                "02",    # Protokol Niedere Version
                "00",    # Protokol Release
                $dpi_Packet_ID,
                "05",    # Typ: Response-Packet
                # Head-Ende
                $Error,    # Fehlercode
                1,    # Fehler bei VarBind 1 
               );
    ####################################################
    # Paketlaenge ermitteln
    $Laenge = length($dpi_Packet);        # Laenge des Packets ermitteln  
    $dpi_Packet_Length = pack("n",$Laenge); # Laenge des Packets in 
                                            # eigenes Paket legen
        
    # Pakete verschicken
    print DPI_Anschluss $dpi_Packet_Length.$dpi_Packet;
    print "Error-Response verschickt\n";
    }

############################################################
# DPI_UnRegister
# Aufbauen eines SNMP_DPI_UnRegister Request Packets und 
# verschicken desselben.
############################################################
sub DPI_UnRegister
    {
    $dpi_Packet_ID++;     # Packet-Identifier hochzaehlen
    $GID_Laenge = length($GROUPID);    
    $PackString = "H2H2H2nH2H2A".$GID_Laenge."x";

    ####################################################
    # Paket ohne Feld Paketlaenge zusammensetzen
    $dpi_Packet = pack($PackString,
                # Head-Beginn
                "02",    # Protokol Haupt Version
                "02",    # Protokol Niedere Version
                "00",    # Protokol Release
                $dpi_Packet_ID,
                "07",    # Typ: Unregister-Packet
                # Head-Ende
                "02",    # Grund: Programmende
                $GROUPID    # GID ab der der Subagent zustaendig
               );
    ####################################################
    # Paketlaenge ermitteln
    $Laenge = length($dpi_Packet);    # Laenge des Packets ermitteln 
             # (+1 wegen des zusaetzl. Feldes Paketlaenge) 
    $dpi_Packet_Length = pack("n",$Laenge);    # Laenge des Packets in 
                                               # eigenes Paket legen

    if($child = fork)
        {
        # Pakete verschicken
        print DPI_Anschluss $dpi_Packet_Length.$dpi_Packet;
        print "Unregister-Request: ";
        }
    else
        {
        # SNMP-DPI Response entgegennehmen und auswerten
        &DPI_OpenResponse;
        }
    waitpid($child,0);
    $Return = $?>>8 ;
    if (!($Return == 0))     # Falls die Unregister-Request nicht angenommen
        {
        print "nicht angenommen!\n";
        print "Fehlercode: $Return\n";
        &DPI_Close;    # Schliessen der DPI-Verbindung
        close(DPI_Anschluss); # Schliessen des Handles fuer die TCP-
                              # Verbindung zum Agenten
        die "\n";
        }
    else
        {
        print "angenommen\n";
        }
    }

############################################################
# DPI_Register
# Aufbauen eines SNMP_DPI_Register Request Packets und 
# verschicken desselben.
############################################################
sub DPI_Register
    {
    $dpi_Packet_ID++;     # Packet-Identifier hochzaehlen
    $GID_Laenge = length($GROUPID);    
    $PackString = "H2H2H2nH2nnH2H2H2H2A".$GID_Laenge."x";

    ####################################################
    # Paket ohne Feld Paketlaenge zusammensetzen
    $dpi_Packet = pack($PackString,
                # Head-Beginn
                "02",    # Protokol Haupt Version
                "02",    # Protokol Niedere Version
                "00",    # Protokol Release
                $dpi_Packet_ID,
                "06",    # Typ: Register-Packet
                # Head-Ende
                0,    # Prioritaet
                5,    # Time-Out in sek. 
                "00",    # Authentifikation von Anfragen:Agent
                "0a",
                "00",    # GetBulk wird zu GetNext
                "00",
                $GROUPID    # GID ab der der Subagent zustaendig,
               );
    ####################################################
    # Paketlaenge ermitteln
    $Laenge = length($dpi_Packet);    # Laenge des Packets ermitteln 
                                      # (+1 wegen des zusaetzl. 
                                      # Feldes Paketlaenge) 
    $dpi_Packet_Length = pack("n",$Laenge);    # Laenge des Packets 
                                               # in eigenes Paket legen

    if($child = fork)
        {
        # Pakete verschicken
        print DPI_Anschluss $dpi_Packet_Length.$dpi_Packet;
        print "Register-Request: ";
        }
    else
        {
        # SNMP-DPI Response entgegennehmen und auswerten
        &DPI_OpenResponse;
        }
    waitpid($child,0);
    $Return = $?>>8 ;
    if (!($Return == 0))     # Falls die Unregister-Request nicht angenommen
        {
        print "nicht angenommen!\n";
        print "Fehlercode: $Return\n";
        &DPI_Close;    # Schliessen der DPI-Verbindung
        close(DPI_Anschluss); # Schliessen des Handles fuer die 
                              # TCP-Verbindung zum Agenten
        die "\n";
        }
    else
        {
        print "angenommen\n";
        }
    }

############################################################
# DPI_AreYouThere
# Aufbauen eines SNMP_DPI_Are_You_There Request Packets und 
# verschicken desselben.
############################################################
sub DPI_AreYouThere
    {
    $dpi_Packet_ID++;     # Packet-Identifier hochzaehlen

    ####################################################
    # Paket ohne Feld Paketlaenge zusammensetzen
    $dpi_Packet = pack("H2H2H2nH2",
                # Head-Beginn
                "02",    # Protokol Haupt Version
                "02",    # Protokol Niedere Version
                "00",    # Protokol Release
                $dpi_Packet_ID,
                "15",    # Typ: AreYouThere-Packet
                # Head-Ende
               );
    ####################################################
    # Paketlaenge ermitteln
    $Laenge = length($dpi_Packet);    # Laenge des Packets ermitteln 
                                      # (+1 wegen des zusaetzl. 
                                      # Feldes Paketlaenge) 
    $dpi_Packet_Length = pack("n",$Laenge); # Laenge des Packets 
                                            # in eigenes Paket legen

    if($child = fork)
        {
        # Pakete verschicken
        print DPI_Anschluss $dpi_Packet_Length.$dpi_Packet;
        print "Are-You_There_Request verschickt\n";
        }
    else
        {
        # SNMP-DPI Response entgegennehmen und auswerten
        &DPI_OpenResponse;
        }
    waitpid($child,0);
    $Return = $?>>8 ;
    if (!($Return == 0))     # Falls die Open-Request nicht angenommen
        {
        print "Verbindung zum Agenten nicht in Ordnung!\n";
        print "Fehlercode: $Return\n";
        die "\n";
        }
    else
        {
        print "Verbindung zum Agenten in Ordnung!\n";
        }        
    }

############################################################
# DPI_Close
# Aufbauen eines SNMP_DPI_Close Request Packets und 
# verschicken desselben.
############################################################
sub DPI_Close
    {
    $dpi_Packet_ID++;     # Packet-Identifier hochzaehlen

    ####################################################
    # Paket ohne Feld Paketlaenge zusammensetzen
    $dpi_Packet = pack("H2H2H2nH2H2",
                # Head-Beginn
                "02",    # Protokol Haupt Version
                "02",    # Protokol Niedere Version
                "00",    # Protokol Release
                $dpi_Packet_ID,
                "09",    # Typ: Close-Packet
                # Head-Ende
                "02"    # Grund: Programmende 
               );
    ####################################################
    # Paketlaenge ermitteln
    $Laenge = length($dpi_Packet)+1;    # Laenge des Packets ermitteln 
                                        # (+1 wegen des zusaetzl. 
                                        # Feldes Paketlaenge) 
    $dpi_Packet_Length = pack("n",$Laenge); # Laenge des Packets in 
                                            # eigenes Paket legen
    ####################################################
    # Pakete verschicken
    print DPI_Anschluss $dpi_Packet_Length.$dpi_Packet;
    print "Close-Request verschickt\n";        
    }

############################################################
# DPI_Open
# Aufbauen eines SNMP_DPI_Open Request Packets und 
# verschicken desselben.
############################################################
sub DPI_Open
    {
    $dpi_Packet_ID++;     # Packet-Identifier hochzaehlen
    $OID_Laenge = length($OID);
    $DESCRIPTION_Laenge = length($DESCRIPTION);
    $PackString = "H2H2H2nH2nnH2A".$OID_Laenge."xA".$DESCRIPTION_Laenge."xn";

    ####################################################
    # Paket ohne Feld Paketlaenge zusammensetzen
    $dpi_Packet = pack($PackString,
                # Head-Beginn
                "02",    # Protokol Haupt Version
                "02",    # Protokol Niedere Version
                "00",    # Protokol Release
                $dpi_Packet_ID,
                "08",    # Typ: Open-Packet
                # Head-Ende
                5,    # Time-Out in Sekunden
                1,    # Maximum VarBinds pro Packet 
                "01",    # Schriftsatz: eigener
                $OID,    # OID ab der der Subagent zustaendig,
                $DESCRIPTION, # Erklaerung zum Subagenten
                0    # Passwort-Laenge ist Null
               );
    ####################################################
    # Paketlaenge ermitteln
    $Laenge = length($dpi_Packet)+1; # Laenge des Packets ermitteln 
                                     # (+1 wegen des zusaetzl. 
                                     # Feldes Paketlaenge) 
    $dpi_Packet_Length = pack("n",$Laenge);# Laenge des Packets 
                                           # in eigenes Paket legen

    if($child = fork)
        {
        # Pakete verschicken
        print DPI_Anschluss $dpi_Packet_Length.$dpi_Packet;
        print "Open-Request: ";
        }
    else
        {
        # SNMP-DPI Response entgegennehmen und auswerten
        &DPI_OpenResponse;
        }
    waitpid($child,0);
    $Return = $?>>8 ;
    if (!($Return == 0))     # Falls die Open-Request nicht angenommen
        {
        print "nicht angenommen!\n";
        print "Fehlercode: $Return\n";
        die "\n";
        }
    else
        {
        print "angenommen\n";
        }
    }

############################################################
# DPI_OpenRespone
# Auf Response-Paket auf Open- bzw. AreYouThere-Request warten 
# und auf Erfolg des Requests ueberpruefen. 
############################################################
sub DPI_OpenResponse
    {
    # Lokale Variablen
    local($Reponse,@Response);
    
    recv(DPI_Anschluss,$Response,15,0);
     
    @Response = unpack("nH2H2H2nH2H2H2H2H2H2",$Response);

    if($Response[5] eq "05" && $Response[6] eq "00" )
        {
        exit;
        }
    else
        {
        exit(hex($Response[6]));
        }        
    }


############################################################
# TCPConnect($Port)
# Aufbauen einer TCP-Verbindung zum, durch die globale Var.
# $AGENT_HOST gegebenen Rechner ueber Port $Port.
# Bei Erfolg steht DPI_Anschluss als Handle zur Verfuegung. 
############################################################
sub TCPConnect
    {
    # Uebernahme der Parameter
    local($Port) = @_ ;

    print "TCPConnect():";
    # Name des Rechners, von dem aus die Verbindung 
    # aufgebaut wird
    $hostname   = `hostname`;

    # Service fuer die Anbindung aufbereiten
    ($name,$aliases,$proto) = getprotobyname('tcp');
    ($name,$aliases,$Port) = getservbyname($Port,'tcp')
    unless $Port =~ /^\d+$/;

    ($name, $aliases, $type, $len, $thisaddr) = gethostbyname($hostname);
    $this = pack($SOCKADDR, $AF_INET, 0, $thisaddr);

    # Gegenadresse auf gewuenschte Domaine setzen
    ($name, $aliases, $type, $len, $thataddr) = gethostbyname($AGENT_HOST);
    $that = pack($SOCKADDR, $AF_INET, $Port, $thataddr);
    
        # Create a handle to the socket
      socket(DPI_Anschluss, $AF_INET, $SOCK_STREAM, $proto) || 
                                            die "Socket fehlgeschlagen\n";
  
      # Assign the socket an address
      bind(DPI_Anschluss, $this) || die "Bind fehlgeschlagen\n";
  
      # Connect to the server
      connect(DPI_Anschluss,$that) || die "Connect fehlgeschlagen\n";

    select(DPI_Anschluss);
    $| = 1;     # Auf nicht puffern stellen
    select(STDOUT);
    print " ok\n"; 
    }         

#######################################################
# qDPIport
# Unterprogramm zum Ermitteln des Port's, ueber den der
# Subagent mit dem Agenten kommunizieren soll.
# Benoetigt den Hostnamen des Agenten in der globalen 
# Variablen $AGENT_HOST
# Rueckgabe: TCP-Port der fuer die weitere DPI-Verbindung
#          vorgeschlagen wurde.
#######################################################
sub qDPIport
    {
    # Definition von lokalen Variablen
    local($snmpPacket,@snmpPacket);

    print "qDPIport: ";
    # Paket zusammensetzen
    $snmpPacket = pack( "H2H2H6H2H2A6H4H6H6H6H4H4H4H22H4",
                "30",     # ASN.1 Header in Hex
                "29",     # PDU-length
                "020100",# snmp Version
                "04",     # Feld:Community-Name
                "06",     # Laenge Community-Name
                "public",# Community-Name
                "a01c",     # snmp-Get-Request
                "020101",# snmp-Request-Id
                "020100",# snmp-error-Status
                "020100",# snmp-Index
                "3011",     # varBind list
                "300f",     # varBind
                "060b",     # Feld:Object-Id
                "2b06010401020201010100", # Object-Id
                "0500"     # null-Value
                  );
    
    
    #####################################
    # UDP-Verbindung zu Agenten aufbauen
    
    # Name des Rechners, auf dem der Subagent gestartet wird
    $hostname   = `hostname`;
    
    ($name, $aliases, $type, $len, $addr) = gethostbyname($hostname);
    $this = pack($SOCKADDR, $AF_INET, 0, $addr);
    ($name, $aliases, $type, $len, $thataddr) = gethostbyname($AGENT_HOST);
    $that = pack($SOCKADDR, $AF_INET, $SNMP_PORT, $thataddr);

        # Create a handle to the socket
      socket(SNMP_Anschluss, $AF_INET, $SOCK_DGRAM, 17) || 
                                            die "Socket fehlgeschlagen\n";
  
      # Assign the socket an address
      bind(SNMP_Anschluss, $this) || die "Bind fehlgeschlagen\n";
  
    ##########################################
    # SNMP-Get-Request-Paket schicken
    send(SNMP_Anschluss,$snmpPacket,0,$that);
    
    ###############################################################
    # SNMP-Response-Paket empfangen die noetigen Informationen
    # ermitteln und zurueckgeben.
    recv(SNMP_Anschluss,$snmp_Packet,54,0);
    close SNMP_Anschluss;    
    @snmp_Packet = unpack("H2H6H6H2H2A6H8H6H6H6H8H8H4H22H4n",$snmp_Packet);

    print "ok\n";
    return($snmp_Packet[15]);
    }

#################################################
# Vergleichsfunktion zum Sortieren        
#################################################
sub by_hierarchy
    {
    local($i,@a,@b);

    @a = split(/\./,$a);
    @b = split(/\./,$b);

    if (@a < @b)
        {
        for ($i=0;$i<@a;$i++)
            {
            if ($a[$i] == $b[$i])
                {
                next;
                }
            else
                {
                return($a[$i]-$b[$i]);
                }
            }
        return(-1);
        }
    elsif (@a > @b)
        {
        for ($i=0;$i<@b;$i++)
            {
            if ($a[$i] == $b[$i])
                {
                next;
                }
            else
                {
                return($a[$i]-$b[$i]);
                }
            }
        return(1);
        }
    else
        {
        for ($i=0;$i<@b;$i++)
            {
            if ($a[$i] == $b[$i])
                {
                next;
                }
            else
                {
                return($a[$i]-$b[$i]);
                }
            }
        return(0);    
        }
    }

#################################################
# Vergleichsfunktion        
#################################################
sub less_by_hierarchy
    {
    # Uebernahme der Parameter
    local($a,$b)=@_;
    local($i,@a,@b);

    @a = split(/\./,$a);
    @b = split(/\./,$b);

    if (@a < @b)
        {
        for ($i=0;$i<@a;$i++)
            {
            if ($a[$i] == $b[$i])
                {
                next;
                }
            else
                {
                return($a[$i]-$b[$i]);
                }
            }
        return(-1);
        }
    elsif (@a > @b)
        {
        for ($i=0;$i<@b;$i++)
            {
            if ($a[$i] == $b[$i])
                {
                next;
                }
            else
                {
                return($a[$i]-$b[$i]);
                }
            }
        return(1);
        }
    else
        {    
        for ($i=0;$i<@b;$i++)
            {
            if ($a[$i] == $b[$i])
                {
                next;
                }
            else
                {
                return($a[$i]-$b[$i]);
                }
            }
        return(-1);    
        }
    }


1;


Copyright Munich Network Management Team