[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Debian JP master SVN www commits (rev.187)



=======================================================
Repository: /org/svn.debian.or.jp/repos
  Revision: 187
  Commiter: yasu
      Date: 2007-02-27 20:00:52 +0900 (火, 27  2月 2007)
=======================================================
Log:

initial import

=======================================================
Changed:

A   cdn/
A   cdn/ChangeLog
A   cdn/Q_and_A.dns_balance
A   cdn/Q_and_A.dns_balance.eng
A   cdn/README.dns_balance
A   cdn/README.dns_balance.eng
A   cdn/README.dnsbalance+daemontools
A   cdn/README.dnsbalance+daemontools.eng
A   cdn/addrdb.rb
A   cdn/as_search.rb
A   cdn/cache.rb
A   cdn/datatype.rb
A   cdn/dns_balance.rb
A   cdn/log_writer.rb
A   cdn/multilog.rb
A   cdn/namespace.rb
A   cdn/sample/
A   cdn/sample/addr
A   cdn/sample/addr.ring
A   cdn/sample/addr.ring.txt
A   cdn/sample/make_namespace.rb
A   cdn/sample/makedb.rb
A   cdn/sample/makeringdb.rb
A   cdn/sample/namespace.rb
A   cdn/sample/namespace.txt
A   cdn/sample/ringupdate.sh
A   cdn/util.rb

Added: cdn/ChangeLog
===================================================================
--- cdn/ChangeLog	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/ChangeLog	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,126 @@
+2005-06-09  YOKOTA Hiroshi  <yokota@xxxxxxxxxxxxxxxxxxxxxxx>
+
+	* dns_balance.rb: コマンドラインオプションの解析を "getopts.rb" か
+	ら "optparse.rb" の物にする。
+	Ruby 1.8 でサポートされた Socket::do_not_reverse_lookup の設定によ
+	り DNS を意図せずに使わない様にする事が出来るようになったので
+	Socket ではなく UDPSocket が使えるようになった。
+
+2003-02-01  YOKOTA Hiroshi  <yokota@xxxxxxxxxxxxxxxxxxxxxxx>
+
+	* dns_balance.rb: -d オプションによる NS/SOA レコードがキャッシュ
+	サーバを混乱させるようなので削除する事にした。
+
+2003-01-30  YOKOTA Hiroshi  <yokota@xxxxxxxxxxxxxxxxxxxxxxx>
+
+	* dns_balance.rb: SOA レコードが正しく NS レコードと対になっていな
+	かったので直す。
+
+2002-10-13  YOKOTA Hiroshi  <yokota@xxxxxxxxxxxxxxxxxxxxxxx>
+
+	* log_writer.rb : 起動しないバグ修正。カンマが一つ多かった。
+
+2002-10-10  YOKOTA Hiroshi  <yokota@xxxxxxxxxxxxxxxxxxxxxxx>
+
+	* dns_balance.rb: パケットの末尾にゴミを付けてよこす DNS
+	クライアントがあるようだ。パケットの解析法を変える。
+
+2002-10-04  YOKOTA Hiroshi  <yokota@xxxxxxxxxxxxxxxxxxxxxxx>
+
+	* dns_balance.rb: キャッシュサーバがおかしくなる原因は他にあるようだ。
+	元に戻す。
+	* multilog.rb: クラスの汎用度を高める改良。IO クラスの任意の出力
+	ポート(ファイル、ネットワークソケットなど)に出力できるようになる。
+
+2002-09-27  YOKOTA Hiroshi  <yokota@xxxxxxxxxxxxxxxxxxxxxxx>
+
+	* dns_balance.rb: DNS キャッシュサーバの中には同一の内容が複数
+	含まれる返答を受けとるとおかしくなるものがあるようだ。対処する。
+
+2002-09-24  YOKOTA Hiroshi  <yokota@xxxxxxxxxxxxxxxxxxxxxxx>
+
+	* dns_balance.rb: クラスレスネットワークアドレスに対応。
+	これによりアドレスデータベースのラベルが大きく変わる。
+
+	* dns_balance.rb, as_search.rb, cache.rb: whois.ra.net の
+	AS 情報で振り分けられるようにする。AS 調査動作速度の向上の為に
+	キャッシュを設ける。
+	(Thanks! "Hiroshi Funahashi" <bass_effect@xxxxxxxxxxx>)
+
+2002-09-19  YOKOTA Hiroshi  <yokota@xxxxxxxxxxxxxxxxxxxxxxx>
+
+	* dns_balance.rb: NS,SOA レコードを単独で返せるようにする。
+	SOA レコードの内容を変える。
+
+2002-09-10  YOKOTA Hiroshi  <yokota@xxxxxxxxxxxxxxxxxxxxxxx>
+
+	* dns_balance.rb: 変数 $prefix で DNS Balance のパスを指定できる
+	ようにした
+
+	* dns_balance.rb, multilog.rb, log_writer.rb: 出力を MultiLog
+	クラス経由に変更し、 "-l" オプション削除
+
+2002-09-06  YOKOTA Hiroshi  <yokota@xxxxxxxxxxxxxxxxxxxxxxx>
+
+	* dns_balance.rb: 同時回答数を 5 個から 8 個にする。
+
+	* dns_balance.rb: 可能ならネームサーバの位置を示す NS,SOA レコードを
+	付加するようにする "-d" オプション追加
+
+2002-06-08  YOKOTA Hiroshi  <yokota@xxxxxxxxxxxxxxxxxxxxxxx>
+
+	* dns_ballance.rb : ユーザ定義例外の名前の一部が ruby の例外と
+	被ってしまったので変更。(Thanks! "Hiroshi Funahashi"
+	<bass_effect@xxxxxxxxxxx>)
+	* * : Cygwin 版 ruby で動く事を確認する
+
+Fri Feb  2 17:54:12 JST 2001
+	* dnsbalance.rb : アドレスデータベースが間違っているとデータベース更新
+	スレッドが止まるのを防ぐ
+
+Fri Dec 22 04:31:57 JST 2000
+	* dns_balance.rb : ANY レコードも受け付けるようにする。
+	これで余計な問い合わせが減り、多少は速度の向上が見込める。
+	* dns_balance.rb : djbdns と協調して動けるように listen する
+	IP アドレスを指定できるようにする
+
+Sun Dec 17 15:06:26 JST 2000
+	* dns_balance.rb : daemontools で動かせるようにログ出力の方法を
+	変更
+
+Thu Nov 30 10:07:16 JST 2000
+	* dns_balance.rb, namespace.rb : アドレスの別名を定義して
+	まとめて管理出来るようにした。
+
+Fri Sep 15 17:18:11 JST 2000
+	* dns_balance.rb : スレッドの競合により意図しない変数の上書きの可能性を
+	修正 (Thanks! TAKAHASHI Masayoshi <maki@xxxxxxxxxx>)
+
+Thu Sep  7 18:05:10 JST 2000
+	* dns_balance.rb : ホスト名に使ってはいけない文字のチェックを
+	追加
+	* dns_balance.rb : 自動更新を5分おきに変更
+
+Fri Aug 25 17:59:40 JST 2000
+	* dns_balance.rb : 選択表の圧縮をやめてみる。こうするとサーバの
+	返答内容に同一の答えが含まれる事になるが、選択効率は若干上がる。
+	問題は resolver がこれをうまく処理できるかだ。
+	* makeringdb.rb : Ring サーバ向け addr ファイル作成スクリプト。
+
+Thu Aug 24 13:33:43 JST 2000
+	* dns_balance.rb : 調査用のログ出力機能を付ける
+	* dns_balance.rb : 任意の IP アドレスで listen させる機能を付けて
+	みたが、あまり使わないような気がするので取り外す
+
+Tue Aug 15 10:58:49 JST 2000
+	* dns_balance.rb : 重みつき選択の方法に間違いがあったのを直す。
+	壊れたパケットに対する返答を強化。
+	* Ver.0.2
+
+Wed Aug  9 00:25:23 JST 2000
+	* dns_balance.rb : 例外処理を使う
+	* makedb.rb : CVS ファイルの内容によってうまくファイルが作成されない
+	バグを直す
+
+Tue Aug  8 12:48:15 JST 2000
+	* Ver.0.1 完成

Added: cdn/Q_and_A.dns_balance
===================================================================
--- cdn/Q_and_A.dns_balance	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/Q_and_A.dns_balance	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,9 @@
+
+                         << DNS Balance Q&A >>
+
+
+Q2 I want to run DNS Balance in many places.
+A2 You must transfer badness data file to all places.
+   You can use "scp" or "rsync" to transfer file.
+
+By: YOKOTA Hiroshi <yokota@xxxxxxxxxxxxxxxxxxxxxxx>

Added: cdn/Q_and_A.dns_balance.eng
===================================================================
--- cdn/Q_and_A.dns_balance.eng	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/Q_and_A.dns_balance.eng	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,25 @@
+
+                         << DNS Balance Q&A >>
+
+
+Q1 自国内と外国からの応答とで返事を変えるには?
+A1 "http://cr.yp.to/djbdns/pickdns/country"; によると、 IP アドレスと
+   マシンの存在位置にはある程度関連性があるようです。例えば、日本なら
+   130.54.*.*, 130.69.*.*, 130.87.*.* ... 等です。これを使って日本国内と
+   外国とを切り分けて下さい。例えば国内向けサーバ A と国外向けサーバ B
+   があった場合、
+
+	国内	サーバA		Badness=0
+		サーバB		Badness=5000
+	国外	サーバA		Badness=5000
+		サーバB		Badness=0
+
+   のように設定すると効果的でしょう。
+
+Q2 複数の場所で DNS Balance を動かしたいのですが
+A2 その場合、負荷分散の情報を全ての DNS Balance に配送する必要があります。
+   個々のサイトで独自に負荷情報を集めても良いのですが、一つのサイトで
+   調べ、それを scp か rsync, もしくはその両方を用いて転送すると良いで
+   しょう。
+
+By: YOKOTA Hiroshi <yokota@xxxxxxxxxxxxxxxxxxxxxxx>

Added: cdn/README.dns_balance
===================================================================
--- cdn/README.dns_balance	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/README.dns_balance	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,181 @@
+
+                              <<DNS Balance>>
+
+ By: 横田 裕思 <yokota@xxxxxxxxxxxxxxxxxxxxxxx>
+
+
+
+[1. これは何ですか]
+
+ DNS Balance は動的な負荷分散を行なう事の出来る DNS サーバーです。
+昨今は kernel.org や *bsd.org, RING サーバーなど、広範囲にミラーサーバを
+置くようなサーバが増えてきました。従来は手動でミラーサーバを選択した
+のですが、この DNS Balance によりそれを自動化できます。
+
+ DNS Balance には以下のような機能があります。
+
+o 各サーバの報告により提供するアドレスを動的に変化させる事が出来る。
+o クライアントの IP アドレス毎に提供するサーバの IP アドレスを
+  変える事が出来る。
+o 必要最小限の機能のみを提供する事により、より安全な運用が出来る(はず)。
+
+
+[2. 必要なもの]
+
+ DNS Balance は Ruby (http://www.ruby-lang.org/) で作成していますので
+Ruby を手に入れてインストールしておいて下さい。最近ではバイナリパッケージ
+もあるようです。
+
+
+[3. 実行]
+
+1. DNS Balance のアーカイブを "/usr/local/share" で展開して下さい。
+   他のディレクトリで展開する場合は スクリプト "dns_balance.rb" の先頭部分の
+   変数 $prefix の値を変更して下さい。
+2. 展開されたアーカイブの中の addrdb.rb がアドレスデータベースです。
+   これを編集する事により、提供するアドレス情報を決めます。
+   これは Ruby のプログラムで記述されているので、記述を間違うと
+   おかしくなりますので気をつけて下さい。
+
+------------------
+$addr_db = {
+  "130.12.0.0/16" => {         # => 130.12.0.0/16 からの問い合わせ。
+                               #    IPアドレス 123.45.67.89 に対しては
+                               #    "123.45.67.89/32" から
+                               #    "0.0.0.0/1" の順に調べていきます。
+    "www.foo.com" => [         # => www.foo.com のアドレス問い合わせ。
+                               #    ホスト名は小文字で書いて下さい。
+      [[1,2,3,4], 0],          # => アドレス情報と接続の難しさ(最大10000)
+      [[1,2,3,5], 10000],      #    の組を並べます。接続の難しさは 0 で
+      [[1,2,3,6], 9000],       #    最も接続しやすく、10000 で接続不可に
+      [[1,2,3,7], 9000],       #    なります。
+    ],
+  },
+  "default" => {               # => 特に指定のない場合は "default" の
+    "www.foo.com" => [         #    情報が使われます。
+      [[1,2,3,4], 0],
+      [[1,2,3,5], 100],
+      [[1,2,3,6], 1000],
+      [[1,2,3,7], 9000],
+    ],
+    "localhost" => [
+      [[127,0,0,1], 0],
+    ],
+  },
+}
+------------------
+
+3. クライアントのアドレスの振り分け先が多過ぎるようなら namespace.rb に
+   別名を定義しまとめて管理する事もできます。
+
+------------------
+$namespace_db = {
+  "127.0.0.0/8"     => "localnet",  # アドレスと別名の対を記述する。
+  "192.168.0.0/16"  => "foo-net",   # 検索順は 123.45.67.89 からの問い合わせなら
+  "130.199.0.0/16"  => "foo-net",   # "123.45.67.89/32" から
+  "130.123.12.0/28" => "foo-net",   # "0.0.0.0/1" の順です。
+}
+------------------
+
+   これを使うと addrdb.rb の記述を以下のように別名で記述する事ができます。
+
+------------------
+$addr_db = {
+  "localnet" => {
+    "www.foo.com" => [
+      [[1,2,3,6], 2000],
+      [[1,2,3,7], 1000],
+    ],
+  },
+  "foo-net" => {
+    "www.foo.com" => [
+      [[1,2,3,4], 0],
+      [[1,2,3,5], 100],
+    ],
+  },
+  "default" => {
+    "www.foo.com" => [
+      [[1,2,3,4], 0],
+      [[1,2,3,5], 10000],
+      [[1,2,3,6], 9000],
+      [[1,2,3,7], 9000],
+    ],
+  },
+}
+------------------
+
+4. また、オプション起動時にオプション "--as" を付けると whois.ra.net で
+   提供される自律ネットワーク構成情報を用いて振分をする事もできます。
+   これは調査に若干の時間がかかるので使用には注意して下さい。
+
+   whois.ra.net では以下のようなコマンドでそのアドレスの属するネットワークを
+   知らせてくれます。
+
+---------
+$ whois -h whois.ra.net 192.168.0.1
+route:         192.168.0.0/24
+descr:         Foo networks
+origin:        AS1000
+member-of:     RS-COMM_FOONET
+mnt-by:        MAINT-AS1000
+changed:       rm@xxxxxxxxx 99999999
+source:        BARNET
+---------
+
+   ここで origin と言う項目に注目して下さい。これが 192.168.0.1 の属する
+   自律ネットワークです。この項目を振り分けに使用する事ができます。
+
+--------------
+$addr_db = {
+  "AS1000" => {
+    "www.foo.com" => [
+      [[1,2,3,4], 0],
+    ],
+  },
+  "default" => {
+    "www.foo.com" => [
+      [[1,2,3,4], 0],
+      [[1,2,3,5], 10000],
+    ],
+  },
+}
+--------------
+
+
+5. プログラムを起動します。実行には root 権限が必要です。
+   "ruby /usr/local/share/DNS-Balance-x.x/dns_balance.rb"
+   とタイプして下さい。うまく動いたら "host -v <ホスト名>" 等のコマンドで
+   確かめてみて下さい。
+
+6. 展開したディレクトリに "addr" という名前のファイルがあると、一定期間毎
+   (標準では5分毎) に読み込みます。内容は addrdb.rb と同じです。
+   なお、この更新をすると以前の addrdb.rb で設定した内容が消えてしまうので
+   再設定して下さい。 CSV 形式のファイルから "addr" の内容を作成する
+   スクリプトも作ってみましたので参考にして下さい。
+
+7. オプション "-i xxx.xxx.xxx.xxx" で listen する IP アドレスを指定できます。
+   オプション "-h" で簡単なヘルプメッセージが出力されます。
+
+
+[4. お断り]
+
+ このパッケージに含まれるプログラム等については私こと 横田 裕思 に著作権が
+あります。使用した事による損害に対しては何の補償もありませんが、配布、
+変更等は自由です。ただし、変更して配布する時は変更が分かるようにファイルに
+書いて下さい。また、その際は今後の参考にしたいので、その変更点を私に教えて
+下されば有難いです。
+
+ 現在、このパッケージは私のWWWページにてメンテナンスをしています。
+時々覗いていただくと最新情報が手に入るかもしれません。
+
+   URL http://www.netlab.is.tsukuba.ac.jp/~yokota/
+       http://www.netlab.is.tsukuba.ac.jp/~yokota/izumi/dns_balance/
+
+ 使用した感想、語要望、バグ報告などをメールで送っていただければ幸いです。
+
+
+ 最後に、このパッケージを使用して下さった方、更にバク等の報告をしていただいた
+全ての人に感謝します。
+
+
+                  2002/09/06:  横田 裕思 (yokota@xxxxxxxxxxxxxxxxxxxxxxx)

Added: cdn/README.dns_balance.eng
===================================================================
--- cdn/README.dns_balance.eng	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/README.dns_balance.eng	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,157 @@
+
+                            <<DNS Balance>>
+
+ By: YOKOTA Hiroshi <yokota@xxxxxxxxxxxxxxxxxxxxxxx>
+
+
+
+[1. What's this]
+
+ DNS Balance is a load-balancing DNS server.
+Today's Web server, like "kernel.org", "*bsd.org" and Ring Server Project
+(http://www.ring.gr.jp/) are mirrored all over the world. DNS Balance
+selects fast server from all over the world for DNS resolver.
+
+ DNS Balance has these functions:
+
+o Dynamic load balancing.
+o Answer different IP address between DNS client's IP address.
+o Minimun implement. This may be good for security.
+
+
+[2. What you need]
+
+ DNS Balance requires Ruby (http://www.ruby-lang.org/).
+So, you must install it. Some PC-UNIX has binary packages.
+
+
+[3. What you do]
+
+1. Extract the archive in "/usr/local/share". If you want to extract another
+   directory, change "$prefix" in script "dns_balance.rb".
+2. File "addrdb.rb" is the address database. You must edit this for
+   your site.
+
+------------------
+$addr_db = {
+  "130.12.0.0/16" => {         # => Request from 130.12.0.0/16
+                               #    For example, DNS client's IP is
+                               #    "123.45.67.89", search "123.45.67.89/32" to
+                               #    "0.0.0.0/1".
+    "www.foo.com" => [         # => IP address for "www.foo.com"
+                               #    This host name must be lower case character.
+      [[1,2,3,4], 0],          # => IP address and badness information.
+      [[1,2,3,5], 10000],      #    Badness must be 0-10000. 0 is for fastest
+      [[1,2,3,6], 9000],       #    server, and 10000 is for downed server.
+      [[1,2,3,7], 9000],
+    ],
+  },
+  "default" => {               # => If theres nothing to match, use "default".
+    "www.foo.com" => [
+      [[1,2,3,4], 0],
+      [[1,2,3,5], 100],
+      [[1,2,3,6], 1000],
+      [[1,2,3,7], 9000],
+    ],
+    "localhost" => [
+      [[127,0,0,1], 0],
+    ],
+  },
+}
+------------------
+
+3. If your addrdb.rb is too complex to maintain, you can use namespace.rb .
+
+------------------
+$namespace_db = {
+  "127.0.0.0/8"     => "localnet", # Write IP address and its alias name.
+  "192.168.0.0/16"  => "foo-net",  # If client IP is 123.45.67.89, search
+  "130.199.0.0/16"  => "foo-net",  # "123.45.67.89/32" to "0.0.0.0/1".
+  "130.123.12.0/28" => "foo-net",
+}
+------------------
+
+   If you use namespace.rb , you can write this way.
+
+------------------
+$addr_db = {
+  "localnet" => {
+    "www.foo.com" => [
+      [[1,2,3,6], 2000],
+      [[1,2,3,7], 1000],
+    ],
+  },
+  "foo-net" => {
+    "www.foo.com" => [
+      [[1,2,3,4], 0],
+      [[1,2,3,5], 100],
+    ],
+  },
+  "default" => {
+    "www.foo.com" => [
+      [[1,2,3,4], 0],
+      [[1,2,3,5], 10000],
+      [[1,2,3,6], 9000],
+      [[1,2,3,7], 9000],
+    ],
+  },
+}
+------------------
+
+4. You can use "--as" option to use "Autonomous System" information
+   from whois.ra.net .
+
+   whois.ra.net offers AS information.
+---------
+$ whois -h whois.ra.net 192.168.0.1
+route:         192.168.0.0/24
+descr:         Foo networks
+origin:        AS1000   <==================== This is AS information
+member-of:     RS-COMM_FOONET
+mnt-by:        MAINT-AS1000
+changed:       rm@xxxxxxxxx 99999999
+source:        BARNET
+---------
+
+   You can use AS information like this.
+
+--------------
+$addr_db = {
+  "AS1000" => {
+    "www.foo.com" => [
+      [[1,2,3,4], 0],
+    ],
+  },
+  "default" => {
+    "www.foo.com" => [
+      [[1,2,3,4], 0],
+      [[1,2,3,5], 10000],
+    ],
+  },
+}
+--------------
+
+
+5. Run DNS Balance. Type "ruby /usr/local/lib/DNS-Balance-x.x/dns_balance.rb"
+   for run DNS Balance.
+
+6. If exists a file named "addr", DNS Balance is loads automatically every
+   5 minutes. This file contains same database as "addrdb.rb".
+   I make some sample script like CSV -> address database converter.
+   See "sample" directory
+
+7. "-i xxx.xxx.xxx.xxx" to specify listen IP address.
+   And "-h" to display some help message.
+
+
+[4. Copyright]
+
+ See README.dns_balance.
+
+ If you want newer version, see my homepage.
+   URL http://www.netlab.is.tsukuba.ac.jp/~yokota/
+       http://www.netlab.is.tsukuba.ac.jp/~yokota/izumi/dns_balance/
+
+ Any questions and suggestions are welcome.
+
+                  2002/09/06: YOKOTA Hiroshi (yokota@xxxxxxxxxxxxxxxxxxxxxxx)

Added: cdn/README.dnsbalance+daemontools
===================================================================
--- cdn/README.dnsbalance+daemontools	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/README.dnsbalance+daemontools	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,41 @@
+
+      <<dnemontools の配下で DNS Balance を動かす方法>>
+
+ DNS Balance は単独でも動かせますが、 D. J. Bernstein 氏の
+daemontools (http://cr.yp.to/daemontools.html,
+http://djbdns.jp.qmail.org/tools/daemontools/) の元でも動かす事が出来ます。
+
+[やりかた]
+
+1. まず、 daemontools をインストールします。
+2. DNS Balance のインストール位置を決めます。例えば /foo/bar/dnsbalance/root/
+   にします。DNS Balance のプログラムファイルをそこにコピーします。
+   また、これに合わせて dns_balance.rb の変数 $prefix の値を
+   "/foo/bar/dnsbalance/root" に変更して下さい。
+3. /foo/bar/dnsbalance/ に "run" という名前のスタートアップスクリプトを
+   作ります。例えば以下のようにします。以下の例では djbdns と協調動作させる
+   ために "-i" オプションで listen させる IP アドレスを 192.168.0.1 に
+   し、"-d" オプションでこの DNS Balance が動作するドメインを
+   "balancer.example.co.jp" にしています。また、 DNS Balance が使用する
+   メモリを最大 8メガバイトに制限しています。このスクリプトに実行属性を
+   付けて実行できるようにして下さい。
+
+------------------------------
+#!/bin/sh
+exec 2>&1
+exec softlimit -d 8000000 /usr/local/bin/ruby /foo/bar/dnsbalance/root/dns_balance.rb -i 192.168.0.1 -d balancer.example.co.jp:192.168.0.1
+------------------------------
+
+4. ログファイルを記録するために /foo/bar/dnsbalance/log/ を作り、 multilog
+   が起動するようにします。 multilog の設定は daemontools のドキュメントを
+   参照して下さい。
+   ログ記録用のプロセスを起動させるために /foo/bar/dnsbalance/ に t ビット
+   を付加するのを忘れないで下さい。最新版の daemontools ならばこれは必要
+   ありません。
+
+5. svscan を起動し、さらに svscan の監視ディレクトリ(標準では /service/)
+   に "cd /service/ ; ln -s /foo/bar/dnsbalance ." としてリンクを設定すれば
+   動き出します。
+
+
+                  2002/09/08:  横田 裕思 (yokota@xxxxxxxxxxxxxxxxxxxxxxx)

Added: cdn/README.dnsbalance+daemontools.eng
===================================================================
--- cdn/README.dnsbalance+daemontools.eng	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/README.dnsbalance+daemontools.eng	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,33 @@
+
+      <<Running DNS Balance under daemontools>>
+
+ DNS Balance can running stand alone, but you can use DNS Balance with
+"daemontools" (http://cr.yp.to/daemontools.html).
+
+
+[How to do that]
+
+1. Install daemontools.
+2. Specify where to install DNS Balance. For example,
+   "/foo/bar/dnsbalance/root/".
+   Copy all scripts to "/foo/bar/dnsbalance/root/".
+   And change valuable "$prefix" in "dns_balance.rb". (See
+   README.dns_balance.eng)
+3. Create "run" script and place to "/foo/bar/dnsbalance/".
+
+-<example>--------------------
+#!/bin/sh
+exec 2>&1
+exec softlimit -d 8000000 /usr/local/bin/ruby /foo/bar/dnsbalance/root/dns_balance.rb -i 192.168.0.1 -d balancer.example.com:192.168.0.1
+------------------------------
+
+4. If you want log file, create "/foo/bar/dnsbalance/log/" and setup "multilog".
+   See "daemontools" document.
+   And set sticky bit to "/foo/bar/dnsbalance/". (This is not need for
+   latest version of daemontools)
+
+5. Run "svscan" and create symbolic link to service directry.
+   For example, "cd /service/ ; ln -s /foo/bar/dnsbalance ."
+
+
+                  2002/09/08: YOKOTA Hiroshi (yokota@xxxxxxxxxxxxxxxxxxxxxxx)

Added: cdn/addrdb.rb
===================================================================
--- cdn/addrdb.rb	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/addrdb.rb	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,17 @@
+##Thu Feb 08 18:02:04 JST 2007
+
+$addr_db = {
+  "default" => {
+    "ns.cdn.araki.net" => [
+      [[210,157,158,38], 0],
+    ],
+    "localhost" => [
+      [[127,0,0,1], 0],
+    ],
+    "deb.cdn.araki.net" => [
+	[[203,178,137,175], 100],
+	[[210,157,158,38], 9900],
+
+    ],
+  },
+}

Added: cdn/as_search.rb
===================================================================
--- cdn/as_search.rb	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/as_search.rb	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,124 @@
+#
+# AS namespace
+#
+
+# $Id: as_search.rb,v 1.5 2003/01/31 21:50:34 elca Exp $
+
+require "socket"
+require "timeout"
+
+require "cache.rb"
+require "util.rb"
+require "datatype.rb"
+
+Ra_host = [
+  "198.108.0.18",  # whois.ra.net
+  "209.244.1.180", # rr.Level3.net
+]
+
+Whois_cache = Hash.new
+
+#require "multilog"
+#ML = MultiLog.new
+#ML.open
+
+# from Michael Neumann (neumann@xxxxxxxxxxxxxx)'s whois.rb
+def raw_whois (send_string, host)
+  s = TCPsocket.open(array_randomize(host)[0], Service::Whois)
+  s.write(send_string + "\n")
+  ret = ""
+  while l = s.gets
+    ret += l
+  end
+  s.close
+  return ret
+end
+
+def as_get(str)
+  begin
+    tmp = nil
+    as  = nil
+    net = nil
+
+    timeout(30) {
+      tmp = raw_whois(str, Ra_host)
+    }
+    tmp.split("\n").each {
+      |i|
+      if /^origin:/ =~ i
+	as = i.split[1]
+      end
+      if /^route:/  =~ i
+	net = i.split[1]
+      end
+    }
+    if as != nil && net != nil
+      return {"route" => net, "as" => as}
+    end
+
+    return nil
+  rescue
+    return nil
+  end
+end
+
+def as_search(str)
+  #p Whois_cache
+
+  netaddrs = [str] + ip_masklist(str)
+
+  # まずキャッシュを探索
+  netaddrs.each {
+    |i|
+    if Whois_cache[i] != nil
+      ML.log("cached AS: " + i + "=>" + Whois_cache[i]["as"])
+      return Whois_cache[i]["as"]
+    end
+  }
+
+  # 同じ要求が集中した時は ra.net に問い合わせが集中しないように
+  # ロックしておく。
+  Whois_cache[str] = {
+    "timeout" => Time.now.to_i + 600,   # 10分
+    "as"      => "default"
+  }
+
+
+  # ra.net に問い合わせ。結果が得られた場合はその結果でキャッシュを上書きする。
+  tmp = as_get(str)
+  if tmp != nil
+    Whois_cache.delete(str)
+
+    as  = tmp["as"]
+    net = tmp["route"]
+
+    ML.log("add AS cache: " + net + "=>" + as)
+    Whois_cache[net] = {
+      "timeout" => Time.now.to_i + 10800, # 3時間
+      "as"      => as
+    }
+    return tmp["as"]
+  end
+
+  # うまく問い合わせの結果が得られない場合はキャッシュをそのままにして
+  # nil を返す。
+  ML.log("add NULL AS cache: " + str + "=>default")
+
+  return nil
+end
+
+# 定期的に古い内容を削除
+Thread.start do
+  loop do
+    sleep 15
+    # キャッシュに時間制限をかける
+    cache_timeout(Whois_cache, "as timeout: ")
+
+    sleep 15
+    # キャッシュにサイズ制限をかける
+    cache_reduction(Whois_cache, 2000, "as overflow: ")
+
+  end
+end
+
+# end

Added: cdn/cache.rb
===================================================================
--- cdn/cache.rb	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/cache.rb	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,36 @@
+#
+# キャッシュデータ管理
+#
+
+# $Id: cache.rb,v 1.3 2003/01/31 21:50:34 elca Exp $
+
+# キャッシュの大きさ制限
+# キャッシュは "timeout" の要素を持っている事
+def cache_reduction(cache, overflow_size, logstr)
+  h = Hash.new
+  cache.each_key {
+    |key|
+    h[cache[key]["timeout"]] = key
+  }
+  if h.size > overflow_size
+    del_h = h.keys.sort[0, h.size - overflow_size] # 古い順に並べる
+    del_h.each { |i|
+      ML.log(logstr + h[i].dump + "=>" + cache[key].to_s.dump)
+      cache.delete(h[i])
+    }
+  end
+end
+
+# キャッシュの時間制限
+# キャッシュは "timeout" の要素を持っている事
+def cache_timeout(cache, logstr)
+  cache.each_key {
+    |key|
+    if cache[key]["timeout"] < Time.now.to_i
+      ML.log(logstr + key.dump + "=>" + cache[key].to_s.dump)
+      cache.delete(key)
+    end
+  }
+end
+
+# end

Added: cdn/datatype.rb
===================================================================
--- cdn/datatype.rb	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/datatype.rb	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,76 @@
+#
+# static data
+#
+# By: YOKOTA Hiroshi <yokota@xxxxxxxxxxxxxxxxxxxxxxx>
+
+# $Id: datatype.rb,v 1.5 2003/01/31 21:50:34 elca Exp $
+
+module DnsClass
+  INET  = "\0\1"
+  CS    = "\0\2"
+  CHAOS = "\0\3"
+  HS    = "\0\4"
+  ANY   = "\0\377"
+end
+
+module DnsType
+  A     = "\0\1"
+  NS    = "\0\2"
+  CNAME = "\0\5"
+  SOA   = "\0\6"
+  PTR   = "\0\14"
+  HINFO = "\0\15"
+  MX    = "\0\17"
+  TXT   = "\0\20"
+  RP    = "\0\21"
+  SIG   = "\0\30"
+  KEY   = "\0\31"
+  AAAA  = "\0\34"
+  SRV   = "\0\41"
+  A6    = "\0\46"
+  AXFR  = "\0\374"
+  ANY   = "\0\377"
+end
+
+module Signal
+  HUP    =  1
+  INT    =  2
+  QUIT   =  3
+  ILL    =  4
+  TRAP   =  5
+  ABRT   =  6
+  BUS    =  7
+  FPE    =  8
+  KILL   =  9
+  USR1   = 10
+  SEGV   = 11
+  USR2   = 12
+  PIPE   = 13
+  ALRM   = 14
+  TERM   = 15
+  # ???  = 16
+  CHLD   = 17
+  CONT   = 18
+  STOP   = 19
+  TSTP   = 20
+  TTIN   = 21
+  TTOU   = 22
+  URG    = 23
+  XCPU   = 24
+  XFSZ   = 25
+  VTALRM = 26
+  PROF   = 27
+  WINCH  = 28
+  IO     = 29
+  PWR    = 30
+  SYS    = 31
+end
+
+module Service
+  Whois   = 43
+  Domain  = 53
+  MDomain = 5353
+  DebDomain = 10053
+end
+
+# end

Added: cdn/dns_balance.rb
===================================================================
--- cdn/dns_balance.rb	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/dns_balance.rb	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,365 @@
+#!/usr/bin/ruby
+#
+# DNS Balance --- 動的負荷分散を行なう DNS サーバ
+#
+# By: YOKOTA Hiroshi <yokota@xxxxxxxxxxxxxxxxxxxxxxx>
+
+# $Id: dns_balance.rb,v 1.25 2003/06/13 22:07:27 elca Exp $
+
+# DNS Balance の存在するパス名
+if ENV["ROOT"] == nil
+  warn("\"ROOT\" environment is recommended. Use current directory in this time.")
+  PREFIX = "."
+#  exit(111)
+else
+  PREFIX = ENV["ROOT"]
+  $LOAD_PATH.unshift(PREFIX)
+end
+$LOAD_PATH.freeze
+
+require 'socket'
+require 'thread'
+require 'optparse'
+
+require 'datatype.rb'
+require 'multilog.rb'
+require 'log_writer.rb'
+require 'util.rb'
+require 'as_search.rb'
+
+require 'namespace.rb'
+require 'addrdb.rb'
+
+#####################################################################
+# ユーザ定義例外
+class DnsNotImplementedError < StandardError ; end
+class DnsTruncatedError      < StandardError ; end
+class DnsNoQueryError        < StandardError ; end
+class DnsNoMoreResourceError < StandardError ; end
+
+class DnsNoErrorError < StandardError ; end
+
+Socket::do_not_reverse_lookup = true
+
+###################################################################
+# 関数
+
+# DNS パケットから質問内容と質問のタイプと質問のクラスを取り出す
+def parse_packet(packet)
+  (number, flags, num_q, ans_rr, ort_rr, add_rr, str) =  packet.unpack("a2 a2 a2 a2 a2 a2 a*")
+
+  if num_q != "\0\1"
+    ML.log("Q must be 1")
+    return [nil, nil, nil]
+  end
+
+  qlen = str.split("\0")[0].length + 1
+
+  (q, q_type, q_class) = str.unpack("a#{qlen} a2 a2")
+
+  return [q, q_type, q_class]
+end
+
+# クライアントの情報を返す
+def get_client_data(cli)
+  (family, port, fqdn, ipaddr) = cli
+  return {"family" => family, "port" => port, "fqdn" => fqdn, "addr" => ipaddr}
+end
+
+# クライアントのIPアドレスによって返答内容を変える事が出来る
+# 名前空間を選択。当てはまる物がなければ "default" になる
+def select_namespace(addrstr, name)
+
+  netaddrs = [addrstr] + ip_masklist(addrstr)
+
+  # custom namespace
+  netaddrs.each {
+    |i|
+    if $namespace_db[i]                  != nil &&
+	$addr_db[$namespace_db[i]]       != nil &&
+	$addr_db[$namespace_db[i]][name] != nil
+      return $namespace_db[i]
+    end
+  }
+
+  # address number namespace
+  netaddrs.each {
+    |i|
+    if $addr_db[i]        != nil &&
+	$addr_db[i][name] != nil
+      return i
+    end
+  }
+
+  # AS namespace
+  if OPT["as"] &&
+      # RFC1918 / プライベートアドレスはどこの AS にも属していない
+      ip_mask(addrstr,  8) != "10.0.0.0"      &&
+      ip_mask(addrstr, 12) != "172.16.0.0"    &&
+      ip_mask(addrstr, 16) != "192.168.0.0"   &&
+      ip_mask(addrstr, 21) != "204.152.184.0" &&
+      addrstr              != "127.0.0.1"
+
+    as = as_search(addrstr)
+    if as                  != nil &&
+	$addr_db[as]       != nil &&
+	$addr_db[as][name] != nil
+      return as
+    end
+  end
+
+  return "default"
+end
+
+# 重みつき変数のための表を作る
+def make_rand_array(namespace, name)
+  rnd_max = 0
+  rnd_slesh = []
+
+  $addr_db[namespace][name].each {
+    |i|
+    rnd_max += (10000 - min(10000, i[1])) # badness の最大値は 10000
+    rnd_slesh.push(rnd_max)
+  }
+
+  return [rnd_max, rnd_slesh]
+end
+
+# 重みつき乱数で選択
+def select_rand_array(namespace, name, size)
+  (rnd_max, rnd_slesh) = make_rand_array(namespace, name)
+
+  if rnd_max == 0  # 全てのホストの Badness が 10000 だった
+    return []
+  end
+
+  arr = []
+  (0...size).each {
+    |i|
+    rnd = rand(rnd_max)
+    (0...rnd_slesh.size).each {
+      |j|
+      if rnd <= rnd_slesh[j]
+	arr.push(j)
+	break
+      end
+    }
+  }
+
+  return arr
+end
+
+# パケットの正当性チェック
+def check_packet(q, q_type, q_class)
+  # ゾーン転送は無し
+  if q_type == DnsType::AXFR
+    ML.log("AXFR: " + q.dump + ":" + q_type.dump + ":" + q_class.dump)
+    raise DnsNotImplementedError
+  end
+
+  # IP(UDP) のみ受け付け
+  if !(q_class == DnsClass::INET || q_class == DnsClass::ANY)
+    ML.log("noIP: " + q.dump + ":" + q_type.dump + ":" + q_class.dump)
+    raise DnsNoQueryError
+  end
+
+  # 使用不可な文字がある
+  if (q =~ /[()<>@,;:\\\"\.\[\]]/) != nil
+    ML.log("char: " + q.dump + ":" + q_type.dump + ":" + q_class.dump)
+    raise DnsNoQueryError
+  end
+
+end
+
+def check_type(q, q_type, q_class, namespace)
+
+  # レコードは存在するがタイプが違う
+  if q_type != DnsType::A &&
+      q_type != DnsType::ANY &&
+      $addr_db[namespace] != nil &&
+      $addr_db[namespace][dnsstr_to_str(q).downcase] != nil
+    ML.log("noT: " + q.dump + ":" + q_type.dump + ":" + q_class.dump)
+    raise DnsNoErrorError
+  end
+
+  # A/ANY レコードのみ受け付け
+  if q_type != DnsType::A && q_type != DnsType::ANY
+    ML.log("noA: " + q.dump + ":" + q_type.dump + ":" + q_class.dump)
+    raise DnsNoQueryError
+  end
+end
+
+######################################################################
+# main
+
+srand()
+
+OPT = Hash::new
+OptionParser::new {
+  |opt|
+  opt.on("-i ADDR", String, "Listen IP address (default:0.0.0.0)") {
+    |o|
+    OPT["i"] = o;
+  }
+  opt.on("--as", "Enable AS namespace") {
+    OPT["as"] = true
+  }
+  opt.on_tail("-h", "--help", "Show this help message and exit") {
+    STDERR.printf("%s", opt.to_s)
+    exit(111)
+  }
+  opt.parse!
+}
+OPT.freeze
+
+ML = MultiLog::new
+ML.open
+
+ML.log("dir: " + PREFIX)
+ML.log("start")
+
+
+#
+# アドレスデータベースの動的更新
+#
+Thread::start {
+  loop {
+    if test(?r, PREFIX + "/addr") || test(?r, "./addr")
+      begin
+	load("addr")
+
+	ML.log("reload")
+      rescue NameError,SyntaxError,Exception
+	ML.log("reload failed")
+      end
+    end
+
+    #if test(?r, PREFIX + "/addr-once") || test(?r, "./addr-once")
+    #  Thread.exit
+    #end
+
+    #p $addr_db
+    sleep(2*60) # 5 分毎に更新
+  }
+}
+
+gs = UDPSocket::new()
+sockaddr = (if OPT["i"] == nil then Socket::INADDR_ANY else OPT["i"] end)
+gs.bind(sockaddr, Service::Domain)
+
+#
+# メインループ
+#
+loop {
+  (packet, client) = gs.recvfrom(1024)
+  Thread.start {
+    $SAFE = 2
+    begin
+      client_data = get_client_data(client)
+      (q, q_type, q_class) = parse_packet(packet)
+      check_packet(q, q_type, q_class) # -> NoQuery, NotImpl
+
+      name      = dnsstr_to_str(q).downcase
+      namespace = select_namespace(client_data["addr"], name)
+
+      check_type(q, q_type, q_class, namespace)
+
+      if $addr_db[namespace][name].size > 1  # -> NoMethodError -> NoQuery
+	size = 8
+      else
+	size = 1
+      end
+      a_array = select_rand_array(namespace, name, size) #.uniq
+
+      if a_array.size == 0
+	raise DnsNoMoreResourceError
+      end
+
+      # 返答生成
+      r = packet[0,12] + q + q_type + q_class
+      r[2] |= 0x84  # answer & authenticated
+      r[3] = 0      # no error
+
+      ans_addrs = []
+      a_array.each {
+	|i|
+	addr = $addr_db[namespace][name][i][0]
+	ans_addrs.push(addr)   # ログ出力用
+
+	# TTL 選択。近い所がある事が分かっているなら TTL を長くする
+	if (a_array.size == 1)
+	  ttl = "\0\0\x0e\x10" # 1時間
+	else
+	  ttl = "\0\0\0\x3c"   # 60秒
+	end
+
+	# 返答生成。 オフセットは 0x000c
+	r += "\xc0\x0c" + DnsType::A + DnsClass::INET + ttl + "\0\4" + addr.pack("CCCC")
+      }
+
+      # 返答の数をセット
+      r[6,2] = [a_array.size].pack("n")
+      r[8,4] = "\0\0\0\0"
+
+      # 長過ぎたら削る
+      if r.length > 512
+	raise DnsTruncatedError
+      end
+
+      status = "ok"
+
+    rescue DnsNotImplementedError
+      r = packet[0,12] + q + q_type + q_class
+      r[2] |= 0x80  # answer
+      r[2] &= ~0x04 # not authenticated
+      r[3] = 0
+      r[3] |= 0x04  # not implemented error
+      r[6,6] = "\0\0\0\0\0\0"
+      status = "NotImpl"
+
+    rescue DnsTruncatedError
+      # 長過ぎる時は削ってフラグを立てる
+      r = r[0,512]
+      r[2] |= 0x02
+      status = "Truncated"
+
+    rescue DnsNoErrorError
+      r = packet[0,12] + q + q_type + q_class
+      r[2] |= 0x84  # answer & authenticated
+      r[3] = 0      # no error
+
+      r[6,6] = "\0\0\0\0\0\0"
+
+      status = "NoError"
+
+    rescue DnsNoQueryError,DnsNoMoreResourceError,NoMethodError,StandardError
+      r = packet[0,12] + q + q_type + q_class
+      r[2] |= 0x84  # answer & authenticated
+      r[3] = 0
+      r[3] |= 0x03  # name error
+      r[6,6] = "\0\0\0\0\0\0"
+      status = "NoQuery"
+
+    rescue
+      # ここには来ないはず
+      r = packet[0,12] + q + q_type + q_class
+      r[2] |= 0x80  # answer
+      r[2] &= ~0x04 # not authenticated
+      r[3] = 0
+      r[3] |= 0x05  # query refused error
+      r[6,6] = "\0\0\0\0\0\0"
+      status = "other"
+    end
+
+    #print packet.dump, "\n"
+    #print r.dump, "\n"
+    #p q
+
+    gs.send(r, 0, client_data["addr"], client_data["port"])
+
+    logger(ML, client_data["addr"], status, name, namespace, ans_addrs)
+
+  }
+}
+
+# end

Added: cdn/log_writer.rb
===================================================================
--- cdn/log_writer.rb	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/log_writer.rb	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,33 @@
+#
+# DNS Balance
+#
+# ログ出力
+#
+# By: YOKOTA Hiroshi <yokota@xxxxxxxxxxxxxxxxxxxxxxx>
+
+# $Id: log_writer.rb,v 1.6 2003/06/13 22:05:38 elca Exp $
+
+require "util.rb"
+
+# ログ出力
+def logger(mutex, addr, status, name = "", namespace = "", answers = [])
+  out = sprintf("%s:%s:%s:%s",
+		addr,
+		status,
+		name,
+		namespace)
+
+  if answers == nil || answers == []
+    out += ":"
+  else
+    s = []
+    answers.each {
+      |i|
+      s.push(sprintf("%d.%d.%d.%d", i[0], i[1], i[2], i[3]))
+    }
+    out += sprintf(":%s", s.join(" "))
+  end
+  mutex.log(out)
+end
+
+# end

Added: cdn/multilog.rb
===================================================================
--- cdn/multilog.rb	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/multilog.rb	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,123 @@
+#
+# "syslog" like log interface for multilog
+#
+
+# $Id: multilog.rb,v 1.4 2002/10/05 16:29:57 elca Exp elca $
+
+=begin
+  multilog.rb - Syslog like log interface for DJB multilog
+=end
+
+require "thread"
+
+=begin
+MultiLog#open(port = $stdout)
+  Open log stream
+Multilog#log(string)
+  Put string to log stream
+Multilog#close
+  Close log stream
+=end
+
+class MultiLog
+
+  def initialize()
+    @loglock = nil
+    @outport = nil
+  end
+
+  def open(port = $stdout)
+    raise RuntimeError if @loglock != nil
+    raise RuntimeError if !port.is_a?(IO)
+
+    @loglock = Mutex.new()
+    @outport = port
+  end
+
+  def log(str)
+    raise RuntimeError if !opened?()
+
+    @loglock.synchronize do
+      @outport.print(str + "\n")
+      @outport.flush
+    end
+  end
+
+  def close()
+    @loglock = nil
+    @outport = nil
+  end
+
+  def opened?()
+    if @loglock != nil
+      return true
+    else
+      return false
+    end
+  end
+
+  def reopen(port = $stdout)
+    if opened?()
+      close()
+    end
+
+    open(port)
+  end
+
+  #
+  def panic(str)
+    log("panic: " + str)
+  end
+  def crit(str)
+    log("crit: " + str)
+  end
+  def info(str)
+    log("info: " + str)
+  end
+  def notice(str)
+    log("notice: " + str)
+  end
+
+  #
+  def nullcmd()
+  end
+  private :nullcmd
+
+  alias setmask nullcmd
+  alias open!   reopen
+
+end
+
+# m = MultiLog.new
+
+# m.open()
+# m.log("ok")
+# m.close
+# print("ok\n")
+
+# m.open($stderr)
+# m.log("ok")
+# m.close
+# print("ok\n")
+
+# fd = open("/tmp/mltest", "w")
+# m.open(fd)
+# m.log("ok")
+# m.close
+# fd.close
+
+# open("/tmp/mltest2", "w") {
+#   |fd|
+#   m.open(fd)
+#   m.log("ok")
+#   m.close
+# }
+
+# require "socket"
+# s = TCPSocket.new("localhost", 80)
+# m.open(s)
+# m.log("ok")
+# m.close
+# s.close
+
+# end

Added: cdn/namespace.rb
===================================================================
--- cdn/namespace.rb	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/namespace.rb	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,13 @@
+#
+# DNS Balance
+#
+# 別名データベース
+#
+# By: YOKOTA Hiroshi <yokota@xxxxxxxxxxxxxxxxxxxxxxx>
+
+# $Id: namespace.rb,v 1.2 2000/11/30 02:03:43 elca Exp $
+
+$namespace_db = {
+}
+
+# end

Added: cdn/sample/addr
===================================================================
--- cdn/sample/addr	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/sample/addr	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,29 @@
+
+$addr_db = {
+	"130.0.0.0/8" => {
+		"www.foo.com" => [
+			[[192,168,1,1], 1000],
+			[[192,168,1,2], 200],
+			[[192,168,1,3], 254],
+			[[192,168,1,4], 1],
+		],
+	},
+	"default" => {
+		"ftp.foo.com" => [
+			[[192,168,0,5], 200],
+			[[192,168,0,6], 1030],
+			[[192,168,0,7], 2250],
+			[[192,168,0,8], 10],
+		],
+		"localhost" => [
+			[[127,0,0,1], 0],
+		],
+		"www.foo.com" => [
+			[[192,168,0,1], 0],
+			[[192,168,0,2], 10],
+			[[192,168,0,3], 250],
+			[[192,168,0,4], 0],
+		],
+	},
+}
+

Added: cdn/sample/addr.ring
===================================================================
--- cdn/sample/addr.ring	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/sample/addr.ring	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,116 @@
+
+$addr_db = {
+	"default" => {
+		"core.ring.gr.jp" => [
+			[[150,29,9,6], 0],
+		],
+		"ftp.ring.gr.jp" => [
+			[[130,34,246,198], 0],
+			[[133,18,72,10], 2200],
+			[[133,243,3,209], 5800],
+			[[150,29,9,6], 0],
+			[[160,26,1,22], 1000],
+			[[192,50,77,195], 1700],
+			[[202,18,64,24], 3400],
+			[[202,224,39,15], 2200],
+			[[202,234,233,10], 1700],
+			[[202,245,159,10], 0],
+			[[210,132,247,108], 8100],
+			[[210,154,149,34], 700],
+			[[210,156,40,3], 0],
+			[[210,159,1,54], 1000],
+			[[210,161,150,21], 700],
+			[[210,162,2,10], 1000],
+			[[210,167,0,75], 2200],
+			[[210,167,6,130], 0],
+			[[210,235,130,17], 2200],
+			[[210,81,45,28], 0],
+		],
+		"openlab.ring.gr.jp" => [
+			[[150,29,9,5], 0],
+		],
+		"ring.aist.go.jp" => [
+			[[150,29,9,6], 0],
+		],
+		"ring.asahi-net.or.jp" => [
+			[[202,224,39,15], 0],
+		],
+		"ring.astem.or.jp" => [
+			[[133,18,72,10], 0],
+		],
+		"ring.crl.go.jp" => [
+			[[133,243,3,209], 0],
+		],
+		"ring.data-hotel.net" => [
+			[[210,81,45,28], 0],
+		],
+		"ring.edogawa-u.ac.jp" => [
+			[[210,235,130,17], 0],
+		],
+		"ring.etl.go.jp" => [
+			[[192,50,77,195], 0],
+		],
+		"ring.exp.fujixerox.co.jp" => [
+			[[210,154,149,34], 0],
+		],
+		"ring.htcn.ne.jp" => [
+			[[210,167,0,75], 0],
+		],
+		"ring.ip-kyoto.ad.jp" => [
+			[[202,245,159,10], 0],
+		],
+		"ring.iwate-pu.ac.jp" => [
+			[[210,156,40,3], 0],
+		],
+		"ring.jah.ne.jp" => [
+			[[210,162,2,10], 0],
+		],
+		"ring.jec.ad.jp" => [
+			[[210,161,150,21], 0],
+		],
+		"ring.ocn.ad.jp" => [
+			[[202,234,233,10], 0],
+		],
+		"ring.omp.ad.jp" => [
+			[[210,159,1,54], 0],
+		],
+		"ring.shibaura-it.ac.jp" => [
+			[[202,18,64,24], 0],
+		],
+		"ring.so-net.ne.jp" => [
+			[[210,132,247,108], 0],
+		],
+		"ring.tains.tohoku.ac.jp" => [
+			[[130,34,246,198], 0],
+		],
+		"ring.toyama-ix.net" => [
+			[[210,167,6,130], 0],
+		],
+		"ring.toyama-u.ac.jp" => [
+			[[160,26,1,22], 0],
+		],
+		"www.ring.gr.jp" => [
+			[[130,34,246,198], 0],
+			[[133,18,72,10], 2200],
+			[[133,243,3,209], 5800],
+			[[150,29,9,6], 0],
+			[[160,26,1,22], 1000],
+			[[192,50,77,195], 1700],
+			[[202,18,64,24], 3400],
+			[[202,224,39,15], 2200],
+			[[202,234,233,10], 1700],
+			[[202,245,159,10], 0],
+			[[210,132,247,108], 8100],
+			[[210,154,149,34], 700],
+			[[210,156,40,3], 0],
+			[[210,159,1,54], 1000],
+			[[210,161,150,21], 700],
+			[[210,162,2,10], 1000],
+			[[210,167,0,75], 2200],
+			[[210,167,6,130], 0],
+			[[210,235,130,17], 2200],
+			[[210,81,45,28], 0],
+		],
+	},
+}
+

Added: cdn/sample/addr.ring.txt
===================================================================
--- cdn/sample/addr.ring.txt	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/sample/addr.ring.txt	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,108 @@
+# ring.data-hotel.net 8d0b589ed3ed7466ce9ab7479bc0969c
+default,www.ring.gr.jp,210.81.45.28,10000
+default,ftp.ring.gr.jp,210.81.45.28,10000
+# ring.edogawa-u.ac.jp b3e87be0b7d8fd7abd160f78dcf82051
+default,www.ring.gr.jp,210.235.130.17,2200
+default,ftp.ring.gr.jp,210.235.130.17,2200
+# ring.jec.ad.jp 6e57d1300e96c5527599af35b823cde4
+default,www.ring.gr.jp,210.161.150.21,700
+default,ftp.ring.gr.jp,210.161.150.21,700
+# ring.toyama-u.ac.jp 075d7eb92a087ecd965b14ead6ad46d0
+default,www.ring.gr.jp,160.26.1.22,0
+default,ftp.ring.gr.jp,160.26.1.22,0
+# ring.tains.tohoku.ac.jp 075d7eb92a087ecd965b14ead6ad46d0
+default,www.ring.gr.jp,130.34.246.198,0
+default,ftp.ring.gr.jp,130.34.246.198,0
+# ring.etl.go.jp addace7a5a938cc5d417d502ea351894
+default,www.ring.gr.jp,192.50.77.195,1000
+default,ftp.ring.gr.jp,192.50.77.195,1000
+# ring.toyama-ix.net 075d7eb92a087ecd965b14ead6ad46d0
+default,www.ring.gr.jp,210.167.6.130,0
+default,ftp.ring.gr.jp,210.167.6.130,0
+# ring.htcn.ne.jp b24abb8540c3a3f930c97d1c48730683
+default,www.ring.gr.jp,210.167.0.75,1700
+default,ftp.ring.gr.jp,210.167.0.75,1700
+# ring.asahi-net.or.jp addace7a5a938cc5d417d502ea351894
+default,www.ring.gr.jp,202.224.39.15,1000
+default,ftp.ring.gr.jp,202.224.39.15,1000
+# core.ring.gr.jp 075d7eb92a087ecd965b14ead6ad46d0
+default,www.ring.gr.jp,150.29.9.6,0
+default,ftp.ring.gr.jp,150.29.9.6,0
+# ring.crl.go.jp aee8c28793e407b274304070f597fcea
+default,www.ring.gr.jp,133.243.3.209,3400
+default,ftp.ring.gr.jp,133.243.3.209,3400
+# ring.shibaura-it.ac.jp aee8c28793e407b274304070f597fcea
+default,www.ring.gr.jp,202.18.64.24,3400
+default,ftp.ring.gr.jp,202.18.64.24,3400
+# ring.ip-kyoto.ad.jp 075d7eb92a087ecd965b14ead6ad46d0
+default,www.ring.gr.jp,202.245.159.10,0
+default,ftp.ring.gr.jp,202.245.159.10,0
+# ring.omp.ad.jp 6e57d1300e96c5527599af35b823cde4
+default,www.ring.gr.jp,210.159.1.54,700
+default,ftp.ring.gr.jp,210.159.1.54,700
+# ring.ocn.ad.jp b3e87be0b7d8fd7abd160f78dcf82051
+default,www.ring.gr.jp,202.234.233.10,2200
+default,ftp.ring.gr.jp,202.234.233.10,2200
+# ring.iwate-pu.ac.jp 075d7eb92a087ecd965b14ead6ad46d0
+default,www.ring.gr.jp,210.156.40.3,0
+default,ftp.ring.gr.jp,210.156.40.3,0
+# ring.so-net.ne.jp 0f66ec5998ba979fcd1bf17e0b983e21
+default,www.ring.gr.jp,210.132.247.108,9500
+default,ftp.ring.gr.jp,210.132.247.108,9500
+# ring.exp.fujixerox.co.jp 075d7eb92a087ecd965b14ead6ad46d0
+default,www.ring.gr.jp,210.154.149.34,0
+default,ftp.ring.gr.jp,210.154.149.34,0
+# ring.jah.ne.jp b3e87be0b7d8fd7abd160f78dcf82051
+default,www.ring.gr.jp,210.162.2.10,2200
+default,ftp.ring.gr.jp,210.162.2.10,2200
+# ring.astem.or.jp b3e87be0b7d8fd7abd160f78dcf82051
+default,www.ring.gr.jp,133.18.72.10,2200
+default,ftp.ring.gr.jp,133.18.72.10,2200
+# ring.aist.go.jp 075d7eb92a087ecd965b14ead6ad46d0
+default,www.ring.gr.jp,150.29.9.6,0
+default,ftp.ring.gr.jp,150.29.9.6,0
+# ring.data-hotel.net
+default,ring.data-hotel.net,210.81.45.28,0
+# ring.edogawa-u.ac.jp
+default,ring.edogawa-u.ac.jp,210.235.130.17,0
+# ring.jec.ad.jp
+default,ring.jec.ad.jp,210.161.150.21,0
+# ring.toyama-u.ac.jp
+default,ring.toyama-u.ac.jp,160.26.1.22,0
+# ring.tains.tohoku.ac.jp
+default,ring.tains.tohoku.ac.jp,130.34.246.198,0
+# ring.etl.go.jp
+default,ring.etl.go.jp,192.50.77.195,0
+# ring.toyama-ix.net
+default,ring.toyama-ix.net,210.167.6.130,0
+# ring.htcn.ne.jp
+default,ring.htcn.ne.jp,210.167.0.75,0
+# ring.asahi-net.or.jp
+default,ring.asahi-net.or.jp,202.224.39.15,0
+# core.ring.gr.jp
+default,core.ring.gr.jp,150.29.9.6,0
+# ring.crl.go.jp
+default,ring.crl.go.jp,133.243.3.209,0
+# ring.shibaura-it.ac.jp
+default,ring.shibaura-it.ac.jp,202.18.64.24,0
+# ring.ip-kyoto.ad.jp
+default,ring.ip-kyoto.ad.jp,202.245.159.10,0
+# ring.omp.ad.jp
+default,ring.omp.ad.jp,210.159.1.54,0
+# ring.ocn.ad.jp
+default,ring.ocn.ad.jp,202.234.233.10,0
+# ring.iwate-pu.ac.jp
+default,ring.iwate-pu.ac.jp,210.156.40.3,0
+# ring.so-net.ne.jp
+default,ring.so-net.ne.jp,210.132.247.108,0
+# ring.exp.fujixerox.co.jp
+default,ring.exp.fujixerox.co.jp,210.154.149.34,0
+# ring.jah.ne.jp
+default,ring.jah.ne.jp,210.162.2.10,0
+# ring.astem.or.jp
+default,ring.astem.or.jp,133.18.72.10,0
+# ring.aist.go.jp
+default,ring.aist.go.jp,150.29.9.6,0
+# openlab
+default,openlab.ring.gr.jp,150.29.9.5,0
+#end

Added: cdn/sample/make_namespace.rb
===================================================================
--- cdn/sample/make_namespace.rb	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/sample/make_namespace.rb	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,35 @@
+#!/usr/local/bin/ruby
+#
+# CSV -> namespace ファイル変換
+#
+
+#
+# 内容は一行に <アドレス>,<別名> を書く
+#
+# Usage: sort < input.csv | uniq | make_namespace.rb > namespace.rb
+#
+# $Id: make_namespace.rb,v 1.2 2002/06/08 16:27:31 elca Exp $
+
+print <<"__EOM__"
+
+$namespace_db = {
+__EOM__
+
+
+while gets
+  if $_ =~ /^#/ || $_ =~ /^[ \t]*$/ # コメント
+    next
+  end
+
+  l = $_.chop.split(",")
+  #p l
+
+  print "\t\"", l[0], "\" => \"", l[1], "\",\n"
+
+end
+
+print <<"__EOM__"
+}
+__EOM__
+
+# end

Added: cdn/sample/makedb.rb
===================================================================
--- cdn/sample/makedb.rb	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/sample/makedb.rb	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,65 @@
+#!/usr/local/bin/ruby
+#
+# CSV -> addr ファイル変換
+#
+# By: YOKOTA Hiroshi <yokota@xxxxxxxxxxxxxxxxxxxxxxx>
+
+#
+# 入力内容は sort されている事
+# 内容は一行に <振り分けタグ>,<ホスト名>,<IPアドレス>,<Badness> を書く
+#
+# Usage: sort < input.csv | uniq | makedb.rb > addr
+#
+
+# $Id: makedb.rb,v 1.7 2002/06/08 16:27:31 elca Exp $
+
+print <<"__EOM__"
+
+$addr_db = {
+__EOM__
+
+
+l0 = ""
+l1 = ""
+l2 = ""
+l3 = ""
+
+while gets
+  if $_ =~ /^#/ # コメント
+    next
+  end
+
+  l = $_.chop.split(",")
+
+  if (l1 != l[1] && l1 != "") || (l0 != l[0] && l0 != "")
+    print "\t\t],\n"
+  end
+  if l0 != l[0] && l0 != ""
+    print "\t},\n"
+  end
+
+  if l0 != l[0]
+    print "\t\"", l[0], "\" => {\n"
+  end
+  if l1 != l[1] || l0 != l[0]
+    print "\t\t\"", l[1], "\" => [\n"
+  end
+  if l2 != l[2] || l1 != l[1] || l0 != l[0]
+    print "\t\t\t[[", l[2].tr(".",","), "], ", l[3], "],\n"
+  end
+
+
+  l0 = l[0]
+  l1 = l[1]
+  l2 = l[2]
+  l3 = l[3]
+end
+
+print <<"__EOM__"
+\t\t],
+\t},
+}
+
+__EOM__
+
+# end

Added: cdn/sample/makeringdb.rb
===================================================================
--- cdn/sample/makeringdb.rb	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/sample/makeringdb.rb	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,86 @@
+#
+# RING Server 向け addr ファイル作成スクリプト
+#
+
+# usage:
+#   ruby makeringdb.rb | sort | uniq | ruby makedb.rb > addr
+
+require 'md5'
+
+servers = {
+  "core.ring.gr.jp" => "150.29.9.6", # -> aist
+  "ring.etl.go.jp"  => "192.50.77.195",
+  "ring.aist.go.jp" => "150.29.9.6",
+  "ring.asahi-net.or.jp" => "202.224.39.15",
+  "ring.crl.go.jp" => "133.243.3.209",
+  "ring.astem.or.jp" => "133.18.72.10",
+  "ring.jah.ne.jp" => "210.162.2.10",
+  "ring.exp.fujixerox.co.jp" => "210.154.149.34",
+  "ring.so-net.ne.jp" => "210.132.247.108",
+  "ring.ip-kyoto.ad.jp" => "202.245.159.10",
+  "ring.iwate-pu.ac.jp" => "210.156.40.3",
+  "ring.shibaura-it.ac.jp" => "202.18.64.24",
+  "ring.ocn.ad.jp" => "202.234.233.10",
+  "ring.htcn.ne.jp" => "210.167.0.75",
+  "ring.omp.ad.jp" => "210.159.1.54",
+  "ring.jec.ad.jp" => "210.161.150.21",
+  "ring.tains.tohoku.ac.jp" => "130.34.246.198",
+  "ring.toyama-ix.net" => "210.167.6.130",
+  "ring.toyama-u.ac.jp" => "160.26.1.22",
+  "ring.edogawa-u.ac.jp" => "210.235.130.17",
+  "ring.data-hotel.net" => "210.81.45.28",
+  "ring.yamanashi.ac.jp" => "133.23.250.240"
+}
+
+for i in servers.keys
+#  if i == "core.ring.gr.jp"  # -> aist
+#    next
+#  end
+
+  md5 = MD5.new(`lynx -source http://core.ring.gr.jp/ring/#{i}.gif`)
+  digest = md5.hexdigest
+
+  case digest
+  when "075d7eb92a087ecd965b14ead6ad46d0"
+    badness = 0
+  when "6e57d1300e96c5527599af35b823cde4"
+    badness = 700
+  when "addace7a5a938cc5d417d502ea351894"
+    badness = 1000
+  when "b24abb8540c3a3f930c97d1c48730683"
+    badness = 1700
+  when "b3e87be0b7d8fd7abd160f78dcf82051"
+    badness = 2200
+  when "aee8c28793e407b274304070f597fcea"
+    badness = 3400
+  when "9eadd49cb2e8814030b115299aff0fff"
+    badness = 5800
+  when "f15789c3897e2eaf08ebf5dd048f9702"
+    badness = 6900
+  when "4796929e047f2984872a9b8b7f4ad933"
+    badness = 8100
+  when "0f66ec5998ba979fcd1bf17e0b983e21"
+    badness = 9500
+  when "8d0b589ed3ed7466ce9ab7479bc0969c"
+    badness = 10000      # server down
+  else
+    badness = 10000
+    print "# other\n"
+  end
+
+  print "# #{i} #{digest}\n"
+  print "default,www.ring.gr.jp,#{servers[i]},#{badness}\n"
+  print "default,ftp.ring.gr.jp,#{servers[i]},#{badness}\n"
+end
+
+for i in servers.keys
+  print "# #{i}\n"
+  print "default,#{i},#{servers[i]},0\n"
+end
+
+print "# openlab\n"
+print "default,openlab.ring.gr.jp,150.29.9.5,0\n"
+
+print "#end\n"
+
+# end

Added: cdn/sample/namespace.rb
===================================================================
--- cdn/sample/namespace.rb	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/sample/namespace.rb	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,7 @@
+
+$namespace_db = {
+	"192.168.0.0/24" => "foo-net",
+	"192.168.65.0/28" => "foo-65-net",
+	"130.23.0.0/16" => "bar-domain",
+	"127.0.0.0/8" => "localnet",
+}

Added: cdn/sample/namespace.txt
===================================================================
--- cdn/sample/namespace.txt	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/sample/namespace.txt	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,7 @@
+#
+# This is sample namespace file.
+#
+192.168.0.0/24,foo-net
+192.168.65.0/28,foo-65-net
+130.23.0.0/16,bar-domain
+127.0.0.0/8,localnet

Added: cdn/sample/ringupdate.sh
===================================================================
--- cdn/sample/ringupdate.sh	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/sample/ringupdate.sh	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,34 @@
+#! /bin/bash
+#
+# 一定時間毎に RingServer の addr ファイルを作り続ける
+# その際更新情報のログも残す
+
+N=$$
+h=999
+
+while true
+do
+    #echo -n "update:"
+
+    next_h=`date '+%S'`
+    now=`date '+%s'`
+
+    perl get_httpd_stat > out.db-${now}
+    cat out.db-${now} | sort | uniq | ruby makedb.rb > addr.tmp.${N}
+
+    # 1時間に1回ログを取る
+    if [ $h != $next_h ]
+    then
+	cp -p out.db-${now} out/
+	gzip -9 out/out.db-${now}
+    fi
+
+    h=$next_h
+
+    mv addr.tmp.${N} addr
+    rm out.db-${now}
+
+    sleep 300
+done
+
+# end


Property changes on: cdn/sample/ringupdate.sh
___________________________________________________________________
Name: svn:executable
   + 

Added: cdn/util.rb
===================================================================
--- cdn/util.rb	2007-02-27 11:00:40 UTC (rev 186)
+++ cdn/util.rb	2007-02-27 11:00:52 UTC (rev 187)
@@ -0,0 +1,176 @@
+#
+# DNS Balance
+#
+# 雑用
+#
+# By: YOKOTA Hiroshi <yokota@xxxxxxxxxxxxxxxxxxxxxxx>
+
+# $Id: util.rb,v 1.7 2003/06/13 22:05:38 elca Exp $
+
+# DNS パケット中の RR 名を人間に読みやすい形式に変換
+def dnsstr_to_str(dnsstr)
+  arr = []
+  c = 0
+
+  while TRUE
+    break if dnsstr.size <= c
+    break if dnsstr[c] == 0
+
+    arr.push(dnsstr[c+1, dnsstr[c]])
+    c += dnsstr[c]+1
+  end
+
+  return arr.join(".")
+end
+
+def str_to_dnsstr(str)
+  return str.split(".").collect {
+    |i|
+    sz = min(i.size, 63) # less than 63 chars for each domain
+
+    sz.chr + i[0,sz]
+  }.join("") + "\0"
+end
+
+# 文字列を DNS TXT RR にする
+def str_to_dnstxt(str)
+  return str_split(str,127).collect {|i| i.size.chr + i}.join("")
+end
+
+# IP アドレス表記からそれに見合った4バイトの文字列を生成
+#
+# ex) "127.0.0.1" => "\x7f\x0\x0\x1"
+def str_to_ipstr(str)
+  return str.split(".").collect{|i| i.to_i}.pack("C4")
+end
+
+def ipstr_to_str(ipstr)
+  return ipstr.unpack("C4").join(".")
+end
+
+def ipstr_array_to_str(arr)
+  return arr.collect{|i| ipstr_to_str(i)}.join(" ")
+end
+
+def str_to_ip6str(str)
+  tmp = str.split("::")
+
+  laddr = raddr = []
+
+  if tmp[0] != nil
+    laddr = tmp[0].split(":").collect{|i| i.hex}
+  end
+
+  if tmp[1] != nil
+    raddr = tmp[1].split(":").collect{|i| i.hex}
+  end
+
+  addr6 = laddr + ([0] * (8 - (laddr.size + raddr.size))) + raddr
+
+  return addr6.pack("n8")
+end
+
+def ip6str_to_str(str)
+  return str.unpack("H4" * 8).join(":") #.gsub(/:0?0?0?/, ":")
+end
+    
+
+# 文字列を指定文字数で区切る
+def str_split(str, num)
+  a = Array.new
+  (0...((str.length + num - 1)/num).to_i).each {
+    |i|
+    a << str[i * num, num]
+  }
+  return a
+end
+
+# ipstr に対してビットマスクをかける
+def ipstr_mask(ipstr, mask)
+  n = ipstr.unpack("N")[0] & (0xffffffff << (32 - mask))
+  return [n].pack("N")
+end
+
+#
+def ip_mask(str, mask)
+  ipstr = str_to_ipstr(str)
+  ans   = ipstr_mask(ipstr, mask)
+  return ipstr_to_str(ans)
+end
+
+# IP アドレスの /32 から /1 までのマスクをかけたアドレスのリストを返す
+def ip_masklist(str)
+
+  netaddrs = []
+  (0..31).each {
+    |i|
+    mask = 32-i
+
+    netaddrs << (ip_mask(str, mask) + "/" + mask.to_s)
+  }
+
+  return netaddrs
+end
+
+def domain_makelist(name)
+  n = name.split(".")
+  ret = []
+
+  (0...(n.size)).each {
+    |i|
+    ret << n[i...(n.size)].join(".")
+  }
+
+  return ret
+end
+
+# add "unique" flag to dns class
+def unique_add(str)
+  tmp = str.dup
+  tmp[0] |= 0x80
+  return tmp
+end
+
+def unique_drop(str)
+  tmp = str.dup
+  tmp[0] &= 0x7f
+  return tmp
+end
+
+
+#
+def min(a, b)
+  return (if a < b then a else b end)
+end
+
+def max(a, b)
+  return (if a < b then b else a end)
+end
+
+# 配列をランダムに並べ変える
+def array_randomize(arr)
+  return []  if arr.size == 0
+  return arr if arr.size == 1
+
+  h = Hash.new
+  (0...arr.size).each {
+    |i|
+    p = rand()
+    h[p] = i
+  }
+
+  tmp = Array.new
+  h.sort.each {
+    |i|
+    tmp << i[1]
+  }
+
+  ret = tmp.collect {
+    |i|
+    arr[i]
+  }
+
+  return ret
+end
+
+# end