ping.c 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <ip.h>
  4. #include "../icmp.h"
  5. static void
  6. catch(void *a, char *msg)
  7. {
  8. USED(a);
  9. if(strstr(msg, "alarm"))
  10. noted(NCONT);
  11. else
  12. noted(NDFLT);
  13. }
  14. #define MSG "dhcp probe"
  15. /*
  16. * make sure noone is using the address
  17. * TODO: ipv6 ping
  18. */
  19. int
  20. icmpecho(uchar *a)
  21. {
  22. int fd, i, n, len, rv;
  23. ushort sseq, x;
  24. char buf[512];
  25. Icmphdr *ip;
  26. rv = 0;
  27. if (!isv4(a))
  28. return 0;
  29. sprint(buf, "%I", a);
  30. fd = dial(netmkaddr(buf, "icmp", "1"), 0, 0, 0);
  31. if(fd < 0){
  32. return 0;
  33. }
  34. sseq = getpid()*time(0);
  35. ip = (Icmphdr *)(buf + IPV4HDR_LEN);
  36. notify(catch);
  37. for(i = 0; i < 3; i++){
  38. ip->type = EchoRequest;
  39. ip->code = 0;
  40. strcpy((char*)ip->data, MSG);
  41. ip->seq[0] = sseq;
  42. ip->seq[1] = sseq>>8;
  43. len = IPV4HDR_LEN + ICMP_HDRSIZE + sizeof(MSG);
  44. /* send a request */
  45. if(write(fd, buf, len) < len)
  46. break;
  47. /* wait 1/10th second for a reply and try again */
  48. alarm(100);
  49. n = read(fd, buf, sizeof(buf));
  50. alarm(0);
  51. if(n <= 0)
  52. continue;
  53. /* an answer to our echo request? */
  54. x = (ip->seq[1]<<8) | ip->seq[0];
  55. if(n >= len && ip->type == EchoReply && x == sseq &&
  56. strcmp((char*)ip->data, MSG) == 0){
  57. rv = 1;
  58. break;
  59. }
  60. }
  61. close(fd);
  62. return rv;
  63. }