get_gateway-bsd.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. * ZMap Copyright 2013 Regents of the University of Michigan
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy
  6. * of the License at http://www.apache.org/licenses/LICENSE-2.0
  7. */
  8. #ifndef ZMAP_GET_GATEWAY_BSD_H
  9. #define ZMAP_GET_GATEWAY_BSD_H
  10. #ifdef ZMAP_GET_GATEWAY_LINUX_H
  11. #error "Don't include both get_gateway-bsd.h and get_gateway-linux.h"
  12. #endif
  13. #include <net/route.h>
  14. #include <net/if.h>
  15. #include <net/if_dl.h>
  16. #if !defined(__APPLE__)
  17. #include <dnet/os.h>
  18. #include <dnet/eth.h>
  19. #include <dnet/ip.h>
  20. #include <dnet/ip6.h>
  21. #include <dnet/addr.h>
  22. #include <dnet/arp.h>
  23. #endif
  24. #define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(int) - 1))) : sizeof(int))
  25. #define UNUSED __attribute__((unused))
  26. int get_hw_addr(struct in_addr *gw_ip, UNUSED char *iface, unsigned char *hw_mac)
  27. {
  28. arp_t *arp;
  29. struct arp_entry entry;
  30. if (!gw_ip || !hw_mac) {
  31. return EXIT_FAILURE;
  32. }
  33. if ((arp = arp_open()) == NULL) {
  34. log_error("get_hw_addr", "failed to open arp table");
  35. return EXIT_FAILURE;
  36. }
  37. // Convert gateway ip to dnet struct format
  38. memset(&entry, 0, sizeof(struct arp_entry));
  39. entry.arp_pa.addr_type = ADDR_TYPE_IP;
  40. entry.arp_pa.addr_bits = IP_ADDR_BITS;
  41. entry.arp_pa.addr_ip = gw_ip->s_addr;
  42. if (arp_get(arp, &entry) < 0) {
  43. log_debug("get_hw_addr", "failed to fetch arp entry");
  44. return EXIT_FAILURE;
  45. } else {
  46. log_debug("get_hw_addr", "found ip %s at hw_addr %s",
  47. addr_ntoa(&entry.arp_pa),
  48. addr_ntoa(&entry.arp_ha));
  49. memcpy(hw_mac, &entry.arp_ha.addr_eth, ETHER_ADDR_LEN);
  50. }
  51. arp_close(arp);
  52. return EXIT_SUCCESS;
  53. }
  54. int get_iface_ip(char *iface, struct in_addr *ip)
  55. {
  56. assert(iface);
  57. struct ifaddrs *ifaddr, *ifa;
  58. if (getifaddrs(&ifaddr)) {
  59. log_fatal("get-iface-ip", "unable able to retrieve list of network interfaces: %s",
  60. strerror(errno));
  61. }
  62. for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
  63. if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET) {
  64. continue;
  65. }
  66. if (!strcmp(iface, ifa->ifa_name)) {
  67. struct sockaddr_in *sin = (struct sockaddr_in *)ifa->ifa_addr;
  68. ip->s_addr = sin->sin_addr.s_addr;
  69. log_debug("get-iface-ip", "ip address found for %s: %s",
  70. iface, inet_ntoa(*ip));
  71. return EXIT_SUCCESS;
  72. }
  73. }
  74. log_fatal("get-iface-ip", "specified interface does not"
  75. " exist or have an IPv4 address");
  76. return EXIT_FAILURE;
  77. }
  78. int get_iface_hw_addr(char *iface, unsigned char *hw_mac)
  79. {
  80. eth_t *e = eth_open(iface);
  81. if (e) {
  82. eth_addr_t eth_addr;
  83. int res = eth_get(e, &eth_addr);
  84. log_debug("gateway", "res: %d", res);
  85. if (res == 0) {
  86. memcpy(hw_mac, eth_addr.data, ETHER_ADDR_LEN);
  87. return EXIT_SUCCESS;
  88. }
  89. }
  90. return EXIT_FAILURE;
  91. }
  92. int _get_default_gw(struct in_addr *gw, char **iface)
  93. {
  94. char buf[4096];
  95. struct rt_msghdr *rtm = (struct rt_msghdr*) &buf;
  96. memset(rtm, 0, sizeof(buf));
  97. int seq = 0x00FF;
  98. rtm->rtm_msglen = sizeof(buf);
  99. rtm->rtm_type = RTM_GET;
  100. rtm->rtm_flags = RTF_GATEWAY;
  101. rtm->rtm_version = RTM_VERSION;
  102. rtm->rtm_seq = seq;
  103. rtm->rtm_addrs = RTA_DST | RTA_IFP;
  104. rtm->rtm_pid = getpid();
  105. int fd = socket(PF_ROUTE, SOCK_RAW, 0);
  106. assert (fd > 0);
  107. if (!write(fd, (char*) rtm, sizeof(buf))) {
  108. log_fatal("get-gateway", "unable to send request");
  109. }
  110. size_t len;
  111. while (rtm->rtm_type == RTM_GET && (len = read(fd, rtm, sizeof(buf))) > 0) {
  112. if (len < (int)sizeof(*rtm)) {
  113. return (-1);
  114. }
  115. if (rtm->rtm_type == RTM_GET && rtm->rtm_pid == getpid() && rtm->rtm_seq == seq) {
  116. if (rtm->rtm_errno) {
  117. errno = rtm->rtm_errno;
  118. return (-1);
  119. }
  120. break;
  121. }
  122. }
  123. struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
  124. for (int i = 0; i < RTAX_MAX; i++) {
  125. if (rtm->rtm_addrs & (1 << i)) {
  126. if ((1<<i) == RTA_IFP) {
  127. struct sockaddr_dl *sdl = (struct sockaddr_dl *) sa;
  128. if (!sdl) {
  129. log_fatal("get-gateway", "fuck");
  130. }
  131. char *_iface = xmalloc(sdl->sdl_nlen+1);
  132. memcpy(_iface, sdl->sdl_data, sdl->sdl_nlen);
  133. _iface[sdl->sdl_nlen+1] = 0;
  134. *iface = _iface;
  135. }
  136. if ((1<<i) == RTA_GATEWAY) {
  137. struct sockaddr_in *sin = (struct sockaddr_in *) sa;
  138. gw->s_addr = sin->sin_addr.s_addr;
  139. }
  140. // next element
  141. sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa);
  142. }
  143. }
  144. close(fd);
  145. return EXIT_SUCCESS;
  146. }
  147. char* get_default_iface(void)
  148. {
  149. struct in_addr t;
  150. char *retv = NULL;
  151. _get_default_gw(&t, &retv);
  152. return retv;
  153. }
  154. int get_default_gw(struct in_addr *gw, UNUSED char *iface)
  155. {
  156. char *_iface = NULL;
  157. _get_default_gw(gw, &_iface);
  158. return EXIT_SUCCESS;
  159. }
  160. #endif /* ZMAP_GET_GATEWAY_BSD_H */