Files
openairinterface5g/openair-cn/SGI/sgi_util.c
T
Lionel Gauthier 91e6729d46 Licence
git-svn-id: http://svn.eurecom.fr/openair4G/trunk@5169 818b1a75-f10b-46b9-bf7c-635c3b92a50f
2014-03-14 09:49:18 +00:00

247 lines
9.4 KiB
C
Executable File

/*******************************************************************************
Eurecom OpenAirInterface core network
Copyright(c) 1999 - 2014 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope 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
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : EURECOM,
Campus SophiaTech,
450 Route des Chappes,
CS 50193
06904 Biot Sophia Antipolis cedex,
FRANCE
*******************************************************************************/
/*! \file sgi_util.c
* \brief
* \author Lionel Gauthier
* \company Eurecom
* \email: lionel.gauthier@eurecom.fr
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <net/if_arp.h>
#include <netinet/in.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include "sgi.h"
#define FW_2_PRINT_BUFFER_LEN 10000
static char fw_2_print_buffer[FW_2_PRINT_BUFFER_LEN];
//-----------------------------------------------------------------------------
void sgi_print_hex_octets(unsigned char* dataP, unsigned long sizeP)
//-----------------------------------------------------------------------------
{
return;
unsigned long octet_index = 0;
unsigned long buffer_marker = 0;
unsigned char aindex;
if (dataP == NULL) {
return;
}
SGI_IF_DEBUG("------+-------------------------------------------------|\n");
SGI_IF_DEBUG(" | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n");
SGI_IF_DEBUG("------+-------------------------------------------------|\n");
for (octet_index = 0; octet_index < sizeP; octet_index++) {
if ((octet_index % 16) == 0){
if (octet_index != 0) {
buffer_marker+=snprintf(&fw_2_print_buffer[buffer_marker], FW_2_PRINT_BUFFER_LEN - buffer_marker, " |\n");
SGI_IF_DEBUG("%s", fw_2_print_buffer);
buffer_marker = 0;
}
buffer_marker+=snprintf(&fw_2_print_buffer[buffer_marker], FW_2_PRINT_BUFFER_LEN - buffer_marker, " %04ld |", octet_index);
}
/*
* Print every single octet in hexadecimal form
*/
buffer_marker+=snprintf(&fw_2_print_buffer[buffer_marker], FW_2_PRINT_BUFFER_LEN - buffer_marker, " %02x", dataP[octet_index]);
/*
* Align newline and pipes according to the octets in groups of 2
*/
}
/*
* Append enough spaces and put final pipe
*/
for (aindex = octet_index; aindex < 16; ++aindex)
buffer_marker+=snprintf(&fw_2_print_buffer[buffer_marker], FW_2_PRINT_BUFFER_LEN - buffer_marker, " ");
//SGI_IF_DEBUG(" ");
buffer_marker+=snprintf(&fw_2_print_buffer[buffer_marker], FW_2_PRINT_BUFFER_LEN - buffer_marker, " |\n");
SGI_IF_DEBUG("%s",fw_2_print_buffer);
}
//-----------------------------------------------------------------------------
char* sgi_status_2_str(SGIStatus_t statusP)
//-----------------------------------------------------------------------------
{
switch (statusP) {
case SGI_STATUS_OK: return "SGI_STATUS_OK";break;
case SGI_STATUS_ERROR_CONTEXT_ALREADY_EXIST: return "SGI_STATUS_ERROR_CONTEXT_ALREADY_EXIST";break;
case SGI_STATUS_ERROR_CONTEXT_NOT_FOUND: return "SGI_STATUS_ERROR_CONTEXT_NOT_FOUND";break;
case SGI_STATUS_ERROR_INVALID_MESSAGE_FORMAT: return "SGI_STATUS_ERROR_INVALID_MESSAGE_FORMAT";break;
case SGI_STATUS_ERROR_SERVICE_NOT_SUPPORTED: return "SGI_STATUS_ERROR_SERVICE_NOT_SUPPORTED";break;
case SGI_STATUS_ERROR_SYSTEM_FAILURE: return "SGI_STATUS_ERROR_SYSTEM_FAILURE";break;
case SGI_STATUS_ERROR_NO_RESOURCES_AVAILABLE: return "SGI_STATUS_ERROR_NO_RESOURCES_AVAILABLE";break;
case SGI_STATUS_ERROR_NO_MEMORY_AVAILABLE: return "SGI_STATUS_ERROR_NO_MEMORY_AVAILABLE";break;
default: return "UNKNOWN_SGI_STATUS";
}
}
//-----------------------------------------------------------------------------
char* sgi_arpopcode_2_str(unsigned short int opcodeP)
//-----------------------------------------------------------------------------
{
switch (opcodeP) {
case ARPOP_REQUEST: return "ARPOP_REQUEST";break;
case ARPOP_REPLY: return "ARPOP_REPLY";break;
case ARPOP_RREQUEST: return "ARPOP_RREQUEST";break;
case ARPOP_RREPLY: return "ARPOP_RREPLY";break;
case ARPOP_InREQUEST: return "ARPOP_InREQUEST";break;
case ARPOP_InREPLY: return "ARPOP_InREPLY";break;
case ARPOP_NAK: return "ARPOP_NAK";break;
default: return "UNKNOWN_ARP_OPCODE";
}
}
//-----------------------------------------------------------------------------
unsigned short in_cksum(unsigned short *addr, int len)
//-----------------------------------------------------------------------------
{
register int sum = 0;
u_short answer = 0;
register u_short *w = addr;
register int nleft = len;
/*
* Our algorithm is simple, using a 32 bit accumulator (sum), we add
* sequential 16 bit words to it, and at the end, fold back all the
* carry bits from the top 16 bits into the lower 16 bits.
*/
while (nleft > 1)
{
sum += *w++;
nleft -= 2;
}
/* mop up an odd byte, if necessary */
if (nleft == 1)
{
*(u_char *) (&answer) = *(u_char *) w;
sum += answer;
}
/* add back carry outs from top 16 bits to low 16 bits */
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return (answer);
}
//-----------------------------------------------------------------------------
void sgi_send_arp_request(sgi_data_t *sgi_dataP, char* dst_ip_addrP)
//-----------------------------------------------------------------------------
{
char buffer[100]; // ARP request is 60 bytes including ethernet
struct arphdr_s *arph = (struct arphdr_s *)(buffer);
struct hostent *hp = NULL;
uint32_t i;
struct in_addr ip_dst;
struct ifreq ifr;
struct iovec iov[2];
sgi_dataP->eh.ether_dhost[0] = (u_int8_t)(0xFF);
sgi_dataP->eh.ether_dhost[1] = (u_int8_t)(0xFF);
sgi_dataP->eh.ether_dhost[2] = (u_int8_t)(0xFF);
sgi_dataP->eh.ether_dhost[3] = (u_int8_t)(0xFF);
sgi_dataP->eh.ether_dhost[4] = (u_int8_t)(0xFF);
sgi_dataP->eh.ether_dhost[5] = (u_int8_t)(0xFF);
// get IP address of the default virtual interface
ifr.ifr_addr.sa_family = AF_INET;
sprintf(ifr.ifr_name, "%s.%d",sgi_dataP->interface_name,SGI_MIN_EPS_BEARER_ID);
if (ioctl(sgi_dataP->sd[0], SIOCGIFADDR, &ifr) != 0) {
SGI_IF_ERROR("Error during IP ADDRESS RETRIEVAL ON SGI INTERFACE (%s:%d)\n",strerror(errno), errno);
exit (-1);
}
if ((hp = gethostbyname(dst_ip_addrP)) == NULL)
{
SGI_IF_DEBUG("gethostbyname() is OK.\n");
if ((ip_dst.s_addr = inet_addr(dst_ip_addrP)) == -1)
{
SGI_IF_ERROR("%s: Can't resolve, unknown host.\n", dst_ip_addrP);
exit(1);
}
}
else
bcopy(hp->h_addr_list[0], &ip_dst.s_addr, hp->h_length);
arph->ar_hrd = htons(ARPHRD_ETHER);
arph->ar_pro = htons(ETH_P_IP);
arph->ar_hln = ETH_ALEN;
arph->ar_pln = 4;
arph->ar_op = htons(ARPOP_REQUEST);
// sources
memcpy(arph->ar_sha, sgi_dataP->eh.ether_shost, ETH_ALEN);
i = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
arph->ar_sip[3] = i >> 24;
arph->ar_sip[2] = (i & 0x00FF0000) >> 16;
arph->ar_sip[1] = (i & 0x0000FF00) >> 8;
arph->ar_sip[0] = (i & 0x000000FF);
// destinations
memset(arph->ar_tha, 0, ETH_ALEN);
i = ip_dst.s_addr;
arph->ar_tip[3] = i >> 24;
arph->ar_tip[2] = (i & 0x00FF0000) >> 16;
arph->ar_tip[1] = (i & 0x0000FF00) >> 8;
arph->ar_tip[0] = (i & 0x000000FF);
// save ip address of router for comparing with ARP REPLY
sgi_dataP->ipv4_addr_of_router = ip_dst.s_addr;
iov[0].iov_base = &sgi_dataP->eh;
iov[0].iov_len = sizeof(sgi_dataP->eh);
iov[1].iov_base = (void *)buffer;
iov[1].iov_len = sizeof (struct arphdr) + ETH_ALEN*2 + 4*2;
#ifdef VLAN8021Q
sgi_data_p->eh.ether_vlan8021q.vlan_tpid = htons(0x8100);
sgi_dataP->eh.ether_vlan8021q.vlan_tci = htons(0x7000 | 0x0000 | SGI_MIN_EPS_BEARER_ID);
#endif
sgi_dataP->eh.ether_type = htons(ETH_P_ARP);
sgi_print_hex_octets(iov[0].iov_base, iov[0].iov_len);
sgi_print_hex_octets(iov[1].iov_base, iov[1].iov_len);
if (writev(sgi_dataP->sd[0], (const struct iovec *)&iov, 2) < 0) {
SGI_IF_ERROR("Error during send ARP to socket %d bearer id %d : (%s:%d)\n",
sgi_dataP->sd[0],
SGI_MIN_EPS_BEARER_ID,
strerror(errno),
errno);
exit(1);
}
}