fakeDiameter.pl revision 7c478bd95313f5f23a4c958a745db2134aa03244
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License, Version 1.0 only
# (the "License"). You may not use this file except in compliance
# with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
# ident "%Z%%M% %I% %E% SMI"
#
# Copyright (c) 1999 by Sun Microsystems, Inc.
# All rights reserved.
#
# This script will fake a diameter server for testing.
#
$DEFAULT_PORT = 1234;
use Socket;
use Fcntl;
require "errno.ph";
#define MOBILE_IP_OPEN_SESSION_REQUEST 1
#define MOBILE_IP_OPEN_SESSION_ANSWER 2
#define MOBILE_IP_OPEN_SESSION_INDICATOIN 3
#define MOBILE_IP_OPEN_SESSION_INDICATION_RESPONSE 4
#define MOBILE_IP_ACCOUNTING_START_REQUEST 5
#define MOBILE_IP_ACCOUNTING_START_ANSWER 6
#define MOBILE_IP_ACCOUNTING_INTERIM_REQUEST 7
#define MOBILE_IP_ACCOUNTING_INTERIM_ANSWER 8
#define MOBILE_IP_ACCOUNTING_STOP_REQUEST 9
#define MOBILE_IP_ACCOUNTING_STOP_ANSWER 10
#define MOBILE_IP_CLOSE_SESSION_REQUEST 11
#define MOBILE_IP_CLOSE_SESSION_ANSWER 12
#define MOBILE_NODE_NAI 1
#define FOREIGN_AGENT_NAI 2
#define REGISTRATION_REQUEST 3
#define NUMBER_OF_CHALLENGE_BYTES_IN_RR 4
#define MOBILE_NODE_RESPONSE 5
#define MOBILE_NODE_HOME_ADDRESS 6
#define HOME_AGENT_ADDRESS 7
#define RESULT_CODE 8
#define REGISTRATION_REPLY 9
#define MN_FA_SPI 10
#define MN_FA_KEY 11
#define FA_HA_SPI 12
#define FA_HA_KEY 13
#define SESSION_TIMEOUT 14
#define HA_FA_KEY 15
#define FA_MN_KEY 16
#define MN_HA_SPI 17
#define MN_HA_KEY 18
#define HA_MN_KEY 19
#define SESSION_TIMEOUT_1 20
#define SESSION_TIME 21
my $CONVERT_FROM = 0;
my $CONVERT_TO = 1;
my %commandCodes;
my @commandCodesRev;
func => \&processOpenSessionRequest };
func => \&processAccountingStart };
func => \&processAccountingInterim };
func => \&processAccountingStop };
func => \&processCloseSession };
my %avpCodes;
my @avpCodesRev;
func => \&ConvertString };
func => \&ConvertString };
func => \&ConvertData };
func => \&ConvertInteger };
func => \&ConvertData };
func => \&ConvertIpAddr };
func => \&ConvertIpAddr };
func => \&ConvertInteger };
func => \&ConvertData };
func => \&ConvertInteger };
func => \&ConvertData };
func => \&ConvertInteger };
func => \&ConvertData };
func => \&ConvertInteger };
func => \&ConvertData };
func => \&ConvertData };
func => \&ConvertInteger };
func => \&ConvertData };
func => \&ConvertData };
func => \&ConvertInteger };
func => \&ConvertInteger };
my $CurrentHandle = 1;
# Data Handling routines
# Takes a NULL terminated string, and unpacks it
sub ConvertString($;$;) {
if ($fromOrTo == $CONVERT_FROM) {
return unpack("A*", $data);
} else {
return pack("A*",$data);
}
} # ConvertString
#Converts Data to a printable string
sub ConvertData($;) {
my $buffer;
my $returnBuffer="";
my $i;
if ($fromOrTo == $CONVERT_FROM) {
for ($i=0;$i < length($data); $i ++) {
}
# remove the final space
} else {
# Assume it's already binary.
return $data;
}
} # ConvertData
sub ConvertInteger($;) {
if ($fromOrTo == $CONVERT_FROM) {
if (length($data) != 4) {
print "Error: Integer is not 4 bytes long . . treating as data";
return ConvertData($data);
}
return unpack("N", $data);
} else {
return pack("N", $data);
}
} #ConvertInteger
sub ConvertIpAddr($;) {
if ($fromOrTo == $CONVERT_FROM) {
if (length($data) != 4) {
print "Error: IPAddr is not 4 bytes long . . treating as data";
return ConvertData($data);
}
} else {
}
} # ConvertIpAddr
sub initSocket {
my $port = shift;
my $proto = getprotobyname('tcp');
pack("l", 1)) || die "setsockopt: $!";
# make socket non-blocking
return $fh;
} # initSocket
sub REAPER {
$waitedpid = wait;
print "reaped $waitedpid" . ($? ? " with exit $?" : '') . "\n";
} # REAPER
sub spawn {
my $pid;
if (!defined($pid = fork)) {
warn "cannot fork: $!\n";
return;
} elsif ($pid) {
warn "begat $pid\n";
return; # I'm the parent
}
# else I'm the child -- go spawn
sleep (1);
exit &processMessages(\*Client);
} # spawn
# seperate the avps out into a hash containing
# the data (indexed by AVP name)
sub processAVPs($;) {
my $avpBuffer = shift;
my %entry;
my $avpName;
my %ReturnHash;
my %EntryHash;
my $entry;
print "DEBUG: AVPS:\n";
while (length($avpBuffer) > 0) {
# Now validate the code.
if (!defined($entry)) {
print "ERROR: Invalid AVP Code: $avpCode\n";
} else {
# Valid Avp . . . add it
$CONVERT_FROM);
}
# And, fix the buffer
}
return \%ReturnHash;
} # processAVPs
sub processMessages {
my $fh = shift;
my $buffer;
my $bytesLeftToRead;
my $avpBytesLeftToRead;
my $rc;
my $response;
print "processMessages: executing!\n";
while ( 1 ) {
# print "Reading in 4+4+4 bytes!\n";
die "Unable to read in header ($!)\n" if (!defined $rc);
return (0) if (!length($buffer));
# print "DEBUG: read " . length($buffer) . " bytes when expecing 4+4+4\n";
print "Received commandCode $commandCode, handle $handle" .
", length $length\n";
my $offset=0;
my $bytesRead = 0;
# And, read in the rest of the packet.
while ($bytesLeftToRead) {
die "Unable to read AVPs" if (!defined $rc);
# print "DEBUG: readChunk " . $bytesRead . " bytes\n";
$bytesLeftToRead -= $bytesRead;
}
# Ok, now take apart the packets
}
} # processMessages
sub processMessage($;$;$;$;) {
if (!defined $entry) {
sendError();
return 0;
}
# Now that we have a good entry, take apart the AVPs
} # processMessage
sub convertAvp($;$;$;) {
my %entryHash;
my $conversionFunc;
if (!defined($entry)) {
print "ERROR: Invalid AVP: $avpName\n";
return undef;
} else {
# Valid Avp . . . add it
return
}
} #addAvp
sub processOpenSessionRequest($;$;$;) {
my %OutAvpHash;
print "OpenSessionRequest($name)\n";
# MobileNode NAI
$CONVERT_TO);
# ResultCode
# ForeignAgentNAI
$CONVERT_TO);
# Registration Reply
# WORK
# MN-FA SPI
# WORK
# MN-FA Key
# WORK
# FA-HA SPI
# WORK
# FA-HA Key
# WORK
# HomeAgentAddress
"192.168.168.1",
$CONVERT_TO);
# Mobile Node Home ADdress
"192.168.168.2",
$CONVERT_TO);
# Session Timeout
# Send back a changing hancle of one.
$CurrentHandle++);
return 0;
} #processOpenSessionRequest
sub processAccountingStart($;$;$;) {
my %OutAvpHash;
print "ProcessAccountingStart($name) handle = $handle\n";
# MobileNode NAI
$CONVERT_TO);
# ResultCode
# ForeignAgentNAI
$CONVERT_TO);
# Send back the passed in handle.
$handle);
} #processAccountingStart
sub processAccountingInterim($;$;$;) {
my %OutAvpHash;
print "ProcessAccountingInterim($name)\n";
# MobileNode NAI
$CONVERT_TO);
# ResultCode
# ForeignAgentNAI
$CONVERT_TO);
# Send back the passed in handle.
$handle);
} #processAccountingInterim
sub processAccountingStop($;$;$;) {
my %OutAvpHash;
print "ProcessAccountingStop($name)\n";
# MobileNode NAI
$CONVERT_TO);
# ResultCode
# ForeignAgentNAI
$CONVERT_TO);
# Send back the passed in handle.
$handle);
} #processAccountingStop
sub processCloseSession($;$;$;) {
my %OutAvpHash;
print "ProcessCloseSession($name)\n";
# MobileNode NAI
$CONVERT_TO);
# ResultCode
# ForeignAgentNAI
$CONVERT_TO);
# Send back the passed in handle.
$handle);
} #processCloseSession
# This routine will package up the passed in AVPS
sub buildResponse($;$;$;) {
my $header;
my $body = "";
my $avp;
my $key;
" to response\n";
}
print "Building response with code = $code, handle = $handle, length = " .
# Now build header
} #buildResponse
sub niy($;$;$;$) {
print "Error: I don't know how to handle $name (Not Implemented Yet)\n";
} #niy
# Main ( multithreaded )
my $socket = initSocket();
listen($socket,5);
my $paddr;
print "Waiting for connections to port $DEFAULT_PORT\n";
while (1) {
if (defined($paddr)) {
"] at port $port\n";
&spawn;
} else {
if ($! != &EINTR) {
}
}
} # main for