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.
21 #include <linux/limits.h>
25 //void dump(unsigned char* data, USHORT size);
26 //unsigned char dcc(UCHAR c);
30 log = Log::getInstance();
38 int Bootpd::shutdown()
40 if (threadIsActive()) threadCancel();
46 int Bootpd::run(const char* tconfigDir)
48 if (threadIsActive()) return 1;
49 log->log("BOOTPD", Log::DEBUG, "Starting bootpd");
51 configDir = tconfigDir;
55 log->log("BOOTPD", Log::DEBUG, "DSock init error");
62 log->log("BOOTPD", Log::DEBUG, "Thread start error");
67 log->log("BOOTPD", Log::DEBUG, "Bootp replier started");
71 void Bootpd::threadMethod()
76 log->log("BOOTPD", Log::DEBUG, "Starting wait");
77 retval = ds.waitforMessage(0);
78 log->log("BOOTPD", Log::DEBUG, "Wait finished");
82 log->log("BOOTPD", Log::CRIT, "Wait for packet error");
91 processRequest((UCHAR*)ds.getData(), ds.getDataLength());
96 void Bootpd::processRequest(UCHAR* data, int length)
98 log->log("BOOTPD", Log::DEBUG, "Got request");
99 // dump(data, (USHORT)length);
101 if (data[0] != 1) return; // Check it's a request
103 // Open a config file for the given MAC
105 #ifndef VOMPSTANDALONE
106 const char* useConfigDir = configDir;
108 const char* useConfigDir = ".";
112 log->log("BOOTPD", Log::ERR, "No config dir!");
117 char configFileName[PATH_MAX];
118 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]);
119 if (config.init(configFileName))
121 log->log("BOOTPD", Log::DEBUG, "Opened config file: %s", configFileName);
125 log->log("BOOTPD", Log::ERR, "Could not open/create config file: %s", configFileName);
129 // Get an IP for the MVP (make a local copy so future returns don't all have to free string)
130 char newClientIP[100];
131 newClientIP[0] = '\0';
132 bool configHasIP = false;
133 char* cfnewClientIP = config.getValueString("Boot", "IP");
136 strncpy(newClientIP, cfnewClientIP, 99);
137 delete[] cfnewClientIP;
140 log->log("BOOTPD", Log::DEBUG, "Found IP %s for MVP", newClientIP);
144 log->log("BOOTPD", Log::WARN, "No IP found for MVP. Hopefully it has one already...");
147 // See if we should enforce the IP from the config file
149 long enforceConfigIP = config.getValueLong("Boot", "Override IP", &failure);
150 if (newClientIP[0] && enforceConfigIP)
152 log->log("BOOTPD", Log::DEBUG, "Will enforce IP %s on MVP even if it already has another", newClientIP);
156 log->log("BOOTPD", Log::DEBUG, "Will not change MVP IP if it already has one");
159 // See if the MVP already has an IP
160 bool clientAlreadyHasIP = (data[12] || data[13] || data[14] || data[15]);
163 Subset of Bootp protocol for MVP
167 Opcode 0 Check for value 1 Set to value 2
169 Hardware address length 2
175 Your IP 16-19 Set to MVP IP
176 Server IP 20-23 Set to server IP
178 Client HW address 28-43 (16) Use to lookup IP for MVP
179 Server Host Name 44-107 (64)
180 Boot filename 108-235 (128) Fill with filename for TFTP
181 Vendor info 236-299 (64)
185 mvpAlreadyHasIP configHasIP enforceConfigIP result
188 3 Y 0 1 0 set config ip
189 4 Y 0 1 1 set config ip
191 6 Y 1 0 1 set enforce false, set mvp ip
193 8 Y 1 1 1 set config ip
196 if (!clientAlreadyHasIP && !configHasIP) // cases 1 & 2
198 log->log("BOOTPD", Log::DEBUG, "No IP found to give to MVP");
202 if (!configHasIP) enforceConfigIP = 0; // case 6
204 // Ok, we will send a reply
206 in_addr_t finalMVPIP;
208 if ((!clientAlreadyHasIP) || (configHasIP && enforceConfigIP))
210 // Cases 3 & 4, case 8
211 log->log("BOOTPD", Log::DEBUG, "Giving MVP IP from config");
213 *((in_addr_t*)&data[16]) = inet_addr(newClientIP);
214 finalMVPIP = *((in_addr_t*)&data[16]);
219 // copy existing ciaddr to yiaddr?
220 log->log("BOOTPD", Log::DEBUG, "Leave YI=0 as MVP already has good IP");
221 finalMVPIP = *((in_addr_t*)&data[12]);
224 // Set Server IP in packet
225 if (!getmyip(finalMVPIP, (in_addr_t*)&data[20]))
227 log->log("BOOTPD", Log::ERR, "Get my IP failed");
231 char* tftpFileName = config.getValueString("Boot", "TFTP file name");
234 strncpy((char*)&data[108], tftpFileName, 127);
235 delete[] tftpFileName;
239 strncpy((char*)&data[108], "vomp-dongle", 127);
240 config.setValueString("Boot", "TFTP file name", "vomp-dongle");
246 // dump(data, (USHORT)length);
248 ds.send("255.255.255.255", 16868, (char*)data, length);
252 int Bootpd::getmyip(in_addr_t destination, in_addr_t* result)
255 struct sockaddr_in my_addr;
256 struct sockaddr_in dest_addr;
257 socklen_t my_addr_len = sizeof(struct sockaddr_in);
259 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
260 if (sockfd == -1) return 0;
262 dest_addr.sin_family = AF_INET;
263 dest_addr.sin_port = htons(1);
264 dest_addr.sin_addr.s_addr = destination;
265 memset(&(dest_addr.sin_zero), 0, 8);
267 r1 = connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr));
274 memset(&my_addr, 0, sizeof(struct sockaddr_in));
275 r2 = getsockname(sockfd, (struct sockaddr *)&my_addr, &my_addr_len);
279 if (r2 == -1) return 0;
281 *result = my_addr.sin_addr.s_addr;
286 void dump(unsigned char* data, USHORT size)
288 printf("Size = %u\n", size);
295 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",
296 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
297 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15],
298 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]),
299 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]));
307 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",
308 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
309 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14],
310 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]),
311 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]));
315 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",
316 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
317 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13],
318 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]),
319 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]));
323 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",
324 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
325 data[c+8], data[c+9], data[c+10], data[c+11], data[c+12],
326 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]),
327 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]));
331 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",
332 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
333 data[c+8], data[c+9], data[c+10], data[c+11],
334 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]),
335 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]));
339 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c\n",
340 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
341 data[c+8], data[c+9], data[c+10],
342 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]),
343 dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]));
347 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c\n",
348 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
349 data[c+8], data[c+9],
350 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]),
351 dcc(data[c+8]), dcc(data[c+9]));
355 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c\n",
356 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
358 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]),
363 printf(" %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c\n",
364 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7],
365 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]));
369 printf(" %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c\n",
370 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6],
371 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]));
375 printf(" %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c\n",
376 data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5],
377 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]));
381 printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n",
382 data[c], data[c+1], data[c+2], data[c+3], data[c+4],
383 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]));
387 printf(" %02X %02X %02X %02X %c%c%c%c\n",
388 data[c], data[c+1], data[c+2], data[c+3],
389 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]));
393 printf(" %02X %02X %02X %c%c%c\n",
394 data[c], data[c+1], data[c+2],
395 dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]));
399 printf(" %02X %02X %c%c\n",
401 dcc(data[c]), dcc(data[c+1]));
415 unsigned char dcc(UCHAR c)
417 if (isspace(c)) return ' ';
418 if (isprint(c)) return c;