mn_api.c

Go to the documentation of this file.
00001 /* $Id: mn_api.c,v 1.46 2001/09/29 16:06:39 jm Exp $
00002  * Mobile Node - API handling
00003  *
00004  * Dynamic hierarchial IP tunnel
00005  * Copyright (C) 1998-2001, Dynamics group
00006  *
00007  * This program is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License version 2 as
00009  * published by the Free Software Foundation. See README and COPYING for
00010  * more details.
00011  */
00012 
00013 #include "config.h"
00014 #include <sys/socket.h>
00015 #include <netinet/in.h>
00016 #include <arpa/inet.h>
00017 #include <errno.h>
00018 #include <string.h>
00019 #include <unistd.h>
00020 #include <fcntl.h>
00021 #include <time.h>
00022 
00023 #include "agentapi.h"
00024 #include "debug.h"
00025 #include "dyn_ip.h"
00026 #include "list.h"
00027 #include "util.h"
00028 #ifdef WITH_WIRELESS
00029 #include "monitor.h"
00030 #endif
00031 #include "mn.h"
00032 
00033 extern struct mn_data mn;
00034 extern struct mn_config config; /* configuration information */
00035 extern struct timeval timers[TIMER_COUNT];
00036 
00037 /* Policies can be changed on/off from dynmn_tool (policy) */
00038 static struct policy_vars monitor_policy[] = {
00039         {EARLY_EXPIRE_STR,    EARLY_EXPIRE_BIT},
00040         {NEWEST_FA_STR,       NEWEST_FA_BIT},
00041         {EAGER_SWITCH_STR,    EAGER_SWITCH_BIT},
00042         {NEWEST_ADV_STR,      NEWEST_ADV_BIT},
00043         {"", -1}
00044 };
00045 
00046 static dyn_api_sockaddr api_addr; /* address of progressing api call */
00047 static socklen_t api_addr_len = 0;
00048 
00049 /* String representations of the states */
00050 char *state_strings[MN_STATE_COUNT] = {
00051         "Startup", "Disconnected", "Find Agent", "Passive Find",
00052         "Request Tunnel", "Connected",
00053         "Close For Home", "At Home", "Error", "Stop" };
00054 
00055 
00056 /* Fill static status structure and return a pointer to it. */
00057 static struct dynamics_mobile_status *
00058 get_mobile_status(void)
00059 {
00060         static struct dynamics_mobile_status status;
00061 
00062         status.state = mn.state;
00063 
00064         if (mn.state >= 0 && mn.state < MN_STATE_COUNT)
00065                 dynamics_strlcpy(status.state_str, state_strings[mn.state],
00066                                  API_STATE_LEN);
00067         else
00068                 memset(status.state_str, 0, sizeof(status.state_str));
00069         status.local_addr = mn.local_addr;
00070         status.co_addr = mn.co_addr;
00071         status.fa_addr = mn.fa_addr;
00072         status.ha_addr = config.ha_ip_addr;
00073         status.home_addr = config.mn_home_ip_addr;
00074         status.tunnel_up = mn.tunnel_up;
00075         status.tunnel_mode = mn.tunnel_mode;
00076         if (mn.tunnel_up) {
00077                 status.lifetime = timers[TIMER_LIFETIME].tv_sec - time(NULL);
00078         } else {
00079                 status.lifetime = 0;
00080         }
00081         status.last_reply_code = mn.last_reply_code;
00082         status.last_reply_rcvd = mn.last_reply_rcvd;
00083         status.last_request_sent = mn.last_request_sent;
00084         if (mn.info_str == NULL)
00085                 memset(status.info_str, 0, API_INFO_LEN + 1);
00086         else
00087                 dynamics_strlcpy(status.info_str, mn.info_str,
00088                                  API_INFO_LEN + 1);
00089         if (mn.warn_str == NULL)
00090                 memset(status.warn_str, 0, API_INFO_LEN + 1);
00091         else
00092                 dynamics_strlcpy(status.warn_str, mn.warn_str,
00093                                  API_INFO_LEN + 1);
00094         status.device_count = mn.device_count;
00095         status.discarded_msgs = mn.discarded_msgs;
00096 
00097         return &status;
00098 }
00099 
00100 
00101 /*
00102  * Handling function for API update location call. API message is in msg.
00103  * Set own local address according to msg. If in disconnected state, stay
00104  * there, but otherwise go to find_agent state, because we have
00105  * moved under another FA and we will want hear its address.
00106  * Tunnels must be updated for new address.
00107  */
00108 static void handle_api_locupd(int s, dyn_api_sockaddr *addr, socklen_t addrlen,
00109                               struct api_msg *msg, int block_api)
00110 {
00111         int ok, i;
00112         char device[IFNAMSIZ + 1];
00113         struct in_addr iaddr;
00114 
00115         /* locupd should have new IP address or interface name after four
00116          * zero octets */
00117 
00118         ok = 1;
00119         if (msg->length == 4) {
00120                 if (mn.local_addr.s_addr != (__u32) *msg->params) {
00121                         /* set local address */
00122                         memcpy(&mn.local_addr, msg->params, 4);
00123                         DEBUG(DEBUG_INFO, "Address changed to %s\n",
00124                               inet_ntoa(mn.local_addr));
00125                 }
00126         } else if (msg->length > 4 && msg->params[0] == 0 &&
00127                 msg->params[1] == 0 && msg->params[2] == 0 &&
00128                 msg->params[3] == 0) {
00129                 if (msg->length > IFNAMSIZ)
00130                         ok = 0;
00131                 else {
00132                         memcpy(device, msg->params + 4, msg->length - 4);
00133                         device[msg->length - 4] = '\0';
00134                         ok = 2;
00135                 }
00136         } else if (msg->length == 0) {
00137                 /* try to use the first available interface */
00138                 for (i = 0; i < MAX_INTERFACES; i++) {
00139                         if (mn.iface[i].s > -1) {
00140                                 memcpy(device, mn.iface[i].device, IFNAMSIZ);
00141                                 device[sizeof(device) - 1] = '\0';
00142                                 ok = 2;
00143                                 break;
00144                         }
00145                 }
00146                 if (ok != 2) ok = 0;
00147         } else ok = 0;
00148 
00149         if (ok == 2) {
00150                 DEBUG(DEBUG_INFO, "\tinterface[%s]\n", device);
00151                 if (dyn_ip_get_ifaddr(device, &iaddr) < 0)
00152                         ok = 0;
00153                 else if (mn.local_addr.s_addr != iaddr.s_addr) {
00154                         DEBUG(DEBUG_INFO,
00155                               "Address changed to %s (%s)\n",
00156                               inet_ntoa(iaddr), device);
00157                         mn.local_addr.s_addr = iaddr.s_addr;
00158                 }
00159         }
00160 
00161         if (!ok) {
00162                 DEBUG(DEBUG_INFO, "API: locupd failed - illegal parameter\n");
00163                 api_send_reply(s, addr, addrlen, API_ILLEGAL_PARAMETERS, NULL,
00164                                0);
00165                 return;
00166         }
00167 
00168         /* check if we are at home */
00169         if (mn.local_addr.s_addr == config.mn_home_ip_addr.s_addr &&
00170             !config.enable_fa_decapsulation) {
00171                 close_for_home(STATE_INIT);
00172         } else {
00173                 switch (mn.state) {
00174                 case MN_DISCONNECTED:
00175                         break;
00176                 default:
00177                         /* allow quick locupd */
00178                         timerclear(&mn.last_reg_send_time);
00179                         find_agent(STATE_INIT);
00180                         break;
00181                 }
00182         }
00183 
00184         if (!block_api)
00185                 api_send_reply(s, addr, addrlen, API_SUCCESS, NULL, 0);
00186 }
00187 
00188 
00189 static void handle_api_force_fa(int s, dyn_api_sockaddr *addr,
00190                                 socklen_t addrlen,
00191                                 struct api_msg *msg)
00192 {
00193         /* force_fa should have new address */
00194         if (msg->length != 4) {
00195                 api_send_reply(s, addr, addrlen, API_ILLEGAL_PARAMETERS, NULL,
00196                                0);
00197                 return;
00198         }
00199 
00200         /* set local address */
00201         memcpy(&mn.force_fa_addr, msg->params, 4);
00202         DEBUG(DEBUG_INFO, "Force FA address set to %s\n",
00203               inet_ntoa(mn.force_fa_addr));
00204 
00205         api_send_reply(s, addr, addrlen, API_SUCCESS, NULL, 0);
00206 }
00207 
00208 
00209 static int adv_iter(struct node *node, void *data)
00210 {
00211         struct agentadv_data *adv;
00212         struct api_msg *api_msg;
00213         struct dynamics_mobile_fa_list *list;
00214         int size, tmp;
00215         unsigned int flags;
00216 
00217         adv = (struct agentadv_data *) node;
00218         api_msg = (struct api_msg *) data;
00219 
00220         list = (struct dynamics_mobile_fa_list *)
00221                 ((char *) api_msg->params + api_msg->length);
00222 
00223         size = sizeof(struct dynamics_mobile_fa_list);
00224         if ((api_msg->length + size) > API_DATA_SIZE) {
00225                 DEBUG(DEBUG_INFO, "adv_iter: Not enough room in msg "
00226                       " (itemsize %d, length %d)\n",
00227                       size, api_msg->length);
00228                 return 0;
00229         }
00230         api_msg->length += size;
00231 
00232         /* copy values */
00233         UNALIGNED_(&list->addr, &adv->addr);
00234         MOVE_UNALIGNED(list->interface, adv->ifname, IFNAMSIZ);
00235         UNALIGNED_(&list->in_use, &adv->in_use);
00236 
00237         if (mn.current_adv != NULL && 
00238             adv->addr.s_addr == mn.current_adv->addr.s_addr) {
00239                 tmp = 1;
00240         } else {
00241                 tmp = 0;
00242         }
00243         UNALIGNED_(&list->current_adv, &tmp);
00244         flags = 0;
00245         if (adv->adv.ext) {
00246                 int opts = ntohs(adv->adv.ext->opts);
00247                 if (opts & AGENT_ADV_FOREIGN_AGENT)
00248                         flags |= API_MA_FLAGS_FA;
00249                 if (opts & AGENT_ADV_HOME_AGENT)
00250                         flags |= API_MA_FLAGS_HA;
00251                 if (opts & AGENT_ADV_BUSY)
00252                         flags |= API_MA_FLAGS_BUSY;
00253         }
00254         if (adv->adv.own_ext)
00255                 flags |= API_MA_FLAGS_DYNAMICS;
00256         UNALIGNED_(&list->flags, &flags);
00257 
00258 #ifdef WITH_WIRELESS
00259         if (adv->mon != NULL) {
00260                 tmp = adv->mon->avg;
00261         } else {
00262                 tmp = -1;
00263         }
00264 #else
00265         tmp = -1;
00266 #endif
00267         UNALIGNED_(&list->quality_avg, &tmp);
00268         
00269         /* Priorities aren't calculated if MN is in DISCONNECTED
00270            state. That is why we don't want to update priority because
00271            it's not up to date information and may confuse the
00272            user. */
00273         if (mn.state == MN_DISCONNECTED) {
00274                 tmp = -2;  /* not up to date information */
00275                 UNALIGNED_(&list->priority, &tmp); 
00276         } else 
00277                 UNALIGNED_(&list->priority, &adv->priority);
00278         UNALIGNED_(&list->last, &adv->last.tv_sec);
00279         UNALIGNED_(&list->reduce, &adv->prio_degrade_percent);
00280         
00281         return 1;
00282 }
00283 
00284 
00285 static void handle_api_get_fa_list(int s, dyn_api_sockaddr *addr,
00286                                    socklen_t addrlen,
00287                                    struct api_msg *msg)
00288 {
00289         msg->length = 0;
00290         hashtable_iterator(mn.agentadv, adv_iter, msg);
00291         api_send_reply(s, addr, addrlen, API_SUCCESS,
00292                        (unsigned char *) &msg->params, msg->length);
00293 }
00294 
00295 
00296 static void handle_api_get_fa_info(int s, dyn_api_sockaddr *addr,
00297                                    socklen_t addrlen,
00298                                    struct api_msg *msg)
00299 {
00300         struct dynamics_mobile_fa_info *info;
00301         struct agentadv_data *adv;
00302         struct in_addr fa_addr;
00303         int ifindex, tmp;
00304         char interface[IFNAMSIZ + 1];
00305         char nai[API_MAX_NAI_LEN + 1];
00306 
00307         /* should have fa address */
00308         if (msg->length != sizeof(struct dynamics_mobile_fa_info)) {
00309                 api_send_reply(s, addr, addrlen, API_ILLEGAL_PARAMETERS, NULL,
00310                                0);
00311                 return;
00312         }
00313         info = (struct dynamics_mobile_fa_info *)&msg->params;
00314         MOVE_UNALIGNED(&fa_addr, &info->list.addr, sizeof(struct in_addr));
00315         DEBUG(DEBUG_API, "handle_api_get_fa_info: %s\n",
00316               inet_ntoa(fa_addr));
00317         
00318         ifindex = 0;
00319         MOVE_UNALIGNED(interface, &info->list.interface, IFNAMSIZ);
00320         interface[IFNAMSIZ] = '\0';
00321         if (strlen(interface) > 0) {
00322                 ifindex = dyn_ip_get_ifindex(interface);
00323                 DEBUG(DEBUG_API, "handle_api_get_fa_info: interface \"%s\""
00324                       " ifindex %d\n", interface, ifindex);
00325         }
00326         adv = adv_fetch(mn.agentadv, &fa_addr, ifindex);
00327         if (adv == NULL) {
00328                 DEBUG(DEBUG_API, "handle_api_get_fa_info: %s not found\n",
00329                       inet_ntoa(fa_addr));
00330                 api_send_reply(s, addr, addrlen, API_FAILED, NULL, 0);
00331                 return;
00332         }
00333 
00334         msg->length = sizeof(struct dynamics_mobile_fa_info);
00335         UNALIGNED_(&info->list.addr, &adv->addr);
00336         UNALIGNED_(&info->list.in_use, &adv->in_use);
00337         UNALIGNED_(&info->ifindex, &ifindex);
00338 #ifdef WITH_WIRELESS
00339         if (adv->mon != NULL)
00340                 UNALIGNED_(&info->list.quality_avg, &adv->mon->avg);
00341         else {
00342                 tmp = -1;
00343                 UNALIGNED_(&info->list.quality_avg, &tmp);
00344         }
00345 #else
00346         tmp = -1;
00347         UNALIGNED_(&info->list.quality_avg, &tmp);
00348 #endif
00349         UNALIGNED_(&tmp, &info->list.quality_avg);
00350         DEBUG(DEBUG_INFO, "quality: %d\n", tmp);
00351         UNALIGNED_(&info->list.priority, &adv->priority);
00352         UNALIGNED_(&info->ifindex, &adv->ifindex);
00353         MOVE_UNALIGNED(info->list.interface, adv->ifname, sizeof(adv->ifname));
00354         UNALIGNED_(&info->list.last, &adv->last.tv_sec);
00355         UNALIGNED_(&info->expire, &adv->expire.tv_sec);
00356         UNALIGNED_(&info->arpentry, &adv->arpentry);
00357         nai[0] = '\0';
00358         if (adv->adv.fa_nai != NULL &&
00359             API_MAX_NAI_LEN >= GET_NAI_LEN(adv->adv.fa_nai)) {
00360                 memcpy(nai, MSG_NAI_DATA(adv->adv.fa_nai), API_MAX_NAI_LEN);
00361                 nai[GET_NAI_LEN(adv->adv.fa_nai)] = '\0';
00362         }
00363         DEBUG(DEBUG_INFO, "\tNAI[%s]\n", nai);
00364         MOVE_UNALIGNED(&info->nai, &nai, API_MAX_NAI_LEN + 1);
00365 
00366         api_send_reply(s, addr, addrlen, API_SUCCESS,
00367                        (unsigned char *) &msg->params, msg->length);
00368 }
00369 
00370 
00371 #ifdef WITH_WIRELESS
00372 static void handle_api_get_iw_ch(int s, dyn_api_sockaddr *addr,
00373                                  socklen_t addrlen,
00374                                  struct api_msg *msg)
00375 {
00376         int r;
00377         struct dynamics_mn_iw_ch_info *info;
00378 
00379         msg->length = 0;
00380         r = monitor_api_get_ch((unsigned char *)msg->params, &msg->length);
00381 
00382         info = (struct dynamics_mn_iw_ch_info *)msg->params;
00383         DEBUG(DEBUG_API, "handle_api_get_iw_ch: %s: %d "
00384               "(msg->length: %d(%d) num: %d)\n",
00385               info->ifname, info->channel,
00386               msg->length, sizeof(struct dynamics_mn_iw_ch_info),
00387               msg->length/sizeof(struct dynamics_mn_iw_ch_info));
00388 
00389         if (r)
00390                 api_send_reply(s, addr, addrlen, API_FAILED, NULL, 0);
00391         else
00392                 api_send_reply(s, addr, addrlen, API_SUCCESS,
00393                                (unsigned char *) msg->params, msg->length);
00394 }
00395 
00396 
00397 static void handle_api_set_iw_ch(int s, dyn_api_sockaddr *addr,
00398                                  socklen_t addrlen,
00399                                  struct api_msg *msg)
00400 {
00401         struct dynamics_mn_iw_ch_info info;
00402 
00403         memcpy((char *)&info, (char *)msg->params,
00404                sizeof(struct dynamics_mn_iw_ch_info));
00405 
00406         if (monitor_api_set_ch(info.ifname, info.channel))
00407                 api_send_reply(s, addr, addrlen, API_FAILED, NULL, 0);
00408         else
00409                 api_send_reply(s, addr, addrlen, API_SUCCESS, NULL, 0);
00410 }
00411 #endif /* WITH_WIRELESS */
00412 
00413 static void handle_api_rescan(int s, dyn_api_sockaddr *addr,
00414                               socklen_t addrlen,
00415                               struct api_msg *msg)
00416 {
00417         int r = check_interfaces(mn.iface, MAX_INTERFACES);
00418         api_send_reply(s, addr, addrlen, r ? API_FAILED : API_SUCCESS, NULL,
00419                        0);
00420 }
00421 
00422 static void handle_register_dev_info_socket(int s, dyn_api_sockaddr *addr,
00423                                             socklen_t addrlen,
00424                                             struct api_msg *msg)
00425 {
00426         char *path = (char *) msg->params;
00427 
00428         DEBUG(DEBUG_API, "API register device info socket[%s]\n", path);
00429         if (msg->length < 2) {
00430                 DEBUG(DEBUG_API, "\ttoo short message\n");
00431                 api_send_reply(s, addr, addrlen, API_FAILED, NULL, 0);
00432                 return;
00433         }
00434         path[msg->length - 1] = '\0';
00435         memset(&mn.dev_info_addr, 0, sizeof(mn.dev_info_addr));
00436         mn.dev_info_addr.sun_family = AF_LOCAL;
00437         dynamics_strlcpy(mn.dev_info_addr.sun_path, path, msg->length);
00438         api_send_reply(s, addr, addrlen, API_SUCCESS, NULL, 0);
00439 }
00440 
00441 
00442 static int monitor_api_set_policy(char *name, int on)
00443 {
00444         struct policy_vars *t = monitor_policy;
00445         int i = 0, len;
00446 
00447         if (name == NULL || (on != 0 && on != 1))
00448                 return 1;
00449 
00450         DEBUG(DEBUG_API, "monitor_set_policy: '%s' %s \n", 
00451               name, on == 0 ? "off" : "on");
00452 
00453         len = strlen(t[i].name);
00454         len = strlen(name) < len ? strlen(name) : len;
00455         while (t[i].bit != -1 && 
00456                strncasecmp(t[i].name, name, len) != 0)
00457                 i++;
00458         
00459         if (t[i].bit == -1) {
00460                 DEBUG(DEBUG_API, "monitor_set_policy: No policy matched!\n");
00461                 return 1;
00462         }
00463 
00464         if (on)
00465                 POLICY_SET(t[i].bit);
00466         else
00467                 POLICY_CLR(t[i].bit);
00468 
00469         return 0;
00470 }
00471 
00472 
00473 static int monitor_api_get_policy(char *buffer, int len)
00474 {
00475         int curr = 0, r, i;
00476         struct policy_vars *t = monitor_policy;
00477 
00478         for (i = 0, r = 0; t[i].bit != -1 && r == 0; i++)
00479                 r = copy_str(buffer, len, &curr, t[i].name, 
00480                              POLICY(t[i].bit) ? "ON " : "OFF");
00481         if (r) {
00482                 DEBUG(DEBUG_API, "monitor_api_get_policy: insufficient "
00483                       "space\n");
00484                 return API_INSUFFICIENT_SPACE;
00485         }
00486 
00487         DEBUG(DEBUG_API, buffer);
00488         return API_SUCCESS;
00489 }
00490 
00491 
00492 static void handle_policy(int s, dyn_api_sockaddr *addr,
00493                           socklen_t addrlen,
00494                           struct api_msg *msg, int on)
00495 {
00496         int r = monitor_api_set_policy((char *)msg->params, on);
00497         api_send_reply(s, addr, addrlen, r, msg->params, msg->length);
00498 }
00499 
00500 static void handle_get_policy(int s, dyn_api_sockaddr *addr,
00501                               socklen_t addrlen,
00502                               struct api_msg *msg)
00503 {
00504         int r = monitor_api_get_policy((char *)msg->params, msg->length);
00505         api_send_reply(s, addr, addrlen, r, msg->params, msg->length);
00506 }
00507 
00508 #ifdef WITH_WIRELESS
00509 
00510 static void handle_mon_conf(int s, dyn_api_sockaddr *addr,
00511                             socklen_t addrlen,
00512                             struct api_msg *msg, int type)
00513 {
00514         int r = monitor_api_mon_conf((char *)msg->params, msg->length, type);
00515         api_send_reply(s, addr, addrlen, r, msg->params, msg->length);
00516 }
00517 
00518 #endif /* WITH_WIRELESS */
00519 
00520 
00521 /* Handle API call from socket sock. If it is privileged, the admin
00522  * is nonzero. */
00523 void handle_api(int sock, int admin)
00524 {
00525         dyn_api_sockaddr addr;
00526         unsigned int addrlen;
00527         struct api_msg msg;
00528 #ifdef MN_LOCUPD_PROFILER
00529         char *name;
00530         char tmp[30];
00531         struct in_addr faaddr;
00532 #endif
00533 
00534         DEBUG(DEBUG_API, "receive from api\n");
00535         addrlen = sizeof(addr);
00536         memset(&addr, 0, addrlen);
00537         if (api_receive(sock, &addr, &addrlen, &msg) < 0) {
00538                 LOG2(LOG_ERR, "api receive: %s\n", strerror(errno));
00539                 return;
00540         }
00541         if (msg.type != API_CALL_MSG) return;
00542 #ifdef MN_LOCUPD_PROFILER
00543         switch (msg.code) {
00544         case API_FORCE_FA:
00545                 memcpy(&faaddr, msg.params, 4);
00546                 snprintf(tmp, sizeof(tmp), "FORCE %s", inet_ntoa(faaddr));
00547                 name = tmp;
00548                 break;
00549         case API_UPDATE_LOCATION: name = "UPDATE"; break;
00550         case API_UPDATE_LOCATION_BLOCK: name = "UPDATEB"; break;
00551         case API_DISCONNECT: name = "DISCONNECT"; break;
00552         case API_CONNECT: name = "CONNECT"; break;
00553         default:
00554                 snprintf(tmp, sizeof(tmp), "%i", msg.code);
00555                 name = tmp;
00556                 break;
00557         }
00558         gettimeofday(&mn.last_api, NULL);
00559         fprintf(mn.profile, "API %s %u.%06u\n", name,
00560                 (unsigned int) mn.last_api.tv_sec,
00561                 (unsigned int) mn.last_api.tv_usec);
00562 #endif
00563         switch (msg.code) {
00564         case API_CONNECT:
00565                 DEBUG(DEBUG_API, "api connect\n");
00566                 if (!admin) break;
00567                 mn.ha_error_count = 0;
00568                 if (mn.state == MN_DISCONNECTED) {
00569                         /* allow quick locupd */
00570                         timerclear(&mn.last_reg_send_time);
00571                         check_interfaces(mn.iface, MAX_INTERFACES);
00572                         memcpy(&mn.tunnel_mode, msg.params,
00573                                sizeof(mn.tunnel_mode));
00574                         DEBUG(DEBUG_API, "tunnel_mode=%i\n", mn.tunnel_mode);
00575                         if (mn.tunnel_mode == API_TUNNEL_FULL_HA &&
00576                             mn.local_addr.s_addr ==
00577                             config.mn_home_ip_addr.s_addr) {
00578                                 struct in_addr iaddr;
00579                                 char device[IFNAMSIZ + 1];
00580                                 if (dyn_ip_route_get(config.ha_ip_addr, device,
00581                                                      IFNAMSIZ) == 0 &&
00582                                     dyn_ip_get_ifaddr(device, &iaddr) == 0 &&
00583                                     mn.local_addr.s_addr != iaddr.s_addr) {
00584                                         DEBUG(DEBUG_INFO,
00585                                               "Address changed to %s\n",
00586                                               inet_ntoa(iaddr));
00587                                         mn.local_addr.s_addr = iaddr.s_addr;
00588                                 }
00589                         }
00590                         find_agent(STATE_INIT);
00591                         memcpy(&api_addr, &addr, sizeof(addr));
00592                         api_addr_len = addrlen;
00593                         /* this API call is replied with reply_waiting_api
00594                          * after the status of the connection attempt is known
00595                          */
00596                 } else {
00597                         api_send_reply(sock, &addr, addrlen, API_NOT_PERMITTED,
00598                                        NULL, 0);
00599                 }
00600                 break;
00601         case API_UPDATE_LOCATION:
00602                 DEBUG(DEBUG_API, "api update location\n");
00603                 if (!admin) break;
00604                 check_interfaces(mn.iface, MAX_INTERFACES);
00605                 handle_api_locupd(sock, &addr, addrlen, &msg, 0);
00606                 break;
00607         case API_UPDATE_LOCATION_BLOCK:
00608                 DEBUG(DEBUG_API, "api update location (block)\n");
00609                 if (!admin) break;
00610                 check_interfaces(mn.iface, MAX_INTERFACES);
00611                 handle_api_locupd(sock, &addr, addrlen, &msg, 1);
00612                 memcpy(&api_addr, &addr, sizeof(addr));
00613                 api_addr_len = addrlen;
00614                 /* this API call is replied with reply_waiting_api
00615                  * after the status of the connection attempt is known */
00616                 break;
00617         case API_CANCEL:
00618                 DEBUG(DEBUG_API, "Cancel received.\n");
00619                 if (!admin) break;
00620 
00621                 api_send_reply(sock, &addr, addrlen, API_SUCCESS, NULL, 0);
00622                 break;
00623         case API_DISCONNECT:
00624                 DEBUG(DEBUG_API, "api disconnect\n");
00625                 if (!admin) break;
00626                 check_interfaces(mn.iface, MAX_INTERFACES);
00627                 disconnect();
00628                 api_send_reply(sock, &addr, addrlen, API_SUCCESS, NULL, 0);
00629                 break;
00630         case API_GET_CAREOF_ADDR:
00631                 api_send_reply(sock, &addr, addrlen, API_SUCCESS,
00632                                (unsigned char *) &mn.co_addr,
00633                                sizeof(mn.co_addr));
00634                 break;
00635         case API_GET_TUNNELING_MODE:
00636                 api_send_reply(sock, &addr, addrlen, API_SUCCESS,
00637                                (unsigned char *) &mn.tunnel_mode, sizeof(int));
00638                 break;
00639         case API_GET_STATUS:
00640                 api_send_reply(sock, &addr, addrlen, API_SUCCESS,
00641                                (unsigned char *) get_mobile_status(),
00642                                sizeof(struct dynamics_mobile_status));
00643                 break;
00644         case API_CONFIRM:
00645                 DEBUG(DEBUG_API, "api confirm\n");
00646                 if (!admin) break;
00647                 if (mn.state != MN_CONNECTED &&
00648                     mn.state != MN_REQUEST_TUNNEL)  {
00649                         api_send_reply(sock, &addr, addrlen,
00650                                        API_NOT_PERMITTED, NULL, 0);
00651                         break;
00652 
00653                 }
00654                 memcpy(&api_addr, &addr, sizeof(addr));
00655                 api_addr_len = addrlen;
00656                 request_tunnel(STATE_INIT, 1, 0);
00657                 break;
00658         case API_FORCE_FA:
00659                 DEBUG(DEBUG_API, "api force fa\n");
00660                 if (!admin) break;
00661                 handle_api_force_fa(sock, &addr, addrlen, &msg);
00662                 break;
00663         case API_GET_FA_LIST:
00664                 DEBUG(DEBUG_API, "api get fa list\n");
00665                 handle_api_get_fa_list(sock, &addr, addrlen, &msg);
00666                 break;
00667         case API_GET_FA_INFO:
00668                 DEBUG(DEBUG_API, "api get fa info\n");
00669                 handle_api_get_fa_info(sock, &addr, addrlen, &msg);
00670                 break;
00671 #ifdef WITH_WIRELESS
00672         case API_IW_GET_CH:
00673                 DEBUG(DEBUG_API, "api get wireless channel info\n");
00674                 handle_api_get_iw_ch(sock, &addr, addrlen, &msg);
00675                 break;
00676         case API_IW_SET_CH:
00677                 DEBUG(DEBUG_API, "api set wireless channel info\n");
00678                 if (!admin) break;
00679                 handle_api_set_iw_ch(sock, &addr, addrlen, &msg);
00680                 break;
00681 #endif
00682         case API_RESCAN:
00683                 DEBUG(DEBUG_API, "api rescan interfaces\n");
00684                 handle_api_rescan(sock, &addr, addrlen, &msg);
00685                 break;
00686         case API_REGISTER_DEV_INFO_SOCKET:
00687                 DEBUG(DEBUG_API, "api register dev info socket\n");
00688                 if (!admin) break;
00689                 handle_register_dev_info_socket(sock, &addr, addrlen, &msg);
00690                 break;
00691         case API_POLICY_OFF:
00692                 DEBUG(DEBUG_API, "api policy off\n");
00693                 if (!admin) break;
00694                 handle_policy(sock, &addr, addrlen, &msg, 0);
00695                 break;
00696         case API_POLICY_ON:
00697                 DEBUG(DEBUG_API, "api policy on\n");
00698                 if (!admin) break;
00699                 handle_policy(sock, &addr, addrlen, &msg, 1);
00700                 break;
00701         case API_GET_POLICY:
00702                 DEBUG(DEBUG_API, "api get policy\n");
00703                 handle_get_policy(sock, &addr, addrlen, &msg);
00704                 break;
00705 #ifdef WITH_WIRELESS
00706         case API_GET_MON_CONF:
00707                 DEBUG(DEBUG_API, "api get mon conf\n");
00708                 handle_mon_conf(sock, &addr, addrlen, &msg, GET_MONCONF);
00709                 break;
00710         case API_GET_MON_CONF_VAR:
00711                 DEBUG(DEBUG_API, "api get mon conf var\n");
00712                 handle_mon_conf(sock, &addr, addrlen, &msg, GET_MONCONF_VAR);
00713                 break;
00714         case API_SET_MON_CONF_VAR:
00715                 DEBUG(DEBUG_API, "api set mon conf\n");
00716                 if (!admin) break;
00717                 handle_mon_conf(sock, &addr, addrlen, &msg, SET_MONCONF_VAR);
00718                 break;
00719 #endif
00720         default:
00721                 /* Just send a message indicating that the function is not
00722                  * supported. No need to confirm that message gets through. */
00723                 DEBUG(DEBUG_API, "api call not supported\n");
00724                 api_send_reply(sock, &addr, addrlen, API_NOT_SUPPORTED, NULL,
00725                                0);
00726                 break;
00727         }
00728 }
00729 
00730 
00731 /*
00732  * Reply to possibly waiting API call.
00733  * Parameters:
00734  *  code - error code to return
00735  */
00736 void reply_waiting_api(int code, unsigned char *data, int datalen)
00737 {
00738 #ifdef DYN_TARGET_LINUX
00739         if (api_addr_len > 0) {
00740 #endif
00741 #ifdef DYN_TARGET_WINDOWS
00742         if (api_addr.sin_port != 0) {
00743 #endif
00744                 DEBUG(DEBUG_API, "Replying to waiting API call\n");
00745                 api_send_reply(mn.api_rw_socket, &api_addr, api_addr_len, code,
00746                                data, datalen);
00747                 memset(&api_addr, 0, sizeof(api_addr));
00748                 api_addr_len = 0;
00749         } else DEBUG(DEBUG_API, "reply_waiting_api: no waiting call\n");
00750 }

Generated on Tue Jan 15 08:50:43 2008 for Virtual foreign agent generator version 0.1 by  doxygen 1.5.1