Hugh,
Thanks for making this available: it has been a big help.
One mistake I made that other people who want to use it should avoid is the assumption that you can use the “talk” function just like you would a telnet connection. E.g., I tried something like:
@cmd = ("/category/command", "keyword1=value1", "keyword2=value2");
($rc, @response) = Mtik::talk(\@cmd);
Mtik::talk works fine for commands with no operands, but, if you’re sending a command with keyword-based operands, you need to use the “mtik_cmd” function, and supply the operands in a hash, like the main loop in the example does. I think this is because mtik_cmd is doing the special formatting (like adding a leading “=” to operands) that’s different between the terminal interface and the API.
The problem I’m having right now, though, is that I’m using the API to fiddle the firewall tables to provide temporary access to certain servers for users who’ve logged in through a web interface. I can add entries okay, now that I’m using mtik_cmd. But, when I try to remove entries with:
my @cmd = ("/ip/firewall/filter/remove", "$rowno");
my($retval,@results) = Mtik::talk(\@cmd);
The debug output says that the code is sending the command and operand, and I get a “!done” response. But the command doesn’t remove the entry.
I’d kinda like to find out why this doesn’t work, for future reference. Has anyone worked out a general-purpose method for sending commands with positional parameters?
Meanwhile, I found a hint in another posting that enabled me to make it work. It was about another command that takes a “row number” as a positional parameter in the telnet interface. In the API, the row is identified using the “.id” value passed back when listing the table (notthe row number that you’d use in the telnet interface), and a keyword of “numbers”.
I have a function that uses the “talk” function to build an array of hashes containing the current firewall table, and another that will find the entry to be deleted. So the code to remove an entry looks like this:
# Remove a camera/IPA pair from the firewall list.
# Returns 0 if it was removed, or a negative number if it wasn't.
# Inputs:
# The camera resource name (which is also used as the name of
# its chain in the firewall)
# The source (i.e., user's) IP address
sub mtik_access_remove
{
my($chain) = shift;
my($ipa) = shift;
# First see whether it's already in the list
my($rc, @firewall) = mtik_get_firewall;
if ($rc) {
return $rc;
}
my($rowno) = mtik_find_entry_in_firewall(\@firewall, $chain, $ipa);
if ($rowno < 0) {
print "IPA $ipa not found in chain $chain\n";
return -1;
}
# It's there, so try to remove it
# my @cmd = ("/ip", "firewall", "filter", "remove", "$rowno");
my %operands;
$operands{'numbers'} = $firewall[$rowno]{".id"};
my($retval,@results) = Mtik::mtik_cmd("/ip/firewall/filter/remove", \%operands);
if ($retval != 1) {
print "removal of IPA $ipa from $chain failed. RC = $retval\n$Mtik::error_msg\n";
return $retval;
}
return 0;
}
[code]
Note the way I test $retval for a value of 1 (instead of 0) for "success". I translate it to 0 for code calling my functions, since I'm used to the convention of "0 for success, non-zero for failure".
Thanks again for sharing. I hope others find this record of my mistakes useful in avoiding repeating them.
Ran