Для удобного конфигурирования и однозначной привязки IP-телефона к сетевому оборудованию, можно использовать механизм Provision, реализованный на подавляющем большинстве IP-телефонов. А благодаря наличию TFTP-сервера и поддержке скриптов на маршрутизаторах Mikrotik, можно настраивать VoIP оборудование исходя из многих факторов.
Задача такова:
На точки выдаётся маршрутизатор Mikrotik и IP-телефон Grandstream. У маршрутизатора есть внутренний учётный номер типа «R32» и телефон должен настраиваться так, чтобы его номер был номер_роутера + префикс. Так как телефоны и роутеры могут перемешиваться между собой, то жёстко вбивать номер нельзя.
Решение:
Скриптом генерируем конфиг для телефона и разрешаем доступ к файлу через TFTP. Скрипт будет выполняться раз в день и чтобы не затереть флеш-память до дыр, необходимо сверить CRC существующего файла и сгенерированного конфига в памяти.
:global crc8 do={
:local crc 0x0
:local poly 0x7
:local tbl ( "\00", "\01", "\02", "\03", "\04", "\05", "\06", "\07", "\08", "\09", "\0A", "\0B", "\0C", "\0D", "\0E", "\0F", \
"\10", "\11", "\12", "\13", "\14", "\15", "\16", "\17", "\18", "\19", "\1A", "\1B", "\1C", "\1D", "\1E", "\1F", \
"\20", "\21", "\22", "\23", "\24", "\25", "\26", "\27", "\28", "\29", "\2A", "\2B", "\2C", "\2D", "\2E", "\2F", \
"\30", "\31", "\32", "\33", "\34", "\35", "\36", "\37", "\38", "\39", "\3A", "\3B", "\3C", "\3D", "\3E", "\3F", \
"\40", "\41", "\42", "\43", "\44", "\45", "\46", "\47", "\48", "\49", "\4A", "\4B", "\4C", "\4D", "\4E", "\4F", \
"\50", "\51", "\52", "\53", "\54", "\55", "\56", "\57", "\58", "\59", "\5A", "\5B", "\5C", "\5D", "\5E", "\5F", \
"\60", "\61", "\62", "\63", "\64", "\65", "\66", "\67", "\68", "\69", "\6A", "\6B", "\6C", "\6D", "\6E", "\6F", \
"\70", "\71", "\72", "\73", "\74", "\75", "\76", "\77", "\78", "\79", "\7A", "\7B", "\7C", "\7D", "\7E", "\7F" )
for i from=0 to=($2 - 1) do={
:local chr [:pick $1 $i ($i + 1)]
set $crc ($crc ^ [:find $tbl $chr])
for j from=0 to=7 do={
if ($crc & 0x80 = 0) do={
set $crc ($crc << 1)
} else={
:set $crc ((($crc << 1) & 0xFF) ^ $poly)
}
}
}
:local crchex
if ($crc & 0xF0 > 0x90) do={:set crchex [:pick $tbl (($crc >> 4) + 0x37)]} else={:set crchex [:pick $tbl (($crc >> 4) + 0x30)]}
if ($crc & 0x0F > 9) do={:set crchex ($crchex.[:pick $tbl (($crc & 0xF) + 0x37)])} else={:set crchex ($crchex.[:pick $tbl (($crc & 0xF) + 0x30)])}
:return $crchex
}
:local defaultphone 600
:local filename "cfg.xml.txt"
do {
:set defaultphone ([:pick [/system identity get name] ([:len [/system identity get name]]-2) [:len [/system identity get name]]]+600)
} on-error={:log info "use default phone number 600"}
:local cfg ("<\?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" \?>\n\
<gs_provision version=\\\"1\\\">\n\
<config version=\\\"1\\\">\n\
<P271>1</P271>\n\
<P270>PHONE\$default_phone</P270>\n\
<P47>10.62.5.2</P47>\n\
<P35>\$default_phone</P35>\n\
<P36>\$default_phone</P36>\n\
<P34>Pass\$default_phone\".\"word</P34>\n\
<P3>CGB</P3>\n\
<P1402>1</P1402>\n\
<P1405>0</P1405>\n\
<P1377>RSXX0433</P1377>\n\
<P1415>0</P1415>\n\
<P8>0</P8>\n\
<P146>phone-\$default_phone</P146>\n\
<P1348>0</P1348>\n\
<P2>admin</P2>\n\
<P238>0</P238>\n\
<P194>2</P194>\n\
<P285>1</P285>\n\
<P1362>ru</P1362>\n\
</config>\n\
</gs_provision>\n")
:local cfgcrc [$crc8 $cfg [:len $cfg]]
if ([:len [/file find name=cfg.xml.txt]] > 0) do={
:local fc [/file get $filename contents]
:local filecrc [$crc8 $fc [:len $fc]]
if ($cfgcrc = $filecrc) do={
:log info "provision files equals"
} else={
/file print file=$filename
:delay 2
/file set $filename contents=$cfg
}
} else={
:log info "provision file not exists. creating"
/file print file=$filename
:delay 2
/file set $filename contents=$cfg
}
Сначала, скрипт получает строку /system identity, выделяет два последних символа, которые являются номером маршрутизатора и прибавляет к значению телефонного номера по умолчанию (в данном случае — 600). Так как символы могут оказаться не числом, то завернём код в обработчик исключения и при неверной строке просто оставим номер по умолчанию и сообщим об этом в лог.
Далее, создаём строку с конфигурацией, в которую вставляем из переменной полученный номер телефона и считаем её CRC8. Если файл существует в файловой системе, то считаем его контрольную сумму и сравниваем с CRC конфигурации в памяти и если контрольные суммы равны, значит ничего не изменилось и можно оставить всё как есть, иначе перезаписываем файл.
Теперь разрешаем доступ к файлу через TFTP, добавив в конфигурацию Mikrotik следующие строки:
/ip tftp add real-filename=cfg.xml.txt req-filename=cfg.xml
И не забудем добавить скрипт в планировщик:
/system scheduler add interval=1d name=phone on-event=phone policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon start-date=jan/01/1970 start-time=00:00:00