ClojureでMagicPacket送信ツールを作ってみた
Clojureで書くとこんな感じかな。
(ns #^{:author "otabat", :doc "Magic packet sender"} masquerade (:gen-class)) (import '(java.net InetSocketAddress DatagramPacket DatagramSocket)) (use '[clojure.contrib.str-utils :only (re-split)]) (def default-port 2304) (def buf-length 102) (defn send-magic-packet "Send magic packet to specified host" [ip port mac-byte] (let [mac-byte-array (into-array (Byte/TYPE) mac-byte) sock (DatagramSocket.) host-addr (InetSocketAddress. ip port) packet (DatagramPacket. mac-byte-array buf-length host-addr)] (.setBroadcast sock true) (.send sock packet))) (defn repeat-seq [n buf] (loop [res '() i n] (if (zero? i) res (recur (concat res buf) (dec i))))) (defn string-hex-to-byte-digit [mac] (for [x (re-split #":" mac)] (byte (Integer/parseInt x 16)))) (defn is-port "Determine whether it is a valid port number." [port] (and (>= port 0) (<= port 65535))) (defn is-mac "Determine whether it is a valid mac address." [mac] (let [patn "^((([a-fA-F0-9]){2}):){5}([a-fA-F0-9]){2}$"] (and (= mac (first (re-find (re-pattern patn) mac)))))) (defn is-ip "Determine whether it is a valid ip address." [ip] (let [p "(\\d|[01]?\\d\\d|2[0-4]\\d|25[0-5])" patn (str "^" p "\\." p "\\." p "\\." p "$")] (and (= ip (first (re-find (re-pattern patn) ip)))))) (defn -main [ip mac port] (let [port (Integer/parseInt port) buf (repeat 6 (byte 0xff))] (when-not (and (is-ip ip) (is-mac mac) (is-port port)) (println "Invalid input.") (System/exit 0)) (let [mac-byte (string-hex-to-byte-digit mac) buf (concat buf (repeat-seq 16 mac-byte))] (send-magic-packet ip port buf))))
ついでにビルド方法も。
Leiningen使ってる人は以下のようにやればOK。
$ lein compile [null] Compiling masquerade $ lein uberjar All :namespaces already compiled. Created /プロジェクトのパス/masquerade.jar Including masquerade.jar Including clojure-1.1.0-master-20091231.150150-10.jar Including clojure-contrib-1.1.0-master-20100114.180141-21.jar
最後に起動方法。
$ java -jar masquerade-standalone.jar xxx.xxx.xxx.xxx MM:MM:MM:MM:MM:MM 2304