| #include <common.h> |
| #include <command.h> |
| #include <clock.h> |
| #include <net.h> |
| #include <errno.h> |
| #include <linux/err.h> |
| |
| static uint16_t ping_sequence_number; |
| |
| static IPaddr_t net_ping_ip; /* the ip address to ping */ |
| |
| #define PING_STATE_INIT 0 |
| #define PING_STATE_SUCCESS 1 |
| |
| static int ping_state; |
| |
| static struct net_connection *ping_con; |
| |
| static int ping_send(void) |
| { |
| unsigned char *payload; |
| struct icmphdr *icmp; |
| uint64_t ts; |
| |
| icmp = ping_con->icmp; |
| |
| icmp->type = ICMP_ECHO_REQUEST; |
| icmp->code = 0; |
| icmp->checksum = 0; |
| icmp->un.echo.id = 0; |
| icmp->un.echo.sequence = htons(ping_sequence_number); |
| |
| ping_sequence_number++; |
| |
| payload = (char *)(icmp + 1); |
| ts = get_time_ns(); |
| memcpy(payload, &ts, sizeof(ts)); |
| payload[8] = 0xab; |
| payload[9] = 0xcd; |
| return net_icmp_send(ping_con, 9); |
| } |
| |
| static void ping_handler(void *ctx, char *pkt, unsigned len) |
| { |
| IPaddr_t tmp; |
| struct iphdr *ip = net_eth_to_iphdr(pkt); |
| |
| tmp = net_read_ip((void *)&ip->saddr); |
| if (tmp != net_ping_ip) |
| return; |
| |
| ping_state = PING_STATE_SUCCESS; |
| } |
| |
| static int do_ping(struct command *cmdtp, int argc, char *argv[]) |
| { |
| int ret; |
| uint64_t ping_start = 0; |
| |
| if (argc < 2) |
| return COMMAND_ERROR_USAGE; |
| |
| net_ping_ip = resolv(argv[1]); |
| if (!net_ping_ip) { |
| printf("unknown host %s\n", argv[1]); |
| return 1; |
| } |
| |
| ping_con = net_icmp_new(net_ping_ip, ping_handler, NULL); |
| if (IS_ERR(ping_con)) { |
| ret = PTR_ERR(ping_con); |
| goto out; |
| } |
| |
| ping_start = get_time_ns(); |
| ret = ping_send(); |
| if (ret) |
| goto out_unreg; |
| |
| ping_state = PING_STATE_INIT; |
| ping_sequence_number = 0; |
| |
| while (ping_state == PING_STATE_INIT) { |
| if (ctrlc()) { |
| ret = -EINTR; |
| break; |
| } |
| |
| net_poll(); |
| |
| if (is_timeout(ping_start, 10 * SECOND)) { |
| ping_start = get_time_ns(); |
| ret = ping_send(); |
| if (ret) |
| goto out_unreg; |
| } |
| } |
| |
| if (!ret) |
| printf("host %s is alive\n", argv[1]); |
| |
| out_unreg: |
| net_unregister(ping_con); |
| out: |
| if (ret) |
| printf("ping failed: %s\n", strerror(-ret)); |
| return ping_state == PING_STATE_SUCCESS ? 0 : 1; |
| } |
| |
| BAREBOX_CMD_START(ping) |
| .cmd = do_ping, |
| .usage = "ping <destination>", |
| BAREBOX_CMD_END |