コード例 #1
0
ファイル: session.c プロジェクト: tidatida/lagopus
lagopus_result_t
session_bind(lagopus_session_t s, struct addrunion *saddr, uint16_t sport) {
  int ret;
  char addr[256];
  char port[16];

  if (s == NULL || saddr == NULL || sport == 0) {
    lagopus_msg_warning("session is null.\n");
    return LAGOPUS_RESULT_ANY_FAILURES;
  }

  inet_ntop(saddr->family, &saddr->addr4, addr, sizeof(addr));
  snprintf(port, sizeof(port), "%d", sport);
  ret = bind_default(s, addr, port);
  if (ret < 0) {
    lagopus_msg_warning("bind_default error.\n");
    return LAGOPUS_RESULT_POSIX_API_ERROR;
  }

  if (s->session_type & SESSION_PASSIVE) {
    ret = listen(s->sock, SOMAXCONN);
    if (ret < 0) {
      return LAGOPUS_RESULT_POSIX_API_ERROR;
    }
  }

  return LAGOPUS_RESULT_OK;
}
コード例 #2
0
lagopus_result_t
ofp_port_status_handle(struct port_status *port_status, uint64_t dpid) {
  lagopus_result_t ret;
  struct pbuf *send_pbuf = NULL;

  if (port_status != NULL) {
    /* PortStatus. */
    ret = ofp_port_status_create(port_status, &send_pbuf);
    if (ret == LAGOPUS_RESULT_OK) {
      ret = ofp_role_channel_write(send_pbuf, dpid,
                                   OFPT_PORT_STATUS,
                                   port_status->ofp_port_status.reason);
      if (ret != LAGOPUS_RESULT_OK) {
        lagopus_msg_warning("Socket write error (%s).\n",
                            lagopus_error_get_string(ret));
      }
    } else {
      lagopus_msg_warning("FAILED : ofp_port_status_create (%s).\n",
                          lagopus_error_get_string(ret));
    }

    /* free. */
    if (send_pbuf != NULL) {
      pbuf_free(send_pbuf);
    }
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
コード例 #3
0
ファイル: ofp_header_handler.c プロジェクト: tidatida/lagopus
bool
ofp_header_version_check(struct channel *channel,
                         struct ofp_header *header) {
  bool ret = false;
  uint8_t bridge_ofp_version;
  uint64_t dpid;

  if (channel != NULL && header != NULL) {
    dpid = channel_dpid_get(channel);
    ret = dpmgr_bridge_ofp_version_get(dpid, &bridge_ofp_version);

    if (ret == LAGOPUS_RESULT_OK) {
      if (bridge_ofp_version == header->version) {
        ret = true;
      } else {
        lagopus_msg_warning("Unsupported ofp version : %"PRIu8".\n",
                            header->version);
        ret = false;
      }
    } else {
      lagopus_msg_warning("FAILED (%s).\n",
                          lagopus_error_get_string(ret));
      ret = false;
    }
  } else {
    lagopus_msg_warning("Arg is NULL.\n");
    ret = false;
  }

  return ret;
}
コード例 #4
0
ファイル: callout.c プロジェクト: 1514louluo/lagopus
void
lagopus_callout_finalize_handler(void) {
  if (s_is_handler_inited == true) {
    lagopus_result_t r = LAGOPUS_RESULT_ANY_FAILURES;

    /*
     * Stop the main loop first then shutdown/wait/destroy the callout
     * stage/workers.
     */
    if (likely((r = s_stop_callout_main_loop()) == LAGOPUS_RESULT_OK)) {
      if (likely(s_n_workers > 0)) {
        r = s_finish_callout_stage(CALLOUT_STAGE_SHUTDOWN_TIMEOUT);
        if (unlikely(r != LAGOPUS_RESULT_OK)) {
          lagopus_perror(r);
          lagopus_msg_warning("failed to stop the callout stage so the "
                              "callout queues still remain.\n");
          goto done;
        }
      }

      s_destroy_all_queued_timed_tasks();
      (void)lagopus_bbq_clear(&s_urgent_tsk_q, true);
      (void)lagopus_bbq_clear(&s_idle_tsk_q, true);

    } else {
      lagopus_perror(r);
      lagopus_msg_warning("failed to stop the callout scheduler main loop.\n");
    }

 done:
    s_is_handler_inited = false;
  }
}
コード例 #5
0
static lagopus_result_t
s_parse_bucket_list(struct pbuf *pbuf,
                    struct bucket_list *bucket_list,
                    struct ofp_error *error) {
  lagopus_result_t res = LAGOPUS_RESULT_OK;
  if (TAILQ_EMPTY(bucket_list) == true && pbuf_plen_get(pbuf) == 0) {
    res = LAGOPUS_RESULT_OK;    /* bucket_list is empty */
  } else {
    /* decode buckets. */
    while (pbuf_plen_get(pbuf) > 0) {
      res = ofp_bucket_parse(pbuf, bucket_list, error);
      if (res != LAGOPUS_RESULT_OK) {
        lagopus_msg_warning("FAILED : ofp_bucket_parse (%s).\n",
                            lagopus_error_get_string(res));
        break;
      }
    }
    /* check plen. */
    if (res == LAGOPUS_RESULT_OK && pbuf_plen_get(pbuf) > 0) {
      lagopus_msg_warning("packet decode failed. (size over).\n");
      ofp_error_set(error, OFPET_GROUP_MOD_FAILED,
                    OFPGMFC_BAD_BUCKET);
      res = LAGOPUS_RESULT_OFP_ERROR;
    }
  }
  return res;
}
コード例 #6
0
/* Experimenter packet receive. */
lagopus_result_t
ofp_experimenter_request_handle(struct channel *channel, struct pbuf *pbuf,
                                struct ofp_header *xid_header) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;
  struct pbuf *send_pbuf = NULL;
  struct ofp_experimenter_header exper_req;

  if (channel != NULL && pbuf != NULL &&
      xid_header != NULL) {
    /* Parse packet. */
    ret = ofp_experimenter_header_decode(pbuf, &exper_req);
    if (ret == LAGOPUS_RESULT_OK) {
      /* Experimenter request reply. */
      ret = ofp_experimenter_reply_create(channel, &send_pbuf,
                                          xid_header, &exper_req);
      if (ret == LAGOPUS_RESULT_OK) {
        channel_send_packet(channel, send_pbuf);
        ret = LAGOPUS_RESULT_OK;
      } else {
        lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret));
      }
    } else {
      lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret));
      ret = LAGOPUS_RESULT_OFP_ERROR;
    }

    if (ret != LAGOPUS_RESULT_OK && send_pbuf != NULL) {
      channel_pbuf_list_unget(channel, send_pbuf);
    }
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
コード例 #7
0
/* Send PacketIn packet. */
lagopus_result_t
ofp_packet_in_handle(struct packet_in *packet_in,
                     uint64_t dpid) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;
  struct pbuf *send_pbuf = NULL;

  if (packet_in != NULL && packet_in->data != NULL) {
    /* PacketIn. */
    ret = ofp_packet_in_create(packet_in, &send_pbuf);

    if (ret == LAGOPUS_RESULT_OK) {
      ret = ofp_role_channel_write(send_pbuf, dpid,
                                   OFPT_PACKET_IN,
                                   packet_in->ofp_packet_in.reason);
      if (ret != LAGOPUS_RESULT_OK) {
        lagopus_msg_warning("Socket write error (%s).\n",
                            lagopus_error_get_string(ret));
      }
    } else {
      lagopus_msg_warning("FAILED (%s).\n",
                          lagopus_error_get_string(ret));
    }
  } else {
    lagopus_msg_warning("Arg is NULL.\n");
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  /* free. */
  if (send_pbuf != NULL) {
    pbuf_free(send_pbuf);
  }

  return ret;
}
コード例 #8
0
ファイル: session.c プロジェクト: tidatida/lagopus
lagopus_result_t
session_connect_check(lagopus_session_t s) {
  int ret0, value;
  lagopus_result_t ret1;
  socklen_t len = sizeof(value);

  if (s == NULL) {
    lagopus_msg_warning("session is null.\n");
    return LAGOPUS_RESULT_ANY_FAILURES;
  }

  ret0 = getsockopt(s->sock, SOL_SOCKET, SO_ERROR, (void *)&value, &len);
  if (ret0 < 0) {
    lagopus_msg_warning("getsockopt error %d.\n", errno);
    return LAGOPUS_RESULT_ANY_FAILURES;
  } else if (value != 0) {
    lagopus_msg_warning("getsockopt value error %d.\n", value);
    return LAGOPUS_RESULT_SOCKET_ERROR;
  }

  if (s->connect_check) {
    ret1 = s->connect_check(s);
  } else {
    ret1 = LAGOPUS_RESULT_OK;
  }

  return ret1;
}
コード例 #9
0
ファイル: ofp_role.c プロジェクト: D-TOKIOKA/lagopus
bool
ofp_role_generation_id_check(uint64_t dpid,
                             uint32_t role,
                             uint64_t generation_id) {
  uint64_t gen;
  lagopus_result_t ret;

  if (role != OFPCR_ROLE_MASTER && role != OFPCR_ROLE_SLAVE) {
    /* do not care */
    return true;
  }

  ret = channel_mgr_generation_id_get(dpid, &gen);
  if (ret == LAGOPUS_RESULT_OK && distance(generation_id, gen) < 0) {
    lagopus_msg_warning("generation_id was already updated(old: %ld, new:%ld).\n",
                        gen, generation_id);
    return false;
  } else if (ret != LAGOPUS_RESULT_OK && ret != LAGOPUS_RESULT_NOT_DEFINED) {
    return false;
  }

  ret = channel_mgr_generation_id_set(dpid, generation_id);
  if (ret != LAGOPUS_RESULT_OK) {
    lagopus_msg_warning("generation_id update failed(old: %ld, new:%ld).\n",
                        gen, generation_id);
    return false;
  }

  return true;
}
コード例 #10
0
/* Group mod received. */
lagopus_result_t
ofp_group_mod_handle(struct channel *channel, struct pbuf *pbuf,
                     struct ofp_header *xid_header,
                     struct ofp_error *error) {
  lagopus_result_t res = LAGOPUS_RESULT_ANY_FAILURES;
  uint64_t dpid;
  struct ofp_group_mod group_mod;

  /* check params */
  if (channel != NULL && pbuf != NULL &&
      xid_header != NULL && error != NULL) {
    /* Parse group_mod header. */
    res = ofp_group_mod_decode(pbuf, &(group_mod));
    if (res == LAGOPUS_RESULT_OK) {
      /* check type */
      res = s_group_type_check(group_mod.type, error);
      if (res == LAGOPUS_RESULT_OK) {
        /* exec group_mod command. */
        dpid = channel_dpid_get(channel);
        switch (group_mod.command) {
          case OFPGC_ADD:
            res = s_ofpgc_add(pbuf, dpid,
                              &group_mod, error);
            break;
          case OFPGC_MODIFY:
            res = s_ofpgc_modify(pbuf, dpid,
                                 &group_mod, error);
            break;
          case OFPGC_DELETE:
            res = s_ofpgc_delete(pbuf, dpid,
                                 &group_mod, error);
            break;
          default:
            lagopus_msg_warning("unknown group_mod command.\n");
            ofp_error_set(error, OFPET_GROUP_MOD_FAILED, OFPGMFC_BAD_COMMAND);
            res = LAGOPUS_RESULT_OFP_ERROR;
            break;
        }
      }

      if (res != LAGOPUS_RESULT_OK) {
        lagopus_msg_warning("FAILED (%s).\n",
                            lagopus_error_get_string(res));
      }
    } else {
      lagopus_msg_warning("group_mod decode error (%s)\n",
                          lagopus_error_get_string(res));
      ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
      res = LAGOPUS_RESULT_OFP_ERROR;
    }
  } else {
    /* params are NULL */
    res = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return res;
}
コード例 #11
0
lagopus_result_t
ofp_get_async_request_handle(struct channel *channel,
                             struct pbuf *pbuf,
                             struct ofp_header *xid_header,
                             struct ofp_error *error) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;
  struct pbuf *send_pbuf = NULL;

  /* check params */
  if (channel != NULL && pbuf != NULL &&
      xid_header != NULL && error != NULL) {

    ret = pbuf_plen_check(pbuf, xid_header->length);

    if (ret == LAGOPUS_RESULT_OK) {
      /* Parse packet. */
      ret = ofp_header_handle(channel, pbuf, error);

      if (ret == LAGOPUS_RESULT_OK) {
        /* dump trace. */
        get_async_request_trace(xid_header);

        /* Reply send.*/
        ret = ofp_get_async_reply_create(channel, &send_pbuf,
                                         xid_header);

        if (ret == LAGOPUS_RESULT_OK) {
          channel_send_packet(channel, send_pbuf);
        } else {
          lagopus_msg_warning("FAILED (%s).\n",
                              lagopus_error_get_string(ret));
        }
      } else {
        lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret));
        ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
        ret = LAGOPUS_RESULT_OFP_ERROR;
      }

      if (ret != LAGOPUS_RESULT_OK && send_pbuf != NULL) {
        channel_pbuf_list_unget(channel, send_pbuf);
      }
    } else {
      lagopus_msg_warning("bad length.\n");
      ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
      ret = LAGOPUS_RESULT_OFP_ERROR;
    }
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
コード例 #12
0
/* Port mod received. */
lagopus_result_t
ofp_port_mod_handle(struct channel *channel, struct pbuf *pbuf,
                    struct ofp_header *xid_header,
                    struct ofp_error *error) {
  lagopus_result_t res = LAGOPUS_RESULT_ANY_FAILURES;
  uint64_t dpid;
  struct ofp_port_mod port_mod;

  /* check params */
  if (channel != NULL && pbuf != NULL &&
      xid_header != NULL && error != NULL) {
    /* Parse port_mod header. */
    res = ofp_port_mod_decode(pbuf, &(port_mod));
    if (res != LAGOPUS_RESULT_OK) {
      lagopus_msg_warning("port_mod decode error.\n");
      ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
      res = LAGOPUS_RESULT_OFP_ERROR;
    } else if (pbuf_plen_get(pbuf) > 0) {
      lagopus_msg_warning("packet decode failed. (size over).\n");
      ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
      res = LAGOPUS_RESULT_OFP_ERROR;
    } else {                    /* decode success */
      /* dump trace. */
      port_mod_trace(&port_mod);

      /* check config. */
      res = ofp_port_config_check(port_mod.config, error);
      if (res == LAGOPUS_RESULT_OK) {
        /* check mask. */
        res = ofp_port_config_check(port_mod.mask, error);
        if (res == LAGOPUS_RESULT_OK) {
          /* check advertise. */
          res = ofp_port_features_check(port_mod.advertise, error);
          if (res == LAGOPUS_RESULT_OK) {
            dpid = channel_dpid_get(channel);
            /* call API */
            res = ofp_port_mod_modify(dpid, &port_mod, error);
            if (res != LAGOPUS_RESULT_OK) {
              lagopus_msg_warning("FAILED (%s).\n",
                                  lagopus_error_get_string(res));
            }
          }
        }
      }
    }
  } else {
    res = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return res;
}
コード例 #13
0
ファイル: ofp_header_handler.c プロジェクト: tidatida/lagopus
lagopus_result_t
ofp_header_packet_set(struct channel *channel,
                      struct pbuf *pbuf) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;
  uint16_t cur_length;
  pbuf_info_t cur_pbuf_info;
  pbuf_info_t update_pbuf_info;
  struct ofp_header header;

  if (channel != NULL && pbuf != NULL) {
    /* Store current pbuf info. */
    pbuf_info_store(pbuf, &cur_pbuf_info);
    ret = pbuf_length_get(pbuf, &cur_length);

    if (ret == LAGOPUS_RESULT_OK) {
      /* Update pbuf info for ofp_header_decode_sneak. */
      pbuf_getp_set(&update_pbuf_info, pbuf_data_get(pbuf));
      pbuf_putp_set(&update_pbuf_info,
                    pbuf_data_get(pbuf) + sizeof(struct ofp_header));
      pbuf_plen_set(&update_pbuf_info, sizeof(struct ofp_header));
      pbuf_info_load(pbuf, &update_pbuf_info);

      ret = ofp_header_decode_sneak(pbuf, &header);
      if (ret == LAGOPUS_RESULT_OK) {
        /* Update pbuf info for ofp_header_create. */
        pbuf_reset(pbuf);
        pbuf_plen_set(pbuf, (size_t) cur_length);

        ret = ofp_header_create(channel, header.type, NULL,
                                &header, pbuf);
        if (ret == LAGOPUS_RESULT_OK) {
          /* Load pbuf info. */
          pbuf_info_load(pbuf, &cur_pbuf_info);
        } else {
          lagopus_msg_warning("FAILED (%s).\n",
                              lagopus_error_get_string(ret));
        }
      } else {
        lagopus_msg_warning("FAILED (%s).\n",
                            lagopus_error_get_string(ret));
      }
    } else {
      lagopus_msg_warning("FAILED (%s).\n",
                          lagopus_error_get_string(ret));
    }
  } else {
    return LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
コード例 #14
0
STATIC lagopus_result_t
ofp_role_reply_create(struct channel *channel,
                      struct pbuf **pbuf,
                      struct ofp_header *xid_header,
                      struct ofp_role_request *role_request) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;
  /* reply is ofp_role_request structure. */
  struct ofp_role_request role_reply;

  /* check params */
  if (channel != NULL && pbuf != NULL &&
      xid_header != NULL && role_request != NULL) {
    /* alloc */
    *pbuf = channel_pbuf_list_get(channel,
                                  sizeof(struct ofp_role_request));
    if (*pbuf != NULL) {
      pbuf_plen_set(*pbuf, sizeof(struct ofp_role_request));

      /* Fill in header. */
      ofp_header_set(&role_reply.header,
                     channel_version_get(channel),
                     OFPT_ROLE_REPLY,
                     (uint16_t) pbuf_plen_get(*pbuf),
                     xid_header->xid);

      role_reply.role = role_request->role;
      memset(role_reply.pad, 0, sizeof(role_request->pad));
      role_reply.generation_id = role_request->generation_id;

      /* Encode message. */
      ret = ofp_role_request_encode(*pbuf, &role_reply);
      if (ret != LAGOPUS_RESULT_OK) {
        lagopus_msg_warning("FAILED (%s).\n",
                            lagopus_error_get_string(ret));
      }

      if (ret != LAGOPUS_RESULT_OK && *pbuf != NULL) {
        channel_pbuf_list_unget(channel, *pbuf);
        *pbuf = NULL;
      }
    } else {
      lagopus_msg_warning("Can't allocate pbuf.\n");
      ret = LAGOPUS_RESULT_NO_MEMORY;
    }
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
コード例 #15
0
lagopus_result_t
ofp_meter_features_request_handle(struct channel *channel,
                                  struct pbuf *pbuf,
                                  struct ofp_header *xid_header,
                                  struct ofp_error *error) {
  lagopus_result_t res = LAGOPUS_RESULT_ANY_FAILURES;
  uint64_t dpid;
  struct ofp_meter_features ofp_meter_features;
  struct pbuf_list *send_pbuf_list = NULL;

  /* check params */
  if (channel != NULL && pbuf != NULL &&
      xid_header != NULL && error != NULL) {
    if (pbuf_plen_equal_check(pbuf, 0) == LAGOPUS_RESULT_OK) {
      /* get datas */
      memset(&ofp_meter_features, 0, sizeof(ofp_meter_features));
      dpid = channel_dpid_get(channel);
      res = ofp_meter_features_get(dpid, &ofp_meter_features, error);
      if (res == LAGOPUS_RESULT_OK) {
        /* create desc reply. */
        res = ofp_meter_features_reply_create(channel,
                                              &send_pbuf_list,
                                              &ofp_meter_features,
                                              xid_header);
        if (res == LAGOPUS_RESULT_OK) {
          /* send desc reply */
          res = channel_send_packet_list(channel, send_pbuf_list);
          if (res != LAGOPUS_RESULT_OK) {
            lagopus_msg_warning("Socket write error (%s).\n",
                                lagopus_error_get_string(res));
          }
        } else {
          lagopus_msg_warning("reply creation failed, (%s).\n",
                              lagopus_error_get_string(res));
        }
        /* free. */
        if (send_pbuf_list != NULL) {
          pbuf_list_free(send_pbuf_list);
        }
      }
    } else {
      lagopus_msg_warning("over packet length.\n");
      ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
      res = LAGOPUS_RESULT_OFP_ERROR;
    }
  } else {
    res = LAGOPUS_RESULT_INVALID_ARGS;
  }
  return res;
}
コード例 #16
0
/* Group Features Request packet receive. */
lagopus_result_t
ofp_group_features_request_handle(struct channel *channel, struct pbuf *pbuf,
                                  struct ofp_header *xid_header,
                                  struct ofp_error *error) {
  lagopus_result_t ret;
  uint64_t dpid;
  struct ofp_group_features group_features;
  struct pbuf_list *pbuf_list = NULL;

  if (channel != NULL && pbuf != NULL &&
      xid_header != NULL && error != NULL) {
    if (pbuf_plen_equal_check(pbuf, 0) == LAGOPUS_RESULT_OK) {
      dpid = channel_dpid_get(channel);

      ret = ofp_group_features_get(dpid,
                                   &group_features,
                                   error);
      if (ret == LAGOPUS_RESULT_OK) {
        ret = ofp_group_features_reply_create(channel, &pbuf_list,
                                              &group_features,
                                              xid_header);
        if (ret == LAGOPUS_RESULT_OK) {
          /* write packets. */
          ret = channel_send_packet_list(channel, pbuf_list);
          if (ret != LAGOPUS_RESULT_OK) {
            lagopus_msg_warning("Can't write\n");
          }
        } else {
          lagopus_msg_warning("FAILED (%s)\n", lagopus_error_get_string(ret));
        }
      } else {
        lagopus_msg_warning("FAILED (%s)\n", lagopus_error_get_string(ret));
      }
    } else {
      lagopus_msg_warning("over packet length.\n");
      ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
      ret = LAGOPUS_RESULT_OFP_ERROR;
    }

    /* free. */
    if (pbuf_list != NULL) {
      pbuf_list_free(pbuf_list);
    }
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
コード例 #17
0
ファイル: ofp_role.c プロジェクト: lagopus/lagopus
static lagopus_result_t
ofp_write_channel(struct channel *channel,
                  struct pbuf *pbuf) {
  lagopus_result_t ret = LAGOPUS_RESULT_OK;
  struct pbuf *send_pbuf = NULL;
  uint16_t len = 0;

  if (channel != NULL && pbuf != NULL) {
    ret = pbuf_length_get(pbuf, &len);

    if (ret == LAGOPUS_RESULT_OK) {
      send_pbuf = channel_pbuf_list_get(channel,
                                        (size_t) len);
      if (send_pbuf != NULL) {
        /* Copy pbuf. */
        ret = pbuf_copy(send_pbuf, pbuf);

        if (ret == LAGOPUS_RESULT_OK) {
          ret = ofp_header_packet_set(channel, send_pbuf);

          if (ret == LAGOPUS_RESULT_OK) {
            channel_send_packet(channel, send_pbuf);
            ret = LAGOPUS_RESULT_OK;
          } else {
            lagopus_msg_warning("FAILED (%s).\n",
                                lagopus_error_get_string(ret));
          }
        } else {
          lagopus_msg_warning("FAILED (%s).\n",
                              lagopus_error_get_string(ret));
        }
      } else {
        lagopus_msg_warning("Can't allocate pbuf.\n");
        ret = LAGOPUS_RESULT_NO_MEMORY;
      }
    } else {
      lagopus_msg_warning("FAILED (%s).\n",
                          lagopus_error_get_string(ret));
    }

    if (ret != LAGOPUS_RESULT_OK && send_pbuf != NULL) {
      channel_pbuf_list_unget(channel, send_pbuf);
    }
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
コード例 #18
0
ファイル: session_tls.c プロジェクト: D-TOKIOKA/lagopus
static int
check_cert_chain(const SSL *ssl) {
  int ret = -1;
  char *issuer = NULL, *subject = NULL;
  X509 *peer = NULL;

  if (SSL_get_verify_result(ssl) != X509_V_OK) {
    lagopus_msg_warning("SSL_get_verify_result() failed.\n");
    return -1;
  }

  peer = SSL_get_peer_certificate(ssl);
  if (peer == NULL) {
    lagopus_msg_warning("SSL_get_peer_certificate() failed.\n");
    return -1;
  }

  issuer = X509_NAME_oneline(X509_get_issuer_name(peer), NULL, 0);
  if (issuer == NULL) {
    lagopus_msg_warning("no memory, get_issuer_name failed.\n");
    ret = -1;
    goto done;
  }

  subject = X509_NAME_oneline(X509_get_subject_name(peer), NULL, 0);
  if (issuer == NULL) {
    lagopus_msg_warning("no memory, get_subject_name failed.\n");
    ret = -1;
    goto done;
  }

  if (check_certificates != NULL) {
    if (check_certificates(issuer, subject) == LAGOPUS_RESULT_OK) {
      ret = 0;
    } else {
      ret = -1;
    }
    lagopus_msg_info("issuer:[%s], subject:[%s] ret: %d\n", issuer, subject, ret);
  } else {
    lagopus_msg_warning("check_certificates function is null.\n");
  }

done:
  free(issuer);
  free(subject);
  X509_free(peer);

  return ret;
}
コード例 #19
0
ファイル: session.c プロジェクト: tidatida/lagopus
static int
bind_default(lagopus_session_t s, const char *host, const char *port) {
  int ret;
  int sock = -1;
  char service[NI_MAXSERV];
  struct addrinfo hints = {0,0,0,0,0,NULL,NULL,NULL}, *res = NULL;

  snprintf(service, sizeof(service), "%s", port);
  lagopus_msg_debug(10, "host:%s, service:%s\n", host, service);
  hints.ai_family = s->family;
  hints.ai_socktype = s->type;
  ret = getaddrinfo(host, service, &hints, &res);
  if (ret != 0) {
    lagopus_msg_warning("getaddrinfo error %s.\n", gai_strerror(ret));
    freeaddrinfo(res);
    return -1;
  }

  sock = socket_create(res->ai_family, res->ai_socktype, res->ai_protocol,
                       s->session_type & SESSION_ACTIVE ? true : false);
  if (sock < 0) {
    freeaddrinfo(res);
    return -1;
  }

  if (s->session_type & SESSION_PASSIVE) {
    const int on = 1;
    ret = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
    if (ret < 0) {
      lagopus_msg_warning("setsockopt error %s.\n", strerror(errno));
      freeaddrinfo(res);
      close(sock);
      return ret;
    }
  }

  ret = bind(sock, res->ai_addr, res->ai_addrlen);
  if (ret < 0 && errno != EINPROGRESS) {
    lagopus_msg_warning("connect error %s.\n", strerror(errno));
    freeaddrinfo(res);
    close(sock);
    return ret;
  }

  s->sock = sock;
  freeaddrinfo(res);
  return ret;
}
コード例 #20
0
STATIC lagopus_result_t
ofp_get_async_reply_create(struct channel *channel,
                           struct pbuf **pbuf,
                           struct ofp_header *xid_header) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;
  struct ofp_async_config async_config;

  /* check params */
  if (channel != NULL && pbuf != NULL &&
      xid_header != NULL) {
    /* alloc */
    *pbuf = channel_pbuf_list_get(channel,
                                  sizeof(struct ofp_async_config));
    if (*pbuf != NULL) {
      pbuf_plen_set(*pbuf, sizeof(struct ofp_async_config));

      /* Copy packet_in_mask, port_status_mask, flow_removed_mask. */
      channel_role_mask_get(channel, &async_config);

      /* Fill in header. */
      ofp_header_set(&async_config.header,
                     channel_version_get(channel),
                     OFPT_GET_ASYNC_REPLY,
                     (uint16_t) pbuf_plen_get(*pbuf),
                     xid_header->xid);

      /* Encode message. */
      ret = ofp_async_config_encode(*pbuf, &async_config);

      if (ret != LAGOPUS_RESULT_OK) {
        lagopus_msg_warning("FAILED : ofp_async_config_encode (%s).\n",
                            lagopus_error_get_string(ret));
      }
    } else {
      lagopus_msg_warning("Can't allocate pbuf.\n");
      ret = LAGOPUS_RESULT_NO_MEMORY;
    }

    if (ret != LAGOPUS_RESULT_OK &&  *pbuf != NULL) {
      channel_pbuf_list_unget(channel, *pbuf);
      *pbuf = NULL;
    }
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
コード例 #21
0
ファイル: session.c プロジェクト: tidatida/lagopus
lagopus_result_t
session_accept(lagopus_session_t s1, lagopus_session_t *s2) {
  int sock;
  struct sockaddr_storage ss = {0,0,{0}};
  socklen_t ss_len = sizeof(ss);
  session_type_t t;
  lagopus_result_t ret;

  sock = accept(s1->sock, (struct sockaddr *) &ss, &ss_len);
  if (sock  < 0) {
    lagopus_msg_warning("accept error.\n");
    return LAGOPUS_RESULT_POSIX_API_ERROR;
  }

  t = ((s1->session_type
        & (unsigned int) ~(SESSION_PASSIVE|SESSION_ACTIVE)) | SESSION_ACCEPTED);
  ret = session_create(t, s2);
  if (*s2 == NULL) {
    close(sock);
    return ret;
  }
  (*s2)->sock = sock;

  if (s1->accept != NULL) {
    return s1->accept(s1, s2);
  }

  return LAGOPUS_RESULT_OK;
}
コード例 #22
0
/* Features Request packet receive. */
lagopus_result_t
ofp_features_request_handle(struct channel *channel, struct pbuf *pbuf,
                            struct ofp_header *xid_header,
                            struct ofp_error *error) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;
  struct pbuf *send_pbuf = NULL;

  /* Parse packet. */
  ret = ofp_header_handle(channel, pbuf, error);
  if (ret == LAGOPUS_RESULT_OK) {
    /* Features request reply. */
    ret = ofp_features_reply_create(channel, &send_pbuf,
                                    xid_header);
    if (ret == LAGOPUS_RESULT_OK) {
      features_request_trace(xid_header);

      channel_send_packet(channel, send_pbuf);
      ret = LAGOPUS_RESULT_OK;
    } else {
      lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret));
    }
  }

  if (ret != LAGOPUS_RESULT_OK && send_pbuf != NULL) {
    channel_pbuf_list_unget(channel, send_pbuf);
  }

  return ret;
}
コード例 #23
0
ファイル: ofp_bridgeq_mgr.c プロジェクト: D-TOKIOKA/lagopus
static inline lagopus_result_t
bridgeq_mgr_map_to_array(void) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;

  if (bridgeq_table != NULL) {
    bridgeq_mgr_lock();
    n_bridgeqs = 0;

    if (lagopus_hashmap_size(&bridgeq_table) != 0) {
      /* NOTE:
       *   hashmap_iterate() is very slow.
       */
      ret = lagopus_hashmap_iterate(&bridgeq_table,
                                    iter_to_array,
                                    NULL);
    } else {
      ret = LAGOPUS_RESULT_OK;
    }
    bridgeq_mgr_unlock();
  } else {
    ret = LAGOPUS_RESULT_INVALID_OBJECT;
    lagopus_msg_warning("bridgeq_table is NULL.\n");
  }

  return ret;
}
コード例 #24
0
ファイル: ofp_bridgeq_mgr.c プロジェクト: D-TOKIOKA/lagopus
lagopus_result_t
ofp_bridgeq_mgr_bridgeqs_to_array(struct ofp_bridgeq *brqs[],
                                  uint64_t *count,
                                  const size_t max_size) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;
  uint64_t i;

  if (brqs != NULL && count != NULL &&
      max_size <= MAX_BRIDGES) {
    if (bridgeq_table != NULL) {
      bridgeq_mgr_lock();
      for (i = 0; i < n_bridgeqs; i++) {
        brqs[i] = bridgeqs[i];
        /* inclement reference counter */
        ofp_bridgeq_refs_get(bridgeqs[i]);
      }
      *count = n_bridgeqs;
      bridgeq_mgr_unlock();
      ret = LAGOPUS_RESULT_OK;
    } else {
      ret = LAGOPUS_RESULT_INVALID_OBJECT;
      lagopus_msg_warning("bridgeq_table is NULL.\n");
    }
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
コード例 #25
0
ファイル: thread_test.c プロジェクト: D-TOKIOKA/lagopus
static inline bool
s_check_get_thread_id(lagopus_thread_t *thd_ptr,
                      lagopus_result_t require_ret) {
  bool result = false;
  lagopus_result_t ret;
  pthread_t tid;
  int i;
  for (i = 0; i < GET_TID_RETRY; i++) {
    ret = lagopus_thread_get_pthread_id(thd_ptr, &tid);
    if (ret == require_ret) {
      break;
    }
  }
  if (ret == require_ret) {
    if (ret == LAGOPUS_RESULT_OK) {
      TEST_ASSERT_NOT_EQUAL(tid, LAGOPUS_INVALID_THREAD);
    }
    result = true;
  } else {
    if (require_ret == LAGOPUS_RESULT_OK
        && ret == LAGOPUS_RESULT_ALREADY_HALTED) {
      lagopus_msg_warning(
        "test requires LAGOPUS_RESULT_OK, but result is LAGOPUS_ALREADY_HALTED. "
        "Modify value of WAIT_NSEC and MAIN_SLEEP_USEC of thread_test.c, please try again.\n");
      result = true;
    } else {
      lagopus_perror(ret);
      TEST_FAIL_MESSAGE("get_thread_id failed");
      result = false;
    }
  }
  return result;
}
コード例 #26
0
ファイル: session_tls.c プロジェクト: D-TOKIOKA/lagopus
static lagopus_result_t
connect_check_tls(struct session *s) {
  long res = -1;
  X509 *peer = NULL;
  lagopus_result_t ret = 0;

  lagopus_msg_debug(10, "connect check in\n");
  if (IS_CTX_NULL(s)) {
    lagopus_msg_warning("session ctx is null.\n");
    return LAGOPUS_RESULT_INVALID_ARGS;
  }

  if (IS_TLS_NOT_INIT(s) == false) {
    res = SSL_get_verify_result(GET_TLS_CTX(s)->ssl);
    peer = SSL_get_peer_certificate(GET_TLS_CTX(s)->ssl);
  }

  if (res != X509_V_OK || peer == NULL
      || GET_TLS_CTX(s)->verified == false) {
    ret = connect_tls(s, NULL, NULL);
  }
  lagopus_msg_debug(10, "connect check out ret:%d\n", (int) ret);

  return ret;
}
コード例 #27
0
ファイル: ofp_header_handler.c プロジェクト: tidatida/lagopus
/* header only packet. */
lagopus_result_t
ofp_header_create(struct channel *channel, uint8_t type,
                  struct ofp_header *xid_header,
                  struct ofp_header *header,
                  struct pbuf *pbuf) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;
  uint32_t xid;

  if (channel != NULL && header != NULL &&
      pbuf != NULL) {
    if (xid_header != NULL) {
      xid = xid_header->xid;
    } else {
      xid = channel_xid_get(channel);
    }

    ofp_header_set(header, channel_version_get(channel), type,
                   (uint16_t) pbuf_plen_get(pbuf), xid);

    ret = ofp_header_encode(pbuf, header);
    if (ret != LAGOPUS_RESULT_OK) {
      lagopus_msg_warning("FAILED (%s).\n",
                          lagopus_error_get_string(ret));
    }
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
コード例 #28
0
ファイル: rib_notifier.c プロジェクト: hibitomo/lagopus
/**
 * Delete route information notified from netlink.
 */
void
rib_notifier_ipv4_route_delete(struct in_addr *dest, int prefixlen,
                               struct in_addr *gate, int ifindex)   {
  struct rib *rib;
  lagopus_result_t rv;
  struct notification_entry *entry = NULL;

  rv = ifinfo_rib_get(ifindex, &rib);
  if (rv == LAGOPUS_RESULT_OK && rib != NULL) {
    entry = rib_create_notification_entry(NOTIFICATION_TYPE_ROUTE,
                                          NOTIFICATION_ACTION_TYPE_DEL);
    if (entry) {
      /* add notification entry to queue. */
      entry->route.ifindex = ifindex;
      entry->route.dest = *dest;
      entry->route.gate = *gate;
      entry->route.scope = 0;
      entry->route.prefixlen = prefixlen;
      rv = rib_add_notification_entry(rib, entry);
    } else {
      lagopus_msg_warning("create notification entry failed\n");
    }
  }

  return;
}
コード例 #29
0
/* Send switch features reply. */
STATIC lagopus_result_t
ofp_features_reply_create(struct channel *channel,
                          struct pbuf **pbuf,
                          struct ofp_header *xid_header) {
  struct ofp_switch_features features;
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;

  if (channel != NULL && pbuf != NULL && xid_header != NULL) {
    /* alloc */
    *pbuf = channel_pbuf_list_get(channel,
                                  sizeof(struct ofp_switch_features));
    if (*pbuf != NULL) {
      pbuf_plen_set(*pbuf, sizeof(struct ofp_switch_features));

      ret = features_reply_features_get(channel, &features);
      if (ret == LAGOPUS_RESULT_OK) {
        /* Fill in header. */
        ofp_header_set(&features.header, channel_version_get(channel),
                       OFPT_FEATURES_REPLY, (uint16_t) pbuf_plen_get(*pbuf),
                       xid_header->xid);

        /* Encode message. */
        ret = ofp_switch_features_encode(*pbuf, &features);
        if (ret != LAGOPUS_RESULT_OK) {
          lagopus_msg_warning("FAILED (%s).\n",
                              lagopus_error_get_string(ret));
        }
      } else {
        lagopus_msg_warning("FAILED (%s).\n",
                            lagopus_error_get_string(ret));
      }
    } else {
      lagopus_msg_warning("Can't allocate pbuf.\n");
      ret = LAGOPUS_RESULT_NO_MEMORY;
    }

    if (ret != LAGOPUS_RESULT_OK && *pbuf != NULL) {
      channel_pbuf_list_unget(channel, *pbuf);
      *pbuf = NULL;
    }
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
コード例 #30
0
ファイル: rib_notifier.c プロジェクト: hibitomo/lagopus
/**
 * Add ipv4 addr information notified from netlink.
 */
void
rib_notifier_ipv4_addr_add(int ifindex, struct in_addr *addr, int prefixlen,
                           struct in_addr *broad, char *label) {
  lagopus_result_t rv;
  struct ifinfo_entry *entry;
  struct ifinfo_entry *dentry;
  uint8_t hwaddr[UPDATER_ETH_LEN];
  struct bridge *bridge;
  struct notification_entry *nentry = NULL;

  addr_ipv4_log("add", ifindex, addr, prefixlen, broad, label);

  /* new ifinfo entry to registered to ifinfo_hashmap. */
  entry = calloc(1, sizeof(struct ifinfo_entry));
  if (entry == NULL) {
    lagopus_msg_warning("no memory.\n");
    return;
  }
  memset(entry, 0, sizeof(struct ifinfo_entry));
  memcpy(entry->ifname, label, strlen(label));

  if (dp_tapio_interface_info_get(label, hwaddr, &bridge)
      != LAGOPUS_RESULT_OK) {
    lagopus_msg_warning("get interface info failed.\n");
    ifinfo_entry_free(entry);
    return;
  }
  memcpy(entry->hwaddr, hwaddr, UPDATER_ETH_LEN);
  entry->rib = &(bridge->rib);
  dentry = entry;
  lagopus_hashmap_add(&ifinfo_hashmap, (void *)ifindex, (void **)&dentry, true);

  /* create and set notification entry. */
  nentry = rib_create_notification_entry(NOTIFICATION_TYPE_IFADDR,
                                         NOTIFICATION_ACTION_TYPE_ADD);
  if (nentry) {
    /* add notification entry to queue. */
    nentry->ifaddr.ifindex = ifindex;
    rv = rib_add_notification_entry(&bridge->rib, nentry);
  } else {
    lagopus_msg_warning("create notification entry failed\n");
    ifinfo_entry_free(entry);
  }

  return;
}