kann sockets nicht verwenden

Status
Für weitere Antworten geschlossen.

steffen

Benutzer
Mitglied seit
29. Mai 2008
Beiträge
9
Punkte für Reaktionen
0
Punkte
0
Hallo

ich hab jetzt schon ein paar stunden nach dem Fehler gegooglet aber leider nix hilfreiches gefunden.

Mein Problem ist folgendes:
Ich möchte mit der DiskStation (106J) via PHP meine Rechner anpingen um zu sehen, welcher Rechner an ist. Dazu benutze ich fogendes Skript, was ich im Netz gefunden hab.
PHP:
<?php

class Net_Ping
{
  var $icmp_socket;
  var $request;
  var $request_len;
  var $reply;
  var $errstr;
  var $time;
  var $timer_start_time;
  function Net_Ping()
  {
    $this->icmp_socket = socket_create(AF_INET, SOCK_RAW, 1) 
		or die("Unable to create socket\n");
    socket_set_block($this->icmp_socket);
		//or die("Unable to set block on socket\n");
  }
 
  function ip_checksum($data)
  {
     for($i=0;$i<strlen($data);$i += 2)
     {
         if($data[$i+1]) $bits = unpack('n*',$data[$i].$data[$i+1]);
         else $bits = unpack('C*',$data[$i]);
         $sum += $bits[1];
     }
    
     while ($sum>>16) $sum = ($sum & 0xffff) + ($sum >> 16);
     $checksum = pack('n1',~$sum);
     return $checksum;
  }

  function start_time()
  {
    $this->timer_start_time = microtime();
  }
 
  function get_time($acc=2)
  {
    // format start time
    $start_time = explode (" ", $this->timer_start_time);
    $start_time = $start_time[1] + $start_time[0];
    // get and format end time
    $end_time = explode (" ", microtime());
    $end_time = $end_time[1] + $end_time[0];
    return number_format ($end_time - $start_time, $acc);
  }

  function Build_Packet()
  {
    $data = "abcdefghijklmnopqrstuvwabcdefghi"; // the actual test data
    $type = "\x08"; // 8 echo message; 0 echo reply message
    $code = "\x00"; // always 0 for this program
    $chksm = "\x00\x00"; // generate checksum for icmp request
    $id = "\x00\x00"; // we will have to work with this later
    $sqn = "\x00\x00"; // we will have to work with this later

    // now we need to change the checksum to the real checksum
    $chksm = $this->ip_checksum($type.$code.$chksm.$id.$sqn.$data);

    // now lets build the actual icmp packet
    $this->request = $type.$code.$chksm.$id.$sqn.$data;
    $this->request_len = strlen($this->request);
  }
 
  function Ping($dst_addr,$timeout=5,$percision=3)
  {
    // lets catch dumb people
    if ((int)$timeout <= 0) $timeout=5;
    if ((int)$percision <= 0) $percision=3;
   
    // set the timeout
    socket_set_option($this->icmp_socket,
      SOL_SOCKET,  // socket level
      SO_RCVTIMEO, // timeout option
      array(
       "sec"=>$timeout, // Timeout in seconds
       "usec"=>0  // I assume timeout in microseconds
       )
      );

    if ($dst_addr)
    {
      if (@socket_connect($this->icmp_socket, $dst_addr, NULL))
      {
     
      } else {
        $this->errstr = "Cannot connect to $dst_addr";
        return FALSE;
      }
      $this->Build_Packet();
      $this->start_time();
      socket_write($this->icmp_socket, $this->request, $this->request_len);
      if (@socket_recv($this->icmp_socket, &$this->reply, 256, 0))
      {
        $this->time = $this->get_time($percision);
        return $this->time;
      } else {
        $this->errstr = "Timed out";
        return FALSE;
      }
    } else {
      $this->errstr = "Destination address not specified";
      return FALSE;
    }
  }
}

$ping = new Net_Ping;
$ping->ping("www.google.de");

if ($ping->time)
  echo "Time: ".$ping->time;
else
  echo $ping->errstr;

?>

Mittels xampp auf meinem Windowsrechner geht das auch, aber wenn ich das auf der DiskStation ausführe bekomme ich immer folgenden Fehler:
Rich (BBCode):
Warning: socket_create() [function.socket-create]: Unable to create socket [1]: Operation not permitted in /volume1/web/src/ping.php on line 14

Kann mir einer bei dem Problem weiterhelfen?
 

itari

Benutzer
Mitglied seit
15. Mai 2008
Beiträge
21.900
Punkte für Reaktionen
14
Punkte
0
hi steffen,

schau dir einfach mal im PHP-Handbuch unter socket-create die Beispiele in der Diskussion an. Da steht, dass man unter Unix der User root sein muss für den Aufruf, den du vor hast. Das braucht man unter Windows nicht. Dein Code geht also wie folgt:

if(posix_seteuid(0)) $socket = socket_create(AF_INET, SOCK_RAW, 1);

Und das funktioniert bei mir ohne Fehler...
 

steffen

Benutzer
Mitglied seit
29. Mai 2008
Beiträge
9
Punkte für Reaktionen
0
Punkte
0
Danke für die Antwort. Ich hab leider vergessen in meinem Post zu erwähnen, das ich schon rausgefunden hab, das es wahrescheinlich an den Rechten liegt, mit denen das PHP ausgeführt. :eek:

Dein code hat mir dahingehen weiter geholfen, dass ich keinen Fehler mehr bekomme. Dennoch besteht noch das Problem, dass ich nicht heraus bekomme, ob die Rechner an sind. Kann mir jemand sagen, wie ich PHP als root ausführen kann, damit ich die socket-funktionalität verwenden kann?
 

itari

Benutzer
Mitglied seit
15. Mai 2008
Beiträge
21.900
Punkte für Reaktionen
14
Punkte
0
lies doch bitte mal die Code-Zeile genau:

das Skripte erhält durch den Funktionsaufruf posix_seteuid(0) die 'effektiven Rechte des Benutzers 0', das ist der root-Benutzer. Das heisst, Dein Skripte hat nach dem Aufruf bereits die richtigen Rechte ... was bedeutet, Du fährst bereits mit maximalen Rechten ...

Ob Dein Skript nu die anderen Recher erwischen kann, vermag ich nicht zu sagen, aber das SOCKET-Problem ist gelöst.

Lies doch noch mal im PHP-Handbuch weiter ... es scheint so als müsste noch die Datei /etc/protocols mit entsprechenden Einträgen versehen werden ...
 

steffen

Benutzer
Mitglied seit
29. Mai 2008
Beiträge
9
Punkte für Reaktionen
0
Punkte
0
ich hab mir schon den code genau angeschaut, aber wenn die Funktion die Rechte nicht setzten kann (gibt mir false zurück), dann komme ich dennoch nicht weiter.

btw. Kann mir nicht so recht vorstellen, was da in die /etc/protocols rein kommen soll. Hast du da einen Tipp?
 

itari

Benutzer
Mitglied seit
15. Mai 2008
Beiträge
21.900
Punkte für Reaktionen
14
Punkte
0
sorry,

bei mir geht der posix_seteuid(0) auch nicht ... bin dem Wegfall der Fehlermeldung aufgesessen.

Dem Apache kann man in der Konfigurationsdatei des Apache: httpd.conf mitteilen, unter welchem User man arbeiten möchte. Da müsste man dann eintragen:

User root

Ist aber nicht wirklich zu empfehlen, da man alle Türen ganz weit aufmacht. :(
 

itari

Benutzer
Mitglied seit
15. Mai 2008
Beiträge
21.900
Punkte für Reaktionen
14
Punkte
0
hi,

hab noch was gefunden, weiß aber nicht, ob das in deinem Skript funktioniert, aber es erstellt eine Socket:

$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);

Jemand hat damit das wake-up von PCs realisiert, schau mal hier http://www.nas-forum.com/forum/index.php?showtopic=1875
 

steffen

Benutzer
Mitglied seit
29. Mai 2008
Beiträge
9
Punkte für Reaktionen
0
Punkte
0
Danke für den Tip, aber es geht mit diesem Socket auch nicht ohne root rechte. Generell benötigt man bei dem Socktetyp 'SOCK_RAW' root-rechte. Aber eben nur dieser macht es möglich, dass man einen Rechner im Netzwerk anpingen kann.

Ich habe jetzt den Apache als root laufen üder den Eintrag 'user root' in der httpd.conf, auch wenn das möglicher weiße Tore auf macht...

Den link mit dem WakeOnLan hab ich auch gleich noch mit umgesetzt, danke! :)

Jetzt funktioniert erstmal alles. Ich wäre aber dennoch für Lösungen offen, bei denen ich nicht den apache als root laufen lassen müsst.
 
Status
Für weitere Antworten geschlossen.
 

Kaffeautomat

Wenn du das Forum hilfreich findest oder uns unterstützen möchtest, dann gib uns doch einfach einen Kaffee aus.

Als Dankeschön schalten wir deinen Account werbefrei.

:coffee:

Hier gehts zum Kaffeeautomat