#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>
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];
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;
+}
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"
.tftpcmd = NULL,
.file_local = NULL,
.file_remote = NULL,
+ .ipaddr_intf = NULL,
.ipaddr = NULL,
.ipmask = "255.255.255.0",
.intf = NULL,
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;
}
}
- 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;
}
}
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 };
if (garp) {
ethsock_arp_del(gsock, arpmac, &arpip);
}
+ ethsock_del_ip(gsock, &gundo);
ethsock_close(gsock);
gsock = NULL;
}
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;
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;
+ 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 = 0;
+ autoip = false;
}
- if ((ipconf.mask.s_addr = inet_addr(args->ipmask)) == INADDR_NONE) {
- fprintf(stderr, "Invalid subnet mask '%s'.\n", args->ipmask);
+ 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;
}
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;
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)) {
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);
}
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) {
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;
const char *tftpcmd;
const char *file_local;
const char *file_remote;
+ const char *ipaddr_intf;
const char *ipaddr;
const char *ipmask;
const char *intf;
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);
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