readable_v6.c 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /* include readable_v61 */
  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. #ifdef IPV6
  8. #include <netinet/ip6.h>
  9. #include <netinet/icmp6.h>
  10. #endif
  11. int
  12. readable_v6(void)
  13. {
  14. #ifdef IPV6
  15. int i, hlen2, icmp6len, sport;
  16. char buf[MAXLINE];
  17. char srcstr[INET6_ADDRSTRLEN], dststr[INET6_ADDRSTRLEN];
  18. ssize_t n;
  19. socklen_t len;
  20. struct ip6_hdr *ip6, *hip6;
  21. struct icmp6_hdr *icmp6;
  22. struct udphdr *udp;
  23. struct sockaddr_in6 from, dest;
  24. struct icmpd_err icmpd_err;
  25. len = sizeof(from);
  26. n = Recvfrom(fd6, buf, MAXLINE, 0, (SA *) &from, &len);
  27. printf("%d bytes ICMPv6 from %s:",
  28. n, Sock_ntop_host((SA *) &from, len));
  29. icmp6 = (struct icmp6_hdr *) buf; /* start of ICMPv6 header */
  30. if ( (icmp6len = n) < 8)
  31. err_quit("icmp6len (%d) < 8", icmp6len);
  32. printf(" type = %d, code = %d\n", icmp6->icmp6_type, icmp6->icmp6_code);
  33. /* end readable_v61 */
  34. /* include readable_v62 */
  35. if (icmp6->icmp6_type == ICMP6_DST_UNREACH ||
  36. icmp6->icmp6_type == ICMP6_PACKET_TOO_BIG ||
  37. icmp6->icmp6_type == ICMP6_TIME_EXCEEDED) {
  38. if (icmp6len < 8 + 8)
  39. err_quit("icmp6len (%d) < 8 + 8", icmp6len);
  40. hip6 = (struct ip6_hdr *) (buf + 8);
  41. hlen2 = sizeof(struct ip6_hdr);
  42. printf("\tsrcip = %s, dstip = %s, next hdr = %d\n",
  43. Inet_ntop(AF_INET6, &hip6->ip6_src, srcstr, sizeof(srcstr)),
  44. Inet_ntop(AF_INET6, &hip6->ip6_dst, dststr, sizeof(dststr)),
  45. hip6->ip6_nxt);
  46. if (hip6->ip6_nxt == IPPROTO_UDP) {
  47. udp = (struct udphdr *) (buf + 8 + hlen2);
  48. sport = udp->uh_sport;
  49. /* 4find client's Unix domain socket, send headers */
  50. for (i = 0; i <= maxi; i++) {
  51. if (client[i].connfd >= 0 &&
  52. client[i].family == AF_INET6 &&
  53. client[i].lport == sport) {
  54. bzero(&dest, sizeof(dest));
  55. dest.sin6_family = AF_INET6;
  56. #ifdef HAVE_SOCKADDR_SA_LEN
  57. dest.sin6_len = sizeof(dest);
  58. #endif
  59. memcpy(&dest.sin6_addr, &hip6->ip6_dst,
  60. sizeof(struct in6_addr));
  61. dest.sin6_port = udp->uh_dport;
  62. icmpd_err.icmpd_type = icmp6->icmp6_type;
  63. icmpd_err.icmpd_code = icmp6->icmp6_code;
  64. icmpd_err.icmpd_len = sizeof(struct sockaddr_in6);
  65. memcpy(&icmpd_err.icmpd_dest, &dest, sizeof(dest));
  66. /* 4convert type & code to reasonable errno value */
  67. icmpd_err.icmpd_errno = EHOSTUNREACH; /* default */
  68. if (icmp6->icmp6_type == ICMP6_DST_UNREACH &&
  69. icmp6->icmp6_code == ICMP6_DST_UNREACH_NOPORT)
  70. icmpd_err.icmpd_errno = ECONNREFUSED;
  71. if (icmp6->icmp6_type == ICMP6_PACKET_TOO_BIG)
  72. icmpd_err.icmpd_errno = EMSGSIZE;
  73. Write(client[i].connfd, &icmpd_err, sizeof(icmpd_err));
  74. }
  75. }
  76. }
  77. }
  78. return(--nready);
  79. #endif
  80. }
  81. /* end readable_v62 */