getAllByProp('uuid',$uuid); if (count($hosts)>0) { return array_pop($hosts); } else { return false; } } function getClientFromIP($ip=false) { global $hosts_db; $hosts = $hosts_db->getAllByProp('IpAddress',$ip); if (count($hosts)>0) { return array_pop($hosts); } else { return false; } } function getClientMac($ip=false) { if (false === $ip) { $ip = $_SERVER['REMOTE_ADDR']; } $result = pingHost($ip,1); if (!$result) return false; $macAddr=false; $arptable=`arp -n $ip`; $lines=explode("\n", $arptable); foreach($lines as $line) { $cols=preg_split('/\s+/', trim($line)); if ($cols[0]==$ip) { return $cols[2]; } } return false; } function pingHost($host, $timeout=1) { $pingresult = exec("/bin/ping -c 1 -t 2 -W $timeout $host", $output, $retvar); return (0 == $retvar); } function filtered_json() { global $_filtered_json; if (is_null($_filtered_json)) { $ok_elements = array('client_uuid','server_uuid','last_config','hostname'); $data = json_decode(file_get_contents('php://input'), true); $_filtered_json = array_intersect_key($data,array_flip($ok_elements)); } return $_filtered_json; } function my_uuid() { global $config_db; $uuid = $config_db->getProp(CONFIG_KEY,'uuid'); if (empty($uuid)) { $uuid=trim(shell_exec('/usr/bin/uuidgen')); $config_db->setProp(CONFIG_KEY,array('uuid'=>$uuid)); } return $uuid; } function find_free_ipaddress() { global $hosts_db, $dhcp_db; $ip = ip2long($ip_str); if ( ! $ip_str_start = $dhcp_db->getProp('lan0','DhcpRangeStart') ) { return false; } if ( ! $ip_str_end = $dhcp_db->getProp('lan0','DhcpRangeEnd') ) { return false; } $ip_start = ip2long($ip_str_start)+1; $ip_end = ip2long($ip_str_end); while($ip_start <= $ip_end){ $hosts = $hosts_db->getAllByProp('IpAddress',long2ip($ip_start)); if (count($hosts)==0) { return long2ip($ip_start); } $start_ip++; } return false; } function ROUTE_POST_ping() { global $config_db, $hosts_db; $data = filtered_json(); $server_uuid=my_uuid(); $out=array(); $domainName = (string)$config_db->getKeyValue('DomainName'); if (!isset($data['server_uuid'])) { # client is unmanaged, let's fix that $systemName = (string)$config_db->getKeyValue('SystemName'); $TCPPort = $config_db->getProp(CONFIG_KEY,'TCPPort'); $out['ping_url']="http://$systemName.$domainName:$TCPPort/ping"; $out['server_uuid']=$server_uuid; } elseif ($data['server_uuid'] != $server_uuid) { # this client belongs to someone else, let's ignore it echo json_encode(array('error'=>'you\'re devoted to another master')); exit; } if (!isset($data['client_uuid'])) { # client hasn't sent its uuid. This is not allowed (client uuid is always generated client-side) echo json_encode(array('error'=>'missing client uuid')); exit; } $client_ip = $_SERVER['REMOTE_ADDR']; $client = false; if (! $client = getClientFromUUID($data['client_uuid'])) { # client uuid not registered, let's search for IP $mac = getClientMac(); if ($client = getClientFromIP($client_ip)) { # we have one if (isset($client['uuid'])) { # with a registered UUID, that we know to be different from ours # so it's an IP collision. # we investigate: if ($mac == $client['MacAddress']) { # the macaddress is the same, but we have different uuid echo json_encode(array('error'=>'uuid mismatch')); exit; } elseif (!$mac) { # we don't have any macaddress info (maybe because we're on # different networks, so no arp) echo json_encode(array('error'=>'can\'t add host because no macaddress')); exit; } else { # we have a macadrress different from the one we have # registered for this IP address, so it's a real IP collision # and we add a new host reservation if (! $new_ip = find_free_ipaddress()) { echo json_encode(array('error'=>'no more free ip addresses')); exit; } $props = array( 'Description' => '', 'IpAddress' => $new_ip, 'MacAddress' => $mac, 'uuid' => $data['client_uuid'] ); if (!$hosts_db->setKey($data['hostname'], 'local', $props)) { echo json_encode(array('error'=>'can\'t add new host')); exit; } $client = getClientFromUUID($data['client_uuid']); } } else { # the configured client doen't have the uuid # so we update it $props = array( 'uuid' => $data['client_uuid'] ); if (!$hosts_db->setProp($client['name'], $props)) { echo json_encode(array('error'=>'can\'t update host')); exit; } $client['uuid'] = $data['client_uuid']; } } else { # no client registered with this uuid or this IP if ($mac) { # we have a client mac address, # we can register a new host if (isset($data['hostname'])) { $props = array( 'Description' => '', 'IpAddress' => $client_ip, 'MacAddress' => $mac, 'uuid' => $data['client_uuid'] ); if (!$hosts_db->setKey($data['hostname'], 'local', $props)) { echo json_encode(array('error'=>'can\'t add host')); exit; } $client = getClientFromUUID($data['client_uuid']); } else { echo json_encode(array('error'=>'missing client hostname')); exit; } } else { # we don't have a mac address (maybe a different network) # we can't register a new host echo json_encode(array('error'=>'missing client mac address')); exit; } } } $hosts_db->setProp($client['name'],array('LastSeen' => time())); if (isset($data['last_config'])) { $hosts_db->setProp($client['name'],array('LastConfig' => $data['last_config'])); $current_config = $config_db->getProp(CONFIG_KEY,'lastConfig'); if ($data['last_config'] != $current_config ) { exec('/usr/bin/sudo /sbin/e-smith/signal-event client-reconfigure ' . $client['name'] . ' > /dev/null &'); } } $out['hostname']=$client['name']; $out['domainname']=$domainName; $out['ipaddress']=$client['IpAddress']; $out['server_uuid']=$server_uuid; echo json_encode($out); }