Rewrite the ARP ping code to properly use modern interfaces. In detail:
- Use AF_PACKET and SOCK_RAW rather than the decade-deprecated SOCK_PACKET interface. - Separate out socket creation code into a subfunction. - Use C99 initializers for packet and address structures. - Cosmetic cleanups.
This commit is contained in:
parent
8f5eb7e921
commit
c37d815754
89
ndhc/arp.c
89
ndhc/arp.c
@ -3,10 +3,6 @@
|
|||||||
*
|
*
|
||||||
* Copyright 2010-2011 Nicholas J. Kain <njkain@gmail.com>
|
* Copyright 2010-2011 Nicholas J. Kain <njkain@gmail.com>
|
||||||
*
|
*
|
||||||
* Originally derived from busybox's udhcpc variant, which in turn was...
|
|
||||||
* Mostly stolen from: dhcpcd - DHCP client daemon
|
|
||||||
* by Yoichi Hariguchi <yoichi@fore.com>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
@ -30,6 +26,7 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <linux/if_packet.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "arp.h"
|
#include "arp.h"
|
||||||
@ -38,7 +35,6 @@
|
|||||||
#include "ifchange.h"
|
#include "ifchange.h"
|
||||||
#include "leasefile.h"
|
#include "leasefile.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "strl.h"
|
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
|
|
||||||
#define ARP_MSG_SIZE 0x2a
|
#define ARP_MSG_SIZE 0x2a
|
||||||
@ -49,33 +45,18 @@ static int arpreply_offset;
|
|||||||
static struct dhcpMessage arp_dhcp_packet;
|
static struct dhcpMessage arp_dhcp_packet;
|
||||||
static int arp_packet_num;
|
static int arp_packet_num;
|
||||||
|
|
||||||
static int arp_close_fd(struct client_state_t *cs)
|
static int arp_open_fd(struct client_state_t *cs)
|
||||||
{
|
{
|
||||||
if (cs->arpFd != -1) {
|
|
||||||
epoll_del(cs, cs->arpFd);
|
|
||||||
close(cs->arpFd);
|
|
||||||
cs->arpFd = -1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Returns 0 on success, -1 on failure. */
|
|
||||||
static int arpping(struct client_state_t *cs, uint32_t test_ip)
|
|
||||||
{
|
|
||||||
int opt = 1;
|
|
||||||
struct sockaddr addr; /* for interface name */
|
|
||||||
struct arpMsg arp;
|
|
||||||
|
|
||||||
if (cs->arpFd == -1) {
|
if (cs->arpFd == -1) {
|
||||||
int arpfd = socket(AF_PACKET, SOCK_PACKET, htons(ETH_P_ARP));
|
int arpfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
|
||||||
if (arpfd == -1) {
|
if (arpfd == -1) {
|
||||||
log_error("arp: failed to create socket: %s", strerror(errno));
|
log_error("arp: failed to create socket: %s", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int opt = 1;
|
||||||
if (setsockopt(arpfd, SOL_SOCKET, SO_BROADCAST,
|
if (setsockopt(arpfd, SOL_SOCKET, SO_BROADCAST,
|
||||||
&opt, sizeof opt) == -1) {
|
&opt, sizeof opt) == -1) {
|
||||||
log_error("arp: failed to set broadcast: %s", strerror(errno));
|
log_error("arp: failed to set broadcast: %s", strerror(errno));
|
||||||
close(arpfd);
|
close(arpfd);
|
||||||
return -1;
|
return -1;
|
||||||
@ -88,26 +69,48 @@ static int arpping(struct client_state_t *cs, uint32_t test_ip)
|
|||||||
cs->arpFd = arpfd;
|
cs->arpFd = arpfd;
|
||||||
epoll_add(cs, arpfd);
|
epoll_add(cs, arpfd);
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* send arp request */
|
static int arp_close_fd(struct client_state_t *cs)
|
||||||
memset(&arp, 0, sizeof arp);
|
{
|
||||||
memset(arp.h_dest, 0xff, 6); /* MAC DA */
|
if (cs->arpFd != -1) {
|
||||||
memcpy(arp.h_source, client_config.arp, 6); /* MAC SA */
|
epoll_del(cs, cs->arpFd);
|
||||||
arp.h_proto = htons(ETH_P_ARP); /* protocol type (Ethernet) */
|
close(cs->arpFd);
|
||||||
arp.htype = htons(ARPHRD_ETHER); /* hardware type */
|
cs->arpFd = -1;
|
||||||
arp.ptype = htons(ETH_P_IP); /* protocol type (ARP message) */
|
return 1;
|
||||||
arp.hlen = 6; /* hardware address length */
|
}
|
||||||
arp.plen = 4; /* protocol address length */
|
return 0;
|
||||||
arp.operation = htons(ARPOP_REQUEST); /* ARP op code */
|
}
|
||||||
memcpy(arp.smac, client_config.arp, 6); /* source hardware address */
|
|
||||||
memset(arp.sip4, 0, sizeof arp.sip4); /* source IP address */
|
// Returns 0 on success, -1 on failure.
|
||||||
/* dmac is zero-filled */ /* target hardware address */
|
static int arpping(struct client_state_t *cs, uint32_t test_ip)
|
||||||
memcpy(arp.dip4, &test_ip, sizeof test_ip); /* target IP address */
|
{
|
||||||
|
if (arp_open_fd(cs) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
struct arpMsg arp = {
|
||||||
|
.h_proto = htons(ETH_P_ARP),
|
||||||
|
.htype = htons(ARPHRD_ETHER),
|
||||||
|
.ptype = htons(ETH_P_IP),
|
||||||
|
.hlen = 6,
|
||||||
|
.plen = 4,
|
||||||
|
.operation = htons(ARPOP_REQUEST),
|
||||||
|
};
|
||||||
|
memset(arp.h_dest, 0xff, 6);
|
||||||
|
memcpy(arp.h_source, client_config.arp, 6);
|
||||||
|
memcpy(arp.smac, client_config.arp, 6);
|
||||||
|
memcpy(arp.dip4, &test_ip, sizeof test_ip);
|
||||||
|
|
||||||
|
struct sockaddr_ll addr = {
|
||||||
|
.sll_family = AF_PACKET,
|
||||||
|
.sll_ifindex = client_config.ifindex,
|
||||||
|
.sll_halen = 6,
|
||||||
|
};
|
||||||
|
memcpy(addr.sll_addr, client_config.arp, 6);
|
||||||
|
|
||||||
memset(&addr, 0, sizeof addr);
|
|
||||||
strlcpy(addr.sa_data, client_config.interface, sizeof addr.sa_data);
|
|
||||||
if (safe_sendto(cs->arpFd, (const char *)&arp, sizeof arp,
|
if (safe_sendto(cs->arpFd, (const char *)&arp, sizeof arp,
|
||||||
0, &addr, sizeof addr) < 0) {
|
0, (struct sockaddr *)&addr, sizeof addr) < 0) {
|
||||||
log_error("arp: sendto failed: %s", strerror(errno));
|
log_error("arp: sendto failed: %s", strerror(errno));
|
||||||
arp_close_fd(cs);
|
arp_close_fd(cs);
|
||||||
return -1;
|
return -1;
|
||||||
@ -195,10 +198,8 @@ void arp_success(struct client_state_t *cs)
|
|||||||
|
|
||||||
arp_close_fd(cs);
|
arp_close_fd(cs);
|
||||||
|
|
||||||
/* enter bound state */
|
|
||||||
cs->t1 = cs->lease >> 1;
|
cs->t1 = cs->lease >> 1;
|
||||||
/* little fixed point for n * .875 */
|
cs->t2 = (cs->lease * 0x7) >> 3; // T2 = lease * 0.875
|
||||||
cs->t2 = (cs->lease * 0x7) >> 3;
|
|
||||||
cs->timeout = cs->t1 * 1000;
|
cs->timeout = cs->t1 * 1000;
|
||||||
cs->leaseStartTime = curms();
|
cs->leaseStartTime = curms();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user