@@ 0,0 1,78 @@
+use fmt;
+use getopt;
+use io;
+use memio;
+use net::icmp;
+use net::ip;
+use os;
+use rt;
+
+export fn main() void = {
+
+ const cmd = getopt::parse(os::args,
+ "send ICMP echo requests",
+ "address",
+ );
+ defer getopt::finish(&cmd);
+
+ if (len(cmd.args) != 1) {
+ fmt::fatal("Must specify exactly one target address");
+ };
+ let addr = ip::parse(cmd.args[0])!;
+ let (icmp_proto, domain, proto) = match (addr) {
+ case ip::addr4 =>
+ yield (icmp::IP_V4, rt::AF_INET, rt::IPPROTO_ICMP);
+ case ip::addr6 =>
+ // TODO imcp::encode does not handle v6 atm
+ // TODO rt is missing IPPROTO_ICMP6
+ //yield (icmp::IP_V6, rt::AF_INET6, 58);
+ fmt::fatal("Error: IPv6 is currently not supported!");
+ };
+
+ static let buf: [512]u8 = [0...];
+
+ let s = match (rt::socket(domain: int, rt::SOCK_DGRAM, proto)) {
+ case let s: int =>
+ yield s;
+ case let err: rt::errno =>
+ fmt::fatalf("Failed to create socket: {}", rt::strerror(err));
+ };
+ defer io::close(s)!;
+
+ // This would be nice, but rt currently doesn't know about SO_RCVTIMEO
+ //let timeout = rt::timeval {
+ // tv_sec = 2,
+ // tv_usec = 0,
+ //};
+ //let i = rt::setsockopt(s, rt::SOL_SOCKET, rt::SO_RCVTIMEO, &timeout: *void, size(rt::timeval))!;
+
+ let echo = icmp::echo {
+ id = 1234,
+ seq = 1,
+ data = ['1': u8, '2': u8, '3': u8, '4': u8, '5': u8],
+ };
+
+ let inmsg = icmp::message {
+ proto = proto,
+ code = 0,
+ checksum = 0,
+ body = echo,
+ };
+
+ let outbuf = memio::fixed(buf[..]);
+ let encsz = icmp::encode(&outbuf, &inmsg)!;
+ let sa = ip::to_native(addr, 0);
+ let data = memio::buffer(&outbuf);
+ let addrsz = size(rt::sockaddr): u32;
+ let sz = rt::sendto(s, data: *[*]u8, encsz, 0, &sa, addrsz);
+ match (sz) {
+ case let err: rt::errno =>
+ fmt::fatalf("sendto: {}", rt::strerror(err));
+ case let s: size =>
+ yield s;
+ };
+
+ sz = rt::recvfrom(s, &buf: *[*]u8, 512, 0, &sa, &addrsz)!;
+ let (from, port) = ip::from_native(sa);
+ fmt::printfln("Received response from {}", ip::string(from))!;
+};