#! /usr/bin/perl -w # pd100_get2.pl - a client for bsti pd100 ip cameras # modified by Patrick Salecker # added support for my camera and login password # original version: http://217.20.164.161/pd100_get.pl.txt #---------------- use strict; use Socket; use IO::Handle; our ($typacket, $dopacket); my ($pipe, $host, $port, $password, $proto, $iaddr, $paddr, $pid, $buf, $client_hash, $dsize, $file_to_save, $interval, $jpgcode); # settings $host = "192.168.1.102"; $port = 80; $password =""; $file_to_save="image.jpg"; $interval=.1; ############################################################# # IF $typacket == 0x4f # dopacket: # -> - to camera # <- - from camera ############################################################# #t/f hex explanation # -> 00 - reset camera's config for logged user # <- 01 - show camera's mac address # -> 02 - login info sending to camera # <- 03 - login answer from camera (access/deny) # -> 10 - clearing something ???? # <- 16 - answer to "10", maybe cleared ???? # -> 04 - something setup asking ???? # <- 11 - some code sended (answer) # <- 05 - again something sended ############################################################## #$typacket == 0x56 ############################################################## # -> 00 - send code gotted from 05 in 0x04f setup (see upper) ############################################################## #$typacket == 0x4f ############################################################## # -> 07 - clearing something (or say "start") ############################################################## #$typacket == 0x56 ############################################################## # <- 01 - sending data ############################################################## sub makepacket { my $data = $_[0]; my $strsize=length($data); my $dsize=$strsize/2; $strsize = $strsize+46; return pack("H".$strsize,"4d4f5f".$typacket.unpack("H2",pack("i",$dopacket))."00000000000000000000".unpack("H8",pack("i",$dsize)).unpack("H8",pack("i",$dsize)).$data); } sub countpacketdata { my $buf = $_[0]; # debug #my $data="4d4f5f4f01000000000000000000001b0000001b00000000003130333637353432333243410000000001000000000600000e"; #$buf=pack("H100",$data); #print $buf; if ($buf =~ m/^\x4d\x4f\x5f(.)(.)\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00(.{4})(.{4}).*/){ $typacket = unpack("H2",$1); $dopacket = unpack("c",$2); my $psize= unpack("v",$3); my $psizecheck= unpack("v",$4); if ($psize == $psizecheck){ return $psize; } else { return 0; } } else { return 0; } } # initialize host and port $proto = getprotobyname('tcp'); # get the port address $iaddr = inet_aton($host); $paddr = sockaddr_in($port, $iaddr); socketpair(CHILD, PARENT, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die "socketpair: $!"; CHILD->autoflush(1); PARENT->autoflush(1); if($pid = fork()) { # Parent print "parent\n"; close PARENT; # create the socket, connect to the port socket(SOCK_CTRL, PF_INET, SOCK_STREAM, $proto) or die "socket: $!"; binmode(SOCK_CTRL); connect(SOCK_CTRL, $paddr) or die "connect: $!"; $typacket="4f"; $dopacket=0; $buf=makepacket(""); send(SOCK_CTRL, $buf, 0); read(SOCK_CTRL,$buf,23); $dsize=countpacketdata($buf); # $dopacket & $typacket - changed too!! #debug #print $dsize."\n-\n"; #print $typacket."\n-\n"; #print $dopacket."\n-\n"; read(SOCK_CTRL,$buf,$dsize); if ($dopacket==1){ print "Connected to MAC:".substr($buf,2,12)."\n"; } else { print "Connected, but don't know MAC!\n"; } $dopacket=2; # login to camera (just "admin", no password) #$buf=makepacket("61646d696e00000000000000000000000000000000bb76cbb7dd"); # login to camera (just "admin", "test") #$buf=makepacket("61646D696E00382E312E31003074657374000000000000000000"); $buf=makepacket("61646D696E0000000000000000".unpack("H*", $password)."0" x (26-(length($password)*2))); send(SOCK_CTRL, $buf, 0); read(SOCK_CTRL,$buf,23); $dsize=countpacketdata($buf); # $dopacket & $typacket - changed too!! read(SOCK_CTRL,$buf,$dsize); if ((unpack("H6",$buf) eq "000002") && ($dopacket==3)){ print "login OK!\n"; } else { print "ERROR: wrong login or packet cmd\n"; } $dopacket=16; $buf=makepacket(""); send(SOCK_CTRL, $buf, 0); read(SOCK_CTRL,$buf,23); $dsize=countpacketdata($buf); # $dopacket & $typacket - changed too!! read(SOCK_CTRL,$buf,$dsize); if (($dopacket==22) && (unpack("H2",$buf) eq "00")){ print "Answer to \"0x10\" OK!\n"; } else { if ($dopacket==22) { print "Answer to \"0x10\" NOT OK!\n"; } else { print "No answer to \"0x10\"!\n"; } } $dopacket=4; $buf=makepacket("02"); send(SOCK_CTRL, $buf, 0); # 1-st packer recv #skip useless data read(SOCK_CTRL,$buf,23); $dsize=countpacketdata($buf); # $dopacket & $typacket - changed too!! read(SOCK_CTRL,$buf,$dsize); read(SOCK_CTRL,$buf,23); $dsize=countpacketdata($buf); read(SOCK_CTRL,$buf,$dsize); if ($dopacket==17){ print "Answer to \"0x04\" give: 0x".unpack("H".length($buf)*2,$buf)."\n"; } # 2-nd packer recv read(SOCK_CTRL,$buf,23); $dsize=countpacketdata($buf); # $dopacket & $typacket - changed too!! read(SOCK_CTRL,$buf,$dsize); if ($dopacket==05){ #print "And: 0x".unpack("H".length($buf)*2,$buf)." - too (hash to 2-nd socket)!\n"; ################################################################################# # picture socket code ################################################################################# $client_hash=substr(unpack("H".length($buf)*2,$buf),4); print CHILD $client_hash."\n"; print "Sended client hash to file:".$client_hash." ".length($client_hash)."\n"; #################################### # say to control socket "start"! $typacket="4f"; $dopacket=7; $buf=makepacket("00000000"); send(SOCK_CTRL, $buf, 0); #################################### ################################################################################# } for (;;){ # 2-nd packer recv read(SOCK_CTRL,$buf,23); $dsize=countpacketdata($buf); # $dopacket & $typacket - changed too!! #read(SOCK_CTRL,$buf,$dsize); if ($dopacket=="-1"){ print time()." Send keep-alive: ".$dopacket."\n"; $buf=makepacket(""); send(SOCK_CTRL, $buf, 0); # 1-st packer recv } else { print "Control received: 0x".unpack("H".length($buf)*2,$buf)." - unknown data!\n"; } } waitpid($pid,0); #################################### # say to control socket "stop"! $typacket="4f"; $dopacket=6; $buf=makepacket(""); send(SOCK_CTRL, $buf, 0); #################################### close(SOCK_CTRL) or die "close: $!"; close CHILD; } elsif(defined $pid) { # Child print "children\n"; close CHILD; chomp($buf = ); print "getting hash\n"; print $buf."<- got user hash\n"; $typacket="56"; $dopacket=0; $buf=makepacket($buf); socket(SOCK_GET, PF_INET, SOCK_STREAM, $proto) or die "socket: $!"; binmode(SOCK_GET); connect(SOCK_GET, $paddr) or die "connect: $!"; send(SOCK_GET, $buf, 0); #################################### # loop for image gets do { read(SOCK_GET,$buf,23); $dsize=countpacketdata($buf); # $dopacket & $typacket - changed too!! if ($dsize > 0){ print time()." got image \n"; read(SOCK_GET,$buf,$dsize); # save to file open(FH, ">$file_to_save.tmp") or die "Can't open $file_to_save.tmp: $!"; $jpgcode= substr($buf,13); print FH $jpgcode; close(FH) or die "close: $!"; rename("$file_to_save.tmp", "$file_to_save"); #sleep 1; select(undef,undef,undef,$interval); } } while (($typacket eq "56") && ($dsize > 0)); #################################### close(SOCK_GET) or die "close: $!"; close PARENT; }