/******************************************************************************* OpenAirInterface Copyright(c) 1999 - 2014 Eurecom OpenAirInterface is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenAirInterface is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenAirInterface.The full GNU General Public License is included in this distribution in the file called "COPYING". If not, see <http://www.gnu.org/licenses/>. Contact Information OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE *******************************************************************************/ #define MRAL_MODULE #define MRALLTE_MAIN_C //----------------------------------------------------------------------------- #include "mRALlte_main.h" #include "mRALlte_constants.h" #include "mRALlte_variables.h" #include "mRALlte_proto.h" #include "mRALlte_mih_msg.h" #include "nas_ue_netlink.h" #include "nasUE_config.h" //----------------------------------------------------------------------------- #include "MIH_C.h" //----------------------------------------------------------------------------- #define NAS_UE_NETL_MAXLEN 500 // TO DO #ifndef SVN_REV #define SVN_REV "0.1" #endif // Global variables int netl_s, s_nas; struct sockaddr_un ralu_socket; int wait_start_mihf; int listen_mih; struct ral_lte_priv rl_priv; struct ral_lte_priv *ralpriv; char message[NAS_UE_NETL_MAXLEN]; static int g_log_output; //----------------------------------------------------------------------------- static void arg_usage(char *exec_nameP) { //----------------------------------------------------------------------------- fprintf(stderr, "Usage: %s [options]\nOptions:\n" " -V, --version Display version information\n" " -?, -h, --help Display this help text\n" " -P <number>, --ral-listening-port Listening port for incoming MIH-F messages\n" " -I <string>, --ral-ip-address Binding IP(v4 or v6) address for RAL\n" " -p <number>, --mihf-remote-port MIH-F remote port\n" " -i <string>, --mihf-ip-address MIH-F IP(v4 or v6) address\n" " -c, --output-to-console All stream outputs are redirected to console\n" " -f, --output-to-syslog All stream outputs are redirected to file\n" " -s, --output-to-syslog All stream outputs are redirected to syslog\n", exec_nameP); } //--------------------------------------------------------------------------- int parse_opts(int argc, char *argv[]) { //--------------------------------------------------------------------------- static struct option long_opts[] = { {"version", 0, 0, 'V'}, {"help", 0, 0, 'h'}, {"ral-listening-port", optional_argument, 0, 'P'}, {"ral-ip-address", optional_argument, 0, 'I'}, {"mihf-remote-port", optional_argument, 0, 'p'}, {"mihf-ip-address", optional_argument, 0, 'i'}, {"link.id", optional_argument, 0, 'l'}, {"mihf.id", optional_argument, 0, 'm'}, {"output-to-console", 0, 0, 'c'}, {"output-to-file", 0, 0, 'f'}, {"output-to-syslog", 0, 0, 's'}, {0, 0, 0, 0} }; /* parse all other cmd line parameters than -c */ while (1) { int idx, c; c = getopt_long(argc, argv, "PIpil:Vh?cfs", long_opts, &idx); if (c == -1) break; switch (c) { case 'V': fprintf(stderr, "SVN MODULE VERSION: %s\n", SVN_REV); return -1; case '?': case 'h': arg_usage(basename(argv[0])); return -1; case 'i': fprintf(stderr, "Option mihf-ip-address:\t%s\n", optarg); g_mihf_ip_address = optarg; break; case 'p': fprintf(stderr, "Option mihf-remote-port:\t%s\n", optarg); g_mihf_remote_port = optarg; break; case 'P': fprintf(stderr, "Option ral-listening-port:\t%s\n", optarg); g_ral_listening_port_for_mihf = optarg; break; case 'I': fprintf(stderr, "Option ral-ip-address:\t%s\n", optarg); g_ral_ip_address = optarg; break; case 'l': fprintf(stderr, "Option link.id:\t%s\n", optarg); g_link_id = optarg; break; case 'm': fprintf(stderr, "Option mihf.id:\t%s\n", optarg); g_mihf_id = optarg; break; case 'c': fprintf(stderr, "Option output-to-console\n"); g_log_output = LOG_TO_CONSOLE; break; case 'f': fprintf(stderr, "Option output-to-file\n"); g_log_output = LOG_TO_FILE; break; case 's': fprintf(stderr, "Option output-to-syslog\n"); g_log_output = LOG_TO_SYSTEM; break; default: WARNING("UNKNOWN OPTION\n"); break; }; } return 0; } //--------------------------------------------------------------------------- void IAL_D_Netlink_socket_init(void) { //--------------------------------------------------------------------------- int len; struct sockaddr_un local; if ((netl_s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { perror("IAL_D_Netlink_socket_init : socket command failed, err %d\n"); exit(1); } local.sun_family = AF_UNIX; strcpy(local.sun_path, SOCK_NAS_PATH); unlink(local.sun_path); len = strlen(local.sun_path) + sizeof(local.sun_family); if (bind(netl_s, (struct sockaddr *)&local, len) == -1) { perror("IAL_D_Netlink_socket_init : bind command failed, \n"); exit(1); } if (listen(netl_s, 1) == -1) { perror("IAL_D_Netlink_socket_init : listen command failed, \n"); exit(1); } } //--------------------------------------------------------------------------- void mRALlte_get_IPv6_addr(void) { //--------------------------------------------------------------------------- #define IPV6_ADDR_LINKLOCAL 0x0020U #ifdef RAL_DUMMY char * eth0_name="eth0";/* interface name */ #endif #ifdef RAL_REALTIME char * graal0_name="graal0";/* interface name */ #endif FILE *f; char devname[20]; int plen, scope, dad_status, if_idx; char addr6p[8][5]; int intf_found = 0; char my_addr[16]; char temp_addr[32]; int i, j; if ((f = fopen("/proc/net/if_inet6", "r")) != NULL) { while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n", addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7], &if_idx, &plen, &scope, &dad_status, devname) != EOF) { #ifdef RAL_DUMMY if (!strcmp(devname, eth0_name)) { #endif #ifdef RAL_REALTIME if (!strcmp(devname, graal0_name)) { #endif intf_found = 1; // retrieve numerical value if ((scope ==0)||(scope== IPV6_ADDR_LINKLOCAL)) { DEBUG(" adresse %s:%s:%s:%s:%s:%s:%s:%s", addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7]); DEBUG(" Scope:"); switch (scope) { case 0: DEBUG("Global"); break; case IPV6_ADDR_LINKLOCAL: DEBUG("Link"); break; default: DEBUG("Unknown"); } DEBUG("\n Numerical value: "); for (i = 0; i < 8; i++) { for (j=0; j<4; j++) { addr6p[i][j]= toupper(addr6p[i][j]); if ((addr6p[i][j] >= 'A') && (addr6p[i][j] <= 'F')) { temp_addr[(4*i)+j] =(unsigned short int)(addr6p[i][j]-'A')+10; } else if ((addr6p[i][j] >= '0') && (addr6p[i][j] <= '9')) { temp_addr[(4*i)+j] =(unsigned short int)(addr6p[i][j]-'0'); } } my_addr[2*i]= (16*temp_addr[(4*i)])+temp_addr[(4*i)+1]; my_addr[(2*i)+1]= (16*temp_addr[(4*i)+2])+temp_addr[(4*i)+3]; } for (i=0; i<16; i++) { DEBUG("-%hhx-",my_addr[i]); } DEBUG("\n\n"); } } } fclose(f); if (!intf_found) { ERR("interface not found\n\n"); } } } //--------------------------------------------------------------------------- int inits(int argc, char *argv[]) { //--------------------------------------------------------------------------- MIH_C_TRANSACTION_ID_T transaction_id; unsigned int t; struct sockaddr_un nas_socket; ralpriv = &rl_priv; memset(ralpriv, 0, sizeof(struct ral_lte_priv)); memset(g_msg_codec_recv_buffer, 0, MSG_CODEC_RECV_BUFFER_SIZE); // Initialize defaults g_ral_ip_address = DEFAULT_IP_ADDRESS_RAL; g_ral_listening_port_for_mihf = DEFAULT_LOCAL_PORT_RAL; g_mihf_remote_port = DEFAULT_REMOTE_PORT_MIHF; g_mihf_ip_address = DEFAULT_IP_ADDRESS_MIHF; g_link_id = DEFAULT_LINK_ID; g_mihf_id = DEFAULT_MIHF_ID; g_sockd_mihf = -1; g_log_output = LOG_TO_CONSOLE; MIH_C_init(g_log_output); if (parse_opts( argc, argv) < 0) { exit(0); } if (mRALlte_mihf_connect() < 0 ) { ERR("Could not connect to MIH-F...exiting\n"); exit(-1); } DEBUG("MT-MIHF socket initialized.\n\n"); // excluded MIH_C_LINK_AC_TYPE_NONE // excluded MIH_C_LINK_AC_TYPE_LINK_LOW_POWER // excluded MIH_C_LINK_AC_TYPE_NONE ralpriv->mih_supported_action_list = MIH_C_LINK_AC_TYPE_LINK_DISCONNECT | MIH_C_LINK_AC_TYPE_LINK_POWER_DOWN | MIH_C_LINK_AC_TYPE_LINK_POWER_UP | MIH_C_LINK_AC_TYPE_LINK_FLOW_ATTR | MIH_C_LINK_AC_TYPE_LINK_ACTIVATE_RESOURCES | MIH_C_LINK_AC_TYPE_LINK_DEACTIVATE_RESOURCES; ralpriv->mih_supported_link_event_list = MIH_C_BIT_LINK_DETECTED | MIH_C_BIT_LINK_UP | MIH_C_BIT_LINK_DOWN | MIH_C_BIT_LINK_PARAMETERS_REPORT | MIH_C_BIT_LINK_GOING_DOWN | MIH_C_BIT_LINK_HANDOVER_IMMINENT | MIH_C_BIT_LINK_HANDOVER_COMPLETE | MIH_C_BIT_LINK_PDU_TRANSMIT_STATUS; ralpriv->mih_supported_link_command_list = MIH_C_BIT_LINK_EVENT_SUBSCRIBE | MIH_C_BIT_LINK_EVENT_UNSUBSCRIBE | \ MIH_C_BIT_LINK_GET_PARAMETERS | MIH_C_BIT_LINK_CONFIGURE_THRESHOLDS | \ MIH_C_BIT_LINK_ACTION; ralpriv->link_to_be_detected = MIH_C_BOOLEAN_TRUE; NOTICE("[MSC_NEW][%s][MIH-F=%s]\n", getTimeStamp4Log(), g_mihf_id); NOTICE("[MSC_NEW][%s][RAL=%s]\n", getTimeStamp4Log(), g_link_id); NOTICE("[MSC_NEW][%s][NAS=%s]\n", getTimeStamp4Log(), "nas"); IAL_D_Netlink_socket_init(); DEBUG("Waiting for a connection from NAS Driver ...\n"); t = sizeof(nas_socket); if ((s_nas = accept(netl_s, (struct sockaddr *)&nas_socket, &t)) == -1) { perror("main - s_nas - accept "); exit(1); } DEBUG("NAS Driver Connected.\n\n"); // get interface ipv6 address mRALlte_get_IPv6_addr(); // get L2 identifier IAL_process_DNAS_message(IO_OBJ_IMEI, IO_CMD_ADD, 0); IAL_decode_NAS_message(); // Initialize measurements IAL_NAS_measures_init(); ralpriv->state = DISCONNECTED; IAL_process_DNAS_message(IO_OBJ_MEAS, IO_CMD_LIST, ralpriv->cell_id); IAL_decode_NAS_message(); transaction_id = (MIH_C_TRANSACTION_ID_T)0; mRALlte_send_link_register_indication(&transaction_id); return 0; } //--------------------------------------------------------------------------- int main(int argc, char *argv[]) { //--------------------------------------------------------------------------- int rc, done; int meas_polling_counter; fd_set readfds; struct timeval tv; inits(argc, argv); done = 0; ralpriv->pending_req_flag = 0; meas_polling_counter = 1; do { // Create fd_set and wait for input; FD_ZERO(&readfds); FD_SET(g_sockd_mihf, &readfds); FD_SET (s_nas, &readfds); tv.tv_sec = MIH_C_RADIO_POLLING_INTERVAL_SECONDS; tv.tv_usec = MIH_C_RADIO_POLLING_INTERVAL_MICRO_SECONDS; rc= select(FD_SETSIZE, &readfds, NULL, NULL, &tv); if(rc == -1) { perror("select"); done = 1; } //something received! if(rc >= 0) { if(FD_ISSET(g_sockd_mihf, &readfds)) { done=mRALlte_mih_link_process_message(); } /*else { // tick mRALlte_mih_fsm(NULL, 0); }*/ if (FD_ISSET(s_nas,&readfds)) { //printf("\n something received s_nas\n"); done = IAL_decode_NAS_message(); } //get measures from NAS - timer = 21x100ms -- impair // if (meas_polling_counter ++ == 51){ if (meas_polling_counter ++ == 51) { IAL_NAS_measures_update(meas_polling_counter); rallte_NAS_measures_polling(); meas_polling_counter =1; } if (ralpriv->pending_req_flag > 0) { //wait until next time ralpriv->pending_req_flag ++; rallte_verifyPendingConnection(); } } } while(!done); close(g_sockd_mihf); close(netl_s); MIH_C_exit(); return 0; }