2012-05-18 2 views
2

Мне нужно подключиться к коммутатору cisco с помощью php и выполнить команду show interface status и получить результаты. Я пробовал некоторые классы php, которые я нашел в Интернете, но ни один из них не мог подключиться к устройству. Поэтому я попытался написать сценарий сам, но у меня такая же проблема, я не могу подключиться к устройству.Переключатель Telnet to cisco с использованием php

Хост посылает мне сообщение баннера, а затем новую строку с username:. Я отправляю свое имя пользователя с \r\n, жду некоторое время и пытается прочитать данные, но мне кажется, что хост просто игнорирует мои новые персонажи. Это ответ, который я получил (взрываются («\ п») на ответ):

Array 
(
    [0] => % 
    [1] => User Access Verification 
    [2] => Username: timeout expired! 
) 

Почему я не получить приглашение на пароль? Я попробовал его с отправкой заголовков telnet и без изменений. Кто-нибудь может мне помочь, пожалуйста!

Вот мой код

<? 
$host = "switchName"; 
$name = "name"; 
$pass = "pass"; 
$port = 23; 
$timeOut = 15; 
$connected = false; 
$skipNullLines = true; 
$timeout = 125000; 


$header1=chr(0xFF).chr(0xFB).chr(0x1F).chr(0xFF).chr(0xFB).chr(0x20).chr(0xFF).chr(0xFB).chr(0x18).chr(0xFF).chr(0xFB).chr(0x27).chr(0xFF).chr(0xFD).chr(0x01).chr(0xFF).chr(0xFB).chr(0x03).chr(0xFF).chr(0xFD).chr(0x03).chr(0xFF).chr(0xFC).chr(0x23).chr(0xFF).chr(0xFC).chr(0x24).chr(0xFF).chr(0xFA).chr(0x1F).chr(0x00).chr(0x50).chr(0x00).chr(0x18).chr(0xFF).chr(0xF0).chr(0xFF).chr(0xFA).chr(0x20).chr(0x00).chr(0x33).chr(0x38).chr(0x34).chr(0x30).chr(0x30).chr(0x2C).chr(0x33).chr(0x38).chr(0x34).chr(0x30).chr(0x30).chr(0xFF).chr(0xF0).chr(0xFF).chr(0xFA).chr(0x27).chr(0x00).chr(0xFF).chr(0xF0).chr(0xFF).chr(0xFA).chr(0x18).chr(0x00).chr(0x41).chr(0x4E).chr(0x53).chr(0x49).chr(0xFF).chr(0xF0); 
$header2=chr(0xFF).chr(0xFC).chr(0x01).chr(0xFF).chr(0xFC).chr(0x22).chr(0xFF).chr(0xFE).chr(0x05).chr(0xFF).chr(0xFC).chr(0x21); 


function read_string() 
{ 
    global $fw,$host,$skipNullLines; 
    $string = ""; 

    while(!feof($fw)) 
    { 
     $read = fgets($fw); 

     $string .= $read; 

     // Probably prompt, stop reading 
     if(strpos($read, ':') !== FALSE || strpos($read, '> (enable)') !== FALSE || strpos($read, $host.'#') !== FALSE) 
     { break; } 
    } 

    $string = explode("\n", $string); 

    // Get rid of null lines 
    $ret = array(); 
    for($i = 0; $i<count($string); $i++) 
    { 
     if(trim($string[$i]) == '' && $skipNullLines) continue; 

     $ret[] = $string[$i]; 
    } 

    return $ret; 
} 

function send_string($string, $force=false) 
{ 
    GLOBAL $timeout,$fw; 
    $string = trim($string); 

    // execute only strings that are preceded by "show" (if not forced) 
    if(!$force && strpos($string, 'show ') !== 0) 
    { 
     return 1; 
    } 

    fputs($fw, $string."\r\n"); 
    echo("SEND:".$string."\r\n"); 
    usleep($timeout); 
} 


$fw = fsockopen($host, $port, $errno, $errorstr, $timeOut);  
if($fw == false) 
{ 
    echo("Cant connect"); 
} 
else 
{ 
    echo("Connected<br>"); 
    $connected = true; 

    stream_set_timeout($fw, $timeout); 

// fputs($fw, $header1); 
// usleep($timeout); 
// fputs($fw, $header2); 
// usleep($timeout); 
    print_r(read_string()); 
    send_string("test", true); 
    print_r(read_string()); 
} 

fclose($fw); 
?> 

UPDATE Если я посылаю имя сначала, а потом я прочитал, я получаю запрос на ввод пароля. Я не понимаю этого, почему не могу сначала прочитать сообщения от хоста, а затем отправить свой ответ. То, как это работает со мной сейчас (отправить ответ, а затем прочитать для подсказки), не имеет смысла! (и я все еще получил сообщение «% Authentication failed.» с правильным паролем/именем).

... 
$connected = true; 
stream_set_timeout($fw, $timeout); 
send_string("name", true); 
send_string("password", true); 
print_r(read_string()); 
... 

ответ

4

Хорошо, так что я не знаю, в чем была проблема, но после того, как «несколько» тестов я был в состоянии написать этот класс, который работает для меня. Я не знаю, почему другие классы telnet не работают, хотя они почти одинаковы. Так что, если кто-то будет иметь подобную проблему, вы можете попробовать это:

class TELNET 
{ 
    private $host; 
    private $name; 
    private $pass; 
    private $port; 
    private $connected; 
    private $connect_timeout; 
    private $stream_timetout; 

    private $socket; 

    public function TELNET() 
    { 
    $this->port = 23; 
    $this->connected = false;   // connected? 
    $this->connect_timeout = 10;  // timeout while asking for connection 
    $this->stream_timeout = 380000; // timeout between I/O operations 
    } 

    public function __destruct() 
    { 
    if($this->connected) { fclose($this->socket); } 
    } 

    // Connects to host 
    // @$_host - addres (or hostname) of host 
    // @$_user - name of user to log in as 
    // [email protected]_pass - password of user 
    // 
    // Return: TRUE on success, other way function will return error string got by fsockopen() 
    public function Connect($_host, $_user, $_pass) 
    { 
    // If connected successfully 
    if(($this->socket = @fsockopen($_host, $this->port, $errno, $errorstr, $this->connect_timeout)) !== FALSE) 
    { 
     $this->host = $_host; 
     $this->user = $_user; 
     $this->pass = $_pass; 

     $this->connected = true; 

     stream_set_timeout($this->socket, 0, 380000); 
     stream_set_blocking($this->socket, 1); 

     return true; 
    } 
    // else if coulnt connect 
    else return $errorstr; 
    } 


    // LogIn to host 
    // 
    // RETURN: will return true on success, other way returns false 
    public function LogIn() 
    { 
    if(!$this->connected) return false; 

    // Send name and password 
    $this->SendString($this->user, true); 
    $this->SendString($this->pass, true); 

    // read answer 
    $data = $this->ReadTo(array('#')); 

    // did we get the prompt from host? 
    if(strtolower(trim($data[count($data)-1])) == strtolower($this->host).'#') return true; 
    else return false; 
    } 


    // Function will execute command on host and returns output 
    // 
    // @$_command - command to be executed, only commands beginning with "show " can be executed, you can change this by adding 
    //    "true" (bool type) as the second argument for function SendString($command) inside this function (3rd line) 
    // 
    function GetOutputOf($_command) 
    { 
    if(!$this->connected) return false; 

    $this->SendString($_command); 

    $output = array(); 
    $work = true; 

    // 
    // Read whole output 
    // 
    // read_to(array(STRINGS)), STRINGS are meant as possible endings of outputs 
    while($work && $data = $this->ReadTo(array("--More--","#"))) 
    { 
     // CHeck wheter we actually did read any data 
     $null_data = true; 
     foreach($data as $line) 
     { 
     if(trim($line) != "") {$null_data = false;break;} 
     } 
     if($null_data) { break;} 

     // if device is paging output, send space to get rest 
     if(trim($data[count($data)-1]) == '--More--') 
     { 
     // delete line with prompt (or "--More--") 
     unset($data[count($data)-1]); 

     // if second line is blank, delete it 
     if(trim($data[1]) == '') unset($data[1]); 
     // If first line contains send command, delete it 
     if(strpos($data[0], $_command)!==FALSE) unset($data[0]); 

     // send space 
     fputs($this->socket, " "); 
     } 

     // ak ma vystup max dva riadky 
     // alebo sme uz nacitali prompt 
     // IF we got prompt (line ending with #) 
     // OR string that we've read has only one line 
     // THEN we reached end of data and stop reading 
     if(strpos($data[count($data)-1], '#')!==FALSE /* || (count($data) == 1 && $data[0] == "")*/ ) 
     { 
     // delete line with prompt 
     unset($data[count($data)-1]); 

     // if second line is blank, delete it 
     if(trim($data[1]) == '') unset($data[1]); 
     // If first line contains send command, delete it 
     if(strpos($data[0], $_command)!==FALSE) unset($data[0]); 

     // stop while cyclus 
     $work = false; 
     } 

     // get rid of empty lines at the end 
     for($i = count($data)-1; $i>0; $i--) 
     { 
     if(trim($data[$i]) == "") unset($data[$i]); 
     else break; 
     } 

     // add new data to $output 
     foreach($data as $v) 
     { $output[] = $v; } 
    } 

    // return output 
    return $output; 
    } 


    // Read from host until occurence of any index from $array_of_stops 
    // @array_of_stops - array that contains strings of texts that may be at the end of output 
    // RETURNS: output of command as array of lines 
    function ReadTo($array_of_stops) 
    { 
    $ret = array(); 
    $max_empty_lines = 3; 
    $count_empty_lines = 0; 

    while(!feof($this->socket)) 
    { 
     $read = fgets($this->socket); 
     $ret[] = $read; 

     // 
     // Stop reading after (int)"$max_empty_lines" empty lines 
    // 
     if(trim($read) == "") 
     { 
     if($count_empty_lines++ > $max_empty_lines) break; 
     } 
     else $count_empty_lines = 0; 

     // 
     // Does last line of readed data contain any of "Stop" strings ?? 
     $found = false; 
     foreach($array_of_stops AS $stop) 
     { 
     if(strpos($read, $stop) !== FALSE) { $found = true; break; } 
     } 
     // If so, stop reading 
     if($found) break; 
    } 

    return $ret; 
    } 



    // Send string to host 
    // If force is set to false (default), function sends to host only strings that begins with "show " 
    // 
    // @$string - command to be executed 
    // @$force - force command? Execute if not preceeded by "show " ? 
    // @$newLine - append character of new line at the end of command? 
    function SendString($string, $force=false, $newLine=true) 
    { 
    $t1 = microtime(true); 
    $string = trim($string); 

    // execute only strings that are preceded by "show" 
    // and execute only one command (no new line characters) ! 
    if(!$force && strpos($string, 'show ') !== 0 && count(explode("\n", $string)) == 1) 
    { 
     return 1; 
    } 


    if($newLine) $string .= "\n"; 
    fputs($this->socket, $string); 

    $t2 = microtime(true); 
    } 

} 


// EXAMPLE 
$host = "hostname"; 
$name = "username"; 
$pass = "password"; 


$t = new TELNET(); 
echo("CONNECT:".$t->Connect($host, $name, $pass)."<br>"); 
echo("LOGIN:".(int)$t->LogIn()); 
echo("<br>OUTPUT:<br>"); 
print_r($t->GetOutputOf("show snmp")); 
print_r($t->GetOutputOf("show users")); 
print_r($t->GetOutputOf("show interface status")); 

PS: мои устройства подскажите есть «имя хост #», так что вам, возможно, потребуется изменить Войти функцию, чтобы сделать этот код работать с подсказкой устройства (поэтому вам может понадобиться GetOutputOf())

Смежные вопросы