1/* 2 * Copyright (C) NEC Europe Ltd., 2003 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the project nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#include <stdlib.h> 31#include <string.h> 32#include <sys/types.h> 33#include <sys/socket.h> 34#include <arpa/inet.h> 35 36#include "relay6_database.h" 37 38void 39init_relay(void) 40{ 41 nr_of_uni_addr = 0; 42 multicast_off = 0; 43 nr_of_devices = 0; 44 max_count = 0; 45 46 cifaces_list.next = &cifaces_list; 47 48 sifaces_list.next = &sifaces_list; 49 50 server_list.next = &server_list; 51 52 IPv6_address_list.next = &IPv6_address_list; 53 54 IPv6_uniaddr_list.next = &IPv6_uniaddr_list; 55 56 interface_list.prev = &interface_list; 57 interface_list.next = &interface_list; 58 59 msg_parser_list.prev = &msg_parser_list; 60 msg_parser_list.next = &msg_parser_list; 61} 62 63int 64check_interface_semafor(int index) 65{ 66 struct interface *device = NULL; 67 struct cifaces *iface; 68 69 device = get_interface(index); 70 if (device == NULL) { 71 printf("FATAL ERROR IN CheckInterfaceSemafor()\n"); 72 exit(1); 73 } 74 75 if (cifaces_list.next == &cifaces_list) 76 return 1; 77 78 for (iface = cifaces_list.next; iface != &cifaces_list; 79 iface = iface->next) { 80 if (strcmp(device->ifname, iface->ciface) == 0) 81 return 1; 82 } 83 84 return 0; 85} 86 87struct interface *get_interface(int if_index) 88{ 89 struct interface *deviface; 90 91 for (deviface = interface_list.next; deviface != &interface_list; 92 deviface = deviface->next) { 93 if (deviface->devindex == if_index) 94 return deviface; 95 } 96 97 return NULL; 98} 99 100struct interface *get_interface_s(char *s) 101{ 102 struct interface *deviface; 103 104 for (deviface = interface_list.next; deviface != &interface_list; 105 deviface = deviface->next) { 106 if (strcmp(s, deviface->ifname)== 0) 107 return deviface; 108 } 109 110 return NULL; 111} 112 113struct msg_parser *get_send_messages_out(void) 114{ 115 struct msg_parser *msg; 116 117 for (msg = msg_parser_list.next; msg != &msg_parser_list; msg = msg->next) { 118 if (msg->sent == 0) 119 return msg; 120 } 121 122 return NULL; 123} 124 125 126void delete_messages(void) 127{ 128 struct msg_parser *msg; 129 130 for (msg = msg_parser_list.next; msg != &msg_parser_list; msg = msg->next) { 131 if (msg->sent == 1) { 132 msg->prev->next = msg->next; 133 msg->next->prev = msg->prev; 134 msg->next = NULL; 135 msg->prev = NULL; 136 free(msg->buffer); 137 free(msg); 138 msg = msg_parser_list.next; 139 } 140 } 141} 142 143 144int 145process_RELAY_FORW(struct msg_parser *msg) 146{ 147 uint8_t *head = (uint8_t *) malloc(HEAD_SIZE*sizeof(uint8_t)); 148 uint8_t *newbuff = (uint8_t *) malloc(MAX_DHCP_MSG_LENGTH*sizeof(uint8_t)); 149 uint8_t *pointer; 150 struct interface *device = NULL; 151 struct sockaddr_in6 sap; 152 int check = 0; 153 uint16_t *p16, *optl; 154 uint32_t *p32; 155 int len, hop; 156 157 if ((head == NULL) || (newbuff == NULL)) { 158 printf("ProcessRELAYFORW--> ERROR, NO MORE MEMRY AVAILABLE \n"); 159 exit(1); 160 } 161 162 memset(head, 0, HEAD_SIZE); 163 164 pointer = head; 165 166 167 if (msg->isRF == 1) { /* got message from a relay agent to be relayed */ 168 (*pointer) = RELAY_FORW; 169 pointer += 1; 170 (*pointer) = msg->hop_count + 1; /* increased hop-count */ 171 msg->hc_pointer = pointer; 172 173 if (max_count == 1) { 174 (*pointer) = MAXHOPCOUNT; 175 hop = (int) (*pointer); 176 TRACE(dump, "%s - %s%d\n", dhcp6r_clock(), "HOPCOUNT: ", hop); 177 } 178 179 pointer += 1; 180 181 } 182 else { /*got message from a client to be relayed */ 183 (*pointer) = RELAY_FORW; 184 pointer += 1; 185 (*pointer) = 0; /* hop-count */ 186 msg->hc_pointer = pointer; 187 188 if (max_count == 1) { 189 (*pointer) = MAXHOPCOUNT; 190 hop = (int) (*pointer); 191 TRACE(dump, "%s - %s%d\n", dhcp6r_clock(), "HOPCOUNT: ", hop); 192 } 193 pointer += 1; 194 } 195 196 msg->msg_type = RELAY_FORW; 197 198 device = get_interface(msg->interface_in); 199 if (device == NULL) { 200 printf("ProcessRELAYFORW--->ERROR NO INTERFACE FOUND!\n"); 201 exit(1); 202 } 203 204 /* fill in link-address */ 205 206 if (inet_pton(AF_INET6, msg->src_addr , &sap.sin6_addr) <= 0) { 207 printf("ProcessRELAYFORW1--->ERROR IN inet_pton !\n"); 208 exit(1); 209 } 210 211 if ((!IN6_IS_ADDR_LINKLOCAL(&sap.sin6_addr)) && (nr_of_devices == 1 )) { 212 memset(&sap.sin6_addr, 0, sizeof(sap.sin6_addr)); 213 memcpy(pointer, &sap.sin6_addr, INET6_LEN); 214 pointer += INET6_LEN; 215 } 216 else { 217 check = 0; 218 219 memset(&sap.sin6_addr, 0, sizeof(sap.sin6_addr)); 220 221 if (inet_pton(AF_INET6, device->ipv6addr->gaddr, &sap.sin6_addr) <= 0) { 222 printf("ProcessRELAYFORW1--->ERROR IN inet_pton !\n"); 223 exit(1); 224 } 225 226 memcpy(pointer, &sap.sin6_addr, INET6_LEN); 227 pointer += INET6_LEN; 228 } 229 230 231 /* fill in peer-addrees */ 232 memset(&sap.sin6_addr, 0, sizeof(sap.sin6_addr)); 233 234 if (inet_pton(AF_INET6, msg->src_addr , &sap.sin6_addr) <= 0) { 235 printf("ProcessRELAYFORW--->ERROR2 IN inet_pton !\n"); 236 exit(1); 237 } 238 239 memcpy(pointer, &sap.sin6_addr, INET6_LEN); 240 pointer += INET6_LEN; 241 242 /* Insert Interface_ID option to identify the interface */ 243 p16 = (uint16_t *) pointer; 244 *p16 = htons(OPTION_INTERFACE_ID); 245 pointer += 2; 246 p16 = (uint16_t *) pointer; 247 *p16 = htons(4); /* 4 octeti length */ 248 pointer += 2; 249 p32 = (uint32_t *) pointer; 250 *p32 = htonl(device->opaq); 251 pointer += 4; 252 253 p16 = (uint16_t *) pointer; 254 *p16 = htons(OPTION_RELAY_MSG); 255 pointer += 2; 256 optl = (uint16_t *) pointer; 257 pointer += 2; 258 *optl = htons(msg->datalength); 259 260 len = (pointer - head); 261 TRACE(dump, "%s - %s%d\n", dhcp6r_clock(), "RELAY_FORW HEADERLENGTH: ", 262 len); 263 TRACE(dump, "%s - %s%d\n", dhcp6r_clock(), "ORIGINAL MESSAGE LENGTH: ", 264 msg->datalength ); 265 266 if ((len+ msg->datalength) > MAX_DHCP_MSG_LENGTH) { 267 printf(" ERROR FRAGMENTATION WILL OCCUR IF SENT, DROP THE PACKET" 268 "......\n"); 269 return 0; 270 } 271 272 pointer = newbuff; 273 memset(pointer, 0, MAX_DHCP_MSG_LENGTH); 274 memcpy(pointer, head, len); 275 pointer += len; 276 memcpy(pointer, msg->buffer, msg->datalength); 277 msg->datalength += len; /* final length for sending */ 278 free(msg->buffer); 279 free(head); 280 msg->buffer = newbuff; 281 282 return 1; 283} 284 285int 286process_RELAY_REPL(struct msg_parser *msg) 287{ 288 uint8_t *newbuff = (uint8_t *) malloc(MAX_DHCP_MSG_LENGTH*sizeof(uint8_t)); 289 uint8_t *pointer, *pstart, *psp; 290 struct interface *device = NULL; 291 struct sockaddr_in6 sap; 292 int check = 0; 293 uint16_t *p16, option, opaqlen, msglen; 294 uint32_t *p32; 295 int len, opaq; 296 struct IPv6_address *ipv6a; 297 char *s; 298 299 if (newbuff == NULL) { 300 printf("ProcessRELAYREPL--> ERROR, NO MORE MEMRY AVAILABLE \n"); 301 exit(1); 302 } 303 304 pointer = msg->buffer; 305 pstart = pointer; 306 307 if (( ((int) msg->buffer) - ((int) (pointer - pstart)) ) < 308 MESSAGE_HEADER_LENGTH ) { 309 printf("ProcessRELAYREPL()--> opt_length has 0 value for " 310 "MESSAGE_HEADER_LENGTH, DROPING... \n"); 311 return 0; 312 } 313 314 if (*pointer != RELAY_REPL) 315 return 0; 316 317 pointer += 1; /* RELAY_FORW */ 318 msg->hop = *pointer; 319 pointer += 1; /* hop-count */ 320 msg->msg_type = RELAY_REPL; 321 322 if (( ((int) msg->buffer) - ((int) (pointer - pstart)) ) < (2*INET6_LEN) ) { 323 printf("ProcessRELAYREPL()--> opt_length has 0 value for " 324 "INET6_LEN, DROPING... \n"); 325 return 0; 326 } 327 328 /* extract link_address */ 329 memset(msg->link_addr, 0, INET6_ADDRSTRLEN); 330 memset(&sap.sin6_addr, 0, sizeof(sap.sin6_addr)); 331 memcpy(&sap.sin6_addr, pointer, INET6_LEN); 332 pointer += INET6_LEN; 333 334 if (inet_ntop(AF_INET6, &sap.sin6_addr, msg->link_addr, 335 INET6_ADDRSTRLEN ) <=0 ) { 336 printf("ProcessRELAYREPL1--->ERROR IN inet_ntop !\n"); 337 exit(1); 338 } 339 340 /* extract peer address */ 341 memset(msg->peer_addr, 0, INET6_ADDRSTRLEN); 342 memset(&sap.sin6_addr, 0, sizeof(sap.sin6_addr)); 343 memcpy(&sap.sin6_addr, pointer, INET6_LEN); 344 pointer += INET6_LEN; 345 346 if (inet_ntop(AF_INET6, &sap.sin6_addr, msg->peer_addr, 347 INET6_ADDRSTRLEN ) <=0 ) { 348 printf("ProcessRELAYREPL1--->ERROR IN inet_ntop !\n"); 349 exit(1); 350 } 351 352 if (( ((int) msg->buffer) - ((int) (pointer - pstart)) ) < 353 MESSAGE_HEADER_LENGTH ) { 354 printf("ProcessRELAYREPL()--> opt_length has 0 value for " 355 "MESSAGE_HEADER_LENGTH, DROPING... \n"); 356 return 0; 357 } 358 359 p16 = (uint16_t *) pointer; 360 option = ntohs(*p16); 361 362 if (option == OPTION_INTERFACE_ID) { 363 pointer += 2; 364 p16 = (uint16_t *) pointer; 365 opaqlen = ntohs(*p16); 366 pointer += 2; 367 368 if (( ((int) msg->buffer) - ((int) (pointer - pstart)) ) < opaqlen) { 369 printf("ProcessRELAYREPL()--> opt_length has 0 value for " 370 "opaqlen, DROPING... \n"); 371 return 0; 372 } 373 374 p32 = (uint32_t *) pointer; 375 opaq = ntohl(*p32); 376 pointer += opaqlen; 377 378 if (( ((int) msg->buffer) - ((int) (pointer - pstart)) ) < 379 MESSAGE_HEADER_LENGTH ) { 380 printf("ProcessRELAYREPL()--> opt_length has 0 value for " 381 "MESSAGE_HEADER_LENGTH, DROPING... \n"); 382 return 0; 383 } 384 385 p16 = (uint16_t *) pointer; 386 option = ntohs(*p16); 387 388 if (option == OPTION_RELAY_MSG) { 389 pointer += 2; 390 p16 = (uint16_t *) pointer; 391 msglen = ntohs(*p16); 392 pointer += 2; 393 if (( ((int) msg->buffer) - ((int)(pointer - pstart)) ) < msglen ) { 394 printf("ProcessRELAYREPL()--> opt_length has 0 value for " 395 "msglen, DROPING... \n"); 396 return 0; 397 } 398 399 /*--------------------------*/ 400 if (*pointer == RELAY_FORW) 401 *pointer = RELAY_REPL; /* is the job of the server to set to 402 RELAY_REPL? */ 403 /*--------------------------*/ 404 for (device = interface_list.next; device != &interface_list; 405 device = device->next) { 406 if (device->opaq == opaq) 407 break; 408 } 409 410 if (device != &interface_list ) { 411 msg->if_index = device->devindex; 412 memset(newbuff, 0, MAX_DHCP_MSG_LENGTH); 413 len = (pointer - msg->buffer); 414 len = (msg->datalength - len); 415 memcpy(newbuff, pointer, len); 416 msg->datalength = len; 417 free(msg->buffer); 418 msg->buffer = newbuff; 419 return 1; 420 421 } 422 else { 423 s = msg->link_addr; 424 425 for (device = interface_list.next; device != &interface_list; 426 device = device->next) { 427 ipv6a = device->ipv6addr; 428 429 while(ipv6a!= NULL) { 430 if (strcmp(s, ipv6a->gaddr) == 0) { 431 msg->if_index = device->devindex; 432 check = 1; 433 break; 434 } 435 ipv6a = ipv6a->next; 436 } 437 438 if (check == 1) 439 break; 440 } 441 442 if (check == 0) { 443 printf("ProcessRELAYREPL--->ERROR NO INTERFACE FOUND!\n"); 444 return 0; 445 } 446 447 memset(newbuff, 0, MAX_DHCP_MSG_LENGTH); 448 len = (pointer - msg->buffer); 449 len = (msg->datalength - len); 450 memcpy(newbuff, pointer, len); 451 msg->datalength = len; 452 free(msg->buffer); 453 msg->buffer = newbuff; 454 return 1; 455 } 456 } 457 else { /* OPTION_RELAY_MSG */ 458 printf("ProcessRELAYREPL--->ERROR MESSAGE IS MALFORMED NO " 459 "OPTION_RELAY_MSG FOUND, DROPING...!\n"); 460 return 0; 461 } 462 } /* OPTION_INTERFACE_ID */ 463 464 if (option == OPTION_RELAY_MSG) { 465 pointer += 2; 466 p16 = (uint16_t *) pointer; 467 msglen = ntohs(*p16); 468 pointer += 2; 469 470 if (( ((int) msg->buffer) - ((int) (pointer - pstart)) ) < msglen ) { 471 printf("ProcessRELAYREPL()--> opt_length has 0 value for " 472 "msglen, DROPING... \n"); 473 return 0; 474 } 475 476 opaq = 0; 477 psp = (pointer + msglen); /* jump over message, seek for 478 OPTION_INTERFACE_ID */ 479 480 if (( ((int) msg->buffer) - ((int) (psp - pstart)) ) >= 481 MESSAGE_HEADER_LENGTH ) { 482 if (option == OPTION_INTERFACE_ID) { 483 psp += 2; 484 p16 = (uint16_t *) psp; 485 opaqlen = ntohs(*p16); 486 psp += 2; 487 488 if (( ((int) msg->buffer) - ((int) (psp - pstart)) ) < 489 opaqlen) { 490 printf("ProcessRELAYREPL()--> opt_length has 0 value " 491 "for opaqlen, DROPING... \n"); 492 return 0; 493 } 494 495 p32 = (uint32_t *) psp; 496 opaq = ntohl(*p32); 497 psp += opaqlen; 498 } 499 } 500 501 /*--------------------------*/ 502 if (*pointer == RELAY_FORW) 503 *pointer = RELAY_REPL; /* is the job of the server to set to 504 RELAY_REPL? */ 505 /*--------------------------*/ 506 for (device = interface_list.next; device != &interface_list; 507 device = device->next) { 508 if (device->opaq == opaq) 509 break; 510 } 511 512 if (device != &interface_list) { 513 msg->if_index = device->devindex; 514 memset(newbuff, 0, MAX_DHCP_MSG_LENGTH); 515 len = (pointer - msg->buffer); 516 len = (msg->datalength - len); 517 memcpy(newbuff, pointer, len); 518 msg->datalength = len; 519 free(msg->buffer); 520 msg->buffer = newbuff; 521 return 1; 522 } 523 else { 524 s = msg->link_addr; 525 526 for (device = interface_list.next; device != &interface_list; 527 device = device->next) { 528 ipv6a = device->ipv6addr; 529 530 while(ipv6a != NULL) { 531 if (strcmp(s, ipv6a->gaddr) == 0) { 532 msg->if_index = device->devindex; 533 check = 1; 534 break; 535 } 536 ipv6a = ipv6a->next; 537 } 538 539 if (check == 1) 540 break; 541 } 542 543 if (check == 0) { 544 printf("ProcessRELAYREPL--->ERROR NO INTERFACE FOUND!\n"); 545 return 0; 546 } 547 548 memset(newbuff, 0, MAX_DHCP_MSG_LENGTH); 549 len = (pointer - msg->buffer); 550 len = (msg->datalength - len); 551 memcpy(newbuff, pointer, len); 552 msg->datalength = len; 553 free(msg->buffer); 554 msg->buffer = newbuff; 555 return 1; 556 } 557 } 558 else { /* OPTION_RELAY_MSG */ 559 printf("ProcessRELAYREPL--->ERROR MESSAGE IS MALFORMED NO " 560 "OPTION_RELAY_MSG FOUND, DROPING...!\n"); 561 return 0; 562 } 563 564 return 1; 565} 566