d6_socket.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Copyright (C) 2011 Denys Vlasenko.
  4. *
  5. * Licensed under GPLv2, see file LICENSE in this source tree.
  6. */
  7. #include "common.h"
  8. #include "d6_common.h"
  9. #include <net/if.h>
  10. #include <ifaddrs.h>
  11. #include <netpacket/packet.h>
  12. int FAST_FUNC d6_read_interface(const char *interface, int *ifindex, struct in6_addr *nip6, uint8_t *mac)
  13. {
  14. int retval = 3;
  15. struct ifaddrs *ifap, *ifa;
  16. getifaddrs(&ifap);
  17. for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
  18. struct sockaddr_in6 *sip6;
  19. if (!ifa->ifa_addr || (strcmp(ifa->ifa_name, interface) != 0))
  20. continue;
  21. sip6 = (struct sockaddr_in6*)(ifa->ifa_addr);
  22. if (ifa->ifa_addr->sa_family == AF_PACKET) {
  23. struct sockaddr_ll *sll = (struct sockaddr_ll*)(ifa->ifa_addr);
  24. memcpy(mac, sll->sll_addr, 6);
  25. log2("MAC %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  26. *ifindex = sll->sll_ifindex;
  27. log2("ifindex %d", *ifindex);
  28. retval &= (3 - (1<<0));
  29. }
  30. #if 0
  31. if (ifa->ifa_addr->sa_family == AF_INET) {
  32. *nip = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
  33. log1("IP %s", inet_ntoa(((struct sockaddr_in *)ifa->ifa_addr)->sin_addr));
  34. }
  35. #endif
  36. if (ifa->ifa_addr->sa_family == AF_INET6
  37. && IN6_IS_ADDR_LINKLOCAL(&sip6->sin6_addr)
  38. ) {
  39. *nip6 = sip6->sin6_addr; /* struct copy */
  40. log1(
  41. "IPv6 %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
  42. nip6->s6_addr[0], nip6->s6_addr[1],
  43. nip6->s6_addr[2], nip6->s6_addr[3],
  44. nip6->s6_addr[4], nip6->s6_addr[5],
  45. nip6->s6_addr[6], nip6->s6_addr[7],
  46. nip6->s6_addr[8], nip6->s6_addr[9],
  47. nip6->s6_addr[10], nip6->s6_addr[11],
  48. nip6->s6_addr[12], nip6->s6_addr[13],
  49. nip6->s6_addr[14], nip6->s6_addr[15]
  50. );
  51. retval &= (3 - (1<<1));
  52. }
  53. }
  54. freeifaddrs(ifap);
  55. if (retval & (1<<0)) {
  56. /* This iface has no MAC (e.g. ppp), generate a random one */
  57. struct ifreq ifr;
  58. int fd;
  59. /*memset(&ifr, 0, sizeof(ifr)); - SIOCGIFINDEX does not need to clear all */
  60. strncpy_IFNAMSIZ(ifr.ifr_name, interface);
  61. fd = xsocket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
  62. if (ioctl(fd, SIOCGIFINDEX, &ifr) == 0) {
  63. *ifindex = ifr.ifr_ifindex;
  64. log2("ifindex %d", *ifindex);
  65. if (((uint32_t*)mac)[0] == 0) {
  66. /* invent a fictitious MAC (once) */
  67. ((uint32_t*)mac)[0] = rand();
  68. ((uint16_t*)mac)[2] = rand();
  69. mac[0] &= 0xfc; /* make sure it's not bcast */
  70. }
  71. retval &= (3 - (1<<0));
  72. }
  73. close(fd);
  74. }
  75. if (retval == 0)
  76. return retval;
  77. if (retval & (1<<0))
  78. bb_error_msg("can't get %s", "MAC");
  79. if (retval & (1<<1))
  80. bb_error_msg("can't get %s", "link-local IPv6 address");
  81. return -1;
  82. }
  83. int FAST_FUNC d6_listen_socket(int port, const char *inf)
  84. {
  85. int fd;
  86. struct sockaddr_in6 addr;
  87. log1("opening listen socket on *:%d %s", port, inf);
  88. fd = xsocket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
  89. setsockopt_reuseaddr(fd);
  90. if (setsockopt_broadcast(fd) == -1)
  91. bb_perror_msg_and_die("SO_BROADCAST");
  92. /* NB: bug 1032 says this doesn't work on ethernet aliases (ethN:M) */
  93. if (setsockopt_bindtodevice(fd, inf))
  94. xfunc_die(); /* warning is already printed */
  95. memset(&addr, 0, sizeof(addr));
  96. addr.sin6_family = AF_INET6;
  97. addr.sin6_port = htons(port);
  98. /* addr.sin6_addr is all-zeros */
  99. xbind(fd, (struct sockaddr *)&addr, sizeof(addr));
  100. return fd;
  101. }