odhcp6-script.fnl (2746B)
1 (local { : split : merge : hash : base64url } (require :anoia)) 2 (local { : mktree : rmtree } (require :anoia.fs)) 3 4 (local state-directory (assert (os.getenv "SERVICE_STATE"))) 5 (mktree state-directory) 6 7 (fn write-value [name value] 8 (let [path (.. state-directory "/" name)] 9 (with-open [fout (io.open path :w)] 10 (when value (fout:write value))))) 11 12 (fn write-value-from-env [name] 13 (write-value name (os.getenv (string.upper name)))) 14 15 (fn parse-address [str] 16 (fn parse-extra [s] 17 (let [out {}] 18 (each [name val (string.gmatch s ",(.-)=([^,]+)")] 19 (tset out name val)) 20 out)) 21 (let [(address len preferred valid extra) 22 (string.match str "(.-)/(%d+),(%d+),(%d+)(.*)$")] 23 (merge {: address : len 24 :preferred (or preferred "forever") 25 :valid (or valid "forever") 26 } 27 (parse-extra extra)))) 28 29 (fn write-addresses [prefix addresses] 30 (each [_ a (ipairs (split " " addresses))] 31 (let [address (parse-address a) 32 suffix (base64url (string.pack "n" (hash a))) 33 keydir (.. 34 prefix 35 (-> address.address 36 (: :gsub "::$" "") 37 (: :gsub ":" "-")))] 38 (mktree (.. state-directory "/" keydir)) 39 (each [k v (pairs address)] 40 (write-value (.. keydir "/" k) v))))) 41 42 ;; we remove state before updating to ensure that consumers don't get 43 ;; a half-updated snapshot 44 (os.remove (.. state-directory "/state")) 45 46 ;; remove parsed addresses/prefixes from any previous run 47 (rmtree (.. state-directory "/prefix")) 48 (rmtree (.. state-directory "/address")) 49 50 (let [wanted 51 [ 52 :addresses 53 :aftr 54 :cer 55 :domains 56 :lw406 57 :mape 58 :mapt 59 :ntp_fqdn 60 :ntp_ip 61 :option_1 62 :option_2 63 :option_3 64 :option_4 65 :option_5 66 :passthru 67 :prefixes 68 :ra_addresses 69 :ra_dns 70 :ra_domains 71 :ra_hoplimit 72 :ra_mtu 73 :ra_reachable 74 :ra_retransmit 75 :ra_routes 76 :rdnss 77 :server 78 :sip_domain 79 :sip_ip 80 :sntp_ip 81 :sntp_fqdn 82 ]] 83 (each [_ n (ipairs wanted)] 84 (write-value-from-env n)) 85 86 (match (os.getenv :ADDRESSES) s (write-addresses "address/" s)) 87 (match (os.getenv :PREFIXES) s (write-addresses "prefix/" s))) 88 89 (let [[ifname state] arg 90 ready (match state 91 "started" false 92 "unbound" false 93 "stopped" false 94 _ true)] 95 (write-value ".lock" (tostring (os.time))) 96 (write-value "ifname" ifname) 97 (write-value "state" state) 98 (os.remove (.. state-directory "/.lock")) 99 (when ready 100 (with-open [fd (io.open "/proc/self/fd/10" :w)] (fd:write "\n"))))