#!/bin/sh
<? /* vi: set sw=4 ts=4: */
include "/htdocs/phplib/trace.php";
include "/htdocs/phplib/xnode.php";
include "/htdocs/phplib/phyinf.php";
function cmd($cmd) {echo $cmd."\n";}
function msg($msg) {cmd("echo [DHCP6C]: ".$msg." > /dev/console");}
/*****************************************/
function add_each($list, $path, $node)
{
//echo "# add_each(".$list.",".$path.",".$node.")\n";
$i = 0;
$cnt = scut_count($list, "");
while ($i < $cnt)
{
$val = scut($list, $i, "");
if ($val!="") add($path."/".$node, $val);
$i++;
}
return $cnt;
}
/*****************************************/
function handle_stateful($inf, $devnam, $opt)
{
$stsp = XNODE_getpathbytarget("/runtime", "inf", "uid", $inf, 0);
if ($stsp=="" || $devnam=="") return;
/* Preparing ... */
//$conf = "/proc/sys/net/ipv6/conf/".$devnam;
$conf = "/var/run/".$devnam;
$child = query($stsp."/child/uid");
$childgz = query($stsp."/childgz/uid");
/* Strip the tailing spaces. */
$DNS = strip($_GLOBALS["DNS"]);
$NAMESERVERS = strip($_GLOBALS["NAMESERVERS"]);
$DOMAIN = strip($_GLOBALS["DOMAIN"]);
$NEW_ADDR = strip($_GLOBALS["NEW_ADDR"]);
$NEW_PD_PREFIX = strip($_GLOBALS["NEW_PD_PREFIX"]);
$NEW_PD_PLEN = strip($_GLOBALS["NEW_PD_PLEN"]);
$NEW_AFTR_NAME = strip($_GLOBALS["NEW_AFTR_NAME"]);
$NEW_PD_PLFT = strip($_GLOBALS["NEW_PD_PLTIME"]);
$NEW_PD_VLFT = strip($_GLOBALS["NEW_PD_VLTIME"]);
if($DOMAIN!="")
{
XNODE_set_var($child."_DOMAIN", $DOMAIN);
XNODE_set_var($childgz."_DOMAIN", $DOMAIN);
}
XNODE_set_var($child."_PDPLFT", $NEW_PD_PLFT);
XNODE_set_var($child."_PDVLFT", $NEW_PD_VLFT);
XNODE_set_var($childgz."_PDPLFT", $NEW_PD_PLFT);
XNODE_set_var($childgz."_PDVLFT", $NEW_PD_VLFT);
/* Combine the user config and DHCP server setting. */
$dns = $DNS;
/* get primary dns and secondary dns */
$pdns = '';
$sdns = '';
$dns_cnt = scut_count($dns, "");
if($dns_cnt!=0)
{
$pdns = scut($dns, 0, "");
$sdns = scut($dns, 1, "");
}
$nameserver = '';
if($NAMESERVERS!="")
{
$i=0;
$cnt = scut_count($NAMESERVERS, "");
while($i<$cnt)
{
$val = scut($NAMESERVERS, $i, "");
if($val==$pdns || $val==$sdns)
{
msg("Got the same dns server as dns manual setting");
}
else
{
if($nameserver=="") $nameserver = $val;
else $nameserver = $nameserver." ".$val;
}
$i++;
}
$NAMESERVERS = $nameserver;
}
$oflag = fread("e", $conf.".ra_oflag");
//if($oflag=="1") // for M flag = 1, O flag = 0 case
//{
if ($NAMESERVERS!="")
{
if ($dns=="") $dns = $NAMESERVERS;
else $dns = $dns." ".$NAMESERVERS;
}
//}
/* Get RA info. */
if ($_GLOBALS["MODE"]!="PPPDHCP")
{
$prefix = fread("e", $conf.".ra_prefix");
$pfxlen = fread("e", $conf.".ra_prefix_len");
$router = fread("e", $conf.".ra_saddr");
//if ($router=="" || $router=="NULL") {msg("no ra_saddr"); return;}/*TR-124 issue 2 */
//if ($prefix=="" || $prefix=="NULL") {msg("no ra_prefix"); return;}
//if ($pfxlen==0) {msg("no ra_prefix_len"); return;}
}
/* Check renew, do nothing if we got the same prefix and prefix len as previous ones */
$ip = query($stsp."/inet/ipv6/ipaddr");
$pfl = query($stsp."/inet/ipv6/prefix");
$childip = query($stsp."/child/ipaddr");
$childpfl = query($stsp."/child/prefix");
if($opt=="IA-NA+IA-PD")
{
if ($NEW_ADDR!="" && $NEW_PD_PREFIX=="" && $NEW_PD_PLEN== "") { $renew=1; $renewip=1; msg("STATEFUL - opt: ".$opt." RENEW IANA...");}
if ($NEW_ADDR=="" && $NEW_PD_PREFIX!="" && $NEW_PD_PLEN!= "") { $renew=1; $renewip=0; msg("STATEFUL - opt: ".$opt." RENEW IAPD...");}
}
if($opt=="IA-NA")
{
if ($NEW_ADDR!="" && $NEW_PD_PREFIX=="" && $NEW_PD_PLEN== "") { $renew=1sg("STATEFUL - opt: ".$opt." RENEW IANA...");}
}
if ($opt=="IA-PD")
{
if ($child!="")
{
$mac = PHYINF_getphymac($child);
$hostid = ipv6eui64($mac);
if($NEW_PD_PLEN < 64)
{
$slalen = 64-$NEW_PD_PLEN;
$ipaddr = ipv6ip($NEW_PD_PREFIX, $NEW_PD_PLEN, $hostid, 1, $slalen);
$cpfxlen = 64;
}
else
{
$slalen = 1;
$ipaddr = ipv6ip($NEW_PD_PREFIX, $NEW_PD_PLEN, $hostid, 1, 1);
$cpfxlen = $NEW_PD_PLEN+1;
}
if($childip == $ipaddr && $childpfl == $NEW_PD_PLEN+1) {msg("STATEFUL - Renew but do nothing"); return;}
msg("PREFIX=".$NEW_PD_PREFIX.", PLEN=".$NEW_PD_PLEN.", HOSTID=".$hostid.", SLA=1, SLALEN=".$slalen);
msg("IPADDR=".$ipaddr);
set($stsp."/child/ipaddr", $ipaddr);
set($stsp."/child/prefix", $cpfxlen);
set($stsp."/child/pdnetwork", $NEW_PD_PREFIX);
set($stsp."/child/pdprefix", $NEW_PD_PLEN);
set($stsp."/child/pdplft", $NEW_PD_PLFT);
set($stsp."/child/pdvlft", $NEW_PD_VLFT);
}
if ($childgz!="")
{
$mac = PHYINF_getphymac($childgz);
$hostid = ipv6eui64($mac);
if($NEW_PD_PLEN < 64)
{
$slalen = 64-$NEW_PD_PLEN;
$ipaddr = ipv6ip($NEW_PD_PREFIX, $NEW_PD_PLEN, $hostid, 0, $slalen);
$cpfxlen = 64;
}
else
{
$slalen = 1;
$ipaddr = ipv6ip($NEW_PD_PREFIX, $NEW_PD_PLEN, $hostid, 2, 1);
$cpfxlen = $NEW_PD_PLEN+1;
}
if($childip == $ipaddr && $childpfl == $NEW_PD_PLEN+1) {msg("STATEFUL - Renew but do nothing"); return;}
msg("PREFIX=".$NEW_PD_PREFIX.", PLEN=".$NEW_PD_PLEN.", HOSTID=".$hostid.", SLA=1, SLALEN=".$slalen);
msg("IPADDR=".$ipaddr);
set($stsp."/childgz/ipaddr", $ipaddr);
set($stsp."/childgz/prefix", $cpfxlen);
set($stsp."/childgz/pdnetwork", $NEW_PD_PREFIX);
set($stsp."/childgz/pdprefix", $NEW_PD_PLEN);
set($stsp."/childgz/pdplft", $NEW_PD_PLFT);
set($stsp."/childgz/pdvlft", $NEW_PD_VLFT);
}
$ipaddr = ipv6ip($NEW_PD_PREFIX, $NEW_PD_PLEN, 1, 0, 0);
$pfxlen = $NEW_PD_PLEN;
if($ip == $ipaddr && $pfl == $NEW_PD_PLEN) {msg("STATEFUL - opt: ".$opt." Renew but do nothing"); return;}
}
else
{
if ($child!="" && strstr($opt,"IA-PD")!="")
{
$mac = PHYINF_getphymac($child);
$hostid = ipv6eui64($mac);
if($NEW_PD_PLEN<)
{
/* handle blackhole issue */
//cmd("ip -6 route add blackhole ".$NEW_PD_PREFIX."/".$NEW_PD_PLEN." dev lo");
//set($stsp."/blackhole/prefix", $NEW_PD_PREFIX);
//set($stsp."/blackhole/plen", $NEW_PD_PLEN);
$holecnt = query($stsp."/blackhole/count");
if($holecnt=="")
{
$holecnt = 1;
set($stsp."/blackhole/count", $holecnt);
set($stsp."/blackhole/entry:".$holecnt."/prefix", $NEW_PD_PREFIX);
set($stsp."/blackhole/entry:".$holecnt."/plen", $NEW_PD_PLEN);
cmd("ip -6 route add blackhole ".$NEW_PD_PREFIX."/".$NEW_PD_PLEN." dev lo");
}
$ipaddr = ipv6ip($NEW_PD_PREFIX, $NEW_PD_PLEN, $hostid, 1,64-$NEW_PD_PLEN);
$cpfxlen = 64;
}
else
{
$ipaddr = ipv6ip($NEW_PD_PREFIX, $NEW_PD_PLEN, $hostid, 0,0);
$cpfxlen = $NEW_PD_PLEN;
}
if($renew==1 && $childip==$ipaddr && $childpfl==$cpfxlen){msg("STATEFUL - opt: ".$opt." Renew but do nothing"); return;}
if($renew==1 && $NEW_PD_PREFIX!="" && $NEW_PD_PLEN!="")
{
//renew and get the different prefix
$holecnt = $holecnt + 1;
set($stsp."/blackhole/entry:".$holecnt."/prefix", $NEW_PD_PREFIX);
set($stsp."/blackhole/entry:".$holecnt."/plen", $NEW_PD_PLEN);
set($stsp."/blackhole/count", $holecnt);
cmd("ip -6 route add blackhole ".$NEW_PD_PREFIX."/".$NEW_PD_PLEN." dev lo");
}
if($ipaddr!="")/* check if renew IANA, $NEW_PD_PREFIX and $NEW_PD_PLEN are zero */
{
set($stsp."/child/ipaddr", $ipaddr);
set($stsp."/child/prefix", $cpfxlen);
set($stsp."/child/pdnetwork", $NEW_PD_PREFIX);
set($stsp."/child/pdprefix", $NEW_PD_PLEN);
set($stsp."/child/pdplft", $NEW_PD_PLFT);
set($stsp."/child/pdvlft", $NEW_PD_VLFT);
}
}
if ($childgz!="" && strstr($opt,"IA-PD")!="")
{
$mac = PHYINF_getphymac($childgz);
$hostid = ipv6eui64($mac);
if($NEW_PD_PLEN<)
{
$ipaddr = ipv6ip($NEW_PD_PREFIX, $NEW_PD_PLEN, $hostid, 0,64-$NEW_PD_PLEN);
$cpfxlen = 64;
}
else
{
//If pd length is bigger than 63, don't set to guest zone
$ipaddr = "";
$cpfxlen = "";
}
if($ipaddr!="")/* check if renew IANA, $NEW_PD_PREFIX and $NEW_PD_PLEN are zero */
{
set($stsp."/childgz/ipaddr", $ipaddr);
set($stsp."/childgz/prefix", $cpfxlen);
set($stsp."/childgz/pdnetwork", $NEW_PD_PREFIX);
set($stsp."/childgz/pdprefix", $NEW_PD_PLEN);
set($stsp."/childgz/pdplft", $NEW_PD_PLFT);
set($stsp."/childgz/pdvlft", $NEW_PD_VLFT);
}
}
if (strstr($opt,"IA-NA")=="") {msg("no IA-NA"); return;}
if($renew==1 && $renewip==1 && $ip==$NEW_ADDR){msg("STATEFUL - opt: ".$opt." Renew but do nothing"); return;}
if ($NEW_ADDR=="" && $renewip==1) {msg("no NEW_ADDR"); return;}
$ipaddr = $NEW_ADDR;
$pfxlen = 128;
}
set($stsp."/inet/ipv6/dhcpopt", $opt);
/* DS-Lite info */
$remote = strip($_GLOBALS["NEW_AFTR_NAME"]);
if($remote!="")
set($stsp."/inet/ipv4/ipv4in6/remote", $remote);
/* domain info */
if($DOMAIN!="")
{
set($stsp."/inet/ipv6/domain",$DOMAIN);
}
cmd("phpsh /etc/scripts/IPV6.INET.php ACTION=ATTACH".
" INF=".$_GLOBALS["INF"].
" MODE=".$_GLOBALS["MODE"].
" DEVNAM=".$devnam.
" IPADDR=".$ipaddr.
" PREFIX=".$pfxlen.
" GATEWAY=".$router.
' "DNS='.$dns.'"');
return;
}
function handle_stateless($inf, $prefix, $pfxlen)
{
$stsp = XNODE_getpathbytarget("/runtime", "inf", "uid", $inf, 0);
if ($stsp=="") {msg("STATLESS - no runtime for ".$inf); return;}
if ($prefix=="" || $pfxlen=="") {msg("STATELESS - no prefix"); return;}
/* Prepare child. */
msg("STATELESS - Got prefix ".$prefix."/".$pfxlen);
$child = query($stsp."/child/uid");
$mac = PHYINF_getphymac($child);
$hostid = ipv6eui64($mac);
if($pfxlen < 64)
{
/* handle blackhole issue */
//cmd("ip -6 route add blackhole ".$prefix."/".$pfxlen." dev lo");
//set($stsp."/blackhole/prefix", $prefix);
//set($stsp."/blackhole/plen", $pfxlen);
$holecnt = query($stsp."/blackhole/count");
if($holecnt=="")
{
$holecnt = 1;
set($stsp."/blackhole/entry:".$holecnt."/prefix", $prefix);
set($stsp."/blackhole/entry:".$holecnt."/plen", $pfxlen);
set($stsp."/blackhole/count", $holecnt);
cmd("ip -6 route add blackhole ".$prefix."/".$pfxlen." dev lo");
}
$slalen = 64-$pfxlen;
$ipaddr = ipv6ip($prefix, $pfxlen, $hostid, 1, $slalen);
$pfxlen = 64;
}
else
{
$ipaddr = ipv6ip($prefix, $pfxlen, $hostid,0,0);
}
/* Check renew, do nothing if we got the same prefix and prefix len as previous ones */
$oldip = query($stsp."/child/ipaddr");
$oldpfl = query($stsp."/child/prefix");
if($oldip == $ipaddr && $oldpfl == $pfxlen) {msg("STATELESS - Renew but do nothing"); return;}
set($stsp."/child/ipaddr", $ipaddr);
set($stsp."/child/prefix", $pfxlen);
set($stsp."/child/pdnetwork", strip($_GLOBALS["NEW_PD_PREFIX"]));
set($stsp."/child/pdprefix", strip($_GLOBALS["NEW_PD_PLEN"]));
set($stsp."/child/pdplft", strip($_GLOBALS["NEW_PD_PLTIME"]));
set($stsp."/child/pdvlft", strip($_GLOBALS["NEW_PD_VLTIME"]));
$DOMAIN = strip($_GLOBALS["DOMAIN"]);
if($DOMAIN!="")
XNODE_set_var($child."_DOMAIN", $DOMAIN);
XNODE_set_var($child."_PDPLFT", strip($_GLOBALS["NEW_PD_PLTIME"]));
XNODE_set_var($child."_PDVLFT", strip($_GLOBALS["NEW_PD_VLTIME"]));
msg("STATELESS - Child ".$ipaddr."/".$pfxlen);
$DNS = strip($_GLOBALS["DNS"]);
$NAMESERVERS = strip($_GLOBALS["NAMESERVERS"]);
/* Combine the user config and DHCP server setting. */
$dns = $DNS;
/*
if ($NAMESERVERS!="")
{
if ($dns=="") $dns = $NAMESERVERS;
else $dns = $dns." ".$NAMESERVERS;
}
*/
$infprev = query($stsp."/infprevious");
if($infprev!="")
{
$stsprevp = XNODE_getpathbytarget("/runtime", "inf", "uid", $infprev, 0);
$pdevnam = query($stsprevp."/devnam");
$conf = "/var/run/".$pdevnam;
}
else
$conf = "/var/run/".query($stsp."/devnam");
//$oflag = fread("e", $conf.".ra_oflag");
//if($oflag=="1")
//{
if ($NAMESERVERS!="")
{
if ($dns=="") $dns = $NAMESERVERS;
else $dns = $dns." ".$NAMESERVERS;
}
//}
/* DS-Lite info */
$remote = strip($_GLOBALS["NEW_AFTR_NAME"]);
if($remote!="")
set($stsp."/inet/ipv4/ipv4in6/remote", $remote);
anchor($stsp);
cmd("phpsh /etc/scripts/IPV6.INET.php ACTION=ATTACH".
" MODE=STATELESS".
" INF=". $inf.
" DEVNAM=". query("devnam").
" IPADDR=". query("stateless/ipaddr").
" PREFIX=". query("stateless/prefix").
" GATEWAY=".query("stateless/gateway").
//' "DNS='. query("stateless/dns").'"');
' "DNS='.$dns.'"');
/*del($stsp."/stateless");*/ /*renew may cause wan ip be disappered*/
}
function handle_infoonly($inf)
{
$stsp = XNODE_getpathbytarget("/runtime", "inf", "uid", $inf, 0);
if ($stsp=="") {msg("INFOONLY - no runtime for ".$inf); return;}
$DNS = strip($_GLOBALS["DNS"]);
$NAMESERVERS = strip($_GLOBALS["NAMESERVERS"]);
/* Combine the user config and DHCP server setting. */
$dns = $DNS;
if ($NAMESERVERS!="")
{
if ($dns=="") $dns = $NAMESERVERS;
else $dns = $dns." ".$NAMESERVERS;
}
//$NEW_AFTR_NAME = strip($_GLOBALS["NEW_AFTR_NAME"]);
$remote = strip($_GLOBALS["NEW_AFTR_NAME"]);
msg("INFOONLY - DNS: ".$dns.", aftr server: ".$remote);
add_each($dns, $stsp."/inet/ipv6", "dns");
/* DS-Lite info */
//$remote = strip($_GLOBALS["NEW_AFTR_NAME"]);
if($remote!="")
set($stsp."/inet/ipv4/ipv4in6/remote", $remote);
}
function handle_pppdhcp($inf, $devnam, $opt)
{
$stsp = XNODE_getpathbytarget("/runtime", "inf", "uid", $inf, 0);
if ($stsp=="" || $devnam=="") return;
$infprev = query($stsp."/infprevious");
$prevstsp = XNODE_getpathbytarget("/runtime", "inf", "uid", $infprev, 0);
$prevphyinf = query($prevstsp."/phyinf");
$p = XNODE_getpathbytarget("/runtime", "phyinf", "uid", $prevphyinf, 0);
if ($p=="") {msg("PPPDHCP - no runtime phyinf for ".$infprev); return;}
$ipaddr = query($p."/ipv6/global/ipaddr");
$child = query($stsp."/child/uid");
if($child!="")
{
/* we use global ip of ppp interface to judge stateless or stateful */
if($ipaddr!="")
{
msg("PPPDHCP - Stateless - PD/".$opt);
/* IA-PD is assigned to lan */
handle_stateless($_GLOBALS["INF"],strip($_GLOBALS["NEW_PD_PREFIX"]),strip($_GLOBALS["NEW_PD_PLEN"]));
}
else
{
msg("PPPDHCP - Stateful - PD/".$opt);
/* IA-NA+IA-PD/IA-PD is assigned to wan and lan */
handle_stateful($_GLOBALS["INF"],$_GLOBALS["DEVNAM"], $_GLOBALS["DHCPOPT"]);
}
}
else
{
msg("PPPDHCP - Stateful - IANA");
handle_stateful($_GLOBALS["INF"],$_GLOBALS["DEVNAM"], $_GLOBALS["DHCPOPT"]);
}
return;
}
/**************************************************************/
/* dhcpv6c has tailing space character in the arguments to the callback script.
* strip the extra space characters with strip(). */
/* ip release case */
if(strip($_GLOBALS["NEW_ADDR"])=="" && strip($_GLOBALS["NEW_PD_PREFIX"])=="" && strip($_GLOBALS["NEW_PD_PLEN"])=="" && $_GLOBALS["MODE"]!="INFOONLY") return;
set("/runtime/device/ntp6/server", strip($_GLOBALS["NTPSERVER"]));
if ($_GLOBALS["MODE"]=="STATELESS")
handle_stateless($_GLOBALS["INF"],strip($_GLOBALS["NEW_PD_PREFIX"]),strip($_GLOBALS["NEW_PD_PLEN"]));
//else if ($_GLOBALS["MODE"]=="STATEFUL" || $_GLOBALS["MODE"]=="PPPDHCP")
else if ($_GLOBALS["MODE"]=="STATEFUL")
handle_stateful($_GLOBALS["INF"],$_GLOBALS["DEVNAM"], $_GLOBALS["DHCPOPT"]);
else if ($_GLOBALS["MODE"]=="PPPDHCP")
handle_pppdhcp($_GLOBALS["INF"],$_GLOBALS["DEVNAM"], $_GLOBALS["DHCPOPT"]);
else if ($_GLOBALS["MODE"]=="INFOONLY")
handle_infoonly($_GLOBALS["INF"]);
else msg("Unknown mode - ".$_GLOBALS["MODE"]);
?>