diff options
Diffstat (limited to 'src/irmd')
| -rw-r--r-- | src/irmd/main.c | 265 | 
1 files changed, 146 insertions, 119 deletions
| diff --git a/src/irmd/main.c b/src/irmd/main.c index 03f9a3c2..db96b6ed 100644 --- a/src/irmd/main.c +++ b/src/irmd/main.c @@ -72,14 +72,16 @@ struct reg_name_entry {          /* FIXME: make a list resolve to AP-I instead */          instance_name_t  * api; +        char **            argv; +        bool               autoexec;          bool   accept; -        char * req_ap_name;          char * req_ae_name;          int    response;          int    flow_arrived;          pthread_cond_t  acc_signal; +        pthread_cond_t  acc_arr_signal;          pthread_mutex_t acc_lock;  }; @@ -264,11 +266,17 @@ static struct reg_name_entry * reg_name_entry_create()          e->name         = NULL;          e->api          = NULL; +        e->argv         = NULL; +        e->autoexec     = false;          e->accept       = false; -        e->req_ap_name  = NULL;          e->req_ae_name  = NULL;          e->flow_arrived = -1; +        if (pthread_cond_init(&e->acc_arr_signal, NULL)) { +                free(e); +                return NULL; +        } +          if (pthread_cond_init(&e->acc_signal, NULL)) {                  free(e);                  return NULL; @@ -286,13 +294,17 @@ static struct reg_name_entry * reg_name_entry_create()  static struct reg_name_entry * reg_name_entry_init(struct reg_name_entry * e,                                                     char *                  name, -                                                   instance_name_t *       api) +                                                   instance_name_t *       api, +                                                   char **                 argv, +                                                   bool                    ae)  {          if (e == NULL || name == NULL || api == NULL)                  return NULL; -        e->name = name; -        e->api  = api; +        e->name     = name; +        e->api      = api; +        e->argv     = argv; +        e->autoexec = ae;          return e;  } @@ -306,7 +318,7 @@ static int reg_name_entry_destroy(struct reg_name_entry * e)                  pthread_mutex_lock(&e->acc_lock);                  e->flow_arrived = -2;                  pthread_mutex_unlock(&e->acc_lock); -                pthread_cond_broadcast(&e->acc_signal); +                pthread_cond_broadcast(&e->acc_arr_signal);                  sched_yield();          } @@ -335,6 +347,21 @@ static struct reg_name_entry * get_reg_name_entry_by_name(char * name)          return NULL;  } +static struct reg_name_entry * get_reg_name_entry_by_ap_name(char * ap_name) +{ +        struct list_head * pos = NULL; + +        list_for_each(pos, &instance->reg_names) { +                struct reg_name_entry * e = +                        list_entry(pos, struct reg_name_entry, next); + +                if (strcmp(ap_name, e->api->name) == 0) +                        return e; +        } + +        return NULL; +} +  static struct reg_name_entry * get_reg_name_entry_by_id(pid_t pid)  {          struct list_head * pos = NULL; @@ -351,7 +378,10 @@ static struct reg_name_entry * get_reg_name_entry_by_id(pid_t pid)  }  /* FIXME: add only name when we have NSM solved */ -static int reg_name_entry_add_name_instance(char * name, instance_name_t * api) +static int reg_name_entry_add_name_instance(char *            name, +                                            instance_name_t * api, +                                            char **           argv, +                                            bool              autoexec)  {          struct reg_name_entry * e = get_reg_name_entry_by_name(name);          if (e == NULL) { @@ -359,7 +389,8 @@ static int reg_name_entry_add_name_instance(char * name, instance_name_t * api)                  if (e == NULL)                          return -1; -                if (reg_name_entry_init(e, name, api) == NULL) { +                if (reg_name_entry_init(e, name, api, argv, autoexec) +                    == NULL) {                          reg_name_entry_destroy(e);                          return -1;                  } @@ -595,46 +626,12 @@ static int enroll_ipcp(instance_name_t  * api,          return 0;  } -static int reg_ipcp(instance_name_t * api, -                    char **           difs, -                    size_t            difs_size) -{ -        rw_lock_rdlock(&instance->state_lock); -        rw_lock_wrlock(&instance->reg_lock); - -        if (ipcp_reg(api->id, difs, difs_size)) { -                rw_lock_unlock(&instance->reg_lock); -                rw_lock_unlock(&instance->state_lock); -                LOG_ERR("Could not register IPCP to N-1 DIF(s)."); -                return -1; -        } - -        rw_lock_unlock(&instance->reg_lock); -        rw_lock_unlock(&instance->state_lock); - -        return 0; -} - -static int unreg_ipcp(instance_name_t  * api, -                      char **            difs, -                      size_t             difs_size) -{ -        rw_lock_rdlock(&instance->state_lock); -        rw_lock_wrlock(&instance->reg_lock); -        if (ipcp_unreg(api->id, difs, difs_size)) { -                rw_lock_unlock(&instance->reg_lock); -                rw_lock_unlock(&instance->state_lock); -                LOG_ERR("Could not unregister IPCP from N-1 DIF(s)."); -                return -1; -        } -        rw_lock_unlock(&instance->reg_lock); -        rw_lock_unlock(&instance->state_lock); - -        return 0; -} - -static int ap_reg(char *  ap_name, +static int ap_reg(char *  name, +                  char *  ap_name,                    pid_t   ap_id, +                  int     argc, +                  char ** argv, +                  bool    autoexec,                    char ** difs,                    size_t  len)  { @@ -644,6 +641,7 @@ static int ap_reg(char *  ap_name,          struct reg_name_entry * rne = NULL;          instance_name_t * api   = NULL; +        char ** argv_dup = NULL;          rw_lock_rdlock(&instance->state_lock);          rw_lock_wrlock(&instance->reg_lock); @@ -661,16 +659,15 @@ static int ap_reg(char *  ap_name,                  return -1;          } -        if (instance_name_init_from(api, ap_name, ap_id) == NULL) { +        if (instance_name_init_from(api, path_strip(ap_name), ap_id) == NULL) {                  rw_lock_unlock(&instance->reg_lock);                  rw_lock_unlock(&instance->state_lock);                  instance_name_destroy(api);                  return -1;          } -        /* check if this ap_name is already registered */ - -        rne = get_reg_name_entry_by_name(ap_name); +        /* check if this name is already registered */ +        rne = get_reg_name_entry_by_name(name);          if (rne != NULL) {                  rw_lock_unlock(&instance->reg_lock);                  rw_lock_unlock(&instance->state_lock); @@ -678,11 +675,6 @@ static int ap_reg(char *  ap_name,                  return -1; /* can only register one instance for now */          } -        /* -         * for now, the whatevercast name is the same as the ap_name and -         * contains a single instance only -         */ -          list_for_each(pos, &instance->ipcps) {                  struct ipcp_entry * e =                          list_entry(pos, struct ipcp_entry, next); @@ -692,26 +684,42 @@ static int ap_reg(char *  ap_name,                  for (i = 0; i < len; ++i) {                          if (wildcard_match(difs[i], e->dif_name) == 0) { -                                if (ipcp_name_reg(e->api->id, ap_name)) { +                                if (ipcp_name_reg(e->api->id, name)) {                                          LOG_ERR("Could not register " -                                                "%s in DIF %s.", -                                                api->name, e->dif_name); +                                                "%s in DIF %s as %s.", +                                                api->name, e->dif_name, name);                                  } else { +                                        LOG_INFO("Registered %s as %s in %s", +                                                 api->name, name, e->dif_name);                                          ++ret;                                  }                          }                  }          } -          if (ret ==  0) {                  rw_lock_unlock(&instance->reg_lock);                  rw_lock_unlock(&instance->state_lock);                  instance_name_destroy(api);                  return -1;          } + +        /* we need to duplicate argv */ +        if (argc != 0) { +                argv_dup = malloc((argc + 2) * sizeof(*argv_dup)); +                argv_dup[0] = strdup(api->name); +                for (i = 1; i <= argc; ++i) +                        argv_dup[i] = strdup(argv[i - 1]); +                argv_dup[argc + 1] = NULL; +        } + +          /* for now, we register single instances */ -        ret = reg_name_entry_add_name_instance(strdup(ap_name), -                                               api); +        if ((ret = reg_name_entry_add_name_instance(strdup(name), +                                                    api, +                                                    argv_dup, +                                                    autoexec)) +            < 0) +                LOG_DBGF("Failed to add application %s.", api->name);          rw_lock_unlock(&instance->reg_lock);          rw_lock_unlock(&instance->state_lock); @@ -719,38 +727,28 @@ static int ap_reg(char *  ap_name,          return ret;  } -static int ap_unreg(char *  ap_name, +static int ap_unreg(char *  name, +                    char *  ap_name,                      pid_t   ap_id,                      char ** difs, -                    size_t  len) +                    size_t  len, +                    bool    hard)  {          int i;          int ret = 0;          struct reg_name_entry * rne = NULL;          struct list_head      * pos = NULL; +        if (name == NULL || len == 0 || difs == NULL || difs[0] == NULL) +                return -1; +          rw_lock_rdlock(&instance->state_lock);          rw_lock_wrlock(&instance->reg_lock); -        /* check if ap_name is registered */ -        rne = get_reg_name_entry_by_id(ap_id); -        if (rne == NULL) { -                rw_lock_unlock(&instance->reg_lock); -                rw_lock_unlock(&instance->state_lock); -                return 0; /* no such id */ -        } - -        if (strcmp(ap_name, rne->api->name)) { -                rw_lock_unlock(&instance->reg_lock); -                rw_lock_unlock(&instance->state_lock); -                return 0; -        } - -        if (instance->ipcps.next == NULL) { -                rw_lock_unlock(&instance->reg_lock); -                rw_lock_unlock(&instance->state_lock); -                LOG_ERR("No IPCPs in this system."); -                return 0; +        if (!hard && strcmp(difs[0], "*") != 0) { +                LOG_INFO("Unregistration not complete yet."); +                LOG_MISSING; +                return -1;          }          list_for_each(pos, &instance->ipcps) { @@ -762,7 +760,8 @@ static int ap_unreg(char *  ap_name,                  for (i = 0; i < len; ++i) {                          if (wildcard_match(difs[i], e->dif_name) == 0) { -                                if (ipcp_name_unreg(e->api->id, rne->name)) { +                                if (ipcp_name_unreg(e->api->id, +                                                    rne->name)) {                                          LOG_ERR("Could not unregister "                                                  "%s in DIF %s.",                                                  rne->name, e->dif_name); @@ -772,7 +771,6 @@ static int ap_unreg(char *  ap_name,                  }          } -        /* FIXME: check if name is not registered in any DIF before removing */          reg_name_entry_del_name(rne->name);          rw_lock_unlock(&instance->reg_lock); @@ -782,8 +780,8 @@ static int ap_unreg(char *  ap_name,  }  static struct port_map_entry * flow_accept(pid_t    pid, -                                           char **  ap_name, -                                           char **  ae_name) +                                           char *   srv_ap_name, +                                           char **  dst_ae_name)  {          struct port_map_entry * pme;          struct reg_name_entry * rne = NULL; @@ -791,11 +789,21 @@ static struct port_map_entry * flow_accept(pid_t    pid,          rw_lock_rdlock(&instance->state_lock);          rw_lock_rdlock(&instance->reg_lock); -        rne = get_reg_name_entry_by_id(pid); +        rne = get_reg_name_entry_by_ap_name(srv_ap_name);          if (rne == NULL) {                  rw_lock_unlock(&instance->reg_lock);                  rw_lock_unlock(&instance->state_lock); -                LOG_DBGF("Unregistered AP calling accept()."); +                LOG_DBGF("AP %s is unknown.", srv_ap_name); +                return NULL; +        } + +        if (rne->api->id == 0) { +                rne->api->id = pid; +        } else if (rne->api->id != pid) { +                rw_lock_unlock(&instance->reg_lock); +                rw_lock_unlock(&instance->state_lock); +                LOG_DBGF("Can only register one instance."); +                LOG_MISSING;                  return NULL;          } @@ -809,6 +817,8 @@ static struct port_map_entry * flow_accept(pid_t    pid,          rne->accept       = true;          rne->flow_arrived = -1; +        pthread_cond_broadcast(&rne->acc_signal); +          rw_lock_unlock(&instance->reg_lock);          rw_lock_unlock(&instance->state_lock); @@ -817,7 +827,7 @@ static struct port_map_entry * flow_accept(pid_t    pid,                               (void*) &rne->acc_lock);          while (rne->flow_arrived == -1) -                pthread_cond_wait(&rne->acc_signal, &rne->acc_lock); +                pthread_cond_wait(&rne->acc_arr_signal, &rne->acc_lock);          pthread_mutex_unlock(&rne->acc_lock);          pthread_cleanup_pop(0); @@ -843,9 +853,8 @@ static struct port_map_entry * flow_accept(pid_t    pid,                  return NULL;          } -        *ap_name = rne->req_ap_name; -        if (ae_name != NULL) -                *ae_name = rne->req_ae_name; +        if (dst_ae_name != NULL) +                *dst_ae_name = rne->req_ae_name;          rw_lock_unlock(&instance->flows_lock);          rw_lock_unlock(&instance->state_lock); @@ -919,7 +928,6 @@ static int flow_alloc_resp(pid_t n_pid,  static struct port_map_entry * flow_alloc(pid_t  pid,                                            char * dst_name, -                                          char * src_ap_name,                                            char * src_ae_name,                                            struct qos_spec * qos)  { @@ -967,7 +975,6 @@ static struct port_map_entry * flow_alloc(pid_t  pid,                              pme->port_id,                              pme->n_pid,                              dst_name, -                            src_ap_name,                              src_ae_name,                              QOS_CUBE_BE) < 0) {                  rw_lock_rdlock(&instance->state_lock); @@ -1085,9 +1092,30 @@ static int flow_dealloc(int port_id)          return ret;  } +static int auto_execute(char * ap, char ** argv) +{ +        pid_t pid; +        LOG_INFO("Executing %s.", ap); +        pid = fork(); +        if (pid == -1) { +                LOG_ERR("Failed to fork"); +                return pid; +        } + +        if (pid != 0) { +                return pid; +        } + +        execv(ap, argv); + +        LOG_ERR("Failed to execute."); + +        exit(EXIT_FAILURE); +        return 0; +} +  static struct port_map_entry * flow_req_arr(pid_t  pid,                                              char * dst_name, -                                            char * ap_name,                                              char * ae_name)  {          struct reg_name_entry * rne; @@ -1125,20 +1153,27 @@ static struct port_map_entry * flow_req_arr(pid_t  pid,          pthread_mutex_lock(&rne->acc_lock); -        rne->req_ap_name = ap_name;          rne->req_ae_name = ae_name;          if (rne->accept == false) { -                pthread_mutex_unlock(&rne->acc_lock); -                LOG_WARN("This AP is not accepting flow allocations."); -                return NULL; +                if (rne->autoexec) { +                        pme->n_pid = auto_execute(rne->api->name, rne->argv); +                        while (rne->accept == false) +                                pthread_cond_wait(&rne->acc_signal, +                                                  &rne->acc_lock); +                } else { +                        pthread_mutex_unlock(&rne->acc_lock); +                        LOG_WARN("%s is not accepting flow allocations.", +                                 rne->name); +                        return NULL; +                }          }          rne->flow_arrived = 0;          pthread_mutex_unlock(&rne->acc_lock); -        if (pthread_cond_signal(&rne->acc_signal)) +        if (pthread_cond_signal(&rne->acc_arr_signal))                  LOG_ERR("Failed to send signal.");          while (acc_wait) { @@ -1345,35 +1380,29 @@ void * mainloop()                          ret_msg.result = enroll_ipcp(&api,                                                       msg->dif_name[0]);                          break; -                case IRM_MSG_CODE__IRM_REG_IPCP: -                        ret_msg.has_result = true; -                        ret_msg.result = reg_ipcp(&api, -                                                  msg->dif_name, -                                                  msg->n_dif_name); -                        break; -                case IRM_MSG_CODE__IRM_UNREG_IPCP: -                        ret_msg.has_result = true; -                        ret_msg.result = unreg_ipcp(&api, -                                                    msg->dif_name, -                                                    msg->n_dif_name); -                        break;                  case IRM_MSG_CODE__IRM_AP_REG:                          ret_msg.has_result = true; -                        ret_msg.result = ap_reg(msg->ap_name, +                        ret_msg.result = ap_reg(msg->dst_name, +                                                msg->ap_name,                                                  msg->pid, +                                                msg->n_args, +                                                msg->args, +                                                msg->autoexec,                                                  msg->dif_name,                                                  msg->n_dif_name);                          break;                  case IRM_MSG_CODE__IRM_AP_UNREG:                          ret_msg.has_result = true; -                        ret_msg.result = ap_unreg(msg->ap_name, +                        ret_msg.result = ap_unreg(msg->dst_name, +                                                  msg->ap_name,                                                    msg->pid,                                                    msg->dif_name, -                                                  msg->n_dif_name); +                                                  msg->n_dif_name, +                                                  msg->hard);                          break;                  case IRM_MSG_CODE__IRM_FLOW_ACCEPT:                          e = flow_accept(msg->pid, -                                        &ret_msg.ap_name, +                                        msg->ap_name,                                          &ret_msg.ae_name);                          if (e == NULL) @@ -1393,7 +1422,6 @@ void * mainloop()                  case IRM_MSG_CODE__IRM_FLOW_ALLOC:                          e = flow_alloc(msg->pid,                                         msg->dst_name, -                                       msg->ap_name,                                         msg->ae_name,                                         NULL);                          if (e == NULL) @@ -1415,7 +1443,6 @@ void * mainloop()                  case IRM_MSG_CODE__IPCP_FLOW_REQ_ARR:                          e = flow_req_arr(msg->pid,                                           msg->dst_name, -                                         msg->ap_name,                                           msg->ae_name);                          if (e == NULL)                                  break; | 
