[DHCPD]
[reactos.git] / rosapps / applications / net / dhcpd / src / parsing / parser.c
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 }