Uncommented beaudio code
[pwlib.git] / src / ptlib / unix / uicmp.cxx
blob71a6ee1d7061f5efa5937e7259c75ccaf15bbd90
1 /*
2 * uicmp.cxx
4 * ICMP socket class implementation.
6 * Portable Windows Library
8 * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
18 * under the License.
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
25 * All Rights Reserved.
27 * Contributor(s): ______________________________________.
29 * $Log$
30 * Revision 1.15 2002/10/10 04:43:44 robertj
31 * VxWorks port, thanks Martijn Roest
33 * Revision 1.14 2001/09/10 03:03:36 robertj
34 * Major change to fix problem with error codes being corrupted in a
35 * PChannel when have simultaneous reads and writes in threads.
37 * Revision 1.13 2001/06/30 06:59:07 yurik
38 * Jac Goudsmit from Be submit these changes 6/28. Implemented by Yuri Kiryanov
40 * Revision 1.12 2001/03/07 07:00:17 yurik
41 * #ifdef'd setsockopt IPPROTO_IP for BeOS
43 * Revision 1.11 2001/03/06 22:20:21 craigs
44 * Fixed TTL and other stuff so that traceroute is almost possible!
46 * Revision 1.10 1999/08/09 04:06:39 robertj
47 * Change to avoid name space problem with X windows library
49 * Revision 1.9 1999/02/22 13:26:54 robertj
50 * BeOS port changes.
52 * Revision 1.8 1998/11/30 21:52:06 robertj
53 * New directory structure.
55 * Revision 1.7 1998/09/24 04:12:29 robertj
56 * Added open software license.
58 * Revision 1.6 1998/08/26 01:45:56 craigs
59 * Fixed error in IPHdr
61 * Revision 1.5 1998/01/26 07:27:09 robertj
62 * Added part support for extra ping info. Still needs TTL for traceroute.
64 * Revision 1.4 1996/11/16 11:12:56 craigs
65 * Fixed problem with work misaligns under SOlaris
67 * Revision 1.3 1996/10/31 10:20:07 craigs
68 * Moved ICMP implementation into here, as it is now platform dependent
70 * Revision 1.6 1996/09/14 13:09:34 robertj
71 * Major upgrade:
72 * rearranged sockets to help support IPX.
73 * added indirect channel class and moved all protocols to descend from it,
74 * separating the protocol from the low level byte transport.
76 * Revision 1.5 1996/08/11 06:52:14 robertj
77 * Oops
79 * Revision 1.4 1996/08/07 13:40:57 robertj
80 * Fixed sparc memory alignment problem from int 64
82 * Revision 1.3 1996/06/03 10:03:10 robertj
83 * Changed ping to return more parameters.
85 * Revision 1.2 1996/05/30 10:08:51 robertj
86 * Fixed bug in ping (checksum incorrect).
88 * Revision 1.1 1996/05/15 21:11:35 robertj
89 * Initial revision
93 #pragma implementation "icmpsock.h"
95 #include <ptlib.h>
96 #include <ptlib/sockets.h>
98 #define MAX_IP_LEN 60
99 #define MAX_ICMP_LEN 76
100 #define ICMP_DATA_LEN (64-8)
101 #define RX_BUFFER_SIZE (MAX_IP_LEN+MAX_ICMP_LEN+ICMP_DATA_LEN)
103 #define ICMP_ECHO_REPLY 0
104 #define ICMP_ECHO 8
106 #define ICMP_TIMXCEED 11
109 typedef struct {
110 BYTE type;
111 BYTE code;
112 WORD checksum;
114 WORD id;
115 WORD sequence;
117 PInt64 sendtime;
118 BYTE data[ICMP_DATA_LEN-sizeof(PInt64)];
119 } ICMPPacket;
122 typedef struct {
123 BYTE verIhl;
124 BYTE typeOfService;
125 WORD totalLength;
126 WORD identification;
127 WORD fragOff;
128 BYTE timeToLive;
129 BYTE protocol;
130 WORD checksum;
131 BYTE sourceAddr[4];
132 BYTE destAddr[4];
133 } IPHdr;
136 static WORD CalcChecksum(void * p, PINDEX len)
138 WORD * ptr = (WORD *)p;
139 DWORD sum = 0;
140 while (len > 1) {
141 sum += *ptr++;
142 len-=2;
145 if (len > 0) {
146 WORD t = *(BYTE *)ptr;
147 sum += t;
150 sum = (sum >> 16) + (sum & 0xffff);
151 sum += (sum >> 16);
152 return (WORD)~sum;
156 PICMPSocket::PICMPSocket()
158 OpenSocket();
162 BOOL PICMPSocket::Ping(const PString & host)
164 PingInfo info;
165 return Ping(host, info);
169 BOOL PICMPSocket::Ping(const PString & host, PingInfo & info)
171 if (!WritePing(host, info))
172 return FALSE;
174 return ReadPing(info);
178 BOOL PICMPSocket::WritePing(const PString & host, PingInfo & info)
180 // find address of the host
181 PIPSocket::Address addr;
182 if (!GetHostAddress(host, addr))
183 return SetErrorValues(BadParameter, EINVAL);
185 // create the ICMP packet
186 ICMPPacket packet;
188 // clear the packet including data area
189 memset(&packet, 0, sizeof(packet));
191 packet.type = ICMP_ECHO;
192 packet.sequence = info.sequenceNum;
193 packet.id = info.identifier;
195 #ifndef BE_BONELESS
196 if (info.ttl != 0) {
197 char ttl = (char)info.ttl;
198 if (::setsockopt(os_handle, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) != 0)
199 return FALSE;
201 #endif
203 // set the send time
204 packet.sendtime = PTimer::Tick().GetMilliSeconds();
206 // calculate the checksum
207 packet.checksum = CalcChecksum(&packet, sizeof(packet));
209 // send the packet
210 return WriteTo(&packet, sizeof(packet), addr, 0);
214 BOOL PICMPSocket::ReadPing(PingInfo & info)
216 // receive a packet
217 BYTE packet[RX_BUFFER_SIZE];
218 IPHdr * ipHdr;
219 ICMPPacket * icmpPacket;
220 WORD port;
221 PInt64 now;
222 PTimer timeout(GetReadTimeout());
224 for (;;) {
225 memset(&packet, 0, sizeof(packet));
227 if (!ReadFrom(packet, sizeof(packet), info.remoteAddr, port))
228 return FALSE;
230 now = PTimer::Tick().GetMilliSeconds();
231 ipHdr = (IPHdr *)packet;
232 icmpPacket = (ICMPPacket *)(packet + ((ipHdr->verIhl & 0xf) << 2));
234 if (( icmpPacket->type == ICMP_ECHO_REPLY) &&
235 ((WORD)icmpPacket->id == info.identifier)) {
236 info.status = PingSuccess;
237 break;
240 if (icmpPacket->type == ICMP_TIMXCEED) {
241 info.status = TtlExpiredTransmit;
242 break;
245 if (!timeout.IsRunning())
246 return FALSE;
249 info.remoteAddr = Address(ipHdr->sourceAddr[0], ipHdr->sourceAddr[1],
250 ipHdr->sourceAddr[2], ipHdr->sourceAddr[3]);
251 info.localAddr = Address(ipHdr->destAddr[0], ipHdr->destAddr[1],
252 ipHdr->destAddr[2], ipHdr->destAddr[3]);
254 // calc round trip time. Be careful, as unaligned "long long" ints
255 // can cause problems on some platforms
256 #if defined(P_SUN4) || defined(P_SOLARIS)
257 PInt64 then;
258 BYTE * pthen = (BYTE *)&then;
259 BYTE * psendtime = (BYTE *)&icmpPacket->sendtime;
260 memcpy(pthen, psendtime, sizeof(PInt64));
261 info.delay.SetInterval(now - then);
262 #else
263 info.delay.SetInterval(now - icmpPacket->sendtime);
264 #endif
266 info.sequenceNum = icmpPacket->sequence;
268 return TRUE;
272 BOOL PICMPSocket::OpenSocket()
274 #if !defined BE_BONELESS && !defined(P_VXWORKS)
275 struct protoent * p = ::getprotobyname(GetProtocolName());
276 if (p == NULL)
277 return ConvertOSError(-1);
278 return ConvertOSError(os_handle = os_socket(AF_INET, SOCK_RAW, p->p_proto));
279 #else // Raw sockets not supported in BeOS R4 or VxWorks.
280 return ConvertOSError(os_handle = os_socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP));
281 #endif //!defined BE_BONELESS && !defined(P_VXWORKS)
285 const char * PICMPSocket::GetProtocolName() const
287 return "icmp";
291 PICMPSocket::PingInfo::PingInfo(WORD id)
293 identifier = id;
294 sequenceNum = 0;
295 ttl = 255;
296 buffer = NULL;
297 status = PingSuccess;
301 // End Of File ///////////////////////////////////////////////////////////////