Watt-32 tcp/ip  2.2 dev-rel.10
pcping.c
Go to the documentation of this file.
1 
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <limits.h>
8 
9 #include "copyrigh.h"
10 #include "wattcp.h"
11 #include "misc.h"
12 #include "timer.h"
13 #include "chksum.h"
14 #include "strings.h"
15 #include "language.h"
16 #include "ip4_in.h"
17 #include "ip4_out.h"
18 #include "pcsed.h"
19 #include "pcarp.h"
20 #include "pcdbug.h"
21 #include "pctcp.h"
22 #include "pcicmp.h"
23 
24 // #undef time
25 
29 static struct ping_cache {
30  DWORD host;
31  DWORD time;
32  DWORD number;
33  } pcache [10];
34 
45 int W32_CALL _ping (DWORD host, DWORD countnum, const BYTE *pattern, size_t len)
46 {
47  struct ping_pkt *pkt;
48  struct ICMP_echo *icmp;
49  struct in_Header *ip;
50  eth_address dest;
51 
52  if (sin_mask != 0xFFFFFFFF && !_ip4_is_loopback_addr(host) &&
53  !(~host & ~sin_mask))
54  {
55  outsnl (_LANG("Cannot ping a network!"));
56  return (0);
57  }
58 
59  if (!_arp_resolve(host,&dest))
60  {
61  outsnl (_LANG("Cannot resolve host's hardware address"));
62  return (0);
63  }
64 
65  if (debug_on >= 2)
66  {
67  outs (_LANG("\nDEBUG: destination hardware: "));
68  outhexes ((char*)&dest, sizeof(dest));
69  outs ("\n");
70  }
71 
72  host = intel (host);
73 
74  /* Jumbo packets must be sent as IP fragments
75  */
76 #if defined(USE_FRAGMENTS)
77  if (len > (size_t)(_mtu - sizeof(*ip) - sizeof(*icmp)))
78  {
79  int rc = 0;
80 
81  len = min (len, USHRT_MAX - sizeof(*ip) - sizeof(*icmp));
82  icmp = (struct ICMP_echo*) malloc (len + sizeof(*icmp));
83  if (!icmp)
84  {
85  if (debug_on)
86  outsnl (_LANG("_ping(): malloc failed"));
87  return (0);
88  }
89 
90  if (pattern)
91  memcpy (icmp+1, pattern, len);
92  len += sizeof(*icmp);
93  icmp->type = ICMP_ECHO;
94  icmp->code = 0;
95  icmp->index = countnum;
96  icmp->identifier = set_timeout (0) & 0xFFFF; /* "random" id */
97  icmp->sequence = 0;
98  icmp->checksum = 0;
99  icmp->checksum = ~CHECKSUM (icmp, len);
100  rc = _IP4_SEND_FRAGMENTS (NULL, ICMP_PROTO, host, icmp, len);
101  free (icmp);
102  return (rc < 0 ? 0 : rc);
103  }
104 #else
105  len = min (len, _mtu - sizeof(*ip) - sizeof(*icmp)); /* truncate */
106 #endif
107 
108  /* Ordinary small pings; format an Ethernet packet with IPv4 type
109  */
110  pkt = (struct ping_pkt*) _eth_formatpacket (&dest, IP4_TYPE);
111  ip = &pkt->in;
112  icmp = &pkt->icmp;
113 
114  if (pattern && len > 0)
115  {
116  len = min (len, _mtu-sizeof(struct ping_pkt));
117  memcpy (icmp+1, pattern, len); /* pattern after echo header */
118  len += sizeof (*icmp);
119  }
120  else
121  len = sizeof (*icmp);
122 
123  icmp->type = ICMP_ECHO;
124  icmp->code = 0;
125  icmp->index = countnum;
126  icmp->identifier = set_timeout (0) & 0xFFFF; /* "random" id */
127  icmp->sequence = 0;
128  icmp->checksum = 0;
129  icmp->checksum = ~CHECKSUM (icmp, len);
130 
131  return IP4_OUTPUT (ip, 0, host, ICMP_PROTO, 0, (BYTE)_default_tos,
132  0, len, NULL);
133 }
134 
138 static int MS_CDECL compare (const struct ping_cache *a,
139  const struct ping_cache *b)
140 {
141  return ((long)a->number - (long)b->number);
142 }
143 
147 void W32_CALL add_ping (DWORD host, DWORD time, DWORD number)
148 {
149  int i;
150 
151  for (i = 0; i < DIM(pcache); i++)
152  if (host && pcache[i].host == 0) /* vacant entry */
153  {
154  if (time > 0x7FFFFFFFL)
155  time += 0x1800B0L;
156  pcache[i].host = host;
157  pcache[i].time = time;
158  pcache[i].number = number;
159  qsort ((void*)&pcache, DIM(pcache), sizeof(pcache[0]), (CmpFunc)compare);
160  break;
161  }
162 }
163 
169 DWORD W32_CALL _chk_ping (DWORD host, DWORD *number)
170 {
171  int i;
172 
173  WATT_YIELD();
174 
175  for (i = 0; i < DIM(pcache); i++)
176  if (host && pcache[i].host == host)
177  {
178  pcache[i].host = 0; /* clear entry */
179  if (number)
180  *number = pcache[i].number;
181  return (pcache[i].time);
182  }
183  return (0xFFFFFFFFUL);
184 }
185 
186 
DWORD W32_CALL _chk_ping(DWORD host, DWORD *number)
Check for ICMP echo reply in ping-cache.
Definition: pcping.c:169
Core definitions.
Definition: ip_icmp.h:62
DWORD W32_CALL set_timeout(DWORD msec)
Return time for when given timeout (msec) expires.
Definition: timer.c:503
DWORD sin_mask
our net-mask, 255.255.255.0
Definition: pctcp.c:71
void *W32_CALL _eth_formatpacket(const void *mac_dest, WORD eth_type)
_eth_format_packet() places the next packet to be transmitted into the above link-layer output packet...
Definition: pcsed.c:135
Definition: ip.h:67
int W32_CALL _ping(DWORD host, DWORD countnum, const BYTE *pattern, size_t len)
Format and send an ICMP echo request (ping).
Definition: pcping.c:45
void W32_CALL add_ping(DWORD host, DWORD time, DWORD number)
Add an ICMP echo reply to the ping-cache.
Definition: pcping.c:147
static int MS_CDECL compare(const struct ping_cache *a, const struct ping_cache *b)
Compare two entries in ping-cache.
Definition: pcping.c:138
BOOL W32_CALL _arp_resolve(DWORD ip, eth_address *eth)
The blocking lookup function visible to higher functions.
Definition: pcarp.c:1279
BYTE _default_tos
Definition: ip4_out.c:53