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 <sys/types.h> 32#include <unistd.h> 33#include <signal.h> 34#include <string.h> 35#if TIME_WITH_SYS_TIME 36# include <sys/time.h> 37# include <sys/timeb.h> 38# include <time.h> 39#else 40# if HAVE_SYS_TIME_H 41# include <sys/time.h> 42# else 43# include <time.h> 44# endif 45#endif 46#include <sys/socket.h> 47#include <arpa/inet.h> 48 49#include "relay6_parser.h" 50#include "relay6_socket.h" 51#include "relay6_database.h" 52 53int 54main(argc, argv) 55 int argc; 56 char **argv; 57{ 58 int err =0, i; 59 FILE *fp; 60 int sw = 0; 61 int du = 0; 62 struct interface *iface; 63 struct sockaddr_in6 sin6; 64 char *sf, *eth, *addr; 65 struct cifaces *ci; 66 struct sifaces *si; 67 struct IPv6_uniaddr *unia; 68 struct server *sa; 69 struct msg_parser *mesg; 70 71 fp = fopen(PIDFILE, "w+"); 72 if (fp == NULL) { 73 printf("COULD NOT WRITE PID FILE\n"); 74 exit(1); 75 } 76 fprintf(fp, "%d", getpid()); 77 fclose(fp); 78 79 signal(SIGINT, handler); 80 init_relay(); 81 82 if (argc > 1) { 83 for (i = 1; i < argc; ++i) { 84 if (strcmp(argv[i], "-d") == 0) 85 du = 1; 86 } 87 if (du == 0) { 88 dump = fopen(DUMPFILE, "w+"); 89 if (dump == NULL) { 90 printf("COULD NOT WRITE DUMP FILE: %s\n", DUMPFILE); 91 exit(1); 92 } 93 } 94 else { 95 dump = stderr; 96 } 97 98 if (get_interface_info() == 0) 99 goto ERROR; 100 101 for(i = 1; i < argc; ++i) { 102 if (strcmp(argv[i], "-cm") == 0) { 103 i++; 104 if (get_interface_s(argv[i]) == NULL) { 105 err = 5; 106 goto ERROR; 107 } 108 109 sw = 1; 110 ci = (struct cifaces *) malloc(sizeof(struct cifaces)); 111 if (ci == NULL) { 112 TRACE(dump, "%s - %s ", dhcp6r_clock(), 113 "Main--> ERROR NO MORE MEMORY AVAILABLE\n"); 114 exit(1); 115 } 116 ci->ciface = strdup(argv[i]); 117 ci->next = cifaces_list.next; 118 cifaces_list.next = ci; 119 120 TRACE(dump, "%s - %s'%s'\n", dhcp6r_clock(), 121 "SETTING UP CLIENT INTERFACE: ", argv[i]); 122 continue; 123 } 124 else if (strcmp(argv[i], "-cu") == 0) { 125 multicast_off = 1; 126 } 127 else if (strcmp(argv[i], "-sm") == 0) { 128 i++; 129 if (get_interface_s(argv[i]) == NULL) { 130 err = 5; 131 goto ERROR; 132 } 133 si = (struct sifaces *) malloc(sizeof(struct sifaces)); 134 if (si == NULL) { 135 TRACE(dump, "%s - %s", dhcp6r_clock(), 136 "Main--> ERROR NO MORE MEMORY AVAILABLE\n"); 137 exit(1); 138 } 139 si->siface = strdup(argv[i]); 140 si->next = sifaces_list.next; 141 sifaces_list.next = si; 142 143 TRACE(dump, "%s - %s'%s'\n", dhcp6r_clock(), 144 "SETTING UP SERVER INTERFACE: ", argv[i]); 145 146 continue; 147 } 148 else if (strcmp(argv[i], "-d") == 0) { 149 continue; 150 } 151 else if (strcmp(argv[i], "-su") == 0) { 152 i++; 153 /* destination address */ 154 if (inet_pton(AF_INET6, argv[i] , &sin6.sin6_addr) <= 0) { 155 err = 3; 156 goto ERROR; 157 } 158 159 if (IN6_IS_ADDR_UNSPECIFIED(&sin6.sin6_addr)) { 160 err = 3; 161 goto ERROR; 162 } 163 164 unia = (struct IPv6_uniaddr *) 165 malloc(sizeof(struct IPv6_uniaddr)); 166 if (unia == NULL) { 167 TRACE(dump, "%s - %s", dhcp6r_clock(), 168 "Main--> ERROR NO MORE MEMORY AVAILABLE\n"); 169 exit(1); 170 } 171 unia->uniaddr = strdup(argv[i]); 172 unia->next = IPv6_uniaddr_list.next; 173 IPv6_uniaddr_list.next = unia; 174 175 TRACE(dump, "%s - %s'%s'\n", dhcp6r_clock(), 176 "SETTING UP SERVER ADDRESS: ", argv[i]); 177 nr_of_uni_addr += 1; 178 179 continue; 180 } 181 else if (strcmp(argv[i], "-sf") == 0) { 182 i++; 183 sf = strdup(argv[i]); 184 185 eth = strtok(sf, "+"); 186 if (eth == NULL) { 187 err = 4; 188 goto ERROR; 189 } 190 addr = strtok((sf+strlen(eth)+1), "\0"); 191 if (addr == NULL) { 192 err = 4; 193 goto ERROR; 194 } 195 196 /* destination address */ 197 if (inet_pton(AF_INET6, addr , &sin6.sin6_addr) <= 0) { 198 err = 3; 199 goto ERROR; 200 } 201 202 if (IN6_IS_ADDR_UNSPECIFIED(&sin6.sin6_addr) ) { 203 err = 3; 204 goto ERROR; 205 } 206 207 if ((iface = get_interface_s(eth)) != NULL) { 208 sa = (struct server *) malloc(sizeof(struct server)); 209 if (sa == NULL) { 210 TRACE(dump, "%s - %s", dhcp6r_clock(), 211 "Main--> ERROR NO MORE MEMORY AVAILABLE\n"); 212 exit(1); 213 } 214 sa->serv = strdup(addr); 215 sa->next = NULL; 216 if (iface->sname != NULL) 217 sa->next = iface->sname; 218 iface->sname = sa; 219 TRACE(dump, "%s - %s%s FOR INTERFACE: %s\n", dhcp6r_clock(), 220 "SETTING UP SERVER ADDRESS: ", addr, eth); 221 free(sf); 222 } 223 else { 224 err = 5; 225 goto ERROR; 226 } 227 228 continue; 229 } 230 else if ((strcmp(argv[i], "-h") == 0) || 231 (strcmp(argv[i], "--help") == 0)) { 232 command_text(); 233 } 234 else { 235 err = 4; 236 goto ERROR; 237 } 238 } 239 } 240 else { 241 dump = fopen(DUMPFILE, "w+"); 242 if (dump == NULL) { 243 printf("COULD NOT WRITE DUMP FILE: %s\n", DUMPFILE); 244 exit(1); 245 } 246 247 if (get_interface_info() == 0) 248 goto ERROR; 249 } 250 251 if (sw == 1) 252 multicast_off = 0; 253 254 init_socket(); 255 256 if (set_sock_opt() == 0) 257 goto ERROR; 258 259 if (fill_addr_struct() == 0) 260 goto ERROR; 261 262 if (du == 0) { 263 switch(fork()) { 264 case 0: 265 break; 266 case -1: 267 perror("fork"); 268 exit(1); 269 default: 270 exit(0); 271 } 272 } 273 274 while (1) { 275 if (check_select() == 1) { 276 if (recv_data() == 1) { 277 if (get_recv_data() == 1) { 278 mesg = create_parser_obj(); 279 if (put_msg_in_store (mesg) == 0) 280 mesg->sent = 1; /* mark it for deletion */ 281 } 282 } 283 } 284 285 send_message(); 286 delete_messages(); 287 } 288 289ERROR: 290 291 if (err == 3) { 292 printf("dhcp6r: malformed address '%s'\n", argv[i]); 293 exit(1); 294 } 295 296 if (err == 4) { 297 printf("dhcp6r: option '%s' not recognized\n", argv[i]); 298 exit(1); 299 } 300 301 if (err == 5) { 302 printf("dhcp6r: interface '%s' does not exist \n", argv[i]); 303 exit(1); 304 } 305 306 printf("ERROR OCCURED IN THE RELAY AGENT LOOP, EXITING..........\n"); 307 exit(1); 308} 309 310void 311command_text() 312{ 313 printf("Usage:\n"); 314 printf(" dhcp6r [-d] [-cu] [-cm <interface>] [-sm <interface>] " 315 "[-su <address>] [-sf <interface>+<address>] \n"); 316 exit(1); 317} 318 319char* 320dhcp6r_clock() 321{ 322 time_t tim; 323 char *s, *p; 324 325 time(&tim); 326 s = ctime(&tim); 327 328 p = s; 329 do { 330 p = strstr(p, " "); 331 if (p != NULL) { 332 if (*(p-1) == '/') 333 *p = '0'; 334 else 335 *p = '/'; 336 } 337 } while(p != NULL); 338 339 p = strstr(s, "\n"); 340 if (p != NULL) 341 *p = '\0'; 342 343 return s; 344} 345 346void handler(int signo) { 347 close(recvsock->recv_sock_desc); 348 close(sendsock->send_sock_desc); 349 TRACE(dump, "%s - %s", dhcp6r_clock(), 350 "RELAY AGENT IS STOPPING............\n"); 351 fflush(dump); 352 353 exit(0); 354} 355