source: mainline/uspace/app/ping/ping.c@ 6428115

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 6428115 was 6428115, checked in by Jiri Svoboda <jiri@…>, 14 years ago

Ping utility, ICMP echo send and receive.

  • Property mode set to 100644
File size: 4.1 KB
Line 
1/*
2 * Copyright (c) 2012 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup ping
30 * @{
31 */
32/** @file ICMP echo utility.
33 */
34
35#include <errno.h>
36#include <fibril_synch.h>
37#include <inet/inetping.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <sys/types.h>
41
42#define NAME "ping"
43
44/** Ping request timeout in microseconds */
45#define PING_TIMEOUT (1000 * 1000)
46
47static int ping_ev_recv(inetping_sdu_t *);
48static FIBRIL_CONDVAR_INITIALIZE(done_cv);
49static FIBRIL_MUTEX_INITIALIZE(done_lock);
50
51static inetping_ev_ops_t ev_ops = {
52 .recv = ping_ev_recv
53};
54
55static void print_syntax(void)
56{
57 printf("syntax: " NAME " <addr>\n");
58}
59
60static int addr_parse(const char *text, inet_addr_t *addr)
61{
62 unsigned long a[4];
63 char *cp = (char *)text;
64 int i;
65
66 for (i = 0; i < 3; i++) {
67 a[i] = strtoul(cp, &cp, 10);
68 if (*cp != '.')
69 return EINVAL;
70 ++cp;
71 }
72
73 a[3] = strtoul(cp, &cp, 10);
74 if (*cp != '\0')
75 return EINVAL;
76
77 addr->ipv4 = 0;
78 for (i = 0; i < 4; i++) {
79 if (a[i] > 255)
80 return EINVAL;
81 addr->ipv4 = (addr->ipv4 << 8) | a[i];
82 }
83
84 return EOK;
85}
86
87static int addr_format(inet_addr_t *addr, char **bufp)
88{
89 int rc;
90
91 rc = asprintf(bufp, "%d.%d.%d.%d", addr->ipv4 >> 24,
92 (addr->ipv4 >> 16) & 0xff, (addr->ipv4 >> 8) & 0xff,
93 addr->ipv4 & 0xff);
94
95 if (rc < 0)
96 return ENOMEM;
97
98 return EOK;
99}
100
101static int ping_ev_recv(inetping_sdu_t *sdu)
102{
103 char *asrc, *adest;
104 int rc;
105
106 rc = addr_format(&sdu->src, &asrc);
107 if (rc != EOK)
108 return ENOMEM;
109
110 rc = addr_format(&sdu->dest, &adest);
111 if (rc != EOK) {
112 free(asrc);
113 return ENOMEM;
114 }
115 printf("Received ICMP echo reply: from %s to %s, seq. no %u, "
116 "payload size %zu\n", asrc, adest, sdu->seq_no, sdu->size);
117
118 fibril_condvar_broadcast(&done_cv);
119
120 free(asrc);
121 free(adest);
122 return EOK;
123}
124
125int main(int argc, char *argv[])
126{
127 int rc;
128 inetping_sdu_t sdu;
129
130 rc = inetping_init(&ev_ops);
131 if (rc != EOK) {
132 printf(NAME ": Failed connecting to internet ping service "
133 "(%d).\n", rc);
134 return 1;
135 }
136
137 if (argc != 2) {
138 print_syntax();
139 return 1;
140 }
141
142 /* Parse destination address */
143 rc = addr_parse(argv[1], &sdu.dest);
144 if (rc != EOK) {
145 printf(NAME ": Invalid address format.\n");
146 print_syntax();
147 return 1;
148 }
149
150 sdu.seq_no = 1;
151 sdu.data = (void *) "foo";
152 sdu.size = 3;
153
154 /* Determine source address */
155 rc = inetping_get_srcaddr(&sdu.dest, &sdu.src);
156 if (rc != EOK) {
157 printf(NAME ": Failed determining source address.\n");
158 return 1;
159 }
160
161 rc = inetping_send(&sdu);
162 if (rc != EOK) {
163 printf(NAME ": Failed sending echo request (%d).\n", rc);
164 return 1;
165 }
166
167 fibril_mutex_lock(&done_lock);
168 rc = fibril_condvar_wait_timeout(&done_cv, &done_lock, PING_TIMEOUT);
169 fibril_mutex_unlock(&done_lock);
170
171 if (rc == ETIMEOUT) {
172 printf(NAME ": Echo request timed out.\n");
173 return 1;
174 }
175
176 return 0;
177}
178
179/** @}
180 */
Note: See TracBrowser for help on using the repository browser.