153 |
struct arphdr *ah = (struct arphdr *) buf; |
struct arphdr *ah = (struct arphdr *) buf; |
154 |
unsigned char *p = (unsigned char *) (ah + 1); |
unsigned char *p = (unsigned char *) (ah + 1); |
155 |
struct in_addr src_ip, dst_ip; |
struct in_addr src_ip, dst_ip; |
156 |
|
/* moves below assume in_addr is 4 bytes big, ensure that */ |
157 |
|
struct BUG_in_addr_must_be_4 { |
158 |
|
char BUG_in_addr_must_be_4[ |
159 |
|
sizeof(struct in_addr) == 4 ? 1 : -1 |
160 |
|
]; |
161 |
|
char BUG_s_addr_must_be_4[ |
162 |
|
sizeof(src_ip.s_addr) == 4 ? 1 : -1 |
163 |
|
]; |
164 |
|
}; |
165 |
|
|
166 |
/* Filter out wild packets */ |
/* Filter out wild packets */ |
167 |
if (FROM->sll_pkttype != PACKET_HOST |
if (FROM->sll_pkttype != PACKET_HOST |
169 |
&& FROM->sll_pkttype != PACKET_MULTICAST) |
&& FROM->sll_pkttype != PACKET_MULTICAST) |
170 |
return false; |
return false; |
171 |
|
|
172 |
/* Only these types are recognised */ |
/* Only these types are recognized */ |
173 |
if (ah->ar_op != htons(ARPOP_REQUEST) && ah->ar_op != htons(ARPOP_REPLY)) |
if (ah->ar_op != htons(ARPOP_REQUEST) && ah->ar_op != htons(ARPOP_REPLY)) |
174 |
return false; |
return false; |
175 |
|
|
180 |
|
|
181 |
/* Protocol must be IP. */ |
/* Protocol must be IP. */ |
182 |
if (ah->ar_pro != htons(ETH_P_IP) |
if (ah->ar_pro != htons(ETH_P_IP) |
183 |
|| (ah->ar_pln != 4) |
|| (ah->ar_pln != 4) |
184 |
|| (ah->ar_hln != me.sll_halen) |
|| (ah->ar_hln != me.sll_halen) |
185 |
|| (len < (int)(sizeof(*ah) + 2 * (4 + ah->ar_hln)))) |
|| (len < (int)(sizeof(*ah) + 2 * (4 + ah->ar_hln)))) |
186 |
return false; |
return false; |
187 |
|
|
188 |
memcpy(&src_ip, p + ah->ar_hln, 4); |
move_from_unaligned32(src_ip.s_addr, p + ah->ar_hln); |
189 |
memcpy(&dst_ip, p + ah->ar_hln + 4 + ah->ar_hln, 4); |
move_from_unaligned32(dst_ip.s_addr, p + ah->ar_hln + 4 + ah->ar_hln); |
190 |
|
|
191 |
if (dst.s_addr != src_ip.s_addr) |
if (dst.s_addr != src_ip.s_addr) |
192 |
return false; |
return false; |
209 |
dst_ip/dst_hw do not matter. |
dst_ip/dst_hw do not matter. |
210 |
*/ |
*/ |
211 |
if ((memcmp(p, &me.sll_addr, me.sll_halen) == 0) |
if ((memcmp(p, &me.sll_addr, me.sll_halen) == 0) |
212 |
|| (src.s_addr && src.s_addr != dst_ip.s_addr)) |
|| (src.s_addr && src.s_addr != dst_ip.s_addr)) |
213 |
return false; |
return false; |
214 |
} |
} |
215 |
if (!(option_mask32 & QUIET)) { |
if (!(option_mask32 & QUIET)) { |
237 |
} else { |
} else { |
238 |
printf(" UNSOLICITED?\n"); |
printf(" UNSOLICITED?\n"); |
239 |
} |
} |
240 |
fflush(stdout); |
fflush_all(); |
241 |
} |
} |
242 |
received++; |
received++; |
243 |
if (FROM->sll_pkttype != PACKET_HOST) |
if (FROM->sll_pkttype != PACKET_HOST) |
295 |
struct ifreq ifr; |
struct ifreq ifr; |
296 |
|
|
297 |
memset(&ifr, 0, sizeof(ifr)); |
memset(&ifr, 0, sizeof(ifr)); |
298 |
strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name) - 1); |
strncpy_IFNAMSIZ(ifr.ifr_name, device); |
299 |
/* We use ifr.ifr_name in error msg so that problem |
/* We use ifr.ifr_name in error msg so that problem |
300 |
* with truncated name will be visible */ |
* with truncated name will be visible */ |
301 |
ioctl_or_perror_and_die(sock_fd, SIOCGIFINDEX, &ifr, err_str, "not found"); |
ioctl_or_perror_and_die(sock_fd, SIOCGIFINDEX, &ifr, err_str, "not found"); |
315 |
/* if (!inet_aton(target, &dst)) - not needed */ { |
/* if (!inet_aton(target, &dst)) - not needed */ { |
316 |
len_and_sockaddr *lsa; |
len_and_sockaddr *lsa; |
317 |
lsa = xhost_and_af2sockaddr(target, 0, AF_INET); |
lsa = xhost_and_af2sockaddr(target, 0, AF_INET); |
318 |
memcpy(&dst, &lsa->u.sin.sin_addr.s_addr, 4); |
dst = lsa->u.sin.sin_addr; |
319 |
if (ENABLE_FEATURE_CLEAN_UP) |
if (ENABLE_FEATURE_CLEAN_UP) |
320 |
free(lsa); |
free(lsa); |
321 |
} |
} |
348 |
if (setsockopt(probe_fd, SOL_SOCKET, SO_DONTROUTE, &const_int_1, sizeof(const_int_1)) == -1) |
if (setsockopt(probe_fd, SOL_SOCKET, SO_DONTROUTE, &const_int_1, sizeof(const_int_1)) == -1) |
349 |
bb_perror_msg("setsockopt(SO_DONTROUTE)"); |
bb_perror_msg("setsockopt(SO_DONTROUTE)"); |
350 |
xconnect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); |
xconnect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); |
351 |
if (getsockname(probe_fd, (struct sockaddr *) &saddr, &alen) == -1) { |
getsockname(probe_fd, (struct sockaddr *) &saddr, &alen); |
352 |
bb_perror_msg_and_die("getsockname"); |
//never happens: |
353 |
} |
//if (getsockname(probe_fd, (struct sockaddr *) &saddr, &alen) == -1) |
354 |
|
// bb_perror_msg_and_die("getsockname"); |
355 |
if (saddr.sin_family != AF_INET) |
if (saddr.sin_family != AF_INET) |
356 |
bb_error_msg_and_die("no IP address configured"); |
bb_error_msg_and_die("no IP address configured"); |
357 |
src = saddr.sin_addr; |
src = saddr.sin_addr; |
366 |
|
|
367 |
{ |
{ |
368 |
socklen_t alen = sizeof(me); |
socklen_t alen = sizeof(me); |
369 |
|
getsockname(sock_fd, (struct sockaddr *) &me, &alen); |
370 |
if (getsockname(sock_fd, (struct sockaddr *) &me, &alen) == -1) { |
//never happens: |
371 |
bb_perror_msg_and_die("getsockname"); |
//if (getsockname(sock_fd, (struct sockaddr *) &me, &alen) == -1) |
372 |
} |
// bb_perror_msg_and_die("getsockname"); |
373 |
} |
} |
374 |
if (me.sll_halen == 0) { |
if (me.sll_halen == 0) { |
375 |
bb_error_msg(err_str, "is not ARPable (no ll address)"); |
bb_error_msg(err_str, "is not ARPable (no ll address)"); |