Mail Archives: cygwin-apps/2000/07/12/09:10:46
This is a multi-part message in MIME format.
------=_NextPart_000_000F_01BFEC57.1022CFD0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
That as the fragment where I think the problem occurs. I've attached the
whole program now as it's pretty small.
It's an optional process used by squid to ping web servers to decide whether
a direct connection or parent connection is most efficient.
yes, it calls socket and so on.
I doctored the icmp.h and in.h headers from Linux (where other cygwin
headers seem to have come from :-) ) - so I won't be surprised if the
problem is the supporting code is missing.../
Rob
----- Original Message -----
From: "Corinna Vinschen" <vinschen AT cygnus DOT com>
To: "Robert Collins" <robert DOT collins AT itdomain DOT com DOT au>
Cc: "cygapp" <cygwin-apps AT sourceware DOT cygnus DOT com>
Sent: Wednesday, July 12, 2000 11:03 PM
Subject: Re: sendto function
> Robert Collins wrote:
> >
> > Is the sendto function capable of sending icmp packets?
> >
> > The following code fragment is not working properly...
> > It runs on Un*x at the moment, and I'm hoping for some hint/direction
for me
> > to alter it, or alter cygwin to get it working.
>
> This works on unix? I'm missing the icmp_sock definition
> as well as the socket() call. fd 2 is used which is stderr
> typically. Are you sure that you got your icmp_sock descriptor
> by a socket() call? Or is that application called by inetd
> with already opened descriptors?
>
> Corinna
>
> --
> Corinna Vinschen
> Cygwin Developer
> Cygnus Solutions, a Red Hat company
>
------=_NextPart_000_000F_01BFEC57.1022CFD0
Content-Type: application/octet-stream;
name="pinger.c"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="pinger.c"
=0A=
/*=0A=
* $Id: pinger.c,v 1.1.1.3.12.2.6.1 2000/07/11 23:41:19 rbcollins Exp $=0A=
*=0A=
* DEBUG: section 42 ICMP Pinger program=0A=
* AUTHOR: Duane Wessels=0A=
*=0A=
* SQUID Internet Object Cache http://squid.nlanr.net/Squid/=0A=
* ----------------------------------------------------------=0A=
*=0A=
* Squid is the result of efforts by numerous individuals from the=0A=
* Internet community. Development is led by Duane Wessels of the=0A=
* National Laboratory for Applied Network Research and funded by the=0A=
* National Science Foundation. Squid is Copyrighted (C) 1998 by=0A=
* the Regents of the University of California. Please see the=0A=
* COPYRIGHT file for full details. Squid incorporates software=0A=
* developed and/or copyrighted by other sources. Please see the=0A=
* CREDITS file for full details.=0A=
*=0A=
* This program is free software; you can redistribute it and/or modify=0A=
* it under the terms of the GNU General Public License as published by=0A=
* the Free Software Foundation; either version 2 of the License, or=0A=
* (at your option) any later version.=0A=
* =0A=
* This program is distributed in the hope that it will be useful,=0A=
* but WITHOUT ANY WARRANTY; without even the implied warranty of=0A=
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the=0A=
* GNU General Public License for more details.=0A=
* =0A=
* You should have received a copy of the GNU General Public License=0A=
* along with this program; if not, write to the Free Software=0A=
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.=0A=
*=0A=
*/=0A=
=0A=
#include "squid.h"=0A=
=0A=
#if USE_ICMP=0A=
=0A=
#include <netinet/in_systm.h>=0A=
#include <netinet/in.h>=0A=
#include <netinet/ip.h>=0A=
#include <netinet/ip_icmp.h>=0A=
=0A=
#ifndef _SQUID_LINUX_=0A=
#ifndef _SQUID_CYGWIN_=0A=
#define icmphdr icmp=0A=
#define iphdr ip=0A=
#endif=0A=
#endif=0A=
=0A=
#if defined (_SQUID_LINUX_) || defined (_SQUID_CYGWIN_)=0A=
#ifdef icmp_id=0A=
#undef icmp_id=0A=
#endif=0A=
#ifdef icmp_seq=0A=
#undef icmp_seq=0A=
#endif=0A=
#define icmp_type type=0A=
#define icmp_code code=0A=
#define icmp_cksum checksum=0A=
#define icmp_id un.echo.id=0A=
#define icmp_seq un.echo.sequence=0A=
#define ip_hl ihl=0A=
#define ip_v version=0A=
#define ip_tos tos=0A=
#define ip_len tot_len=0A=
#define ip_id id=0A=
#define ip_off frag_off=0A=
#define ip_ttl ttl=0A=
#define ip_p protocol=0A=
#define ip_sum check=0A=
#define ip_src saddr=0A=
#define ip_dst daddr=0A=
#endif=0A=
=0A=
#if ALLOW_SOURCE_PING=0A=
#define MAX_PKT_SZ 8192=0A=
#define MAX_PAYLOAD (MAX_PKT_SZ - sizeof(struct icmphdr) - sizeof (char) =
- sizeof(struct timeval) - 1)=0A=
#else=0A=
#define MAX_PAYLOAD SQUIDHOSTNAMELEN=0A=
#define MAX_PKT_SZ (MAX_PAYLOAD + sizeof(struct timeval) + sizeof (char) =
+ sizeof(struct icmphdr) + 1)=0A=
#endif=0A=
=0A=
typedef struct {=0A=
struct timeval tv;=0A=
unsigned char opcode;=0A=
char payload[MAX_PAYLOAD];=0A=
} icmpEchoData;=0A=
=0A=
int icmp_ident =3D -1;=0A=
int icmp_pkts_sent =3D 0;=0A=
=0A=
static const char *icmpPktStr[] =3D=0A=
{=0A=
"Echo Reply",=0A=
"ICMP 1",=0A=
"ICMP 2",=0A=
"Destination Unreachable",=0A=
"Source Quench",=0A=
"Redirect",=0A=
"ICMP 6",=0A=
"ICMP 7",=0A=
"Echo",=0A=
"ICMP 9",=0A=
"ICMP 10",=0A=
"Time Exceeded",=0A=
"Parameter Problem",=0A=
"Timestamp",=0A=
"Timestamp Reply",=0A=
"Info Request",=0A=
"Info Reply",=0A=
"Out of Range Type"=0A=
};=0A=
=0A=
static int in_cksum(unsigned short *ptr, int size);=0A=
static void pingerRecv(void);=0A=
static void pingerLog(struct icmphdr *, struct in_addr, int, int);=0A=
static int ipHops(int ttl);=0A=
static void pingerSendtoSquid(pingerReplyData * preply);=0A=
=0A=
void=0A=
pingerOpen(void)=0A=
{=0A=
struct protoent *proto =3D NULL;=0A=
if ((proto =3D getprotobyname("icmp")) =3D=3D 0) {=0A=
debug(42, 0) ("pingerOpen: unknown protocol: icmp\n");=0A=
exit(1);=0A=
}=0A=
icmp_sock =3D socket(PF_INET, SOCK_RAW, proto->p_proto);=0A=
if (icmp_sock < 0) {=0A=
debug(50, 0) ("pingerOpen: icmp_sock: %s\n", xstrerror());=0A=
exit(1);=0A=
}=0A=
icmp_ident =3D getpid() & 0xffff;=0A=
debug(42, 0) ("pinger: ICMP socket opened\n");=0A=
}=0A=
=0A=
void=0A=
pingerClose(void)=0A=
{=0A=
close(icmp_sock);=0A=
icmp_sock =3D -1;=0A=
icmp_ident =3D 0;=0A=
}=0A=
=0A=
static void=0A=
pingerSendEcho(struct in_addr to, int opcode, char *payload, int len)=0A=
{=0A=
LOCAL_ARRAY(char, pkt, MAX_PKT_SZ);=0A=
struct icmphdr *icmp =3D NULL;=0A=
icmpEchoData *echo;=0A=
int icmp_pktsize =3D sizeof(struct icmphdr);=0A=
struct sockaddr_in S;=0A=
memset(pkt, '\0', MAX_PKT_SZ);=0A=
icmp =3D (struct icmphdr *) (void *) pkt;=0A=
/*=0A=
* cevans - beware signed/unsigned issues in untrusted data from=0A=
* the network!!=0A=
*/=0A=
if (len < 0) {=0A=
len =3D 0;=0A=
}=0A=
icmp->icmp_type =3D ICMP_ECHO;=0A=
icmp->icmp_code =3D 0;=0A=
icmp->icmp_cksum =3D 0;=0A=
icmp->icmp_id =3D icmp_ident;=0A=
icmp->icmp_seq =3D (u_short) icmp_pkts_sent++;=0A=
echo =3D (icmpEchoData *) (icmp + 1);=0A=
echo->opcode =3D (unsigned char) opcode;=0A=
echo->tv =3D current_time;=0A=
icmp_pktsize +=3D sizeof(icmpEchoData) - MAX_PAYLOAD;=0A=
if (payload) {=0A=
if (len > MAX_PAYLOAD)=0A=
len =3D MAX_PAYLOAD;=0A=
xmemcpy(echo->payload, payload, len);=0A=
icmp_pktsize +=3D len;=0A=
}=0A=
icmp->icmp_cksum =3D in_cksum((u_short *) icmp, icmp_pktsize);=0A=
S.sin_family =3D AF_INET;=0A=
/*=0A=
* cevans: alert: trusting to-host, was supplied in network packet=0A=
*/=0A=
S.sin_addr =3D to;=0A=
S.sin_port =3D 0;=0A=
assert(icmp_pktsize <=3D MAX_PKT_SZ);=0A=
sendto(icmp_sock,=0A=
pkt,=0A=
icmp_pktsize,=0A=
0,=0A=
(struct sockaddr *) &S,=0A=
sizeof(struct sockaddr_in));=0A=
debug(50,0) ("WSAError is %s\n", xstrerror());=0A=
pingerLog(icmp, to, 0, 0);=0A=
}=0A=
=0A=
static void=0A=
pingerRecv(void)=0A=
{=0A=
int n;=0A=
socklen_t fromlen;=0A=
struct sockaddr_in from;=0A=
int iphdrlen =3D 20;=0A=
struct iphdr *ip =3D NULL;=0A=
struct icmphdr *icmp =3D NULL;=0A=
static char *pkt =3D NULL;=0A=
struct timeval now;=0A=
icmpEchoData *echo;=0A=
static pingerReplyData preply;=0A=
=0A=
if (pkt =3D=3D NULL)=0A=
pkt =3D xmalloc(MAX_PKT_SZ);=0A=
fromlen =3D sizeof(from);=0A=
n =3D recvfrom(icmp_sock,=0A=
pkt,=0A=
MAX_PKT_SZ,=0A=
0,=0A=
(struct sockaddr *) &from,=0A=
&fromlen);=0A=
#if GETTIMEOFDAY_NO_TZP=0A=
gettimeofday(&now);=0A=
#else=0A=
gettimeofday(&now, NULL);=0A=
#endif=0A=
debug(42, 9) ("pingerRecv: %d bytes from %s\n", n, =
inet_ntoa(from.sin_addr));=0A=
ip =3D (struct iphdr *) (void *) pkt;=0A=
#if HAVE_IP_HL=0A=
iphdrlen =3D ip->ip_hl << 2;=0A=
#else /* HAVE_IP_HL */=0A=
#if WORDS_BIGENDIAN=0A=
iphdrlen =3D (ip->ip_vhl >> 4) << 2;=0A=
#else=0A=
iphdrlen =3D (ip->ip_vhl & 0xF) << 2;=0A=
#endif=0A=
#endif /* HAVE_IP_HL */=0A=
icmp =3D (struct icmphdr *) (void *) (pkt + iphdrlen);=0A=
debug(42, 9) ("pingerRecv: icmp-type %d from %s\n", icmp->icmp_type, =
inet_ntoa(from.sin_addr));=0A=
debug(42, 9) ("pingerRecv: icmp-id %d for ident %d from %s\n", =
icmp->icmp_id, icmp_ident, inet_ntoa(from.sin_addr)); if =
(icmp->icmp_type !=3D ICMP_ECHOREPLY)=0A=
return;=0A=
=0A=
if (icmp->icmp_id !=3D icmp_ident)=0A=
return;=0A=
echo =3D (icmpEchoData *) (void *) (icmp + 1);=0A=
debug(42, 9) ("pingerRecv: about to send to squid for reply from %s\n", =
inet_ntoa(from.sin_addr));=0A=
preply.from =3D from.sin_addr;=0A=
preply.opcode =3D echo->opcode;=0A=
preply.hops =3D ipHops(ip->ip_ttl);=0A=
preply.rtt =3D tvSubMsec(echo->tv, now);=0A=
preply.psize =3D n - iphdrlen - (sizeof(icmpEchoData) - MAX_PKT_SZ);=0A=
debug(42, 9) ("pingerRecv: about to send to squid for reply from =
%s\n", inet_ntoa(from.sin_addr)); =0A=
pingerSendtoSquid(&preply);=0A=
pingerLog(icmp, from.sin_addr, preply.rtt, preply.hops);=0A=
}=0A=
=0A=
=0A=
static int=0A=
in_cksum(unsigned short *ptr, int size)=0A=
{=0A=
long sum;=0A=
unsigned short oddbyte;=0A=
unsigned short answer;=0A=
sum =3D 0;=0A=
while (size > 1) {=0A=
sum +=3D *ptr++;=0A=
size -=3D 2;=0A=
}=0A=
if (size =3D=3D 1) {=0A=
oddbyte =3D 0;=0A=
*((unsigned char *) &oddbyte) =3D *(unsigned char *) ptr;=0A=
sum +=3D oddbyte;=0A=
}=0A=
sum =3D (sum >> 16) + (sum & 0xffff);=0A=
sum +=3D (sum >> 16);=0A=
answer =3D ~sum;=0A=
return (answer);=0A=
}=0A=
=0A=
static void=0A=
pingerLog(struct icmphdr *icmp, struct in_addr addr, int rtt, int hops)=0A=
{=0A=
debug(42, 2) ("pingerLog: %9d.%06d %-16s %d %-15.15s %dms %d hops\n",=0A=
(int) current_time.tv_sec,=0A=
(int) current_time.tv_usec,=0A=
inet_ntoa(addr),=0A=
(int) icmp->icmp_type,=0A=
icmpPktStr[icmp->icmp_type],=0A=
rtt,=0A=
hops);=0A=
}=0A=
=0A=
static int=0A=
ipHops(int ttl)=0A=
{=0A=
if (ttl < 33)=0A=
return 33 - ttl;=0A=
if (ttl < 63)=0A=
return 63 - ttl; /* 62 =3D (64+60)/2 */=0A=
if (ttl < 65)=0A=
return 65 - ttl; /* 62 =3D (64+60)/2 */=0A=
if (ttl < 129)=0A=
return 129 - ttl;=0A=
if (ttl < 193)=0A=
return 193 - ttl;=0A=
return 256 - ttl;=0A=
}=0A=
=0A=
static int=0A=
pingerReadRequest(void)=0A=
{=0A=
static pingerEchoData pecho;=0A=
int n;=0A=
int guess_size;=0A=
memset(&pecho, '\0', sizeof(pecho));=0A=
n =3D recv(0, (char *) &pecho, sizeof(pecho), 0);=0A=
if (n < 0)=0A=
return n;=0A=
if (0 =3D=3D n) {=0A=
/* EOF indicator */=0A=
fprintf(stderr, "EOF encountered\n");=0A=
errno =3D 0;=0A=
return -1;=0A=
}=0A=
guess_size =3D n - (sizeof(pingerEchoData) - PINGER_PAYLOAD_SZ);=0A=
if (guess_size !=3D pecho.psize) {=0A=
fprintf(stderr, "size mismatch, guess=3D%d psize=3D%d\n",=0A=
guess_size, pecho.psize);=0A=
/* don't process this message, but keep running */=0A=
return 0;=0A=
}=0A=
pingerSendEcho(pecho.to,=0A=
pecho.opcode,=0A=
pecho.payload,=0A=
pecho.psize);=0A=
return n;=0A=
}=0A=
=0A=
static void=0A=
pingerSendtoSquid(pingerReplyData * preply)=0A=
{=0A=
int len =3D sizeof(pingerReplyData) - MAX_PKT_SZ + preply->psize;=0A=
if (send(1, (char *) preply, len, 0) < 0) {=0A=
debug(50, 0) ("pinger: send: %s\n", xstrerror());=0A=
exit(1);=0A=
}=0A=
}=0A=
=0A=
time_t=0A=
getCurrentTime(void)=0A=
{=0A=
#if GETTIMEOFDAY_NO_TZP=0A=
gettimeofday(¤t_time);=0A=
#else=0A=
gettimeofday(¤t_time, NULL);=0A=
#endif=0A=
return squid_curtime =3D current_time.tv_sec;=0A=
}=0A=
=0A=
=0A=
int=0A=
main(int argc, char *argv[])=0A=
{=0A=
fd_set R;=0A=
int x;=0A=
struct timeval tv;=0A=
const char *debug_args =3D "ALL,1";=0A=
char *t;=0A=
time_t last_check_time =3D 0;=0A=
=0A=
/*=0A=
* cevans - do this first. It grabs a raw socket. After this we can=0A=
* drop privs=0A=
*/=0A=
pingerOpen();=0A=
setgid(getgid());=0A=
setuid(getuid());=0A=
=0A=
if ((t =3D getenv("SQUID_DEBUG")))=0A=
debug_args =3D xstrdup(t);=0A=
getCurrentTime();=0A=
_db_init(NULL, debug_args);=0A=
=0A=
for (;;) {=0A=
tv.tv_sec =3D 10;=0A=
tv.tv_usec =3D 0;=0A=
FD_ZERO(&R);=0A=
FD_SET(0, &R);=0A=
FD_SET(icmp_sock, &R);=0A=
x =3D select(icmp_sock + 1, &R, NULL, NULL, &tv);=0A=
getCurrentTime();=0A=
if (x < 0)=0A=
exit(1);=0A=
if (FD_ISSET(0, &R))=0A=
if (pingerReadRequest() < 0) {=0A=
debug(42, 0) ("Pinger exiting.\n");=0A=
exit(1);=0A=
}=0A=
if (FD_ISSET(icmp_sock, &R))=0A=
pingerRecv();=0A=
if (10 + last_check_time < squid_curtime) {=0A=
if (send(1, (char *) &tv, 0, 0) < 0)=0A=
exit(1);=0A=
last_check_time =3D squid_curtime;=0A=
}=0A=
}=0A=
/* NOTREACHED */=0A=
}=0A=
=0A=
#else=0A=
#include <stdio.h>=0A=
int=0A=
main(int argc, char *argv[])=0A=
{=0A=
fprintf(stderr, "%s: ICMP support not compiled in.\n", argv[0]);=0A=
return 1;=0A=
}=0A=
#endif /* USE_ICMP */=0A=
------=_NextPart_000_000F_01BFEC57.1022CFD0--
- Raw text -