По мере освоения linux начинаешь все больше и больше вникать в систему, понимать ее, все чаще хочется контролировть свою систему на качественно новом уровне, а не ожидать от нее финтов ушами. :) На определенном этапе я перешел от готовых программных продуктов типа kppp (ссылка) и wvdial (ссылка) до простых скриптов дозвона. Это позволяет мне контролировать весь процесс соединения с провайдером, что бывает иногда очень полезным :) об этом в конце статьи.
Что делать?
Наличие Linux на машине. Учтите без этого ничего не заработает. :) В моем случае это ALTLinux Master 2.2 (ссылка)
Один текстовый редактор. Лучше vim (ссылка) (для особо вдвинутых emacs (ссылка) )
Установленные пакеты ppp и ppp-extra.
И конечно не забудь закачать сами скрипты архив (выложить архив)
Все три скрипта ppp-onppp-off redialer помещаем в /etc/ppp, хотя любая другая папка тоже подойдет. Если папка отличается от /etc/ppp, не забудьте внести изменения в ppp-on.
ppp-on
Как ясно из названия, если кто англицкий язык конечно знает, этот скрипт отвечает за включение ppp-соединение. PPP расшифровывается как Point To Point протокол, а дословно переводиться как От Точки До Точки. О нем подробно можно почитать в документах (сылки на RFC). За ppp соединение в linux отвечает программка pppd, но только за него. Дозвон и регистрацией в системе провайдера занимается другая программка chat.
Вот собственно и сам скрипт
Итак
DIALER_SCRIPT=/etc/ppp/redialer как я уже говорил, за дозвон и авторитизацию отвечает программка chat, вот redialer является скриптом, который передает нужные данные этой программке. Можно сказать, что этот скрипт отвечает дозвон.
/dev/modem это собственно мой модем в linux'е, то как система его воспринимает :)
debug Увеличить уровень отладки (то же что -d). Если эта опция есть, pppd будет записывать в журнал все прибывшие и отправленные пакеты в читабельной форме. Пакеты регистрируются в лог-файлах через syslog со средством daemon и уровнем отладки.
-chap Не соглашаться с аутентификацией CHAP.
+pap Требует, чтобы другая сторона назвала себя используя PAP.
115200 максимальная скорость передачи данных.
crtscts Использовать аппаратное управление потоком данных (напр., RTS/CTS), чтобы управлять потоком данных на последовательном порту
noauth Не требовать от удаленной стороны назвать себя перед тем как начнется обмен пакетами.
defaultroute Добавить маршрут по умолчанию в системную таблицу маршрутизации. Эта запись удаляется при завершении связи.
name username Установить имя локальной системы для аутентификационных целей в username.
mru <n> Установить значение MRU [Maximum Receive Unit] в <n> при договоренности. pppd запросит удаленную сторону отправлять пакеты не более, чем по <n> байт. Минимальное значение MRU 128. Значение MRU по умолчанию 1500. Для медленных линков рекомендуется 296 (40 байт для заголовка TCP/IP + 256 байт данных).
mtu <n> Установить значение MTU [Maximum Transmit Unit] в <n>. Пока другая сторона на попросит меньшее значение при договоре о MRU, pppd будет требовать у сетевого кода ядра отправлять пакеты данных не более, чем по n байт через сетевой интерфейс PPP.
idle <n> Время в секундах после истечения которого pppd положить трубку, если не пересылаются пакеты. Очень удобная опция, чтобы случайно не растратить все деньги со счета. :)
updetach pppd не будет уходить в background до тех пор, пока не будет раздан ip-адрес.
connect $DIALER_SCRIPT указывает программку дозвона
Примечания:
Конструкция типа
применяется мной для ситуаций, когда DIALER_SCRIPT отработал, начинается установка ppp соединения, но на этом этапе происходит ошибка. При отсутсвии параметра updetach у pppd и конструкции выше скрипт просто подвисает. Особенно это паршиво при хитрых закачках ;) О них по позже.
НЕ забудьте добавить строку «ваш_логин_у_провайдера» * «ваш_пароль_у_провайдера» в /etc/ppp/pap-secrets
redialer
ABORT 'строка' отмена при получении от модема ошибки в виде строки
\n новая строка
\r отослать или ожидать символа возврата каретки
BUSY модем обнаружил короткие гудки (сигнал «занято»).
NO DIALTONE модем не обнаружил непрерывного гудка (сигнала «набирайте»).
ERROR была введена неверная или недопустимая в данном режиме команда, произошел сбой аппаратуры модема или длинна командной строки превысила 40 символов
NO CARRIER потеряна (или не обнаружена в процессе установления соединения) несущая удаленного модема.
NO ANSWER модем не обнаружил «тишину» в линии, когда был использован символ '@' в команде набора номера.
RINGING модем обнаружил входящий звонок.
'' ожидать или отослать строку нулевой длины
at &d2 &c1 S7=60 выполнить команду (c at начинаются все команды модема)
&d2 падение входного сигнала вызывает переход в командный режим с разрывом соединения.
&c1 разрешает контроль несущего сигнала, уровень на линии DCD определяется несущим сигналом в канале.
S7=60 время ожидания тона «ответ» удаленного модема после набора номера в секундах.
M0 спикер всегда выключен
D набрать номер
T тональный (DTMF) набор номера
PHONE переменная с номером телефона
Последующая часть функции обозначает, что если предыдущая команда, chat, вернула нулевое значение, то скрипт завершается c кодом 0.
А вот и конец этого скрипта
initialize вызов соответствующей функции
if [ ! "$?" = 0 ] если функция вернула не нулевое значение то exit 1.
attempt=0 переменной attempt присвоили значение 0
while : делаем до бесконечности
attempt=`expr $attempt + 1` переменной attempt присвоить результат выполнения команды expr (вычислить выражение) 1 + $attempt. Т.е. увеличить значение переменной на 1
callnumber вызов функции
echo «I'm trying to call $attempt's time» > /dev/console написать в консоль данную фразу
if [ "$attempt" = "$MAX_ATTEMPTS" ] если количество попыток в переменной attempt совпадает с числом в переменной MAX_ATTEMPTS, то вызвать exit с 1
sleep "$SLEEP_DELAY" ничего не делать в течении SLEEP_DELAY секунд.
ppp-off
Вот и выключатель всей этой эпопеи
DEVICE=ppp0 переменной DEVICE
if [ -r /var/run/$DEVICE.pid ] если файл /var/run/$DEVICE.pid существует и имеет права на чтение, то
kill -INT `cat /var/run/$DEVICE.pid` послать сигнал INT процессу с номером хранящимся в /var/run/$DEVICE.pid
if [ ! "$?" = 0 ]; then если результат предыдущей команды был не ноль, то