aboutsummaryrefslogtreecommitdiffstats
path: root/src/fnet/arp.c
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2016-10-30 15:54:05 -0400
committerLibravatar netblue30 <netblue30@yahoo.com>2016-10-30 15:54:05 -0400
commitf898290fd79e0e64d13ceef56fc5960da879d179 (patch)
tree7112345d8121d1d61f90995e09754bbfbfbf467f /src/fnet/arp.c
parentMerge pull request #878 from msva/patch-1 (diff)
downloadfirejail-f898290fd79e0e64d13ceef56fc5960da879d179.tar.gz
firejail-f898290fd79e0e64d13ceef56fc5960da879d179.tar.zst
firejail-f898290fd79e0e64d13ceef56fc5960da879d179.zip
major cleanup
Diffstat (limited to 'src/fnet/arp.c')
-rw-r--r--src/fnet/arp.c208
1 files changed, 208 insertions, 0 deletions
diff --git a/src/fnet/arp.c b/src/fnet/arp.c
new file mode 100644
index 000000000..96684fdf9
--- /dev/null
+++ b/src/fnet/arp.c
@@ -0,0 +1,208 @@
1/*
2 * Copyright (C) 2014-2016 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "fnet.h"
21#include <sys/socket.h>
22#include <sys/ioctl.h>
23#include <linux/if_ether.h> //TCP/IP Protocol Suite for Linux
24#include <net/if.h>
25#include <netinet/in.h>
26#include <linux/ip.h>
27#include <linux/udp.h>
28#include <linux/tcp.h>
29#include <linux/if_packet.h>
30
31typedef struct arp_hdr_t {
32 uint16_t htype;
33 uint16_t ptype;
34 uint8_t hlen;
35 uint8_t plen;
36 uint16_t opcode;
37 uint8_t sender_mac[6];
38 uint8_t sender_ip[4];
39 uint8_t target_mac[6];
40 uint8_t target_ip[4];
41} ArpHdr;
42
43
44// scan interface (--scan option)
45void arp_scan(const char *dev, uint32_t ifip, uint32_t ifmask) {
46 assert(dev);
47 assert(ifip);
48
49// printf("Scanning interface %s (%d.%d.%d.%d/%d)\n",
50// dev, PRINT_IP(ifip & ifmask), mask2bits(ifmask));
51
52 if (strlen(dev) > IFNAMSIZ) {
53 fprintf(stderr, "Error: invalid network device name %s\n", dev);
54 exit(1);
55 }
56
57 // find interface mac address
58 int sock;
59 if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
60 errExit("socket");
61 struct ifreq ifr;
62 memset(&ifr, 0, sizeof (ifr));
63 strncpy(ifr.ifr_name, dev, IFNAMSIZ);
64 if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0)
65 errExit("ioctl");
66 close(sock);
67 uint8_t mac[6];
68 memcpy (mac, ifr.ifr_hwaddr.sa_data, 6);
69
70 // open layer2 socket
71 if ((sock = socket(PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0)
72 errExit("socket");
73
74 // try all possible ip addresses in ascending order
75 uint32_t range = ~ifmask + 1; // the number of potential addresses
76 // this software is not supported for /31 networks
77 if (range < 4) {
78 fprintf(stderr, "Warning: this option is not supported for /31 networks\n");
79 close(sock);
80 return;
81 }
82
83 uint32_t dest = (ifip & ifmask) + 1;
84 uint32_t last = dest + range - 1;
85 uint32_t src = htonl(ifip);
86
87 // wait not more than one second for an answer
88 int header_printed = 0;
89 uint32_t last_ip = 0;
90 struct timeval ts;
91 ts.tv_sec = 2; // 2 seconds receive timeout
92 ts.tv_usec = 0;
93
94 while (1) {
95 fd_set rfds;
96 FD_ZERO(&rfds);
97 FD_SET(sock, &rfds);
98 fd_set wfds;
99 FD_ZERO(&wfds);
100 FD_SET(sock, &wfds);
101 int maxfd = sock;
102
103 uint8_t frame[ETH_FRAME_LEN]; // includes eht header, vlan, and crc
104 memset(frame, 0, ETH_FRAME_LEN);
105
106 int nready;
107 if (dest < last)
108 nready = select(maxfd + 1, &rfds, &wfds, (fd_set *) 0, NULL);
109 else
110 nready = select(maxfd + 1, &rfds, (fd_set *) 0, (fd_set *) 0, &ts);
111
112 if (nready < 0)
113 errExit("select");
114
115 if (nready == 0) { // timeout
116 break;
117 }
118
119 if (FD_ISSET(sock, &wfds) && dest < last) {
120 // configure layer2 socket address information
121 struct sockaddr_ll addr;
122 memset(&addr, 0, sizeof(addr));
123 if ((addr.sll_ifindex = if_nametoindex(dev)) == 0)
124 errExit("if_nametoindex");
125 addr.sll_family = AF_PACKET;
126 memcpy (addr.sll_addr, mac, 6);
127 addr.sll_halen = htons(6);
128
129 // build the arp packet header
130 ArpHdr hdr;
131 memset(&hdr, 0, sizeof(hdr));
132 hdr.htype = htons(1);
133 hdr.ptype = htons(ETH_P_IP);
134 hdr.hlen = 6;
135 hdr.plen = 4;
136 hdr.opcode = htons(1); //ARPOP_REQUEST
137 memcpy(hdr.sender_mac, mac, 6);
138 memcpy(hdr.sender_ip, (uint8_t *)&src, 4);
139 uint32_t dst = htonl(dest);
140 memcpy(hdr.target_ip, (uint8_t *)&dst, 4);
141
142 // build ethernet frame
143 uint8_t frame[ETH_FRAME_LEN]; // includes eht header, vlan, and crc
144 memset(frame, 0, sizeof(frame));
145 frame[0] = frame[1] = frame[2] = frame[3] = frame[4] = frame[5] = 0xff;
146 memcpy(frame + 6, mac, 6);
147 frame[12] = ETH_P_ARP / 256;
148 frame[13] = ETH_P_ARP % 256;
149 memcpy (frame + 14, &hdr, sizeof(hdr));
150
151 // send packet
152 int len;
153 if ((len = sendto (sock, frame, 14 + sizeof(ArpHdr), 0, (struct sockaddr *) &addr, sizeof (addr))) <= 0)
154 errExit("send");
155//printf("send %d bytes to %d.%d.%d.%d\n", len, PRINT_IP(dest));
156 fflush(0);
157 dest++;
158 }
159
160 if (FD_ISSET(sock, &rfds)) {
161 // read the incoming packet
162 int len = recvfrom(sock, frame, ETH_FRAME_LEN, 0, NULL, NULL);
163 if (len < 0) {
164 perror("recvfrom");
165 }
166
167 // parse the incoming packet
168 if ((unsigned int) len < 14 + sizeof(ArpHdr))
169 continue;
170
171 // look only at ARP packets
172 if (frame[12] != (ETH_P_ARP / 256) || frame[13] != (ETH_P_ARP % 256))
173 continue;
174
175 ArpHdr hdr;
176 memcpy(&hdr, frame + 14, sizeof(ArpHdr));
177
178 if (hdr.opcode == htons(2)) {
179 // check my mac and my address
180 if (memcmp(mac, hdr.target_mac, 6) != 0)
181 continue;
182 uint32_t ip;
183 memcpy(&ip, hdr.target_ip, 4);
184 if (ip != src)
185 continue;
186 memcpy(&ip, hdr.sender_ip, 4);
187 ip = ntohl(ip);
188
189 if (ip == last_ip) // filter duplicates
190 continue;
191 last_ip = ip;
192
193 // printing
194 if (header_printed == 0) {
195 printf(" Network scan:\n");
196 header_printed = 1;
197 }
198 printf(" %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n",
199 PRINT_MAC(hdr.sender_mac), PRINT_IP(ip));
200 }
201 }
202 }
203
204 close(sock);
205}
206
207
208