summaryrefslogtreecommitdiff
path: root/rdns_scan/zmap4rdns/src/get_gateway-linux.h
diff options
context:
space:
mode:
Diffstat (limited to 'rdns_scan/zmap4rdns/src/get_gateway-linux.h')
-rw-r--r--rdns_scan/zmap4rdns/src/get_gateway-linux.h311
1 files changed, 311 insertions, 0 deletions
diff --git a/rdns_scan/zmap4rdns/src/get_gateway-linux.h b/rdns_scan/zmap4rdns/src/get_gateway-linux.h
new file mode 100644
index 0000000..629c571
--- /dev/null
+++ b/rdns_scan/zmap4rdns/src/get_gateway-linux.h
@@ -0,0 +1,311 @@
+/*
+ * ZMap Copyright 2013 Regents of the University of Michigan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+#ifndef ZMAP_GET_GATEWAY_LINUX_H
+#define ZMAP_GET_GATEWAY_LINUX_H
+
+#ifdef ZMAP_GET_GATEWAY_BSD_H
+#error "Don't include both get_gateway-bsd.h and get_gateway-linux.h"
+#endif
+
+#include <sys/ioctl.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <arpa/inet.h>
+#include <pcap/pcap.h>
+
+#define GW_BUFFER_SIZE 64000
+
+char *get_default_iface(void)
+{
+ char errbuf[PCAP_ERRBUF_SIZE];
+ char *iface = pcap_lookupdev(errbuf);
+ if (iface == NULL) {
+ log_fatal("send", "ZMap could not detect your default network interface. "
+ "You likely do not privileges to open a raw packet socket. "
+ "Are you running as root or with the CAP_NET_RAW capability? If you are, you "
+ "may need to manually set interface using the \"-i\" flag.");
+ }
+ return iface;
+}
+
+int read_nl_sock(int sock, char *buf, int buf_len)
+{
+ int msg_len = 0;
+ char *pbuf = buf;
+ do {
+ int len = recv(sock, pbuf, buf_len - msg_len, 0);
+ if (len <= 0) {
+ log_debug("get-gw", "recv failed: %s", strerror(errno));
+ return -1;
+ }
+ struct nlmsghdr *nlhdr = (struct nlmsghdr *)pbuf;
+ if (NLMSG_OK(nlhdr, ((unsigned int)len)) == 0 ||
+ nlhdr->nlmsg_type == NLMSG_ERROR) {
+ log_debug("get-gw", "recv failed: %s", strerror(errno));
+ return -1;
+ }
+ if (nlhdr->nlmsg_type == NLMSG_DONE) {
+ break;
+ } else {
+ msg_len += len;
+ pbuf += len;
+ }
+ if ((nlhdr->nlmsg_flags & NLM_F_MULTI) == 0) {
+ break;
+ }
+ } while (1);
+ return msg_len;
+}
+
+int send_nl_req(uint16_t msg_type, uint32_t seq, void *payload,
+ uint32_t payload_len)
+{
+ int sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
+ if (sock < 0) {
+ log_error("get-gw", "unable to get socket: %s",
+ strerror(errno));
+ return -1;
+ }
+ if (NLMSG_SPACE(payload_len) < payload_len) {
+ close(sock);
+ // Integer overflow
+ return -1;
+ }
+ struct nlmsghdr *nlmsg;
+ nlmsg = xmalloc(NLMSG_SPACE(payload_len));
+
+ memset(nlmsg, 0, NLMSG_SPACE(payload_len));
+ memcpy(NLMSG_DATA(nlmsg), payload, payload_len);
+ nlmsg->nlmsg_type = msg_type;
+ nlmsg->nlmsg_len = NLMSG_LENGTH(payload_len);
+ nlmsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
+ nlmsg->nlmsg_seq = seq;
+ nlmsg->nlmsg_pid = getpid();
+
+ if (send(sock, nlmsg, nlmsg->nlmsg_len, 0) < 0) {
+ log_error("get-gw", "failure sending: %s", strerror(errno));
+ return -1;
+ }
+ free(nlmsg);
+ return sock;
+}
+
+int get_hw_addr(struct in_addr *gw_ip, char *iface, unsigned char *hw_mac)
+{
+ struct ndmsg req;
+ memset(&req, 0, sizeof(struct ndmsg));
+
+ if (!gw_ip || !hw_mac) {
+ return -1;
+ }
+ // Send RTM_GETNEIGH request
+ req.ndm_family = AF_INET;
+ req.ndm_ifindex = if_nametoindex(iface);
+ req.ndm_state = NUD_REACHABLE;
+ req.ndm_type = NDA_LLADDR;
+
+ int sock = send_nl_req(RTM_GETNEIGH, 1, &req, sizeof(req));
+ // Read responses
+ char *buf = xmalloc(GW_BUFFER_SIZE);
+ int nl_len = read_nl_sock(sock, buf, GW_BUFFER_SIZE);
+ if (nl_len <= 0) {
+ free(buf);
+ return -1;
+ }
+ // Parse responses
+ struct nlmsghdr *nlhdr = (struct nlmsghdr *)buf;
+ while (NLMSG_OK(nlhdr, nl_len)) {
+ struct rtattr *rt_attr;
+ struct rtmsg *rt_msg;
+ int rt_len;
+ unsigned char mac[6];
+ struct in_addr dst_ip;
+ int correct_ip = 0;
+
+ rt_msg = (struct rtmsg *)NLMSG_DATA(nlhdr);
+ if ((rt_msg->rtm_family != AF_INET)) {
+ free(buf);
+ return -1;
+ }
+ rt_attr = (struct rtattr *)RTM_RTA(rt_msg);
+ rt_len = RTM_PAYLOAD(nlhdr);
+ while (RTA_OK(rt_attr, rt_len)) {
+ switch (rt_attr->rta_type) {
+ case NDA_LLADDR:
+ if (RTA_PAYLOAD(rt_attr) != IFHWADDRLEN) {
+ // could be using a VPN
+ log_fatal(
+ "get_gateway",
+ "Unexpected hardware address length (%d)."
+ " If you are using a VPN, supply the --iplayer flag (and provide an"
+ " interface via -i)",
+ RTA_PAYLOAD(rt_attr));
+ }
+ memcpy(mac, RTA_DATA(rt_attr), IFHWADDRLEN);
+ break;
+ case NDA_DST:
+ if (RTA_PAYLOAD(rt_attr) != sizeof(dst_ip)) {
+ // could be using a VPN
+ log_fatal(
+ "get_gateway",
+ "Unexpected IP address length (%d)."
+ " If you are using a VPN, supply the --iplayer flag"
+ " (and provide an interface via -i)",
+ RTA_PAYLOAD(rt_attr));
+ }
+ memcpy(&dst_ip, RTA_DATA(rt_attr),
+ sizeof(dst_ip));
+ if (memcmp(&dst_ip, gw_ip, sizeof(dst_ip)) ==
+ 0) {
+ correct_ip = 1;
+ }
+ break;
+ }
+ rt_attr = RTA_NEXT(rt_attr, rt_len);
+ }
+ if (correct_ip) {
+ memcpy(hw_mac, mac, IFHWADDRLEN);
+ free(buf);
+ return 0;
+ }
+ nlhdr = NLMSG_NEXT(nlhdr, nl_len);
+ }
+ free(buf);
+ return -1;
+}
+
+// gw and iface[IF_NAMESIZE] MUST be allocated
+int _get_default_gw(struct in_addr *gw, char *iface)
+{
+ struct rtmsg req;
+ unsigned int nl_len;
+ char buf[8192];
+ struct nlmsghdr *nlhdr;
+
+ if (!gw || !iface) {
+ return -1;
+ }
+
+ // Send RTM_GETROUTE request
+ memset(&req, 0, sizeof(req));
+ int sock = send_nl_req(RTM_GETROUTE, 0, &req, sizeof(req));
+
+ // Read responses
+ nl_len = read_nl_sock(sock, buf, sizeof(buf));
+ if (nl_len <= 0) {
+ return -1;
+ }
+
+ // Parse responses
+ nlhdr = (struct nlmsghdr *)buf;
+ while (NLMSG_OK(nlhdr, nl_len)) {
+ struct rtattr *rt_attr;
+ struct rtmsg *rt_msg;
+ int rt_len;
+ int has_gw = 0;
+
+ rt_msg = (struct rtmsg *)NLMSG_DATA(nlhdr);
+
+ // There could be multiple routing tables. Loop until we find the
+ // correct one.
+ if ((rt_msg->rtm_family != AF_INET) ||
+ (rt_msg->rtm_table != RT_TABLE_MAIN)) {
+ nlhdr = NLMSG_NEXT(nlhdr, nl_len);
+ continue;
+ }
+
+ rt_attr = (struct rtattr *)RTM_RTA(rt_msg);
+ rt_len = RTM_PAYLOAD(nlhdr);
+ while (RTA_OK(rt_attr, rt_len)) {
+ switch (rt_attr->rta_type) {
+ case RTA_OIF:
+ if_indextoname(*(int *)RTA_DATA(rt_attr),
+ iface);
+ break;
+ case RTA_GATEWAY:
+ gw->s_addr = *(unsigned int *)RTA_DATA(rt_attr);
+ has_gw = 1;
+ break;
+ }
+ rt_attr = RTA_NEXT(rt_attr, rt_len);
+ }
+
+ if (has_gw) {
+ return 0;
+ }
+ nlhdr = NLMSG_NEXT(nlhdr, nl_len);
+ }
+ return -1;
+}
+
+int get_default_gw(struct in_addr *gw, char *iface)
+{
+ char _iface[IF_NAMESIZE];
+ memset(_iface, 0, IF_NAMESIZE);
+
+ _get_default_gw(gw, _iface);
+ if (strcmp(iface, _iface)) {
+ log_fatal(
+ "get-gateway",
+ "The specified network (\"%s\") does not match "
+ "the interface associated with the default gateway (%s). You will "
+ "need to manually specify the MAC address of your gateway using "
+ "the \"--gateway-mac\" flag.", iface, _iface);
+ }
+ return EXIT_SUCCESS;
+}
+
+int get_iface_ip(char *iface, struct in_addr *ip)
+{
+ int sock;
+ struct ifreq ifr;
+ memset(&ifr, 0, sizeof(struct ifreq));
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock < 0) {
+ log_fatal("get-iface-ip", "failure opening socket: %s",
+ strerror(errno));
+ }
+ ifr.ifr_addr.sa_family = AF_INET;
+ strncpy(ifr.ifr_name, iface, IFNAMSIZ - 1);
+
+ if (ioctl(sock, SIOCGIFADDR, &ifr) < 0) {
+ close(sock);
+ log_fatal("get-iface-ip", "Unable to automatically identify the correct "
+ "source address for %s interface. ioctl failure: %s. "
+ "If this is the unexpected interface, you can manually specify "
+ "the correct interface with \"-i\" flag. If this is the correct "
+ "interface, you likely need to manually specify the source IP "
+ "address to use with the \"-S\" flag.", iface, strerror(errno));
+ }
+ ip->s_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
+ close(sock);
+ return EXIT_SUCCESS;
+}
+
+int get_iface_hw_addr(char *iface, unsigned char *hw_mac)
+{
+ int s;
+ struct ifreq buffer;
+
+ // Load the hwaddr from a dummy socket
+ s = socket(PF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+ log_error("get_iface_hw_addr", "Unable to open socket: %s",
+ strerror(errno));
+ return EXIT_FAILURE;
+ }
+ memset(&buffer, 0, sizeof(buffer));
+ strncpy(buffer.ifr_name, iface, IFNAMSIZ);
+ ioctl(s, SIOCGIFHWADDR, &buffer);
+ close(s);
+ memcpy(hw_mac, buffer.ifr_hwaddr.sa_data, 6);
+ return EXIT_SUCCESS;
+}
+
+#endif /* ZMAP_GET_GATEWAY_LINUX_H */