Привет всем. У меня была задача определить внешний 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; // Вуаля!
}