readable_v4.c 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /* include readable_v41 */
  2. #include "icmpd.h"
  3. #include <netinet/in_systm.h>
  4. #include <netinet/ip.h>
  5. #include <netinet/ip_icmp.h>
  6. #include <netinet/udp.h>
  7. int
  8. readable_v4(void)
  9. {
  10. int i, hlen1, hlen2, icmplen, sport;
  11. char buf[MAXLINE];
  12. char srcstr[INET_ADDRSTRLEN], dststr[INET_ADDRSTRLEN];
  13. ssize_t n;
  14. socklen_t len;
  15. struct ip *ip, *hip;
  16. struct icmp *icmp;
  17. struct udphdr *udp;
  18. struct sockaddr_in from, dest;
  19. struct icmpd_err icmpd_err;
  20. len = sizeof(from);
  21. n = Recvfrom(fd4, buf, MAXLINE, 0, (SA *) &from, &len);
  22. printf("%d bytes ICMPv4 from %s:",
  23. n, Sock_ntop_host((SA *) &from, len));
  24. ip = (struct ip *) buf; /* start of IP header */
  25. hlen1 = ip->ip_hl << 2; /* length of IP header */
  26. icmp = (struct icmp *) (buf + hlen1); /* start of ICMP header */
  27. if ( (icmplen = n - hlen1) < 8)
  28. err_quit("icmplen (%d) < 8", icmplen);
  29. printf(" type = %d, code = %d\n", icmp->icmp_type, icmp->icmp_code);
  30. /* end readable_v41 */
  31. /* include readable_v42 */
  32. if (icmp->icmp_type == ICMP_UNREACH ||
  33. icmp->icmp_type == ICMP_TIMXCEED ||
  34. icmp->icmp_type == ICMP_SOURCEQUENCH) {
  35. if (icmplen < 8 + 20 + 8)
  36. err_quit("icmplen (%d) < 8 + 20 + 8", icmplen);
  37. hip = (struct ip *) (buf + hlen1 + 8);
  38. hlen2 = hip->ip_hl << 2;
  39. printf("\tsrcip = %s, dstip = %s, proto = %d\n",
  40. Inet_ntop(AF_INET, &hip->ip_src, srcstr, sizeof(srcstr)),
  41. Inet_ntop(AF_INET, &hip->ip_dst, dststr, sizeof(dststr)),
  42. hip->ip_p);
  43. if (hip->ip_p == IPPROTO_UDP) {
  44. udp = (struct udphdr *) (buf + hlen1 + 8 + hlen2);
  45. sport = udp->uh_sport;
  46. /* 4find client's Unix domain socket, send headers */
  47. for (i = 0; i <= maxi; i++) {
  48. if (client[i].connfd >= 0 &&
  49. client[i].family == AF_INET &&
  50. client[i].lport == sport) {
  51. bzero(&dest, sizeof(dest));
  52. dest.sin_family = AF_INET;
  53. #ifdef HAVE_SOCKADDR_SA_LEN
  54. dest.sin_len = sizeof(dest);
  55. #endif
  56. memcpy(&dest.sin_addr, &hip->ip_dst,
  57. sizeof(struct in_addr));
  58. dest.sin_port = udp->uh_dport;
  59. icmpd_err.icmpd_type = icmp->icmp_type;
  60. icmpd_err.icmpd_code = icmp->icmp_code;
  61. icmpd_err.icmpd_len = sizeof(struct sockaddr_in);
  62. memcpy(&icmpd_err.icmpd_dest, &dest, sizeof(dest));
  63. /* 4convert type & code to reasonable errno value */
  64. icmpd_err.icmpd_errno = EHOSTUNREACH; /* default */
  65. if (icmp->icmp_type == ICMP_UNREACH) {
  66. if (icmp->icmp_code == ICMP_UNREACH_PORT)
  67. icmpd_err.icmpd_errno = ECONNREFUSED;
  68. else if (icmp->icmp_code == ICMP_UNREACH_NEEDFRAG)
  69. icmpd_err.icmpd_errno = EMSGSIZE;
  70. }
  71. Write(client[i].connfd, &icmpd_err, sizeof(icmpd_err));
  72. }
  73. }
  74. }
  75. }
  76. return(--nready);
  77. }
  78. /* end readable_v42 */