суббота, 20 февраля 2010 г.

Переопределение настроек DHCP на клиенте

Когда появляется задача использовать в локальной сети какие-то дополнительные настройки помимо тех, которые предлагает использовать DHCP сервер, есть несколько способов сделать это.
На мой взгляд наиболее правильный и простой способ (ну или, по крайней мере, один из них) - использовать возможности dhclient.

Вот так, к примеру, выглядит /etc/dhclient.conf на нетбуке, с которого я пишу это сообщение:
interface "wlan0" {
 send host-name "btr-nb.properlan.net";
 prepend domain-name-servers 10.0.0.3;
 append classless-routes 29,192,168,212,0,10,0,12,12;
 request subnet-mask, broadcast-address,
  classless-routes, routers, domain-name,
  domain-name-servers, host-name;
}
Здесь есть две дополнительные команды prepend и append, которые позволяют изменить настройки, выдаваемые DHCP сервером. В моём случае это адрес DNS сервера и дополнительный статический маршрут.

В общем-то, вроде ничего сложного, об этих командах можно прочитать в руководстве dhclient.conf(5). Команда append добавляет указанное значение к выбранной опции, а prepend добавляет к указанному значению значение, выдаваемое сервером. Есть и ещё одна команда - supersede, она переопределяет значение указанной опции. Сложность может вызвать разве что выбор формата, в котором записать значение опции. Даже в приведённом мной примере не для каждого покажется очевидным, что запись "29,192,168,212,0,10,0,12,12" означает "192.168.212.0/29 10.0.12.12". Мне в какой-то степени это проще, ведь я добавлял поддержку этой опции в dhclient. :)

Формат каждой опции можно узнать в исходном коде dhclient'а. К счатью, это вполне по силам любому, знание языков программирования для этого не нужно. Для этого достаточно просмотреть файл /usr/src/sbin/dhclient/tables.c:
/*
 * DHCP Option names, formats and codes, from RFC1533.
 *
 * Format codes:
 *
 * e - end of data
 * I - IP address
 * l - 32-bit signed integer
 * L - 32-bit unsigned integer
 * s - 16-bit signed integer
 * S - 16-bit unsigned integer
 * b - 8-bit signed integer
 * B - 8-bit unsigned integer
 * t - ASCII text
 * f - flag (true or false)
 * A - array of whatever precedes (e.g., IA means array of IP addresses)
 */

struct universe dhcp_universe;
struct option dhcp_options[256] = {
        { "pad", "",                                    &dhcp_universe, 0 },
        { "subnet-mask", "I",                           &dhcp_universe, 1 },
        { "time-offset", "l",                           &dhcp_universe, 2 },
        { "routers", "IA",                              &dhcp_universe, 3 },
В комментарии перечислены буквенные коды возможных форматов опций, например "I" - IP-адрес, а "IA" - список IP адресов. Так, для опции domain-name-servers указан код формата "IA". Это значит, что в dhclient.conf эту опцию можно задать списком IP адресов, перечисленных через запятую. Для опции classless-routes указан код формата "BA" - список беззнаковых чисел. Но для того чтобы знать, какие числа указывать, нужно изучить RFC 3442. Если в кратце - сначала идёт маска сети, затем значащие цифры номера сети и потом адрес шлюза. Но длинна номера сети может различаться в зависимости от маски, поэтому лучше всётаки изучить RFC.
Ну и в качестве дополнительного бонуса, в файле tables.c можно найти все поддерживаемые опции.

1 комментарий:

  1. клиент для определения динамических адресов в различных сетях взял на себя обязанности работы со статическими правильно ли это?

    возможно, да не наверняка, проще было в стартовый скрипт добавить пару строк или включить dhcp дома, нынче это сложно НЕ сделать

    ОтветитьУдалить