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 <arpa/inet.h> 33#include <net/if.h> 34 35#include "relay6_socket.h" 36#include "relay6_database.h" 37 38void 39init_socket() 40{ 41 recvsock = (struct receive *) malloc(sizeof(struct receive)); 42 sendsock = (struct send *) malloc(sizeof(struct send)); 43 44 if ((recvsock == NULL) || (sendsock == NULL)) { 45 TRACE(dump, "%s - %s", dhcp6r_clock(), 46 "init_socket--> ERROR NO MORE MEMORY AVAILABLE\n"); 47 exit(1); 48 } 49 50 memset(recvsock, 0, sizeof(struct receive)); 51 memset(sendsock, 0, sizeof(struct send)); 52 53 recvsock->databuf = (char *) malloc(MAX_DHCP_MSG_LENGTH*sizeof(char)); 54 if (recvsock->databuf == NULL) { 55 TRACE(dump, "%s - %s", dhcp6r_clock(), 56 "init_socket--> ERROR NO MORE MEMORY AVAILABLE\n"); 57 exit(1); 58 } 59 60 if ((recvsock->recv_sock_desc = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 61 printf("Failed to get new socket with socket()\n"); 62 exit(0); 63 } 64 65 if ((sendsock->send_sock_desc = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 66 printf("Failed to get new socket with socket()\n"); 67 exit(0); 68 } 69} 70 71int 72get_recv_data() 73{ 74 struct cmsghdr *cm; 75 struct in6_pktinfo *pi; 76 struct sockaddr_in6 dst; 77 78 memset(recvsock->src_addr, 0, sizeof(recvsock->src_addr)); 79 80 for(cm = (struct cmsghdr *) CMSG_FIRSTHDR(&recvsock->msg); cm; 81 cm = (struct cmsghdr *) CMSG_NXTHDR(&recvsock->msg, cm)) { 82 if ((cm->cmsg_level == IPPROTO_IPV6) && (cm->cmsg_type == IPV6_PKTINFO) 83 && (cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo)))) { 84 pi = (struct in6_pktinfo *)(CMSG_DATA(cm)); 85 dst.sin6_addr = pi->ipi6_addr; 86 recvsock->pkt_interface = pi->ipi6_ifindex; /* the interface index 87 the packet got in */ 88 89 if (IN6_IS_ADDR_LOOPBACK(&recvsock->from.sin6_addr)) { 90 TRACE(dump, "%s - %s", dhcp6r_clock(), 91 "get_recv_data()-->SOURCE ADDRESS IS LOOPBACK!\n"); 92 return 0; 93 } 94 95 if (inet_ntop(AF_INET6, &recvsock->from.sin6_addr, 96 recvsock->src_addr, INET6_ADDRSTRLEN) <= 0) { 97 TRACE(dump, "%s - %s", dhcp6r_clock(), 98 "inet_ntop failed in get_recv_data()\n"); 99 return 0; 100 } 101 102 if (IN6_IS_ADDR_LOOPBACK(&dst.sin6_addr)) { 103 recvsock->dst_addr_type = 1; 104 } 105 else if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr)) { 106 recvsock->dst_addr_type = 2; 107 if (multicast_off == 1) { 108 TRACE(dump, "%s - %s", dhcp6r_clock(), 109 "RECEIVED MULTICAST PACKET IS DROPPED, ONLY UNICAST " 110 "IS ALLOWED!\n"); 111 return 0; 112 } 113 } 114 else if (IN6_IS_ADDR_LINKLOCAL(&dst.sin6_addr)) { 115 recvsock->dst_addr_type = 3; 116 } 117 else if (IN6_IS_ADDR_SITELOCAL(&dst.sin6_addr)) 118 recvsock->dst_addr_type = 4; 119 120 return 1; 121 } 122 } /* for */ 123 124 return 0; 125} 126 127int 128check_select(void) 129{ 130 int i = 0; 131 int flag = 0; 132 struct timeval tv; 133 134 tv.tv_sec = 0; 135 tv.tv_usec = 0; 136 137 FD_ZERO(&readfd); 138 fdmax = recvsock->recv_sock_desc; /* check the max of them if many 139 desc used */ 140 FD_SET(fdmax, &readfd); 141 142 if ((i = select(fdmax+1, &readfd, NULL, NULL, &tv)) == -1) { 143 TRACE(dump, "%s - %s", dhcp6r_clock(), "Failure in select()\n"); 144 return 0; 145 } 146 147 if (FD_ISSET(fdmax, &readfd)) { 148 flag = 1; 149 } 150 else{ 151 flag = 0; 152 } 153 154 return flag; 155} 156 157int 158set_sock_opt() 159{ 160 int on = 1; 161 struct interface *device; 162 int flag; 163 struct cifaces *iface; 164 struct ipv6_mreq sock_opt; 165 166 if (setsockopt(recvsock->recv_sock_desc, IPPROTO_IPV6, IPV6_PKTINFO, 167 &on, sizeof(on) ) < 0) { 168 TRACE(dump, "%s - %s", dhcp6r_clock(), 169 "Failed to set socket for IPV6_PKTINFO\n"); 170 return 0; 171 } 172 173 for (device = interface_list.next; device != &interface_list; 174 device = device->next) { 175 if (cifaces_list.next != &cifaces_list) { 176 flag = 0; 177 for (iface = cifaces_list.next; iface != &cifaces_list; 178 iface = iface->next) { 179 if (strcmp(device->ifname, iface->ciface) == 0) { 180 flag = 1; 181 break; 182 } 183 } 184 if (flag == 0) 185 continue; 186 } 187 188 sock_opt.ipv6mr_interface = device->devindex; 189 190 if (inet_pton(AF_INET6, ALL_DHCP_RELAY_AND_SERVERS, 191 &sock_opt.ipv6mr_multiaddr) <= 0) { 192 TRACE(dump, "%s - %s", dhcp6r_clock(), 193 "Failed to set struct for MULTICAST receive\n"); 194 return 0; 195 } 196 197 if (setsockopt(recvsock->recv_sock_desc, IPPROTO_IPV6, IPV6_JOIN_GROUP, 198 (char *) &sock_opt, sizeof(sock_opt)) < 0) { 199 TRACE(dump, "%s - %s", dhcp6r_clock(), 200 "Failed to set socket option for IPV6_JOIN_GROUP \n"); 201 return 0; 202 } 203 } 204 205 TRACE(dump, "%s - %s", dhcp6r_clock(), 206 "SOCKET OPTIONS ARE SET............\n"); 207 fflush(dump); 208 return 1; 209} 210 211 212int 213fill_addr_struct() 214{ 215 bzero((char *)&recvsock->from, sizeof(struct sockaddr_in6)); 216 recvsock->from.sin6_family = AF_INET6; 217 recvsock->from.sin6_addr = in6addr_any; 218 recvsock->from.sin6_port = htons(547); 219 220 recvsock->iov[0].iov_base = recvsock->databuf; 221 recvsock->iov[0].iov_len = MAX_DHCP_MSG_LENGTH; 222 recvsock->msg.msg_name = (void *) &recvsock->from; 223 recvsock->msg.msg_namelen = sizeof(recvsock->from); 224 recvsock->msg.msg_iov = &recvsock->iov[0]; 225 recvsock->msg.msg_iovlen = 1; 226 227 recvsock->recvmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)); 228 recvsock->recvp = (char *) malloc(recvsock->recvmsglen*sizeof(char)); 229 recvsock->msg.msg_control = (void *) recvsock->recvp; 230 recvsock->msg.msg_controllen = recvsock->recvmsglen; 231 232 if (bind(recvsock->recv_sock_desc, (struct sockaddr *)&recvsock->from, 233 sizeof(recvsock->from)) < 0) { 234 perror("bind"); 235 return 0; 236 } 237 238 return 1; 239} 240 241int 242recv_data() 243{ 244 int count = -1; 245 246 memset(recvsock->databuf, 0, (MAX_DHCP_MSG_LENGTH*sizeof(char))); 247 248 if ((count = recvmsg(recvsock->recv_sock_desc, &recvsock->msg, 0)) < 0) { 249 TRACE(dump, "%s - %s", dhcp6r_clock(), 250 "Failed to receive data with recvmsg()-->Receive::recv_data()\n"); 251 return -1; 252 } 253 254 recvsock->buflength = count; 255 256 return 1; 257} 258 259int 260get_interface_info() 261{ 262 FILE *f; 263 char addr6[40], devname[20]; 264 struct sockaddr_in6 sap; 265 int plen, scope, dad_status, if_idx; 266 char addr6p[8][5]; 267 char src_addr[INET6_ADDRSTRLEN]; 268 struct interface *device = NULL; 269 int opaq = OPAQ; 270 int sw = 0; 271 struct IPv6_address *ipv6addr; 272 273 if ((f = fopen(INTERFACEINFO, "r")) == NULL) { 274 printf("FATAL ERROR-->COULD NOT OPEN FILE: %s\n", INTERFACEINFO); 275 return 0; 276 } 277 278 while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n", 279 addr6p[0], addr6p[1], addr6p[2], addr6p[3],addr6p[4], 280 addr6p[5], addr6p[6], addr6p[7], &if_idx, &plen, &scope, 281 &dad_status, devname) != EOF) { 282 memset(src_addr, 0, INET6_ADDRSTRLEN); 283 sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s", addr6p[0], addr6p[1], 284 addr6p[2], addr6p[3],addr6p[4], addr6p[5], addr6p[6], 285 addr6p[7]); 286 sap.sin6_family = AF_INET6; 287 sap.sin6_port = 0; 288 289 if (inet_pton(AF_INET6, addr6, sap.sin6_addr.s6_addr) <= 0) 290 return 0; 291 292 if (inet_ntop(AF_INET6, &sap.sin6_addr, src_addr, sizeof(src_addr)) <= 293 0) 294 return 0; 295 296 if (IN6_IS_ADDR_LOOPBACK(&sap.sin6_addr)) 297 continue; 298 299 sw = 0; 300 for (device = interface_list.next; device != &interface_list; 301 device = device->next) { 302 if (device->devindex == if_idx) { 303 sw = 1; 304 break; 305 } 306 } 307 308 if (sw == 0) { 309 opaq += 10; 310 device = (struct interface *) malloc(sizeof(struct interface)); 311 if (device ==NULL) { 312 TRACE(dump, "%s - %s", dhcp6r_clock(), 313 "get_interface_info()--> " 314 "ERROR NO MORE MEMORY AVAILABLE\n"); 315 exit(1); 316 } 317 device->opaq = opaq; 318 device->ifname = strdup(devname); 319 device->devindex = if_idx; 320 device->ipv6addr = NULL; 321 device->prev = &interface_list; 322 device->next = interface_list.next; 323 device->prev->next = device; 324 device->next->prev = device; 325 nr_of_devices += 1; 326 } 327 328 if (IN6_IS_ADDR_LINKLOCAL(&sap.sin6_addr)) { 329 device->link_local = strdup(src_addr); 330 TRACE(dump,"%s %s %s %d %s %s\n",\ 331 "RELAY INTERFACE INFO-> DEVNAME:", devname, "INDEX:", if_idx, 332 "LINK_LOCAL_ADDRR:", src_addr); 333 } 334 else { 335 ipv6addr = (struct IPv6_address *) 336 malloc(sizeof(struct IPv6_address)); 337 if (ipv6addr ==NULL) { 338 TRACE(dump, "%s - %s", dhcp6r_clock(), 339 "get_interface_info()--> " 340 "ERROR NO MORE MEMORY AVAILABLE\n"); 341 exit(1); 342 } 343 ipv6addr->gaddr = strdup(src_addr); 344 ipv6addr->next = NULL; 345 if (device->ipv6addr!= NULL) 346 ipv6addr->next = device->ipv6addr; 347 348 device->ipv6addr = ipv6addr; 349 } 350 } /* while */ 351 352 fflush(dump); 353 for (device = interface_list.next; device != &interface_list; 354 device = device->next) { 355 if ( device->ipv6addr == NULL) { 356 TRACE(dump,"%s - ERROR--> ONE MUST ASSIGN SITE SCOPED IPv6 " 357 "ADDRESS FOR INTERFACE: %s\n", dhcp6r_clock(), 358 device->ifname); 359 exit(1); 360 } 361 } 362 363 fclose(f); 364 return 1; 365} 366 367int 368send_message() 369{ 370 struct sockaddr_in6 sin6; /* my address information */ 371 struct msghdr msg; 372 uint32_t count = 0; 373 struct msg_parser *mesg; 374 struct in6_pktinfo *in6_pkt; 375 struct cmsghdr *cmsgp; 376 char dest_addr[INET6_ADDRSTRLEN]; 377 struct IPv6_uniaddr *ipv6uni; 378 struct interface *iface; 379 int hit = 0; 380 struct iovec iov[1]; 381 int recvmsglen; 382 char *recvp; 383 struct server *uservers; 384 struct sifaces *si; 385 386 if ((mesg = get_send_messages_out()) == NULL) 387 return 0; 388 389 if (mesg->sent == 1) 390 return 0; 391 392 bzero((char *)&sin6, sizeof(struct sockaddr_in6)); 393 sin6.sin6_family = AF_INET6; 394 sin6.sin6_flowinfo = 0; 395 sin6.sin6_scope_id = 0; 396 397 if (mesg->msg_type == RELAY_REPL) { 398 memset(dest_addr, 0, INET6_ADDRSTRLEN); 399 memcpy(dest_addr, mesg->peer_addr , INET6_ADDRSTRLEN); 400 401 recvmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)); 402 recvp = (char *) malloc(recvmsglen*sizeof(char)); 403 if (recvp == NULL) { 404 printf("ERROR-->recvp NO MORE MEMORY AVAILABLE \n"); 405 exit(1); 406 } 407 memset(recvp, 0, recvmsglen); 408 cmsgp = (struct cmsghdr *) recvp; 409 cmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 410 cmsgp->cmsg_level = IPPROTO_IPV6; 411 cmsgp->cmsg_type = IPV6_PKTINFO; 412 in6_pkt = (struct in6_pktinfo *) CMSG_DATA(cmsgp); 413 msg.msg_control = (void *) recvp; 414 msg.msg_controllen = recvmsglen; 415 416 /* destination address */ 417 if (inet_pton(AF_INET6, dest_addr, &sin6.sin6_addr)<=0) { 418 TRACE(dump, "%s - %s", dhcp6r_clock(), 419 "send_message()--> inet_pton FAILED \n"); 420 exit(1); 421 } 422 sin6.sin6_scope_id = mesg->if_index; 423 424 if (mesg->hop > 0) 425 sin6.sin6_port = htons(SERVER_PORT); 426 else 427 sin6.sin6_port = htons(CLIENT_PORT); 428 429 iface = get_interface(mesg->if_index); 430 431 if (iface != NULL) { 432 if (inet_pton(AF_INET6, iface->ipv6addr->gaddr, 433 &in6_pkt->ipi6_addr) <= 0) { /* source address */ 434 TRACE(dump, "%s - %s", dhcp6r_clock(), 435 "inet_pton failed in send_message()\n"); 436 exit(1); 437 } 438 TRACE(dump, "%s - SOURCE ADDRESS: %s\n", dhcp6r_clock(), 439 iface->ipv6addr->gaddr); 440 } 441 else { 442 /* the kernel will choose the source address */ 443 memset(&in6_pkt->ipi6_addr, 0, sizeof(in6_pkt->ipi6_addr)); 444 } 445 446 /* OUTGOING DEVICE FOR RELAY_REPLY MSG */ 447 in6_pkt->ipi6_ifindex = mesg->if_index; 448 TRACE(dump, "%s - OUTGOING DEVICE INDEX: %d\n", dhcp6r_clock(), 449 in6_pkt->ipi6_ifindex); 450 TRACE(dump, "%s - DESTINATION PORT: %d\n", dhcp6r_clock(), 451 ntohs(sin6.sin6_port)); 452 453 iov[0].iov_base = mesg->buffer; 454 iov[0].iov_len = mesg->datalength; 455 msg.msg_name = (void *) &sin6; 456 msg.msg_namelen = sizeof(sin6); 457 msg.msg_iov = &iov[0]; 458 msg.msg_iovlen = 1; 459 460 if ((count = sendmsg(sendsock->send_sock_desc, &msg, 0)) < 0) { 461 perror("sendmsg"); 462 return 0; 463 } 464 465 if (count > MAX_DHCP_MSG_LENGTH) 466 perror("bytes in sendmsg"); 467 468 TRACE(dump, "%s - *********> RELAY_REPL, SENT TO: %s SENT_BYTES: %d\n", 469 dhcp6r_clock(), dest_addr, count); 470 471 free(recvp); 472 473 mesg->sent = 1; 474 return 1; 475 } 476 477 if (mesg->msg_type == RELAY_FORW) { 478 for (ipv6uni = IPv6_uniaddr_list.next; ipv6uni != &IPv6_uniaddr_list; 479 ipv6uni = ipv6uni->next) { 480 bzero((char *)&sin6, sizeof(struct sockaddr_in6)); 481 sin6.sin6_family = AF_INET6; 482 483 memset(dest_addr, 0, INET6_ADDRSTRLEN); 484 memcpy(dest_addr, ipv6uni->uniaddr , INET6_ADDRSTRLEN); 485 486 /* destination address */ 487 if (inet_pton(AF_INET6, dest_addr, &sin6.sin6_addr) <= 0) { 488 TRACE(dump,"%s - %s",dhcp6r_clock(), 489 "inet_pton failed in send_message()\n"); 490 return 0; 491 } 492 493 recvmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)); 494 recvp = (char *) malloc(recvmsglen*sizeof(char)); 495 if (recvp == NULL) { 496 TRACE(dump, "%s - %s", dhcp6r_clock(), 497 "ERROR-->recvp NO MORE MEMORY AVAILABLE \n"); 498 exit(1); 499 } 500 memset(recvp, 0, recvmsglen); 501 502 cmsgp = (struct cmsghdr *) recvp; 503 cmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 504 cmsgp->cmsg_level = IPPROTO_IPV6; 505 cmsgp->cmsg_type = IPV6_PKTINFO; 506 in6_pkt = (struct in6_pktinfo *) CMSG_DATA(cmsgp); 507 msg.msg_control = (void *) recvp; 508 msg.msg_controllen = recvmsglen; 509 510 /* destination address */ 511 if (inet_pton(AF_INET6, dest_addr, &sin6.sin6_addr)<=0) { 512 TRACE(dump, "%s - %s", dhcp6r_clock(), 513 "inet_pton failed in send_message()\n"); 514 return 0; 515 } 516 sin6.sin6_scope_id = 0; 517 sin6.sin6_port = htons(SERVER_PORT); 518 519 /* the kernel will choose the source address */ 520 memset(&in6_pkt->ipi6_addr, 0, sizeof(in6_pkt->ipi6_addr)); 521 /* OUTGOING DEVICE FOR RELAY_REPLY MSG */ 522 in6_pkt->ipi6_ifindex = 0; 523 524 iov[0].iov_base = mesg->buffer; 525 iov[0].iov_len = mesg->datalength; 526 msg.msg_name = (void *) &sin6; 527 msg.msg_namelen = sizeof(sin6); 528 msg.msg_iov = &iov[0]; 529 msg.msg_iovlen = 1; 530 531 if ((count = sendmsg(sendsock->send_sock_desc, &msg, 0)) < 0) { 532 perror("sendmsg"); 533 return 0; 534 } 535 536 if (count > MAX_DHCP_MSG_LENGTH) 537 perror("bytes sendmsg"); 538 539 TRACE(dump, 540 "%s - ========> RELAY_FORW, SENT TO: %s SENT_BYTES: %d\n", 541 dhcp6r_clock(), dest_addr, count); 542 free(recvp); 543 hit = 1; 544 } /* for */ 545 546 for (iface = interface_list.next; iface!= &interface_list; 547 iface = iface->next) { 548 uservers = iface->sname; 549 while (uservers != NULL) { 550 bzero((char *)&sin6, sizeof(struct sockaddr_in6)); 551 sin6.sin6_family = AF_INET6; 552 553 memset(dest_addr, 0, INET6_ADDRSTRLEN); 554 memcpy(dest_addr, uservers->serv , INET6_ADDRSTRLEN); 555 556 /* destination address */ 557 if (inet_pton(AF_INET6, dest_addr, &sin6.sin6_addr) <= 0) { 558 TRACE(dump, "%s - %s", dhcp6r_clock(), 559 "inet_pton failed in send_message()\n"); 560 exit(1); 561 } 562 563 recvmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)); 564 recvp = (char *) malloc(recvmsglen*sizeof(char)); 565 if (recvp == NULL) { 566 TRACE(dump, "%s - %s", dhcp6r_clock(), 567 "ERROR-->recvp NO MORE MEMORY AVAILABLE \n"); 568 exit(1); 569 } 570 memset(recvp, 0, recvmsglen); 571 572 cmsgp = (struct cmsghdr *) recvp; 573 cmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 574 cmsgp->cmsg_level = IPPROTO_IPV6; 575 cmsgp->cmsg_type = IPV6_PKTINFO; 576 in6_pkt = (struct in6_pktinfo *) CMSG_DATA(cmsgp); 577 msg.msg_control = (void *) recvp; 578 msg.msg_controllen = recvmsglen; 579 580 /* destination address */ 581 if (inet_pton(AF_INET6, dest_addr, &sin6.sin6_addr) <= 0) { 582 TRACE(dump, "%s - %s", dhcp6r_clock(), 583 "inet_pton failed in send_message()\n"); 584 return 0; 585 } 586 587 in6_pkt->ipi6_ifindex = iface->devindex; 588 sin6.sin6_scope_id = in6_pkt->ipi6_ifindex; 589 590 TRACE(dump, "%s - OUTGOING DEVICE INDEX: %d\n", dhcp6r_clock(), 591 in6_pkt->ipi6_ifindex); 592 if (inet_pton(AF_INET6, iface->ipv6addr->gaddr, 593 &in6_pkt->ipi6_addr) <= 0) { /* source address */ 594 TRACE(dump,"%s - %s",dhcp6r_clock(), 595 "inet_pton failed in send_message()\n"); 596 exit(1); 597 } 598 TRACE(dump, "%s - SOURCE ADDRESS: %s\n", dhcp6r_clock(), 599 iface->ipv6addr->gaddr); 600 601 sin6.sin6_port = htons(SERVER_PORT); 602 603 iov[0].iov_base = mesg->buffer; 604 iov[0].iov_len = mesg->datalength; 605 msg.msg_name = (void *) &sin6; 606 msg.msg_namelen = sizeof(sin6); 607 msg.msg_iov = &iov[0]; 608 msg.msg_iovlen = 1; 609 610 if ((count = sendmsg(sendsock->send_sock_desc, &msg, 0)) < 0) { 611 perror("sendmsg"); 612 return 0; 613 } 614 615 if (count > MAX_DHCP_MSG_LENGTH) 616 perror("bytes sendmsg"); 617 618 TRACE(dump, 619 "%s - ========> RELAY_FORW, SENT TO: %s SENT_BYTES: %d\n", 620 dhcp6r_clock(), dest_addr, count); 621 free(recvp); 622 uservers = uservers->next; 623 hit = 1; 624 } /* while */ 625 } /* Interfaces */ 626 627 for (si = sifaces_list.next; si != &sifaces_list; si = si->next) { 628 *(mesg->hc_pointer)= MAXHOPCOUNT; 629 bzero((char *)&sin6, sizeof(struct sockaddr_in6)); 630 sin6.sin6_family = AF_INET6; 631 632 memset(dest_addr, 0, INET6_ADDRSTRLEN); 633 strcpy(dest_addr, ALL_DHCP_SERVERS); 634 635 /* destination address */ 636 if (inet_pton(AF_INET6, dest_addr, &sin6.sin6_addr) <= 0) { 637 TRACE(dump, "%s - %s", dhcp6r_clock(), 638 "inet_pton failed in send_message()\n"); 639 return 0; 640 } 641 642 recvmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)); 643 recvp = (char *) malloc(recvmsglen*sizeof(char)); 644 if (recvp == NULL) { 645 TRACE(dump, "%s - %s", dhcp6r_clock(), 646 "ERROR-->recvp NO MORE MEMORY AVAILABLE \n"); 647 exit(1); 648 } 649 memset(recvp, 0, recvmsglen); 650 651 cmsgp = (struct cmsghdr *) recvp; 652 cmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 653 cmsgp->cmsg_level = IPPROTO_IPV6; 654 cmsgp->cmsg_type = IPV6_PKTINFO; 655 in6_pkt = (struct in6_pktinfo *) CMSG_DATA(cmsgp); 656 msg.msg_control = (void *) recvp; 657 msg.msg_controllen = recvmsglen; 658 659 /* destination address */ 660 if (inet_pton(AF_INET6, dest_addr, &sin6.sin6_addr) <= 0) { 661 TRACE(dump,"%s - %s",dhcp6r_clock(), 662 "inet_pton failed in send_message()\n"); 663 return 0; 664 } 665 666 in6_pkt->ipi6_ifindex = if_nametoindex(si->siface); 667 sin6.sin6_scope_id = in6_pkt->ipi6_ifindex; 668 669 TRACE(dump, "%s - OUTGOING DEVICE INDEX: %d\n", dhcp6r_clock(), 670 in6_pkt->ipi6_ifindex); 671 iface = get_interface(in6_pkt->ipi6_ifindex); 672 if (iface == NULL) { 673 TRACE(dump, "%s - %s", dhcp6r_clock(), 674 "ERROR--> send_message(), NO INTERFACE INFO FOUND\n"); 675 exit(0); 676 } 677 if (inet_pton(AF_INET6, iface->ipv6addr->gaddr, 678 &in6_pkt->ipi6_addr)<=0) { /* source address */ 679 TRACE(dump, "%s - %s", dhcp6r_clock(), 680 "inet_pton failed in send_message()\n"); 681 exit(1); 682 } 683 TRACE(dump,"%s - SOURCE ADDRESS: %s\n",dhcp6r_clock(), 684 iface->ipv6addr->gaddr); 685 686 sin6.sin6_port = htons(SERVER_PORT); 687 688 iov[0].iov_base = mesg->buffer; 689 iov[0].iov_len = mesg->datalength; 690 msg.msg_name = (void *) &sin6; 691 msg.msg_namelen = sizeof(sin6); 692 msg.msg_iov = &iov[0]; 693 msg.msg_iovlen = 1; 694 695 if ((count = sendmsg(sendsock->send_sock_desc, &msg, 0)) < 0) { 696 perror("sendmsg"); 697 return 0; 698 } 699 700 if (count > MAX_DHCP_MSG_LENGTH) 701 perror("bytes sendmsg"); 702 703 TRACE(dump, 704 "%s - ========> RELAY_FORW, SENT TO: %s SENT_BYTES: %d\n", 705 dhcp6r_clock(), dest_addr, count); 706 707 free(recvp); 708 hit = 1; 709 } /* for */ 710 711 if (hit == 0) { 712 for (iface = interface_list.next; iface != &interface_list; 713 iface = iface->next) { 714 if (mesg->interface_in == iface->devindex) 715 continue; 716 717 *(mesg->hc_pointer)= MAXHOPCOUNT; 718 bzero((char *)&sin6, sizeof(struct sockaddr_in6)); 719 sin6.sin6_family = AF_INET6; 720 721 memset(dest_addr, 0, INET6_ADDRSTRLEN); 722 strcpy(dest_addr, ALL_DHCP_SERVERS); 723 724 /* destination address */ 725 if (inet_pton(AF_INET6, dest_addr, &sin6.sin6_addr) <= 0) { 726 TRACE(dump, "%s - %s", dhcp6r_clock(), 727 "inet_pton failed in send_message()\n"); 728 return 0; 729 } 730 731 recvmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)); 732 recvp = (char *) malloc(recvmsglen*sizeof(char)); 733 if (recvp ==NULL) { 734 TRACE(dump, "%s - %s", dhcp6r_clock(), 735 "ERROR-->recvp NO MORE MEMORY AVAILABLE \n"); 736 exit(1); 737 } 738 memset(recvp, 0, recvmsglen); 739 740 cmsgp = (struct cmsghdr *) recvp; 741 cmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 742 cmsgp->cmsg_level = IPPROTO_IPV6; 743 cmsgp->cmsg_type = IPV6_PKTINFO; 744 in6_pkt = (struct in6_pktinfo *) CMSG_DATA(cmsgp); 745 msg.msg_control = (void *) recvp; 746 msg.msg_controllen = recvmsglen; 747 748 /* destination address */ 749 if (inet_pton(AF_INET6, dest_addr, &sin6.sin6_addr) <= 0) { 750 TRACE(dump, "%s - %s", dhcp6r_clock(), 751 "inet_pton failed in send_message()\n"); 752 return 0; 753 } 754 sin6.sin6_port = htons(SERVER_PORT); 755 756 in6_pkt->ipi6_ifindex = iface->devindex; 757 sin6.sin6_scope_id = in6_pkt->ipi6_ifindex; 758 759 TRACE(dump, "%s - OUTGOING DEVICE INDEX: %d\n", dhcp6r_clock(), 760 in6_pkt->ipi6_ifindex); 761 if (inet_pton(AF_INET6, iface->ipv6addr->gaddr, 762 &in6_pkt->ipi6_addr)<=0) { /* source address */ 763 TRACE(dump, "%s - %s", dhcp6r_clock(), 764 "inet_pton failed in send_message()\n"); 765 exit(1); 766 } 767 768 TRACE(dump, "%s - SOURCE ADDRESS: %s\n", dhcp6r_clock(), 769 iface->ipv6addr->gaddr); 770 771 iov[0].iov_base = mesg->buffer; 772 iov[0].iov_len = mesg->datalength; 773 msg.msg_name = (void *) &sin6; 774 msg.msg_namelen = sizeof(sin6); 775 msg.msg_iov = &iov[0]; 776 msg.msg_iovlen = 1; 777 778 if ((count = sendmsg(sendsock->send_sock_desc, &msg, 0))< 0) { 779 perror("sendmsg"); 780 return 0; 781 } 782 783 if (count > MAX_DHCP_MSG_LENGTH) 784 perror("sendmsg"); 785 786 TRACE(dump, 787 "%s - ========> RELAY_FORW, SENT TO: %s SENT_BYTES: %d\n", 788 dhcp6r_clock(), dest_addr, count); 789 free(recvp); 790 } /* for */ 791 } 792 } 793 794 fflush(dump); 795 mesg->sent = 1; 796 return 1; 797 798 799 TRACE(dump, "%s - %s", dhcp6r_clock(), 800 "FATAL ERROR--> NO MESSAGE TYPE TO BE SENT!\n"); 801 exit(1); 802} 803