Junos SRX OP 脚本错误

网络工程 瞻博网络
2021-07-21 10:54:01

我在排除此 OP 脚本的故障时遇到问题。当我运行以下脚本并包含 IP 地址时,出现以下错误:

{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'.

我为 op-scripts 运行了 traceoptions,看起来它实际上在第 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'

我无法弄清楚缺少评估的哪一部分,似乎一切都被称为必要,但我不是这些脚本的专家。

(作为一个附带问题,是否可以在盒子上编辑 op-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 }
1个回答

我的脚本有递归问题,所以我会看看我是否可以先解决这个问题,但是:

作为一个附带问题,是否可以在盒子上编辑 op-script 而不是删除和重新上传脚本?

有三种方法可以让您的 SLAX 开发体验不那么痛苦(不幸的是,对 SLAX 本身做不了太多;))。

  1. 您可以打开两个会话到您的盒子,然后将其中一个放入 shell,然后直接在 shell 中使用 vi 在一个窗口中编辑脚本,然后在另一个窗口中在 Junos 中进行测试。

  2. 在您的开发 PC 上运行一个盒子可以访问的网络服务器,在您的 PC 上本地编辑文件,然后远程调用它。

.

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

然后执行:

op url http://172.16.10.30/slax/tpol.slax destination-addres x.x.x.x etc. 
  1. 使用 Junos 用户界面脚本环境 (JUISE),它为您提供远程系统上的 SLAX 语言,同时仍允许您连接到远程瞻博网络设备以提取数据 - https://github.com/Juniper/juise