Как программно определить внешний адрес своего роутера
От: yuriel  
Дата: 01.02.11 20:07
Оценка:
Привет всем. У меня была задача определить внешний IP роутера и записать его в текстовый файл. ИМХО Самый оптимальный вариант — юзать SNMP протокол управления сетевым оборудованием. Вот что я наваял на C++. Раньше кодил на ассемблере. Думал прогу написать на masm32. Но со структурами запутался окончательно. Решил освоить С++
Перед этим покурил здесь: http://ru.wikipedia.org/wiki/SNMP
Потом втыкал Здесь: http://book.itep.ru/4/44/snm_4413.htm
Ну и окончательно расчехлился здесь: http://msdn.microsoft.com/en-us/library/aa378988%28v=VS.85%29.aspx

#include <iostream.h>
#include <Snmp.h>
#include <Mgmtapi.h>
#include <Winuser.h>
#include <Winbase.h>
#include <stdio.h>
// Курю С++ всего две недели. Поэтому прошу не судить предвзято :) 
// snmp агент - ADSLроутер: D-LINK DSL-2600U
// Прога считывает WAN ip адрес роутера, преобразовывает его в строку в виде ХХХ.ХХХ.ХХХ.ХХХ
// и записывает его в файл!
int main()
{
    AsnInteger errorStatus=0; //Код полученной ошибки. 
    AsnInteger errorIndex=0;  //Какой-то индекс ошибки (Лень было вникать)

    AsnObjectIdentifier OID;  //Идентификатор объекта (переменной, в которой будет искомый ip)
    SnmpVarBindList snmpVarList; //струтура передаваемая функции 
    snmpVarList.len = 1;         //Нас же только одна переменная интересует, пока :)
    //Указатель на еще одну структуру, содержащую всю инфу про эту самую переменную =)
    //Память под нее выделяем функцией SnmpUtilMemAlloc. Потом желательно освободить память функцией SnmpUtilMemFree()
    snmpVarList.list = (SnmpVarBind *) SnmpUtilMemAlloc(sizeof(SnmpVarBind)*snmpVarList.len);

    //Преобразовываем текстовое представление переменой, в которой храниться IP адрес роутера, в уникальный идентификатор этой переменной-OID
    SnmpMgrStrToOid(".1.3.6.1.2.1.4.20.1.1", &OID);
    SnmpUtilOidCpy(&snmpVarList.list[0].name,&OID);
    
    // Начинаем работу с SNMP агентом: (внутренний LAN адрес роутера(SNMPагента) - 10.0.0.1 (компа - 10.0.0.2) 
    // пароль на считывание переменной, по умолчанию - "public")
    // 1000 - Это таймаут перед повторной попыткой соединиться с агентом (в милисекундах)
    // 1 - кол-во попыток соединения соответственно (имхо не существенно)
    PVOID snmpH = SnmpMgrOpen("10.0.0.1", "public", 1000, 1);
    if (!snmpH)
    {
        MessageBox(0, "Не удалось начать SNMP сессию","Ошибочко вышло",MB_OK|MB_ICONERROR);
    }
    short i;
    
    // В цикле делаем запрос 3 раза. 
    // В первый раз получаем LAN адрес роутера - (в моем случае 10.0.0.1) - Не интересно
    // Во второй раз получаем адрес локального хоста - 127.0.0.1          - Не интересно
    // И, о боги, в третий раз получаем WAN адрес роутера - (У каждого он различный разумеется) - ТО ЧТО НАДО!!!!
    for (i = 0; i < 3; i++)
    {
        if(!SnmpMgrRequest(snmpH, SNMP_PDU_GETNEXT, &snmpVarList, &errorStatus,&errorIndex))
            {
                MessageBox(0, "Не удалось запросить переменную","Да что ж такое!?",MB_OK|MB_ICONERROR);
                SnmpUtilVarBindListFree(&snmpVarList);
                SnmpUtilOidFree(&OID);
                return 1;
            }
    }        
    
    // Указатель на полученный IP адресс
    // Внимание он храниться в четрырехбайтной переменной, каждый байт - одна из 4-х десятичных цифр адреса
    // например если IP - 101.11.238.54 то в памяти он выглядит: 650BEE36
    // Порядок следования байтов обратный. Почему? Это уже отдельный вопрос.
    int *ipPointer = (int *)snmpVarList.list[0].value.asnValue.address.stream; 
    char buffer[256] = "";
    char buf[256] = "";
    // Здесь я ходил с бубном преобразовывая IP в строковый вид
    // Подозреваю можно проще
    for (i = 0; i < 4; i++)
    {
        int ipAddress = *ipPointer;
        ipAddress >>= i*8;
        ipAddress &= 255;
        wsprintf(buf, "%u", ipAddress);
        lstrcat(buffer, buf);
        if (i < 3)
        {
            lstrcat(buffer, ".");
        }
        
    }
    // Освобождаем память, выделенную функцией SnmpUtilMemAlloc:
    SnmpUtilMemFree(snmpVarList.list);
    // В buffer - полученная строка
        
    // Открываем файл "ip.txt" и собсно записываем туды IP-шник
    FILE *fileH = fopen("ip.txt", "w");
    fputs(buffer, fileH);
    fclose(fileH);
    
    return 0; // Вуаля!
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.