Alternc  latest
Alternc logiel libre pour l'hébergement
 All Classes Namespaces Files Functions Variables Pages
m_upnp.php
Go to the documentation of this file.
1 <?php
2 /*
3  ----------------------------------------------------------------------
4  AlternC - Web Hosting System
5  Copyright (C) 2000-2012 by the AlternC Development Team.
6  https://alternc.org/
7  ----------------------------------------------------------------------
8  LICENSE
9 
10  This program is free software; you can redistribute it and/or
11  modify it under the terms of the GNU General Public License (GPL)
12  as published by the Free Software Foundation; either version 2
13  of the License, or (at your option) any later version.
14 
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU General Public License for more details.
19 
20  To read the license please visit http://www.gnu.org/copyleft/gpl.html
21  ----------------------------------------------------------------------
22  Purpose of file: Manage UPnP ports forwarding from router
23  ----------------------------------------------------------------------
24 */
25 
26 /**
27 * This class handle UPnP forwarding from a IGD/UPnP compliant router
28 * you need this only when you are behind a IGD-compliant router
29 * each class may exports a hook that defined named port/protocol to
30 * forward to the local IP address of the server.
31 * this class manage the upnp table
32 * and its configuration from admin control panel
33 */
34 class m_upnp {
35 
36 
37  /* ----------------------------------------------------------------- */
38  /** get the list of current upnp forwards and their status
39  * @return array the attributes of all port-forwards
40  */
41  function get_forward_list() {
42  global $db,$err;
43  $err->log("upnp","get_forward_list");
44  $db->query("SELECT * FROM upnp");
45  $res=array();
46  while ($db->next_record()) {
47  $res[]=$db->Record;
48  }
49  return $res;
50  }
51 
52 
53  /* ----------------------------------------------------------------- */
54  /** enable a upnp port in the upnp table
55  * @param integer the id of the port to enable
56  * @return boolean TRUE if the port has been properly forwarded
57  * FALSE if an error occurred
58  */
59  function enable_port($id) {
60  global $db,$err;
61  $id=intval($id);
62  $err->log("upnp","enable_port($id)");
63  $db->query("SELECT enabled FROM upnp WHERE id=$id;");
64  if (!$db->next_record()) {
65  $err->raise("upnp",_("The required port is not currently defined"));
66  return false;
67  }
68  if (!$db->f("enabled")) {
69  $db->query("UPDATE upnp SET enabled=1 WHERE id=$id;");
70  $err->raise("upnp",_("The specified upnp port is now enabled"));
71  return true;
72  }
73  $err->raise("upnp",_("The specified upnp port is already enabled"));
74  return true;
75  }
76 
77 
78  /* ----------------------------------------------------------------- */
79  /** disable a upnp port in the upnp table
80  * @param integer the id of the port to disable
81  * @return boolean TRUE if the port has been properly forwarded
82  * FALSE if an error occurred
83  */
84  function disable_port($id) {
85  global $db,$err;
86  $id=intval($id);
87  $err->log("upnp","disable_port($id)");
88  $db->query("SELECT enabled,mandatory FROM upnp WHERE id=$id;");
89  if (!$db->next_record()) {
90  $err->raise("upnp",_("The required port is not currently defined"));
91  return false;
92  }
93  if ($db->f("mandatory")) {
94  $err->raise("upnp",_("You can't disable that mandatory port forward"));
95  return false;
96  }
97  if ($db->f("enabled")) {
98  $db->query("UPDATE upnp SET enabled=0 WHERE id=$id;");
99  $err->raise("upnp",_("The specified upnp port is now disabled"));
100  return true;
101  }
102  $err->raise("upnp",_("The specified upnp port is already disabled"));
103  return true;
104  }
105 
106 
107  /* ----------------------------------------------------------------- */
108  /** cron launched every minute to check the status of UPnP forwarding
109  */
110  function cron() {
111  global $hooks,$db,$L_INTERNAL_IP,$PUBLIC_IP;
112  // if we check anything less than 5 minutes ago, or if the upnp table is empty, let's make a check...
113  $db->query("SELECT UNIX_TIMESTAMP(lastcheck) AS lc, * FROM upnp ORDER BY lastcheck ASC;");
114  $forwards=array();
115  $bigcheck=false;
116  if (!$db->next_record()) {
117  $bigcheck=true;
118  } else {
119  if ($db->f("lc")+600<time()) {
120  $bigcheck=true;
121  }
122  do {
123  $db->Record["found"]=false;
124  $forwards[]=$db->Record;
125  } while ($db->next_record());
126  }
127 
128  if ($bigcheck) {
129  // Do the check first by calling the hooks & comparing the arrays
130  $res=$hooks->invoke("hooks_upnp_list");
131  foreach($res as $c=>$tmp) {
132  if (is_array($tmp) && count($tmp)) {
133  foreach($tmp as $name=>$v) {
134 
135  // We compare the hook array with the forwards array
136  $found=false;
137  for($i=0;$i<count($forwards);$i++) {
138  if ($forwards[$i]["class"]==$c &&
139  $forwards[$i]["name"]==$name &&
140  $forwards[$i]["protocol"]==$v["protocol"] &&
141  $forwards[$i]["port"]==$v["port"] &&
142  $forwards[$i]["mandatory"]==$v["mandatory"]) {
143  // Found it and unchanged
144  $forwards[$i]["found"]=true;
145  $found=true;
146  }
147  } // compare with forwards class.
148  if (!$found) {
149  // Mark it for creation
150  $db->query("INSERT INTO upnp SET mandatory='".addslashes($v["mandatory"])."', protocol='".addslashes($v["protocol"])."', port='".addslashes($v["port"])."', name='".addslashes($name)."', action='CREATE'");
151  $id=$db->last_id();
152  $forwards[]=array("id"=>$id, "mandatory" => intval($v["mandatory"]), "protocol" => $v["protocol"], "port" => intval($v["port"]), "name" => $name, "action" => "CREATE");
153  }
154  } // for each port forward in that class
155  }
156  } // for each hooked class
157  // Now We search the "not found" and remove them from the array
158  for($i=0;$i<count($forwards);$i++) {
159  if (!$forwards[$i]["found"]) {
160  $forwards[$i]["action"]="DELETING";
161  $db->query("UPDATE upnp SET action='DELETING' WHERE id=".$forwards[$i]["id"].";");
162  }
163  }
164 
165  } // bigcheck ?
166 
167  // Ask for the current upnp status of forwarded ports
168  $status=array(); $statusout=array(); $bad=false;
169  unset($out);
170  exec("upnpc -l 2>&1",$res,$out);
171  if ( is_array($out) && !empty($out)) {
172  foreach($out as $line) {
173  // example line: 1 TCP 222->192.168.0.5:22 'libminiupnpc' ''
174  if (preg_match("#^ *([0-9]+) (TCP|UDP) *([0-9]+)\->([0-9\.]+):([0-9]+) *#",$line,$mat)) {
175  if ($mat[4]==$L_INTERNAL_IP) {
176  $status[]=array("protocol" => $mat[2], "port" => $mat[3]);
177  } else {
178  $statusout[]=array("protocol" => $mat[2], "port" => $mat[3], "ip" => $mat[4]);
179  }
180  }
181  if (preg_match("#No IGD UPnP Device found on the network#",$line)) {
182  $bad=true;
183  }
184  } // For each line in upnpc -l (check list)
185  }
186 
187  // No UPnP peripheral !! maybe you should not have installed AlternC-upnp altogether ?
188  if ($bad) {
189  foreach($forwards as $f) {
190  if ($f["action"]!="OK") {
191  $db->query("UPDATE upnp SET lastupdate=NOW(), lastcheck=NOW(), result='No UPnP device detected in your network !' WHERE id=".$f["id"].";");
192  } else {
193  $db->query("UPDATE upnp SET lastupdate=NOW(), lastcheck=NOW(), WHERE id=".$f["id"].";");
194  }
195  }
196  return;
197  }
198 
199  // Now, for each forward, we either
200  // * check it (via upnpc -l parsing)
201  // * add it (via upnpc -a)
202  // * remove it (via upnpc -d)
203  foreach($forwards as $f) {
204  switch ($f["action"]) {
205  case "OK": // check
206  $found=false;
207  foreach($status as $s) {
208  if ($s["port"]==$f["port"] && $s["protocol"]==$s["protocol"]) {
209  $found=true;
210  $db->query("UPDATE upnp SET lastcheck=NOW() WHERE id=".$f["id"].";");
211  }
212  }
213  if (!$found) {
214  // Search this protocol+port in the OTHER list ... if found, tell it ...
215  }
216  break;
217  case "CREATE":
218  break;
219  case "DELETE":
220  case "DELETING":
221  break;
222  case "DISABLE":
223  break;
224  case "ENABLE":
225  break;
226  }
227  }
228 
229 
230  } // CRON function
231 
232 
233 
234 
235 
236 
237 } /* Class UPnP */
238 
$hooks
Definition: bootstrap.php:74
$found
Definition: aws_del.php:29
disable_port($id)
disable a upnp port in the upnp table
Definition: m_upnp.php:84
get_forward_list()
get the list of current upnp forwards and their status
Definition: m_upnp.php:41
global $db
Definition: bootstrap.php:22
$i
$err
Definition: bootstrap.php:72
This class handle UPnP forwarding from a IGD/UPnP compliant router you need this only when you are be...
Definition: m_upnp.php:34
$res
Definition: index.php:123
cron()
cron launched every minute to check the status of UPnP forwarding
Definition: m_upnp.php:110
enable_port($id)
enable a upnp port in the upnp table
Definition: m_upnp.php:59
$c
Definition: bootstrap.php:47
if(!isset($is_include)) if(!$key &&!$crt) $id