/****************************************************************************** * Copyright (c) 2000-2019 Ericsson Telecom AB * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html ******************************************************************************/ /////////////////////////////////////////////////////////////////////////////// // // File: TCCInterface.cc // Description: TCC Useful Functions: Interface Functions // Rev: R36B // Prodnr: CNL 113 472 // /////////////////////////////////////////////////////////////////////////////// #include "TCCInterface_Functions.hh" #include #include #include #include #include #include #include #include // gethostbyname #include #if defined LINUX #include #include #include "TCCInterface_ip.h" #endif #if defined LKSCTP_1_0_7 || defined LKSCTP_1_0_9 || USE_SCTP #include #endif #if defined SOLARIS || defined SOLARIS8 # include #endif namespace TCCInterface__Functions { TCCInterface__PortStatus f__getPortAvailabilityStatus(const CHARSTRING& ipAddress, const INTEGER& portNumber, const TCCInterface__ProtocolType& protocolType){ int addrfamily = 0; int addrtype = 0; int addrproto = 0; struct sockaddr_in saddr; memset(&saddr, 0, sizeof(saddr)); // Legacy system support just for fun. Because we like Noah #ifdef AF_INET6 struct sockaddr_in6 saddr6; memset(&saddr6, 0, sizeof(saddr6)); #endif // Always prepare to worst TCCInterface__PortStatus ret_val = TCCInterface__PortStatus::PORT__STATUS__PARAMETER__ERROR; // and have a beer // Ah, new acquisitions! You are a protocol droid, are you not? // I am C-3PO, human/cyborg... // Just determine the protocol switch(protocolType){ case TCCInterface__ProtocolType::PROTO__TYPE__UDP: addrtype=SOCK_DGRAM; break; case TCCInterface__ProtocolType::PROTO__TYPE__TCP: addrtype=SOCK_STREAM; break; #if defined LKSCTP_1_0_7 || defined LKSCTP_1_0_9 || USE_SCTP case TCCInterface__ProtocolType::PROTO__TYPE__SCTP: addrtype=SOCK_STREAM; addrproto=IPPROTO_SCTP; break; #endif default: // Ouch! Pay attention to what you're doing! TTCN_warning("The f_getPortAvailabilityStatus was called with unsupported protocol. Try to enable the sctp support."); return ret_val; break; } // What port? if(portNumber<=0 || portNumber>65535){ // I'm terribly sorry about all this. TTCN_warning("The f_getPortAvailabilityStatus was called with invalid port number. %s",(const char*)int2str(portNumber)); return ret_val; } // Which address? if(inet_pton(AF_INET, ipAddress, &(saddr.sin_addr))) { saddr.sin_family = AF_INET; saddr.sin_port = htons( portNumber ); addrfamily = AF_INET; } #ifdef AF_INET6 else if(inet_pton(AF_INET6, ipAddress, &(saddr6.sin6_addr))) { saddr6.sin6_family = AF_INET6; saddr6.sin6_port = htons( portNumber ); addrfamily = AF_INET6; } #endif else { // This is all your fault. TTCN_warning("The f_getPortAvailabilityStatus was called with invalid address: %s",(const char*)ipAddress); return ret_val; } int sock=socket(addrfamily,addrtype,addrproto); if(sock==-1){ // We've stopped. Wake up! Wake up! TTCN_warning("f_getPortAvailabilityStatus socket call failed: %d %s",errno,strerror(errno)); return TCCInterface__PortStatus::PORT__STATUS__INTERNAL__ERROR; } int b_res=-1; if(addrfamily == AF_INET){ b_res=bind(sock,(struct sockaddr *)&saddr, sizeof(saddr)); } #ifdef AF_INET6 else { b_res=bind(sock,(struct sockaddr *)&saddr6, sizeof(saddr6)); } #endif if(b_res==0){ // success. The port was free to use, but not more ret_val = TCCInterface__PortStatus::PORT__STATUS__WAS__VACANT; } else { if(errno==EADDRINUSE){ // Somebody else use the port already ret_val = TCCInterface__PortStatus::PORT__STATUS__WAS__OCCUPIED; } else { // I have a bad feeling about this. // Wrong address/port combination. TTCN_warning("The f_getPortAvailabilityStatus called with invalid arguments. The system returned: %d %s",errno,strerror(errno)); TTCN_warning("f_getPortAvailabilityStatus parameters: %s %s",(const char*)ipAddress,(const char*)int2str(portNumber)); } } close(sock); // the status information is not valid any more. We can return whatever we want. Doesn't matter. return ret_val; } /////////////////////////////////////////////////////////////////////////////// // Function: f__setIP // // Purpose: // Set IP address, subnet mask and broadcast address in a network inteface // If number is set, a range of virtual interfaces are set up with // continuous IP address (no subnet mask, broadcast checking) // // Parameters: // interface - *in* *charstring* - network interface // ipaddress - *in* *charstring* - starting IP address // subnetmask - *in* *charstring* - subnetmask // broadcast - *in* *charstring* - broadcast // number - *in* *integer* - number of interfaces to set up // // Return Value: // - // // Errors: // - // // Detailed description: // - // /////////////////////////////////////////////////////////////////////////////// void f__setIP(const CHARSTRING& interface, const CHARSTRING& ipaddress, const CHARSTRING& subnetmask, const CHARSTRING& broadcast, const INTEGER& number) { #if defined USE_IPROUTE && defined LINUX if (! f__setIP__ip(interface, ipaddress, 32, 1)){ TTCN_warning("f_setIP_ip error!"); } #else #if defined LINUX || defined SOLARIS || defined SOLARIS8 /* Check the name of the interface */ if (!interface.is_bound()) TTCN_error("f_setIP(): Unbound argument `interface'."); int interface_len = interface.lengthof(); if (interface_len == 0) TTCN_error("f_setIP(): Argument `interface' " "is an empty string."); else if (interface_len > IFNAMSIZ) TTCN_error("f_setIP(): Argument " "`interface' is too long (expected: at most %d, given: %d characters).", IFNAMSIZ, interface_len); const char *interface_str = interface; /* Check the IP address */ if (!ipaddress.is_bound()) TTCN_error("f_setIP(): Unbound argument `ipaddress'."); int ip_len = ipaddress.lengthof(); if (ip_len < 7 || ip_len > 15) TTCN_error("f_setIP(): Invalid length of argument `ipaddress' " "(expected 7-15, given: %d characters).", ip_len); /* Check the subnet mask */ if (!subnetmask.is_bound()) TTCN_error("f_setIP(): Unbound argument `subnetmask'."); int subnetmask_len = subnetmask.lengthof(); if (subnetmask_len < 7 || subnetmask_len > 15) TTCN_error("f_setIP(): Invalid length of argument " "`subnetmask' (expected 7-15, given: %d characters).", subnetmask_len); /* Check the broadcast address */ if (!broadcast.is_bound()) TTCN_error("f_setIP(): Unbound argument `broadcast'."); int broadcast_len = broadcast.lengthof(); if (broadcast_len < 7 || broadcast_len > 15) TTCN_error("f_setIP(): Invalid length of argument " "`broadcast' (expected 7-15, given: %d characters).", broadcast_len); /* Check number parameter */ int loop = 1; if (!number.is_bound()) TTCN_error("f_setIP(): Unbound argument `number'."); else loop = (int)number; /* Get start position (of virtual interface) */ int start = 0; if (strchr(interface_str, ':') != NULL) { start = atoi(strchr(interface_str,':')+1); } /* Convert addresses */ unsigned char ip[4]; unsigned char subnet[4]; unsigned char broad[4]; inet_aton(ipaddress, (struct in_addr *)&(ip[0])); inet_aton(subnetmask, (struct in_addr *)&(subnet[0])); inet_aton(broadcast, (struct in_addr *)&(broad[0])); /* Set address of interfaces */ if(loop != 1) { /* Set up number of virtual interfaces */ for(int i=start; i<(loop+start); i++) { char *ifname; ifname = (char *)Malloc(20*sizeof(char *)); if(strchr(interface_str, ':') != NULL) { // if virtual, change the end strncpy(ifname, interface_str, strlen(interface_str)-strlen(strchr(interface_str,':'))+2); ifname[strlen(interface_str)-strlen(strchr(interface_str,':'))+1] = '\0'; strcat(ifname,(const char *)int2str(i)); } else { // if real, append strcpy(ifname,interface_str); strcat(ifname,":"); strcat(ifname,(const char *)int2str(i)); } /* Set the IP, Netmask, Broadcast for the actual virtual interface */ /* Open a socket */ int sock = socket(PF_INET, SOCK_DGRAM, 0); if (sock < 0) TTCN_error("f_setIP(): Could not create socket."); struct ifreq ifr; struct sockaddr_in *addr = (struct sockaddr_in*)&ifr.ifr_addr; /* Set the IP address */ memset(&ifr, 0, sizeof(struct ifreq)); memcpy(ifr.ifr_name, ifname, strlen(ifname)); addr->sin_family = AF_INET; memcpy(&addr->sin_addr, ip, 4); if (ioctl(sock, SIOCSIFADDR, &ifr) < 0) { TTCN_warning("f_setIP(): Could not set IP address of interface `%s'.", interface_str); } /* Set the subnet mask */ memset(&ifr, 0, sizeof(struct ifreq)); memcpy(ifr.ifr_name, ifname, strlen(ifname)); addr->sin_family = AF_INET; memcpy(&addr->sin_addr, subnet, 4); if (ioctl(sock, SIOCSIFNETMASK, &ifr) < 0) { TTCN_warning("f_setIP(): Could not set subnetmask of interface `%s'.", interface_str); } /* Set the broadcast address */ memset(&ifr, 0, sizeof(struct ifreq)); memcpy(ifr.ifr_name, ifname, strlen(ifname)); addr->sin_family = AF_INET; memcpy(&addr->sin_addr, broad, 4); if (ioctl(sock, SIOCSIFBRDADDR, &ifr) < 0) { TTCN_warning("f_setIP(): Could not set broadcast address of interface `%s'.", interface_str); } close(sock); Free(ifname); /* Step the IPaddress */ if(ip[3]+1 > 254) { // 255 for broadcast ip[3] = 1; // 0 reserved ip[2] += 1; if(ip[2] > 254) { ip[2] = 0; ip[1] += 1; if(ip[1] > 254) { ip[1] = 0; ip[0] += 1; if(ip[0] > 254) { TTCN_error("f_setIP(): IP address range limit."); } } } } else { ip[3] += 1; } }//for end }//if loop end else { /* Open a socket */ int sock = socket(PF_INET, SOCK_DGRAM, 0); if (sock < 0) TTCN_error("f_setIP(): Could not create socket."); struct ifreq ifr; struct sockaddr_in *addr = (struct sockaddr_in*)&ifr.ifr_addr; /* Set the IP address */ memset(&ifr, 0, sizeof(struct ifreq)); memcpy(ifr.ifr_name, interface_str, interface_len); addr->sin_family = AF_INET; memcpy(&addr->sin_addr, ip, 4); if (ioctl(sock, SIOCSIFADDR, &ifr) < 0) { TTCN_warning("f_setIP(): Could not set IP address of interface `%s'.", interface_str); } /* Set the subnet mask */ memset(&ifr, 0, sizeof(struct ifreq)); memcpy(ifr.ifr_name, interface_str, interface_len); addr->sin_family = AF_INET; memcpy(&addr->sin_addr, subnet, 4); if (ioctl(sock, SIOCSIFNETMASK, &ifr) < 0) { TTCN_warning("f_setIP(): Could not set subnet mask of interface `%s'.", interface_str); } /* Set the broadcast address */ memset(&ifr, 0, sizeof(struct ifreq)); memcpy(ifr.ifr_name, interface_str, interface_len); addr->sin_family = AF_INET; memcpy(&addr->sin_addr, broad, 4); if (ioctl(sock, SIOCSIFBRDADDR, &ifr) < 0) { TTCN_warning("f_setIP(): Could not set broadcast address of interface `%s'.", interface_str); } close(sock); } #else TTCN_error("f_setIP(): Setting the IP address is supported on Linux and Solaris only."); #endif #endif // USE_IPROUTE } /////////////////////////////////////////////////////////////////////////////// // Function: f__deleteIP // // Purpose: // Delete IP address from a network inteface // // Parameters: // interface - *in* *charstring* - network interface // // Return Value: // - // // Errors: // - // // Detailed description: // - // /////////////////////////////////////////////////////////////////////////////// void f__deleteIP(const CHARSTRING& interface) { #if defined USE_IPROUTE && defined LINUX if (! f__setIP__ip(interface, "", 32, 0)){ TTCN_warning("f_delIP_ip error!"); } #else #if defined LINUX || defined SOLARIS || defined SOLARIS8 /* Check the name of the interface */ if (!interface.is_bound()) TTCN_error("f_deleteIP(): Unbound argument `interface'."); int interface_len = interface.lengthof(); if (interface_len == 0) TTCN_error("f_deleteIP(): Argument `interface' " "is an empty string."); else if (interface_len > IFNAMSIZ) TTCN_error("f_deleteIP(): Argument " "`interface' is too long (expected: at most %d, given: %d characters).", IFNAMSIZ, interface_len); const char *interface_str = interface; /* Open a socket */ int sock = socket(PF_INET, SOCK_DGRAM, 0); if (sock < 0) TTCN_error("f_deleteIP(): Could not create socket."); struct ifreq ifr; memset(&ifr, 0, sizeof(struct ifreq)); memcpy(ifr.ifr_name, interface_str, interface_len); if (strchr(interface_str, ':') != NULL) { /* The interface is a virtual interface (e.g. eth1:0) */ /* set the status to down */ if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) { TTCN_warning("f_deleteIP(): Could not get the flags of interface `%s'.", interface_str); } ifr.ifr_flags &= ~IFF_UP; if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) { TTCN_warning("f_deleteIP(): Could not set the flags of interface `%s'.", interface_str); } } else { /* The interface is a real interface (e.g. eth2) */ /* assign IP address 0.0.0.0 = delete */ struct sockaddr_in *addr = (struct sockaddr_in*)&ifr.ifr_addr; addr->sin_family = AF_INET; if (ioctl(sock, SIOCSIFADDR, &ifr) < 0) { TTCN_warning("f_deleteIP(): Could not delete IP address on interface `%s'.",interface_str); } } close(sock); #else TTCN_error("f_deleteIP(): Deleting the IP address is supported on Linux and Solaris only."); #endif #endif } /////////////////////////////////////////////////////////////////////////////// // Function: f__getIP // // Purpose: // Get IP address, subnet mask and broadcast address from a network inteface // // Parameters: // interface - *in* *charstring* - network interface // ip - *out* *charstring* - IP address // netmask - *out* *charstring* - netmask // broadcast - *out* *charstring* - broadcast // addressType - *in* - type of IP addresses (default is IPv4) // // Return Value: // - // // Errors: // - // // Detailed description: // - // /////////////////////////////////////////////////////////////////////////////// void f__getIP(const CHARSTRING& interface, CHARSTRING& ip, CHARSTRING& netmask, CHARSTRING& broadcast, const TCCInterface__IPAddressType& addressType) { ip =""; netmask = ""; broadcast =""; /* Check the name of the interface */ if (!interface.is_bound()) TTCN_error("f_getIP(): Unbound argument `interface'."); int interface_len = interface.lengthof(); if (interface_len == 0) TTCN_error("f_getIP(): Argument `interface' " "is an empty string."); else if (interface_len > IFNAMSIZ) TTCN_error("f_getIP(): Argument " "`interface' is too long (expected: at most %d, given: %d characters).", IFNAMSIZ, interface_len); const char *interface_str = interface; switch (addressType) { case TCCInterface__IPAddressType::IPv4: { //IPv4 /* Open a socket */ int sock = socket(PF_INET, SOCK_DGRAM, 0); if (sock < 0) TTCN_error("f_getIP(): Could not create socket."); struct ifreq ifr; struct sockaddr_in *addr = (struct sockaddr_in*)&ifr.ifr_addr; /* Get IP address */ memset(&ifr, 0, sizeof(struct ifreq)); memcpy(ifr.ifr_name, interface_str, interface_len); if (ioctl(sock, SIOCGIFADDR, &ifr) < 0) { TTCN_warning("f_getIP(): Could not get address of interface '%s', %s.\n", interface_str,strerror(errno)); } else { ip = inet_ntoa(addr->sin_addr); } /* Get subnet mask */ memset(&ifr, 0, sizeof(struct ifreq)); memcpy(ifr.ifr_name, interface_str, interface_len); if (ioctl(sock, SIOCGIFNETMASK, &ifr) < 0) { TTCN_warning("f_getIP(): Could not get subnet mask of interface `%s', %s.", interface_str,strerror(errno)); } else { netmask = inet_ntoa(addr->sin_addr); } /* Get the broadcast address */ memset(&ifr, 0, sizeof(struct ifreq)); memcpy(ifr.ifr_name, interface_str, interface_len); if (ioctl(sock, SIOCGIFBRDADDR, &ifr) < 0) { TTCN_warning("f_getIP(): Could not get broadcast address of interface `%s', %s.", interface_str,strerror(errno)); } else { broadcast = inet_ntoa(addr->sin_addr); } close(sock); break; } case TCCInterface__IPAddressType::IPv6: { //IPv6 #if defined LINUX /* // works only with linux! char devname[IFNAMSIZ]; char addr6p[8][5]; char addr6[40]; int plen, scope, dad_status, if_idx; FILE *f; 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) { if (!strcmp(devname, interface)) { sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s", addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7]); ip = addr6; } } fclose(f); } */ char ipaddr[INET6_ADDRSTRLEN]; char subnet[INET6_ADDRSTRLEN]; struct ifaddrs *ifap,*ifa; if((getifaddrs(&ifap)) <0){ TTCN_warning("f_getIP(): Could not get address of interface '%s', %s.\n", interface_str, strerror(errno)); break; } for (ifa = ifap; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_name == interface && ifa->ifa_addr != NULL) { if (ifa->ifa_addr->sa_family == AF_INET6) { struct sockaddr_in6 *sa = (struct sockaddr_in6 *) ifa->ifa_addr; inet_ntop(AF_INET6,&(sa->sin6_addr),ipaddr,INET6_ADDRSTRLEN); ip = ipaddr; struct sockaddr_in6 *saMask = (struct sockaddr_in6 *)ifa->ifa_netmask; inet_ntop(AF_INET6,&(saMask->sin6_addr),subnet,INET6_ADDRSTRLEN); netmask = subnet; broadcast = ""; //broadcast address not supported in IPv6 freeifaddrs(ifap); break; } } } #else TTCN_error("f_getIP(): Getting the IPv6 address is supported on Linux only."); #endif break; } default: { TTCN_error("f_getIP(): Not supported address type."); break; } } //switch } /////////////////////////////////////////////////////////////////////////////// // Function: f__setInterfaceUp // // Purpose: // Set up a network interface // // Parameters: // interface - *in* *charstring* - network interface // addressType - *in* - type of IP addresses (default is IPv4) // // Return Value: // - // // Errors: // - // // Detailed description: // - // /////////////////////////////////////////////////////////////////////////////// void f__setInterfaceUp(const CHARSTRING& interface, const TCCInterface__IPAddressType& addressType) { #if defined LINUX || defined SOLARIS || defined SOLARIS8 /* Check the name of the interface */ if (!interface.is_bound()) TTCN_error("f_setInterfaceUp(): Unbound argument `interface'."); int interface_len = interface.lengthof(); if (interface_len == 0) TTCN_error("f_setInterfaceUp(): Argument `interface' " "is an empty string."); else if (interface_len > IFNAMSIZ) TTCN_error("f_setInterfaceUp(): Argument " "`interface' is too long (expected: at most %d, given: %d characters).", IFNAMSIZ, interface_len); const char *interface_str = interface; int sock; struct ifreq ifr; int sa_family; switch (addressType) { case TCCInterface__IPAddressType::IPv4: { //IPv4 sa_family = AF_INET; break; } case TCCInterface__IPAddressType::IPv6: { //IPv6 sa_family = AF_INET6; break; } default: { TTCN_error("f_setInterfaceDown(): Not supported address type."); break; } } //switch if ((sock = socket(sa_family, SOCK_DGRAM, IPPROTO_IP)) < 0) { TTCN_error("f_setInterfaceUp(): Cannot open socket."); } memset(&ifr, 0, sizeof(struct ifreq)); strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name)-1); if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) { TTCN_warning("f_setInterfaceUp(): Cannot get flags of interface '%s', %s.", interface_str, strerror(errno)); } ifr.ifr_flags |= IFF_UP; if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) { TTCN_warning("f_setInterfaceUp(): Cannot set up interface '%s', %s.", interface_str, strerror(errno)); } close(sock); #else TTCN_error("f_setInterfaceUp(): Setting up the interface is supported on Linux and Solaris only."); #endif } /////////////////////////////////////////////////////////////////////////////// // Function: f__setInterfaceDown // // Purpose: // Set down a network interface // // Parameters: // interface - *in* *charstring* - network interface // addressType - *in* - type of IP addresses (default is IPv4) // // Return Value: // - // // Errors: // - // // Detailed description: // - // /////////////////////////////////////////////////////////////////////////////// void f__setInterfaceDown(const CHARSTRING& interface, const TCCInterface__IPAddressType& addressType) { #if defined LINUX || defined SOLARIS || defined SOLARIS8 /* Check the name of the interface */ if (!interface.is_bound()) TTCN_error("f_setInterfaceDown(): Unbound argument `interface'."); int interface_len = interface.lengthof(); if (interface_len == 0) TTCN_error("f_setInterfaceDown(): Argument `interface' " "is an empty string."); else if (interface_len > IFNAMSIZ) TTCN_error("f_setInterfaceDown(): Argument " "`interface' is too long (expected: at most %d, given: %d characters).", IFNAMSIZ, interface_len); const char *interface_str = interface; int sock; struct ifreq ifr; int sa_family; switch (addressType) { case TCCInterface__IPAddressType::IPv4: { //IPv4 sa_family = AF_INET; break; } case TCCInterface__IPAddressType::IPv6: { //IPv6 sa_family = AF_INET6; break; } default: { TTCN_error("f_setInterfaceDown(): Not supported address type."); break; } } //switch if ((sock = socket(sa_family, SOCK_DGRAM, IPPROTO_IP)) < 0) { TTCN_error("f_setInterfaceDown(): Cannot open socket."); } memset(&ifr, 0, sizeof(struct ifreq)); strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name)-1); if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) { TTCN_warning("f_setInterfaceDown(): Cannot get flags of interface '%s', %s.", interface_str, strerror(errno)); } ifr.ifr_flags &= ~IFF_UP; if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) { TTCN_warning("f_setInterfaceDown(): Cannot set down interface '%s', %s.", interface_str, strerror(errno)); } close(sock); #else TTCN_error("f_setInterfaceDown(): Setting down the interface is supported on Linux and Solaris only."); #endif } /////////////////////////////////////////////////////////////////////////////// // Function: f__getHostName // // Purpose: // Get name of host // // Parameters: // - // // Return Value: // charstring - name of the host // // Errors: // - // // Detailed description: // - // /////////////////////////////////////////////////////////////////////////////// CHARSTRING f__getHostName() { char *ret_val= new char[255]; if (!gethostname(ret_val, 255)) {return ret_val;} else {return "";}; } /////////////////////////////////////////////////////////////////////////////// // Function: f__getIpAddr // // Purpose: // Get IP address of host // // Parameters: // hostname - *in* *charstring* - name of the host // addressType - *in* - type of IP addresses (default is IPv4) // // Return Value: // charstring - IP address of the host // // Errors: // - // // Detailed description: // - // /////////////////////////////////////////////////////////////////////////////// CHARSTRING f__getIpAddr(const CHARSTRING& hostname, const TCCInterface__IPAddressType& addressType) { #if defined LINUX || defined SOLARIS || defined SOLARIS8 int err = 0; struct addrinfo myaddr, *res; memset(&myaddr,0,sizeof(myaddr)); myaddr.ai_flags = AI_ADDRCONFIG|AI_PASSIVE|AI_CANONNAME; myaddr.ai_socktype = SOCK_STREAM; myaddr.ai_protocol = 0; switch (addressType) { case TCCInterface__IPAddressType::IPv4: { //IPv4 myaddr.ai_family = AF_INET; char dst[INET_ADDRSTRLEN]; if ((err = getaddrinfo(hostname, NULL, &myaddr, &res)) != 0) {//&myaddr TTCN_Logger::log ( TTCN_DEBUG, "f_getIpAddr(): getaddrinfo: %i, %s", err, gai_strerror(err) ); return ""; } else { struct sockaddr_in *saddr = (struct sockaddr_in *) res->ai_addr; inet_ntop(AF_INET,&(saddr->sin_addr),dst,INET_ADDRSTRLEN); freeaddrinfo(res); return dst; } break; } case TCCInterface__IPAddressType::IPv6: { //IPv6 char dst[INET6_ADDRSTRLEN]; myaddr.ai_family = AF_INET6; if ((err = getaddrinfo(hostname, NULL, &myaddr, &res)) != 0) { TTCN_Logger::log ( TTCN_DEBUG, "f_getIpAddr(): getaddrinfo: %i, %s", err, gai_strerror(err) ); return ""; } else { struct sockaddr_in6 *saddr = (struct sockaddr_in6 *) res->ai_addr; inet_ntop(AF_INET6,&(saddr->sin6_addr),dst,INET6_ADDRSTRLEN); freeaddrinfo(res); } return dst; break; } default: { TTCN_error("f_getIpAddr(): Not supported address type."); return ""; break; } } //switch #else //Cygwin switch (addressType) { case TCCInterface__IPAddressType::IPv4: { //IPv4 struct hostent *host; struct in_addr address; host = gethostbyname (hostname); //getaddrinfo not supported if (host == NULL) return ""; else { memcpy (&address, host->h_addr_list[0], 4); return inet_ntoa(address); } break; } case TCCInterface__IPAddressType::IPv6: { //IPv6 TTCN_error("f_getIpAddr(): Getting IPv6 addresses is supported on Linux and Solaris only."); return ""; break; } default: { TTCN_error("f_getIpAddr(): Not supported address type."); return ""; break; } } //switch #endif } /////////////////////////////////////////////////////////////////////////////// // Function: f_setIP_ip // // Purpose: // Set IP address, subnet mask in a network inteface // Uses RTLN netlink interface on linux, which is faster than original POSIX. // // Parameters: // interface - *in* *charstring* - network interface // ipaddress - *in* *charstring* - starting IP address // prefix - *in* *integer* - subnetmask of the ipaddress // // Return Value: // True on success, false in other cases. // // Errors: // Many possibilities, all generates a TTCN_warning // // Detailed description: // - // /////////////////////////////////////////////////////////////////////////////// BOOLEAN f__setIP__ip(const CHARSTRING& interface, const CHARSTRING& ipaddress, const INTEGER& prefix = 32, const INTEGER& v_set = 1){ #ifdef LINUX if ((int)prefix > 32 or (int)prefix < 0) { TTCN_warning("Wrong prefix number"); return false; } char buf[3]; sprintf(buf, "%d", (int)prefix); char *ip = (char *)malloc((ipaddress.lengthof() + strlen(buf) + 1 + 1)*sizeof(char)); strcpy(ip, (char*)(const char*)ipaddress); strcat(ip,"/"); strcat(ip, buf); if (rtnl_open(&rth, 0) < 0 ){ TTCN_warning("RTNL: Can not open RTLN link"); return false; } int cmd = (v_set == 1 ? RTM_NEWADDR : RTM_DELADDR); int flags = NLM_F_CREATE|NLM_F_EXCL; struct { struct nlmsghdr n; struct ifaddrmsg ifa; char buf[256]; } req; char *d = NULL; char *lcl_arg = NULL; inet_prefix lcl; //int local_len = 0; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); req.n.nlmsg_flags = NLM_F_REQUEST | flags; req.n.nlmsg_type = cmd; req.ifa.ifa_family = preferred_family; d = (char*)(const char*)interface; // IP_ADDRESS handling lcl_arg = ip; if (get_prefix(&lcl, lcl_arg, req.ifa.ifa_family) == -1) return 0; if (req.ifa.ifa_family == AF_UNSPEC) req.ifa.ifa_family = lcl.family; addattr_l(&req.n, sizeof(req), IFA_LOCAL, &lcl.data, lcl.bytelen); //local_len = lcl.bytelen; // further processing if (cmd == RTM_DELADDR && lcl.family == AF_INET && !(lcl.flags & PREFIXLEN_SPECIFIED)) { TTCN_warning("You should never see this!"); } else { //peer = lcl; addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &lcl.data, lcl.bytelen); } if (req.ifa.ifa_prefixlen == 0) req.ifa.ifa_prefixlen = lcl.bitlen; if(cmd != RTM_DELADDR) req.ifa.ifa_scope = default_scope(&lcl); // ll_init_map(&rth); if ((req.ifa.ifa_index = ll_name_to_index(d)) == 0) { TTCN_warning("RTNL: Cannot find device"); goto error; } if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) { TTCN_warning("RTNL: talk error!"); goto error; } free(ip); rtnl_close(&rth); return true; error: free(ip); return false; #else TTCN_warning("f_setIP_ip is only supported on Linux!"); return false; #endif } /////////////////////////////////////////////////////////////////////////////// // Function: f_delIP_ip // // Purpose: // Set IP address, subnet mask in a network inteface // Uses RTLN netlink interface on linux, which is faster than original POSIX. // // Parameters: // interface - *in* *charstring* - network interface // ipaddress - *in* *charstring* - starting IP address // prefix - *in* *integer* - subnetmask of the ipaddress // // Return Value: // True on success, false in other cases. // // Errors: // Many possibilities, all generates a TTCN_warning // // Detailed description: // - // /////////////////////////////////////////////////////////////////////////////// BOOLEAN f__delIP__ip(const CHARSTRING& interface, const CHARSTRING& ipaddress, const INTEGER& prefix = 32){ #ifdef LINUX return f__setIP__ip(interface, ipaddress, prefix, 0); #else TTCN_warning("f_deIP_ip is only supported on Linux!"); return false; #endif } /////////////////////////////////////////////////////////////////////////////// // Function: f_getIpAddresses // // Purpose: // Get both IPv4 and IPv6 addresses of the given host // // Parameters: // hostname - *charstring* - the hostname // // Return Value: // Initialized IPAddress structure // // Errors: // Many possibilities, all generates a TTCN_warning // // Detailed description: // - // /////////////////////////////////////////////////////////////////////////////// IPAddresses f__getIpAddresses(const CHARSTRING& hostname){ #if defined LINUX || defined SOLARIS || defined SOLARIS8 struct addrinfo hints, *res, *p; int status; char ipstr[INET6_ADDRSTRLEN]; IPAddresses iplist; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version CharstringList ipv4list(NULL_VALUE); CharstringList ipv6list(NULL_VALUE); if ((status = getaddrinfo((const char*)hostname, NULL, &hints, &res)) != 0) { TTCN_Logger::log(TTCN_DEBUG, "f_getIpAddresses: getaddrinfo: %s for \"%s\"\n", gai_strerror(status), (const char*)hostname); return IPAddresses(ipv4list, ipv6list); } for(p = res;p != NULL; p = p->ai_next) { if (p->ai_family == AF_INET) { // IPv4 struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; inet_ntop(p->ai_family, &(ipv4->sin_addr), ipstr, sizeof ipstr); ipv4list[ipv4list.size_of()] = ipstr; } else if (p->ai_family == AF_INET6){ //IPv6 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; inet_ntop(p->ai_family, &(ipv6->sin6_addr), ipstr, sizeof ipstr); ipv6list[ipv6list.size_of()] = ipstr; } } freeaddrinfo(res); // free the linked list return IPAddresses(ipv4list, ipv6list); #else CharstringList ipv4list(NULL_VALUE); CharstringList ipv6list(NULL_VALUE); struct hostent *host; struct in_addr address; host = gethostbyname(hostname); //getaddrinfo not supported if (host) while (*host->h_addr_list){ memcpy (&address, host->h_addr_list++, host->h_length); ipv4list[ipv4list.size_of()] = inet_ntoa(address); } return IPAddresses(ipv4list, ipv6list); #endif } }//namespace