Don't require user to specify -a anymore
This commit is contained in:
parent
f38833e940
commit
2cf812dcfe
4 changed files with 200 additions and 33 deletions
130
ethsock.c
130
ethsock.c
|
@ -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
16
main.c
|
@ -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
82
nmrp.c
|
@ -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;
|
||||
|
|
5
nmrpd.h
5
nmrpd.h
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue