Add and use ethsock_for_each_ip

This commit is contained in:
Joseph C. Lehner 2016-02-13 16:16:51 +01:00
parent 1b3bb6779b
commit ae05a62666
3 changed files with 73 additions and 13 deletions

View file

@ -544,18 +544,19 @@ int ethsock_list_all(void)
return 0;
}
int ethsock_is_same_subnet(struct ethsock *sock, struct in_addr *ipaddr,
struct in_addr *ipmask)
int ethsock_for_each_ip(struct ethsock *sock, ethsock_ip_callback_t callback,
void *arg)
{
struct ethsock_ip_callback_args args;
pcap_if_t *devs, *dev;
pcap_addr_t *addr;
uint32_t ip, mask, net;
int status;
if (x_pcap_findalldevs(&devs) != 0) {
return -1;
}
net = ipaddr->s_addr & ipmask->s_addr;
args.arg = arg;
for (dev = devs; dev; dev = dev->next) {
if (strcmp(sock->intf, dev->name)) {
@ -564,14 +565,20 @@ int ethsock_is_same_subnet(struct ethsock *sock, struct in_addr *ipaddr,
for (addr = dev->addresses; addr; addr = addr->next) {
if (addr->addr->sa_family == AF_INET) {
ip = ((struct sockaddr_in*)addr->addr)->sin_addr.s_addr;
mask = ((struct sockaddr_in*)addr->netmask)->sin_addr.s_addr;
if ((ip & mask) == net) {
return 1;
args.ipaddr = &((struct sockaddr_in*)addr->addr)->sin_addr;
args.ipmask = &((struct sockaddr_in*)addr->netmask)->sin_addr;
status = callback(&args);
if (status <= 0) {
break;
}
}
}
break;
}
return 0;
pcap_freealldevs(devs);
return status <= 0 ? status : 0;
}

50
nmrp.c
View file

@ -265,6 +265,40 @@ static int mac_parse(const char *str, uint8_t *hwaddr)
return 0;
}
struct is_valid_ip_arg
{
struct in_addr *ipaddr;
struct in_addr *ipmask;
int result;
};
static int is_valid_ip_cb(struct ethsock_ip_callback_args *args)
{
#define SUBNET(x) ((x)->ipaddr->s_addr & (x)->ipmask->s_addr)
struct is_valid_ip_arg *arg = args->arg;
if (SUBNET(args) == SUBNET(arg)) {
arg->result = args->ipaddr->s_addr != arg->ipaddr->s_addr;
return 0;
}
return 1;
#undef SUBNET
}
static int is_valid_ip(struct ethsock *sock, struct in_addr *ipaddr,
struct in_addr *ipmask)
{
int status;
struct is_valid_ip_arg arg = {
.ipaddr = ipaddr,
.ipmask = ipmask,
.result = 0
};
status = ethsock_for_each_ip(sock, is_valid_ip_cb, &arg);
return status < 0 ? status : arg.result;
}
static struct ethsock *gsock = NULL;
static void sigh(int sig)
@ -331,13 +365,13 @@ int nmrp_do(struct nmrpd_args *args)
return 1;
}
status = ethsock_is_same_subnet(sock, &ipaddr, &ipmask);
status = is_valid_ip(sock, &ipaddr, &ipmask);
if (status <= 0) {
if (!status) {
fprintf(stderr, "Address %s/%s invalid for interface %s.\n",
fprintf(stderr, "Address %s/%s cannot be used on interface %s.\n",
args->ipaddr, args->ipmask, args->intf);
}
return 1;
goto out;
}
gsock = sock;
@ -494,6 +528,16 @@ int nmrp_do(struct nmrpd_args *args)
}
if (!status && args->file_local) {
status = is_valid_ip(sock, &ipaddr, &ipmask);
if (status < 0) {
goto out;
} else if (!status) {
printf("IP address of %s has changed. Please assign a "
"static ip to the interface.\n", args->intf);
tx.msg.code = NMRP_C_CLOSE_REQ;
break;
}
if (verbosity) {
printf("Using remote filename '%s'.\n",
args->file_remote);

11
nmrpd.h
View file

@ -97,6 +97,15 @@ ssize_t ethsock_recv(struct ethsock *sock, void *buf, size_t len);
int ethsock_set_timeout(struct ethsock *sock, unsigned msec);
uint8_t *ethsock_get_hwaddr(struct ethsock *sock);
int ethsock_list_all(void);
int ethsock_is_same_subnet(struct ethsock *sock, struct in_addr* ip, struct in_addr *mask);
struct ethsock_ip_callback_args
{
struct in_addr *ipaddr;
struct in_addr *ipmask;
void *arg;
};
typedef int (*ethsock_ip_callback_t)(struct ethsock_ip_callback_args *args);
int ethsock_for_each_ip(struct ethsock *sock, ethsock_ip_callback_t callback,
void *arg);
#endif