* NET-3 Networking Distribution for the LINUX operating
* system.
*
- * Version: arp 1.69 (1996-05-17)
+ * Version: arp 1.82 (1997-09-25)
*
* Maintainer: Bernd 'eckes' Eckenfels, <net-tools@lina.inka.de>
*
* Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
*
* Changes:
+ * (based on work from Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>)
* Alan Cox : modified for NET3
* Andrew Tridgell : proxy arp netmasks
* Bernd Eckenfels : -n option
* {1.61} Bernd Eckenfels : more verbose messages
* {1.62} Bernd Eckenfels : check -t for hw adresses and try to
* explain EINVAL (jeff)
- *960125 {1.63} Bernd Eckenfels : -a print hardwarename instead of tiltle
- *960201 {1.64} Bernd Eckenfels : net-features.h support
- *960203 {1.65} Bernd Eckenfels : "#define" in "#if",
+ *970125 {1.63} Bernd Eckenfels : -a print hardwarename instead of tiltle
+ *970201 {1.64} Bernd Eckenfels : net-features.h support
+ *970203 {1.65} Bernd Eckenfels : "#define" in "#if",
* -H|-A additional to -t|-p
- *960214 {1.66} Bernd Eckenfels : Fix optarg required for -H and -A
- *960412 {1.67} Bernd Eckenfels : device=""; is default
- *960514 {1.68} Bernd Eckenfels : -N and -D
- *960517 {1.69} Bernd Eckenfels : usage() fixed
+ *970214 {1.66} Bernd Eckenfels : Fix optarg required for -H and -A
+ *970412 {1.67} Bernd Eckenfels : device=""; is default
+ *970514 {1.68} Bernd Eckenfels : -N and -D
+ *970517 {1.69} Bernd Eckenfels : usage() fixed
+ *970622 {1.70} Bernd Eckenfels : arp -d priv
+ *970106 {1.80} Bernd Eckenfels : new syntax without -D and with "dev <If>",
+ * ATF_MAGIC, ATF_DONTPUB support.
+ * Typo fix (Debian Bug#5728 Giuliano Procida)
+ *970803 {1.81} Bernd Eckenfels : removed junk comment line 1
+ *970925 {1.82} Bernd Eckenfels : include fix for libc6
+ *
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
+/* #include <linux/netdevice.h> */
+/* #include <linux/if_arp.h> */
#include <net/if_arp.h>
#include <stdlib.h>
#include <stdio.h>
char *Release = RELEASE,
- *Version = "arp 1.69 (1996-05-17)";
+ *Version = "arp 1.82 (1997-09-25)";
int opt_n = 0; /* do not resolve addresses */
int opt_N = 0; /* use symbolic names */
int opt_v = 0; /* debugging output flag */
int opt_D = 0; /* HW-address is devicename */
+int opt_e = 0; /* 0=BSD output, 1=new linux */
+int opt_a = 0; /* all entries, substring match */
struct aftype *ap; /* current address family */
struct hwtype *hw; /* current hardware type */
int sockfd=0; /* active socket descriptor */
char host[128];
struct arpreq req;
struct sockaddr sa;
+ int flags=0;
#if HAVE_NEW_SIOCSARP
struct arpreq_old old_req;
#endif
/* If a host has more than one address, use the correct one! */
memcpy((char *) &req.arp_pa, (char *) &sa, sizeof(struct sockaddr));
- req.arp_flags=0;
+ if (hw_set)
+ req.arp_ha.sa_family=hw->type;
- if (args[1]) {
- if (strcmp(args[1],"pub")==0)
- req.arp_flags|=ATF_PUBL;
- else
- usage();
+ req.arp_flags=ATF_PERM;
+ args++;
+ while (*args != NULL) {
+ if (opt_v) fprintf(stderr,"args=%s\n",*args);
+ if (! strcmp(*args, "pub")) {
+ flags |= 1;
+ args++;
+ continue;
+ }
+ if (! strcmp(*args, "priv")) {
+ flags |= 2;
+ args++;
+ continue;
+ }
+ if (! strcmp(*args, "temp")) {
+ req.arp_flags &= ~ATF_PERM;
+ args++;
+ continue;
+ }
+ if (! strcmp(*args, "trail")) {
+ req.arp_flags |= ATF_USETRAILERS;
+ args++;
+ continue;
+ }
+ if (! strcmp(*args, "dontpub")) {
+#ifdef HAVE_ATF_DONTPUB
+ req.arp_flags |= ATF_DONTPUB;
+#else
+ ENOSUPP("arp", "ATF_DONTPUB");
+#endif
+ args++;
+ continue;
+ }
+ if (! strcmp(*args, "auto")) {
+#ifdef HAVE_ATF_MAGIC
+ req.arp_flags |= ATF_MAGIC;
+#else
+ ENOSUPP("arp", "ATF_MAGIC");
+#endif
+ args++;
+ continue;
+ }
+ if (! strcmp(*args, "dev")) {
+ if (*++args == NULL) usage();
+ strncpy(device,*args,sizeof(device)-1);
+ device[sizeof(device)-1]='\0';
+ args++;
+ continue;
+ }
+ if (! strcmp(*args, "netmask")) {
+ if (*++args == NULL) usage();
+ if (strcmp(*args,"255.255.255.255") != 0) {
+ strcpy(host, *args);
+ if (ap->input(0, host, &sa) < 0) {
+ ap->herror(host);
+ return(-1);
+ }
+ memcpy((char *) &req.arp_netmask, (char *) &sa,
+ sizeof(struct sockaddr));
+ req.arp_flags |= ATF_NETMASK;
+ }
+ args++;
+ continue;
+ }
+ usage();
}
-
+ if (flags == 0)
+ flags = 3;
+
#if HAVE_NEW_SIOCSARP
strcpy(req.arp_dev,device);
- memcpy((char *)&old_req,(char *)&req,sizeof(old_req));
/* Call the kernel. */
- if (opt_v) fprintf(stderr,"arp: SIOCDARP()\n");
- if (ioctl(sockfd, SIOCDARP, &req) < 0) {
- if (errno == EINVAL) {
- if (opt_v) fprintf(stderr,"arp: OLD_SIOCDARP()\n");
- if (ioctl(sockfd, OLD_SIOCDARP, &old_req) < 0) {
- if (errno != ENXIO) {
- perror("OLD_SIOCSARP");
- return(-1);
+ if (flags & 2) {
+ if (opt_v) fprintf(stderr,"arp: SIOCDARP(nopub)\n");
+ if (ioctl(sockfd, SIOCDARP, &req) < 0) {
+ if (errno == EINVAL) {
+ if (opt_v) fprintf(stderr,"arp: OLD_SIOCDARP(priv)\n");
+ memcpy((char *)&old_req,(char *)&req,sizeof(old_req));
+ if (ioctl(sockfd, OLD_SIOCDARP, &old_req) < 0) {
+ if (errno != ENXIO) {
+ perror("OLD_SIOCSARP(priv)");
+ return(-1);
+ }
+ } else {
+ return(0);
}
- } else {
- return(0);
}
- }
- if (errno == ENXIO) {
- printf(NLS_CATGETS(catfd, arpSet, arp_no_arp,
- "No ARP entry for %s\n"), host);
+ if (errno == ENXIO) {
+ if (flags & 1)
+ goto nopub;
+ printf(NLS_CATGETS(catfd, arpSet, arp_no_arp,
+ "No ARP entry for %s\n"), host);
+ return(-1);
+ }
+ perror("SIOCDARP(priv)");
return(-1);
- }
- perror("SIOCDARP");
- return(-1);
+ }
+ }
+ if (flags & 1) {
+nopub:
+ req.arp_flags |= ATF_PUBL;
+ if (opt_v) fprintf(stderr,"arp: SIOCDARP(pub)\n");
+ if (ioctl(sockfd, SIOCDARP, &req) < 0) {
+ if (errno == EINVAL) {
+ if (opt_v) fprintf(stderr,"arp: OLD_SIOCDARP(pub)\n");
+ memcpy((char *)&old_req,(char *)&req,sizeof(old_req));
+ if (ioctl(sockfd, OLD_SIOCDARP, &old_req) < 0) {
+ if (errno != ENXIO) {
+ perror("OLD_SIOCSARP(pub)");
+ return(-1);
+ }
+ } else {
+ return(0);
+ }
+ }
+ if (errno == ENXIO) {
+ printf(NLS_CATGETS(catfd, arpSet, arp_no_arp,
+ "No ARP entry for %s\n"), host);
+ return(-1);
+ }
+ perror("SIOCDARP(pub)");
+ return(-1);
+ }
}
#else
/* Call the kernel. */
/* Check out any modifiers. */
flags = ATF_PERM;
while (*args != NULL) {
- if (! strcmp(*args, "temp")) flags &= ~ATF_PERM;
- if (! strcmp(*args, "pub")) flags |= ATF_PUBL;
-/* if (! strcmp(*args, "rarp")) flags |= ATF_RARP;*/
- if (! strcmp(*args, "trail")) flags |= ATF_USETRAILERS;
- if (! strcmp(*args, "netmask"))
- {
- if (*++args == NULL) usage();
- if (strcmp(*args,"255.255.255.255") != 0)
- {
- strcpy(host, *args);
- if (ap->input(0, host, &sa) < 0) {
- ap->herror(host);
- return(-1);
- }
- memcpy((char *) &req.arp_netmask, (char *) &sa,
- sizeof(struct sockaddr));
- flags |= ATF_NETMASK;
- }
- }
- args++;
- }
+ if (! strcmp(*args, "temp")) {
+ flags &= ~ATF_PERM;
+ args++;
+ continue;
+ }
+ if (! strcmp(*args, "pub")) {
+ flags |= ATF_PUBL;
+ args++;
+ continue;
+ }
+ if (! strcmp(*args, "priv")) {
+ flags &= ~ATF_PUBL;
+ args++;
+ continue;
+ }
+ if (! strcmp(*args, "trail")) {
+ flags |= ATF_USETRAILERS;
+ args++;
+ continue;
+ }
+ if (! strcmp(*args, "dontpub")) {
+#ifdef HAVE_ATF_DONTPUB
+ flags |= ATF_DONTPUB;
+#else
+ ENOSUPP("arp", "ATF_DONTPUB");
+#endif
+ args++;
+ continue;
+ }
+
+ if (! strcmp(*args, "auto")) {
+#ifdef HAVE_ATF_MAGIC
+ flags |= ATF_MAGIC;
+#else
+ ENOSUPP("arp", "ATF_MAGIC");
+#endif
+ args++;
+ continue;
+ }
+ if (! strcmp(*args, "dev")) {
+ if (*++args == NULL) usage();
+ strncpy(device,*args,sizeof(device)-1);
+ device[sizeof(device)-1]='\0';
+ args++;
+ continue;
+ }
- if ((flags & ATF_NETMASK) && !(flags & ATF_PUBL))
- usage();
+ if (! strcmp(*args, "netmask")) {
+ if (*++args == NULL) usage();
+ if (strcmp(*args,"255.255.255.255") != 0) {
+ strcpy(host, *args);
+ if (ap->input(0, host, &sa) < 0) {
+ ap->herror(host);
+ return(-1);
+ }
+ memcpy((char *) &req.arp_netmask, (char *) &sa,
+ sizeof(struct sockaddr));
+ flags |= ATF_NETMASK;
+ }
+ args++;
+ continue;
+ }
+ usage();
+ }
/* Fill in the remainder of the request. */
req.arp_flags = flags;
perror("SIOCSARP and OLD_SIOCSARP");
if (flags & ATF_PUBL)
fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_einv_pub,
- "Probably destination is reached via ARP Interface. See arp(8)\n"));
+ "Probably route to destination points to interface. See arp(8)\n"));
else
fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_einv_nopub,
- "Probably destination is on different Interface. See arp(8)\n"));
+ "No ARP Support or route to destination points to other interface. See arp(8)\n"));
return(-1);
}
}
/* Print the contents of an ARP request block. */
static void
-arp_disp_2(char *ip,int type,int arp_flags,char *hwa,char *mask,char *dev)
+arp_disp_2(char *name,int type,int arp_flags,char *hwa,char *mask,char *dev)
{
static int title = 0;
struct hwtype *xhw;
- struct aftype *xap;
- char *sp;
- struct sockaddr sap;
- char flags[6];
+ char flags[10];
xhw = get_hwntype(type);
if (xhw == NULL)
- xhw = get_hwtype("ether");
-/*
- * xap = get_afntype(req->arp_pa.sa_family);
- * if (xap == NULL)
- */
- xap = get_aftype("inet");
+ xhw = get_hwtype(DFLT_HW);
if (title++ == 0) {
printf(NLS_CATGETS(catfd, arpSet, arp_address,
if (arp_flags & ATF_COM) strcat(flags, "C");
if (arp_flags & ATF_PERM) strcat(flags, "M");
if (arp_flags & ATF_PUBL) strcat(flags, "P");
-/* if (arp_flags & ATF_RARP) strcat(flags, "R");*/
+#ifdef HAVE_ATF_MAGIC
+ if (arp_flags & ATF_MAGIC) strcat(flags, "A");
+#endif
+#ifdef HAVE_ATF_DONTPUB
+ if (arp_flags & ATF_DONTPUB) strcat(flags, "!");
+#endif
if (arp_flags & ATF_USETRAILERS) strcat(flags, "T");
- /* This IS ugly but it works -be */
- if (xap->input(0, ip,&sap) < 0)
- sp=ip;
- else
- sp = xap->sprint(&sap, opt_n);
+ if (!(arp_flags & ATF_NETMASK)) mask="";
+
+ printf("%-23.23s\t", name);
+
+ if (!(arp_flags & ATF_COM)) {
+ if (arp_flags & ATF_PUBL)
+ printf("%-8.8s%-20.20s","*","*");
+ else
+ printf("%-8.8s%-20.20s","","(incomplete)");
+ } else {
+ printf("%-8.8s%-20.20s", xhw->name, hwa);
+ }
+
+ printf("%-6.6s%-15.15s %s\n", flags,mask,dev);
+}
+
+/* Print the contents of an ARP request block. */
+static void
+arp_disp(char *name, char *ip, int type,int arp_flags,char *hwa,char *mask,char *dev)
+{
+ struct hwtype *xhw;
+
+ xhw = get_hwntype(type);
+ if (xhw == NULL)
+ xhw = get_hwtype(DFLT_HW);
+
+
+
+ printf("%s (%s) at ", name, ip);
+
+ if (!(arp_flags & ATF_COM)) {
+ if (arp_flags & ATF_PUBL)
+ printf("* ");
+ else
+ printf("<incomplete> ");
+ } else {
+ printf("%s [%s] ", hwa, xhw->name);
+ }
- printf("%-23.23s\t%-8.8s", sp, xhw->name);
- printf("%-20.20s%-6.6s%-15.15s %s\n", hwa, flags,mask,dev);
+ if (arp_flags & ATF_NETMASK)
+ printf("netmask %s ", mask);
+
+ if (arp_flags & ATF_PERM) printf("PERM ");
+ if (arp_flags & ATF_PUBL) printf("PUP ");
+#ifdef HAVE_ATF_MAGIC
+ if (arp_flags & ATF_MAGIC) printf("AUTO ");
+#endif
+#ifdef HAVE_ATF_DONTPUB
+ if (arp_flags & ATF_DONTPUB) printf("DONTPUB ");
+#endif
+ if (arp_flags & ATF_USETRAILERS) printf("TRAIL ");
+
+ printf("on %s\n", dev);
}
char dev[100];
int type,flags;
FILE *fp;
+ char *hostname;
int num,entries=0,showed=0;
host[0]='\0';
/* if the user specified device differs, skip it */
if (device[0] && strcmp(dev,device))
continue;
- showed++;
- arp_disp_2(ip,type,flags,hwa,mask,dev);
+
+ showed++;
+ /* This IS ugly but it works -be */
+ if (opt_n)
+ hostname="?";
+ else {
+ if (ap->input(0, ip,&sa) < 0)
+ hostname=ip;
+ else
+ hostname = ap->sprint(&sa, opt_n | 0x8000);
+ if (strcmp(hostname, ip)==0)
+ hostname="?";
+ }
+
+ if (opt_e)
+ arp_disp_2(hostname[0]=='?'?ip:hostname,type,flags,hwa,mask,dev);
+ else
+ arp_disp(hostname,ip,type,flags,hwa,mask,dev);
}
}
if (opt_v)
printf(NLS_CATGETS(catfd, arpSet, arp_sum,
- "Entries: %d\tSkiped: %d\tFound: %d\n"),entries,entries-showed,showed);
+ "Entries: %d\tSkipped: %d\tFound: %d\n"),entries,entries-showed,showed);
- if (!showed && (hw_set || host[0] || device[0]))
- printf(NLS_CATGETS(catfd, arpSet, arp_none,
- "arp: in %d entries no match found.\n"),entries);
+ if (!showed) {
+ if (host[0] && !opt_a)
+ printf("%s (%s) -- no entry\n", name, host);
+ else if (hw_set || host[0] || device[0]) {
+ printf(NLS_CATGETS(catfd, arpSet, arp_none,
+ "arp: in %d entries no match found.\n"),entries);
+ }
+ }
(void) fclose(fp);
return(0);
}
fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_usage1,
"Usage: arp [-vn] [-H type] [-i if] -a [hostname]\n"));
fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_usage2,
- " arp [-v] [-i if] -d hostname [pub]\n"));
+ " arp [-v] [-i if] -d hostname [pub][nopub]\n"));
fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_usage3,
- " arp [-v] [-H type] [-i if] -s hostname hw_addr [temp]\n"));
+ " arp [-v] [-H type] [-i if] -s hostname hw_addr [temp][nopub]\n"));
fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_usage4,
" arp [-v] [-H type] [-i if] -s hostname hw_addr [netmask nm] pub\n"));
fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_usage5,
{
{"verbose", 0, 0, 'v'},
{"version", 0, 0, 'V'},
- {"display", 0, 0, 'a'},
+ {"all", 0, 0, 'a'},
{"delete", 0, 0, 'd'},
{"file", 0, 0, 'f'},
{"numeric", 0, 0, 'n'},
NLS_CATCLOSE(catfd)
return(-1);
}
- what = -1;
+ what = 0;
/* Fetch the command-line arguments. */
/* opterr = 0; */
- while ((i = getopt_long(argc, argv, "A:H:adfp:nsi:t:vh?DNV",longopts, &lop)) != EOF) switch(i) {
+ while ((i = getopt_long(argc, argv, "A:H:adfp:nsei:t:vh?DNV",longopts, &lop)) != EOF) switch(i) {
case 'a':
what = 1;
+ opt_a = 1;
+ break;
+ case 'f':
+ what = 2;
break;
-
case 'd':
what = 3;
break;
-
- case 'f':
- what = 2;
+ case 's':
+ what = 4;
break;
+
+ case 'e':
+ opt_e = 1;
+ break;
case 'n':
opt_n = FLAG_NUM;
break;
opt_N = FLAG_SYM;
fprintf(stderr,"arp: -N not yet supported.\n");
break;
+ case 'v':
+ opt_v = 1;
+ break;
+
case 'A':
case 'p':
ap = get_aftype(optarg);
exit(-1);
}
break;
-
- case 's':
- what = 4;
- break;
-
case 'H':
case 't':
hw = get_hwtype(optarg);
device[sizeof(device)-1]='\0';
break;
- case 'v':
- opt_v = 1;
- break;
-
case 'V':
version();
-
case '?':
case 'h':
default:
/* Now see what we have to do here... */
switch(what) {
+ case 0:
+ opt_e = 1;
+ what = arp_show(argv[optind]);
+ break;
+
case 1: /* show an ARP entry in the cache */
what = arp_show(argv[optind]);
break;
#endif /* HAVE_AFINET6 */
-#ifndef IFF_PORTSEL
-#define IFF_PORTSEL 0x2000
-#define IFF_AUTOMEDIA 0x4000
-#endif
-
-#ifndef SIOCSIFTXQLEN /* 2.1.77+ option */
-#define SIOCGIFTXQLEN 0x8942 /* Get the tx queue length */
-#define SIOCSIFTXQLEN 0x8943 /* Set the tx queue length */
-#endif
+/* Check for supported features */
-#ifndef ifr_qlen
-#define ifr_qlen ifr_ifru.ifru_ivalue /* Queue length */
+#if defined(SIOCSIFTXQLEN) && defined(ifr_qlen)
+#define HAVE_TXQUEUELEN
#endif
/* This is from <linux/netdevice.h>. */
{ NULL, NULL, NULL, NULL },
};
-/* Not all kernels have these new ioctls. */
-#ifndef SIOGIFNAME
-#define SIOGIFNAME 0x8934 /* if_index -> name mapping */
-#endif
-#ifndef SIOCDIFADDR
-#define SIOCDIFADDR 0x8936 /* delete PA address */
-#endif
-
#if HAVE_AFIPX
#include "ipx.h"
#endif
ptr->hwaddr[4] || ptr->hwaddr[5])))
printf(NLS_CATGETS(catfd, ifconfigSet, ifconfig_hw, "HWaddr %s ")
, hw->print(ptr->hwaddr));
+#ifdef IFF_PORTSEL
if (ptr->flags & IFF_PORTSEL)
printf("Media:%s%s", if_port_text[ptr->map.port][0],
(ptr->flags & IFF_AUTOMEDIA)?"(auto)":"");
+#endif
printf("\n");
#if HAVE_AFINET6
if (ap->af != AF_INET6) {
if (ptr->flags & IFF_MULTICAST) printf("MULTICAST ");
printf(NLS_CATGETS(catfd, ifconfigSet, ifconfig_mtu, " MTU:%d Metric:%d\n"),
ptr->mtu, ptr->metric?ptr->metric:1);
- /* XXX: Merge this with the previous line, but I don't want to touch the
- * NLS stuff yet. */
if (ptr->tx_queue_len != -1)
- printf("TXQUEUELEN: %d\n", ptr->tx_queue_len);
+ printf(" txqueuelen:%d\n", ptr->tx_queue_len);
/* If needed, display the interface statistics. */
printf(" ");
else
ife->map = ifr.ifr_map;
+#ifdef HAVE_TXQUEUELEN
strcpy(ifr.ifr_name, ifname);
if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) < 0)
ife->tx_queue_len = -1; /* unknown value */
else
ife->tx_queue_len = ifr.ifr_qlen;
+#else
+ ife->tx_queue_len = -1; /* unknown value */
+#endif
#if HAVE_AFINET
strcpy(ifr.ifr_name, ifname);
fprintf(stderr, " [[family] address]\n");
#if HAVE_AFINET6
fprintf(stderr, " [add inet6address/prefixlen]\n");
+#ifdef SIOCDIFADDR
fprintf(stderr, " [del inet6address/prefixlen]\n");
+#endif
fprintf(stderr, " [tunnel aa.bb.cc.dd]\n");
#endif
#if HAVE_AFINET
fprintf(stderr, " [multicast]\n");
fprintf(stderr, " [mem_start NN] [io_addr NN] [irq NN]\n");
fprintf(stderr, " [media type]\n");
+#ifdef HAVE_TXQUEUELEN
fprintf(stderr, " [txqueuelen len]\n");
+#endif
fprintf(stderr, " [up] [down] ...\n");
NLS_CATCLOSE(catfd)
exit(1);
continue;
}
+#ifdef HAVE_TXQUEUELEN
if (!strcmp(*spp, "txqueuelen")) {
if (*++spp == NULL) usage();
ifr.ifr_qlen = strtoul(*spp, NULL, 0);
spp++;
continue;
}
+#endif
if (!strcmp(*spp, "mem_start")) {
if (*++spp == NULL) usage();
ifr6.ifr6_ifindex = ifr.ifr_ifindex;
ifr6.ifr6_prefixlen = prefix_len;
+#ifdef SIOCDIFADDR
if (ioctl(inet6_sock, SIOCDIFADDR, &ifr6) < 0) {
fprintf(stderr, "SIOCDIFADDR: %s\n",
strerror(errno));
goterr = 1;
}
+#else
+ fprintf(stderr, "Address deletion not supported on this system.\n");
+#endif
spp++;
continue;
}