Revision: 14917
Author:   adrian.chadd
Date:     Thu Jul 14 04:10:35 2011
Log:      Pass 1 of the ICMPv6'ifying pinger.

* extract out the ICMPv4 related stuff, throw in libpinger
* break apart "assemble and send ICMPv4 packet" and "populate icmpSendEcho bits"
  so to enforce sensible API layering.


http://code.google.com/p/lusca-cache/source/detail?r=14917

Added:
 /playpen/LUSCA_HEAD_ipv6/libpinger
 /playpen/LUSCA_HEAD_ipv6/libpinger/Makefile.am
 /playpen/LUSCA_HEAD_ipv6/libpinger/icmp_v4.c
 /playpen/LUSCA_HEAD_ipv6/libpinger/icmp_v4.h
 /playpen/LUSCA_HEAD_ipv6/libpinger/icmp_v6.c
 /playpen/LUSCA_HEAD_ipv6/libpinger/icmp_v6.h
Modified:
 /playpen/LUSCA_HEAD_ipv6/Makefile.am
 /playpen/LUSCA_HEAD_ipv6/configure.in
 /playpen/LUSCA_HEAD_ipv6/src/Makefile.am
 /playpen/LUSCA_HEAD_ipv6/src/pinger.c

=======================================
--- /dev/null
+++ /playpen/LUSCA_HEAD_ipv6/libpinger/Makefile.am      Thu Jul 14 04:10:35 2011
@@ -0,0 +1,10 @@
+## Process this file with automake to produce Makefile.in
+
+INCLUDES       = -I. -I$(top_builddir)
+
+libpinger_a_SOURCES = \
+       icmp_v4.c \
+       icmp_v6.c
+
+noinst_LIBRARIES = \
+       libpinger.a
=======================================
--- /dev/null
+++ /playpen/LUSCA_HEAD_ipv6/libpinger/icmp_v4.c        Thu Jul 14 04:10:35 2011
@@ -0,0 +1,194 @@
+/*
+ * $Id$
+ *
+ * DEBUG: section 42    ICMP/Pinger
+ * AUTHOR: Harvest Derived
+ *
+ * SQUID Web Proxy Cache          http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ *  Squid is the result of efforts by numerous individuals from
+ *  the Internet community; see the CONTRIBUTORS file for full
+ *  details.   Many organizations have provided support for Squid's
+ *  development; see the SPONSORS file for full details.  Squid is
+ *  Copyrighted (C) 2001 by the Regents of the University of
+ *  California; see the COPYRIGHT file for full details.  Squid
+ *  incorporates software developed and/or copyrighted by other
+ *  sources; see the CREDITS file for full details.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+
+#include "../include/config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#if !defined(_SQUID_WIN32_)
+
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+
+#define PINGER_TIMEOUT 10
+
+#else /* _SQUID_WIN32_ */
+
+#ifdef _SQUID_MSWIN_
+
+#if HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif
+#include <process.h>
+
+#define PINGER_TIMEOUT 5
+
+static SOCKET socket_to_squid = -1;
+#define socket_from_squid socket_to_squid
+
+#else /* _SQUID_MSWIN */
+
+/* Cygwin */
+
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+
+#define PINGER_TIMEOUT 10
+
+static int socket_from_squid = 0;
+static int socket_to_squid = 1;
+
+#endif /* _SQUID_MSWIN_ */
+
+#endif /* _SQUID_WIN32_ */
+
+#include "include/util.h"
+#include "libcore/tools.h"
+#include "libsqdebug/debug.h"
+
+#include "icmp_v4.h"
+
+/* IPv4 ICMP type strings */
+
+const char *icmpPktStr[] =
+{
+    "Echo Reply",
+    "ICMP 1",
+    "ICMP 2",
+    "Destination Unreachable",
+    "Source Quench",
+    "Redirect",
+    "ICMP 6",
+    "ICMP 7",
+    "Echo",
+    "ICMP 9",
+    "ICMP 10",
+    "Time Exceeded",
+    "Parameter Problem",
+    "Timestamp",
+    "Timestamp Reply",
+    "Info Request",
+    "Info Reply",
+    "Out of Range Type"
+};
+
+int icmp_ident = -1;
+int icmp_pkts_sent = 0;
+
+static int
+in_cksum(unsigned short *ptr, int size)
+{
+    long sum;
+    unsigned short oddbyte;
+    unsigned short answer;
+    sum = 0;
+    while (size > 1) {
+        sum += *ptr++;
+        size -= 2;
+    }
+    if (size == 1) {
+        oddbyte = 0;
+        *((unsigned char *) &oddbyte) = *(unsigned char *) ptr;
+        sum += oddbyte;
+    }
+    sum = (sum >> 16) + (sum & 0xffff);
+    sum += (sum >> 16);
+    answer = (unsigned short) ~sum;
+    return (answer);
+}
+
+/*
+ * Assemble an IPv4 ICMP Echo packet.
+ *
+ * This doesn't know about the payload layout; it simply assembles the
+ * packet and fires it off.
+ */
+void
+pingerv4SendEcho(int icmp_sock, struct in_addr to, int opcode, char *payload,
+  int len)
+{
+    LOCAL_ARRAY(char, pkt, MAX_PKT_SZ);
+    struct icmphdr *icmp = NULL;
+
+    int icmp_pktsize = sizeof(struct icmphdr);
+    struct sockaddr_in S;
+    memset(pkt, '\0', MAX_PKT_SZ);
+    icmp = (struct icmphdr *) (void *) pkt;
+
+    /*
+     * cevans - beware signed/unsigned issues in untrusted data from
+     * the network!!
+     */
+    if (len < 0) {
+        len = 0;
+    }
+    icmp->icmp_type = ICMP_ECHO;
+    icmp->icmp_code = 0;
+    icmp->icmp_cksum = 0;
+    icmp->icmp_id = icmp_ident;
+    icmp->icmp_seq = (u_short) icmp_pkts_sent++;
+
+    /* The ICMP payload is the entire 'payload' + 'len' */
+    /* The caller will setup the tmimestamp and icmpEchoData */
+
+    if (payload) {
+        if (len > MAX_PAYLOAD)
+            len = MAX_PAYLOAD;
+        xmemcpy(pkt + sizeof(struct icmphdr), payload, len);
+        icmp_pktsize += len;
+    }
+
+    icmp->icmp_cksum = in_cksum((u_short *) icmp, icmp_pktsize);
+    S.sin_family = AF_INET;
+    /*
+     * cevans: alert: trusting to-host, was supplied in network packet
+     */
+    S.sin_addr = to;
+    S.sin_port = 0;
+    assert(icmp_pktsize <= MAX_PKT_SZ);
+    sendto(icmp_sock,
+      pkt,
+      icmp_pktsize,
+      0,
+      (struct sockaddr *) &S,
+      sizeof(struct sockaddr_in));
+}
+
=======================================
--- /dev/null
+++ /playpen/LUSCA_HEAD_ipv6/libpinger/icmp_v4.h        Thu Jul 14 04:10:35 2011
@@ -0,0 +1,99 @@
+#ifndef        __LIBPINGER_ICMP_V4_H__
+#define        __LIBPINGER_ICMP_V4_H__
+
+
+
+#if    defined(_SQUID_WIN32_)
+
+/*
+ * Native Windows port doesn't have netinet support, so we emulate it.
+ * At this time, Cygwin lacks icmp support in its include files, so we need
+ * to use the native Windows port definitions.
+ */
+
+#define ICMP_ECHO 8
+#define ICMP_ECHOREPLY 0
+
+typedef struct iphdr {
+    u_int8_t ip_vhl:4;>.>......./* Length of the header in dwords */
+    u_int8_t version:4;>>......./* Version of IP                  */
+    u_int8_t tos;>......>......./* Type of service                */
+    u_int16_t total_len;>......./* Length of the packet in dwords */
+    u_int16_t ident;>...>......./* unique identifier              */
+    u_int16_t flags;>...>......./* Flags                          */
+    u_int8_t ip_ttl;>...>......./* Time to live                   */
+    u_int8_t proto;>....>......./* Protocol number (TCP, UDP etc) */
+    u_int16_t checksum;>>......./* IP checksum                    */
+    u_int32_t source_ip;
+    u_int32_t dest_ip;
+} iphdr;
+
+/* ICMP header */
+typedef struct icmphdr {
+    u_int8_t icmp_type;>>......./* ICMP packet type                 */
+    u_int8_t icmp_code;>>......./* Type sub code                    */
+    u_int16_t icmp_cksum;
+    u_int16_t icmp_id;
+    u_int16_t icmp_seq;
+    u_int32_t timestamp;>......./* not part of ICMP, but we need it */
+} icmphdr;
+
+#endif /* _SQUID_WIN32_ */
+
+/*
+ * Linux short-cuts
+ */
+#if    defined (_SQUID_LINUX_)
+#ifdef         icmp_id
+#undef         icmp_id
+#endif
+#ifdef         icmp_seq
+#undef         icmp_seq
+#endif
+#define                icmp_type       type
+#define                icmp_code       code
+#define                icmp_cksum      checksum
+#define                icmp_id un.echo.id
+#define                icmp_seq        un.echo.sequence
+#define                ip_hl   ihl
+#define                ip_v    version
+#define                ip_tos  tos
+#define                ip_len  tot_len
+#define                ip_id   id
+#define                ip_off  frag_off
+#define                ip_ttl  ttl
+#define                ip_p    protocol
+#define                ip_sum  check
+#define                ip_src  saddr
+#define                ip_dst  daddr
+#endif
+
+/*
+ * BSDisms?
+ */
+#ifndef        _SQUID_LINUX_
+#ifndef                _SQUID_WIN32_
+#define                        icmphdr icmp
+#define                        iphdr   ip
+#endif
+#endif
+
+#if    ALLOW_SOURCE_PING
+#define        MAX_PKT_SZ 8192
+#define        MAX_PAYLOAD     (MAX_PKT_SZ - sizeof(struct icmphdr) - \
+                           sizeof (char) - sizeof(struct timeval) - 1)
+#else
+#define        MAX_PAYLOAD     SQUIDHOSTNAMELEN
+#define        MAX_PKT_SZ      (MAX_PAYLOAD + sizeof(struct timeval) + \
+                           sizeof (char) + sizeof(struct icmphdr) + 1)
+#endif
+
+extern const char *icmpPktStr[];
+
+extern int icmp_ident;
+extern int icmp_pkts_sent;
+
+extern void pingerv4SendEcho(int sock, struct in_addr to, int opcode,
+  char *payload, int len);
+
+#endif /* __LIBPINGER_ICMP_V4_H__ */
=======================================
--- /playpen/LUSCA_HEAD_ipv6/Makefile.am        Tue Aug 31 09:02:21 2010
+++ /playpen/LUSCA_HEAD_ipv6/Makefile.am        Thu Jul 14 04:10:35 2011
@@ -4,8 +4,8 @@
 #

 AUTOMAKE_OPTIONS = dist-bzip2 subdir-objects 1.5
-DIST_SUBDIRS = lib libcore libmem libsqname libcb libiapp libstat libsqftp libsqurl libhttp libsqdns libsqident libsqinet libhelper libmime libsqdebug libstmem libasyncio libsqtlv libsqstore snmplib scripts src icons errors contrib doc helpers tools app test-suite -SUBDIRS = lib libcore libmem libsqname libcb libiapp libstat libsqftp libsqurl libhttp libsqdns libsqident libsqinet libhelper libmime libsqdebug libstmem libasyncio libsqtlv libsqstore @makesnmplib@ scripts src icons errors doc helpers tools app test-suite +DIST_SUBDIRS = lib libcore libmem libsqname libcb libiapp libstat libsqftp libsqurl libhttp libsqdns libsqident libsqinet libhelper libmime libsqdebug libstmem libasyncio libsqtlv libsqstore libpinger snmplib scripts src icons errors contrib doc helpers tools app test-suite +SUBDIRS = lib libcore libmem libsqname libcb libiapp libstat libsqftp libsqurl libhttp libsqdns libsqident libsqinet libhelper libmime libsqdebug libstmem libasyncio libsqtlv libsqstore libpinger @makesnmplib@ scripts src icons errors doc helpers tools app test-suite

 DISTCLEANFILES = include/stamp-h include/stamp-h[0-9]*
DEFAULT_PINGER = $(libexecdir)/`echo pinger | sed '$(transform);s/$$/$(EXEEXT)/'`
=======================================
--- /playpen/LUSCA_HEAD_ipv6/configure.in       Tue Aug 31 09:02:21 2010
+++ /playpen/LUSCA_HEAD_ipv6/configure.in       Thu Jul 14 04:10:35 2011
@@ -3331,6 +3331,7 @@
        app/ufs_rebuild/Makefile \
        app/ufs_newfs/Makefile \
        app/tcptest/Makefile \
+       libpinger/Makefile \
        libsqstore/Makefile \
        libsqtlv/Makefile \
        libmime/Makefile \
=======================================
--- /playpen/LUSCA_HEAD_ipv6/src/Makefile.am    Sat Jul  2 02:29:37 2011
+++ /playpen/LUSCA_HEAD_ipv6/src/Makefile.am    Thu Jul 14 04:10:35 2011
@@ -317,7 +317,7 @@
 data_DATA = \
        mib.txt

-LDADD = -L../lib -L../libcore -L../libsqdebug -L../libmem -L../libsqname -L../libcb -L../libhelper -L../libmime -L../libstmem -L../libiapp -L../libsqftp -L../libsqurl -L../libhttp -L../libstat -L../libsqdns -L../libsqident -L../libsqinet -L../libasyncio -L../libsqtlv -L../libsqstore -lsqstore -lsqtlv -lasyncio -lsqinet -lsqdns -lsqdebug -lcore -lmem -lsqname -lcb -lsqident -lhelper -lmime -lstmem -liapp -lsqftp -lsqurl -lhttp -lstat -lmiscutil @XTRA_LIBS@ +LDADD = -L../lib -L../libcore -L../libsqdebug -L../libmem -L../libsqname -L../libcb -L../libhelper -L../libmime -L../libstmem -L../libiapp -L../libsqftp -L../libsqurl -L../libhttp -L../libstat -L../libsqdns -L../libsqident -L../libsqinet -L../libasyncio -L../libsqtlv -L../libsqstore -L../libpinger -lpinger -lsqstore -lsqtlv -lasyncio -lsqinet -lsqdns -lsqdebug -lcore -lmem -lsqname -lcb -lsqident -lhelper -lmime -lstmem -liapp -lsqftp -lsqurl -lhttp -lstat -lmiscutil @XTRA_LIBS@

 EXTRA_DIST = \
        cf_gen_defines \
=======================================
--- /playpen/LUSCA_HEAD_ipv6/src/pinger.c       Wed Jul 13 02:00:28 2011
+++ /playpen/LUSCA_HEAD_ipv6/src/pinger.c       Thu Jul 14 04:10:35 2011
@@ -70,7 +70,9 @@
 static SOCKET socket_to_squid = -1;
 #define socket_from_squid socket_to_squid

-#else /* _SQUID_CYGWIN_ */
+#else /* _SQUID_MSWIN */
+
+/* Cygwin */

 #include <netinet/in_systm.h>
 #include <netinet/in.h>
@@ -82,76 +84,12 @@
 static int socket_from_squid = 0;
 static int socket_to_squid = 1;

-#endif
-
-#define ICMP_ECHO 8
-#define ICMP_ECHOREPLY 0
-
-typedef struct iphdr {
-    u_int8_t ip_vhl:4;         /* Length of the header in dwords */
-    u_int8_t version:4;                /* Version of IP                  */
-    u_int8_t tos;              /* Type of service                */
-    u_int16_t total_len;       /* Length of the packet in dwords */
-    u_int16_t ident;           /* unique identifier              */
-    u_int16_t flags;           /* Flags                          */
-    u_int8_t ip_ttl;           /* Time to live                   */
-    u_int8_t proto;            /* Protocol number (TCP, UDP etc) */
-    u_int16_t checksum;                /* IP checksum                    */
-    u_int32_t source_ip;
-    u_int32_t dest_ip;
-} iphdr;
-
-/* ICMP header */
-typedef struct icmphdr {
-    u_int8_t icmp_type;                /* ICMP packet type                 */
-    u_int8_t icmp_code;                /* Type sub code                    */
-    u_int16_t icmp_cksum;
-    u_int16_t icmp_id;
-    u_int16_t icmp_seq;
-    u_int32_t timestamp;       /* not part of ICMP, but we need it */
-} icmphdr;
-
 #endif /* _SQUID_MSWIN_ */

-#ifndef _SQUID_LINUX_
-#ifndef _SQUID_WIN32_
-#define icmphdr icmp
-#define iphdr ip
-#endif
-#endif
-
-#if defined (_SQUID_LINUX_)
-#ifdef icmp_id
-#undef icmp_id
-#endif
-#ifdef icmp_seq
-#undef icmp_seq
-#endif
-#define icmp_type type
-#define icmp_code code
-#define icmp_cksum checksum
-#define icmp_id un.echo.id
-#define icmp_seq un.echo.sequence
-#define ip_hl ihl
-#define ip_v version
-#define ip_tos tos
-#define ip_len tot_len
-#define ip_id id
-#define ip_off frag_off
-#define ip_ttl ttl
-#define ip_p protocol
-#define ip_sum check
-#define ip_src saddr
-#define ip_dst daddr
-#endif
-
-#if ALLOW_SOURCE_PING
-#define MAX_PKT_SZ 8192
-#define MAX_PAYLOAD (MAX_PKT_SZ - sizeof(struct icmphdr) - sizeof (char) - sizeof(struct timeval) - 1)
-#else
-#define MAX_PAYLOAD SQUIDHOSTNAMELEN
-#define MAX_PKT_SZ (MAX_PAYLOAD + sizeof(struct timeval) + sizeof (char) + sizeof(struct icmphdr) + 1)
-#endif
+#endif /* _SQUID_WIN32_ */
+
+#include "../libpinger/icmp_v4.h"
+#include "../libpinger/icmp_v6.h"

 typedef struct {
     struct timeval tv;
@@ -159,34 +97,8 @@
     char payload[MAX_PAYLOAD];
 } icmpEchoData;

-int icmp_ident = -1;
-int icmp_pkts_sent = 0;
-
-static const char *icmpPktStr[] =
-{
-    "Echo Reply",
-    "ICMP 1",
-    "ICMP 2",
-    "Destination Unreachable",
-    "Source Quench",
-    "Redirect",
-    "ICMP 6",
-    "ICMP 7",
-    "Echo",
-    "ICMP 9",
-    "ICMP 10",
-    "Time Exceeded",
-    "Parameter Problem",
-    "Timestamp",
-    "Timestamp Reply",
-    "Info Request",
-    "Info Reply",
-    "Out of Range Type"
-};
-
-static int in_cksum(unsigned short *ptr, int size);
 static void pingerRecv(void);
-static void pingerLog(struct icmphdr *, struct in_addr, int, int);
+static void pingerLog(int, struct in_addr, int, int);
 static int ipHops(int ttl);
 static void pingerSendtoSquid(pingerReplyData * preply);
 static void pingerOpen(void);
@@ -299,51 +211,24 @@
 static void
 pingerSendEcho(struct in_addr to, int opcode, char *payload, int len)
 {
-    LOCAL_ARRAY(char, pkt, MAX_PKT_SZ);
-    struct icmphdr *icmp = NULL;
-    icmpEchoData *echo;
-    int icmp_pktsize = sizeof(struct icmphdr);
-    struct sockaddr_in S;
-    memset(pkt, '\0', MAX_PKT_SZ);
-    icmp = (struct icmphdr *) (void *) pkt;
-
-    /*
-     * cevans - beware signed/unsigned issues in untrusted data from
-     * the network!!
-     */
-    if (len < 0) {
-       len = 0;
-    }
-    icmp->icmp_type = ICMP_ECHO;
-    icmp->icmp_code = 0;
-    icmp->icmp_cksum = 0;
-    icmp->icmp_id = icmp_ident;
-    icmp->icmp_seq = (u_short) icmp_pkts_sent++;
-    echo = (icmpEchoData *) (icmp + 1);
-    echo->opcode = (unsigned char) opcode;
-    memcpy(&echo->tv, &current_time, sizeof(current_time));
-    icmp_pktsize += sizeof(struct timeval) + sizeof(char);
+    icmpEchoData echo;
+    int icmp_pktsize;
+
+    /* Assemble the icmpEcho payload */
+    echo.opcode = (unsigned char) opcode;
+    memcpy(&echo.tv, &current_time, sizeof(current_time));
+
+    /* size of the IcmpEchoData header */
+    icmp_pktsize = sizeof(struct timeval) + sizeof(char);
+
+    /* If there's a payload, add it */
     if (payload) {
-       if (len > MAX_PAYLOAD)
-           len = MAX_PAYLOAD;
-       xmemcpy(echo->payload, payload, len);
-       icmp_pktsize += len;
-    }
-    icmp->icmp_cksum = in_cksum((u_short *) icmp, icmp_pktsize);
-    S.sin_family = AF_INET;
-    /*
-     * cevans: alert: trusting to-host, was supplied in network packet
-     */
-    S.sin_addr = to;
-    S.sin_port = 0;
-    assert(icmp_pktsize <= MAX_PKT_SZ);
-    sendto(icmp_sock,
-       pkt,
-       icmp_pktsize,
-       0,
-       (struct sockaddr *) &S,
-       sizeof(struct sockaddr_in));
-    pingerLog(icmp, to, 0, 0);
+        memcpy(echo.payload, payload, MIN(len, MAX_PAYLOAD));
+        icmp_pktsize += MIN(len, MAX_PAYLOAD);
+    }
+
+    pingerv4SendEcho(icmp_sock, to, opcode, (char *) &echo, icmp_pktsize);
+    pingerLog(ICMP_ECHO, to, 0, 0);
 }

 static void
@@ -409,41 +294,18 @@
     preply.rtt = tvSubMsec(tv, now);
     preply.psize = n - iphdrlen - (sizeof(icmpEchoData) - MAX_PKT_SZ);
     pingerSendtoSquid(&preply);
-    pingerLog(icmp, from.sin_addr, preply.rtt, preply.hops);
-}
-
-
-static int
-in_cksum(unsigned short *ptr, int size)
-{
-    long sum;
-    unsigned short oddbyte;
-    unsigned short answer;
-    sum = 0;
-    while (size > 1) {
-       sum += *ptr++;
-       size -= 2;
-    }
-    if (size == 1) {
-       oddbyte = 0;
-       *((unsigned char *) &oddbyte) = *(unsigned char *) ptr;
-       sum += oddbyte;
-    }
-    sum = (sum >> 16) + (sum & 0xffff);
-    sum += (sum >> 16);
-    answer = (unsigned short) ~sum;
-    return (answer);
+    pingerLog(icmp->icmp_type, from.sin_addr, preply.rtt, preply.hops);
 }

 static void
-pingerLog(struct icmphdr *icmp, struct in_addr addr, int rtt, int hops)
+pingerLog(int icmp_type, struct in_addr addr, int rtt, int hops)
 {
     debug(42, 2) ("pingerLog: %9d.%06d %-16s %d %-15.15s %dms %d hops\n",
        (int) current_time.tv_sec,
        (int) current_time.tv_usec,
        inet_ntoa(addr),
-       (int) icmp->icmp_type,
-       icmpPktStr[icmp->icmp_type],
+       (int) icmp_type,
+       icmpPktStr[icmp_type],
        rtt,
        hops);
 }

--
You received this message because you are subscribed to the Google Groups 
"lusca-commit" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/lusca-commit?hl=en.

Reply via email to