Don't require user to specify -a anymore

This commit is contained in:
Joseph C. Lehner 2016-11-12 15:40:26 +01:00
parent f38833e940
commit 2cf812dcfe
4 changed files with 200 additions and 33 deletions

130
ethsock.c
View file

@ -10,8 +10,11 @@
#define WPCAP
#include <pcap.h>
#else
#include <pcap.h>
#include <sys/ioctl.h>
#include <ifaddrs.h>
#include <unistd.h>
#include <net/if.h>
#include <pcap.h>
#if defined(NMRPFLASH_LINUX)
#define NMRPFLASH_AF_PACKET AF_PACKET
#include <linux/if_packet.h>
@ -35,6 +38,15 @@ struct ethsock
uint8_t hwaddr[6];
};
struct ethsock_ip_undo
{
#ifndef NRMPFLASH_WINDOWS
uint32_t ip[2];
#else
ULONG context;
#endif
};
const char *mac_to_str(uint8_t *mac)
{
static char buf[18];
@ -631,3 +643,119 @@ int ethsock_for_each_ip(struct ethsock *sock, ethsock_ip_callback_t callback,
return status <= 0 ? status : 0;
}
#ifndef NMRPFLASH_WINDOWS
static int get_ip_cb(struct ethsock_ip_callback_args* args)
{
uint32_t *ip = args->arg;
ip[0] = args->ipaddr->s_addr;
ip[1] = args->ipmask->s_addr;
return 0;
}
#endif
int ethsock_set_ip(struct ethsock *sock, uint32_t ipaddr, uint32_t ipmask, struct ethsock_ip_undo **undo)
{
if (undo && !(*undo = malloc(sizeof(struct ethsock_ip_undo)))) {
perror("malloc");
return -1;
}
#ifndef NMRPFLASH_WINDOWS
struct ifreq ifr = { 0 };
int fd, ret = -1;
if (undo) {
(*undo)->ip[0] = INADDR_NONE;
(*undo)->ip[1] = INADDR_NONE;
if (ethsock_for_each_ip(sock, &get_ip_cb, (*undo)->ip) != 0) {
return 1;
}
}
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (!fd) {
perror("socket");
return -1;
}
strncpy(ifr.ifr_name, sock->intf, IFNAMSIZ);
struct sockaddr_in* sin = (struct sockaddr_in*)&ifr.ifr_addr;
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = ipaddr;
if (ioctl(fd, SIOCSIFADDR, &ifr) != 0) {
perror("ioctl(SIOSIFADDR)");
goto out;
}
sin = (struct sockaddr_in*)&ifr.ifr_netmask;
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = ipmask;
if (ioctl(fd, SIOCSIFNETMASK, &ifr) != 0) {
perror("ioctl(SIOCSIFNETMASK)");
goto out;
}
if (ioctl(fd, SIOCGIFFLAGS, &ifr) != 0) {
perror("ioctl(SIOCGIFFLAGS)");
goto out;
}
ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0) {
perror("ioctl(SIOCSIFFLAGS)");
goto out;
}
ret = 0;
out:
close(fd);
return ret;
#else
ULONG instance;
DWORD ret = AddIPAddress(ipaddr, ipmask, sock->index, &undo->context, &instance);
if (ret != NO_ERROR) {
win_perror2("AddIPAddress", ret);
return -1;
}
return 0;
#endif
}
int ethsock_del_ip(struct ethsock *sock, struct ethsock_ip_undo **undo)
{
if (!*undo) {
return 0;
}
int ret;
#ifndef NMRPFLASH_WINDOWS
if ((*undo)->ip[0] != INADDR_NONE) {
ret = ethsock_set_ip(sock, (*undo)->ip[0], (*undo)->ip[1], NULL);
} else {
ret = 0;
}
#else
DWORD err = DeleteIPAddress((*undo)->context);
if (err != NO_ERROR) {
win_perror2("DeleteIPAddress", ret);
ret = -1;
} else {
ret = 0;
}
#endif
free(*undo);
*undo = NULL;
return ret;
}

16
main.c
View file

@ -32,8 +32,9 @@ void usage(FILE *fp)
fprintf(fp,
"Usage: nmrpflash [OPTIONS...]\n"
"\n"
"Options (-a, -i and -f and/or -c are mandatory):\n"
"Options (-i, -f and/or -c are mandatory):\n"
" -a <ipaddr> IP address to assign to target device\n"
" -A <ipaddr> IP address to assign to seleted interface\n"
" -c <command> Command to run before (or instead of) TFTP upload\n"
" -f <firmware> Firmware file\n"
" -F <filename> Remote filename to use during TFTP upload\n"
@ -119,6 +120,7 @@ int main(int argc, char **argv)
.tftpcmd = NULL,
.file_local = NULL,
.file_remote = NULL,
.ipaddr_intf = NULL,
.ipaddr = NULL,
.ipmask = "255.255.255.0",
.intf = NULL,
@ -160,12 +162,15 @@ int main(int argc, char **argv)
opterr = 0;
while ((c = getopt(argc, argv, "a:c:f:F:i:m:M:p:R:t:T:hLVvU")) != -1) {
while ((c = getopt(argc, argv, "a:A:c:f:F:i:m:M:p:R:t:T:hLVvU")) != -1) {
max = 0x7fffffff;
switch (c) {
case 'a':
args.ipaddr = optarg;
break;
case 'A':
args.ipaddr_intf = optarg;
break;
case 'c':
args.tftpcmd = optarg;
break;
@ -241,7 +246,12 @@ int main(int argc, char **argv)
}
}
if (!list && ((!args.file_local && !args.tftpcmd) || !args.intf || !args.ipaddr)) {
if (args.ipaddr_intf && !args.ipaddr) {
fprintf(stderr, "Error: cannot use -A <ipaddr> without using -a <ipaddr>.\n");
return 1;
}
if (!list && ((!args.file_local && !args.tftpcmd) || !args.intf /*|| !args.ipaddr*/)) {
usage(stderr);
return 1;
}

82
nmrp.c
View file

@ -371,6 +371,7 @@ static int is_valid_ip(struct ethsock *sock, struct in_addr *ipaddr,
}
static struct ethsock *gsock = NULL;
static struct ethsock_ip_undo *gundo = NULL;
static int garp = 0;
static struct in_addr arpip = { 0 };
static uint8_t arpmac[6] = { 0 };
@ -382,6 +383,7 @@ static void sigh(int sig)
if (garp) {
ethsock_arp_del(gsock, arpmac, &arpip);
}
ethsock_del_ip(gsock, &gundo);
ethsock_close(gsock);
gsock = NULL;
}
@ -400,6 +402,7 @@ int nmrp_do(struct nmrpd_args *args)
time_t beg;
int i, status, ulreqs, expect, upload_ok, autoip;
struct ethsock *sock;
uint32_t intf_addr;
void (*sigh_orig)(int);
struct {
struct in_addr addr;
@ -416,19 +419,34 @@ int nmrp_do(struct nmrpd_args *args)
return 1;
}
if ((ipconf.addr.s_addr = inet_addr(args->ipaddr)) == INADDR_NONE) {
autoip = 1;
//fprintf(stderr, "Invalid IP address '%s'.\n", args->ipaddr);
//return 1;
} else {
autoip = 0;
}
if ((ipconf.mask.s_addr = inet_addr(args->ipmask)) == INADDR_NONE) {
fprintf(stderr, "Invalid subnet mask '%s'.\n", args->ipmask);
return 1;
}
if (!args->ipaddr) {
autoip = true;
args->ipaddr = "10.11.12.254";
if (!args->ipaddr_intf) {
args->ipaddr_intf = "10.11.12.253";
}
} else if (args->ipaddr_intf) {
autoip = true;
} else {
autoip = false;
}
if ((ipconf.addr.s_addr = inet_addr(args->ipaddr)) == INADDR_NONE) {
fprintf(stderr, "Invalid IP address '%s'.\n", args->ipaddr);
return 1;
}
if (args->ipaddr_intf && (intf_addr = inet_addr(args->ipaddr_intf)) == INADDR_NONE) {
fprintf(stderr, "Invalid IP address '%s'.\n", args->ipaddr_intf);
return 1;
}
if (args->file_local && strcmp(args->file_local, "-") && access(args->file_local, R_OK) == -1) {
fprintf(stderr, "Error accessing file '%s'.\n", args->file_local);
return 1;
@ -454,12 +472,6 @@ int nmrp_do(struct nmrpd_args *args)
status = 1;
if (autoip) {
if (arp_find_free_ip(args->intf, &ipconf.addr.s_addr) != 0) {
return 1;
}
}
sock = ethsock_create(args->intf, ETH_P_NMRP);
if (!sock) {
return 1;
@ -469,13 +481,15 @@ int nmrp_do(struct nmrpd_args *args)
garp = 0;
sigh_orig = signal(SIGINT, sigh);
status = is_valid_ip(sock, &ipconf.addr, &ipconf.mask);
if (status <= 0) {
if (!status) {
fprintf(stderr, "Address %s/%s cannot be used on interface %s.\n",
args->ipaddr, args->ipmask, args->intf);
if (!autoip) {
status = is_valid_ip(sock, &ipconf.addr, &ipconf.mask);
if (status <= 0) {
if (!status) {
fprintf(stderr, "Address %s/%s cannot be used on interface %s.\n",
args->ipaddr, args->ipmask, args->intf);
}
goto out;
}
goto out;
}
if (ethsock_set_timeout(sock, args->rx_timeout)) {
@ -608,6 +622,12 @@ int nmrp_do(struct nmrpd_args *args)
status = 0;
if (autoip) {
if (ethsock_set_ip(sock, intf_addr, ipconf.mask.s_addr, &gundo) != 0) {
goto out;
}
}
if (args->tftpcmd) {
printf("Executing '%s' ... ", args->tftpcmd);
fflush(stdout);
@ -616,14 +636,16 @@ int nmrp_do(struct nmrpd_args *args)
}
if (!status && args->file_local) {
status = is_valid_ip(sock, &ipconf.addr, &ipconf.mask);
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 (!autoip) {
status = is_valid_ip(sock, &ipconf.addr, &ipconf.mask);
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) {
@ -640,6 +662,10 @@ int nmrp_do(struct nmrpd_args *args)
status = tftp_put(args);
}
if (ethsock_del_ip(sock, &gundo) != 0) {
goto out;
}
if (!status) {
printf("OK\nWaiting for remote to respond.\n");
upload_ok = 1;

View file

@ -75,6 +75,7 @@ struct nmrpd_args {
const char *tftpcmd;
const char *file_local;
const char *file_remote;
const char *ipaddr_intf;
const char *ipaddr;
const char *ipmask;
const char *intf;
@ -103,6 +104,7 @@ void sock_perror(const char *msg);
extern int verbosity;
struct ethsock;
struct ethsock_ip_undo;
struct ethsock *ethsock_create(const char *intf, uint16_t protocol);
int ethsock_close(struct ethsock *sock);
@ -125,5 +127,6 @@ 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);
int arp_find_free_ip(const char *intf, uint32_t *addr);
int ethsock_set_ip(struct ethsock *sock, uint32_t ipaddr, uint32_t ipmask, struct ethsock_ip_undo **undo);
int ethsock_del_ip(struct ethsock *sock, struct ethsock_ip_undo **undo);
#endif