แก้ปัญหา “login failure for user api from x.x.x.x via api”.

เนื่องจาก Mikrotik ได้เปลี่ยนรูปแบบ connect method เป็นแบบใหม่มาตั้งแต่ RouterOS 6.43 แต่ก็ยังเปิดให้ใช้รูปแบบเดิมไปพร้อมๆ กัน แต่แล้วในที่สุดก็ทำการยกเลิก รูปแบบเดิมออกไปใน RouterOS 6.45.1 ทำให้ API ที่ไม่ได้อัพเดท Code จะไม่สามารถเชื่อมต่อได้ (รายละเอียดมีระบุไว้ที่ wiki.mikrotik.com ซึ่งดูจากที่ลิงค์นี้ https://wiki.mikrotik.com/wiki/Manual:API#Initial_login

สำหรับวิธีแก้ไขคือให้ค้นหาโค๊ดในส่วนที่ตีกรอบไว้ตามภาพด้านล่างในไฟล์ routeros_api.class แล้วทดแทนโค๊ดส่วนนี้ด้วยรหัสที่อยู่ท้ายบทความ หรือทำการอัพเกรดเป็น Class V1.6 เป็นอย่างน้อยครับ


 

    public function connect($ip, $login, $password)
    {
        for ($ATTEMPT = 1; $ATTEMPT <= $this->attempts; $ATTEMPT++) {
            $this->connected = false;
            $PROTOCOL = ($this->ssl ? 'ssl://' : '' );
            $context = stream_context_create(array('ssl' => array('ciphers' => 'ADH:ALL', 'verify_peer' => false, 'verify_peer_name' => false)));
            $this->debug('Connection attempt #' . $ATTEMPT . ' to ' . $PROTOCOL . $ip . ':' . $this->port . '...');
            $this->socket = @stream_socket_client($PROTOCOL . $ip.':'. $this->port, $this->error_no, $this->error_str, $this->timeout, STREAM_CLIENT_CONNECT,$context);
            if ($this->socket) {
                socket_set_timeout($this->socket, $this->timeout);
                $this->write('/login', false);
                $this->write('=name=' . $login, false);
                $this->write('=password=' . $password);
                $RESPONSE = $this->read(false);
                if (isset($RESPONSE[0])) {
                    if ($RESPONSE[0] == '!done') {
                        if (!isset($RESPONSE[1])) {
                            // Login method post-v6.43
                            $this->connected = true;
                            break;
                        } else {
                            // Login method pre-v6.43
                            $MATCHES = array();
                            if (preg_match_all('/[^=]+/i', $RESPONSE[1], $MATCHES)) {
                                if ($MATCHES[0][0] == 'ret' && strlen($MATCHES[0][1]) == 32) {
                                    $this->write('/login', false);
                                    $this->write('=name=' . $login, false);
                                    $this->write('=response=00' . md5(chr(0) . $password . pack('H*', $MATCHES[0][1])));
                                    $RESPONSE = $this->read(false);
                                    if (isset($RESPONSE[0]) && $RESPONSE[0] == '!done') {
                                        $this->connected = true;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                fclose($this->socket);
            }
            sleep($this->delay);
        }

        if ($this->connected) {
            $this->debug('Connected...');
        } else {
            $this->debug('Error...');
        }
        return $this->connected;
    }