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 #define WPCAP
#include <pcap.h> #include <pcap.h>
#else #else
#include <pcap.h> #include <sys/ioctl.h>
#include <ifaddrs.h> #include <ifaddrs.h>
#include <unistd.h>
#include <net/if.h>
#include <pcap.h>
#if defined(NMRPFLASH_LINUX) #if defined(NMRPFLASH_LINUX)
#define NMRPFLASH_AF_PACKET AF_PACKET #define NMRPFLASH_AF_PACKET AF_PACKET
#include <linux/if_packet.h> #include <linux/if_packet.h>
@ -35,6 +38,15 @@ struct ethsock
uint8_t hwaddr[6]; 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) const char *mac_to_str(uint8_t *mac)
{ {
static char buf[18]; 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; 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, fprintf(fp,
"Usage: nmrpflash [OPTIONS...]\n" "Usage: nmrpflash [OPTIONS...]\n"
"\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 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" " -c <command> Command to run before (or instead of) TFTP upload\n"
" -f <firmware> Firmware file\n" " -f <firmware> Firmware file\n"
" -F <filename> Remote filename to use during TFTP upload\n" " -F <filename> Remote filename to use during TFTP upload\n"
@ -119,6 +120,7 @@ int main(int argc, char **argv)
.tftpcmd = NULL, .tftpcmd = NULL,
.file_local = NULL, .file_local = NULL,
.file_remote = NULL, .file_remote = NULL,
.ipaddr_intf = NULL,
.ipaddr = NULL, .ipaddr = NULL,
.ipmask = "255.255.255.0", .ipmask = "255.255.255.0",
.intf = NULL, .intf = NULL,
@ -160,12 +162,15 @@ int main(int argc, char **argv)
opterr = 0; 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; max = 0x7fffffff;
switch (c) { switch (c) {
case 'a': case 'a':
args.ipaddr = optarg; args.ipaddr = optarg;
break; break;
case 'A':
args.ipaddr_intf = optarg;
break;
case 'c': case 'c':
args.tftpcmd = optarg; args.tftpcmd = optarg;
break; 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); usage(stderr);
return 1; 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 *gsock = NULL;
static struct ethsock_ip_undo *gundo = NULL;
static int garp = 0; static int garp = 0;
static struct in_addr arpip = { 0 }; static struct in_addr arpip = { 0 };
static uint8_t arpmac[6] = { 0 }; static uint8_t arpmac[6] = { 0 };
@ -382,6 +383,7 @@ static void sigh(int sig)
if (garp) { if (garp) {
ethsock_arp_del(gsock, arpmac, &arpip); ethsock_arp_del(gsock, arpmac, &arpip);
} }
ethsock_del_ip(gsock, &gundo);
ethsock_close(gsock); ethsock_close(gsock);
gsock = NULL; gsock = NULL;
} }
@ -400,6 +402,7 @@ int nmrp_do(struct nmrpd_args *args)
time_t beg; time_t beg;
int i, status, ulreqs, expect, upload_ok, autoip; int i, status, ulreqs, expect, upload_ok, autoip;
struct ethsock *sock; struct ethsock *sock;
uint32_t intf_addr;
void (*sigh_orig)(int); void (*sigh_orig)(int);
struct { struct {
struct in_addr addr; struct in_addr addr;
@ -416,19 +419,34 @@ int nmrp_do(struct nmrpd_args *args)
return 1; 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) { if ((ipconf.mask.s_addr = inet_addr(args->ipmask)) == INADDR_NONE) {
fprintf(stderr, "Invalid subnet mask '%s'.\n", args->ipmask); fprintf(stderr, "Invalid subnet mask '%s'.\n", args->ipmask);
return 1; 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) { 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); fprintf(stderr, "Error accessing file '%s'.\n", args->file_local);
return 1; return 1;
@ -454,12 +472,6 @@ int nmrp_do(struct nmrpd_args *args)
status = 1; 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); sock = ethsock_create(args->intf, ETH_P_NMRP);
if (!sock) { if (!sock) {
return 1; return 1;
@ -469,13 +481,15 @@ int nmrp_do(struct nmrpd_args *args)
garp = 0; garp = 0;
sigh_orig = signal(SIGINT, sigh); sigh_orig = signal(SIGINT, sigh);
status = is_valid_ip(sock, &ipconf.addr, &ipconf.mask); if (!autoip) {
if (status <= 0) { status = is_valid_ip(sock, &ipconf.addr, &ipconf.mask);
if (!status) { if (status <= 0) {
fprintf(stderr, "Address %s/%s cannot be used on interface %s.\n", if (!status) {
args->ipaddr, args->ipmask, args->intf); 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)) { if (ethsock_set_timeout(sock, args->rx_timeout)) {
@ -608,6 +622,12 @@ int nmrp_do(struct nmrpd_args *args)
status = 0; status = 0;
if (autoip) {
if (ethsock_set_ip(sock, intf_addr, ipconf.mask.s_addr, &gundo) != 0) {
goto out;
}
}
if (args->tftpcmd) { if (args->tftpcmd) {
printf("Executing '%s' ... ", args->tftpcmd); printf("Executing '%s' ... ", args->tftpcmd);
fflush(stdout); fflush(stdout);
@ -616,14 +636,16 @@ int nmrp_do(struct nmrpd_args *args)
} }
if (!status && args->file_local) { if (!status && args->file_local) {
status = is_valid_ip(sock, &ipconf.addr, &ipconf.mask); if (!autoip) {
if (status < 0) { status = is_valid_ip(sock, &ipconf.addr, &ipconf.mask);
goto out; if (status < 0) {
} else if (!status) { goto out;
printf("IP address of %s has changed. Please assign a " } else if (!status) {
"static ip to the interface.\n", args->intf); printf("IP address of %s has changed. Please assign a "
tx.msg.code = NMRP_C_CLOSE_REQ; "static ip to the interface.\n", args->intf);
break; tx.msg.code = NMRP_C_CLOSE_REQ;
break;
}
} }
if (verbosity) { if (verbosity) {
@ -640,6 +662,10 @@ int nmrp_do(struct nmrpd_args *args)
status = tftp_put(args); status = tftp_put(args);
} }
if (ethsock_del_ip(sock, &gundo) != 0) {
goto out;
}
if (!status) { if (!status) {
printf("OK\nWaiting for remote to respond.\n"); printf("OK\nWaiting for remote to respond.\n");
upload_ok = 1; upload_ok = 1;

View file

@ -75,6 +75,7 @@ struct nmrpd_args {
const char *tftpcmd; const char *tftpcmd;
const char *file_local; const char *file_local;
const char *file_remote; const char *file_remote;
const char *ipaddr_intf;
const char *ipaddr; const char *ipaddr;
const char *ipmask; const char *ipmask;
const char *intf; const char *intf;
@ -103,6 +104,7 @@ void sock_perror(const char *msg);
extern int verbosity; extern int verbosity;
struct ethsock; struct ethsock;
struct ethsock_ip_undo;
struct ethsock *ethsock_create(const char *intf, uint16_t protocol); struct ethsock *ethsock_create(const char *intf, uint16_t protocol);
int ethsock_close(struct ethsock *sock); 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, int ethsock_for_each_ip(struct ethsock *sock, ethsock_ip_callback_t callback,
void *arg); 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 #endif