X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=main.c;h=9cf0041c2b82aea2e25388c7ba1dc812dc44ed45;hb=c2ce9b429da981b5055638c53cf30cb8dea87b78;hp=45b406fbcdb668ce608ee308a15eb79e1b6542e7;hpb=98607d141bd8deec3cedb599277589b3d1dc6280;p=oweals%2Fnmrpflash.git diff --git a/main.c b/main.c index 45b406f..9cf0041 100644 --- a/main.c +++ b/main.c @@ -30,16 +30,21 @@ 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 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 (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 @@ -48,13 +53,22 @@ 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 nmrpflash -i eth0 -a 192.168.1.254 -f firmware.bin\n" + "# nmrpflash -i eth0 -f firmware.bin\n" #else - "C:\\> nmrpflash.exe -i net0 -a 192.168.1.254 -f firmware.bin\n" + "C:\\> nmrpflash.exe -i net0 -f firmware.bin\n" #endif + "\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" @@ -64,46 +78,127 @@ void usage(FILE *fp) ); } +#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 = 120000, + .ul_timeout = 5 * 60 * 1000, .tftpcmd = 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:c: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.file_local = optarg; break; + case 'F': + args.file_remote = optarg; + break; case 'i': args.intf = optarg; break; @@ -113,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); @@ -127,7 +230,7 @@ int main(int argc, char **argv) args.port = val; } else if (c == 't') { args.rx_timeout = val; - } else { + } else if (c == 'T') { args.ul_timeout = val * 1000; } @@ -140,7 +243,8 @@ int main(int argc, char **argv) ++verbosity; break; case 'L': - val = ethsock_list_all(); + list = 1; + break; goto out; case 'h': usage(stdout); @@ -161,19 +265,22 @@ int main(int argc, char **argv) } } - if ((!args.file_local && !args.tftpcmd) || !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