Mailing-List: contact cygwin-apps-help AT sourceware DOT cygnus DOT com; run by ezmlm Sender: cygwin-apps-owner AT sourceware DOT cygnus DOT com List-Subscribe: List-Archive: List-Post: List-Help: , Delivered-To: mailing list cygwin-apps AT sources DOT redhat DOT com Message-ID: <001201bfec03$3f8549a0$f7c723cb@lifelesswks> From: "Robert Collins" To: "cygapp" Cc: "cygapp" References: <007d01bfebfb$1aff7090$f7c723cb AT lifelesswks> <396C6CBC DOT E79EA907 AT cygnus DOT com> Subject: Re: sendto function Date: Wed, 12 Jul 2000 23:15:26 +1000 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_000F_01BFEC57.1022CFD0" X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 5.00.2919.6700 X-MimeOLE: Produced By Microsoft MimeOLE V5.00.2919.6700 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" To: "Robert Collins" Cc: "cygapp" 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 =0A= #include =0A= #include =0A= #include =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 =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--