1/* RIPd and zebra interface.
2 * Copyright (C) 1997, 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING.  If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
24#include "command.h"
25#include "prefix.h"
26#include "stream.h"
27#include "routemap.h"
28#include "zclient.h"
29#include "log.h"
30#include "ripd/ripd.h"
31#include "ripd/rip_debug.h"
32
33/* All information about zebra. */
34struct zclient *zclient = NULL;
35
36/* Callback prototypes for zebra client service. */
37int rip_interface_add (int, struct zclient *, zebra_size_t);
38int rip_interface_delete (int, struct zclient *, zebra_size_t);
39int rip_interface_address_add (int, struct zclient *, zebra_size_t);
40int rip_interface_address_delete (int, struct zclient *, zebra_size_t);
41int rip_interface_up (int, struct zclient *, zebra_size_t);
42int rip_interface_down (int, struct zclient *, zebra_size_t);
43
44/* RIPd to zebra command interface. */
45void
46rip_zebra_ipv4_add (struct prefix_ipv4 *p, struct in_addr *nexthop,
47		    u_int32_t metric, u_char distance)
48{
49  struct zapi_ipv4 api;
50
51  if (zclient->redist[ZEBRA_ROUTE_RIP])
52    {
53      api.type = ZEBRA_ROUTE_RIP;
54      api.flags = 0;
55      api.message = 0;
56      SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
57      api.nexthop_num = 1;
58      api.nexthop = &nexthop;
59      api.ifindex_num = 0;
60      SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
61      api.metric = metric;
62
63      if (distance && distance != ZEBRA_RIP_DISTANCE_DEFAULT)
64	{
65	  SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
66	  api.distance = distance;
67	}
68
69      zapi_ipv4_add (zclient, p, &api);
70
71      rip_global_route_changes++;
72    }
73}
74
75void
76rip_zebra_ipv4_delete (struct prefix_ipv4 *p, struct in_addr *nexthop,
77		       u_int32_t metric)
78{
79  struct zapi_ipv4 api;
80
81  if (zclient->redist[ZEBRA_ROUTE_RIP])
82    {
83      api.type = ZEBRA_ROUTE_RIP;
84      api.flags = 0;
85      api.message = 0;
86      SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
87      api.nexthop_num = 1;
88      api.nexthop = &nexthop;
89      api.ifindex_num = 0;
90      SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
91      api.metric = metric;
92
93      zapi_ipv4_delete (zclient, p, &api);
94
95      rip_global_route_changes++;
96    }
97}
98
99/* Zebra route add and delete treatment. */
100int
101rip_zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length)
102{
103  struct stream *s;
104  struct zapi_ipv4 api;
105  unsigned long ifindex;
106  struct in_addr nexthop;
107  struct prefix_ipv4 p;
108
109  s = zclient->ibuf;
110  ifindex = 0;
111  nexthop.s_addr = 0;
112
113  /* Type, flags, message. */
114  api.type = stream_getc (s);
115  api.flags = stream_getc (s);
116  api.message = stream_getc (s);
117
118  /* IPv4 prefix. */
119  memset (&p, 0, sizeof (struct prefix_ipv4));
120  p.family = AF_INET;
121  p.prefixlen = stream_getc (s);
122  stream_get (&p.prefix, s, PSIZE (p.prefixlen));
123
124  /* Nexthop, ifindex, distance, metric. */
125  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
126    {
127      api.nexthop_num = stream_getc (s);
128      nexthop.s_addr = stream_get_ipv4 (s);
129    }
130  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
131    {
132      api.ifindex_num = stream_getc (s);
133      ifindex = stream_getl (s);
134    }
135  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
136    api.distance = stream_getc (s);
137  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
138    api.metric = stream_getl (s);
139
140  /* Then fetch IPv4 prefixes. */
141  if (command == ZEBRA_IPV4_ROUTE_ADD)
142    rip_redistribute_add (api.type, RIP_ROUTE_REDISTRIBUTE, &p, ifindex, &nexthop);
143  else
144    rip_redistribute_delete (api.type, RIP_ROUTE_REDISTRIBUTE, &p, ifindex);
145
146  return 0;
147}
148
149void
150rip_zclient_reset ()
151{
152  zclient_reset (zclient);
153}
154
155#ifdef FOX_LIST_SUPPORT
156/* RIP route-map set for redistribution */
157void
158rip_routemap_set (int type, char *name)
159{
160  if (rip->route_map[type].name)
161    free(rip->route_map[type].name);
162
163  rip->route_map[type].name = strdup (name);
164  rip->route_map[type].map = route_map_lookup_by_name (name);
165}
166
167void
168rip_redistribute_metric_set (int type, int metric)
169{
170  rip->route_map[type].metric_config = 1;
171  rip->route_map[type].metric = metric;
172}
173
174int
175rip_metric_unset (int type,int metric)
176{
177#define DONT_CARE_METRIC_RIP 17
178  if (metric != DONT_CARE_METRIC_RIP &&
179      rip->route_map[type].metric != metric)
180    return 1;
181  rip->route_map[type].metric_config = 0;
182  rip->route_map[type].metric = 0;
183  return 0;
184}
185
186/* RIP route-map unset for redistribution */
187int
188rip_routemap_unset (int type,char *name)
189{
190  if (! rip->route_map[type].name ||
191      (name != NULL && strcmp(rip->route_map[type].name,name)))
192    return 1;
193
194  free (rip->route_map[type].name);
195  rip->route_map[type].name = NULL;
196  rip->route_map[type].map = NULL;
197
198  return 0;
199}
200#endif /* FOX_LIST_SUPPORT */
201
202
203/* Redistribution types */
204static struct {
205  int type;
206  int str_min_len;
207  char *str;
208} redist_type[] = {
209  {ZEBRA_ROUTE_KERNEL,  1, "kernel"},
210  {ZEBRA_ROUTE_CONNECT, 1, "connected"},
211  {ZEBRA_ROUTE_STATIC,  1, "static"},
212  {ZEBRA_ROUTE_OSPF,    1, "ospf"},
213  {ZEBRA_ROUTE_BGP,     1, "bgp"},
214  {0, 0, NULL}
215};
216
217#ifdef FOX_CMD_SUPPORT
218DEFUN (router_zebra,
219       router_zebra_cmd,
220       "router zebra",
221       "Enable a routing process\n"
222       "Make connection to zebra daemon\n")
223{
224  vty->node = ZEBRA_NODE;
225  zclient->enable = 1;
226  zclient_start (zclient);
227  return CMD_SUCCESS;
228}
229
230DEFUN (no_router_zebra,
231       no_router_zebra_cmd,
232       "no router zebra",
233       NO_STR
234       "Enable a routing process\n"
235       "Make connection to zebra daemon\n")
236{
237  zclient->enable = 0;
238  zclient_stop (zclient);
239  return CMD_SUCCESS;
240}
241#endif /* FOX_CMD_SUPPORT */
242
243int
244rip_redistribute_set (int type)
245{
246  if (zclient->redist[type])
247    return CMD_SUCCESS;
248
249  zclient->redist[type] = 1;
250
251  if (zclient->sock > 0)
252    zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient->sock, type);
253
254  return CMD_SUCCESS;
255}
256
257#ifdef FOX_CMD_SUPPORT
258int
259rip_redistribute_unset (int type)
260{
261  if (! zclient->redist[type])
262    return CMD_SUCCESS;
263
264  zclient->redist[type] = 0;
265
266  if (zclient->sock > 0)
267    zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient->sock, type);
268
269  /* Remove the routes from RIP table. */
270  rip_redistribute_withdraw (type);
271
272  return CMD_SUCCESS;
273}
274#endif /* FOX_CMD_SUPPORT */
275
276int
277rip_redistribute_check (int type)
278{
279  return (zclient->redist[type]);
280}
281
282void
283rip_redistribute_clean ()
284{
285  int i;
286
287  for (i = 0; redist_type[i].str; i++)
288    {
289      if (zclient->redist[redist_type[i].type])
290	{
291	  if (zclient->sock > 0)
292	    zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE,
293				     zclient->sock, redist_type[i].type);
294
295	  zclient->redist[redist_type[i].type] = 0;
296
297	  /* Remove the routes from RIP table. */
298	  rip_redistribute_withdraw (redist_type[i].type);
299	}
300    }
301}
302
303#ifdef FOX_CMD_SUPPORT
304DEFUN (rip_redistribute_rip,
305       rip_redistribute_rip_cmd,
306       "redistribute rip",
307       "Redistribute information from another routing protocol\n"
308       "Routing Information Protocol (RIP)\n")
309{
310  zclient->redist[ZEBRA_ROUTE_RIP] = 1;
311  return CMD_SUCCESS;
312}
313
314DEFUN (no_rip_redistribute_rip,
315       no_rip_redistribute_rip_cmd,
316       "no redistribute rip",
317       NO_STR
318       "Redistribute information from another routing protocol\n"
319       "Routing Information Protocol (RIP)\n")
320{
321  zclient->redist[ZEBRA_ROUTE_RIP] = 0;
322  return CMD_SUCCESS;
323}
324#endif /* FOX_CMD_SUPPORT */
325
326DEFUN (rip_redistribute_type,
327       rip_redistribute_type_cmd,
328       "redistribute (kernel|connected|static|ospf|bgp)",
329       "Redistribute information from another routing protocol\n"
330       "Kernel routes\n"
331       "Connected\n"
332       "Static routes\n"
333       "Open Shortest Path First (OSPF)\n"
334       "Border Gateway Protocol (BGP)\n")
335{
336  int i;
337
338  for(i = 0; redist_type[i].str; i++)
339    {
340      if (strncmp (redist_type[i].str, argv[0],
341		   redist_type[i].str_min_len) == 0)
342	{
343	  zclient_redistribute_set (zclient, redist_type[i].type);
344	  return CMD_SUCCESS;
345	}
346    }
347
348  vty_out(vty, "Invalid type %s%s", argv[0],
349	  VTY_NEWLINE);
350
351  return CMD_WARNING;
352}
353
354#ifdef FOX_CMD_SUPPORT
355DEFUN (no_rip_redistribute_type,
356       no_rip_redistribute_type_cmd,
357       "no redistribute (kernel|connected|static|ospf|bgp)",
358       NO_STR
359       "Redistribute information from another routing protocol\n"
360       "Kernel routes\n"
361       "Connected\n"
362       "Static routes\n"
363       "Open Shortest Path First (OSPF)\n"
364       "Border Gateway Protocol (BGP)\n")
365{
366  int i;
367
368  for (i = 0; redist_type[i].str; i++)
369    {
370      if (strncmp(redist_type[i].str, argv[0],
371		  redist_type[i].str_min_len) == 0)
372	{
373#if defined(FOX_LIST_SUPPORT)
374	  rip_metric_unset (redist_type[i].type, DONT_CARE_METRIC_RIP);
375	  rip_routemap_unset (redist_type[i].type,NULL);
376#endif /* FOX_LIST_SUPPORT */
377	  rip_redistribute_unset (redist_type[i].type);
378	  return CMD_SUCCESS;
379        }
380    }
381
382  vty_out(vty, "Invalid type %s%s", argv[0],
383	  VTY_NEWLINE);
384
385  return CMD_WARNING;
386}
387#endif /* FOX_LIST_SUPPORT */
388
389#if defined(FOX_LIST_SUPPORT) && defined(FOX_CMD_SUPPORT)
390DEFUN (rip_redistribute_type_routemap,
391       rip_redistribute_type_routemap_cmd,
392       "redistribute (kernel|connected|static|ospf|bgp) route-map WORD",
393       "Redistribute information from another routing protocol\n"
394       "Kernel routes\n"
395       "Connected\n"
396       "Static routes\n"
397       "Open Shortest Path First (OSPF)\n"
398       "Border Gateway Protocol (BGP)\n"
399       "Route map reference\n"
400       "Pointer to route-map entries\n")
401{
402  int i;
403
404  for (i = 0; redist_type[i].str; i++) {
405    if (strncmp(redist_type[i].str, argv[0],
406		redist_type[i].str_min_len) == 0)
407      {
408	rip_routemap_set (redist_type[i].type, argv[1]);
409	zclient_redistribute_set (zclient, redist_type[i].type);
410	return CMD_SUCCESS;
411      }
412  }
413
414  vty_out(vty, "Invalid type %s%s", argv[0],
415	  VTY_NEWLINE);
416
417  return CMD_WARNING;
418}
419
420DEFUN (no_rip_redistribute_type_routemap,
421       no_rip_redistribute_type_routemap_cmd,
422       "no redistribute (kernel|connected|static|ospf|bgp) route-map WORD",
423       NO_STR
424       "Redistribute information from another routing protocol\n"
425       "Kernel routes\n"
426       "Connected\n"
427       "Static routes\n"
428       "Open Shortest Path First (OSPF)\n"
429       "Border Gateway Protocol (BGP)\n"
430       "Route map reference\n"
431       "Pointer to route-map entries\n")
432{
433  int i;
434
435  for (i = 0; redist_type[i].str; i++)
436    {
437      if (strncmp(redist_type[i].str, argv[0],
438		  redist_type[i].str_min_len) == 0)
439	{
440	  if (rip_routemap_unset (redist_type[i].type,argv[1]))
441	    return CMD_WARNING;
442	  rip_redistribute_unset (redist_type[i].type);
443	  return CMD_SUCCESS;
444        }
445    }
446
447  vty_out(vty, "Invalid type %s%s", argv[0],
448	  VTY_NEWLINE);
449
450  return CMD_WARNING;
451}
452
453DEFUN (rip_redistribute_type_metric,
454       rip_redistribute_type_metric_cmd,
455       "redistribute (kernel|connected|static|ospf|bgp) metric <0-16>",
456       "Redistribute information from another routing protocol\n"
457       "Kernel routes\n"
458       "Connected\n"
459       "Static routes\n"
460       "Open Shortest Path First (OSPF)\n"
461       "Border Gateway Protocol (BGP)\n"
462       "Metric\n"
463       "Metric value\n")
464{
465  int i;
466  int metric;
467
468  metric = atoi (argv[1]);
469
470  for (i = 0; redist_type[i].str; i++) {
471    if (strncmp(redist_type[i].str, argv[0],
472		redist_type[i].str_min_len) == 0)
473      {
474	rip_redistribute_metric_set (redist_type[i].type, metric);
475	zclient_redistribute_set (zclient, redist_type[i].type);
476	return CMD_SUCCESS;
477      }
478  }
479
480  vty_out(vty, "Invalid type %s%s", argv[0],
481	  VTY_NEWLINE);
482
483  return CMD_WARNING;
484}
485
486DEFUN (no_rip_redistribute_type_metric,
487       no_rip_redistribute_type_metric_cmd,
488       "no redistribute (kernel|connected|static|ospf|bgp) metric <0-16>",
489       NO_STR
490       "Redistribute information from another routing protocol\n"
491       "Kernel routes\n"
492       "Connected\n"
493       "Static routes\n"
494       "Open Shortest Path First (OSPF)\n"
495       "Border Gateway Protocol (BGP)\n"
496       "Metric\n"
497       "Metric value\n")
498{
499  int i;
500
501  for (i = 0; redist_type[i].str; i++)
502    {
503      if (strncmp(redist_type[i].str, argv[0],
504		  redist_type[i].str_min_len) == 0)
505	{
506	  if (rip_metric_unset (redist_type[i].type, atoi(argv[1])))
507	    return CMD_WARNING;
508	  rip_redistribute_unset (redist_type[i].type);
509	  return CMD_SUCCESS;
510        }
511    }
512
513  vty_out(vty, "Invalid type %s%s", argv[0],
514	  VTY_NEWLINE);
515
516  return CMD_WARNING;
517}
518
519DEFUN (no_rip_redistribute_type_metric_routemap,
520       no_rip_redistribute_type_metric_routemap_cmd,
521       "no redistribute (kernel|connected|static|ospf|bgp) metric <0-16> route-map WORD",
522       NO_STR
523       "Redistribute information from another routing protocol\n"
524       "Kernel routes\n"
525       "Connected\n"
526       "Static routes\n"
527       "Open Shortest Path First (OSPF)\n"
528       "Border Gateway Protocol (BGP)\n"
529       "Metric\n"
530       "Metric value\n"
531       "Route map reference\n"
532       "Pointer to route-map entries\n")
533{
534  int i;
535
536  for (i = 0; redist_type[i].str; i++)
537    {
538      if (strncmp(redist_type[i].str, argv[0],
539		  redist_type[i].str_min_len) == 0)
540	{
541	  if (rip_metric_unset (redist_type[i].type, atoi(argv[1])))
542	    return CMD_WARNING;
543	  if (rip_routemap_unset (redist_type[i].type, argv[2]))
544	    {
545	      rip_redistribute_metric_set(redist_type[i].type, atoi(argv[1]));
546	      return CMD_WARNING;
547	    }
548	  rip_redistribute_unset (redist_type[i].type);
549	  return CMD_SUCCESS;
550        }
551    }
552
553  vty_out(vty, "Invalid type %s%s", argv[0],
554	  VTY_NEWLINE);
555
556  return CMD_WARNING;
557}
558
559/* Default information originate. */
560
561DEFUN (rip_default_information_originate,
562       rip_default_information_originate_cmd,
563       "default-information originate",
564       "Control distribution of default route\n"
565       "Distribute a default route\n")
566{
567  struct prefix_ipv4 p;
568
569  if (! rip->default_information)
570    {
571      memset (&p, 0, sizeof (struct prefix_ipv4));
572      p.family = AF_INET;
573
574      rip->default_information = 1;
575
576      rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL);
577    }
578
579  return CMD_SUCCESS;
580}
581
582DEFUN (no_rip_default_information_originate,
583       no_rip_default_information_originate_cmd,
584       "no default-information originate",
585       NO_STR
586       "Control distribution of default route\n"
587       "Distribute a default route\n")
588{
589  struct prefix_ipv4 p;
590
591  if (rip->default_information)
592    {
593      memset (&p, 0, sizeof (struct prefix_ipv4));
594      p.family = AF_INET;
595
596      rip->default_information = 0;
597
598      rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
599    }
600
601  return CMD_SUCCESS;
602}
603#endif /* FOX_LIST_SUPPORT && FOX_CMD_SUPPORT */
604
605
606/* RIP configuration write function. */
607int
608config_write_zebra (struct vty *vty)
609{
610#ifdef FOX_CMD_SUPPORT
611  if (! zclient->enable)
612    {
613      vty_out (vty, "no router zebra%s", VTY_NEWLINE);
614      return 1;
615    }
616  else if (! zclient->redist[ZEBRA_ROUTE_RIP])
617    {
618      vty_out (vty, "router zebra%s", VTY_NEWLINE);
619      vty_out (vty, " no redistribute rip%s", VTY_NEWLINE);
620      return 1;
621    }
622#endif /* FOX_CMD_SUPPORT */
623  return 0;
624}
625
626int
627config_write_rip_redistribute (struct vty *vty, int config_mode)
628{
629#ifdef FOX_CMD_SUPPORT
630  int i;
631  char *str[] = { "system", "kernel", "connected", "static", "rip",
632		  "ripng", "ospf", "ospf6", "bgp"};
633
634  for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
635    if (i != zclient->redist_default && zclient->redist[i])
636      {
637	if (config_mode)
638	  {
639	    if (rip->route_map[i].metric_config)
640	      {
641		if (rip->route_map[i].name)
642		  vty_out (vty, " redistribute %s metric %d route-map %s%s",
643			   str[i], rip->route_map[i].metric,
644			   rip->route_map[i].name,
645			   VTY_NEWLINE);
646		else
647		  vty_out (vty, " redistribute %s metric %d%s",
648			   str[i], rip->route_map[i].metric,
649			   VTY_NEWLINE);
650	      }
651	    else
652	      {
653		if (rip->route_map[i].name)
654		  vty_out (vty, " redistribute %s route-map %s%s",
655			   str[i], rip->route_map[i].name,
656			   VTY_NEWLINE);
657		else
658		  vty_out (vty, " redistribute %s%s", str[i],
659			   VTY_NEWLINE);
660	      }
661	  }
662	else
663	  vty_out (vty, " %s", str[i]);
664      }
665#endif /* FOX_CMD_SUPPORT */
666  return 0;
667}
668
669/* Zebra node structure. */
670struct cmd_node zebra_node =
671{
672  ZEBRA_NODE,
673  "%s(config-router)# ",
674};
675
676void
677rip_zclient_init ()
678{
679  /* Set default value to the zebra client structure. */
680  zclient = zclient_new ();
681  zclient_init (zclient, ZEBRA_ROUTE_RIP);
682  zclient->interface_add = rip_interface_add;
683  zclient->interface_delete = rip_interface_delete;
684  zclient->interface_address_add = rip_interface_address_add;
685  zclient->interface_address_delete = rip_interface_address_delete;
686  zclient->ipv4_route_add = rip_zebra_read_ipv4;
687  zclient->ipv4_route_delete = rip_zebra_read_ipv4;
688  zclient->interface_up = rip_interface_up;
689  zclient->interface_down = rip_interface_down;
690
691  /* Install zebra node. */
692  install_node (&zebra_node, config_write_zebra);
693
694#if defined(FOX_CMD_SUPPORT) && defined(FOX_LIST_SUPPORT)
695  /* Install command elements to zebra node. */
696  install_element (CONFIG_NODE, &router_zebra_cmd);
697  install_element (CONFIG_NODE, &no_router_zebra_cmd);
698  install_default (ZEBRA_NODE);
699  install_element (ZEBRA_NODE, &rip_redistribute_rip_cmd);
700  install_element (ZEBRA_NODE, &no_rip_redistribute_rip_cmd);
701#endif /* FOX_CMD_SUPPORT && FOX_LIST_SUPPORT*/
702
703  /* Install command elements to rip node. */
704  install_element (RIP_NODE, &rip_redistribute_type_cmd);
705
706#if defined(FOX_CMD_SUPPORT) && defined(FOX_LIST_SUPPORT)
707  install_element (RIP_NODE, &rip_redistribute_type_routemap_cmd);
708  install_element (RIP_NODE, &rip_redistribute_type_metric_cmd);
709  install_element (RIP_NODE, &no_rip_redistribute_type_cmd);
710#endif /* (FOX_CMD_SUPPORT) && defined(FOX_LIST_SUPPORT) */
711
712#if defined(FOX_CMD_SUPPORT) && defined(FOX_LIST_SUPPORT)
713  install_element (RIP_NODE, &no_rip_redistribute_type_routemap_cmd);
714  install_element (RIP_NODE, &no_rip_redistribute_type_metric_cmd);
715  install_element (RIP_NODE, &no_rip_redistribute_type_metric_routemap_cmd);
716  install_element (RIP_NODE, &rip_default_information_originate_cmd);
717  install_element (RIP_NODE, &no_rip_default_information_originate_cmd);
718#endif /* (FOX_CMD_SUPPORT) && defined(FOX_LIST_SUPPORT) */
719}
720