Mikrotik C# API Kullanımı-1-

Mikrotik son zamanlarda ortak alanlardaki internet kullanımına dair karşılaşılan problemleri gidermede kolaylaıkla kullanılabilecek bir cihaz. Sadece bu alanda değil Network alanındaki bir çok ihtiyaca, tekbir yazılım sayesinde cevap vermekte. Yazılımın Linux çekirdeği üzerinde çalışmasıda, mikrotik cihazının kullanımında klasik windows pencerelerine alışan bizler için biraz zorluklar doğurmakta. Özellikle son kullanıcıların kullanımına açık olması gereken bazı ayarlamalarda (Örneğin Hotspot User işlemleri gib) harici yazılım ihtiyacı doğurmakta. Bu amaçla .Net ortamında çalışabilecek bir API aradığımızda http://wiki.mikrotik.com/wiki/API_in_C_Sharp adresinden Mikrotik için komut gönderimi ve komut sonrası sonuçları okumak amacıyla oluşturulmuş çekirdek bir class buluyoruz. 

Ben adresteki yapıda daha esnek kullanımlar için  bazı küçük değişiklikler yaparak paylaşmak istedim. Aşağıdaki yapı WinForm üzerinde çalışma amaçlı yapmaya çalıştığım bir projeye ait mikrotik çekirdek yazılımı. Bu yazımda sadece bir login form ile mikrtik cihazına bağlanmayı ve test işlemlerini anlatmayaçalışacagım.

MikroticCihaz sınıfını ile projenin ilk login girişinde aldığım bilgileri  statik tanımlayarak kalıcı yapmak istedim. Her mikrotik cihazı ile ilgili işlemlerde de bu bilgileri kullandım.

public static class MikrotikCihaz
    {
        public static string ip = "192.168.88.1";
        public static string user = "admin";
        public static string password = "password";

    }
    public class Mikrotik
    {
        #region Genel Mikrotik İşlemleri
        Stream connection;
        TcpClient con;
        public bool MikrotikConnect()
        {
            con = new TcpClient();
            con.Connect(MikrotikCihaz.ip, 8728);
            connection = (Stream)con.GetStream();
            if (!Login(MikrotikCihaz.user, MikrotikCihaz.password))
            {
                MessageBox.Show("Cihaza Bağlanılamadı.Sistem Hatası", "Hata", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        public void Close()
        {
            connection.Close();
            con.Close();
        }
        public bool Login(string username, string password)
        {
            Send("/login", true);
            string hash = Read()[0].Split(new string[] { "ret=" }, StringSplitOptions.None)[1];
            Send("/login");
            Send("=name=" + username);
            Send("=response=00" + EncodePassword(password, hash), true);
            if (Read()[0] == "!done")
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public void Send(string co)
        {
            byte[] bajty = Encoding.ASCII.GetBytes(co.ToCharArray());
            byte[] velikost = EncodeLength(bajty.Length);

            connection.Write(velikost, 0, velikost.Length);
            connection.Write(bajty, 0, bajty.Length);
        }
        public void Send(string co, bool endsentence)
        {
            byte[] bajty = Encoding.ASCII.GetBytes(co.ToCharArray());
            byte[] velikost = EncodeLength(bajty.Length);
            connection.Write(velikost, 0, velikost.Length);
            connection.Write(bajty, 0, bajty.Length);
            connection.WriteByte(0);
        }
        public List<string> Read()
        {
            List<string> output = new List<string>();
            string o = "";
            byte[] tmp = new byte[4];
            long count;
            while (true)
            {
                tmp[3] = (byte)connection.ReadByte();
                //if(tmp[3] == 220) tmp[3] = (byte)connection.ReadByte(); it sometimes happend to me that 
                //mikrotik send 220 as some kind of "bonus" between words, this fixed things, not sure about it though
                if (tmp[3] == 0)
                {
                    output.Add(o);
                    if (o.Substring(0, 5) == "!done")
                    {
                        break;
                    }
                    else
                    {
                        o = "";
                        continue;
                    }
                }
                else
                {
                    if (tmp[3] < 0x80)
                    {
                        count = tmp[3];
                    }
                    else
                    {
                        if (tmp[3] < 0xC0)
                        {
                            int tmpi = BitConverter.ToInt32(new byte[] { (byte)connection.ReadByte(), tmp[3], 0, 0 }, 0);
                            count = tmpi ^ 0x8000;
                        }
                        else
                        {
                            if (tmp[3] < 0xE0)
                            {
                                tmp[2] = (byte)connection.ReadByte();
                                int tmpi = BitConverter.ToInt32(new byte[] { (byte)connection.ReadByte(), tmp[2], tmp[3], 0 }, 0);
                                count = tmpi ^ 0xC00000;
                            }
                            else
                            {
                                if (tmp[3] < 0xF0)
                                {
                                    tmp[2] = (byte)connection.ReadByte();
                                    tmp[1] = (byte)connection.ReadByte();
                                    int tmpi = BitConverter.ToInt32(new byte[] { (byte)connection.ReadByte(), tmp[1], tmp[2], tmp[3] }, 0);
                                    count = tmpi ^ 0xE0000000;
                                }
                                else
                                {
                                    if (tmp[3] == 0xF0)
                                    {
                                        tmp[3] = (byte)connection.ReadByte();
                                        tmp[2] = (byte)connection.ReadByte();
                                        tmp[1] = (byte)connection.ReadByte();
                                        tmp[0] = (byte)connection.ReadByte();
                                        count = BitConverter.ToInt32(tmp, 0);
                                    }
                                    else
                                    {
                                        //Error in packet reception, unknown length
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }

                for (int i = 0; i < count; i++)
                {
                    o += (Char)connection.ReadByte();
                }
            }
            return output;
        }
        byte[] EncodeLength(int delka)
        {
            if (delka < 0x80)
            {
                byte[] tmp = BitConverter.GetBytes(delka);
                return new byte[1] { tmp[0] };
            }
            if (delka < 0x4000)
            {
                byte[] tmp = BitConverter.GetBytes(delka | 0x8000);
                return new byte[2] { tmp[1], tmp[0] };
            }
            if (delka < 0x200000)
            {
                byte[] tmp = BitConverter.GetBytes(delka | 0xC00000);
                return new byte[3] { tmp[2], tmp[1], tmp[0] };
            }
            if (delka < 0x10000000)
            {
                byte[] tmp = BitConverter.GetBytes(delka | 0xE0000000);
                return new byte[4] { tmp[3], tmp[2], tmp[1], tmp[0] };
            }
            else
            {
                byte[] tmp = BitConverter.GetBytes(delka);
                return new byte[5] { 0xF0, tmp[3], tmp[2], tmp[1], tmp[0] };
            }
        }
        public string EncodePassword(string Password, string hash)
        {
            byte[] hash_byte = new byte[hash.Length / 2];
            for (int i = 0; i <= hash.Length - 2; i += 2)
            {
                hash_byte[i / 2] = Byte.Parse(hash.Substring(i, 2), System.Globalization.NumberStyles.HexNumber);
            }
            byte[] heslo = new byte[1 + Password.Length + hash_byte.Length];
            heslo[0] = 0;
            Encoding.ASCII.GetBytes(Password.ToCharArray()).CopyTo(heslo, 1);
            hash_byte.CopyTo(heslo, 1 + Password.Length);

            Byte[] hotovo;
            System.Security.Cryptography.MD5 md5;

            md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();

            hotovo = md5.ComputeHash(heslo);

            //Convert encoded bytes back to a 'readable' string
            string navrat = "";
            foreach (byte h in hotovo)
            {
                navrat += h.ToString("x2");
            }
            return navrat;
        }
        #endregion

 

Projede sisteme giriş için kullanılacak logn ekranını aşağıdaki gibi tasarladm. Sistemde birden fazla mikrotike baglanma ihtiyaçları olabilecegini düşünerek XML veri tabanı yapısını kullanarak mikrotik kullanıcı adı ve ip gibi bilgileri burada tutmayı düşündüm. Login ekranına da Bu cihazları dropdrown kullanarak listeledim. Bağlan Butonu ile gerçekleştirdiğim işlemleride aşağıdaki şekilde gerçekleştirdim.

Mikrotik-Csharp-Api

 private void Bağlan_Click(object sender, EventArgs e)
        {
            #region cihazKontrol
            string xmlDosyasi = Application.StartupPath + "\\Cihazlar.xml";
            XDocument xmlDoc = XDocument.Load(xmlDosyasi);

            Cihaz liste = (from u in xmlDoc.Root.Elements()
                           where u.Element("Id").Value == comboBox1.SelectedValue.ToString()
                           select new Cihaz
                           {
                               id = u.Element("Id").Value,
                               Adi = u.Element("Adi").Value,
                               Ip = u.Element("Ip").Value,
                               Pass = u.Element("Pass").Value,
                               User = u.Element("User").Value,
                           }
                            ).FirstOrDefault();

            MikrotikCihaz.ip = liste.Ip;
            MikrotikCihaz.password = liste.Pass;
            MikrotikCihaz.user = liste.User;
            Mikrotik mk = new Mikrotik();

            #endregion

            if (mk.MikrotikConnect())
            {
                FormMain frm = new FormMain();
                frm.cihazid = comboBox1.SelectedValue.ToString();
                this.Hide();
                frm.ShowDialog();
                this.Close();
            }     

           
        }

 mikrotik-c-api-aspnet

Yapılan işlemler doğru ise Mikrofik üzerinde yapacağımız .çeşitli işlemler için tasarladığımız FormMain açılma işlemi gerçekleşmekte. Umarım anlaşılır olmuştur. Bir sonra ki yazıda Hotspot üzerindeki temel işlemleri yapabilecek bir arayüz yapmayı düşünüyorum. Şimdilik heybemizde bukadar  bilgi var.

İyi Çalışmalar :)

 

Müellifi: Hüsrev YILDIZ
Yayın Tarihi : 7.2.2017

Hüsrev YILDIZ