0x0 — введение
0x1 — разбираем 🙂
0x2 — знакомимся с программной частью
0x3 — формат прошивки
0x4 — модифицируем файловую систему
0x5 — пишем первую программу
0x6 — последовательный порт
0x7 — заключение
Превращаем ADSL-модем в Ethernet-шилд
Возможно кто-нибудь помнит, как на новогодних каникулах мы проводили исследования ADSL-модема на базе Linux — ZTE ZXDSL831AII (подобен D-link DSL-2500U) и при выводе последовательного интерфейса я обмолвился о возможности превращения модема в своеобразный Ethernet-шилд.
Чтож, настала пора это сделать!
В принципе, задача выглядит просто, но при её решении я столкнулся с несколькими подводными камнями, которые неплохо отняли время на своё решение 🙂
Основная идея превращения модема в Ethernet-шилд очень проста — нужно всего-лишь запустить на модеме программу, которая будет слушать определённый сетевой порт и при подключении выдавать в него данные из последовательного порта и наоборот, передавать принятые данные в последовательный порт.
Разумеется, настоящий Ethernet-шилд позволяет Arduino/CraftDuino работать не только в режиме сервера, но и клиента ( слать запросы в google и писать в twitter) — этого данное решение пока не позволяет, хотя, думаю всё зависит от программы, которую вы запустите на ADSL-модеме 😉
Данное же решение подойдёт, если вам требуется управлять своим контроллером через Ethernet. Например, на базе этого решения можно построить настоящий умный дом 🙂 Короче, всё ограничивается вашей фантазией 😉
А если у вас есть под рукой Wi-Fi-роутер D-Link DIR-320, то всё вообще становится намного проще. На него можно установить прошивку от Олега (http://wl500g.info), OpenWRT (http://openwrt.org) или dd-wrt (http://www.dd-wrt.com)
и превратить свой роутер в настоящего робота!
Идея остаётся та же — на роутере запускается программа трансляции пакетов из сети в последовательный порт, который слушает контроллер и управляет двигателями и прочими робо-прибамбасами. Причём всё это через беспроводное Wi-Fi-соедеинение. Самое удобное, что у D-Link DIR-320 есть USB-порт, к которому можно подлкючить web-камеру (поддерживающую UVC) и с помощью mjpeg-streamer передавать видеокартинку!
Итак, нам нужна программа-прокси слушающая сокет и передающая принятые данные в последовательный порт.
Такая программы уже есть:
http://ser2net.sourceforge.net — Serial to Network Proxy
но я воспользуюсь утилитой suart, написанной участником робофорума — Dead
Пересобираем программу под наш модем. У меня уже установлен toolchain для ADSL модема D-link 2500U
собираем программу
./bin/mips-linux-gcc -o suart suart.c
однако, при попытке запустить программу на модеме она последовательно выдавала ошибки:
/usr/bin/suart: can't resolve symbol 'cfmakeraw' /usr/bin/suart: can't resolve symbol 'cfsetispeed' /usr/bin/suart: can't resolve symbol 'tcflush'
так что, пришлось немного модифицировать программу.
Скачать исходник и готовую программу можно здесь:
suart-DSL-2500.zip
По-умолчанию, программа слушает 3000-й порт и перебрасывает данные на /dev/ttyS0 на скорости 115200.
Эти значения можно изменить с помощью параметров командной строки:
./suart -? Suart is tool that allow you to tunnel a local serial connection over a network Usage: suart [-s] [-p ] [-b ] [-d] [-?] -s Set serial port, default is /dev/ttyS0 -p Set socket address, default is 3000 -b Set serial port baudrate (9600/19200/38400/57600/115200), default is 115200 -d Show debug info - transferred data -w wait seconds befor run, default is 0 -? (-h) Show this help page Example: suart -s/dev/ttyS1 -p3005 -b9600 -d
но для нашего модема всё подходит и программу можно запускать без параметров.
Итак, у вас уже есть программа, которую нужно запихнуть в модем. Для этого нужно модифицировать его файловую систему.
Распаковываем корневую файловую систему (можно взять файл rootfs из предыдущих примеров например, вот этот — sq7.bin).
Напоминаю, что распаковку нужно делать под суперпользователем root 😉
У нас появляется директория
squashfs-root
копируем нашу программу suart в каталог /usr/bin/
(туда же скопируйте программу sleep, которая принимает в качестве параметра число секунд на которые нужно уснуть системе — она нам пригодится )
sleep-DSL-2500.zip
Но так как мы запихнули аж две дополнительных программы — размер корневой файловой системы вырастет и прошивка на модеме скорее всего не запустится. Всё просто — нужно удалить что-нибудь ненужное.
Например, картинки из веб-интерфейса!
переходим в /webs/ и видим много gif-ок
выполним команду
for i in *.gif; do > $i; done;
файлы никуда не делись, но теперь имеют нулевой размер.
Однако, если просто запустить программу на модеме — достучаться до 3000-го порта не получится! Всё дело в файрволе(!!!) iptables, который работает на модеме.
если проверить порт с помощью nmap-а:
nmap -v 192.168.1.1 -p 3000
то он выдаст, что порт открыт, но фильтруется и подключиться к нему не получится 🙁
Окончательно проверить догадку относительно файрвола просто — можно убить http (командой kill -9) и запустить suart на 80-м порту
# /usr/bin/suart -p80
и всё заработает 🙂
Придётся разбираться с iptables. Как звучит-то: настроить файрвол на модеме :)))
Посмотреть существующие настройки можно командой:
# /bin/iptables --list Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT udp -- anywhere anywhere udp dpt:5100 ACCEPT udp -- anywhere anywhere udp dpt:1900 ACCEPT udp -- anywhere anywhere udp dpt:5431 ACCEPT tcp -- anywhere anywhere tcp dpt:5431 ACCEPT all -- anywhere anywhere state RELATED,ESTAB LISHED ACCEPT udp -- anywhere anywhere udp dpt:tftp ACCEPT tcp -- anywhere anywhere tcp dpt:telnet ACCEPT icmp -- anywhere anywhere icmp echo-request ACCEPT tcp -- anywhere anywhere tcp dpt:www ACCEPT tcp -- anywhere anywhere tcp dpt:ftp DROP all -- anywhere anywhere Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination Ага - в цепочке INPUT видим последнюю инструкцию DROP all -- anywhere anywhere
В принципе, можно просто очистить всю таблицу командой:
/bin/iptables -F
Но это не наш метод 🙂
Узнаем номер DROP-а, чтобы его удалить:
# /bin/iptables --list --line-numbers Chain INPUT (policy ACCEPT) num target prot opt source destination 1 ACCEPT udp -- anywhere anywhere udp dpt:5100 2 ACCEPT udp -- anywhere anywhere udp dpt:1900 3 ACCEPT udp -- anywhere anywhere udp dpt:5431 4 ACCEPT tcp -- anywhere anywhere tcp dpt:5431 5 ACCEPT all -- anywhere anywhere state RELATED, ESTABLISHED 6 ACCEPT udp -- anywhere anywhere udp dpt:tftp 7 ACCEPT tcp -- anywhere anywhere tcp dpt:telnet 8 ACCEPT icmp -- anywhere anywhere icmp echo-requ est 9 ACCEPT tcp -- anywhere anywhere tcp dpt:www 10 ACCEPT tcp -- anywhere anywhere tcp dpt:ftp 11 DROP all -- anywhere anywhere Chain FORWARD (policy ACCEPT) num target prot opt source destination Chain OUTPUT (policy ACCEPT) num target prot opt source destination
Удаляем DROP (11-е правило в цепочке INPUT):
/bin/iptables -D INPUT 11
Остайтся открыть 3000-й порт:
/bin/iptables -A OUTPUT -p tcp -m tcp --dport 3000 -j ACCEPT /bin/iptables -A INPUT -p tcp -m tcp --sport 3000 -j ACCEPT
Проверяем — работает!
Запихнём эти команды в файл /usr/bin/mytest
#!/bin/sh echo "[i] RoboCraft is cool!" echo "[i] edit iptables ..." /bin/iptables -D INPUT 11 /bin/iptables -A OUTPUT -p tcp -m tcp --dport 3000 -j ACCEPT /bin/iptables -A INPUT -p tcp -m tcp --sport 3000 -j ACCEPT echo "[i] iptables done!"
Остаётся прописать выполнение этих команд и последующий вызов suart-а в автозагрузку.
Сначала я пробовал запихнуть это дело в /etc/init.d/rcS
мучал его и так и эдак, пробовал ставить в конце & — чтобы программа запускалась в фоновом режиме.
Добавлял в suart параметр w который вызывал задержку(в секундах), вставлял в suart fork() — ни в какую!
В итоге, последняя редакция rcS
#! /bin/sh PATH=/sbin:/bin export PATH mount -t proc proc /proc /bin/mount -a #/sbin/inetd echo "[i] Start..." #/usr/bin/suart -w30 #echo "[i] Ok. Wait 30 sec..."
А где же вызов программы? Всё просто — обратите внимание на лог загрузки модема, который можно посмотреть через последовательный порт.
Если использовать вышеприведённый rcS, то строчка
[i] Start…
будет сразу после строчки
Algorithmics/MIPS FPU Emulator v1.5
а iptables, похоже стартуют позже
обратите внимание на строчку
==> Bcm963xx Software Version:
она отыскалась в здоровущем (аж целый мегабайт!) файле
/bin/cfm
Я решил сделать ход конём — переименовываем файл /bin/cfm в /bin/cfm0
а на его место запихнул скрипт следующего содержания:
#! /bin/sh echo "[i] CFM..." /bin/cfm0 & echo "[i] my start..." /usr/bin/sleep 30 && /usr/bin/mytest /usr/bin/suart
Как видим, он запускает оригинальный /bin/cfm0 в фоновом режиме, а потом ждёт 30 секунд и запускает /usr/bin/mytest, который прописывает дополнительные настройки iptables, а затем и наш /usr/bin/suart
Не забудем сделать скрипт исполняемым и… всё! Можно паковать прошивку!
выполняем команду упаковки корневой файловой системы:
./mksquashfs squashfs-root/ sq8.bin -be -no-fragments -noI -all-root -noappend -lzma -b 65536
получаем sq8.bin
далее используем мою утилиту packImage.exe из набора
ParseImage
и генерируем файл прошивки.
для ZTE ZXDSL831AII:
packImage.exe bcm.bin cfe.bin sq8.bin kernel.bin move result.bin result-sq8-suart.bin
получаем result-sq8-suart.bin
Заходим в веб-интерфейс модема, вкладка Management -> Update firmware
указываем наш файл result-sq8-suart.bin и ждём.
Если смотреть на последовательно порту лог загрузки то мы увидим следующее:
... init started: BusyBox v1.00 (2008.01.31-12:18+0000) multi-call binary Algorithmics/MIPS FPU Emulator v1.5 [i] Start... BusyBox v1.00 (2008.01.31-12:18+0000) Built-in shell (msh) Enter 'help' for a list of built-in commands. Loading drivers and kernel modules... bcm_enet: module license 'Proprietary' taints kernel. Broadcom BCM6338A2 Ethernet Network Device v0.3 Jan 31 2008 20:15:18 Config Internal PHY Through MDIO BCM63xx_ENET: 100 MB Full-Duplex (auto-neg) eth0: MAC Address: 00:D0:D0:86:86:B5 Broadcom BCM6338A2 USB Network Device v0.4 Jan 31 2008 20:15:20 usb0: MAC Address: 00 D0 D0 86 86 B6 usb0: Host MAC Address: 00 D0 D0 86 86 B7 [i] CFM... [i] my start... eth0 Link UP. BcmAdsl_Initialize=0x800EDB88, g_pFnNotifyCallback=0x801A48C4 AnnexCParam=0x7FFF7EB8 AnnexAParam=0x00000980 adsl2=0x00000000 pSdramPHY=0xA07FFFF8, 0x9D701 0xDEADBEEF AdslCoreHwReset: AdslOemDataAddr = 0xA07F8054 AnnexCParam=0x7FFF7EB8 AnnexAParam=0x00000980 adsl2=0x00000000 dgasp: kerSysRegisterDyingGaspHandler: dsl0 registered ATM proc init !!! ip_tables: (C) 2000-2002 Netfilter core team ip_conntrack version 2.1 (61 buckets, 0 max) - 376 bytes per conntrack ip_conntrack_pptp version 2.1 loaded ip_nat_pptp version 2.0 loaded ip_conntrack_rtsp v0.01 loading ip_ct_h323: init success ip_nat_h323: init success insmod: cannot open module `/lib/modules/2.6.8.1/kernel/net/ipv4/netfilter/ip_co nntrack_tftp.ko': No such file or directory insmod: cannot open module `/lib/modules/2.6.8.1/kernel/net/ipv4/netfilter/ip_na t_tftp.ko': No such file or directory ip_nat_irc: Unknown symbol needs_ip_conntrack_irc insmod: cannot insert `/lib/modules/2.6.8.1/kernel/net/ipv4/netfilter/ip_nat_irc .ko': Success (2): Success ip_nat_rtsp v0.01 loading ==> Bcm963xx Software Version: ZXDSL 831AIIV4.1.0a_E09_RU <== device usb0 entered promiscuous mode br0: port 1(usb0) entering learning state br0: topology change detected, propagating br0: port 1(usb0) entering forwarding state ... br0: port 3(nas_0_1_92) entering learning state br0: topology change detected, propagating br0: port 3(nas_0_1_92) entering forwarding state CONSOLED launched exit CONSOLED exited CONSOLED launched exit CONSOLED exited CONSOLED launched exit br1: port 1(usb0) entering disabled state [i] RoboCraft is cool! [i] edit iptables ... [i] iptables done!
полный лог - suart_loading_log.txt
Обратите внимание - когда стартует /etc/init.d/rcS (строчка [i] Start...)
и когда /bin/cfm (строчка [i] CFM... )
проверяем порт с помощью nmap-а:
nmap -v 192.168.1.1 -p 3000
и видим:
Host 192.168.1.1 appears to be up ... good. Interesting ports on 192.168.1.1: PORT STATE SERVICE 3000/tcp open ppp
отлично! порт открыт!
Пробуем подключиться:
telnet 192.168.1.1 3000
Работает!!!!
Вот, собственно и всё. Разумеется, наверное можно отключить вывод отладочной информации о загрузке модема, чтобы на вход микроконтроллера не сыпались лишние данные, но, думаю, это не обязательно - просто перед своими управляющими командами нужно добавить какое-нибудь кодовое слово и всё.
Программы:
suart-DSL-2500.zip
sleep-DSL-2500.zip
sq8.bin
result-sq8-suart.bin
ParseImage
Далее: Исследование Wi-Fi-роутера TP-LINK TL-MR3020
Ссылки
Что нам стоит «умный дом» построить. Делаем фарш из микроконтроллеров и роутера
http://roboforum.ru/wiki/DIR-320
http://roboforum.ru/forum10/topic9534.html
http://roboforum.ru/forum88/topic9793.html
iptables:
http://www.posix.ru/network/iptables/
http://www.opennet.ru/docs/RUS/iptables/
http://www.frozentux.net/iptables-tutorial/iptables-tutorial.html
программирование под Linux:
http://www.advancedlinuxprogramming.com
http://www.opennet.ru/docs/RUS/serial_guide/
Автор: Vladimir (noonv), 2011
Эксклюзивно для robocraft.ru
копирование на другие ресурсы и публикация
без разрешения автора запрещены.
11 комментариев на «“Превращаем ADSL-модем в Ethernet-шилд для Arduino/CraftDuino”»
Если есть полноценный процессор, крос-компилятор и внешние порты, то
нафига козе баянмикроконтроллер? Прогу то можно прямо линуховую написать.Но шилд то конечно своеобразный получился — работающий на последовательном порту. SPI здесь бы лучше смотрелся бы:)
Какое количество внешних портов доступно у данного модема? Светодиоды?
Круто. Изобретательское решение с iptables 🙂
ЗдОрово! Спасибо за статью. А как бы вообще заменить CFM скриптами? Broadcom и вендоры как правило не дают его исходники, а этот монстр управляет всем в роутере.
почему же — на сайте Broadcom есть исходники их CFM 😉
Правда? А вы не путаете CFM с CFE? Может быть ссылочку дадите?
вы правы, я перепутал и говорил оCFE 🙁
Помогите с прошивкой для D-link 2500u — сделал кто? Можете выложить?
Подскажите пожалуйста, как на модем добавить telnet? Сейчас при попытке подключения порт открыт, но подключение обрывается
Прошивка со скорость UART 9600result.bin
подскажите, плиз, уважаемые Гуру) можно ли заставить br1 —выделенный в отдельную группу интерфейс — получать сетевые настройки по DHCP? через ifconfig можно настроить фиксированный ip и gw, а если выполнить команду
, то вылазиет ошибка
, что понятно, т.к в папке /proc/var/fyi/wan нет ничего про br1.. Если создать ADSL подключение, то его имя появляется в папке wan — типа nas_0_8_35.
Может есть способ создать там и папку br1? Или можно запустить dhcpc в обход использования этой папки? Или может можно переименовать br1 в nas_0_8_35.
Машинка — DLink dsl-2640u/bru/c2, fw:2.05