Commit 1e0941d0 authored by gauthier's avatar gauthier

utils

parent a7358548
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file async_shell_cmd.cpp
\brief
\author Lionel GAUTHIER
\date 2017
\email: lionel.gauthier@eurecom.fr
*/
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
#include <inttypes.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
#include "itti.hpp"
#include "async_shell_cmd.hpp"
#include "itti_async_shell_cmd.hpp"
#include "logger.hpp"
#include "common_defs.h"
#include <stdexcept>
using namespace oai::cn::core::itti;
using namespace oai::cn::util;
;
extern itti_mw *itti_inst;
void async_cmd_task (void*);
//------------------------------------------------------------------------------
void async_cmd_task (void*)
{
const task_id_t task_id = TASK_ASYNC_SHELL_CMD;
itti_inst->notify_task_ready(task_id);
do {
std::shared_ptr<itti_msg> shared_msg = itti_inst->receive_msg(task_id);
auto *msg = shared_msg.get();
switch (msg->msg_type) {
case ASYNC_SHELL_CMD:
if (itti_async_shell_cmd* to = dynamic_cast<itti_async_shell_cmd*>(msg)) {
int rc = system ((const char*)to->system_command.c_str());
if (rc) {
Logger::async_cmd().error( "Failed cmd from %d: %s ", to->origin, (const char*)to->system_command.c_str());
if (to->is_abort_on_error) {
Logger::async_cmd().error( "Terminate cause failed cmd %s at %s:%d", to->system_command.c_str(), to->src_file.c_str(), to->src_line);
itti_inst->send_terminate_msg(to->origin);
}
}
}
break;
case TIME_OUT:
if (itti_msg_timeout* to = dynamic_cast<itti_msg_timeout*>(msg)) {
Logger::async_cmd().info( "TIME-OUT event timer id %d", to->timer_id);
}
break;
case TERMINATE:
if (itti_msg_terminate *terminate = dynamic_cast<itti_msg_terminate*>(msg)) {
Logger::async_cmd().info( "Received terminate message");
return;
}
break;
default:
Logger::sgwc_app().info( "no handler for msg type %d", msg->msg_type);
}
} while (true);
}
//------------------------------------------------------------------------------
async_shell_cmd::async_shell_cmd (void)
{
Logger::async_cmd().startup( "Starting..." );
if (itti_inst->create_task(TASK_ASYNC_SHELL_CMD, async_cmd_task, nullptr) ) {
Logger::async_cmd().error( "Cannot create task TASK_ASYNC_SHELL_CMD" );
throw std::runtime_error( "Cannot create task TASK_ASYNC_SHELL_CMD" );
}
Logger::async_cmd().startup( "Started" );
}
//------------------------------------------------------------------------------
int async_shell_cmd::run_command (const task_id_t sender_itti_task, const bool is_abort_on_error, const char* src_file, const int src_line, const std::string& cmd_str)
{
itti_async_shell_cmd cmd(sender_itti_task, TASK_ASYNC_SHELL_CMD, cmd_str, is_abort_on_error, src_file, src_line);
std::shared_ptr<itti_async_shell_cmd> msg = std::make_shared<itti_async_shell_cmd>(cmd);
int ret = itti_inst->send_msg(msg);
if (RETURNok != ret) {
Logger::async_cmd().error( "Could not send ITTI message to task TASK_ASYNC_SHELL_CMD");
return RETURNerror;
}
return RETURNok;
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file async_shell_cmd.hpp
\brief We still use some unix commands for convenience, and we did not have to replace them by system calls
\ Instead of calling C system(...) that can take a lot of time (creation of a process, etc), in many cases
\ it doesn't hurt to do this asynchronously, may be we must tweak thread priority, pin it to a CPU, etc (TODO later)
\author Lionel GAUTHIER
\date 2017
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_ASYNC_SHELL_CMD_HPP_SEEN
#define FILE_ASYNC_SHELL_CMD_HPP_SEEN
#include "itti_msg.hpp"
#include <string>
#include <thread>
namespace oai::cn::util {
class async_shell_cmd {
private:
std::thread::id thread_id;
std::thread thread;
public:
async_shell_cmd();
~async_shell_cmd() {}
async_shell_cmd(async_shell_cmd const&) = delete;
void operator=(async_shell_cmd const&) = delete;
int run_command (const core::itti::task_id_t sender_itti_task, const bool is_abort_on_error, const char* src_file, const int src_line, const std::string& cmd_str);
};
}
#endif /* FILE_ASYNC_SHELL_CMD_HPP_SEEN */
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file conversions.cpp
\brief
\author Sebastien ROUX
\company Eurecom
*/
#include "conversions.hpp"
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <ctype.h>
#include <inttypes.h>
static const char hex_to_ascii_table[16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
};
static const signed char ascii_to_hex_table[0x100] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};
void
hexa_to_ascii (
uint8_t * from,
char *to,
size_t length)
{
size_t i;
for (i = 0; i < length; i++) {
uint8_t upper = (from[i] & 0xf0) >> 4;
uint8_t lower = from[i] & 0x0f;
to[2 * i] = hex_to_ascii_table[upper];
to[2 * i + 1] = hex_to_ascii_table[lower];
}
}
int
ascii_to_hex (
uint8_t * dst,
const char *h)
{
const unsigned char *hex = (const unsigned char *)h;
unsigned i = 0;
for (;;) {
int high,
low;
while (*hex && isspace (*hex))
hex++;
if (!*hex)
return 1;
high = ascii_to_hex_table[*hex++];
if (high < 0)
return 0;
while (*hex && isspace (*hex))
hex++;
if (!*hex)
return 0;
low = ascii_to_hex_table[*hex++];
if (low < 0)
return 0;
dst[i++] = (high << 4) | low;
}
}
//------------------------------------------------------------------------------
imsi64_t imsi_to_imsi64(imsi_t * const imsi)
{
imsi64_t imsi64 = INVALID_IMSI64;
if (imsi) {
imsi64 = 0;
for (int i=0; i < IMSI_BCD8_SIZE; i++) {
uint8_t d2 = imsi->u.value[i];
uint8_t d1 = (d2 & 0xf0) >> 4;
d2 = d2 & 0x0f;
if (10 > d1) {
imsi64 = imsi64*10 + d1;
if (10 > d2) {
imsi64 = imsi64*10 + d2;
} else {
break;
}
} else {
break;
}
}
}
return imsi64;
}
//------------------------------------------------------------------------------
void paa_to_pfcp_ue_ip_address(const oai::cn::core::paa_t& paa, oai::cn::core::pfcp::ue_ip_address_t& ue_ip_address)
{
switch (paa.pdn_type.pdn_type) {
case oai::cn::core::PDN_TYPE_E_IPV4:
ue_ip_address.v4 = 1;
ue_ip_address.ipv4_address = paa.ipv4_address;
break;
case oai::cn::core::PDN_TYPE_E_IPV6:
ue_ip_address.v6 = 1;
ue_ip_address.ipv6_address = paa.ipv6_address;
break;
case oai::cn::core::PDN_TYPE_E_IPV4V6:
ue_ip_address.v4 = 1;
ue_ip_address.v6 = 1;
ue_ip_address.ipv4_address = paa.ipv4_address;
ue_ip_address.ipv6_address = paa.ipv6_address;
break;
case oai::cn::core::PDN_TYPE_E_NON_IP:
default:
;
}
}
//------------------------------------------------------------------------------
void pdn_ip_to_pfcp_ue_ip_address(const oai::cn::core::pdn_type_t& pdn_type,
const struct in_addr& ipv4_address,
const struct in6_addr ipv6_address,
oai::cn::core::pfcp::ue_ip_address_t& ue_ip_address)
{
switch (pdn_type.pdn_type) {
case oai::cn::core::PDN_TYPE_E_IPV4:
ue_ip_address.v4 = 1;
ue_ip_address.ipv4_address = ipv4_address;
break;
case oai::cn::core::PDN_TYPE_E_IPV6:
ue_ip_address.v6 = 1;
ue_ip_address.ipv6_address = ipv6_address;
break;
case oai::cn::core::PDN_TYPE_E_IPV4V6:
ue_ip_address.v4 = 1;
ue_ip_address.v6 = 1;
ue_ip_address.ipv4_address = ipv4_address;
ue_ip_address.ipv6_address = ipv6_address;
break;
case oai::cn::core::PDN_TYPE_E_NON_IP:
default:
;
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file conversions.h
\brief
\author Lionel Gauthier
\company Eurecom
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_EPC_CONVERSIONS_HPP_SEEN
#define FILE_EPC_CONVERSIONS_HPP_SEEN
#include "common_types.h"
#include "3gpp_23.003.h"
#include "3gpp_24.008.h"
#include "3gpp_29.274.h"
#include "EpsQualityOfService.h"
namespace oai {
namespace cn {
namespace util {
inline void build_fteid(core::fteid_t& fteid, const core::ip_address_t ip,const teid_t teid) {
fteid.teid = teid;
fteid.ipv4 = ip.ipv4;
fteid.ipv4_address = ip.address;
}
#define FTEID_T_2_IP_ADDRESS_T(fte_p,ip_p) \
do { \
(ip_p)->ipv4 = false; \
(ip_p)->ipv6 = false; \
if ((fte_p)->ipv4) { \
(ip_p)->ipv4 = true; \
(ip_p)->address.ipv4_address.s_addr = (fte_p)->ipv4_address.s_addr; \
} \
else if ((fte_p)->ipv6) { \
(ip_p)->ipv6 = true; \
memcpy(&(ip_p)->address.ipv6_address, &(fte_p)->ipv6_address, sizeof((fte_p)->ipv6_address)); \
} \
} while (0)
}
}
}
#endif /* FILE_CONVERSIONS_SEEN */
/* From https://gist.github.com/javiermon/6272065#file-gateway_netlink-c */
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <net/if.h>
#include <fstream> // std::ifstream
#include <string>
#include "common_defs.h"
#include "get_gateway_netlink.hpp"
#include "logger.hpp"
#define BUFFER_SIZE 4096
using namespace std;
//------------------------------------------------------------------------------
bool oai::cn::util::get_iface_l2_addr(const std::string& iface, std::string& mac)
{
std::string mac_address_path = fmt::format("/sys/class/net/{}/address", iface);
std::ifstream mac_address_in(mac_address_path.c_str(), ios_base::in | ios_base::binary );
char wb[32];
mac_address_in.get(wb, 32);
mac.assign(wb);
Logger::pfcp_switch().error("Found IFace %s MAC %s", iface.c_str(), mac.c_str());
mac.erase(std::remove(mac.begin(), mac.end(), ':'), mac.end());
return true;
// ifr = {};
// strncpy ((char *) ifr.ifr_name, ifname, IFNAMSIZ);
// if (ioctl(sd, SIOCGIFFLAGS, &ifr) == 0) {
// if (! (ifr.ifr_flags & IFF_LOOPBACK)) { // don't count loopback
// if (ioctl(sd, SIOCGIFHWADDR, &ifr) == 0) {
// memcpy(pdn_mac_address, ifr.ifr_hwaddr.sa_data, 6);
// }
// }
// }
}
//------------------------------------------------------------------------------
bool oai::cn::util::get_gateway_and_iface(std::string& gw, std::string& iface)
{
int received_bytes = 0, msg_len = 0, route_attribute_len = 0;
int sock = -1, msgseq = 0;
struct nlmsghdr *nlh, *nlmsg;
struct rtmsg *route_entry;
// This struct contain route attributes (route type)
struct rtattr *route_attribute;
char gateway_address[INET_ADDRSTRLEN], interface[IF_NAMESIZE+1];
char msgbuf[BUFFER_SIZE], buffer[BUFFER_SIZE];
char *ptr = buffer;
struct timeval tv;
int rv = RETURNok;
if ((sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) {
perror("socket failed");
return false;
}
memset(msgbuf, 0, sizeof(msgbuf));
memset(gateway_address, 0, sizeof(gateway_address));
memset(interface, 0, sizeof(interface));
memset(buffer, 0, sizeof(buffer));
/* point the header and the msg structure pointers into the buffer */
nlmsg = (struct nlmsghdr *)msgbuf;
/* Fill in the nlmsg header*/
nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
nlmsg->nlmsg_type = RTM_GETROUTE; // Get the routes from kernel routing table .
nlmsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; // The message is a request for dump.
nlmsg->nlmsg_seq = msgseq++; // Sequence of the message packet.
nlmsg->nlmsg_pid = getpid(); // PID of process sending the request.
/* 1 Sec Timeout to avoid stall */
tv.tv_sec = 1;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval));
/* send msg */
if (send(sock, nlmsg, nlmsg->nlmsg_len, 0) < 0) {
perror("send failed");
return false;
}
/* receive response */
do {
received_bytes = recv(sock, ptr, sizeof(buffer) - msg_len, 0);
if (received_bytes < 0) {
perror("Error in recv");
return false;
}
nlh = (struct nlmsghdr *) ptr;
/* Check if the header is valid */
if((NLMSG_OK(nlmsg, received_bytes) == 0) ||
(nlmsg->nlmsg_type == NLMSG_ERROR))
{
perror("Error in received packet");
return false;
}
/* If we received all data break */
if (nlh->nlmsg_type == NLMSG_DONE)
break;
else {
ptr += received_bytes;
msg_len += received_bytes;
}
/* Break if its not a multi part message */
if ((nlmsg->nlmsg_flags & NLM_F_MULTI) == 0)
break;
} while ((nlmsg->nlmsg_seq != msgseq) || (nlmsg->nlmsg_pid != getpid()));
/* parse response */
for ( ; NLMSG_OK(nlh, received_bytes); nlh = NLMSG_NEXT(nlh, received_bytes)) {
/* Get the route data */
route_entry = (struct rtmsg *) NLMSG_DATA(nlh);
/* We are just interested in main routing table */
if (route_entry->rtm_table != RT_TABLE_MAIN)
continue;
route_attribute = (struct rtattr *) RTM_RTA(route_entry);
route_attribute_len = RTM_PAYLOAD(nlh);
/* Loop through all attributes */
for ( ; RTA_OK(route_attribute, route_attribute_len);
route_attribute = RTA_NEXT(route_attribute, route_attribute_len)) {
switch(route_attribute->rta_type) {
case RTA_OIF:
if_indextoname(*(int *)RTA_DATA(route_attribute), interface);
break;
case RTA_GATEWAY:
inet_ntop(AF_INET, RTA_DATA(route_attribute),
gateway_address, sizeof(gateway_address));
break;
default:
break;
}
}
if ((*gateway_address) && (*interface)) {
gw.assign(gateway_address);
iface.assign(interface);
break;
} else {
rv = false;
}
}
close(sock);
return true;
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file get_gateway_netlink.hpp
\brief
\author Lionel Gauthier
\company Eurecom
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_GET_GATEWAY_NETLINK_HPP_SEEN
#define FILE_GET_GATEWAY_NETLINK_HPP_SEEN
#include <string>
namespace oai::cn::util {
bool get_iface_l2_addr(const std::string& iface, std::string& mac);
bool get_gateway_and_iface(std::string& gw, std::string& iface);
}
#endif /* FILE_GET_GATEWAY_NETLINK_HPP_SEEN */
/* From https://gist.github.com/javiermon/6272065#file-gateway_netlink-c */
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "common_defs.h"
#include "if.hpp"
#include "logger.hpp"
#include <errno.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#define BUFFER_SIZE 4096
//------------------------------------------------------------------------------
int get_gateway_and_iface(std::string *gw, std::string *iface)
{
int received_bytes = 0, msg_len = 0, route_attribute_len = 0;
int sock = -1, msgseq = 0;
struct nlmsghdr *nlh, *nlmsg;
struct rtmsg *route_entry;
// This struct contain route attributes (route type)
struct rtattr *route_attribute;
char gateway_address[INET_ADDRSTRLEN], interface[IF_NAMESIZE];
char msgbuf[BUFFER_SIZE], buffer[BUFFER_SIZE];
char *ptr = buffer;
struct timeval tv;
int rv = RETURNok;
if ((sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) {
Logger::system().error("socket raw/NETLINK_ROUTE failed");
return EXIT_FAILURE;
}
memset(msgbuf, 0, sizeof(msgbuf));
memset(gateway_address, 0, sizeof(gateway_address));
memset(interface, 0, sizeof(interface));
memset(buffer, 0, sizeof(buffer));
/* point the header and the msg structure pointers into the buffer */
nlmsg = (struct nlmsghdr *)msgbuf;
/* Fill in the nlmsg header*/
nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
nlmsg->nlmsg_type = RTM_GETROUTE; // Get the routes from kernel routing table .
nlmsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; // The message is a request for dump.
nlmsg->nlmsg_seq = msgseq++; // Sequence of the message packet.
nlmsg->nlmsg_pid = getpid(); // PID of process sending the request.
/* 1 Sec Timeout to avoid stall */
tv.tv_sec = 1;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval));
/* send msg */
if (send(sock, nlmsg, nlmsg->nlmsg_len, 0) < 0) {
Logger::system().error("send socket raw/NETLINK_ROUTE failed");
return EXIT_FAILURE;
}
/* receive response */
do
{
received_bytes = recv(sock, ptr, sizeof(buffer) - msg_len, 0);
if (received_bytes < 0) {
Logger::system().error("recv socket raw/NETLINK_ROUTE failed");
return EXIT_FAILURE;
}
nlh = (struct nlmsghdr *) ptr;
/* Check if the header is valid */
if((NLMSG_OK(nlmsg, received_bytes) == 0) ||
(nlmsg->nlmsg_type == NLMSG_ERROR))
{
Logger::system().error("recv msg raw/NETLINK_ROUTE failed");
return EXIT_FAILURE;
}
/* If we received all data break */
if (nlh->nlmsg_type == NLMSG_DONE)
break;
else {
ptr += received_bytes;
msg_len += received_bytes;
}
/* Break if its not a multi part message */
if ((nlmsg->nlmsg_flags & NLM_F_MULTI) == 0)
break;
}
while ((nlmsg->nlmsg_seq != msgseq) || (nlmsg->nlmsg_pid != getpid()));
/* parse response */
for ( ; NLMSG_OK(nlh, received_bytes); nlh = NLMSG_NEXT(nlh, received_bytes))
{
/* Get the route data */
route_entry = (struct rtmsg *) NLMSG_DATA(nlh);
/* We are just interested in main routing table */
if (route_entry->rtm_table != RT_TABLE_MAIN)
continue;
route_attribute = (struct rtattr *) RTM_RTA(route_entry);
route_attribute_len = RTM_PAYLOAD(nlh);
/* Loop through all attributes */
for ( ; RTA_OK(route_attribute, route_attribute_len);
route_attribute = RTA_NEXT(route_attribute, route_attribute_len))
{
switch(route_attribute->rta_type) {
case RTA_OIF:
if_indextoname(*(int *)RTA_DATA(route_attribute), interface);
break;
case RTA_GATEWAY:
inet_ntop(AF_INET, RTA_DATA(route_attribute),
gateway_address, sizeof(gateway_address));
break;
default:
break;
}
}
if ((*gateway_address) && (*interface)) {
*gw = string(gateway_address);
if (iface) {
*iface = string(interface);
}
break;
} else {
rv = RETURNerror;
}
}
close(sock);
return rv;
}
//------------------------------------------------------------------------------
int get_inet_addr_from_iface(const string& if_name, struct in_addr& inet_addr) {
struct ifreq ifr;
char str[INET_ADDRSTRLEN];
memset(&ifr, 0, sizeof(ifr));
int fd = socket(AF_INET, SOCK_DGRAM, 0);
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, (const char *)if_name.c_str(), IFNAMSIZ-1);
if (ioctl(fd, SIOCGIFADDR, &ifr)) {
close(fd);
Logger::system().error("Failed to probe %s inet addr: error %s\n", if_name.c_str(), strerror(errno));
return RETURNerror;
}
close(fd);
struct sockaddr_in* ipaddr = (struct sockaddr_in*)&ifr.ifr_addr;
// check
if (inet_ntop(AF_INET, (const void *)&ipaddr->sin_addr, str, INET_ADDRSTRLEN) == NULL) {
return RETURNerror;
}
inet_addr.s_addr = ipaddr->sin_addr.s_addr;
return RETURNok;
}
//------------------------------------------------------------------------------
int get_mtu_from_iface(const string& if_name, uint32_t& mtu) {
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
int fd = socket(AF_INET, SOCK_DGRAM, 0);
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, (const char *)if_name.c_str(), IFNAMSIZ-1);
if (ioctl(fd, SIOCGIFMTU, &ifr)) {
close(fd);
Logger::system().error("Failed to probe %s MTU: error %s\n", if_name.c_str(), strerror(errno));
return RETURNerror;
}
close(fd);
mtu = ifr.ifr_mtu;
return RETURNok;
}
//------------------------------------------------------------------------------
int get_inet_addr_infos_from_iface(const string& if_name, struct in_addr& inet_addr, struct in_addr& inet_network, unsigned int& mtu) {
struct ifreq ifr;
char str[INET_ADDRSTRLEN];
inet_addr.s_addr = INADDR_ANY;
inet_network.s_addr = INADDR_ANY;
mtu = 0;
memset(&ifr, 0, sizeof(ifr));
int fd = socket(AF_INET, SOCK_DGRAM, 0);
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, (const char *)if_name.c_str(), IFNAMSIZ-1);
if (ioctl(fd, SIOCGIFADDR, &ifr)) {
close(fd);
Logger::system().error("Failed to probe %s inet addr: error %s\n", if_name.c_str(), strerror(errno));
return RETURNerror;
}
struct sockaddr_in* ipaddr = (struct sockaddr_in*)&ifr.ifr_addr;
// check
if (inet_ntop(AF_INET, (const void *)&ipaddr->sin_addr, str, INET_ADDRSTRLEN) == NULL) {
close(fd);
return RETURNerror;
}
inet_addr.s_addr = ipaddr->sin_addr.s_addr;
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, (const char *)if_name.c_str(), IFNAMSIZ-1);
if (ioctl(fd, SIOCGIFNETMASK, &ifr)) {
close(fd);
Logger::system().error("Failed to probe %s inet netmask: error %s\n", if_name.c_str(), strerror(errno));
return RETURNerror;
}
ipaddr = (struct sockaddr_in*)&ifr.ifr_netmask;
// check
if (inet_ntop(AF_INET, (const void *)&ipaddr->sin_addr, str, INET_ADDRSTRLEN) == NULL) {
close(fd);
return RETURNerror;
}
inet_network.s_addr = ipaddr->sin_addr.s_addr;
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, (const char *)if_name.c_str(), IFNAMSIZ-1);
if (ioctl(fd, SIOCGIFMTU, &ifr)) {
Logger::system().error("Failed to probe %s MTU: error %s\n", if_name.c_str(), strerror(errno));
} else {
mtu = ifr.ifr_mtu;
}
close(fd);
return RETURNok;
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file get_gateway_netlink.h
\brief
\author Lionel Gauthier
\company Eurecom
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_IF_HPP_SEEN
#define FILE_IF_HPP_SEEN
# include <string>
using namespace std;
int get_gateway_and_iface(string *gw /*OUT*/, string *iface /*OUT*/);
int get_inet_addr_from_iface(const string& if_name, struct in_addr& inet_addr);
int get_mtu_from_iface(const string& if_name, uint32_t& mtu);
int get_inet_addr_infos_from_iface(const string& if_name, struct in_addr& inet_addr, struct in_addr& inet_netmask, unsigned int& mtu);
#endif /* FILE_IF_HPP_SEEN */
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file pid_file.cpp
\brief
\author Lionel GAUTHIER
\date 2016
\email: lionel.gauthier@eurecom.fr
*/
#include "logger.hpp"
#include "pid_file.hpp"
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <libgen.h>
int g_fd_pid_file = -1;
__pid_t g_pid = -1;
//------------------------------------------------------------------------------
std::string oai::cn::util::get_exe_absolute_path(const std::string &basepath, const unsigned int instance)
{
#define MAX_FILE_PATH_LENGTH 255
char pid_file_name[MAX_FILE_PATH_LENGTH+1] = {0};
char *exe_basename = NULL;
int rv = 0;
int num_chars = 0;
// get executable name
rv = readlink("/proc/self/exe",pid_file_name, 256);
if ( -1 == rv) {
return NULL;
}
pid_file_name[rv] = 0;
exe_basename = basename(pid_file_name);
// Add 6 for the other 5 characters in the path + null terminator + 2 chars for instance.
num_chars = basepath.size() + strlen(exe_basename) + 6 + 2;
if (num_chars > MAX_FILE_PATH_LENGTH) {
num_chars = MAX_FILE_PATH_LENGTH;
}
snprintf(pid_file_name, num_chars, "%s/%s%02u.pid", basepath.c_str(), exe_basename, instance);
return std::string(pid_file_name);
}
//------------------------------------------------------------------------------
int oai::cn::util::lockfile(int fd, int lock_type)
{
// lock on fd only, not on file on disk (do not prevent another process from modifying the file)
return lockf(fd, F_TLOCK, 0);
}
//------------------------------------------------------------------------------
bool oai::cn::util::is_pid_file_lock_success(const char * pid_file_name)
{
char pid_dec[64] = {0};
g_fd_pid_file = open(pid_file_name,
O_RDWR | O_CREAT,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* Read/write by owner, read by grp, others */
if ( 0 > g_fd_pid_file) {
Logger::sgwc_app().error( "open filename %s failed %d:%s\n", pid_file_name, errno, strerror(errno));
return false;
}
if ( 0 > oai::cn::util::lockfile(g_fd_pid_file, F_TLOCK)) {
Logger::sgwc_app().error( "lockfile filename %s failed %d:%s\n", pid_file_name, errno, strerror(errno));
if ( EACCES == errno || EAGAIN == errno ) {
close(g_fd_pid_file);
}
return false;
}
// fruncate file content
if (ftruncate(g_fd_pid_file, 0)) {
Logger::sgwc_app().error( "truncate %s failed %d:%s\n", pid_file_name, errno, strerror(errno));
close(g_fd_pid_file);
return false;
}
// write PID in file
g_pid = getpid();
snprintf(pid_dec, 64 /* should be big enough */, "%ld", (long)g_pid);
if ((ssize_t)-1 == write(g_fd_pid_file, pid_dec, strlen(pid_dec))) {
Logger::sgwc_app().error( "write PID to filename %s failed %d:%s\n", pid_file_name, errno, strerror(errno));
return false;
}
return true;
}
//------------------------------------------------------------------------------
void oai::cn::util::pid_file_unlock(void)
{
oai::cn::util::lockfile(g_fd_pid_file, F_ULOCK);
close(g_fd_pid_file);
g_fd_pid_file = -1;
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file pid_file.hpp
\brief
\author Lionel GAUTHIER
\date 2016
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_PID_FILE_SEEN
#define FILE_PID_FILE_SEEN
#include <string>
namespace oai::cn::util {
/*
* Generate the exe absolute path using a specified base_path.
*
* @param base_path
* the root directory to use.
*
* @return a string for the exe absolute path.
*/
std::string get_exe_absolute_path(const std::string &base_path, const unsigned int instance);
bool is_pid_file_lock_success(const char * pid_file_name);
void pid_file_unlock(void);
int lockfile(int fd, int lock_type);
}
#endif
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "string.hpp"
#include <algorithm>
#include <functional>
#include <cctype>
#include <locale>
#include <stdarg.h>
template<class T>
class Buffer
{
public:
explicit Buffer(size_t size) { msize = size; mbuf = new T[msize]; }
~Buffer() { if (mbuf) delete [] mbuf; }
T *get() { return mbuf; }
private:
Buffer();
size_t msize;
T *mbuf;
};
std::string oai::cn::util::string_format( const char *format, ... )
{
va_list args;
va_start( args, format );
size_t size = vsnprintf( NULL, 0, format, args ) + 1; // Extra space for '\0'
va_end( args );
Buffer<char> buf( size );
va_start( args, format );
vsnprintf( buf.get(), size, format, args );
va_end( args );
return std::string( buf.get(), size - 1 ); // We don't want the '\0' inside
}
// Licence : https://creativecommons.org/licenses/by-sa/4.0/legalcode
//https://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring#217605
// trim from start
std::string &oai::cn::util::ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(),
std::not1(std::ptr_fun<int, int>(std::isspace))));
return s;
}
// trim from end
std::string &oai::cn::util::rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(),
std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
return s;
}
// trim from both ends
std::string &oai::cn::util::trim(std::string &s) {
return oai::cn::util::ltrim(oai::cn::util::rtrim(s));
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file string.hpp
\brief
\author Lionel GAUTHIER
\date 2018
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_STRING_HPP_FILE_SEEN
#define FILE_STRING_HPP_FILE_SEEN
#include <string>
namespace oai::cn::util {
std::string string_format( const char *format, ... );
std::string &ltrim(std::string &s);
// trim from end
std::string &rtrim(std::string &s);
// trim from both ends
std::string &trim(std::string &s);
}
#endif
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file uint_uid_generator.hpp
\author Lionel GAUTHIER
\date 2019
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_UINT_GENERATOR_HPP_SEEN
#define FILE_UINT_GENERATOR_HPP_SEEN
#include <mutex>
#include <set>
namespace oai::cn::util {
template <class UINT> class uint_generator {
private:
UINT uid_generator;
std::mutex m_uid_generator;
std::set<UINT> uid_generated;
std::mutex m_uid_generated;
public:
uint_generator() : m_uid_generator() , m_uid_generated() {
uid_generator = 0;
uid_generated = {};
};
uint_generator(uint_generator const&) = delete;
void operator=(uint_generator const&) = delete;
UINT get_uid()
{
std::unique_lock<std::mutex> lr(m_uid_generator);
UINT uid = ++uid_generator;
while (true) {
// may happen race conditions here
std::unique_lock<std::mutex> ld(m_uid_generated);
if (uid_generated.count(uid) == 0) {
uid_generated.insert(uid);
ld.unlock();
lr.unlock();
return uid;
}
uid = ++uid_generator;
}
}
void free_uid(UINT uid)
{
std::unique_lock<std::mutex> l(m_uid_generated);
uid_generated.erase(uid);
l.unlock();
}
};
template <class UINT> class uint_uid_generator {
private:
UINT uid_generator;
std::mutex m_uid_generator;
std::set<UINT> uid_generated;
std::mutex m_uid_generated;
uint_uid_generator() : m_uid_generator() , m_uid_generated() {
uid_generator = 0;
uid_generated = {};
};
public:
static uint_uid_generator& get_instance()
{
static uint_uid_generator instance;
return instance;
}
uint_uid_generator(uint_uid_generator const&) = delete;
void operator=(uint_uid_generator const&) = delete;
UINT get_uid()
{
std::unique_lock<std::mutex> lr(m_uid_generator);
UINT uid = ++uid_generator;
while (true) {
// may happen race conditions here
std::unique_lock<std::mutex> ld(m_uid_generated);
if (uid_generated.count(uid) == 0) {
uid_generated.insert(uid);
lr.unlock();
ld.unlock();
return uid;
}
uid = ++uid_generator;
}
}
void free_uid(UINT uid)
{
std::unique_lock<std::mutex> l(m_uid_generated);
uid_generated.erase(uid);
l.unlock();
}
};
}
#endif // FILE_UINT_GENERATOR_HPP_SEEN
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment