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