2

I am having trouble troubleshooting this OP script. When I run the following script and include an IP address, I get the following error:

{primary:node1}
user@fwB> op tpol source-address x.x.x.x destination-address x.x.x.0 destination-port 2002    (Real IPs redacted)
error: jcs:execute: null argument
error: xmlXPathCompiledEval: evaluation failed
error: runtime error: file /var/db/scripts/op/policy-test-v2.slax line 104 element variable
error: Failed to evaluate the expression of variable 'get-route'.

I ran traceoptions for op-scripts and it looks like it is actually failing at line 111:

Feb 21 13:29:54 reading op script 'policy-test-v2.slax'
Feb 21 13:29:57 jcs:execute: null argument

Feb 21 13:29:57 xmlXPathCompiledEval: evaluation failed
Feb 21 13:29:57 runtime error: file /var/db/scripts/op/policy-test-v2.slax line 111 element variable

Feb 21 13:29:57 Failed to evaluate the expression of variable 'get-int'.

Feb 21 13:29:57 op script output
Feb 21 13:29:57 begin dump
<?xml version="1.0"?>
Feb 21 13:29:57 end dump
Feb 21 13:29:57 inspecting op output 'policy-test-v2.slax'
Feb 21 13:29:57 finished op script 'policy-test-v2.slax'

I'm having trouble figuring out what piece of the evaluation is missing, it seems like everything is called as necessary, but I am not an expert with these scripts.

(As a side question, is it possible to edit an op-script on-box instead of deleting and re-uploading a script?)

1   /* Machine Crafted with Care (tm) by slaxWriter */
2   version 1.0;
3  
4   ns junos = "http://xml.juniper.net/junos/*/junos";
5   ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
6   ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
7  
8  
9   /*
10  This is a simple script that looks up all the entries in the policy table that match a particular query
11  It is useful to debug polcy configurations
12   */
13  import "../import/junos.xsl";
14  var $arguments = {
15      <argument> {
16          <name> "source-address";
17          <description> "Source IP address of the initial session creation packet";
18      }
19      <argument> {
20          <name> "destination-address";
21          <description> "Destination IP address of the initial session creation packet";
22      }
23      <argument> {
24          <name> "source-port";
25          <description> "Source port of the packet";
26      }
27      <argument> {
28          <name> "destination-port";
29          <description> "Destination port of the packet";
30      }
31      <argument> {
32          <name> "from-zone";
33          <description> "Ingress zone of the packet";
34      }
35      <argument> {
36          <name> "to-zone";
37          <description> "Egress zone of the packet";
38      }
39  }
40  /* Open a persistent connection */
41  var $connection = jcs:open();
42  param $source-address = {
43      expr "0.0.0.0/0";
44  }
45  param $destination-address = {
46      expr "0.0.0.0/0";
47  }
48  param $source-port = {
49      expr "0";
50  }
51  param $destination-port = {
52      expr "0";
53  }
54  param $protocol = {
55      expr "0";
56  }
57  param $from-zone = {
58      call find-zone($ip = $source-address);
59  }
60      param $to-zone = {
61      call find-zone($ip = $destination-address);
62  }   
63          
64 
65  /* print-policy: Displays the policy info */
66  template print-policy ($name, $from-zone, $to-zone, $source-address, $destination-address, $application, $action, $comment, $row = number("1"), $header = false()) {
67      var $format-string = "%-15.14s %-15.14s %-25.24j1s %-25.24s %-25.24s %-15.14s %-10.9s %s \n";
68      
69      if ($header) {
70          expr jcs:printf($format-string, "From-Zone", "To-Zone", "Name", "Src-Addr", "Dst-Addr", "Application", "Action", "");
71      
72      } else {
73          var $num-rows = {
74              if (count($application) >= count($source-address) && count($application) >= count($destination-address)) {
75                  expr count($application);
76              
77              } else if (count($source-address) > count($application) && count($source-address) > count($destination-address)) {
78                  expr count($source-address);
79              
80              } else {
81                  expr count($destination-address);
82              }
83          }
84          
85          if ($row <= $num-rows) {
86              expr jcs:printf($format-string, $from-zone, $to-zone, $name, $source-address[$row] , $destination-address[$row] , $application[$row] , $action, $comment);
87              call print-policy($row = $row + 1, $num-rows, $source-address, $destination-address, $application);
88          }
89      }
90  }
91 
92  /* find-zone: Returns the zone where a given IP is */
93  template find-zone ($ip) {
94      
95      if ($ip == "0.0.0.0/0") {
96          expr "any";
97      
98      } else {
99          var $get-route-rpc = <command> {
100             expr "show route ";
101             expr $ip;
102             expr " active-path best";
103         }
104         var $get-route = jcs:execute($connection, $get-route-rpc);
105         var $zone = {
106             if ($get-route//via) {
107                 var $get-int-rpc = <command> {
108                     expr "show interface ";
109                     expr $get-route//via;
110                 }
111                 var $get-int = jcs:execute($connection, $get-int-rpc);
112                 
113                 expr $get-int//logical-interface-zone-name;
114             
115             } else {
116                 expr "any";
117             }
118         }
119         
120         expr $zone;
121     }
122 }
123
124 /* rshift: Shifts bits to the right. Used to do an IP/MASK comparision */
125 template rshift ($number, $count) {
126     
127     /* <output>
128     <xsl:value-of select="jcs:printf('Shifting %i %i times\n',$number, $count)"/>       
129     </output> */
130     if ($count <= 0) {
131         expr $number;
132     
133     } else {
134         call rshift($number = floor($number div 2), $count = ($count) - 1);
135     }
136 }
137
138 /* match-ip: Returns true if the ip is in the prefix */
139 template match-ip ($prefix, $ip) {
140     var $bytes-network = jcs:regex("([0-9]+).([0-9]+).([0-9]+).([0-9]+)/([0-9]+)", $prefix);
141     var $subnet = {
142         call rshift($number = $bytes-network[2] * 16777216 + $bytes-network[3] * 65536 + $bytes-network[4] * 256 + $bytes-network[5], $count = 32 -($bytes-network[6]));
143     }
144     var $bytes-ip = jcs:regex("([0-9]+).([0-9]+).([0-9]+).([0-9]+)", $ip);
145     var $ipnet = {
146         call rshift($number = $bytes-ip[2] * 16777216 + $bytes-ip[3] * 65536 + $bytes-ip[4] * 256 + $bytes-ip[5], $count = 32 - $bytes-network[6]);
147     }
148     
149     if ($ipnet == $subnet) {
150         expr true();
151     
152     } else {
153         expr false();
154     }
155 }
156
157 /* match-prefix-list: Returns true if the ip is in the prefix list */
158 template match-prefix-list ($ip, $prefix-list) {
159     
160     if ($ip == "0.0.0.0/0") {
161         expr true();
162     } else {
163     if (not($prefix-list)) {
164         expr false();
165     
166     } else {
167         var $match-prefix = {
168             call match-ip($ip, $prefix = $prefix-list);
169         }
170         
171         if ($match-prefix == "true") {
172             expr true();
173         
174         } else {
175             call match-prefix-list($ip, $prefix-list = $prefix-list[position() > 1 ] );
176             }
177         }
178     }
179 }
180
181 match / {
182     <op-script-results> {
183         /* First, check parameters passed */
184         if (not(jcs:parse-ip($source-address))) {
185             <output> jcs:printf("Bad IP address format: %s", $source-address);
186         
187         } else if (not(jcs:parse-ip($destination-address))) {
188             <output> jcs:printf("Bad IP address format: %s", $destination-address);
189         
190         } else if (not($source-port >= 0 && $source-port <= 65535)) {
191             <output> jcs:printf("Bad IP port number: %s", $source-port);
192         
193         } else if (not($destination-port >= 0 && $destination-port <= 65535)) {
194             <output> jcs:printf("Bad IP port number: %s ", $destination-port);
195         
196         } else {
197             <output> {
198                 call print-policy($header = true());
199                 expr jcs:trace( "from-zone ",$from-zone);
200                 expr jcs:trace( "to-zone ",$to-zone);
201             }
202             var $filters = {
203                 if ($from-zone != "any") {
204                     expr " from-zone ";
205                     expr $from-zone;
206                 }
207                 if ($to-zone != "any") {
208                     expr " to-zone ";
209                     expr $to-zone;
210                 }
211             }
212             
213             var $get-policies-rpc = <command> {
214                 expr " show security policies ";
215                 expr $filters;
216                 expr " detail ";
217             }
218             expr jcs:trace( "command ", $get-policies-rpc );
219             /* Get the list of possible policies */
220             var $connection2 = jcs:open();
221             var $policies = jcs:execute( $connection2 , $get-policies-rpc );
222             /* Loop throught the policies to find the matching ones */
223             
224             for-each ($policies//policy-information) {
225                 var $match-source = {
226                     call match-prefix-list($ip = $source-address, $prefix-list = .//source-address//address-prefix);
227                     }
228                         expr jcs:trace( "source-address ", $source-address," prefix-list ", .//source-address//address-prefix ," ", $match-source );
229                 
230                 var $match-destination = {
231                     call match-prefix-list($ip = $destination-address, $prefix-list = .//destination-address//address-prefix);
232                     }
233                     expr jcs:trace( "dest-address ", $destination-address," prefix-list ", .//destination-address//address-prefix ," ", $match-destination );
234                 
235                 var $match-destination-port = {
236                     if ($destination-port == "0") {
237                         expr true();
238                     
239                     } else if (./applications/application/application-term/destination-port-range[low == "0" && high == "0"]) {
240                         expr true();
241                     
242                     } else if (./applications/application/application-term/destination-port-range[low <= $destination-port && high >= $destination-port]) {
243                         expr true();
244                     
245                     } else {
246                         expr false();
247                     }
248                 }
249                 var $match-source-port = {
250                     if ($source-port == "0") {
251                         expr true();
252                     
253                     } else if (./applications/application/application-term/source-port-range[low == "0" && high == "0"]) {
254                         expr true();
255                     
256                     } else if (./applications/application/application-term/source-port-range[low <= $source-port && high >= $source-port]) {
257                         expr true();
258                     
259                     } else {
260                         expr false();
261                     }
262                 }
263                 
264                  /* <output>
265                 <xsl:value-of select="jcs:printf('Policy name: %s\n',./policy-name)"/>
266                 <xsl:value-of select="jcs:printf('  match source: %s\n', $match-source)"/>
267                 <xsl:value-of select="jcs:printf('  match destination: %s\n', $match-destination)"/>
268                 <xsl:value-of select="jcs:printf('  match source port: %s\n', $match-source-port)"/>
269                 <xsl:value-of select="jcs:printf('  match destination port: %s\n', $match-destination-port)"/>
270                 </output> */
271                 if ($match-source == "true" && $match-destination == "true" && $match-source-port == "true" && $match-destination-port == "true") {
272                     <output> {
273                         call print-policy($from-zone = ../../context-information/source-zone-name, $to-zone = ../../context-information/destination-zone-name, $name = ./policy-name, $destination-address = ./destination-addresses/destination-address/address-name, $source-address = ./source-addresses/source-address/address-name, $application = ./applications/application/application-name, $action = ./policy-action/action-type);
274                     }
275                 }
276             }
277         }
278     }
279 }
  • Did any answer help you? if so, you should accept the answer so that the question doesn't keep popping up forever, looking for an answer. Alternatively, you could provide and accept your own answer. – Ron Maupin Aug 7 '17 at 17:37
3

I'm having a recursion problem with your script, so I'll see if I can hack through that first, but:

As a side question, is it possible to edit an op-script on-box instead of deleting and re-uploading a script?

There are three ways to make you SLAX development experience less painful (can't do much about SLAX itself unfortunately ;) ).

  1. You can open two sessions to your box, and drop into the shell on one and use vi directly in the shell to edit your script in one window and test in Junos on the other.

  2. Run a webserver on your development PC that the box can reach, edit the file locally on your PC and then call it remotely. :

.

set system scripts op file tpol.slax arguments destination-address
set system scripts op file tpol.slax arguments destination-port
set system scripts op file tpol.slax arguments from-zone
set system scripts op file tpol.slax arguments source-address
set system scripts op file tpol.slax arguments source-port
set system scripts op file tpol.slax arguments to-zone

then execute with:

op url http://172.16.10.30/slax/tpol.slax destination-addres x.x.x.x etc. 
  1. Use the Junos User Interface Script Environment (JUISE), which gives you the SLAX language offboard on a remote system, while still allowing you to connect to a remote Juniper device to pull data - https://github.com/Juniper/juise

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.