00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifdef HAVE_CONFIG_H
00033 #include <config.h>
00034 #endif
00035
00036 #define DEBUG_FLAG 'H'
00037
00038 #include <sys/types.h>
00039 #include <sys/socket.h>
00040 #include <netinet/in.h>
00041 #include <string.h>
00042 #include <stdio.h>
00043 #include <arpa/inet.h>
00044 #include <sys/un.h>
00045 #include <net/if.h>
00046
00047 #include <pthread.h>
00048
00049 #include <sys/time.h>
00050 #include <unistd.h>
00051 #include <syslog.h>
00052 #ifndef __USE_BSD
00053 #define __USE_BSD
00054 #endif
00055 #include <signal.h>
00056 #include <time.h>
00057 #include <stdlib.h>
00058 #include <assert.h>
00059 #include <errno.h>
00060 #include <getopt.h>
00061 #include <sys/uio.h>
00062
00063 #include "ha.h"
00064 #include "list.h"
00065 #include "hashtable.h"
00066 #include "fileio.h"
00067 #include "msgparser.h"
00068 #include "agentadv.h"
00069 #include "proxyarp.h"
00070 #include "binding.h"
00071 #include "auth.h"
00072 #include "tunnel.h"
00073 #include "debug.h"
00074 #include "agentapi.h"
00075 #include "util.h"
00076 #include "fixed_fd_zero.h"
00077 #include "dyn_ip.h"
00078 #include "ha_config.h"
00079 #include "agent_utils.h"
00080 #include "md5_mac.h"
00081
00082
00083 #include "clientpacket.h"
00084 #include "packet.h"
00085 #include "script.h"
00086 #include "socket.h"
00087 #include "pidfile.h"
00088
00089
00090 #define DEFAULT_SCRIPT "/usr/share/udhcpc/default.script"
00091
00092 struct client_config_t client_config = {
00093
00094 abort_if_no_lease: 0,
00095 foreground: 0,
00096 quit_after_lease: 0,
00097 background_if_no_lease: 0,
00098 interface: "eth2",
00099 pidfile: NULL,
00100 script: DEFAULT_SCRIPT,
00101 clientid: NULL,
00102 hostname: NULL,
00103 ifindex: 0,
00104 arp: "\0\0\0\0\0\0",
00105 };
00106
00107 #define LISTEN_NONE 0
00108 #define LISTEN_KERNEL 1
00109 #define LISTEN_RAW 2
00110 static int listen_mode;
00111
00112
00113 extern int opt_foreground;
00114 extern char *opt_config;
00115
00116
00117 struct dhcp_mobile {
00118 unsigned char *nai;
00119 int state;
00120 unsigned long requested_ip;
00121 unsigned long server_addr;
00122 unsigned long timeout;
00123 int packet_num;
00124 int fd;
00125 int signal_pipe[2];
00126 int nai_length;
00127 int lease;
00128 int spi;
00129 };
00130
00131 struct dhcp_mobile dhcp_mobile_array[HA_DEFAULT_MAX_BINDINGS];
00132
00133 int cur_mobiles=0;
00134 int maxmobiles=HA_DEFAULT_MAX_BINDINGS;
00135
00136
00137
00138
00139
00140 #define ASSERT assert
00141 #define MIN(x, y) ( (x) < (y) ? (x) : (y))
00142
00143 #define LOG2(lev, fmt, args...) { DEBUG(DEBUG_FLAG, fmt, ## args); \
00144 syslog(lev, fmt, ## args); }
00145
00146 #define MAX_ADV_DELAY 200000.0
00147
00148
00149
00150
00151
00152
00153
00154
00155 static void clean_up();
00156
00157
00158
00159 static void remove_tunnel(struct bindingentry *binding);
00160 static void destroy_binding(struct bindingentry *binding);
00161 static struct fa_spi_entry* get_fa_spi(int spi, struct in_addr addr);
00162 static struct spi_entry* get_mn_spi(int spi);
00163 static void init_interfaces(void);
00164
00165
00166
00167 static struct ha_config config;
00168 struct fa_nai_ext *ha_nai = NULL;
00169 static HASH *tunnels;
00170 static struct bindingtable *bindings;
00171 static int bindingcount = 0;
00172 static char *program_name;
00173 static struct dynamics_ha_status stats;
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00193 int find_dhcp_mobile(unsigned char *nai, int nai_length)
00194 {
00195 int i, n, found;
00196 found=-1;
00197 for(i=0;i<cur_mobiles;i++)
00198 {
00199 if(nai_length==dhcp_mobile_array[i].nai_length)
00200 {
00201 n=memcmp(nai, dhcp_mobile_array[i].nai,nai_length);
00202 if( n==0 )
00203 {
00204 found=i;
00205 break;
00206 }
00207 }
00208
00209 }
00210
00211 return found;
00212
00213 }
00214
00215
00225 int add_dhcp_mobile(unsigned long ip, unsigned char *nai, int nai_length)
00226 {
00227 if (cur_mobiles==maxmobiles) return 0;
00228 dhcp_mobile_array[cur_mobiles].requested_ip=ip;
00229 dhcp_mobile_array[cur_mobiles].timeout=0;
00230 dhcp_mobile_array[cur_mobiles].state=DHCPDISCOVER;
00231 dhcp_mobile_array[cur_mobiles].nai= xmalloc(nai_length);
00232 memcpy(dhcp_mobile_array[cur_mobiles].nai, nai, nai_length);
00233 dhcp_mobile_array[cur_mobiles].nai_length=nai_length;
00234 cur_mobiles=cur_mobiles+1;
00235 return 1;
00236 }
00237
00238
00247 int del_dhcp_mobile(int i)
00248 {
00249 if(cur_mobiles <= i || i<0) return 0;
00250 free(dhcp_mobile_array[i].nai);
00251 dhcp_mobile_array[i].state=0;
00252 dhcp_mobile_array[i].requested_ip=0;
00253 dhcp_mobile_array[i].server_addr=0;
00254 dhcp_mobile_array[i].timeout=0;
00255 dhcp_mobile_array[i].packet_num=0;
00256 dhcp_mobile_array[i].fd=0;
00257 dhcp_mobile_array[i].signal_pipe[0]=0;
00258 dhcp_mobile_array[i].signal_pipe[1]=0;
00259 dhcp_mobile_array[i].nai_length=0;
00260 dhcp_mobile_array[i].lease=0;
00261 dhcp_mobile_array[i].spi=0;
00262 dhcp_mobile_array[i]=dhcp_mobile_array[cur_mobiles-1];
00263 cur_mobiles=cur_mobiles-1;
00264 return 1;
00265
00266 }
00267
00268
00269
00270
00271
00272
00273
00274
00275 static void change_mode(int new_mode, int selected_mobile)
00276 {
00277 DEBUG(LOG_INFO, "entering %s listen mode",
00278 new_mode ? (new_mode == 1 ? "kernel" : "raw") : "none");
00279 close(dhcp_mobile_array[selected_mobile].fd);
00280 dhcp_mobile_array[selected_mobile].fd = -1;
00281 listen_mode = new_mode;
00282 }
00283
00284 static void exit_client(int retval)
00285 {
00286 pidfile_delete(client_config.pidfile);
00287 CLOSE_LOG();
00288 exit(retval);
00289 }
00290
00291
00292
00293 static void signal_handler(int sig, int selected_mobile)
00294 {
00295 if (send(dhcp_mobile_array[selected_mobile].signal_pipe[1], &sig, sizeof(sig), MSG_DONTWAIT) < 0) {
00296 LOG(LOG_ERR, "Could not send signal: %s",
00297 strerror(errno));
00298 }
00299 }
00300
00301
00302 static void perform_renew(int selected_mobile)
00303 {
00304
00305 LOG(LOG_INFO, "Performing a DHCP renew");
00306 switch (dhcp_mobile_array[selected_mobile].state) {
00307 case BOUND:
00308 change_mode(LISTEN_KERNEL, selected_mobile);
00309 case RENEWING:
00310 case REBINDING:
00311 dhcp_mobile_array[selected_mobile].state = RENEW_REQUESTED;
00312 break;
00313 case RENEW_REQUESTED:
00314 run_script(NULL, "deconfig");
00315 case REQUESTING:
00316 case RELEASED:
00317 change_mode(LISTEN_RAW, selected_mobile);
00318 dhcp_mobile_array[selected_mobile].state = INIT_SELECTING;
00319 break;
00320 case INIT_SELECTING: NULL;
00321 }
00322
00323
00324 dhcp_mobile_array[selected_mobile].packet_num = 0;
00325
00326
00327 dhcp_mobile_array[selected_mobile].timeout = 0;
00328 }
00329
00330
00331
00332 static void perform_release(int selected_mobile)
00333 {
00334 char buffer[16];
00335
00336 struct in_addr temp_addr;
00337
00338
00339 if (dhcp_mobile_array[selected_mobile].state == BOUND || dhcp_mobile_array[selected_mobile].state == RENEWING || dhcp_mobile_array[selected_mobile].state == REBINDING) {
00340 temp_addr.s_addr = dhcp_mobile_array[selected_mobile].server_addr;
00341 sprintf(buffer, "%s", inet_ntoa(temp_addr));
00342 temp_addr.s_addr = dhcp_mobile_array[selected_mobile].requested_ip;
00343 LOG(LOG_INFO, "Unicasting a release of %s to %s",
00344 inet_ntoa(temp_addr), buffer);
00345 send_release(dhcp_mobile_array[selected_mobile].server_addr, dhcp_mobile_array[selected_mobile].requested_ip);
00346 run_script(NULL, "deconfig");
00347 }
00348 LOG(LOG_INFO, "Entering released state");
00349
00350 change_mode(LISTEN_NONE, selected_mobile);
00351 dhcp_mobile_array[selected_mobile].state = RELEASED;
00352 dhcp_mobile_array[selected_mobile].timeout = 0;
00353 }
00354
00355
00356 static void background(void)
00357 {
00358 int pid_fd;
00359
00360 pid_fd = pidfile_acquire(client_config.pidfile);
00361 while (pid_fd >= 0 && pid_fd < 3) pid_fd = dup(pid_fd);
00362 if (daemon(0, 0) == -1) {
00363 perror("fork");
00364 exit_client(1);
00365 }
00366 client_config.foreground = 1;
00367 pidfile_write_release(pid_fd);
00368 }
00369
00379 unsigned long udhcp(int selected_mobile, int flag)
00380 {
00381
00382 unsigned char *temp, *message;
00383 unsigned long t1 = 0, t2 = 0, xid = 0;
00384 unsigned long start = 0, lease;
00385 fd_set rfds;
00386 int retval;
00387 struct timeval tv;
00388 int c, len;
00389 struct dhcpMessage packet;
00390 struct in_addr temp_addr;
00391 int pid_fd;
00392 time_t now;
00393 int max_fd;
00394 int sig;
00395
00396
00397 if (flag == REQUESTIP)
00398 {
00399 if(dhcp_mobile_array[selected_mobile].state==2) return 0;
00400 listen_mode = 0;
00401 dhcp_mobile_array[selected_mobile].state=1;
00402 }
00403
00404
00405 if (flag == RELEASEIP)
00406 {
00407 perform_release(selected_mobile);
00408 return 0;
00409 }
00410
00411 if(flag == RENEWIP)
00412 {
00413 perform_renew(selected_mobile);
00414 return dhcp_mobile_array[selected_mobile].requested_ip;
00415 }
00416
00417 OPEN_LOG("udhcpc");
00418
00419 pid_fd = pidfile_acquire(client_config.pidfile);
00420 pidfile_write_release(pid_fd);
00421 if (read_interface(client_config.interface, &client_config.ifindex,
00422 NULL, client_config.arp) < 0)
00423 exit_client(1);
00424
00425
00426
00427
00428
00429 int mal_big = dhcp_mobile_array[selected_mobile].nai_length+2;
00430 client_config.clientid = xmalloc(mal_big);
00431 client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID;
00432 client_config.clientid[OPT_LEN] = dhcp_mobile_array[selected_mobile].nai_length;
00433 client_config.clientid[OPT_DATA] = 1;
00434 memcpy(client_config.clientid + 2, dhcp_mobile_array[selected_mobile].nai, dhcp_mobile_array[selected_mobile].nai_length);
00435
00436
00437 socketpair(AF_UNIX, SOCK_STREAM, 0, dhcp_mobile_array[selected_mobile].signal_pipe);
00438 signal(SIGUSR1, signal_handler);
00439 signal(SIGUSR2, signal_handler);
00440 signal(SIGTERM, signal_handler);
00441
00442 dhcp_mobile_array[selected_mobile].state = INIT_SELECTING;
00443
00444 change_mode(LISTEN_RAW, selected_mobile);
00445
00446 for (;;) {
00447
00448 tv.tv_sec = dhcp_mobile_array[selected_mobile].timeout - time(0);
00449 tv.tv_usec = 0;
00450 FD_ZERO(&rfds);
00451
00452 if (listen_mode != LISTEN_NONE && dhcp_mobile_array[selected_mobile].fd < 0) {
00453 if (listen_mode == LISTEN_KERNEL)
00454 dhcp_mobile_array[selected_mobile].fd = listen_socket(INADDR_ANY, CLIENT_PORT, client_config.interface);
00455 else
00456 dhcp_mobile_array[selected_mobile].fd = raw_socket(client_config.ifindex);
00457 if (dhcp_mobile_array[selected_mobile].fd < 0) {
00458 LOG(LOG_ERR, "FATAL: couldn't listen on socket, %s", strerror(errno));
00459 exit_client(0);
00460 }
00461 }
00462 if (dhcp_mobile_array[selected_mobile].fd >= 0) FD_SET(dhcp_mobile_array[selected_mobile].fd, &rfds);
00463 FD_SET(dhcp_mobile_array[selected_mobile].signal_pipe[0], &rfds);
00464
00465 if (tv.tv_sec > 0) {
00466 DEBUG(LOG_INFO, "Waiting on select...\n");
00467 max_fd = dhcp_mobile_array[selected_mobile].signal_pipe[0] > dhcp_mobile_array[selected_mobile].fd ? dhcp_mobile_array[selected_mobile].signal_pipe[0] : dhcp_mobile_array[selected_mobile].fd;
00468 retval = select(max_fd + 1, &rfds, NULL, NULL, &tv);
00469 } else retval = 0;
00470
00471 now = time(0);
00472 if (retval == 0) {
00473
00474 switch (dhcp_mobile_array[selected_mobile].state) {
00475 case INIT_SELECTING:
00476 if (dhcp_mobile_array[selected_mobile].packet_num < 3) {
00477 if (dhcp_mobile_array[selected_mobile].packet_num == 0)
00478 xid = random_xid();
00479
00480
00481
00482 send_discover(xid, dhcp_mobile_array[selected_mobile].requested_ip);
00483
00484 dhcp_mobile_array[selected_mobile].timeout = now + ((dhcp_mobile_array[selected_mobile].packet_num == 2) ? 4 : 2);
00485 dhcp_mobile_array[selected_mobile].packet_num++;
00486 } else {
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497 dhcp_mobile_array[selected_mobile].packet_num = 0;
00498 dhcp_mobile_array[selected_mobile].timeout = 0;
00499 LOG(LOG_INFO, "DHCP-server did not answer after 3 DHCPDISCOVERs");
00500 return -1;
00501 }
00502
00503 break;
00504 case RENEW_REQUESTED:
00505 case REQUESTING:
00506 if (dhcp_mobile_array[selected_mobile].packet_num < 3) {
00507
00508
00509 if (dhcp_mobile_array[selected_mobile].state == RENEW_REQUESTED)
00510 send_renew(xid, dhcp_mobile_array[selected_mobile].server_addr, dhcp_mobile_array[selected_mobile].requested_ip);
00511 else send_selecting(xid, dhcp_mobile_array[selected_mobile].server_addr, dhcp_mobile_array[selected_mobile].requested_ip);
00512
00513 dhcp_mobile_array[selected_mobile].timeout = now + ((dhcp_mobile_array[selected_mobile].packet_num == 2) ? 10 : 2);
00514 dhcp_mobile_array[selected_mobile].packet_num++;
00515 } else {
00516
00517
00518 if (dhcp_mobile_array[selected_mobile].state == RENEW_REQUESTED) run_script(NULL, "deconfig");
00519 dhcp_mobile_array[selected_mobile].state = INIT_SELECTING;
00520 dhcp_mobile_array[selected_mobile].timeout = now;
00521 dhcp_mobile_array[selected_mobile].packet_num = 0;
00522 change_mode(LISTEN_RAW, selected_mobile);
00523 }
00524 break;
00525 case BOUND:
00526
00527 dhcp_mobile_array[selected_mobile].state = RENEWING;
00528 change_mode(LISTEN_KERNEL, selected_mobile);
00529
00530 DEBUG(LOG_INFO, "Entering renew state");
00531
00532 case RENEWING:
00533
00534 if ((t2 - t1) <= (lease / 14400 + 1)) {
00535
00536 dhcp_mobile_array[selected_mobile].state = REBINDING;
00537 dhcp_mobile_array[selected_mobile].timeout = now + (t2 - t1);
00538 DEBUG(LOG_INFO, "Entering rebinding state");
00539 } else {
00540
00541 send_renew(xid, dhcp_mobile_array[selected_mobile].server_addr, dhcp_mobile_array[selected_mobile].requested_ip);
00542
00543 t1 = (t2 - t1) / 2 + t1;
00544 dhcp_mobile_array[selected_mobile].timeout = t1 + start;
00545 }
00546 break;
00547 case REBINDING:
00548
00549 if ((lease - t2) <= (lease / 14400 + 1)) {
00550
00551 dhcp_mobile_array[selected_mobile].state = INIT_SELECTING;
00552 LOG(LOG_INFO, "Lease lost, entering init state");
00553 run_script(NULL, "deconfig");
00554 dhcp_mobile_array[selected_mobile].timeout = now;
00555 dhcp_mobile_array[selected_mobile].packet_num = 0;
00556 change_mode(LISTEN_RAW, selected_mobile);
00557 } else {
00558
00559 send_renew(xid, 0, dhcp_mobile_array[selected_mobile].requested_ip);
00560
00561 t2 = (lease - t2) / 2 + t2;
00562 dhcp_mobile_array[selected_mobile].timeout = t2 + start;
00563 }
00564 break;
00565 case RELEASED:
00566
00567 dhcp_mobile_array[selected_mobile].timeout = 0;
00568 break;
00569 }
00570
00571
00572 } else if (retval > 0 && listen_mode != LISTEN_NONE && FD_ISSET(dhcp_mobile_array[selected_mobile].fd, &rfds)) {
00573
00574
00575 if (listen_mode == LISTEN_KERNEL)
00576 len = get_packet(&packet, dhcp_mobile_array[selected_mobile].fd);
00577 else len = get_raw_packet(&packet, dhcp_mobile_array[selected_mobile].fd);
00578
00579 if (len == -1 && errno != EINTR) {
00580 DEBUG(LOG_INFO, "error on read, %s, reopening socket", strerror(errno));
00581 change_mode(listen_mode, selected_mobile);
00582 }
00583 if (len < 0) continue;
00584
00585
00586 if (packet.xid != xid) {
00587 DEBUG(LOG_INFO, "Ignoring XID %lx (our xid is %lx)",
00588 (unsigned long) packet.xid, xid);
00589 continue;
00590 }
00591
00592 if ((message = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) {
00593 DEBUG(LOG_ERR, "couldnt get option from packet -- ignoring");
00594 continue;
00595 }
00596
00597 switch (dhcp_mobile_array[selected_mobile].state) {
00598 case INIT_SELECTING:
00599
00600 if (*message == DHCPOFFER) {
00601 if ((temp = get_option(&packet, DHCP_SERVER_ID))) {
00602 memcpy(&dhcp_mobile_array[selected_mobile].server_addr, temp, 4);
00603 xid = packet.xid;
00604 dhcp_mobile_array[selected_mobile].requested_ip = packet.yiaddr;
00605
00606
00607 dhcp_mobile_array[selected_mobile].state = REQUESTING;
00608 dhcp_mobile_array[selected_mobile].timeout = now;
00609 dhcp_mobile_array[selected_mobile].packet_num = 0;
00610 } else {
00611 DEBUG(LOG_ERR, "No server ID in message");
00612 }
00613 }
00614 break;
00615 case RENEW_REQUESTED:
00616 case REQUESTING:
00617 case RENEWING:
00618 case REBINDING:
00619 if (*message == DHCPACK) {
00620 if (!(temp = get_option(&packet, DHCP_LEASE_TIME))) {
00621 LOG(LOG_ERR, "No lease time with ACK, using 1 hour lease");
00622 lease = 60 * 60;
00623 } else {
00624 memcpy(&lease, temp, 4);
00625 lease = ntohl(lease);
00626 }
00627
00628
00629 t1 = lease / 2;
00630
00631
00632 t2 = (lease * 0x7) >> 3;
00633 temp_addr.s_addr = packet.yiaddr;
00634 LOG(LOG_INFO, "Lease of %s obtained, lease time %ld",
00635 inet_ntoa(temp_addr), lease);
00636 start = now;
00637 dhcp_mobile_array[selected_mobile].timeout = t1 + start;
00638 dhcp_mobile_array[selected_mobile].requested_ip = packet.yiaddr;
00639 run_script(&packet,
00640 ((dhcp_mobile_array[selected_mobile].state == RENEWING || dhcp_mobile_array[selected_mobile].state == REBINDING) ? "renew" : "bound"));
00641
00642 dhcp_mobile_array[selected_mobile].state = BOUND;
00643 change_mode(LISTEN_NONE, selected_mobile);
00644 if (client_config.quit_after_lease){
00645 return dhcp_mobile_array[selected_mobile].requested_ip;
00646 }
00647 if (!client_config.foreground){
00648
00649 return dhcp_mobile_array[selected_mobile].requested_ip;
00650 }
00651
00652 } else if (*message == DHCPNAK) {
00653
00654 LOG(LOG_INFO, "Received DHCP NAK");
00655 run_script(&packet, "nak");
00656 if (dhcp_mobile_array[selected_mobile].state != REQUESTING)
00657 run_script(NULL, "deconfig");
00658 dhcp_mobile_array[selected_mobile].state = INIT_SELECTING;
00659 dhcp_mobile_array[selected_mobile].timeout = now;
00660 dhcp_mobile_array[selected_mobile].requested_ip = 0;
00661 dhcp_mobile_array[selected_mobile].packet_num = 0;
00662 change_mode(LISTEN_RAW, selected_mobile);
00663 sleep(3);
00664 }
00665 break;
00666
00667 }
00668 } else if (retval > 0 && FD_ISSET(dhcp_mobile_array[selected_mobile].signal_pipe[0], &rfds)) {
00669 if (read(dhcp_mobile_array[selected_mobile].signal_pipe[0], &sig, sizeof(signal)) < 0) {
00670 DEBUG(LOG_ERR, "Could not read signal: %s",
00671 strerror(errno));
00672 continue;
00673 }
00674 switch (sig) {
00675 case SIGUSR1:
00676 perform_renew(selected_mobile);
00677 break;
00678 case SIGUSR2:
00679 perform_release(selected_mobile);
00680 break;
00681 case SIGTERM:
00682 LOG(LOG_INFO, "Received SIGTERM");
00683 exit_client(0);
00684 }
00685 } else if (retval == -1 && errno == EINTR) {
00686
00687 } else {
00688
00689 DEBUG(LOG_ERR, "Error on select");
00690 }
00691
00692 }
00693
00694 return 0;
00695 }
00696
00697
00698
00699
00700
00701
00709 static void
00710 set_ha_nai(void)
00711 {
00712 if (ha_nai != NULL) {
00713 free(ha_nai);
00714 ha_nai = NULL;
00715 }
00716 if (config.ha_nai[0] != '\0') {
00717 ha_nai = (struct fa_nai_ext *)
00718 malloc(sizeof(struct fa_nai_ext) +
00719 strlen(config.ha_nai));
00720 if (ha_nai == NULL) {
00721 DEBUG(DEBUG_FLAG, "Not enough memory for ha_nai\n");
00722 clean_up(1);
00723 }
00724 ha_nai->type = VENDOR_EXT_TYPE2;
00725 ha_nai->reserved = 0;
00726 ha_nai->length = sizeof(struct fa_nai_ext) - 2 +
00727 strlen(config.ha_nai);
00728 ha_nai->vendor_id = htonl(VENDOR_ID_DYNAMICS);
00729 ha_nai->sub_type = htons(VENDOR_EXT_DYNAMICS_FA_NAI);
00730 memcpy(ha_nai + 1, config.ha_nai, strlen(config.ha_nai));
00731 }
00732 }
00733
00734
00740 static void
00741 reload_config(int sig)
00742 {
00743 LOG2(LOG_INFO, "Received signal %d, rereading configuration\n", sig);
00744 cleanup_config(&config);
00745
00746 if (load_config(&config, program_name,
00747 opt_config == NULL ? HA_GLOBAL_CONF_FILE : opt_config)
00748 == FALSE) {
00749 LOG2(LOG_ALERT, "Reloading configuration file failed\n");
00750 clean_up(1);
00751 }
00752 init_interfaces();
00753 set_ha_nai();
00754
00755
00756
00757
00758 }
00759
00760
00761
00762
00763
00764
00776 static int
00777 binding_cleanup_iterator(struct node *node, void *dummy)
00778 {
00779 struct bindingentry *data = (struct bindingentry *) node;
00780
00781 ASSERT(data != NULL);
00782
00783 binding_remove(data);
00784 remove_tunnel(data);
00785 destroy_binding(data);
00786
00787 return 1;
00788 }
00789
00790
00796 static void
00797 sig_handler(int sig)
00798 {
00799 LOG2(LOG_INFO, "signal %d received, cleaning up\n", sig);
00800 clean_up(sig);
00801 }
00802
00803
00809 static void
00810 clean_up(int value)
00811 {
00812
00813
00814 if (bindings != NULL) {
00815 binding_iterator(bindings, binding_cleanup_iterator, NULL);
00816 binding_destroy(bindings);
00817 }
00818 if (tunnels != NULL)
00819 tunnel_destroy_hash(tunnels);
00820
00821
00822 if (config.ha_api_read_socket_path[0] != '\0')
00823 unlink(config.ha_api_read_socket_path);
00824 if (config.ha_api_admin_socket_path[0] != '\0')
00825 unlink(config.ha_api_admin_socket_path);
00826
00827 if (unlink(HA_PID_FILE) < 0) {
00828 LOG2(LOG_INFO, "clean_up() could not remove PID file ("
00829 HA_PID_FILE "): %s\n", strerror(errno));
00830 }
00831
00832 cleanup_config(&config);
00833 if (ha_nai != NULL) {
00834 free(ha_nai);
00835 ha_nai = NULL;
00836 }
00837
00838 syslog(LOG_INFO, "%s home agent daemon version %s stopped\n",
00839 PACKAGE, VERSION);
00840
00841 closelog();
00842 exit(value);
00843 }
00844
00845
00846
00847
00848
00860 static int
00861 binding_get_tunnels_iter(struct node *node, void *data)
00862 {
00863 struct bindingentry *binding = (struct bindingentry *) node;
00864 struct api_msg *api_msg = (struct api_msg *) data;
00865 dyn_tunnel_id id;
00866
00867 if (api_msg->length + sizeof(dyn_tunnel_id) > API_DATA_SIZE) {
00868 DEBUG(DEBUG_FLAG, "API message overflow - skipping rest of "
00869 "the bindings\n");
00870 return 0;
00871 }
00872
00873 id.mn_addr.s_addr = binding->mn_addr.s_addr;
00874 id.ha_addr.s_addr = binding->ha_addr.s_addr;
00875 id.priv_ha = 0;
00876
00877 memcpy((char *) api_msg->params + api_msg->length, &id,
00878 sizeof(dyn_tunnel_id));
00879
00880 api_msg->length += sizeof(dyn_tunnel_id);
00881
00882 return 1;
00883 }
00884
00885
00896 static struct bindingentry*
00897 api_fetch_binding(struct api_msg *msg)
00898 {
00899 dyn_tunnel_id *tid;
00900 struct bindingkey bkey;
00901 struct bindingentry *binding;
00902
00903 if (msg->length != sizeof(dyn_tunnel_id)) {
00904 LOG2(LOG_ERR, "API message has wrong length (%i, expected %i)"
00905 "\n", msg->length, sizeof(dyn_tunnel_id));
00906 return NULL;
00907 }
00908 tid = (dyn_tunnel_id *) msg->params;
00909 bkey.mn_addr = tid->mn_addr;
00910 if (config.sha_addr.s_addr != 0)
00911 bkey.ha_addr = config.sha_addr;
00912 else if (tid->ha_addr.s_addr != 0)
00913 bkey.ha_addr = tid->ha_addr;
00914 else {
00915 struct interface_entry *iface;
00916 iface = (struct interface_entry *)
00917 list_get_first(&config.interfaces);
00918 if (iface == NULL)
00919 return NULL;
00920 bkey.ha_addr = iface->addr;
00921 }
00922 bkey.priv_ha = config.priv_ha;
00923 binding = binding_fetch(bindings, &bkey);
00924 if (!binding) {
00925 DEBUG(DEBUG_FLAG, " API call could not find the request "
00926 "binding\n");
00927 }
00928 return binding;
00929 }
00930
00931
00942 static int
00943 handle_api(int socket, int priv)
00944 {
00945 struct sockaddr_un cli_addr;
00946 socklen_t cli_len;
00947 int n;
00948 struct api_msg recv_msg;
00949 struct api_msg send_msg;
00950 struct bindingentry *binding;
00951 struct dynamics_tunnel_info *info;
00952 struct dynamics_ha_status *status;
00953
00954 memset(&cli_addr, 0, sizeof(cli_addr));
00955 cli_len = sizeof(cli_addr);
00956
00957 n = recvfrom(socket, &recv_msg, sizeof(struct api_msg), 0,
00958 (struct sockaddr*)&cli_addr,
00959 &cli_len);
00960
00961 LOG2(LOG_DEBUG, "API: received %d bytes from %s\n", n,
00962 cli_addr.sun_path);
00963
00964 if (n < 0) {
00965 LOG2(LOG_ERR, "handle_api - recvfrom failed - %s\n",
00966 strerror(errno));
00967 return -1;
00968 }
00969
00970 if (priv)
00971 stats.apicalls_admin++;
00972 else
00973 stats.apicalls_read++;
00974
00975 memset(&send_msg, 0, sizeof(struct api_msg));
00976 send_msg.type = API_REPLY_MSG;
00977 send_msg.code = API_UNDEFINED;
00978 send_msg.length = 0;
00979
00980 switch (recv_msg.code) {
00981 case API_GET_TUNNELS:
00982 DEBUG(DEBUG_FLAG, "Received API_GET_TUNNELS\n");
00983 if (recv_msg.length != 0) {
00984 LOG2(LOG_ERR,
00985 "API_GET_TUNNELS message has wrong length\n");
00986 send_msg.code = API_ILLEGAL_PARAMETERS;
00987 break;
00988 }
00989
00990
00991 if (binding_iterator(bindings, binding_get_tunnels_iter,
00992 &send_msg))
00993 send_msg.code = API_SUCCESS;
00994 else
00995 send_msg.code = API_INSUFFICIENT_SPACE;
00996 break;
00997
00998 case API_GET_TUNNEL_INFO:
00999 DEBUG(DEBUG_FLAG, "Received API_GET_TUNNEL_INFO\n");
01000 binding = api_fetch_binding(&recv_msg);
01001 if (!binding) {
01002 send_msg.code = API_FAILED;
01003 break;
01004 }
01005 info = (struct dynamics_tunnel_info *) send_msg.params;
01006 memset(info, 0, sizeof(struct dynamics_tunnel_info));
01007 info->id.mn_addr.s_addr = binding->mn_addr.s_addr;
01008 info->id.ha_addr.s_addr = binding->ha_addr.s_addr;
01009 info->mn_addr.s_addr = binding->mn_addr.s_addr;
01010 info->co_addr.s_addr = binding->lower_addr.s_addr;
01011 info->ha_addr.s_addr = binding->ha_addr.s_addr;
01012 info->expiration_time = binding->exp_time;
01013 info->creation_time = binding->create_time;
01014 info->refresh_time = binding->mod_time;
01015 info->last_timestamp[0] = ntohl(binding->id[0]);
01016 info->last_timestamp[1] = ntohl(binding->id[1]);
01017 info->spi = binding->spi;
01018 info->confirmed = 1;
01019 info->timeout = binding->timeout;
01020 send_msg.code = API_SUCCESS;
01021 send_msg.length = sizeof(struct dynamics_tunnel_info);
01022 break;
01023
01024 case API_DESTROY_TUNNEL:
01025 DEBUG(DEBUG_FLAG, "Received API_DESTROY_TUNNEL\n");
01026 if (!priv) {
01027 send_msg.code = API_NOT_PERMITTED;
01028 break;
01029 }
01030 binding = api_fetch_binding(&recv_msg);
01031 if (!binding) {
01032 send_msg.code = API_FAILED;
01033 break;
01034 }
01035 binding_remove(binding);
01036 remove_tunnel(binding);
01037 destroy_binding(binding);
01038 send_msg.length = 0;
01039 send_msg.code = API_SUCCESS;
01040 LOG2(LOG_NOTICE, "API call removed binding for MN %s\n",
01041 inet_ntoa(binding->mn_addr));
01042 break;
01043
01044 case API_GET_STATUS:
01045 DEBUG(DEBUG_FLAG, "Received API_GET_STATUS\n");
01046 if (recv_msg.length != 0) {
01047 LOG2(LOG_ERR, "API_GET_STATUS message has wrong "
01048 "length\n");
01049 break;
01050 }
01051 status = (struct dynamics_ha_status *) send_msg.params;
01052 memcpy(status, &stats, sizeof(struct dynamics_ha_status));
01053 UNALIGNED_(&status->tunnel_count, &bindingcount);
01054 send_msg.length = sizeof(struct dynamics_ha_status);
01055 send_msg.code = API_SUCCESS;
01056 break;
01057
01058 case API_RELOAD_CONFIG:
01059
01060 DEBUG(DEBUG_FLAG, "Received API_RELOAD_CONFIG\n");
01061 if (!priv) {
01062 send_msg.code = API_NOT_PERMITTED;
01063 break;
01064 }
01065 reload_config(1);
01066 DEBUG(DEBUG_FLAG, "Configuration_reloaded\n");
01067 send_msg.code = API_SUCCESS;
01068 break;
01069
01070 default:
01071 LOG2(LOG_ERR, "Received unknown API command: %d\n",
01072 recv_msg.code);
01073 send_msg.code = API_NOT_SUPPORTED;
01074 break;
01075 }
01076
01077 return api_send(socket, &cli_addr, cli_len, &send_msg);
01078 }
01079
01080
01081
01082
01083
01094 static int
01095 pubkey_hash_ok(struct msg_key *pubkey, struct msg_key *hash)
01096 {
01097 unsigned char mac[MD5_MAC_LEN];
01098
01099 if (GET_KEY_LEN(hash) != MD5_MAC_LEN) {
01100 DEBUG(DEBUG_FLAG, "pubkey_hash_ok: invalid hash length: %i, "
01101 "expected %i\n", GET_KEY_LEN(hash), MD5_MAC_LEN);
01102 return 0;
01103 }
01104
01105 md5_mac((unsigned char *) "", 0, (unsigned char *) pubkey,
01106 GET_KEY_EXT_LEN(pubkey), mac);
01107 return (memcmp(mac, MSG_KEY_DATA(hash), MD5_MAC_LEN) == 0);
01108 }
01109
01110
01121 static int
01122 check_fa_auth_ext(struct in_addr addr, const struct msg_extensions *ext)
01123 {
01124
01125 struct fa_spi_entry *fa_spi;
01126
01127 fa_spi = get_fa_spi(0, addr);
01128 if (fa_spi == NULL) {
01129
01130
01131 if (ext->fh_auth != NULL) {
01132 DEBUG(DEBUG_FLAG, "No FA-HA security association, but "
01133 "request had FA-HA authentication extension\n");
01134 return 1;
01135 }
01136 return 0;
01137 }
01138
01139 if (ext->fh_auth == NULL && ext->sha_ha_auth != NULL &&
01140 config.sha_addr.s_addr != 0) {
01141 DEBUG(DEBUG_FLAG, "Checking sha_ha_auth\n");
01142 if (auth_check_vendor(fa_spi->alg, fa_spi->shared_secret,
01143 fa_spi->shared_secret_len,
01144 (unsigned char *) ext->req,
01145 ext->sha_ha_auth))
01146 return 0;
01147 return 1;
01148 }
01149
01150 DEBUG(DEBUG_FLAG, "Checking fh_auth\n");
01151 if (ext->fh_auth == NULL ||
01152 !auth_check(fa_spi->alg, fa_spi->shared_secret,
01153 fa_spi->shared_secret_len, (unsigned char *) ext->req,
01154 ext->fh_auth))
01155 return 1;
01156 else
01157 return 0;
01158 }
01159
01160
01190 #define AUTH_MAC_RFC2002 -100
01191
01192 static struct spi_entry *
01193 validate_request(struct bindingentry *binding, struct in_addr faaddr,
01194 const char *msg, int msg_len,
01195 const struct msg_extensions *ext, int *code, int *auth_type)
01196 {
01197 struct node *node;
01198 struct spi_entry *spi = NULL;
01199 time_t current_time;
01200 enum { NOT_FOUND, UNICAST_FOUND, BROADCAST_FOUND } own_addr_found;
01201 struct authorized_entry *auth = NULL;
01202 char faaddrstr[16];
01203 char mnaddrstr[16];
01204 struct ha_tunnel_data *t_data = NULL;
01205
01206 if (binding != NULL)
01207 t_data = (struct ha_tunnel_data *) binding->data;
01208 dynamics_strlcpy(faaddrstr, inet_ntoa(faaddr), sizeof(faaddrstr));
01209
01210
01211 *code = REGREP_ACCEPTED;
01212 *auth_type = 0;
01213
01214
01215 if (ext->req == NULL || ext->mh_auth == NULL) {
01216 LOG2(LOG_WARNING,
01217 "FA %s: message does not contain either request "
01218 "and/or message authentication\n", faaddrstr);
01219 if (ext->mh_auth == NULL)
01220 *code = REGREP_MN_FAILED_AUTH_HA;
01221 else
01222 *code = REGREP_BAD_REQUEST_HA;
01223 return NULL;
01224 }
01225
01226 dynamics_strlcpy(mnaddrstr, inet_ntoa(ext->req->home_addr),
01227 sizeof(mnaddrstr));
01228
01229
01230
01231
01232
01233
01234 for (node = list_get_first(&config.authorized_list); node != NULL;
01235 node = list_get_next(node)) {
01236 auth = (struct authorized_entry *) node;
01237 if (ntohl(ext->mh_auth->spi) >= auth->spi_low &&
01238 ntohl(ext->mh_auth->spi) <= auth->spi_high) {
01239 break;
01240 }
01241 }
01242
01243 if (node == NULL) {
01244 LOG2(LOG_WARNING, "FA %s, MN %s: Not authorized\n",
01245 faaddrstr, mnaddrstr);
01246 *code = REGREP_ADMIN_PROHIBITED_HA;
01247 return NULL;
01248 }
01249
01250
01251 spi = get_mn_spi(ntohl(ext->mh_auth->spi));
01252 if (spi == NULL) {
01253 LOG2(LOG_WARNING, "FA %s, MN %s: SPI %d not found\n",
01254 faaddrstr, mnaddrstr, ntohl(ext->mh_auth->spi));
01255 *code = REGREP_MN_FAILED_AUTH_HA;
01256 return NULL;
01257 }
01258
01259 if (!auth_check(spi->auth_alg, spi->shared_secret,
01260 spi->shared_secret_len,
01261 (unsigned char *) msg, ext->mh_auth)) {
01262 if (spi->auth_alg != AUTH_ALG_MD5 ||
01263 !auth_check(AUTH_ALG_MD5_RFC2002, spi->shared_secret,
01264 spi->shared_secret_len,
01265 (unsigned char *) msg, ext->mh_auth)) {
01266 LOG2(LOG_WARNING, "FA %s, MN %s, SPI %d: Invalid MN-HA"
01267 " authentication extension\n",
01268 faaddrstr, mnaddrstr, spi->spi);
01269 *code = REGREP_MN_FAILED_AUTH_HA;
01270 return spi;
01271 } else {
01272
01273 DEBUG(DEBUG_FLAG, "RFC 2002 MAC calculation "
01274 "detected - trying to use the same method\n");
01275 *auth_type = AUTH_MAC_RFC2002;
01276 }
01277 }
01278
01279 if (ext->double_auth_ext > 0) {
01280 LOG2(LOG_WARNING, "FA %s, MN %s: duplicate authentication "
01281 "extension\n", faaddrstr, mnaddrstr);
01282 if (ext->double_auth_ext & DOUBLE_MH_AUTH)
01283 *code = REGREP_MN_FAILED_AUTH_HA;
01284 else if (ext->double_auth_ext & DOUBLE_FH_AUTH)
01285 *code = REGREP_FA_FAILED_AUTH_HA;
01286 else
01287 *code = REGREP_REASON_UNSPEC_HA;
01288 return spi;
01289 }
01290
01291
01292 if (check_fa_auth_ext(faaddr, ext) != 0) {
01293 LOG2(LOG_WARNING, "FA %s, MN %s: invalid/missing fh_auth\n",
01294 faaddrstr, mnaddrstr);
01295 *code = REGREP_FA_FAILED_AUTH_HA;
01296 return spi;
01297 }
01298
01299
01300 if (!auth_is_protected(ext->pubkey_hash, ext->mh_auth) ||
01301 !auth_is_protected(ext->priv_ha, ext->mh_auth) ||
01302 !auth_is_protected(ext->mn_keyreq, ext->mh_auth) ||
01303 !auth_is_protected(ext->mn_nai, ext->mh_auth)) {
01304 LOG2(LOG_WARNING, "FA %s, MN %s: MN-HA auth. ext. does not "
01305 "protect all the required extensions\n",
01306 faaddrstr, mnaddrstr);
01307 *code = REGREP_MN_FAILED_AUTH_HA;
01308 }
01309
01310
01311 if (ext->mn_fa_key_req_aaa != NULL &&
01312 (ext->mn_aaa_auth == NULL ||
01313 !auth_is_protected(ext->mn_fa_key_req_aaa, ext->mn_aaa_auth))) {
01314 LOG2(LOG_WARNING, "FA %s, MN %s: MN-AAA auth. ext. does not "
01315 "protect MN-FA keyreq from AAA extensions\n",
01316 faaddrstr, mnaddrstr);
01317 *code = REGREP_MN_FAILED_AUTH_HA;
01318 }
01319 if (ext->mn_ha_key_req_aaa != NULL &&
01320 (ext->mn_aaa_auth == NULL ||
01321 !auth_is_protected(ext->mn_ha_key_req_aaa, ext->mn_aaa_auth))) {
01322 LOG2(LOG_WARNING, "FA %s, MN %s: MN-AAA auth. ext. does not "
01323 "protect MN-HA keyreq from AAA extensions\n",
01324 faaddrstr, mnaddrstr);
01325 *code = REGREP_MN_FAILED_AUTH_HA;
01326 }
01327
01328 if (ext->fh_auth != NULL &&
01329 !auth_is_protected(ext->challenge, ext->fh_auth)) {
01330 LOG2(LOG_WARNING, "FA %s, MN %s: FA-HA auth. ext. does not "
01331 "protect all the required extensions\n",
01332 faaddrstr, mnaddrstr);
01333 *code = REGREP_FA_FAILED_AUTH_HA;
01334 }
01335
01336
01337 own_addr_found = NOT_FOUND;
01338 for (node = list_get_first(&config.interfaces); node != NULL;
01339 node = list_get_next(node)) {
01340 struct interface_entry *iface =
01341 (struct interface_entry *) node;
01342 if (iface->addr.s_addr == ext->req->ha_addr.s_addr) {
01343 own_addr_found = UNICAST_FOUND;
01344 break;
01345 }
01346 if (iface->ha_disc &&
01347 iface->bcaddr.s_addr == ext->req->ha_addr.s_addr) {
01348 own_addr_found = BROADCAST_FOUND;
01349 break;
01350 }
01351 }
01352
01353 if (own_addr_found != 1 &&
01354 (config.sha_addr.s_addr == 0 ||
01355 ext->req->ha_addr.s_addr != config.sha_addr.s_addr)) {
01356 if (own_addr_found == BROADCAST_FOUND)
01357 DEBUG(DEBUG_FLAG,
01358 "==> HA discovery, deny with unknown HA\n");
01359 else
01360 LOG2(LOG_WARNING, "FA %s, MN %s: HA address does not "
01361 "match\n", faaddrstr, mnaddrstr);
01362 *code = REGREP_UNKNOWN_HA_HA;
01363 return spi;
01364 }
01365
01366
01367 if (ext->req->opts & REGREQ_SIMULTANEOUS_BINDINGS) {
01368 LOG2(LOG_INFO,
01369 "FA %s, MN %s: Received request for unsupported "
01370 "simultaneous_bindings\n", faaddrstr, mnaddrstr);
01371
01372 *code = REGREP_ACCEPTED_NO_SB;
01373 }
01374
01375 current_time = time(NULL);
01376 if (spi->replay_method == REPLAY_PROTECTION_TIMESTAMP &&
01377 (ntohl(ext->req->id[0]) < current_time + UNIX_NTP_DIFF -
01378 spi->timestamp_tolerance ||
01379 ntohl(ext->req->id[0]) > current_time + UNIX_NTP_DIFF +
01380 spi->timestamp_tolerance)) {
01381 time_t t;
01382 t = ntohl(ext->req->id[0]) - UNIX_NTP_DIFF;
01383 LOG2(LOG_WARNING, "ID mismatch - timestamp difference=%i, "
01384 "tolerance=%i\n", abs(t - current_time),
01385 spi->timestamp_tolerance);
01386 *code = REGREP_ID_MISMATCH_HA;
01387 } else if (spi->replay_method == REPLAY_PROTECTION_NONCE &&
01388 t_data != NULL && ext->req->id[0] != t_data->nonce) {
01389 LOG2(LOG_WARNING, "ID mismatch (nonce)\n");
01390 DEBUG(DEBUG_FLAG, "\treq->id: %08x, expected nonce %08x\n",
01391 ext->req->id[0], t_data->nonce);
01392 *code = REGREP_ID_MISMATCH_HA;
01393 }
01394
01395 if (ext->req->opts & REGREQ_BROADCAST_DATAGRAMS) {
01396 DEBUG(LOG_INFO,
01397 "FA %s, MN %s: Received request for unsupported "
01398 "broadcast message forwarding\n", faaddrstr, mnaddrstr);
01399
01400
01401
01402
01403 }
01404
01405
01406 if (ext->req->opts & (REGREQ_MINIMAL_ENCAPS | REGREQ_GRE_ENCAPS)) {
01407 LOG2(LOG_INFO, "FA %s, MN %s: Received unsupported option "
01408 "request (opts=0x%02x)\n", faaddrstr, mnaddrstr,
01409 ext->req->opts);
01410
01411
01412 if ((ext->req->opts & REGREQ_REVERSE_TUNNEL) != 0)
01413 *code = REGREP_ENCAP_UNAVAIL_HA;
01414 else
01415 *code = REGREP_REASON_UNSPEC_HA;
01416 return spi;
01417 }
01418
01419 if (!config.enable_reverse_tunneling &&
01420 (ext->req->opts & REGREQ_REVERSE_TUNNEL) != 0) {
01421 LOG2(LOG_INFO,
01422 "FA %s, MN %s: Asked forbidden reverse tunneling\n",
01423 faaddrstr, mnaddrstr);
01424 *code = REGREP_REVERSE_TUNNEL_UNAVAIL_HA;
01425 return spi;
01426 }
01427
01428 if (!config.enable_triangle_tunneling &&
01429 (ext->req->opts & REGREQ_REVERSE_TUNNEL) == 0) {
01430 LOG2(LOG_INFO,
01431 "FA %s, MN %s: Reverse tunneling mandatory\n",
01432 faaddrstr, mnaddrstr);
01433 *code = REGREP_REVERSE_TUNNEL_MANDATORY_HA;
01434 return spi;
01435 }
01436
01437 if (ext->req->opts & REGREQ_RESERVED) {
01438 LOG2(LOG_INFO, "FA %s, MN %s: Received a request with non-zero"
01439 " reserved field\n", faaddrstr, mnaddrstr);
01440 *code = REGREP_BAD_REQUEST_HA;
01441 return spi;
01442 }
01443
01444 if (config.pubkey_hash_method == HASH_METHOD_REQUIRE &&
01445 ext->fa_pubkey != NULL && ext->pubkey_hash == NULL) {
01446 LOG2(LOG_INFO, "FA %s, MN %s: Received a request with public "
01447 "key, but without public key hash extension\n",
01448 faaddrstr, mnaddrstr);
01449 *code = REGREP_ADMIN_PROHIBITED_HA;
01450 return spi;
01451 }
01452
01453 if (config.pubkey_hash_method != HASH_METHOD_NONE &&
01454 ext->fa_pubkey != NULL &&
01455 ext->pubkey_hash != NULL &&
01456 !pubkey_hash_ok(ext->fa_pubkey, ext->pubkey_hash)) {
01457 LOG2(LOG_INFO, "FA %s, MN %s: Received a request with public "
01458 "key and mismatching public key hash extension\n",
01459 faaddrstr, mnaddrstr);
01460 *code = REGREP_ADMIN_PROHIBITED_HA;
01461 return spi;
01462 }
01463
01464
01465 return spi;
01466 }
01467
01468
01479 static int
01480 new_session_key(struct bindingentry *binding, struct spi_entry *mn_spi)
01481 {
01482 #ifndef NODEBUGMODE
01483 int i;
01484 #endif
01485
01486
01487
01488 if (binding->last_sent_fa_pubkeyrep)
01489 free(binding->last_sent_fa_pubkeyrep);
01490 binding->last_sent_fa_pubkeyrep = NULL;
01491
01492
01493 binding->keylen =
01494 generate_session_key(mn_spi->auth_alg, mn_spi->shared_secret,
01495 mn_spi->shared_secret_len, binding->key);
01496 if (binding->keylen == -1) {
01497 LOG2(LOG_ERR, "Could not generate session key\n");
01498 return -1;
01499 }
01500
01501 #ifndef NODEBUGMODE
01502 DEBUG(DEBUG_FLAG, "Session key: ");
01503 for (i = 0; i < binding->keylen; i++)
01504 DEBUG(DEBUG_FLAG, "%02x", binding->key[i]);
01505 DEBUG(DEBUG_FLAG, "\n");
01506 #endif
01507
01508 return 0;
01509 }
01510
01511
01512 struct gratuitous_arp_data {
01513 struct gratuitous_arp_data *next;
01514 struct timeval tv;
01515 struct in_addr addr;
01516 char interface[IFNAMSIZ + 1];
01517 };
01518
01519 static struct gratuitous_arp_data *gratuitous_arp_queue = NULL;
01520
01521
01529 static void
01530 send_gratuitous_arp(struct in_addr addr, char *interface)
01531 {
01532 struct gratuitous_arp_data *arp2, *arp3, *arp;
01533
01534
01535
01536
01537
01538 proxyarp_gratuitous(addr, interface);
01539
01540 arp2 = (struct gratuitous_arp_data *)
01541 malloc(sizeof(struct gratuitous_arp_data));
01542 arp3 = (struct gratuitous_arp_data *)
01543 malloc(sizeof(struct gratuitous_arp_data));
01544 if (arp2 == NULL || arp3 == NULL) {
01545 DEBUG(DEBUG_FLAG, "send_gratuitous_arp: malloc() failed\n");
01546 if (arp2 != NULL)
01547 free(arp2);
01548 if (arp3 != NULL)
01549 free(arp3);
01550 return;
01551 }
01552
01553
01554 memset(arp2, 0, sizeof(struct gratuitous_arp_data));
01555 gettimeofday(&arp2->tv, NULL);
01556 add_usecs(&arp2->tv, 100000);
01557 arp2->addr.s_addr = addr.s_addr;
01558 dynamics_strlcpy(arp2->interface, interface, sizeof(arp2->interface));
01559
01560
01561 memcpy(arp3, arp2, sizeof(struct gratuitous_arp_data));
01562 add_usecs(&arp3->tv, 100000);
01563
01564 DEBUG(DEBUG_FLAG, "send_gratuitous_arp - adding packet to queue at "
01565 "%li.%06li and %li.%06li\n", arp2->tv.tv_sec, arp2->tv.tv_usec,
01566 arp3->tv.tv_sec, arp3->tv.tv_usec);
01567
01568 if (gratuitous_arp_queue == NULL) {
01569
01570 gratuitous_arp_queue = arp2;
01571 arp2->next = arp3;
01572 arp3->next = NULL;
01573 return;
01574 }
01575
01576 if (cmp_timeval(&gratuitous_arp_queue->tv, &arp2->tv) > 0) {
01577
01578 arp2->next = gratuitous_arp_queue;
01579 gratuitous_arp_queue = arp2;
01580 } else {
01581
01582 arp = gratuitous_arp_queue;
01583 while (arp->next != NULL &&
01584 cmp_timeval(&arp->next->tv, &arp2->tv) <= 0)
01585 arp = arp->next;
01586 arp2->next = arp->next;
01587 arp->next = arp2;
01588 }
01589
01590
01591 arp = arp2;
01592 while (arp->next != NULL &&
01593 cmp_timeval(&arp->next->tv, &arp3->tv) <= 0)
01594 arp = arp->next;
01595 arp3->next = arp->next;
01596 arp->next = arp3;
01597 }
01598
01599
01605 static void
01606 check_queued_gratuitous_arp(void)
01607 {
01608 struct timeval now;
01609 struct gratuitous_arp_data *arp;
01610
01611 if (gratuitous_arp_queue == NULL)
01612 return;
01613
01614 gettimeofday(&now, NULL);
01615 while (gratuitous_arp_queue != NULL &&
01616 cmp_timeval(&gratuitous_arp_queue->tv, &now) <= 0) {
01617 arp = gratuitous_arp_queue;
01618 DEBUG(DEBUG_FLAG, "Sending queued gratuitous ARP "
01619 "(tv=%li.%06li addr=%s interface=%s)\n",
01620 arp->tv.tv_sec, arp->tv.tv_usec, inet_ntoa(arp->addr),
01621 arp->interface);
01622 proxyarp_gratuitous(arp->addr, arp->interface);
01623 gratuitous_arp_queue = arp->next;
01624 free(arp);
01625 }
01626 if (gratuitous_arp_queue == NULL)
01627 DEBUG(DEBUG_FLAG, "Gratuitous ARP queue empty.\n");
01628 else
01629 DEBUG(DEBUG_FLAG, "Entries remaining in gratuitous ARP queue "
01630 "(next at %li.%06li)\n",
01631 gratuitous_arp_queue->tv.tv_sec,
01632 gratuitous_arp_queue->tv.tv_usec);
01633 }
01634
01635
01648 static struct bindingentry *
01649 create_binding(struct msg_extensions *ext, struct spi_entry *mn_spi,
01650 int create_tunnels)
01651 {
01652 struct bindingentry *binding;
01653 struct ha_tunnel_data *t_data;
01654 char mn_addrstr[17];
01655 char co_addrstr[17];
01656 int ok = TRUE;
01657
01658 DEBUG(DEBUG_FLAG, "Creating a new binding for MN\n");
01659
01660 ASSERT(ext != NULL && ext->req != NULL);
01661 ASSERT(mn_spi != NULL);
01662 if (bindingcount >= config.max_bindings) {
01663 LOG2(LOG_WARNING, "max bindings reached\n");
01664 return NULL;
01665 }
01666
01667
01668 binding = malloc(sizeof(struct bindingentry));
01669 if (binding == NULL) {
01670 LOG2(LOG_ERR, "malloc[binding] - %s\n", strerror(errno));
01671 return NULL;
01672 }
01673 memset(binding, 0, sizeof(struct bindingentry));
01674 binding->data = malloc(sizeof(struct ha_tunnel_data));
01675 if (binding->data == NULL) {
01676 LOG2(LOG_ERR, "malloc[ha_tunnel_data] - %s\n",
01677 strerror(errno));
01678 free(binding);
01679 return NULL;
01680 }
01681 memset(binding->data, 0, sizeof(struct ha_tunnel_data));
01682 t_data = (struct ha_tunnel_data *) binding->data;
01683
01684 binding->spi = mn_spi->spi;
01685
01686 if ((ext->fa_keyreq || ext->fa_pubkey || ext->mn_keyreq) &&
01687 new_session_key(binding, mn_spi) < 0)
01688 ok = FALSE;
01689
01690 binding->mn_addr.s_addr = ext->req->home_addr.s_addr;
01691 binding->ha_addr.s_addr = ext->req->ha_addr.s_addr;
01692 binding->priv_ha = config.priv_ha;
01693 binding->lower_addr.s_addr = config.sha_addr.s_addr != 0 ?
01694 config.sha_addr.s_addr : ext->req->co_addr.s_addr;
01695 dynamics_strlcpy(mn_addrstr, inet_ntoa(ext->req->home_addr),
01696 sizeof(mn_addrstr));
01697 dynamics_strlcpy(co_addrstr, inet_ntoa(ext->req->co_addr),
01698 sizeof(co_addrstr));
01699 memcpy(&binding->id, ext->req->id, REG_REQ_ID_LEN);
01700 binding->create_time = time(NULL);
01701
01702 if (ok && create_tunnels &&
01703 tunnel_add(tunnels, binding->lower_addr, binding->tun_dev,
01704 ext->req->ha_addr, 1, TUNNEL_IPIP, 0) == NULL) {
01705 LOG2(LOG_ERR, "Could not add tunnel to FA %s (COA=%s) for "
01706 "MN %s\n", inet_ntoa(binding->lower_addr), co_addrstr,
01707 mn_addrstr);
01708 ok = FALSE;
01709 }
01710
01711 if (ok && create_tunnels &&
01712 dyn_ip_route_get(binding->mn_addr, t_data->arp_if, IFNAMSIZ)
01713 != 0) {
01714 LOG2(LOG_ERR, "Could not get arp interface for MN %s\n",
01715 mn_addrstr);
01716 ok = FALSE;
01717 }
01718
01719 if (ok && create_tunnels &&
01720 dyn_ip_route_replace(binding->mn_addr, binding->tun_dev) != 0) {
01721 LOG2(LOG_ERR, "Could not add route to MN %s\n",
01722 mn_addrstr);
01723 ok = FALSE;
01724 }
01725
01726 if (!ok) {
01727 free(binding->data);
01728 free(binding);
01729 return NULL;
01730 }
01731
01732 if (create_tunnels) {
01733 DEBUG(DEBUG_FLAG, "tunnel_add => tun_dev=[%s]\n",
01734 binding->tun_dev);
01735 DEBUG(DEBUG_FLAG, "dyn_ip_route_get: %s => %s\n",
01736 inet_ntoa(binding->mn_addr), t_data->arp_if);
01737 proxyarp_add_item(binding->mn_addr, t_data->arp_if);
01738 send_gratuitous_arp(binding->mn_addr, t_data->arp_if);
01739 }
01740
01741 bindingcount++;
01742 return binding;
01743 }
01744
01745
01753 static void
01754 remove_tunnel(struct bindingentry *binding)
01755 {
01756 struct ha_tunnel_data *t_data;
01757
01758 ASSERT(binding != NULL && binding->data != NULL);
01759
01760 t_data = (struct ha_tunnel_data *) binding->data;
01761 if (dyn_ip_route_del(binding->mn_addr, binding->tun_dev) < 0)
01762 LOG2(LOG_WARNING, "remove_tunnel: dyn_ip_route_del failed\n");
01763 if (tunnel_delete(tunnels, binding->lower_addr, 0, TUNNEL_IPIP, 0) < 0)
01764 LOG2(LOG_WARNING, "remove_tunnel: tunnel_delete failed\n");
01765 if (proxyarp_del_item(binding->mn_addr, t_data->arp_if) < 0)
01766 LOG2(LOG_WARNING, "remove_tunnel: proxyarp_del_item failed\n");
01767 }
01768
01769
01781 static int
01782 switch_tunnel(struct bindingentry *binding, struct msg_extensions *ext,
01783 struct spi_entry *mn_spi)
01784 {
01785 char mn_addrstr[17];
01786 char co_addrstr[17];
01787 char old_lower_tunl[IFNAMSIZ];
01788
01789 ASSERT(binding != NULL && ext != NULL && ext->req != NULL);
01790
01791 dynamics_strlcpy(mn_addrstr, inet_ntoa(ext->req->home_addr),
01792 sizeof(mn_addrstr));
01793 dynamics_strlcpy(co_addrstr, inet_ntoa(ext->req->co_addr),
01794 sizeof(co_addrstr));
01795 memcpy(old_lower_tunl, binding->tun_dev, IFNAMSIZ);
01796
01797
01798 if (tunnel_delete(tunnels, binding->lower_addr, 0, TUNNEL_IPIP, 0) < 0)
01799 {
01800 LOG2(LOG_ERR,
01801 "Could not delete old tunnel to FA %s for MN %s\n",
01802 co_addrstr, mn_addrstr);
01803 }
01804
01805 binding->lower_addr = config.sha_addr.s_addr != 0 ?
01806 config.sha_addr : ext->req->co_addr;
01807
01808
01809 if (tunnel_add(tunnels, binding->lower_addr, binding->tun_dev,
01810 ext->req->ha_addr, 1, TUNNEL_IPIP, 0) == NULL) {
01811 LOG2(LOG_ERR, "Could not add tunnel to FA %s (COA=%s) for "
01812 "MN %s\n", inet_ntoa(binding->lower_addr), co_addrstr,
01813 mn_addrstr);
01814 destroy_binding(binding);
01815 return -1;
01816 }
01817 DEBUG(DEBUG_FLAG, "tunnel_add => tun_dev=[%s]\n", binding->tun_dev);
01818
01819 if (dyn_ip_route_replace(binding->mn_addr, binding->tun_dev) != 0) {
01820 LOG2(LOG_WARNING,
01821 "Route replace failed (COA=%s, MN=%s, dev=%s)\n",
01822 co_addrstr, mn_addrstr, binding->tun_dev)
01823 }
01824
01825 if ((ext->fa_keyreq || ext->fa_pubkey || ext->mn_keyreq) &&
01826 new_session_key(binding, mn_spi) < 0) {
01827 destroy_binding(binding);
01828 return -1;
01829 }
01830
01831 return 0;
01832 }
01833
01834
01842 static void
01843 destroy_binding(struct bindingentry *binding)
01844 {
01845 if (binding->data)
01846 free(binding->data);
01847 if (binding->fa_pubkey)
01848 free(binding->fa_pubkey);
01849 if (binding->last_sent_fa_pubkeyrep)
01850 free(binding->last_sent_fa_pubkeyrep);
01851 free(binding);
01852 bindingcount--;
01853 }
01854
01855
01862 static void
01863 check_bindings(void)
01864 {
01865 struct bindingentry *binding;
01866 time_t diff;
01867 static int first_time = 1;
01868 static time_t advance_expire_time;
01869 time_t time2;
01870
01871 if (first_time) {
01872 advance_expire_time = time(NULL);
01873 first_time = 0;
01874 }
01875 time2 = time(NULL);
01876 diff = time2 - advance_expire_time;
01877 advance_expire_time = time2;
01878 if (diff < 0) {
01879 DEBUG(DEBUG_FLAG,
01880 "check_bindings: diff(%li) < 0 - system time changed?\n",
01881 diff);
01882 diff = 0;
01883 }
01884 binding = binding_getexpired(bindings, diff);
01885 while (binding != NULL) {
01886 DEBUG(DEBUG_FLAG, "Binding to MN %s expired\n",
01887 inet_ntoa(binding->mn_addr));
01888 remove_tunnel(binding);
01889 destroy_binding(binding);
01890 binding = binding_getexpired(bindings, 0);
01891 }
01892 }
01893
01894
01907 static struct fa_spi_entry *
01908 get_fa_spi(int spi, struct in_addr addr)
01909 {
01910 struct fa_spi_entry *s;
01911 struct node *node;
01912
01913 for (node = list_get_first(&config.fa_spi_list); node != NULL;
01914 node = list_get_next(node)) {
01915 s = (struct fa_spi_entry *) node;
01916 if ((spi == 0 || s->spi == spi) &&
01917 s->addr.s_addr == addr.s_addr) {
01918 return s;
01919 }
01920 }
01921 return NULL;
01922 }
01923
01924
01934 static struct spi_entry *
01935 get_mn_spi(int spi)
01936 {
01937 struct spi_entry *s;
01938 struct node *node;
01939
01940 for (node = list_get_first(&config.spi_list); node != NULL;
01941 node = list_get_next(node)) {
01942 s = (struct spi_entry *) node;
01943 if (s->spi == spi)
01944 return s;
01945 }
01946 return NULL;
01947 }
01948
01949
01968 static int
01969 ha_add_ext_start(unsigned char *start, unsigned char *pos, int left,
01970 struct msg_extensions *ext, int lifetime,
01971 struct spi_entry *mn_spi, struct bindingentry *binding,
01972 int auth_type)
01973 {
01974 int used = 0, n;
01975
01976 if (config.priv_ha > 0) {
01977 struct priv_ha_ext *priv = (struct priv_ha_ext *) (pos + used);
01978 DEBUG(DEBUG_FLAG, " * priv_ha\n");
01979 if (left < sizeof(struct priv_ha_ext))
01980 return -1;
01981 memset(priv, 0, sizeof(struct priv_ha_ext));
01982 priv->type = VENDOR_EXT_TYPE2;
01983 priv->length = sizeof(struct priv_ha_ext) - 2;
01984 priv->vendor_id = htonl(VENDOR_ID_DYNAMICS);
01985 priv->sub_type = htons(VENDOR_EXT_DYNAMICS_PRIV_HA);
01986 priv->priv_ha = htonl(config.priv_ha);
01987 used += GET_PRIV_HA_EXT_LEN(priv);
01988 left -= GET_PRIV_HA_EXT_LEN(priv);
01989 }
01990
01991
01992 if (ext != NULL && ext->mn_nai != NULL) {
01993 DEBUG(DEBUG_FLAG, " * mn_nai\n");
01994 if (left < GET_MN_NAI_EXT_LEN(ext->mn_nai))
01995 return -1;
01996 memcpy(pos + used, ext->mn_nai,
01997 GET_MN_NAI_EXT_LEN(ext->mn_nai));
01998 used += GET_MN_NAI_EXT_LEN(ext->mn_nai);
01999 left -= GET_MN_NAI_EXT_LEN(ext->mn_nai);
02000 }
02001
02002
02003
02004 if (ext && ext->mn_keyreq != NULL && mn_spi && lifetime != 0) {
02005 struct msg_key *key;
02006 DEBUG(DEBUG_FLAG, " * mn_keyrep\n");
02007 if (left < sizeof(struct msg_key) + MAX_SK_LEN)
02008 return -1;
02009 key = (struct msg_key *) (pos + used);
02010 n = auth_encrypt(mn_spi->auth_alg, mn_spi->shared_secret,
02011 mn_spi->shared_secret_len, binding->key,
02012 key, (struct reg_rep *) start,
02013 VENDOR_EXT_DYNAMICS_MN_KEYREP,
02014 htonl(mn_spi->spi));
02015 used += n;
02016 left -= n;
02017 }
02018
02019 if (ext && mn_spi) {
02020 struct msg_auth *auth;
02021 DEBUG(DEBUG_FLAG, " * mh_auth\n");
02022 if (left < sizeof(struct msg_auth) + MAX_SK_LEN)
02023 return -1;
02024
02025 auth = (struct msg_auth *) (pos + used);
02026 n = auth_add((auth_type == AUTH_RFC2002BIS ?
02027 AUTH_ALG_MD5_RFC2002 : mn_spi->auth_alg),
02028 mn_spi->shared_secret,
02029 mn_spi->shared_secret_len, start,
02030 (struct msg_auth *) (pos + used), MH_AUTH,
02031 htonl(mn_spi->spi));
02032 used += n;
02033 left -= n;
02034 }
02035
02036
02037
02038
02039 if (ext != NULL && ext->challenge != NULL) {
02040 DEBUG(DEBUG_FLAG, " * challenge\n");
02041 n = GET_CHALLENGE_EXT_LEN(ext->challenge);
02042 if (left < n)
02043 return -1;
02044 memcpy(pos + used, ext->challenge, n);
02045 used += n;
02046 left -= n;
02047 }
02048
02049 return used;
02050 }
02051
02052
02068 static int
02069 ha_add_ext_end(unsigned char *start, unsigned char *pos, struct in_addr addr,
02070 int left, struct msg_extensions *ext)
02071 {
02072 struct fa_spi_entry *fa_spi;
02073 int used = 0;
02074
02075 if (config.priv_ha && ext && ext->nonce) {
02076 if (ext->nonce->length != sizeof(struct nonce_ext) - 2) {
02077 DEBUG(DEBUG_FLAG, " - invalid nonce ext len\n");
02078 } else {
02079 DEBUG(DEBUG_FLAG, " * nonce\n");
02080 if (left < GET_NONCE_EXT_LEN(ext->nonce))
02081 return -1;
02082 memcpy(pos + used, ext->nonce,
02083 GET_NONCE_EXT_LEN(ext->nonce));
02084 used += GET_NONCE_EXT_LEN(ext->nonce);
02085 left -= GET_NONCE_EXT_LEN(ext->nonce);
02086 }
02087 }
02088
02089 fa_spi = get_fa_spi(0, addr);
02090 if (fa_spi != NULL && config.priv_ha > 0) {
02091 DEBUG(DEBUG_FLAG, " * sha_ha_auth\n");
02092 if (left < sizeof(struct vendor_msg_auth) + MAX_SK_LEN)
02093 return -1;
02094 used += auth_add_vendor(
02095 AUTH_ALG_MD5, fa_spi->shared_secret,
02096 fa_spi->shared_secret_len, start,
02097 (struct vendor_msg_auth *) (pos + used),
02098 VENDOR_EXT_DYNAMICS_SHA_HA_AUTH, htonl(fa_spi->spi));
02099 } else if (fa_spi != NULL) {
02100 DEBUG(DEBUG_FLAG, " * fh_auth\n");
02101 if (left < sizeof(struct msg_auth) + MAX_SK_LEN)
02102 return -1;
02103 used += auth_add(fa_spi->alg, fa_spi->shared_secret,
02104 fa_spi->shared_secret_len, start,
02105 (struct msg_auth *) (pos + used), FH_AUTH,
02106 htonl(fa_spi->spi));
02107 }
02108
02109 return used;
02110 }
02111
02112
02129 static int
02130 send_reg_repl(int s, struct bindingentry *binding, struct spi_entry *mn_spi,
02131 struct msg_extensions *ext, struct interface_entry *forced_iface,
02132 int code)
02133 {
02134 unsigned char msg[MAXMSG];
02135 unsigned char *msgpos = msg;
02136 struct reg_rep *reply;
02137 struct msg_key *key;
02138 struct sockaddr_in dest_addr;
02139 struct fa_spi_entry *fa_spi;
02140 #ifdef USE_TEARDOWN
02141 struct registration_ext_dynamics *dyn_ext;
02142 #endif
02143 int msglen, result, key_to_fa, left = MAXMSG, n;
02144 struct ha_tunnel_data *t_data;
02145
02146 ASSERT(s >= 0 && binding != NULL && binding->data != NULL &&
02147 mn_spi != NULL);
02148
02149 t_data = (struct ha_tunnel_data *) binding->data;
02150
02151
02152 DEBUG(DEBUG_FLAG, "Reply\n");
02153 reply = (struct reg_rep *) msg;
02154 memset(reply, 0, sizeof(struct reg_rep));
02155 reply->lifetime = htons(binding->timeout);
02156 reply->type = REG_REP;
02157 reply->code = code;
02158 reply->home_addr.s_addr = binding->mn_addr.s_addr;
02159 reply->ha_addr.s_addr = config.sha_addr.s_addr != 0 ?
02160 config.sha_addr.s_addr : binding->ha_addr.s_addr;
02161 memcpy(reply->id, binding->id, REG_REQ_ID_LEN);
02162 if (mn_spi->replay_method == REPLAY_PROTECTION_NONCE)
02163 t_data->nonce = reply->id[0] = get_rand32();
02164 msgpos += sizeof(struct reg_rep);
02165 left -= sizeof(struct reg_rep);
02166
02167 n = ha_add_ext_start(msg, msgpos, left, ext, binding->timeout,
02168 mn_spi, binding, t_data->auth_type);
02169 if (n < 0)
02170 return -1;
02171 msgpos += n;
02172 left -= n;
02173
02174
02175
02176 key_to_fa = 0;
02177 if (binding->fa_spi != 0 && ntohs(reply->lifetime) != 0) {
02178 fa_spi = get_fa_spi(binding->fa_spi, t_data->lower_saddr);
02179 if (fa_spi == NULL) {
02180 LOG2(LOG_ERR, "unknown FA SPI %i\n", binding->fa_spi);
02181 return -1;
02182 }
02183 DEBUG(DEBUG_FLAG, " * fa_keyrep\n");
02184 if (left < sizeof(struct msg_key) + MAX_SK_LEN)
02185 return -1;
02186 key = (struct msg_key *) msgpos;
02187 n = auth_encrypt(fa_spi->alg, fa_spi->shared_secret,
02188 fa_spi->shared_secret_len, binding->key,
02189 key, reply, VENDOR_EXT_DYNAMICS_FA_KEYREP,
02190 htonl(fa_spi->spi));
02191 msgpos += n;
02192 left -= n;
02193 key_to_fa = 1;
02194 } else if (binding->fa_pubkey && ntohs(reply->lifetime) != 0 &&
02195 binding->last_sent_fa_pubkeyrep) {
02196 DEBUG(DEBUG_FLAG, " * fa_pubkeyrep\n");
02197 n = GET_KEY_EXT_LEN(binding->last_sent_fa_pubkeyrep);
02198 if (left < n)
02199 return -1;
02200
02201
02202 key = (struct msg_key *) msgpos;
02203 memcpy(key, binding->last_sent_fa_pubkeyrep, n);
02204 msgpos += n;
02205 left -= n;
02206 key_to_fa = 1;
02207 }
02208
02209 #ifdef USE_TEARDOWN
02210 if (teardown) {
02211 DEBUG(DEBUG_FLAG, " * ext_dynamics (teardown)\n");
02212 if (left < sizeof(struct registration_ext_dynamics))
02213 return -1;
02214 dyn_ext = (struct registration_ext_dynamics *) msgpos;
02215 dyn_ext->type = VENDOR_EXT_TYPE2;
02216 dyn_ext->reserved = 0;
02217 dyn_ext->length = sizeof(struct registration_ext_dynamics) - 2;
02218 dyn_ext->vendor_id = htonl(VENDOR_ID_DYNAMICS);
02219 dyn_ext->sub_type = htons(VENDOR_EXT_DYNAMICS_OPTIONS);
02220 dyn_ext->version = VENDOR_EXT_VERSION;
02221 dyn_ext->opts = REG_EXT_OWN_TEAR_DOWN;
02222 dyn_ext->seq = 0;
02223 msgpos += sizeof(struct registration_ext_dynamics);
02224 left -= sizeof(struct registration_ext_dynamics);
02225 }
02226 #endif
02227
02228 if (key_to_fa) {
02229 DEBUG(DEBUG_FLAG, " * sk_auth\n");
02230 if (left < sizeof(struct vendor_msg_auth) + MAX_SK_LEN)
02231 return -1;
02232
02233 n = auth_add_vendor(AUTH_ALG_MD5, binding->key,
02234 binding->keylen, msg,
02235 (struct vendor_msg_auth *) msgpos,
02236 VENDOR_EXT_DYNAMICS_SK_AUTH,
02237 htonl(mn_spi->spi));
02238 msgpos += n;
02239 left -= n;
02240 }
02241
02242 n = ha_add_ext_end(msg, msgpos, t_data->lower_saddr, left, ext);
02243 if (n < 0)
02244 return -1;
02245 msgpos += n;
02246 left -= n;
02247
02248 msglen = msgpos - msg;
02249
02250 dest_addr.sin_family = AF_INET;
02251 dest_addr.sin_addr.s_addr = t_data->lower_saddr.s_addr;
02252 dest_addr.sin_port = binding->lower_port;
02253
02254 if (forced_iface != NULL &&
02255 setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, forced_iface->dev,
02256 IFNAMSIZ)) {
02257 DEBUG(DEBUG_FLAG, "setsockopt(SOL_SOCKET, SO_BINDTODEVICE): "
02258 "%s\n", strerror(errno));
02259 }
02260
02261 DEBUG(DEBUG_FLAG, " * total %i bytes to %s:%i\n", msglen,
02262 inet_ntoa(dest_addr.sin_addr), ntohs(dest_addr.sin_port));
02263 result = sendto(s, msg, msglen, 0,
02264 (struct sockaddr *) &dest_addr,
02265 sizeof(struct sockaddr_in));
02266
02267 if (forced_iface != NULL) {
02268
02269 char dummy[sizeof(int)];
02270 memset(dummy, 0, sizeof(dummy));
02271 if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, dummy,
02272 sizeof(dummy)))
02273 DEBUG(DEBUG_FLAG, "setsockopt(SOL_SOCKET, "
02274 "SO_BINDTODEVICE): %s\n", strerror(errno));
02275 }
02276
02277 return dynamics_check_sendto(result, msglen, "send_reg_repl");
02278 }
02279
02280
02300 static int
02301 send_reg_failure(int s, struct sockaddr_in *sock_addr,
02302 struct spi_entry *mn_spi, int auth_type,
02303 int code, __u32 *nonce, struct msg_extensions *ext,
02304 struct interface_entry *forced_iface,
02305 struct bindingentry *binding,
02306 struct interface_entry *from_iface)
02307 {
02308 unsigned char msg[MAXMSG];
02309 unsigned char *msgpos = msg;
02310 struct reg_rep *reply;
02311 int msglen, result, n, left = MAXMSG;
02312 struct ha_tunnel_data *t_data = NULL;
02313 static time_t last_failure_time = 0;
02314 time_t *timer, now;
02315
02316 ASSERT(s >= 0 && sock_addr && ext && ext->req && code > 2);
02317
02318 if (binding) {
02319
02320 t_data = (struct ha_tunnel_data *) binding->data;
02321 timer = &t_data->last_failure_time;
02322 } else {
02323
02324 timer = &last_failure_time;
02325 }
02326
02327
02328 time(&now);
02329 if (*timer > now) {
02330 DEBUG(DEBUG_FLAG, "send_reg_failure: timed failure in the "
02331 "future - host time changed?\n");
02332 *timer = now;
02333 } else if (now - *timer < config.reg_error_reply_interval) {
02334 DEBUG(DEBUG_FLAG, "Too frequent error message - skipping\n");
02335 return 0;
02336 }
02337 *timer = now;
02338
02339 if (mn_spi == NULL && ext->mh_auth != NULL)
02340 mn_spi = get_mn_spi(ntohl(ext->mh_auth->spi));
02341
02342
02343 DEBUG(DEBUG_FLAG, "Failure reply\n");
02344 reply = (struct reg_rep *) msg;
02345 memset(reply, 0, sizeof(struct reg_rep));
02346 reply->lifetime = 0;
02347 reply->type = REG_REP;
02348 reply->code = code;
02349 reply->home_addr.s_addr = ext->req->home_addr.s_addr;
02350 reply->ha_addr.s_addr = ext->req->ha_addr.s_addr;
02351 if (config.sha_addr.s_addr != 0)
02352 reply->ha_addr.s_addr = config.sha_addr.s_addr;
02353 else if (code == REGREP_UNKNOWN_HA_HA) {
02354
02355 struct node *node;
02356 int found = 0;
02357 for (node = list_get_first(&config.interfaces); node != NULL;
02358 node = list_get_next(node)) {
02359 struct interface_entry *iface =
02360 (struct interface_entry *) node;
02361 if (iface->ha_disc &&
02362 iface->bcaddr.s_addr == ext->req->ha_addr.s_addr) {
02363 reply->ha_addr.s_addr = iface->addr.s_addr;
02364 found = 1;
02365 break;
02366 }
02367 }
02368 if (!found && from_iface != NULL)
02369 reply->ha_addr.s_addr = from_iface->addr.s_addr;
02370 }
02371 memcpy(reply->id, ext->req->id, REG_REQ_ID_LEN);
02372 if (mn_spi) {
02373 if (mn_spi->replay_method == REPLAY_PROTECTION_TIMESTAMP &&
02374 code == REGREP_ID_MISMATCH_HA) {
02375 reply->id[0] = htonl(time(NULL) + UNIX_NTP_DIFF);
02376 } else if (mn_spi->replay_method == REPLAY_PROTECTION_NONCE) {
02377 reply->id[0] = get_rand32();
02378 if (nonce != NULL)
02379 *nonce = reply->id[0];
02380 }
02381 }
02382 msgpos += sizeof(struct reg_rep);
02383 left -= sizeof(struct reg_rep);
02384
02385 n = ha_add_ext_start(msg, msgpos, left, ext, 0, mn_spi, NULL,
02386 auth_type);
02387 if (n < 0)
02388 return -1;
02389 msgpos += n;
02390 left -= n;
02391
02392 n = ha_add_ext_end(msg, msgpos, sock_addr->sin_addr, left, ext);
02393 if (n < 0)
02394 return -1;
02395 msgpos += n;
02396 left -= n;
02397
02398 msglen = msgpos - msg;
02399
02400 if (forced_iface != NULL &&
02401 setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, forced_iface->dev,
02402 IFNAMSIZ)) {
02403 DEBUG(DEBUG_FLAG, "setsockopt(SOL_SOCKET, SO_BINDTODEVICE): "
02404 "%s\n", strerror(errno));
02405 }
02406
02407 DEBUG(DEBUG_FLAG, "send_reg_failure(code=%i): "
02408 "sending %i bytes to %s:%i (forced_iface=%s)\n", code, msglen,
02409 inet_ntoa(sock_addr->sin_addr), ntohs(sock_addr->sin_port),
02410 forced_iface != NULL ? forced_iface->dev : "N/A");
02411 result = sendto(s, msg, msglen, 0,
02412 (struct sockaddr *)sock_addr,
02413 sizeof(struct sockaddr_in));
02414
02415 if (forced_iface != NULL) {
02416
02417
02418
02419 char dummy[sizeof(int)];
02420 memset(dummy, 0, sizeof(dummy));
02421 if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, dummy,
02422 sizeof(dummy)) < 0 &&
02423 setsockopt(s, SOL_PACKET, SO_BINDTODEVICE, NULL, 0) < 0)
02424 DEBUG(DEBUG_FLAG, "setsockopt(SOL_SOCKET, "
02425 "SO_BINDTODEVICE): %s (this is probably "
02426 "bogus)\n", strerror(errno));
02427 }
02428
02429 return dynamics_check_sendto(result, msglen, "send_reg_failure");
02430 }
02431
02432
02433
02434
02435
02445 static int
02446 handle_reg_msg(struct interface_entry *from_iface, int s)
02447 {
02448 char msg[MAXMSG];
02449 struct sockaddr_in cli_addr;
02450 struct in_addr dst_addr;
02451 struct msghdr mh;
02452 char cdata[256];
02453 struct iovec iov;
02454 struct cmsghdr *cmsg;
02455 struct bindingentry *binding;
02456 struct spi_entry *mn_spi;
02457 int n, res, rsock;
02458 struct msg_extensions ext;
02459 int killbinding;
02460 int code, auth_type;
02461 char mn_addrstr[17];
02462 char fa_addrstr[17];
02463 struct ha_tunnel_data *t_data = NULL;
02464 struct bindingkey bkey;
02465 struct node *node;
02466 struct interface_entry *force_iface = NULL;
02467 int selected_mobile;
02468
02469
02470 memset(&cli_addr, 0, sizeof(cli_addr));
02471 dst_addr.s_addr = 0;
02472 memset(&mh, 0, sizeof(mh));
02473 iov.iov_base = msg;
02474 iov.iov_len = MAXMSG;
02475 mh.msg_name = &cli_addr;
02476 mh.msg_namelen = sizeof(cli_addr);
02477 mh.msg_iov = &iov;
02478 mh.msg_iovlen = 1;
02479 mh.msg_control = &cdata;
02480 mh.msg_controllen = sizeof(cdata);
02481
02482 n = recvmsg(s, &mh, 0);
02483
02484 LOG(LOG_INFO, "Received %d bytes from %s:%d\n", n,
02485 inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));
02486
02487 if (n < 0) {
02488 LOG(LOG_INFO "handle_reg_msg - recvfrom failed - %s\n",
02489 strerror(errno));
02490 return -1;
02491 }
02492
02493
02494 for (cmsg = CMSG_FIRSTHDR(&mh); cmsg != NULL;
02495 cmsg = DYNAMICS_CMSG_NXTHDR(&mh, cmsg)) {
02496 if (cmsg->cmsg_level == SOL_IP &&
02497 cmsg->cmsg_type == IP_PKTINFO) {
02498 struct _in_pktinfo *pkt;
02499 pkt = (struct _in_pktinfo *) CMSG_DATA(cmsg);
02500 dst_addr = pkt->ipi_addr;
02501 DEBUG(DEBUG_FLAG, "\tIP_PKTINFO: ipi_ifindex=%i "
02502 "ipi_spec_dst=%s ", pkt->ipi_ifindex,
02503 inet_ntoa(pkt->ipi_spec_dst));
02504 DEBUG(DEBUG_FLAG, "ipi_addr=%s\n",
02505 inet_ntoa(pkt->ipi_addr));
02506 }
02507 }
02508
02509
02510 rsock = -1;
02511 for (node = list_get_first(&config.interfaces); node != NULL;
02512 node = list_get_next(node)) {
02513 struct interface_entry *iface =
02514 (struct interface_entry *) node;
02515 if (iface->addr.s_addr == dst_addr.s_addr ||
02516 (iface->ha_disc &&
02517 iface->bcaddr.s_addr == dst_addr.s_addr)) {
02518 rsock = iface->udp_sock;
02519 }
02520 }
02521 if (rsock < 0 && from_iface != NULL &&
02522 dst_addr.s_addr == (unsigned int) -1) {
02523 DEBUG(DEBUG_FLAG, "Broadcast 255.255.255.255 destination - "
02524 "using interface[%s] UDP socket[%i]\n", from_iface->dev,
02525 from_iface->udp_sock);
02526 rsock = from_iface->udp_sock;
02527 }
02528 if (rsock < 0) {
02529 LOG2(LOG_WARNING, "Could not find UDP socket for "
02530 "registration reply - trying recv. socket\n");
02531 rsock = s;
02532 }
02533
02534 res = parse_msg(msg, n, &ext);
02535
02536
02537
02538 if (ext.req != NULL && ntohs(ext.req->lifetime) == 0 &&
02539 ext.req->home_addr.s_addr == cli_addr.sin_addr.s_addr &&
02540 ext.req->home_addr.s_addr == ext.req->co_addr.s_addr) {
02541
02542
02543
02544
02545
02546 DEBUG(DEBUG_FLAG, "Dereg. from home => bypassing mobility "
02547 "bindings in routing\n");
02548 force_iface = from_iface;
02549 }
02550
02551 if (res == -3 || res == -4) {
02552 LOG2(LOG_WARNING, "Unknown critical vendor extension in a "
02553 "request from %s:%i\n", inet_ntoa(cli_addr.sin_addr),
02554 ntohs(cli_addr.sin_port));
02555 send_reg_failure(rsock, &cli_addr, NULL, 0,
02556 res == -3 ? REGREP_UNSUPP_VENDOR_ID_MN_HA :
02557 REGREP_UNSUPP_VENDOR_ID_FA_HA, NULL, &ext,
02558 force_iface, NULL, from_iface);
02559 stats.discarded_vendor_ext++;
02560 report_discarded_msg(msg, n, &cli_addr,
02561 "unknown vendor extension");
02562 return -1;
02563 } else if (res != 0 || ext.req == NULL) {
02564 char *reason = "N/A";
02565 if (res == -1) {
02566 reason = "unknown extension";
02567 stats.discarded_unknown_ext++;
02568 } else if (res == -2) {
02569 reason = "malformed message";
02570 stats.discarded_malformed_msg++;
02571 } else if (ext.req == NULL) {
02572 reason = "not a request";
02573 stats.discarded_not_request++;
02574 }
02575 LOG2(LOG_WARNING, "Message parser failed or not a request "
02576 "(from %s:%i): %s\n", inet_ntoa(cli_addr.sin_addr),
02577 ntohs(cli_addr.sin_port), reason);
02578 report_discarded_msg(msg, n, &cli_addr, reason);
02579 return -1;
02580 }
02581
02582 memcpy(&bkey.mn_addr, &ext.req->home_addr, sizeof(bkey.mn_addr));
02583 bkey.ha_addr = config.sha_addr.s_addr != 0 ? config.sha_addr :
02584 ext.req->ha_addr;
02585 bkey.priv_ha = config.priv_ha;
02586 binding = binding_fetch(bindings, &bkey);
02587 if (binding != NULL)
02588 t_data = (struct ha_tunnel_data *) binding->data;
02589 mn_spi = validate_request(binding, cli_addr.sin_addr, msg, n, &ext,
02590 &code, &auth_type);
02591 if (code > 2) {
02592 send_reg_failure(rsock, &cli_addr, mn_spi, 0, code,
02593 (t_data != NULL ? &t_data->nonce : NULL),
02594 &ext, force_iface, binding, from_iface);
02595 stats.req_rejected++;
02596 report_discarded_msg(msg, n, &cli_addr, "invalid message");
02597 return -1;
02598 }
02599 if (mn_spi == NULL) {
02600 stats.req_rejected++;
02601 report_discarded_msg(msg, n, &cli_addr, "MN SPI not found");
02602 return -1;
02603 }
02604
02605 dynamics_strlcpy(mn_addrstr, inet_ntoa(ext.req->home_addr),
02606 sizeof(mn_addrstr));
02607 dynamics_strlcpy(fa_addrstr, inet_ntoa(ext.req->co_addr),
02608 sizeof(fa_addrstr));
02609
02610 if (binding != NULL) {
02611 t_data->auth_type = (auth_type == AUTH_MAC_RFC2002 ?
02612 AUTH_RFC2002BIS : AUTH_RFC2002);
02613
02614
02615
02616
02617
02618
02619 if (mn_spi->replay_method != REPLAY_PROTECTION_NONE &&
02620 binding->id[0] == ext.req->id[0] &&
02621 binding->id[1] == ext.req->id[1]) {
02622 DEBUG(DEBUG_FLAG,
02623 "Received duplicate request - dropping it\n");
02624 stats.req_rejected++;
02625 return -1;
02626 }
02627
02628
02629
02630 if (mn_spi->replay_method == REPLAY_PROTECTION_TIMESTAMP &&
02631 (ntohl(binding->id[0]) > ntohl(ext.req->id[0]) ||
02632 (ntohl(binding->id[0]) == ntohl(ext.req->id[0]) &&
02633 ntohl(binding->id[1]) >= ntohl(ext.req->id[1])))) {
02634 LOG2(LOG_NOTICE, "Timestamp did not increase "
02635 "(MN=%s, FA=%s)\n", mn_addrstr, fa_addrstr);
02636 send_reg_failure(rsock, &cli_addr, mn_spi,
02637 t_data->auth_type,
02638 REGREP_ID_MISMATCH_HA,
02639 &t_data->nonce, &ext, force_iface,
02640 binding, from_iface);
02641 stats.req_rejected++;
02642 return -1;
02643 }
02644
02645
02646 binding_remove(binding);
02647 } else {
02648 LOG2(LOG_NOTICE, "MN %s registers, FA is %s\n",
02649 mn_addrstr, fa_addrstr);
02650 }
02651
02652 stats.req_accepted++;
02653
02654 killbinding = 0;
02655
02656 if (binding &&
02657 (binding->lower_addr.s_addr != (config.sha_addr.s_addr != 0 ?
02658 config.sha_addr.s_addr :
02659 ext.req->co_addr.s_addr) ||
02660 ext.req->lifetime == 0)) {
02661 DEBUG(DEBUG_FLAG, "Found existing binding for MN %s\n",
02662 mn_addrstr);
02663
02664 if (ext.req->co_addr.s_addr == ext.req->home_addr.s_addr &&
02665 ext.req->lifetime == 0) {
02666 DEBUG(DEBUG_FLAG, "MN is deregistering all its "
02667 "simultaneous bindings\n");
02668
02669
02670
02671
02672
02673 }
02674
02675 #ifdef USE_TEARDOWN
02676
02677
02678 if (config.sha_addr.s_addr == 0 &&
02679 binding->lower_addr.s_addr != ext.req->co_addr.s_addr) {
02680 binding->timeout = 0;
02681 DEBUG(DEBUG_FLAG, "Sending purge msg to %s\n",
02682 inet_ntoa(binding->lower_addr));
02683 send_reg_repl(s, binding, mn_spi, NULL, force_iface,
02684 REGREP_ACCEPTED);
02685 }
02686 #endif
02687
02688 if (ext.req->lifetime > 0) {
02689
02690
02691
02692
02693 udhcp(find_dhcp_mobile(MSG_MN_NAI_DATA(ext.mn_nai), ext.mn_nai->length),RENEWIP);
02694
02695 LOG2(LOG_INFO, "MN %s updating tunnel to FA %s\n",
02696 mn_addrstr, fa_addrstr);
02697 if (switch_tunnel(binding, &ext, mn_spi) < 0)
02698 return -1;
02699 } else {
02700
02701
02702
02703
02704 LOG2(LOG_NOTICE, "MN %s deregisters\n", mn_addrstr);
02705 remove_tunnel(binding);
02706
02707
02708
02709 udhcp(find_dhcp_mobile(MSG_MN_NAI_DATA(ext.mn_nai), ext.mn_nai->length),RELEASEIP);
02710
02711 del_dhcp_mobile(find_dhcp_mobile(MSG_MN_NAI_DATA(ext.mn_nai), ext.mn_nai->length));
02712
02713 if (cli_addr.sin_addr.s_addr == binding->mn_addr.s_addr
02714 && ext.req->co_addr.s_addr ==
02715 ext.req->home_addr.s_addr) {
02716 DEBUG(DEBUG_FLAG, "MN returned home and "
02717 "deregistered all care-of addresses\n");
02718
02719
02720
02721
02722
02723
02724
02725
02726 }
02727 killbinding = 1;
02728 }
02729 }
02730
02731 if(ext.mn_nai == NULL) return -1;
02732 if(ext.mn_nai->length==0) return -1;
02733
02734
02735 if (binding == NULL) {
02736
02737 if (ntohs(ext.req->lifetime) == 0) {
02738 DEBUG(DEBUG_FLAG, "Deregistration attempt, but binding"
02739 " not found - creating temporary binding\n");
02740 binding = create_binding(&ext, mn_spi, 0);
02741 killbinding = 1;
02742 } else {
02743
02744
02745
02746
02747
02748
02749
02750
02751
02752
02753
02754 if (find_dhcp_mobile(MSG_MN_NAI_DATA(ext.mn_nai), ext.mn_nai->length)>=0)
02755 {
02756 LOG(LOG_INFO, "Mobile node was already added in the data structure");
02757
02758
02759 }
02760
02761 add_dhcp_mobile(0, MSG_MN_NAI_DATA(ext.mn_nai), ext.mn_nai->length);
02762
02763 LOG(LOG_INFO, "Preparing for DHCP call for registering mobile node");
02764
02765
02766 selected_mobile=find_dhcp_mobile(MSG_MN_NAI_DATA(ext.mn_nai), ext.mn_nai->length);
02767 if (selected_mobile <0) return -1;
02768
02769
02770
02771 if(udhcp(selected_mobile,REQUESTIP)==-1) return -1;
02772
02773 ext.req->home_addr.s_addr=dhcp_mobile_array[selected_mobile].requested_ip;
02774
02775
02776
02777
02778
02779 binding = create_binding(&ext, mn_spi, 1);
02780 }
02781
02782 if (binding == NULL) {
02783 LOG2(LOG_ERR, "Failed to create binding for MN: %s, "
02784 "FA: %s\n", mn_addrstr, fa_addrstr);
02785 send_reg_failure(rsock, &cli_addr, mn_spi,
02786 (auth_type == AUTH_MAC_RFC2002 ?
02787 1 : 0),
02788 REGREP_NO_RESOURCES_HA, NULL, &ext,
02789 force_iface, binding, from_iface);
02790 return -1;
02791 }
02792 t_data = (struct ha_tunnel_data *) binding->data;
02793 t_data->auth_type = (auth_type == AUTH_MAC_RFC2002 ?
02794 AUTH_RFC2002BIS : AUTH_RFC2002);
02795 }
02796 ASSERT(binding != NULL);
02797 t_data = (struct ha_tunnel_data *) binding->data;
02798 ASSERT(t_data != NULL);
02799
02800 binding->mod_time = time(NULL);
02801 t_data->reverse_tunnel = (ext.req->opts & REGREQ_REVERSE_TUNNEL) != 0;
02802 if (ext.req->opts & REGREQ_MINIMAL_ENCAPS)
02803 t_data->encapsulation = ENCAPS_MINIMAL;
02804 else if (ext.req->opts & REGREQ_GRE_ENCAPS)
02805 t_data->encapsulation = ENCAPS_GRE;
02806 else
02807 t_data->encapsulation = ENCAPS_IPIP;
02808
02809 if (ext.fa_keyreq)
02810 binding->fa_spi = ntohl(ext.fa_keyreq->spi);
02811 else
02812 binding->fa_spi = 0;
02813
02814
02815 if (ext.fa_pubkey) {
02816
02817
02818
02819
02820 if (binding->fa_pubkey &&
02821 binding->last_sent_fa_pubkeyrep != NULL &&
02822 (memcmp(binding->fa_pubkey,
02823 ext.fa_pubkey,
02824 GET_KEY_EXT_LEN(ext.fa_pubkey)) == 0))
02825 {
02826 DEBUG(DEBUG_FLAG, "Reusing encrypted SK for FA %s\n",
02827 fa_addrstr);
02828 } else {
02829 if (binding->fa_pubkey)
02830 free(binding->fa_pubkey);
02831 if (binding->last_sent_fa_pubkeyrep)
02832 free(binding->last_sent_fa_pubkeyrep);
02833 binding->last_sent_fa_pubkeyrep = NULL;
02834 binding->fa_pubkey = (struct msg_key *)
02835 malloc(GET_KEY_EXT_LEN(ext.fa_pubkey));
02836 if (binding->fa_pubkey != NULL) {
02837 memcpy(binding->fa_pubkey, ext.fa_pubkey,
02838 GET_KEY_EXT_LEN(ext.fa_pubkey));
02839 } else {
02840 LOG2(LOG_ERR, "Not enough memory "
02841 "for fa_pubkey\n");
02842 return -1;
02843 }
02844 binding->last_sent_fa_pubkeyrep =
02845 dynamics_do_rsa_encrypt(binding->key,
02846 binding->keylen,
02847 binding->fa_pubkey);
02848 if (binding->last_sent_fa_pubkeyrep == NULL) {
02849 LOG2(LOG_ERR, "RSA encryption failed (MN=%s, "
02850 "FA=%s)\n", mn_addrstr, fa_addrstr);
02851 }
02852 }
02853
02854 } else {
02855
02856
02857 if (binding->fa_pubkey)
02858 free(binding->fa_pubkey);
02859 binding->fa_pubkey = NULL;
02860
02861 if (binding->last_sent_fa_pubkeyrep)
02862 free(binding->last_sent_fa_pubkeyrep);
02863 binding->last_sent_fa_pubkeyrep = NULL;
02864 }
02865
02866 memcpy(&binding->id, ext.req->id, REG_REQ_ID_LEN);
02867
02868
02869 t_data->lower_saddr.s_addr = cli_addr.sin_addr.s_addr;
02870 binding->lower_port = cli_addr.sin_port;
02871
02872 binding->timeout = MIN(ntohs(ext.req->lifetime), mn_spi->max_lifetime);
02873 binding->exp_time = time(NULL) + binding->timeout;
02874
02875 if (send_reg_repl(rsock, binding, mn_spi, &ext, force_iface,
02876 code == REGREP_ACCEPTED_NO_SB ?
02877 REGREP_ACCEPTED_NO_SB : REGREP_ACCEPTED) != 0) {
02878 LOG2(LOG_ERR, "sending of registration reply to MN: %s, "
02879 "FA: %s failed\n", mn_addrstr, fa_addrstr);
02880 remove_tunnel(binding);
02881 destroy_binding(binding);
02882 return -1;
02883 }
02884
02885 if (killbinding) {
02886 destroy_binding(binding);
02887 } else {
02888
02889
02890 binding->timeout++;
02891
02892
02893
02894 check_bindings();
02895 binding_add(bindings, binding);
02896 }
02897
02898 return 0;
02899 }
02900
02901
02913 static int
02914 ha_send_agent_adv(struct interface_entry *iface, struct sockaddr_ll *to,
02915 struct in_addr *dest)
02916 {
02917
02918 set_agent_adv_data(
02919 config.ha_default_tunnel_lifetime,
02920 iface->addr,
02921 iface->addr, AGENT_ADV_HOME_AGENT, 0,
02922 iface->interval > 21845 ?
02923 65535 : iface->interval * 3, NULL, 0);
02924 set_agent_adv_nai(ha_nai);
02925
02926 return send_agent_advertisement(iface->icmp_sock,
02927 (struct sockaddr *) to, dest,
02928 iface->if_index);
02929 }
02930
02931
02943 static void
02944 send_agent_advs(struct timeval *next_agentadv)
02945 {
02946 struct interface_entry *iface;
02947 struct node *node;
02948 struct timeval now, next;
02949 unsigned int diff;
02950 int first = 1;
02951
02952
02953 gettimeofday(&now, NULL);
02954 next.tv_sec = 0;
02955 next.tv_usec = 0;
02956 for (node = list_get_first(&config.interfaces); node != NULL;
02957 node = list_get_next(node)) {
02958 iface = (struct interface_entry *) node;
02959 if (iface->agentadv != INTERFACE_AGENTADV_ALL)
02960 continue;
02961
02962 if (now.tv_sec >= iface->last_adv.tv_sec + iface->interval) {
02963 if (!ha_send_agent_adv(iface, NULL, NULL))
02964 stats.adv_sent++;
02965 else {
02966 DEBUG(DEBUG_FLAG, "send_agent_advs: "
02967 "advertisement sending to iface[%s] "
02968 "failed\n", iface->dev);
02969 }
02970 iface->last_adv.tv_sec = now.tv_sec;
02971 iface->last_adv.tv_usec = now.tv_usec;
02972 }
02973
02974 next.tv_sec = iface->last_adv.tv_sec + iface->interval;
02975
02976 next.tv_usec = iface->last_adv.tv_usec +
02977 (int) (MAX_ADV_DELAY * rand() / (RAND_MAX + 1.0));
02978 if (next.tv_usec > 999999) {
02979 next.tv_sec++;
02980 next.tv_usec -= 1000000;
02981 }
02982 if (first || next.tv_sec < next_agentadv->tv_sec) {
02983 DEBUG(DEBUG_FLAG, "** ");
02984 *next_agentadv = next;
02985 }
02986 first = 0;
02987
02988
02989 diff = ((next.tv_sec - now.tv_sec) * 1000000 +
02990 next.tv_usec - now.tv_usec) / 1000;
02991 DEBUG(DEBUG_FLAG, "send_agent_advs: next agentadv: "
02992 "%ld.%ld diff = %u msec\n",
02993 next.tv_sec, next.tv_usec, diff);
02994 }
02995 }
02996
02997
02998 static void
02999 handle_icmp(struct interface_entry *iface)
03000 {
03001 int r;
03002 struct sockaddr_ll from;
03003 struct in_addr to, fromaddr;
03004
03005 r = check_icmp_sol(iface->icmp_sock, &from, &to, &fromaddr);
03006
03007 if (r == 0 && iface->agentadv != INTERFACE_AGENTADV_NONE) {
03008
03009 DEBUG(DEBUG_FLAG,
03010 "\tagent solicitation => reply with agent adv\n");
03011 send_agent_advertisement(iface->icmp_sock,
03012 (struct sockaddr *) &from, &fromaddr,
03013 from.sll_ifindex);
03014 }
03015 }
03016
03017
03029 static void
03030 set_expr_timer(struct timeval *tv, struct timeval next_agentadv)
03031 {
03032 int expire_time;
03033 struct timeval now;
03034
03035 gettimeofday(&now, NULL);
03036 DEBUG(DEBUG_FLAG, "set_expr_timer (now=%li.%06li)\n",
03037 now.tv_sec, now.tv_usec);
03038
03039 if (timerisset(&next_agentadv)) {
03040 tv->tv_sec = next_agentadv.tv_sec - now.tv_sec;
03041 tv->tv_usec = next_agentadv.tv_usec - now.tv_usec;
03042 if (tv->tv_usec < 0) {
03043 tv->tv_sec--;
03044 tv->tv_usec += 1000000;
03045 }
03046 if (tv->tv_sec < 0) {
03047 tv->tv_sec = 0;
03048 tv->tv_usec = 0;
03049 }
03050 DEBUG(DEBUG_FLAG, "\tnext_agentadv in %li.%06li sec\n",
03051 tv->tv_sec, tv->tv_usec);
03052 } else {
03053 tv->tv_sec = -1;
03054 tv->tv_usec = 0;
03055 }
03056
03057 if ((expire_time = binding_nextexpiretime(bindings)) >= 0) {
03058 DEBUG(DEBUG_FLAG, "\tbinding next expire in %i sec\n",
03059 expire_time);
03060 if (tv->tv_sec < 0 || expire_time < tv->tv_sec) {
03061 DEBUG(DEBUG_FLAG, "\tsetting expire time to %i sec\n",
03062 expire_time);
03063 tv->tv_sec = (time_t)expire_time;
03064 tv->tv_usec = 0;
03065 }
03066 }
03067
03068 if (tv->tv_sec == -1 && tunnel_delayed_exists(tunnels)) {
03069 DEBUG(DEBUG_FLAG, "\tsetting expire time to %i sec (tunnel "
03070 "check)\n", TUNNEL_DELAYED_CHECK_INTERVAL);
03071 tv->tv_sec = TUNNEL_DELAYED_CHECK_INTERVAL;
03072 }
03073
03074 if (gratuitous_arp_queue != NULL) {
03075 struct timeval next;
03076
03077 next.tv_sec = gratuitous_arp_queue->tv.tv_sec - now.tv_sec;
03078 next.tv_usec = gratuitous_arp_queue->tv.tv_usec - now.tv_usec;
03079 if (next.tv_usec < 0) {
03080 next.tv_sec--;
03081 next.tv_usec += 1000000;
03082 }
03083 if (next.tv_sec < 0) {
03084 next.tv_sec = 0;
03085 next.tv_usec = 0;
03086 }
03087
03088 if (tv->tv_sec == -1 || cmp_timeval(tv, &next) > 0) {
03089 tv->tv_sec = next.tv_sec;
03090 tv->tv_usec = next.tv_usec;
03091 DEBUG(DEBUG_FLAG, "\tnext gratuitous ARP in %li.%06li "
03092 "sec\n", tv->tv_sec, tv->tv_usec);
03093 }
03094 }
03095 }
03096
03097
03105 static void
03106 init_interfaces(void)
03107 {
03108 struct interface_entry *iface;
03109 struct in_addr bc;
03110
03111 DEBUG(DEBUG_FLAG, "Initializing interfaces\n");
03112 inet_aton("255.255.255.255", &bc);
03113 iface = (struct interface_entry *) list_get_first(&config.interfaces);
03114 if (iface == NULL) {
03115 LOG2(LOG_ALERT, "No interfaces defined\n");
03116 clean_up(-1);
03117 }
03118 while (iface != NULL) {
03119 DEBUG(DEBUG_FLAG, "\t%s: ", iface->dev);
03120 iface->if_index = dyn_ip_get_ifindex(iface->dev);
03121 if (iface->if_index < 0) {
03122 LOG2(LOG_ALERT,
03123 "Could not get ifindex for interface %s\n",
03124 iface->dev);
03125 clean_up(-1);
03126 }
03127 DEBUG(DEBUG_FLAG, "ifindex=%i ", iface->if_index);
03128
03129 if (iface->force_addr.s_addr != 0) {
03130 DEBUG(DEBUG_FLAG, "forcing address ");
03131 iface->addr = iface->force_addr;
03132 } else {
03133 if (dyn_ip_get_ifaddr(iface->dev, &iface->addr) != 0) {
03134 LOG2(LOG_ALERT, "could not get interface[%s] "
03135 "address\n", iface->dev);
03136 clean_up(-1);
03137 }
03138 }
03139
03140
03141
03142 iface->udp_sock = dynamics_open_udp_socket(
03143 config.socket_priority,
03144 iface->force_addr.s_addr != 0 ? iface->force_addr :
03145 iface->addr, config.udpport, NULL);
03146 if (iface->udp_sock < 0) {
03147 LOG2(LOG_ALERT, "UDP socket opening failed\n");
03148 clean_up(-1);
03149 }
03150
03151 if (iface->ha_disc) {
03152
03153
03154 if (dyn_ip_get_bcaddr(iface->dev, &iface->bcaddr) != 0)
03155 {
03156 LOG2(LOG_ALERT, "could not get interface[%s] "
03157 "broadcast address\n", iface->dev);
03158 clean_up(-1);
03159 }
03160 iface->udp_bc_sock = dynamics_open_udp_socket(
03161 config.socket_priority, iface->bcaddr,
03162 config.udpport, iface->dev);
03163 if (iface->udp_bc_sock < 0) {
03164 LOG2(LOG_ALERT, "UDP broadcast socket opening "
03165 "failed for interface[%s]\n", iface->dev);
03166 clean_up(-1);
03167 }
03168
03169 iface->udp_bc_sock2 = dynamics_open_udp_socket(
03170 config.socket_priority, bc, config.udpport,
03171 iface->dev);
03172 if (iface->udp_bc_sock2 < 0) {
03173 LOG2(LOG_ALERT, "UDP broadcast "
03174 "(255.255.255.255) socket opening "
03175 "failed for interface[%s]\n", iface->dev);
03176 clean_up(-1);
03177 }
03178 }
03179
03180 iface->icmp_sock =
03181 open_agent_icmp_adv_socket(iface->dev,
03182 AGENTADV_FILTER_SOL);
03183 if (iface->icmp_sock < 0) {
03184 LOG2(LOG_ALERT, "could not open ICMP socket\n");
03185 clean_up(-1);
03186 }
03187
03188 DEBUG(DEBUG_FLAG, "%s => socket=%i\n", inet_ntoa(iface->addr),
03189 iface->icmp_sock);
03190
03191 iface = (struct interface_entry *) list_get_next(&iface->node);
03192 }
03193 }
03194
03195
03203 static void
03204 ha_parse_command_line(int argc, char *argv[])
03205 {
03206 int c, oindex = 0;
03207 static struct option long_options[] = {
03208
03209 {"help", no_argument, NULL, 'h'},
03210 {"version", no_argument, NULL, 'v'},
03211 {"debug", no_argument, NULL, 0},
03212 {"fg", no_argument, NULL, 0},
03213 {"config", required_argument, NULL, 'c'},
03214
03215
03216 {0, 0, 0, 0}
03217 };
03218
03219 DEBUG(DEBUG_FLAG, "HA command line parsing\n");
03220
03221 while ((c = getopt_long(argc, argv, "+hv", long_options, &oindex)) !=
03222 EOF) {
03223
03224 switch (c) {
03225 case 'h':
03226
03227
03228 exit(1);
03229 break;
03230
03231 case '?':
03232 printf("Command line parsing failed - aborting\n");
03233 exit(1);
03234
03235 case 'v':
03236 case 'c':
03237 case 0:
03238 break;
03239
03240 default:
03241 printf("?? getopt returned character code 0%o ??\n",
03242 c);
03243 exit(1);
03244 }
03245 }
03246 }
03247
03248
03256 int
03257 main(int argc, char *argv[])
03258 {
03259 int api_rw_sock;
03260
03261 int api_ro_sock;
03262
03263 struct timeval next_agentadv;
03264 struct interface_entry *iface;
03265
03266 program_name = parse_long_options(argc, argv, "home agent", PACKAGE,
03267 VERSION, dynamics_usage);
03268
03269 ha_parse_command_line(argc, argv);
03270
03271 memset(&config, 0, sizeof(struct ha_config));
03272
03273 if (load_config(&config, program_name,
03274 opt_config == NULL ? HA_GLOBAL_CONF_FILE : opt_config)
03275 == FALSE) {
03276 clean_up(1);
03277 }
03278 set_ha_nai();
03279 client_config.interface=config.dhcp_if;
03280 LOG(LOG_INFO, "Sending DHCP-packets to interface: %s.\n", client_config.interface);
03281
03282
03283 check_kernel_support(CHECK_KERNEL_IPIP | CHECK_KERNEL_NETLINK);
03284
03285 if (getuid() || geteuid()) {
03286 fprintf(stderr, "%s: This program must be run by root.\n",
03287 program_name);
03288 exit(1);
03289 }
03290
03291 iface = (struct interface_entry *) list_get_first(&config.interfaces);
03292 srand(time(NULL) ^ (iface ? iface->addr.s_addr : 0));
03293
03294 allow_ipv4_forwarding();
03295
03296
03297 bindings = binding_init(config.max_bindings,
03298 config.ha_default_tunnel_lifetime);
03299 if (bindings == NULL) {
03300 LOG2(LOG_ERR, "binding_init failed\n");
03301 clean_up(1);
03302 }
03303
03304 init_interfaces();
03305
03306 tunnels = tunnel_init("TUNL", 1, 253);
03307 if (tunnels == NULL) {
03308 LOG2(LOG_ERR, "tunnel_init failed\n");
03309 clean_up(1);
03310 }
03311
03312 api_rw_sock = api_open_socket(config.ha_api_admin_socket_path,
03313 config.ha_api_admin_socket_group,
03314 config.ha_api_admin_socket_owner,
03315 config.ha_api_admin_socket_permissions);
03316 if (api_rw_sock < 0) {
03317 LOG2(LOG_ERR, "Could not create API rw-socket\n");
03318 clean_up(1);
03319 }
03320
03321 api_ro_sock = api_open_socket(config.ha_api_read_socket_path,
03322 config.ha_api_read_socket_group,
03323 config.ha_api_read_socket_owner,
03324 config.ha_api_read_socket_permissions);
03325 if (api_ro_sock < 0) {
03326 LOG2(LOG_ERR, "Could not create API ro-socket\n");
03327 clean_up(1);
03328 }
03329
03330 if (!opt_foreground && dynamics_fork_daemon() == -1)
03331 clean_up(1);
03332 dynamics_write_pid_file(HA_PID_FILE);
03333
03334 memset(&stats, 0, sizeof(stats));
03335 dynamics_strlcpy(stats.version, VERSION, sizeof(stats.version));
03336
03337
03338 signal(SIGTERM, sig_handler);
03339 signal(SIGINT, sig_handler);
03340 signal(SIGHUP, reload_config);
03341
03342 syslog(LOG_INFO, "%s home agent daemon version %s started\n",
03343 PACKAGE, VERSION);
03344
03345 next_agentadv.tv_sec = 0;
03346 next_agentadv.tv_usec = 0;
03347 send_agent_advs(&next_agentadv);
03348
03349
03350 for (;;) {
03351
03352
03353 fd_set set;
03354 int oldmask;
03355 struct node *node;
03356 struct timeval tv;
03357
03358 oldmask = sigblock(sigmask(SIGHUP));
03359 FD_ZERO(&set);
03360 FD_SET(api_rw_sock, &set);
03361 FD_SET(api_ro_sock, &set);
03362 for (node = list_get_first(&config.interfaces); node != NULL;
03363 node = list_get_next(node)) {
03364 iface = (struct interface_entry *) node;
03365 FD_SET(iface->udp_sock, &set);
03366 if (iface->ha_disc && iface->udp_bc_sock > -1)
03367 FD_SET(iface->udp_bc_sock, &set);
03368 if (iface->ha_disc && iface->udp_bc_sock2 > -1)
03369 FD_SET(iface->udp_bc_sock2, &set);
03370 FD_SET(iface->icmp_sock, &set);
03371 }
03372
03373 set_expr_timer(&tv, next_agentadv);
03374 sigsetmask(oldmask);
03375
03376 if (select(FD_SETSIZE, &set, NULL, NULL,
03377 tv.tv_sec == -1 ? NULL : &tv) < 0) {
03378
03379 if (errno != EINTR) {
03380 LOG2(LOG_ERR, "select - %s", strerror(errno));
03381 clean_up(1);
03382 }
03383 continue;
03384 }
03385
03386
03387
03388
03389 oldmask = sigblock(sigmask(SIGHUP));
03390
03391 if (FD_ISSET(api_rw_sock, &set)) {
03392
03393 handle_api(api_rw_sock, 1);
03394 }
03395
03396 if (FD_ISSET(api_ro_sock, &set)) {
03397
03398 handle_api(api_ro_sock, 0);
03399 }
03400
03401 for (node = list_get_first(&config.interfaces); node != NULL;
03402 node = list_get_next(node)) {
03403 iface = (struct interface_entry *) node;
03404 if (FD_ISSET(iface->udp_sock, &set)) {
03405 LOG(LOG_INFO, "Got UDP message(%s)\n",
03406 iface->dev);
03407
03408 handle_reg_msg(iface, iface->udp_sock);
03409
03410
03411 }
03412 if (iface->ha_disc && iface->udp_bc_sock > -1 &&
03413 FD_ISSET(iface->udp_bc_sock, &set)) {
03414 DEBUG(DEBUG_FLAG, "Got UDP (BC) message(%s)\n",
03415 iface->dev);
03416
03417
03418 handle_reg_msg(iface, iface->udp_bc_sock);
03419 }
03420 if (iface->ha_disc && iface->udp_bc_sock2 > -1 &&
03421 FD_ISSET(iface->udp_bc_sock2, &set)) {
03422 DEBUG(DEBUG_FLAG, "Got UDP (BC "
03423 "255.255.255.255) message(%s)\n",
03424 iface->dev);
03425
03426
03427 handle_reg_msg(iface, iface->udp_bc_sock2);
03428 }
03429 if (FD_ISSET(iface->icmp_sock, &set)) {
03430 handle_icmp(iface);
03431 }
03432
03433 }
03434
03435
03436 if (timerisset(&next_agentadv))
03437 send_agent_advs(&next_agentadv);
03438
03439 check_bindings();
03440 tunnel_check_delayed(tunnels, 0);
03441 check_queued_gratuitous_arp();
03442
03443 sigsetmask(oldmask);
03444
03445 }
03446
03447
03448 return 0;
03449 }