1 #include <headers.h>
2 #include <datatypes.h>
3 #include <display.h>
4 #include <parser.h>
5 #include <leases.h>
6 #include <options.h>
7 
8 int parse_dhcp_options( DHCPMESSAGE *dhcpm, DHCPOPTIONS *dhcpo )
9 {
10   int pointer, opointer;
11   int olength;
12 
13   pointer = 0;
14 
15   fprintf( stdout, "parse_dhcp_options [begin]!\n");
16 
17   /* Options Initialization */
18   /* No message type */
19   dhcpo->type = 0;
20   /* No ip address, 0.0.0.0 */
21   dhcpo->r_ip = 0;
22   /* No mask address, 0.0.0.0 */
23   dhcpo->r_mask = 0;
24   /* No router, 0.0.0.0 */
25   dhcpo->r_router = 0;
26   /* No lease 0 */
27   dhcpo->r_lease = 0;
28   /* No name '\n' */
29   dhcpo->hostname = NULL;
30 
31   while( pointer< 312 )
32     {
33       if(( dhcpm->options[0] != 99 ) && (dhcpm->options[1]!=130) && (dhcpm->options[2]!=83) && (dhcpm->options[3]!= 99))
34 	{
35 	  fprintf( stdout, "No magic cookie! Aborting! \n" );
36 	  return -1;
37 	}
38       switch( dhcpm->options[pointer] ){
39       case PAD:
40 	pointer++;
41 	break;
42       case MESSAGETYPE:
43 	/* Try to figure out the kind of message and start the configuring process */
44 	pointer += 2;
45 	dhcpo->type = dhcpm->options[pointer++];
46 	break;
47       case PREQUEST:
48 	/* Take note of the requested parameters */
49 	opointer = pointer + 2;
50 	olength = pointer + dhcpm->options[pointer + 1];
51 	while( opointer < olength )
52 	  {
53 	    switch( dhcpm->options[opointer] ){
54 	    case IP:
55 	      /* Take note of the requested ip */
56 	      opointer += 2;
57 	      dhcpo->r_ip += dhcpm->options[opointer++];
58 	      dhcpo->r_ip = dhcpo->r_ip << 8;
59 	      dhcpo->r_ip += dhcpm->options[opointer++];
60 	      dhcpo->r_ip = dhcpo->r_ip << 8;
61 	      dhcpo->r_ip += dhcpm->options[opointer++];
62 	      dhcpo->r_ip = dhcpo->r_ip << 8;
63 	      dhcpo->r_ip += dhcpm->options[opointer++];
64 	      break;
65 	    case MASK:
66 	      /* Take note of the requested mask */
67 	      opointer += 2;
68 	      dhcpo->r_mask += dhcpm->options[opointer++];
69 	      dhcpo->r_mask = dhcpo->r_ip << 8;
70 	      dhcpo->r_mask += dhcpm->options[opointer++];
71 	      dhcpo->r_mask = dhcpo->r_ip << 8;
72 	      dhcpo->r_mask += dhcpm->options[opointer++];
73 	      dhcpo->r_mask = dhcpo->r_ip << 8;
74 	      dhcpo->r_mask += dhcpm->options[opointer++];
75 	      break;
76 	    case ROUTER:
77 	      /* Take note of the requested router */
78 	      opointer += 2;
79 	      dhcpo->r_router += dhcpm->options[opointer++];
80 	      dhcpo->r_router = dhcpo->r_ip << 8;
81 	      dhcpo->r_router += dhcpm->options[opointer++];
82 	      dhcpo->r_router = dhcpo->r_ip << 8;
83 	      dhcpo->r_router += dhcpm->options[opointer++];
84 	      dhcpo->r_router = dhcpo->r_ip << 8;
85 	      dhcpo->r_router += dhcpm->options[opointer++];
86 	      break;
87 	    case LEASE:
88 	      opointer += 2;
89 	      dhcpo->r_lease += dhcpm->options[opointer++];
90 	      dhcpo->r_lease = dhcpo->r_ip << 8;
91 	      dhcpo->r_lease += dhcpm->options[opointer++];
92 	      dhcpo->r_lease = dhcpo->r_ip << 8;
93 	      dhcpo->r_lease += dhcpm->options[opointer++];
94 	      dhcpo->r_lease = dhcpo->r_ip << 8;
95 	      dhcpo->r_lease += dhcpm->options[opointer++];
96 	      break;
97 	    case HOSTNAME:
98 	      opointer += 1;
99 	      dhcpo->hostname = (char *)malloc( dhcpm->options[opointer] + 1);
100 	      strncpy( dhcpo->hostname, &dhcpm->options[opointer+1], dhcpm->options[opointer] );
101 	      opointer += dhcpm->options[opointer] + 1;
102 	    default:
103 	      /* Ignore option */
104 	      opointer++;
105 	      break;
106 	    }
107 	  }
108 	pointer = opointer;
109 	break;
110       case  TOFFSET:
111       case  TIMESERVER:
112       case  NS:
113       case  DNS:
114       case  LOGSERVER:
115       case  COOKIESERVER:
116       case  LPRSERVER:
117       case  IMPSERVER:
118       case  RESLOCSERVER:
119       case  BOOTFILESIZE:
120       case  MERITDUMPFILE:
121       case  DOMAINNAME:
122       case  SWAPSERVER:
123       case  ROOTPATH:
124       case  EXTENSIONPATH:
125       case  IPFORWARD:
126       case  NONLOCAL:
127       case  POLICYFILTER:
128       case  MAXIMUMDATAG:
129       case  DEFAULTTTL:
130       case  PATHMTUATO:
131       case  PATHMTUPTO:
132       case  IMTU:
133       case  ALLSUBLOCAL:
134       case  BROADCAST:
135       case  PMASKDISCOVERY:
136       case  MASKSUPPLIER:
137       case  PROUTERDISCOVE:
138       case  RSOLICIADDRESS:
139       case  STATICROUTE:
140       case  TENCAPSULATION:
141       case  ARPCACHE:
142       case  ETHENCAPSUL:
143       case  TCPDEFTTL:
144       case  TCPKAI:
145       case  TCPKAG:
146       case  NISDOMAIN:
147       case  NISSERVER:
148       case  NTPSERVER:
149       case  VENDORSP:
150       case  NBTCPIPNS:
151       case  NBTCPIPDDS:
152       case  NBTCPIPNT:
153       case  NBTCPIPSC:
154       case  XWINFONTSERVER:
155       case  XWINDISPLAY:
156       case  OVERLOAD:
157       case  SERVER:
158       case  MESSAGE:
159       case  MAXIMUMDHCP:
160       case  RENEWALTIME:
161       case  REBINDING:
162       case  VENDORCLASS:
163       case  NISPLUSDOMAIN:
164       case  NISPLUSSERVER:
165       case  TFTPSERVER:
166       case  BOOTFILE:
167       case  MOBILEIP:
168       case  SMTPSERVER:
169       case  POP3SERVER:
170       case  NNTPSERVER:
171       case  HTTPSERVER:
172       case  FINGERSERVER:
173       case  IRCSERVER:
174       case  STREETTALKSE:
175       case  STREETTALKDA:
176       case CLIENT:
177 	pointer++;
178 	pointer += dhcpm->options[pointer];
179       case END:
180 	/* return to the calling functions because this is over */
181 	fprintf( stdout, "parse_dhcp_options: END option found! [end]!\n");
182 	return 0;
183       default:
184 	/* ignored */
185 	pointer++;
186 	break;
187       }
188     }
189   fprintf( stdout, "parse_dhcp_options [end]!\n");
190   return 0;
191 }
192 
193 int process_dhcp_packet( DHCPMESSAGE *dhcpm, DHCPOPTIONS *dhcpo )
194 {
195   int pointer = 4;
196   DHCPLEASE dhcpl;
197   char *name;
198 
199   fprintf( stdout, "process_dhcp_packet [begin]!\n");
200 
201   if( (!dhcpm) || (!dhcpo) )
202     return -1;
203 
204   name = (char *)malloc( 16 );
205   switch( dhcpo->type ){
206 
207   case DHCPDISCOVER:
208     /* We need to send a DHCPOFFER */
209     if( find_lease( &dhcpl, dhcpm->xid, dhcpm->chaddr ) < 0 )
210       {
211 	fprintf( stdout, "No free leases! \n" );
212 	free( name );
213 	return -1;
214       }
215     dhcpm->op = BOOTREPLY;
216     dhcpm->yiaddr = dhcpl.ip;
217     dhcpm->siaddr = dhcpl.siaddr;
218     strcpy(dhcpm->sname, VERSION);
219     dhcpm->options[pointer++] = MESSAGETYPE;
220     dhcpm->options[pointer++] = 1;
221     dhcpm->options[pointer++] = DHCPOFFER;
222     dhcpm->options[pointer++] = ROUTER;
223     dhcpm->options[pointer++] = 4;
224     dhcpm->options[pointer++] = (dhcpl.router & 0xFF);
225     dhcpm->options[pointer++] = ((dhcpl.router >> 8) & 0xFF);
226     dhcpm->options[pointer++] = ((dhcpl.router >> 16) &0xFF);
227     dhcpm->options[pointer++] = (dhcpl.router >> 24);
228     dhcpm->options[pointer++] = MASK;
229     dhcpm->options[pointer++] = 4;
230     dhcpm->options[pointer++] = (dhcpl.mask & 0xFF);
231     dhcpm->options[pointer++] = ((dhcpl.mask >> 8) & 0xFF);
232     dhcpm->options[pointer++] = ((dhcpl.mask >> 16) & 0xFF);
233     dhcpm->options[pointer++] = (dhcpl.mask >> 24);
234     dhcpm->options[pointer++] = SERVER;
235     dhcpm->options[pointer++] = 4;
236     dhcpm->options[pointer++] = (dhcpl.siaddr & 0xFF);
237     dhcpm->options[pointer++] = ((dhcpl.siaddr >> 8) & 0xFF);
238     dhcpm->options[pointer++] = ((dhcpl.siaddr >> 16) & 0xFF);
239     dhcpm->options[pointer++] = (dhcpl.siaddr >> 24);
240     dhcpm->options[pointer++] = LEASE;
241     dhcpm->options[pointer++] = 4;
242     dhcpm->options[pointer++] = (dhcpl.lease >> 24);
243     dhcpm->options[pointer++] = ((dhcpl.lease >> 16) & 0xFF);
244     dhcpm->options[pointer++] = ((dhcpl.lease >> 8) & 0xFF);
245     dhcpm->options[pointer++] = (dhcpl.lease & 0xFF);
246     dhcpm->options[pointer++] = REBINDING;
247     dhcpm->options[pointer++] = 4;
248     dhcpm->options[pointer++] = (dhcpl.lease >> 24);
249     dhcpm->options[pointer++] = ((dhcpl.lease >> 16) & 0xFF);
250     dhcpm->options[pointer++] = ((dhcpl.lease >> 8) & 0xFF);
251     dhcpm->options[pointer++] = (dhcpl.lease & 0xFF) - 5;
252     dhcpm->options[pointer++] = RENEWALTIME;
253     dhcpm->options[pointer++] = 4;
254     dhcpm->options[pointer++] = (dhcpl.lease >> 24);
255     dhcpm->options[pointer++] = ((dhcpl.lease >> 16) & 0xFF);
256     dhcpm->options[pointer++] = ((dhcpl.lease >> 8) & 0xFF);
257     dhcpm->options[pointer++] = (dhcpl.lease & 0xFF) - 5;
258     dhcpm->options[pointer++] = PAD;
259     dhcpm->options[pointer++] = PAD;
260     dhcpm->options[pointer++] = PAD;
261     dhcpm->options[pointer++] = END;
262     for( ; pointer < 312; pointer++ )
263       dhcpm->options[pointer] = PAD;
264     dhcpo->type = DHCPOFFER;
265     strcpy( name, "255.255.255.255" );
266     break;
267 
268   case DHCPREQUEST:
269     /* We need to send an DHCPACK */
270     dhcpm->op = BOOTREPLY;
271     dhcpm->yiaddr = dhcpm->ciaddr;
272     strcpy(dhcpm->sname, VERSION);
273     if( confirm_lease( &dhcpl, dhcpm->xid ) < 0)
274       {
275 	dhcpm->options[pointer++] = MESSAGETYPE;
276 	dhcpm->options[pointer++] = 1;
277 	dhcpm->options[pointer++] = DHCPNAK;
278 	dhcpm->options[pointer++] = PAD;
279 	dhcpm->options[pointer++] = END;
280 	for( ; pointer < 312; pointer++ )
281 	  dhcpm->options[pointer] = PAD;
282 	sprintf( name, "%u.%u.%u.%u", (dhcpm->ciaddr &0xFF), ((dhcpm->ciaddr>>8)&0xFF), ((dhcpm->ciaddr>>16)&0xFF), ((dhcpm->ciaddr>>24)&0xFF));
283 	display_dhcp_packet( dhcpm, dhcpo );
284 	write_packet( dhcpm, name );
285 	free( name );
286 	return -1;
287       }
288     dhcpm->siaddr = dhcpl.siaddr;
289     dhcpm->options[pointer++] = MESSAGETYPE;
290     dhcpm->options[pointer++] = 1;
291     dhcpm->options[pointer++] = DHCPACK;
292     dhcpm->options[pointer++] = ROUTER;
293     dhcpm->options[pointer++] = 4;
294     dhcpm->options[pointer++] = (dhcpl.router >> 24);
295     dhcpm->options[pointer++] = ((dhcpl.router >> 16) & 0xFF);
296     dhcpm->options[pointer++] = ((dhcpl.router >> 8) &0xFF);
297     dhcpm->options[pointer++] = (dhcpl.router & 0xFF);
298     dhcpm->options[pointer++] = MASK;
299     dhcpm->options[pointer++] = 4;
300     dhcpm->options[pointer++] = (dhcpl.mask >> 24);
301     dhcpm->options[pointer++] = ((dhcpl.mask >> 16) & 0xFF);
302     dhcpm->options[pointer++] = ((dhcpl.mask >> 8) & 0xFF);
303     dhcpm->options[pointer++] = (dhcpl.mask & 0xFF);
304     dhcpm->options[pointer++] = SERVER;
305     dhcpm->options[pointer++] = 4;
306     dhcpm->options[pointer++] = dhcpl.siaddr >> 24;
307     dhcpm->options[pointer++] = ((dhcpl.siaddr >> 16) & 0xFF);
308     dhcpm->options[pointer++] = ((dhcpl.siaddr >> 8) & 0xFF);
309     dhcpm->options[pointer++] = (dhcpl.siaddr & 0xFF);
310     dhcpm->options[pointer++] = LEASE;
311     dhcpm->options[pointer++] = 4;
312     dhcpm->options[pointer++] = (dhcpl.lease >> 24);
313     dhcpm->options[pointer++] = ((dhcpl.lease >> 16) & 0xFF);
314     dhcpm->options[pointer++] = ((dhcpl.lease >> 8) & 0xFF);
315     dhcpm->options[pointer++] = (dhcpl.lease & 0xFF);
316     dhcpm->options[pointer++] = REBINDING;
317     dhcpm->options[pointer++] = 4;
318     dhcpm->options[pointer++] = (dhcpl.lease >> 24);
319     dhcpm->options[pointer++] = ((dhcpl.lease >> 16) & 0xFF);
320     dhcpm->options[pointer++] = ((dhcpl.lease >> 8) & 0xFF);
321     dhcpm->options[pointer++] = (dhcpl.lease & 0xFF);
322     dhcpm->options[pointer++] = RENEWALTIME;
323     dhcpm->options[pointer++] = 4;
324     dhcpm->options[pointer++] = (dhcpl.lease >> 24);
325     dhcpm->options[pointer++] = ((dhcpl.lease >> 16) & 0xFF);
326     dhcpm->options[pointer++] = ((dhcpl.lease >> 8) & 0xFF);
327     dhcpm->options[pointer++] = (dhcpl.lease & 0xFF);
328     dhcpm->options[pointer++] = PAD;
329     dhcpm->options[pointer++] = PAD;
330     dhcpm->options[pointer++] = PAD;
331     dhcpm->options[pointer++] = END;
332     for( ; pointer < 312; pointer++ )
333       dhcpm->options[pointer] = PAD;
334     dhcpo->type = DHCPACK;
335     sprintf( name, "%u.%u.%u.%u", (dhcpl.ip & 0xFF), ((dhcpl.ip>>8) & 0xFF), ((dhcpl.ip>>16)&0xFF), (dhcpl.ip>>24));
336     break;
337 
338   default:
339     break;
340   }
341   display_dhcp_packet( dhcpm, dhcpo );
342   write_packet( dhcpm, name );
343   fprintf( stdout, "process_dhcp_packet [end]!\n");
344   free( name );
345   return 0;
346 }
347 
348 int write_packet( DHCPMESSAGE *dhcpm, char *name )
349 {
350   int sockfd;
351   struct sockaddr_in their_addr; // connector's address information
352   struct hostent *he;
353   int numbytes;
354   int enable = 1;
355 
356   fprintf( stdout, "write_packet [begin]\n" );
357 
358   if( !dhcpm )
359     return -1;
360 
361   if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
362     perror("socket");
363     exit(1);
364   }
365 
366   if( setsockopt( sockfd, SOL_SOCKET, SO_BROADCAST, &enable, sizeof( enable )) == -1 )
367     {
368       perror("setsockopt");
369       exit(1);
370     }
371 
372   if( strcmp( "255.255.255.255", name ) )
373     {
374       if ((he=gethostbyname(name)) == NULL) {  // get the host info
375 	perror("gethostbyname");
376 	fprintf( stdout, "Unknown host %s \n", name );
377 	return -1;
378       }
379       their_addr.sin_family = AF_INET;     // host byte order
380       their_addr.sin_port = htons(68); // short, network byte order
381       their_addr.sin_addr = *((struct in_addr *)he->h_addr);
382     } else {
383       their_addr.sin_family = AF_INET;     // host byte order
384       their_addr.sin_port = htons(68); // short, network byte order
385       their_addr.sin_addr.s_addr = 0xFFFFFFFF;
386     }
387 
388   fprintf( stdout, "IP a buscar: %s \n", name );
389   memset(&(their_addr.sin_zero), '\0', 8); // zero the rest of the struct
390 
391   if ((numbytes=sendto(sockfd, dhcpm, sizeof(DHCPMESSAGE), 0,
392 		       (struct sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1) {
393     perror("sendto");
394     exit(1);
395   }
396 
397   printf("sent %d bytes to %s\n", numbytes,
398 	 inet_ntoa(their_addr.sin_addr));
399 
400   close(sockfd);
401 
402   fprintf( stdout, "write_packet [end]\n" );
403 
404   return 0;
405 }
406