Add and use ethsock_for_each_ip
authorJoseph C. Lehner <joseph.c.lehner@gmail.com>
Sat, 13 Feb 2016 15:16:51 +0000 (16:16 +0100)
committerJoseph C. Lehner <joseph.c.lehner@gmail.com>
Sat, 13 Feb 2016 15:16:51 +0000 (16:16 +0100)
ethsock.c
nmrp.c
nmrpd.h

index d0c192ef07749cc7299afee27a1d33564cb38bce..c1674d44cc779982a3dec7c771e275ba3b02a648 100644 (file)
--- a/ethsock.c
+++ b/ethsock.c
@@ -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;
 }
diff --git a/nmrp.c b/nmrp.c
index c9cf6c204745fc747e29265ff2677f557ab4a727..7554929e27897bbcf8df7edf86988fbb60422c4e 100644 (file)
--- a/nmrp.c
+++ b/nmrp.c
@@ -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);
diff --git a/nmrpd.h b/nmrpd.h
index f6b776540e7b92ba5a803602555e68f0ad97f383..0eabf26e7cdfed96b45fe3965ebdf6905669b9cd 100644 (file)
--- a/nmrpd.h
+++ b/nmrpd.h
@@ -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