X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=main.c;h=9cf0041c2b82aea2e25388c7ba1dc812dc44ed45;hb=c2ce9b429da981b5055638c53cf30cb8dea87b78;hp=b8963e9e3ca0a65c7aaf5ad3a1a0b699301ef1b6;hpb=8dc5b3164b4e3982c0f70b8f64a313792fbedde7;p=oweals%2Fnmrpflash.git diff --git a/main.c b/main.c index b8963e9..9cf0041 100644 --- a/main.c +++ b/main.c @@ -1,19 +1,19 @@ /** - * nmrp-flash - Netgear Unbrick Utility + * nmrpflash - Netgear Unbrick Utility * Copyright (C) 2016 Joseph Lehner * - * nmrp-flash is free software: you can redistribute it and/or modify + * nmrpflash is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * nmrp-flash is distributed in the hope that it will be useful, + * nmrpflash is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with nmrp-flash. If not, see . + * along with nmrpflash. If not, see . * */ @@ -23,24 +23,28 @@ #include #include "nmrpd.h" -#define NMRPFLASH_TFTP_TEST - int verbosity = 0; void usage(FILE *fp) { fprintf(fp, - "Usage: nmrp-flash [OPTIONS...]\n" + "Usage: nmrpflash [OPTIONS...]\n" "\n" - "Options (-a, -i and -f are mandatory):\n" + "Options (-i, -f and/or -c are mandatory):\n" " -a IP address to assign to target device\n" + " -A IP address to assign to seleted interface\n" + " -c Command to run before (or instead of) TFTP upload\n" " -f Firmware file\n" + " -F Remote filename to use during TFTP upload\n" " -i Network interface directly connected to device\n" " -m MAC address of target device (xx:xx:xx:xx:xx:xx)\n" " -M Subnet mask to assign to target device\n" " -t Timeout (in milliseconds) for regular messages\n" - " -T Time to wait after successfull TFTP upload\n" + " -T Time (seconds) to wait after successfull TFTP upload\n" " -p Port to use for TFTP upload\n" +#ifdef NMRPFLASH_SET_REGION + " -R Set device region (NA, WW, GR, PR, RU, BZ, IN, KO, JP)\n" +#endif #ifdef NMRPFLASH_TFTP_TEST " -U Test TFTP upload\n" #endif @@ -49,58 +53,151 @@ void usage(FILE *fp) " -L List network interfaces\n" " -h Show this screen\n" "\n" - "Example:\n" - "\n" + "Example: (run as " +#ifndef NMRPFLASH_WINDOWS + "root" +#else + "administrator" +#endif + ")\n\n" #ifndef NMRPFLASH_WINDOWS - "$ sudo nmrp-flash -i eth0 -a 192.168.1.254 -f firmware.bin\n" + "# nmrpflash -i eth0 -f firmware.bin\n" #else - "C:\\> nmrp-flash.exe -i net0 -a 192.168.1.254 -f firmware.bin\n" + "C:\\> nmrpflash.exe -i net0 -f firmware.bin\n" #endif "\n" - "nmrp-flash v%s, Copyright (C) 2016 Joseph C. Lehner\n" - "nmrp-flash is free software, licensed under the GNU GPLv3.\n" - "Source code at https://github.com/jclehner/nmrp-flash\n" + "When using -c, the environment variables IP, PORT, NETMASK\n" + "and MAC are set to the device IP address, TFTP port, subnet\n" + "mask and MAC address, respectively.\n" + "\n" + "nmrpflash %s, Copyright (C) 2016 Joseph C. Lehner\n" + "nmrpflash is free software, licensed under the GNU GPLv3.\n" + "Source code at https://github.com/jclehner/nmrpflash\n" "\n", - NMRPD_VERSION + NMRPFLASH_VERSION ); } +#ifdef NMRPFLASH_WINDOWS +void require_admin() +{ + SID_IDENTIFIER_AUTHORITY auth = SECURITY_NT_AUTHORITY; + PSID group = NULL; + BOOL admin, success = AllocateAndInitializeSid( + &auth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, &group + ); + + if (success) { + success = CheckTokenMembership(NULL, group, &admin); + FreeSid(group); + if (success) { + if (!admin) { + fprintf(stderr, "Error: must be run as administrator\n"); + exit(1); + } else { + return; + } + } + } + + fprintf(stderr, "Warning: failed to check administrator privileges\n"); +} + +void show_exit_prompt() +{ + DWORD pid; + HWND win = GetConsoleWindow(); + if (!win || !GetWindowThreadProcessId(win, &pid)) { + return; + } + + if (GetCurrentProcessId() == pid) { + printf("Press any key to exit\n"); + getch(); + } +} +#else +void require_admin() +{ + if (getuid() != 0) { + fprintf(stderr, "Error: must be run as root\n"); + exit(1); + } +} +#endif + int main(int argc, char **argv) { int c, val, max; + int list = 0; struct nmrpd_args args = { .rx_timeout = 200, - .ul_timeout = 60000, + .ul_timeout = 5 * 60 * 1000, .tftpcmd = NULL, - .filename = NULL, + .file_local = NULL, + .file_remote = NULL, + .ipaddr_intf = NULL, .ipaddr = NULL, .ipmask = "255.255.255.0", .intf = NULL, .mac = "ff:ff:ff:ff:ff:ff", .op = NMRP_UPLOAD_FW, .port = 69, - .force_root = 1 + .region = NULL, }; #ifdef NMRPFLASH_WINDOWS + char *newpath = NULL; + char *oldpath = NULL; + char *windir = NULL; WSADATA wsa; + atexit(&show_exit_prompt); + val = WSAStartup(MAKEWORD(2, 2), &wsa); if (val != 0) { win_perror2("WSAStartup", val); return 1; } + + +#ifndef _WIN64 + // This dirty hack works around the WOW64 file system redirector[1], which would prevent + // us from calling programs residing in %windir%\System32 when running on a 64bit system + // (since nmrpflash is currently shipped as 32bit only). + // + // [1] https://msdn.microsoft.com/en-us/library/windows/desktop/aa384187(v=vs.85).aspx + + oldpath = getenv("PATH"); + windir = getenv("WINDIR"); + if (oldpath && windir) { + newpath = malloc(strlen(oldpath) + strlen(windir) + 32); + sprintf(newpath, "%s;%s\\Sysnative", oldpath, windir); + SetEnvironmentVariable("PATH", newpath); + free(newpath); + } +#endif #endif opterr = 0; - while ((c = getopt(argc, argv, "a:f:i:m:M:p: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; case 'f': - args.filename = optarg; + args.file_local = optarg; + break; + case 'F': + args.file_remote = optarg; break; case 'i': args.intf = optarg; @@ -111,10 +208,18 @@ int main(int argc, char **argv) case 'M': args.ipmask = optarg; break; +#ifdef NMRPFLASH_SET_REGION + case 'R': + args.region = optarg; + break; +#endif case 'p': - max = 0xffff; case 'T': case 't': + if (c == 'p') { + max = 0xffff; + } + val = atoi(optarg); if (val <= 0 || val > max) { fprintf(stderr, "Invalid numeric value for -%c.\n", c); @@ -125,20 +230,21 @@ int main(int argc, char **argv) args.port = val; } else if (c == 't') { args.rx_timeout = val; - } else { - args.ul_timeout = val; + } else if (c == 'T') { + args.ul_timeout = val * 1000; } break; case 'V': - printf("nmrp-flash v%s\n", NMRPD_VERSION); + printf("nmrpflash %s\n", NMRPFLASH_VERSION); val = 0; goto out; case 'v': ++verbosity; break; case 'L': - val = ethsock_list_all(); + list = 1; + break; goto out; case 'h': usage(stdout); @@ -146,7 +252,7 @@ int main(int argc, char **argv) goto out; #ifdef NMRPFLASH_TFTP_TEST case 'U': - if (args.ipaddr && args.filename) { + if (args.ipaddr && args.file_local) { val = tftp_put(&args); goto out; } @@ -159,19 +265,22 @@ int main(int argc, char **argv) } } - if (!args.filename || !args.intf || !args.ipaddr) { - usage(stderr); + if (args.ipaddr_intf && !args.ipaddr) { + fprintf(stderr, "Error: cannot use -A without using -a .\n"); return 1; } -#ifndef NMRPFLASH_WINDOWS - if (geteuid() != 0) { - fprintf(stderr, "This program must be run as root!\n"); +#ifndef NMRPFLASH_FUZZ + if (!list && ((!args.file_local && !args.tftpcmd) || !args.intf /*|| !args.ipaddr*/)) { + usage(stderr); return 1; } -#endif - val = nmrp_do(&args); + if (!list) { + require_admin(); + } +#endif + val = !list ? nmrp_do(&args) : ethsock_list_all(); out: #ifdef NMRPFLASH_WINDOWS