d6_socket.c 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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. log2("ifindex %d", sll->sll_ifindex);
  27. *ifindex = sll->sll_ifindex;
  28. retval &= (0xf - (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 &= (0xf - (1<<1));
  52. }
  53. }
  54. freeifaddrs(ifap);
  55. if (retval == 0)
  56. return retval;
  57. if (retval & (1<<0))
  58. bb_error_msg("can't get %s", "MAC");
  59. if (retval & (1<<1))
  60. bb_error_msg("can't get %s", "link-local IPv6 address");
  61. return -1;
  62. }
  63. int FAST_FUNC d6_listen_socket(int port, const char *inf)
  64. {
  65. int fd;
  66. struct sockaddr_in6 addr;
  67. log1("opening listen socket on *:%d %s", port, inf);
  68. fd = xsocket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
  69. setsockopt_reuseaddr(fd);
  70. if (setsockopt_broadcast(fd) == -1)
  71. bb_perror_msg_and_die("SO_BROADCAST");
  72. /* NB: bug 1032 says this doesn't work on ethernet aliases (ethN:M) */
  73. if (setsockopt_bindtodevice(fd, inf))
  74. xfunc_die(); /* warning is already printed */
  75. memset(&addr, 0, sizeof(addr));
  76. addr.sin6_family = AF_INET6;
  77. addr.sin6_port = htons(port);
  78. /* addr.sin6_addr is all-zeros */
  79. xbind(fd, (struct sockaddr *)&addr, sizeof(addr));
  80. return fd;
  81. }