2 Copyright 2006 Chris Tallon
4 This file is part of VOMP.
6 VOMP is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 VOMP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with VOMP; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 //void dump(unsigned char* data, USHORT size);
24 //unsigned char dcc(UCHAR c);
28 log = Log::getInstance();
36 int Bootpd::shutdown()
38 if (threadIsActive()) threadCancel();
44 int Bootpd::run(const char* tconfigDir)
46 if (threadIsActive()) return 1;
47 log->log("BOOTPD", Log::DEBUG, "Starting bootpd");
49 configDir = tconfigDir;
53 log->log("BOOTPD", Log::DEBUG, "DSock init error");
60 log->log("BOOTPD", Log::DEBUG, "Thread start error");
65 log->log("BOOTPD", Log::DEBUG, "Bootp replier started");
69 void Bootpd::threadMethod()
74 log->log("BOOTPD", Log::DEBUG, "Starting wait");
75 retval = ds.waitforMessage(0);
76 log->log("BOOTPD", Log::DEBUG, "Wait finished");
80 log->log("BOOTPD", Log::CRIT, "Wait for packet error");
89 processRequest((UCHAR*)ds.getData(), ds.getDataLength());
94 void Bootpd::processRequest(UCHAR* data, int length)
96 log->log("BOOTPD", Log::DEBUG, "Got request");
97 // dump(data, (USHORT)length);
99 if (data[0] != 1) return; // Check it's a request
101 // Open a config file for the given MAC
103 #ifndef VOMPSTANDALONE
104 const char* useConfigDir = configDir;
106 const char* useConfigDir = ".";
110 log->log("BOOTPD", Log::ERR, "No config dir!");
115 char configFileName[PATH_MAX];
116 snprintf(configFileName, PATH_MAX, "%s/vomp-%02X-%02X-%02X-%02X-%02X-%02X.conf", useConfigDir, data[28], data[29], data[30], data[31], data[32], data[33]);
117 if (config.init(configFileName))
119 log->log("BOOTPD", Log::DEBUG, "Opened config file: %s", configFileName);
123 log->log("BOOTPD", Log::ERR, "Could not open/create config file: %s", configFileName);
127 // Get an IP for the MVP (make a local copy so future returns don't all have to free string)
128 char newClientIP[100];
129 newClientIP[0] = '\0';
130 bool configHasIP = false;
131 char* cfnewClientIP = config.getValueString("Boot", "IP");
134 strncpy(newClientIP, cfnewClientIP, 99);
135 delete[] cfnewClientIP;
138 log->log("BOOTPD", Log::DEBUG, "Found IP %s for MVP", newClientIP);
142 log->log("BOOTPD", Log::WARN, "No IP found for MVP. Hopefully it has one already...");
145 // See if we should enforce the IP from the config file
147 long enforceConfigIP = config.getValueLong("Boot", "Override IP", &failure);
148 if (newClientIP[0] && enforceConfigIP)
150 log->log("BOOTPD", Log::DEBUG, "Will enforce IP %s on MVP even if it already has another", newClientIP);
154 log->log("BOOTPD", Log::DEBUG, "Will not change MVP IP if it already has one");
157 // See if the MVP already has an IP
158 bool clientAlreadyHasIP = (data[12] || data[13] || data[14] || data[15]);
161 Subset of Bootp protocol for MVP
165 Opcode 0 Check for value 1 Set to value 2
167 Hardware address length 2
173 Your IP 16-19 Set to MVP IP
174 Server IP 20-23 Set to server IP
176 Client HW address 28-43 (16) Use to lookup IP for MVP
177 Server Host Name 44-107 (64)
178 Boot filename 108-235 (128) Fill with filename for TFTP
179 Vendor info 236-299 (64)
183 mvpAlreadyHasIP configHasIP enforceConfigIP result
186 3 Y 0 1 0 set config ip
187 4 Y 0 1 1 set config ip
189 6 Y 1 0 1 set enforce false, set mvp ip
191 8 Y 1 1 1 set config ip
194 if (!clientAlreadyHasIP && !configHasIP) // cases 1 & 2
196 log->log("BOOTPD", Log::DEBUG, "No IP found to give to MVP");
200 if (!configHasIP) enforceConfigIP = 0; // case 6
202 // Ok, we will send a reply
204 in_addr_t finalMVPIP;
206 if ((!clientAlreadyHasIP) || (configHasIP && enforceConfigIP))
208 // Cases 3 & 4, case 8
209 log->log("BOOTPD", Log::DEBUG, "Giving MVP IP from config");
211 *((in_addr_t*)&data[16]) = inet_addr(newClientIP);
212 finalMVPIP = *((in_addr_t*)&data[16]);
217 // copy existing ciaddr to yiaddr?
218 log->log("BOOTPD", Log::DEBUG, "Leave YI=0 as MVP already has good IP");
219 finalMVPIP = *((in_addr_t*)&data[12]);
222 // Set Server IP in packet
223 if (!getmyip(finalMVPIP, (in_addr_t*)&data[20]))
225 log->log("BOOTPD", Log::ERR, "Get my IP failed");
229 char* tftpFileName = config.getValueString("Boot", "TFTP file name");
232 strncpy((char*)&data[108], tftpFileName, 127);
233 delete[] tftpFileName;
237 strncpy((char*)&data[108], "vomp-dongle", 127);
238 config.setValueString("Boot", "TFTP file name", "vomp-dongle");
244 // dump(data, (USHORT)length);
246 ds.send("255.255.255.255", 16868, (char*)data, length);
250 int Bootpd::getmyip(in_addr_t destination, in_addr_t* result)
253 struct sockaddr_in my_addr;
254 struct sockaddr_in dest_addr;
255 socklen_t my_addr_len = sizeof(struct sockaddr_in);
257 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
258 if (sockfd == -1) return 0;
260 dest_addr.sin_family = AF_INET;
261 dest_addr.sin_port = htons(1);
262 dest_addr.sin_addr.s_addr = destination;
263 memset(&(dest_addr.sin_zero), 0, 8);
265 r1 = connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr));
272 memset(&my_addr, 0, sizeof(struct sockaddr_in));
273 r2 = getsockname(sockfd, (struct sockaddr *)&my_addr, &my_addr_len);
277 if (r2 == -1) return 0;
279 *result = my_addr.sin_addr.s_addr;
284 void dump(unsigned char* data, USHORT size)
286 printf("Size = %u\n", size);
293 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
294 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
295 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
296 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
297 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]), dcc(data[c+14]), dcc(data[c+15]));
305 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
306 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
307 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14],
308 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
309 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]), dcc(data[c+14]));
313 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
314 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
315 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13],
316 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
317 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]));
321 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c%c%c\n",
322 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
323 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12],
324 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
325 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]));
329 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c%c\n",
330 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
331 data[c+8], data[c+9], data[c+10], data[c+11],
332 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
333 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]));
337 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c\n",
338 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
339 data[c+8], data[c+9], data[c+10],
340 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
341 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]));
345 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c\n",
346 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
347 data[c+8], data[c+9],
348 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
349 dcc(data[c+8]), dcc(data[c+9]));
353 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c\n",
354 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
356 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]),
361 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c\n",
362 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
363 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]));
367 printf(" %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c\n",
368 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6],
369 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]));
373 printf(" %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c\n",
374 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5],
375 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
379 printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n",
380 data[c], data[c+1], data[c+2], data[c+3], data[c+4],
381 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
385 printf(" %02X %02X %02X %02X %c%c%c%c\n",
386 data[c], data[c+1], data[c+2], data[c+3],
387 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
391 printf(" %02X %02X %02X %c%c%c\n",
392 data[c], data[c+1], data[c+2],
393 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
397 printf(" %02X %02X %c%c\n",
399 dcc(data[c]), dcc(data[c+1]));
413 unsigned char dcc(UCHAR c)
415 if (isspace(c)) return ' ';
416 if (isprint(c)) return c;