#include #include #include #include #include #include #include #include #include #include #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) //----------------------------------------------------------------------------- { 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); } }