1*cf5a6c84SAndroid Build Coastguard Worker /* arping - send ARP REQUEST to a neighbour host.
2*cf5a6c84SAndroid Build Coastguard Worker *
3*cf5a6c84SAndroid Build Coastguard Worker * Copyright 2013 Sandeep Sharma <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker * Copyright 2013 Kyungwan Han <[email protected]>
5*cf5a6c84SAndroid Build Coastguard Worker *
6*cf5a6c84SAndroid Build Coastguard Worker * No Standard.
7*cf5a6c84SAndroid Build Coastguard Worker
8*cf5a6c84SAndroid Build Coastguard Worker USE_ARPING(NEWTOY(arping, "<1>1s:I:w#<0c#<0AUDbqf[+AU][+Df]", TOYFLAG_USR|TOYFLAG_SBIN))
9*cf5a6c84SAndroid Build Coastguard Worker
10*cf5a6c84SAndroid Build Coastguard Worker config ARPING
11*cf5a6c84SAndroid Build Coastguard Worker bool "arping"
12*cf5a6c84SAndroid Build Coastguard Worker default n
13*cf5a6c84SAndroid Build Coastguard Worker help
14*cf5a6c84SAndroid Build Coastguard Worker usage: arping [-fqbDUA] [-c CNT] [-w TIMEOUT] [-I IFACE] [-s SRC_IP] DST_IP
15*cf5a6c84SAndroid Build Coastguard Worker
16*cf5a6c84SAndroid Build Coastguard Worker Send ARP requests/replies
17*cf5a6c84SAndroid Build Coastguard Worker
18*cf5a6c84SAndroid Build Coastguard Worker -f Quit on first ARP reply
19*cf5a6c84SAndroid Build Coastguard Worker -q Quiet
20*cf5a6c84SAndroid Build Coastguard Worker -b Keep broadcasting, don't go unicast
21*cf5a6c84SAndroid Build Coastguard Worker -D Duplicated address detection mode
22*cf5a6c84SAndroid Build Coastguard Worker -U Unsolicited ARP mode, update your neighbors
23*cf5a6c84SAndroid Build Coastguard Worker -A ARP answer mode, update your neighbors
24*cf5a6c84SAndroid Build Coastguard Worker -c N Stop after sending N ARP requests
25*cf5a6c84SAndroid Build Coastguard Worker -w TIMEOUT Time to wait for ARP reply, seconds
26*cf5a6c84SAndroid Build Coastguard Worker -I IFACE Interface to use (default eth0)
27*cf5a6c84SAndroid Build Coastguard Worker -s SRC_IP Sender IP address
28*cf5a6c84SAndroid Build Coastguard Worker DST_IP Target IP address
29*cf5a6c84SAndroid Build Coastguard Worker */
30*cf5a6c84SAndroid Build Coastguard Worker #define FOR_arping
31*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
32*cf5a6c84SAndroid Build Coastguard Worker #include <netinet/ether.h>
33*cf5a6c84SAndroid Build Coastguard Worker #include <netpacket/packet.h>
34*cf5a6c84SAndroid Build Coastguard Worker
35*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
36*cf5a6c84SAndroid Build Coastguard Worker long count;
37*cf5a6c84SAndroid Build Coastguard Worker unsigned long time_out;
38*cf5a6c84SAndroid Build Coastguard Worker char *iface;
39*cf5a6c84SAndroid Build Coastguard Worker char *src_ip;
40*cf5a6c84SAndroid Build Coastguard Worker
41*cf5a6c84SAndroid Build Coastguard Worker int sockfd;
42*cf5a6c84SAndroid Build Coastguard Worker unsigned long start, end;
43*cf5a6c84SAndroid Build Coastguard Worker unsigned sent_at, sent_nr, rcvd_nr, brd_sent, rcvd_req, brd_rcv,
44*cf5a6c84SAndroid Build Coastguard Worker unicast_flag;
45*cf5a6c84SAndroid Build Coastguard Worker )
46*cf5a6c84SAndroid Build Coastguard Worker
47*cf5a6c84SAndroid Build Coastguard Worker struct sockaddr_ll src_pk, dst_pk;
48*cf5a6c84SAndroid Build Coastguard Worker struct in_addr src_addr, dest_addr;
49*cf5a6c84SAndroid Build Coastguard Worker extern void *mempcpy(void *dest, const void *src, size_t n);
50*cf5a6c84SAndroid Build Coastguard Worker
51*cf5a6c84SAndroid Build Coastguard Worker // Gets information of INTERFACE and updates IFINDEX, MAC and IP.
get_interface(char * interface,int * ifindex,uint32_t * oip,uint8_t * mac)52*cf5a6c84SAndroid Build Coastguard Worker static void get_interface(char *interface, int *ifindex, uint32_t *oip,
53*cf5a6c84SAndroid Build Coastguard Worker uint8_t *mac)
54*cf5a6c84SAndroid Build Coastguard Worker {
55*cf5a6c84SAndroid Build Coastguard Worker struct ifreq req;
56*cf5a6c84SAndroid Build Coastguard Worker struct sockaddr_in *ip;
57*cf5a6c84SAndroid Build Coastguard Worker int fd = xsocket(AF_INET, SOCK_RAW, IPPROTO_RAW);
58*cf5a6c84SAndroid Build Coastguard Worker
59*cf5a6c84SAndroid Build Coastguard Worker req.ifr_addr.sa_family = AF_INET;
60*cf5a6c84SAndroid Build Coastguard Worker xstrncpy(req.ifr_name, interface, IFNAMSIZ);
61*cf5a6c84SAndroid Build Coastguard Worker req.ifr_name[IFNAMSIZ-1] = '\0';
62*cf5a6c84SAndroid Build Coastguard Worker
63*cf5a6c84SAndroid Build Coastguard Worker xioctl(fd, SIOCGIFFLAGS, &req);
64*cf5a6c84SAndroid Build Coastguard Worker if (!(req.ifr_flags & IFF_UP)) return;
65*cf5a6c84SAndroid Build Coastguard Worker
66*cf5a6c84SAndroid Build Coastguard Worker if (oip) {
67*cf5a6c84SAndroid Build Coastguard Worker xioctl(fd, SIOCGIFADDR, &req);
68*cf5a6c84SAndroid Build Coastguard Worker ip = (struct sockaddr_in*) &req.ifr_addr;
69*cf5a6c84SAndroid Build Coastguard Worker *oip = ntohl(ip->sin_addr.s_addr);
70*cf5a6c84SAndroid Build Coastguard Worker }
71*cf5a6c84SAndroid Build Coastguard Worker if (ifindex) {
72*cf5a6c84SAndroid Build Coastguard Worker xioctl(fd, SIOCGIFINDEX, &req);
73*cf5a6c84SAndroid Build Coastguard Worker *ifindex = req.ifr_ifindex;
74*cf5a6c84SAndroid Build Coastguard Worker }
75*cf5a6c84SAndroid Build Coastguard Worker if (mac) {
76*cf5a6c84SAndroid Build Coastguard Worker xioctl(fd, SIOCGIFHWADDR, &req);
77*cf5a6c84SAndroid Build Coastguard Worker memcpy(mac, req.ifr_hwaddr.sa_data, 6);
78*cf5a6c84SAndroid Build Coastguard Worker }
79*cf5a6c84SAndroid Build Coastguard Worker xclose(fd);
80*cf5a6c84SAndroid Build Coastguard Worker }
81*cf5a6c84SAndroid Build Coastguard Worker
82*cf5a6c84SAndroid Build Coastguard Worker // SIGINT handler, Print Number of Packets send or receive details.
done(int sig)83*cf5a6c84SAndroid Build Coastguard Worker static void done(int sig)
84*cf5a6c84SAndroid Build Coastguard Worker {
85*cf5a6c84SAndroid Build Coastguard Worker if (!(toys.optflags & FLAG_q)) {
86*cf5a6c84SAndroid Build Coastguard Worker xprintf("Sent %u probe(s) (%u broadcast(s))\n", TT.sent_nr, TT.brd_sent);
87*cf5a6c84SAndroid Build Coastguard Worker xprintf("Received %u repl%s (%u request(s), %u broadcast(s))\n",
88*cf5a6c84SAndroid Build Coastguard Worker TT.rcvd_nr, TT.rcvd_nr == 1 ? "y":"ies", TT.rcvd_req, TT.brd_rcv);
89*cf5a6c84SAndroid Build Coastguard Worker }
90*cf5a6c84SAndroid Build Coastguard Worker if (toys.optflags & FLAG_D) exit(!!TT.rcvd_nr);
91*cf5a6c84SAndroid Build Coastguard Worker //In -U mode, No reply is expected.
92*cf5a6c84SAndroid Build Coastguard Worker if (toys.optflags & FLAG_U) exit(EXIT_SUCCESS);
93*cf5a6c84SAndroid Build Coastguard Worker exit(!TT.rcvd_nr);
94*cf5a6c84SAndroid Build Coastguard Worker }
95*cf5a6c84SAndroid Build Coastguard Worker
96*cf5a6c84SAndroid Build Coastguard Worker // Create and Send Packet
send_packet()97*cf5a6c84SAndroid Build Coastguard Worker static void send_packet()
98*cf5a6c84SAndroid Build Coastguard Worker {
99*cf5a6c84SAndroid Build Coastguard Worker int ret;
100*cf5a6c84SAndroid Build Coastguard Worker unsigned char sbuf[256] = {0,};
101*cf5a6c84SAndroid Build Coastguard Worker struct arphdr *arp_h = (struct arphdr *) sbuf;
102*cf5a6c84SAndroid Build Coastguard Worker unsigned char *ptr = (unsigned char *)(arp_h + 1);
103*cf5a6c84SAndroid Build Coastguard Worker
104*cf5a6c84SAndroid Build Coastguard Worker arp_h->ar_hrd = htons(ARPHRD_ETHER);
105*cf5a6c84SAndroid Build Coastguard Worker arp_h->ar_pro = htons(ETH_P_IP);
106*cf5a6c84SAndroid Build Coastguard Worker arp_h->ar_hln = src_pk.sll_halen;
107*cf5a6c84SAndroid Build Coastguard Worker arp_h->ar_pln = 4;
108*cf5a6c84SAndroid Build Coastguard Worker arp_h->ar_op = (toys.optflags & FLAG_A) ? htons(ARPOP_REPLY)
109*cf5a6c84SAndroid Build Coastguard Worker : htons(ARPOP_REQUEST);
110*cf5a6c84SAndroid Build Coastguard Worker
111*cf5a6c84SAndroid Build Coastguard Worker ptr = mempcpy(ptr, &src_pk.sll_addr, src_pk.sll_halen);
112*cf5a6c84SAndroid Build Coastguard Worker ptr = mempcpy(ptr, &src_addr, 4);
113*cf5a6c84SAndroid Build Coastguard Worker ptr = mempcpy(ptr,
114*cf5a6c84SAndroid Build Coastguard Worker (toys.optflags & FLAG_A) ? &src_pk.sll_addr : &dst_pk.sll_addr,
115*cf5a6c84SAndroid Build Coastguard Worker src_pk.sll_halen);
116*cf5a6c84SAndroid Build Coastguard Worker ptr = mempcpy(ptr, &dest_addr, 4);
117*cf5a6c84SAndroid Build Coastguard Worker
118*cf5a6c84SAndroid Build Coastguard Worker ret = sendto(TT.sockfd, sbuf, ptr - sbuf, 0,
119*cf5a6c84SAndroid Build Coastguard Worker (struct sockaddr *)&dst_pk, sizeof(dst_pk));
120*cf5a6c84SAndroid Build Coastguard Worker if (ret == ptr - sbuf) {
121*cf5a6c84SAndroid Build Coastguard Worker struct timeval tval;
122*cf5a6c84SAndroid Build Coastguard Worker
123*cf5a6c84SAndroid Build Coastguard Worker gettimeofday(&tval, NULL);
124*cf5a6c84SAndroid Build Coastguard Worker TT.sent_at = tval.tv_sec * 1000000ULL + tval.tv_usec;
125*cf5a6c84SAndroid Build Coastguard Worker TT.sent_nr++;
126*cf5a6c84SAndroid Build Coastguard Worker if (!TT.unicast_flag) TT.brd_sent++;
127*cf5a6c84SAndroid Build Coastguard Worker }
128*cf5a6c84SAndroid Build Coastguard Worker }
129*cf5a6c84SAndroid Build Coastguard Worker
130*cf5a6c84SAndroid Build Coastguard Worker // Receive Packet and filter with valid checks.
recv_from(struct sockaddr_ll * from,int * recv_len)131*cf5a6c84SAndroid Build Coastguard Worker static void recv_from(struct sockaddr_ll *from, int *recv_len)
132*cf5a6c84SAndroid Build Coastguard Worker {
133*cf5a6c84SAndroid Build Coastguard Worker struct in_addr s_ip, d_ip;
134*cf5a6c84SAndroid Build Coastguard Worker struct arphdr *arp_hdr = (struct arphdr *)toybuf;
135*cf5a6c84SAndroid Build Coastguard Worker unsigned char *p = (unsigned char *)(arp_hdr + 1);
136*cf5a6c84SAndroid Build Coastguard Worker
137*cf5a6c84SAndroid Build Coastguard Worker if (arp_hdr->ar_op != htons(ARPOP_REQUEST) &&
138*cf5a6c84SAndroid Build Coastguard Worker arp_hdr->ar_op != htons(ARPOP_REPLY)) return;
139*cf5a6c84SAndroid Build Coastguard Worker
140*cf5a6c84SAndroid Build Coastguard Worker if (from->sll_pkttype != PACKET_HOST && from->sll_pkttype != PACKET_BROADCAST
141*cf5a6c84SAndroid Build Coastguard Worker && from->sll_pkttype != PACKET_MULTICAST) return;
142*cf5a6c84SAndroid Build Coastguard Worker
143*cf5a6c84SAndroid Build Coastguard Worker if (arp_hdr->ar_pro != htons(ETH_P_IP) || (arp_hdr->ar_pln != 4)
144*cf5a6c84SAndroid Build Coastguard Worker || (arp_hdr->ar_hln != src_pk.sll_halen)
145*cf5a6c84SAndroid Build Coastguard Worker || (*recv_len < (int)(sizeof(*arp_hdr) + 2 * (4 + arp_hdr->ar_hln))))
146*cf5a6c84SAndroid Build Coastguard Worker return;
147*cf5a6c84SAndroid Build Coastguard Worker
148*cf5a6c84SAndroid Build Coastguard Worker memcpy(&s_ip.s_addr, p + arp_hdr->ar_hln, 4);
149*cf5a6c84SAndroid Build Coastguard Worker memcpy(&d_ip.s_addr, p + arp_hdr->ar_hln + 4 + arp_hdr->ar_hln, 4);
150*cf5a6c84SAndroid Build Coastguard Worker
151*cf5a6c84SAndroid Build Coastguard Worker if (dest_addr.s_addr != s_ip.s_addr) return;
152*cf5a6c84SAndroid Build Coastguard Worker if (toys.optflags & FLAG_D) {
153*cf5a6c84SAndroid Build Coastguard Worker if (src_addr.s_addr && src_addr.s_addr != d_ip.s_addr) return;
154*cf5a6c84SAndroid Build Coastguard Worker if (!memcmp(p, &src_pk.sll_addr, src_pk.sll_halen)) return;
155*cf5a6c84SAndroid Build Coastguard Worker } else if (src_addr.s_addr != d_ip.s_addr ) return;
156*cf5a6c84SAndroid Build Coastguard Worker
157*cf5a6c84SAndroid Build Coastguard Worker if (!(toys.optflags & FLAG_q)) {
158*cf5a6c84SAndroid Build Coastguard Worker printf("%scast re%s from %s [%s]",
159*cf5a6c84SAndroid Build Coastguard Worker from->sll_pkttype == PACKET_HOST ? "Uni" : "Broad",
160*cf5a6c84SAndroid Build Coastguard Worker arp_hdr->ar_op == htons(ARPOP_REPLY) ? "ply" : "quest",
161*cf5a6c84SAndroid Build Coastguard Worker inet_ntoa(s_ip), ether_ntoa((struct ether_addr *) p));
162*cf5a6c84SAndroid Build Coastguard Worker if (TT.sent_at) {
163*cf5a6c84SAndroid Build Coastguard Worker unsigned delta;
164*cf5a6c84SAndroid Build Coastguard Worker struct timeval tval;
165*cf5a6c84SAndroid Build Coastguard Worker
166*cf5a6c84SAndroid Build Coastguard Worker gettimeofday(&tval, NULL);
167*cf5a6c84SAndroid Build Coastguard Worker delta = (tval.tv_sec * 1000000ULL + (tval.tv_usec)) - TT.sent_at;
168*cf5a6c84SAndroid Build Coastguard Worker xprintf(" %u.%03ums\n", delta / 1000, delta % 1000);
169*cf5a6c84SAndroid Build Coastguard Worker }
170*cf5a6c84SAndroid Build Coastguard Worker }
171*cf5a6c84SAndroid Build Coastguard Worker TT.rcvd_nr++;
172*cf5a6c84SAndroid Build Coastguard Worker if (from->sll_pkttype != PACKET_HOST) TT.brd_rcv++;
173*cf5a6c84SAndroid Build Coastguard Worker if (arp_hdr->ar_op == htons(ARPOP_REQUEST)) TT.rcvd_req++;
174*cf5a6c84SAndroid Build Coastguard Worker if (toys.optflags & FLAG_f) done(0);
175*cf5a6c84SAndroid Build Coastguard Worker if (!(toys.optflags & FLAG_b)) {
176*cf5a6c84SAndroid Build Coastguard Worker memcpy(dst_pk.sll_addr, p, src_pk.sll_halen);
177*cf5a6c84SAndroid Build Coastguard Worker TT.unicast_flag = 1;
178*cf5a6c84SAndroid Build Coastguard Worker }
179*cf5a6c84SAndroid Build Coastguard Worker }
180*cf5a6c84SAndroid Build Coastguard Worker
181*cf5a6c84SAndroid Build Coastguard Worker // Alarm signal Handle, send packets in one second interval.
send_signal(int sig)182*cf5a6c84SAndroid Build Coastguard Worker static void send_signal(int sig)
183*cf5a6c84SAndroid Build Coastguard Worker {
184*cf5a6c84SAndroid Build Coastguard Worker struct timeval start;
185*cf5a6c84SAndroid Build Coastguard Worker
186*cf5a6c84SAndroid Build Coastguard Worker gettimeofday(&start, NULL);
187*cf5a6c84SAndroid Build Coastguard Worker if (!TT.start)
188*cf5a6c84SAndroid Build Coastguard Worker TT.end = TT.start = start.tv_sec * 1000 + start.tv_usec / 1000;
189*cf5a6c84SAndroid Build Coastguard Worker else TT.end = start.tv_sec*1000 + start.tv_usec / 1000;
190*cf5a6c84SAndroid Build Coastguard Worker if (toys.optflags & FLAG_c) {
191*cf5a6c84SAndroid Build Coastguard Worker if (!TT.count) done(0);
192*cf5a6c84SAndroid Build Coastguard Worker TT.count--;
193*cf5a6c84SAndroid Build Coastguard Worker }
194*cf5a6c84SAndroid Build Coastguard Worker if ((toys.optflags & FLAG_w) && ((TT.end - TT.start) >
195*cf5a6c84SAndroid Build Coastguard Worker ((TT.time_out)*1000))) done(0);
196*cf5a6c84SAndroid Build Coastguard Worker send_packet();
197*cf5a6c84SAndroid Build Coastguard Worker alarm(1);
198*cf5a6c84SAndroid Build Coastguard Worker }
199*cf5a6c84SAndroid Build Coastguard Worker
arping_main(void)200*cf5a6c84SAndroid Build Coastguard Worker void arping_main(void)
201*cf5a6c84SAndroid Build Coastguard Worker {
202*cf5a6c84SAndroid Build Coastguard Worker struct ifreq ifr;
203*cf5a6c84SAndroid Build Coastguard Worker struct sockaddr_ll from;
204*cf5a6c84SAndroid Build Coastguard Worker socklen_t len;
205*cf5a6c84SAndroid Build Coastguard Worker int if_index, recv_len;
206*cf5a6c84SAndroid Build Coastguard Worker
207*cf5a6c84SAndroid Build Coastguard Worker if (!(toys.optflags & FLAG_I)) TT.iface = "eth0";
208*cf5a6c84SAndroid Build Coastguard Worker TT.sockfd = xsocket(AF_PACKET, SOCK_DGRAM, 0);
209*cf5a6c84SAndroid Build Coastguard Worker
210*cf5a6c84SAndroid Build Coastguard Worker memset(&ifr, 0, sizeof(ifr));
211*cf5a6c84SAndroid Build Coastguard Worker xstrncpy(ifr.ifr_name, TT.iface, IFNAMSIZ);
212*cf5a6c84SAndroid Build Coastguard Worker get_interface(TT.iface, &if_index, NULL, NULL);
213*cf5a6c84SAndroid Build Coastguard Worker src_pk.sll_ifindex = if_index;
214*cf5a6c84SAndroid Build Coastguard Worker
215*cf5a6c84SAndroid Build Coastguard Worker xioctl(TT.sockfd, SIOCGIFFLAGS, (char*)&ifr);
216*cf5a6c84SAndroid Build Coastguard Worker if (!(ifr.ifr_flags & IFF_UP) && !(toys.optflags & FLAG_q))
217*cf5a6c84SAndroid Build Coastguard Worker error_exit("Interface \"%s\" is down", TT.iface);
218*cf5a6c84SAndroid Build Coastguard Worker if ((ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK))
219*cf5a6c84SAndroid Build Coastguard Worker && !(toys.optflags & FLAG_q)) {
220*cf5a6c84SAndroid Build Coastguard Worker xprintf("Interface \"%s\" is not ARPable\n", TT.iface);
221*cf5a6c84SAndroid Build Coastguard Worker toys.exitval = (toys.optflags & FLAG_D) ? 0 : 2;
222*cf5a6c84SAndroid Build Coastguard Worker return;
223*cf5a6c84SAndroid Build Coastguard Worker }
224*cf5a6c84SAndroid Build Coastguard Worker if (!inet_aton(*toys.optargs, &dest_addr)) {
225*cf5a6c84SAndroid Build Coastguard Worker struct hostent *hp = gethostbyname2(*toys.optargs, AF_INET);
226*cf5a6c84SAndroid Build Coastguard Worker
227*cf5a6c84SAndroid Build Coastguard Worker if (!hp) perror_exit("bad address '%s'", *toys.optargs);
228*cf5a6c84SAndroid Build Coastguard Worker memcpy(&dest_addr, hp->h_addr, 4);
229*cf5a6c84SAndroid Build Coastguard Worker }
230*cf5a6c84SAndroid Build Coastguard Worker if ((toys.optflags & FLAG_s) && !(inet_aton(TT.src_ip, &src_addr)))
231*cf5a6c84SAndroid Build Coastguard Worker perror_exit("invalid source address '%s'",TT.src_ip);
232*cf5a6c84SAndroid Build Coastguard Worker if (!(toys.optflags & FLAG_D) && (toys.optflags & FLAG_U)
233*cf5a6c84SAndroid Build Coastguard Worker && !src_addr.s_addr) src_addr = dest_addr;
234*cf5a6c84SAndroid Build Coastguard Worker if (!(toys.optflags & FLAG_D) || src_addr.s_addr) {
235*cf5a6c84SAndroid Build Coastguard Worker struct sockaddr_in saddr;
236*cf5a6c84SAndroid Build Coastguard Worker int p_fd = xsocket(AF_INET, SOCK_DGRAM, 0);
237*cf5a6c84SAndroid Build Coastguard Worker
238*cf5a6c84SAndroid Build Coastguard Worker if (setsockopt(p_fd, SOL_SOCKET, SO_BINDTODEVICE, TT.iface,
239*cf5a6c84SAndroid Build Coastguard Worker strlen(TT.iface))) perror_exit("setsockopt");
240*cf5a6c84SAndroid Build Coastguard Worker
241*cf5a6c84SAndroid Build Coastguard Worker memset(&saddr, 0, sizeof(saddr));
242*cf5a6c84SAndroid Build Coastguard Worker saddr.sin_family = AF_INET;
243*cf5a6c84SAndroid Build Coastguard Worker if (src_addr.s_addr) {
244*cf5a6c84SAndroid Build Coastguard Worker saddr.sin_addr = src_addr;
245*cf5a6c84SAndroid Build Coastguard Worker xbind(p_fd, (struct sockaddr*)&saddr, sizeof(saddr));
246*cf5a6c84SAndroid Build Coastguard Worker } else {
247*cf5a6c84SAndroid Build Coastguard Worker uint32_t oip;
248*cf5a6c84SAndroid Build Coastguard Worker
249*cf5a6c84SAndroid Build Coastguard Worker saddr.sin_port = htons(1025);
250*cf5a6c84SAndroid Build Coastguard Worker saddr.sin_addr = dest_addr;
251*cf5a6c84SAndroid Build Coastguard Worker xconnect(p_fd, (struct sockaddr *) &saddr, sizeof(saddr));
252*cf5a6c84SAndroid Build Coastguard Worker get_interface(TT.iface, NULL, &oip, NULL);
253*cf5a6c84SAndroid Build Coastguard Worker src_addr.s_addr = htonl(oip);
254*cf5a6c84SAndroid Build Coastguard Worker }
255*cf5a6c84SAndroid Build Coastguard Worker xclose(p_fd);
256*cf5a6c84SAndroid Build Coastguard Worker }
257*cf5a6c84SAndroid Build Coastguard Worker
258*cf5a6c84SAndroid Build Coastguard Worker src_pk.sll_family = AF_PACKET;
259*cf5a6c84SAndroid Build Coastguard Worker src_pk.sll_protocol = htons(ETH_P_ARP);
260*cf5a6c84SAndroid Build Coastguard Worker xbind(TT.sockfd, (struct sockaddr *)&src_pk, sizeof(src_pk));
261*cf5a6c84SAndroid Build Coastguard Worker
262*cf5a6c84SAndroid Build Coastguard Worker socklen_t alen = sizeof(src_pk);
263*cf5a6c84SAndroid Build Coastguard Worker getsockname(TT.sockfd, (struct sockaddr *)&src_pk, &alen);
264*cf5a6c84SAndroid Build Coastguard Worker if (!src_pk.sll_halen) {
265*cf5a6c84SAndroid Build Coastguard Worker perror_msg("src is not arpable");
266*cf5a6c84SAndroid Build Coastguard Worker toys.exitval = (toys.optflags & FLAG_D) ? 0 : 2;
267*cf5a6c84SAndroid Build Coastguard Worker return;
268*cf5a6c84SAndroid Build Coastguard Worker }
269*cf5a6c84SAndroid Build Coastguard Worker if (!(toys.optflags & FLAG_q)) {
270*cf5a6c84SAndroid Build Coastguard Worker xprintf("ARPING to %s", inet_ntoa(dest_addr));
271*cf5a6c84SAndroid Build Coastguard Worker xprintf(" from %s via %s\n", inet_ntoa(src_addr), TT.iface);
272*cf5a6c84SAndroid Build Coastguard Worker }
273*cf5a6c84SAndroid Build Coastguard Worker
274*cf5a6c84SAndroid Build Coastguard Worker dst_pk = src_pk;
275*cf5a6c84SAndroid Build Coastguard Worker //First packet always broadcasts.
276*cf5a6c84SAndroid Build Coastguard Worker memset(dst_pk.sll_addr, -1, dst_pk.sll_halen);
277*cf5a6c84SAndroid Build Coastguard Worker signal(SIGINT, done);
278*cf5a6c84SAndroid Build Coastguard Worker signal(SIGALRM, send_signal);
279*cf5a6c84SAndroid Build Coastguard Worker
280*cf5a6c84SAndroid Build Coastguard Worker send_signal(0); // Send first Broadcast message.
281*cf5a6c84SAndroid Build Coastguard Worker while (1) {
282*cf5a6c84SAndroid Build Coastguard Worker len = sizeof(from);
283*cf5a6c84SAndroid Build Coastguard Worker recv_len = recvfrom(TT.sockfd, toybuf, 4096, 0,
284*cf5a6c84SAndroid Build Coastguard Worker (struct sockaddr *)&from, &len);
285*cf5a6c84SAndroid Build Coastguard Worker if (recv_len < 0) continue;
286*cf5a6c84SAndroid Build Coastguard Worker recv_from(&from, &recv_len);
287*cf5a6c84SAndroid Build Coastguard Worker }
288*cf5a6c84SAndroid Build Coastguard Worker }
289