2014/05/13

2014-05-13:mac のベンダーコードを判別して配布するアドレスレンジを分ける

とある同一ネットワークに異なるベンダーコードの NIC を搭載した機器が混在していて、そいつらに対して配布するアドレスの範囲を変えたい、というちょっと特殊なニーズ。
dhcpd.conf 内で mac アドレスを substring() するような仕組みってあるかな、とググったら、dhcpd-eval(5) な man を発見。

substring (data-expr, offset, length)
The substring operator evaluates the data expression and returns the substring of the result of that evaluation that starts offset bytes from the beginning, continuing for length bytes. Offset and length are both numeric expressions. If data-expr, offset or length evaluate to null, then the result is also null. If offset is greater than or equal to the length of the evaluated data, then a zero-length data string is returned. If length is greater then the remaining length of the evaluated data after offset, then a data string containing all data from offset to the end of the evaluated data is returned.

hardware
The hardware operator returns a data string whose first element is the type of network interface indicated in packet being considered, and whose subsequent elements are client’s link-layer address. If there is no packet, or if the RFC2131 hlen field is invalid, then the result is null. Hardware types include ethernet (1), token-ring (6), and fddi (8). Hardware types are specified by the IETF, and details on how the type numbers are defined can be found in RFC2131 (in the ISC DHCP distribution, this is included in the doc/ subdirectory).

ここらへんですね。

以下のような dhcpd.conf でいけました。
CentOS6 の ics-dhcpd-4.1.1-P1 で動作確認。

shared-network mynetwork {
    subnet 192.168.0.0 netmask 255.255.255.0 {
        option routers 192.168.0.1;
        option broadcast-address 192.168.0.255;
        option domain-name-servers 192.168.0.1;
    }

    class "group1" {
        match if substring (hardware,1,3) = 00:12:34;
    }
    class "group2" {
        match if substring (hardware,1,3) = aa:bb:cc;
    }

    pool {
        allow members of "group1";
        range 192.168.0.10 192.168.0.50;
    }
    pool {
        allow members of "group2";
        range 192.168.0.51 192.168.0.100;
    }
}

なんだかんだ、正解が分かるまで小一時間かかってしまった。
hardware,1 が mac を示していて、そこのアタマ 3bytes ということで substring(hardware,1,3) なんだけど、それの比較先が “00:12:34” みたいなのは、どうも直感的じゃないよなぁ。。。
substring() は一般に”文字列”の切り出しの関数だし、文字列として8文字もしくは6文字の比較で考えたくなってしまう。