Added the timezoned daemon "code" (ugly hack alert)

pull/55/merge
Rop 6 years ago
parent 83c7fbfe0b
commit 570fe50fb2

@ -0,0 +1,17 @@
# timezoned - The Timezone Daemon
This is a brutally ugly hack that serves timezone information via UDP port 2342. To use it, try the following on a unix machine with PHP installed:
* Create a user called 'timezoned'
* Copy the 'update' and 'server' scripts to this user's homedir, and change the #! line at the beginning of the server script to point to the PHP binary on the system
* Log in or su to the timezoned user, make the 'update' script executable and run it.
* Make the 'server' script executable and run it. (Make sure the server accepts packets on 2342 UDP.)
* Test by running `nc -u <ip or domain name> 2342` on some other system and then typing a zone (like "Europe/London") followed by Ctrl-D. You should get the POSIX information for that zone.
* If that works, you may (on a FreeBSD machine) use the 'timezoned' script by placing it in /usr/local/etc/rc.d to start the server automatically. On other systems, you'll have to figure out how to start it automatically when the server reboots.
* Run update script and then restart the server periodically to stay up on timezone updates.

@ -0,0 +1,161 @@
#!/usr/local/bin/php
<?php
//Reduce errors
// error_reporting(0);
$tz = array();
// Read posixinfo
if ($file = fopen("/home/timezoned/posixinfo", "r")) {
while(!feof($file)) {
$line = fgets($file);
preg_match("/^(.*?) (.*?)$/", $line, $matches);
if ($matches[1] != "" && $matches[2] != "") {
array_push($tz, array("olsen" => trim($matches[1]), "posix" => trim($matches[2])));
}
}
fclose($file);
}
// Read zone1970.tab
if ($file = fopen("/home/timezoneddownload/zone1970.tab", "r")) {
while(!feof($file)) {
$line = fgets($file);
if ($line[0] != "#") {
$columns = explode("\t", $line);
if (count($columns) >= 3) {
$countries = explode(",", $columns[0]);
for ($n = 0; $n < count($countries); $n++) {
$country = trim($countries[$n]);
$insert_at = -1;
$posix = "";
for ($m = 0; $m < count($tz); $m++) {
if (trim($tz[$m]["olsen"]) == trim($columns[2])) {
$posix = $tz[$m]["posix"];
if (!isset($tz[$m]["country"])) {
$insert_at = $m;
}
}
}
if ($insert_at == -1) {
$insert_at = count($tz);
array_push($tz, array());
}
$tz[$insert_at]["country"] = $countries[$n];
$tz[$insert_at]["coordinates"] = $columns[1];
$tz[$insert_at]["olsen"] = trim($columns[2]);
if ($posix != "") $tz[$insert_at]["posix"] = $posix;
if (isset ($columns[3])) $tz[$insert_at]["comments"] = $columns[3];
}
}
}
}
}
echo "Data read \n";
//Create a UDP socket
if(!($sock = socket_create(AF_INET, SOCK_DGRAM, 0)))
{
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Couldn't create socket: [$errorcode] $errormsg\n");
}
echo "Socket created \n";
// Bind the source address
if( !socket_bind($sock, "0.0.0.0" , 2342) )
{
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Could not bind socket : [$errorcode] $errormsg\n");
}
echo "Socket bind OK \n";
$last_ask = array();
//Process packets. This loop can handle multiple clients
while(1)
{
//Receive packet
$r = socket_recvfrom($sock, $packet, 512, 0, $remote_ip, $remote_port);
// dDoS/flood protection
if (isset($last_ask[$remote_ip]) && $last_ask[$remote_ip] > time() - 3) continue;
$last_ask[$remote_ip] = time();
$parts = explode("#", $packet, 2);
$query = $parts[0];
$version = $parts[1];
$process = strtoupper(str_replace(" ", "_", $query));
$logstart = date("D, d M Y H:i:s") . "Z -- $remote_ip:$remote_port --";
// GeoIP ?
if ($process == "GEOIP") {
if (preg_match("/: ([A-Z][A-Z]),/", exec("geoiplookup " . $remote_ip), $matches)) {
$process = $matches[1];
} else {
echo "$logstart ERR GeoIP Lookup Failed\n";
socket_sendto($sock, "ERROR GeoIP Lookup Failed", 100 , 0 , $remote_ip , $remote_port);
continue;
}
}
if ($process == "UK") $process = "GB";
if ($process == "DE") $process = "EUROPE/BERLIN";
// If a two-letter country-code was provided
if (preg_match('/^[A-Z][A-Z]$/', $process)) {
// Convert to name of timezone if the country happens to have only one timezone
$num_matches = 0;
for ($m = 0; $m < count($tz); $m++) {
if ($tz[$m]["country"] == $process) {
$num_matches++;
$posix = $tz[$m]["posix"];
$olsen = $tz[$m]["olsen"];
}
}
switch ($num_matches) {
case 0:
echo "$logstart ERR COUNTRY NOT FOUND: $query\n";
socket_sendto($sock, "ERROR Country Not Found", 100 , 0 , $remote_ip , $remote_port);
break;
case 1:
echo "$logstart OK $query -> $olsen $posix\n";
socket_sendto($sock, "OK " . $olsen . " " . $posix , 100 , 0 , $remote_ip , $remote_port);
break;
default:
echo "$logstart ERR MULTIPLE TIMEZONES: $query\n";
socket_sendto($sock, "ERROR Country Spans Multiple Timezones", 100 , 0 , $remote_ip , $remote_port);
break;
//
}
} else {
$num_matches = 0;
for ($m = 0; $m < count($tz); $m++) {
if (strpos(strtoupper($tz[$m]["olsen"]), $process) !== false) {
$num_matches++;
$posix = $tz[$m]["posix"];
$olsen = $tz[$m]["olsen"];
echo "$logstart OK $query -> $olsen $posix\n";
socket_sendto($sock, "OK " . $olsen . " " . $posix , 100 , 0 , $remote_ip , $remote_port);
break;
}
}
if (!$num_matches) {
echo "$logstart ERR TIMEZONE NOT FOUND: $query\n";
socket_sendto($sock, "ERROR Timezone Not Found", 100 , 0 , $remote_ip , $remote_port);
}
}
}
socket_close($sock);

@ -0,0 +1,22 @@
#!/bin/sh
# PROVIDE: timezoned
# REQUIRE: LOGIN cleanvar sshd
. /etc/rc.subr
name=timezoned
rcvar=timezoned_enable
: ${timezoned_enable="NO"}
: ${timezoned_pidfile="/var/run/timezoned/timezoned.pid"}
: ${timezoned_user="timezoned"}
: ${timezoned_group="timezoned"}
command="/usr/sbin/daemon"
command_interpreter="/usr/local/bin/php"
command_args="-c -f -r -P ${timezoned_pidfile} -r /home/timezoned/server"
load_rc_config $name
run_rc_command "$1"

@ -0,0 +1,26 @@
#!/bin/sh
rm -rf ~timezoned/download
mkdir ~timezoned/download
rm -rf ~timezoned/zoneinfo
mkdir ~timezoned/zoneinfo
cd ~timezoned/download
wget ftp://ftp.iana.org/tz/tzdata-latest.tar.gz
tar zxvf tzdata-latest.tar.gz
rm tzdata-latest.tar.gz
for i in `ls`; do zic -d ~timezoned/zoneinfo $i;done
rm ~timezoned/posixinfo
cd ~timezoned/zoneinfo
for i in `find *|grep /`
do
if [ -f $i ]; then
echo -n $i >> ~timezoned/posixinfo
echo -n " " >> ~timezoned/posixinfo
tail -1 $i >> ~timezoned/posixinfo
fi
done
Loading…
Cancel
Save