9760c61fad06bd59862276981cb18730d26151de
[oweals/nmrpflash.git] / main.c
1 /**
2  * nmrpflash - Netgear Unbrick Utility
3  * Copyright (C) 2016 Joseph Lehner <joseph.c.lehner@gmail.com>
4  *
5  * nmrpflash is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * nmrpflash is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with nmrpflash.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19
20 #include <unistd.h>
21 #include <getopt.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include "nmrpd.h"
25
26 int verbosity = 0;
27
28 void usage(FILE *fp)
29 {
30         fprintf(fp,
31                         "Usage: nmrpflash [OPTIONS...]\n"
32                         "\n"
33                         "Options (-a, -i and -f and/or -c are mandatory):\n"
34                         " -a <ipaddr>     IP address to assign to target device\n"
35                         " -c <command>    Command to run before (or instead of) TFTP upload\n"
36                         " -f <firmware>   Firmware file\n"
37                         " -F <filename>   Remote filename to use during TFTP upload\n"
38                         " -i <interface>  Network interface directly connected to device\n"
39                         " -m <mac>        MAC address of target device (xx:xx:xx:xx:xx:xx)\n"
40                         " -M <netmask>    Subnet mask to assign to target device\n"
41                         " -t <timeout>    Timeout (in milliseconds) for regular messages\n"
42                         " -T <timeout>    Time (seconds) to wait after successfull TFTP upload\n"
43                         " -p <port>       Port to use for TFTP upload\n"
44 #ifdef NMRPFLASH_SET_REGION
45                         " -R <region>     Set device region\n"
46 #endif
47 #ifdef NMRPFLASH_TFTP_TEST
48                         " -U              Test TFTP upload\n"
49 #endif
50                         " -v              Be verbose\n"
51                         " -V              Print version and exit\n"
52                         " -L              List network interfaces\n"
53                         " -h              Show this screen\n"
54                         "\n"
55                         "Example:\n"
56                         "\n"
57 #ifndef NMRPFLASH_WINDOWS
58                         "$ sudo nmrpflash -i eth0 -a 192.168.1.254 -f firmware.bin\n"
59 #else
60                         "C:\\> nmrpflash.exe -i net0 -a 192.168.1.254 -f firmware.bin\n"
61 #endif
62                         "\n"
63                         "nmrpflash %s, Copyright (C) 2016 Joseph C. Lehner\n"
64                         "nmrpflash is free software, licensed under the GNU GPLv3.\n"
65                         "Source code at https://github.com/jclehner/nmrpflash\n"
66                         "\n",
67                         NMRPFLASH_VERSION
68           );
69 }
70
71 int main(int argc, char **argv)
72 {
73         int c, val, max;
74         struct nmrpd_args args = {
75                 .rx_timeout = 200,
76                 .ul_timeout = 120000,
77                 .tftpcmd = NULL,
78                 .file_local = NULL,
79                 .file_remote = NULL,
80                 .ipaddr = NULL,
81                 .ipmask = "255.255.255.0",
82                 .intf = NULL,
83                 .mac = "ff:ff:ff:ff:ff:ff",
84                 .op = NMRP_UPLOAD_FW,
85                 .port = 69,
86                 .force_root = 1
87         };
88 #ifdef NMRPFLASH_WINDOWS
89         WSADATA wsa;
90
91         val = WSAStartup(MAKEWORD(2, 2), &wsa);
92         if (val != 0) {
93                 win_perror2("WSAStartup", val);
94                 return 1;
95         }
96 #endif
97
98         opterr = 0;
99
100         while ((c = getopt(argc, argv, "a:c:f:F:i:m:M:p:R:t:T:hLVvU")) != -1) {
101                 max = 0x7fffffff;
102                 switch (c) {
103                         case 'a':
104                                 args.ipaddr = optarg;
105                                 break;
106                         case 'c':
107                                 args.tftpcmd = optarg;
108                                 break;
109                         case 'f':
110                                 args.file_local = optarg;
111                                 break;
112                         case 'F':
113                                 args.file_remote = optarg;
114                                 break;
115                         case 'i':
116                                 args.intf = optarg;
117                                 break;
118                         case 'm':
119                                 args.mac = optarg;
120                                 break;
121                         case 'M':
122                                 args.ipmask = optarg;
123                                 break;
124                         case 'p':
125 #ifdef NMRPFLASH_SET_REGION
126                         case 'R':
127 #endif
128                         case 'T':
129                         case 't':
130                                 if (c == 'p') {
131                                         max = 0xffff;
132                                 } else if (c == 'R') {
133                                         max = 0x0009;
134                                 }
135
136                                 val = atoi(optarg);
137                                 if (val <= 0 || val > max) {
138                                         fprintf(stderr, "Invalid numeric value for -%c.\n", c);
139                                         return 1;
140                                 }
141
142                                 if (c == 'p') {
143                                         args.port = val;
144                                 } else if (c == 't') {
145                                         args.rx_timeout = val;
146                                 } else if (c == 'T') {
147                                         args.ul_timeout = val * 1000;
148                                 } else if (c == 'R') {
149                                         args.region = val;
150                                 }
151
152                                 break;
153                         case 'V':
154                                 printf("nmrpflash %s\n", NMRPFLASH_VERSION);
155                                 val = 0;
156                                 goto out;
157                         case 'v':
158                                 ++verbosity;
159                                 break;
160                         case 'L':
161                                 val = ethsock_list_all();
162                                 goto out;
163                         case 'h':
164                                 usage(stdout);
165                                 val = 0;
166                                 goto out;
167 #ifdef NMRPFLASH_TFTP_TEST
168                         case 'U':
169                                 if (args.ipaddr && args.file_local) {
170                                         val = tftp_put(&args);
171                                         goto out;
172                                 }
173                                 /* fall through */
174 #endif
175                         default:
176                                 usage(stderr);
177                                 val = 1;
178                                 goto out;
179                 }
180         }
181
182         if ((!args.file_local && !args.tftpcmd) || !args.intf || !args.ipaddr) {
183                 usage(stderr);
184                 return 1;
185         }
186
187 #ifndef NMRPFLASH_WINDOWS
188         if (geteuid() != 0) {
189                 fprintf(stderr, "This program must be run as root!\n");
190                 return 1;
191         }
192 #endif
193
194         val = nmrp_do(&args);
195
196 out:
197 #ifdef NMRPFLASH_WINDOWS
198         WSACleanup();
199 #endif
200         return val;
201 }