Check if ip address is valid for given interface

This commit is contained in:
Joseph C. Lehner 2016-02-13 14:16:35 +01:00
parent efb7442a15
commit 1b3bb6779b
3 changed files with 65 additions and 21 deletions

View file

@ -28,6 +28,7 @@
struct ethsock struct ethsock
{ {
const char *intf;
pcap_t *pcap; pcap_t *pcap;
#ifndef NMRPFLASH_WINDOWS #ifndef NMRPFLASH_WINDOWS
int fd; int fd;
@ -276,7 +277,8 @@ struct ethsock *ethsock_create(const char *intf, uint16_t protocol)
buf[0] = '\0'; buf[0] = '\0';
sock->pcap = pcap_open_live(intf, BUFSIZ, 1, 1, buf); sock->intf = intf;
sock->pcap = pcap_open_live(sock->intf, BUFSIZ, 1, 1, buf);
if (!sock->pcap) { if (!sock->pcap) {
fprintf(stderr, "%s.\n", buf); fprintf(stderr, "%s.\n", buf);
goto cleanup_malloc; goto cleanup_malloc;
@ -541,3 +543,35 @@ int ethsock_list_all(void)
return 0; return 0;
} }
int ethsock_is_same_subnet(struct ethsock *sock, struct in_addr *ipaddr,
struct in_addr *ipmask)
{
pcap_if_t *devs, *dev;
pcap_addr_t *addr;
uint32_t ip, mask, net;
if (x_pcap_findalldevs(&devs) != 0) {
return -1;
}
net = ipaddr->s_addr & ipmask->s_addr;
for (dev = devs; dev; dev = dev->next) {
if (strcmp(sock->intf, dev->name)) {
continue;
}
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;
}
}
}
}
return 0;
}

49
nmrp.c
View file

@ -287,7 +287,7 @@ int nmrp_do(struct nmrpd_args *args)
char *filename; char *filename;
struct in_addr ipaddr, ipmask; struct in_addr ipaddr, ipmask;
time_t beg; time_t beg;
int i, err, ulreqs, expect; int i, status, ulreqs, expect;
struct ethsock *sock; struct ethsock *sock;
void (*sigh_orig)(int); void (*sigh_orig)(int);
@ -324,13 +324,22 @@ int nmrp_do(struct nmrpd_args *args)
} }
} }
err = 1; status = 1;
sock = ethsock_create(args->intf, ETH_P_NMRP); sock = ethsock_create(args->intf, ETH_P_NMRP);
if (!sock) { if (!sock) {
return 1; return 1;
} }
status = ethsock_is_same_subnet(sock, &ipaddr, &ipmask);
if (status <= 0) {
if (!status) {
fprintf(stderr, "Address %s/%s invalid for interface %s.\n",
args->ipaddr, args->ipmask, args->intf);
}
return 1;
}
gsock = sock; gsock = sock;
sigh_orig = signal(SIGINT, sigh); sigh_orig = signal(SIGINT, sigh);
@ -375,10 +384,10 @@ int nmrp_do(struct nmrpd_args *args)
goto out; goto out;
} }
err = pkt_recv(sock, &rx); status = pkt_recv(sock, &rx);
if (err == 0 && memcmp(rx.eh.ether_dhost, src, 6) == 0) { if (status == 0 && memcmp(rx.eh.ether_dhost, src, 6) == 0) {
break; break;
} else if (err == 1) { } else if (status == 1) {
printf("ERR\n"); printf("ERR\n");
goto out; goto out;
} else { } else {
@ -406,13 +415,13 @@ int nmrp_do(struct nmrpd_args *args)
tx.msg.num_opts = 0; tx.msg.num_opts = 0;
tx.msg.len = 0; tx.msg.len = 0;
err = 1; status = 1;
switch (rx.msg.code) { switch (rx.msg.code) {
case NMRP_C_ADVERTISE: case NMRP_C_ADVERTISE:
printf("Received NMRP advertisement from %s.\n", printf("Received NMRP advertisement from %s.\n",
mac_to_str(rx.eh.ether_shost)); mac_to_str(rx.eh.ether_shost));
err = 1; status = 1;
goto out; goto out;
case NMRP_C_CONF_REQ: case NMRP_C_CONF_REQ:
tx.msg.code = NMRP_C_CONF_ACK; tx.msg.code = NMRP_C_CONF_ACK;
@ -471,20 +480,20 @@ int nmrp_do(struct nmrpd_args *args)
printf("Received upload request with empty filename."); printf("Received upload request with empty filename.");
} }
err = 0; status = 0;
if (args->tftpcmd) { if (args->tftpcmd) {
printf("Executing '%s' ... ", args->tftpcmd); printf("Executing '%s' ... ", args->tftpcmd);
fflush(stdout); fflush(stdout);
err = system(args->tftpcmd); status = system(args->tftpcmd);
if (!err) { if (!status) {
printf("OK\n"); printf("OK\n");
} else { } else {
printf("ERR\n"); printf("ERR\n");
} }
} }
if (!err && args->file_local) { if (!status && args->file_local) {
if (verbosity) { if (verbosity) {
printf("Using remote filename '%s'.\n", printf("Using remote filename '%s'.\n",
args->file_remote); args->file_remote);
@ -496,14 +505,14 @@ int nmrp_do(struct nmrpd_args *args)
printf("Uploading %s ... ", args->file_local); printf("Uploading %s ... ", args->file_local);
} }
fflush(stdout); fflush(stdout);
err = tftp_put(args); status = tftp_put(args);
} }
if (!err) { if (!status) {
printf("OK\nWaiting for remote to respond.\n"); printf("OK\nWaiting for remote to respond.\n");
ethsock_set_timeout(sock, args->ul_timeout); ethsock_set_timeout(sock, args->ul_timeout);
expect = NMRP_C_CLOSE_REQ; expect = NMRP_C_CLOSE_REQ;
} else if (err == -2) { } else if (status == -2) {
expect = NMRP_C_TFTP_UL_REQ; expect = NMRP_C_TFTP_UL_REQ;
} else { } else {
goto out; goto out;
@ -517,7 +526,7 @@ int nmrp_do(struct nmrpd_args *args)
tx.msg.code = NMRP_C_CLOSE_ACK; tx.msg.code = NMRP_C_CLOSE_ACK;
break; break;
case NMRP_C_CLOSE_ACK: case NMRP_C_CLOSE_ACK:
err = 0; status = 0;
goto out; goto out;
default: default:
fprintf(stderr, "Unknown message code 0x%02x!\n", fprintf(stderr, "Unknown message code 0x%02x!\n",
@ -540,9 +549,9 @@ int nmrp_do(struct nmrpd_args *args)
break; break;
} }
err = pkt_recv(sock, &rx); status = pkt_recv(sock, &rx);
if (err) { if (status) {
if (err == 2) { if (status == 2) {
fprintf(stderr, "Timeout while waiting for 0x%02x.\n", expect); fprintf(stderr, "Timeout while waiting for 0x%02x.\n", expect);
} }
goto out; goto out;
@ -552,7 +561,7 @@ int nmrp_do(struct nmrpd_args *args)
} while (1); } while (1);
err = 0; status = 0;
printf("Reboot your device now.\n"); printf("Reboot your device now.\n");
@ -560,5 +569,5 @@ out:
signal(SIGINT, sigh_orig); signal(SIGINT, sigh_orig);
gsock = NULL; gsock = NULL;
ethsock_close(sock); ethsock_close(sock);
return err; return status;
} }

View file

@ -97,5 +97,6 @@ ssize_t ethsock_recv(struct ethsock *sock, void *buf, size_t len);
int ethsock_set_timeout(struct ethsock *sock, unsigned msec); int ethsock_set_timeout(struct ethsock *sock, unsigned msec);
uint8_t *ethsock_get_hwaddr(struct ethsock *sock); uint8_t *ethsock_get_hwaddr(struct ethsock *sock);
int ethsock_list_all(void); int ethsock_list_all(void);
int ethsock_is_same_subnet(struct ethsock *sock, struct in_addr* ip, struct in_addr *mask);
#endif #endif