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)) {
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;
}
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)
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;
}
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);
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