1 module myip.private_; 2 3 import std.string : fromStringz; 4 5 version(Windows) { 6 7 import core.sys.windows.windef; 8 import core.sys.windows.winsock2; 9 10 } else version(Posix) { 11 12 import core.sys.posix.netdb; 13 import core.sys.posix.netinet.in_; 14 import core.sys.posix.sys.socket; 15 16 } 17 18 enum Exclude { 19 20 IPV4 = 1<<0, 21 IPV6 = 1<<1, 22 INTERFACE = 1<<2, 23 24 } 25 26 /** 27 * Gets the private ip addresses of the machine. 28 */ 29 nothrow string[] privateAddresses(uint exclude=0) { 30 31 string[] addresses; 32 33 immutable ipv4 = !(exclude & Exclude.IPV4); 34 immutable ipv6 = !(exclude & Exclude.IPV6); 35 immutable interface_ = exclude & Exclude.INTERFACE; 36 37 nothrow string add(const(sockaddr)* sa, socklen_t salen) { 38 char[64] ip; 39 getnameinfo(sa, salen, ip.ptr, 64, null, 0, NI_NUMERICHOST); 40 return fromStringz(ip.ptr).idup; 41 } 42 43 nothrow void add4(const(sockaddr)* sa) { 44 if(ipv4) { 45 string address = add(sa, sockaddr_in.sizeof); 46 version(Posix) if(address == "127.0.0.1") return; 47 addresses ~= address; 48 } 49 } 50 51 nothrow void add6(const(sockaddr)* sa) { 52 if(ipv6) { 53 string address = add(sa, sockaddr_in6.sizeof); 54 if(interface_) { 55 // std.string.indexOf is not nothrow 56 foreach(i, c; address) { 57 if(c == '%') { 58 address = address[0..i]; 59 break; 60 } 61 } 62 } 63 version(Posix) if(address == "::1") return; 64 addresses ~= address; 65 } 66 } 67 68 version(Windows) { 69 70 WORD versionRequested = MAKEWORD(1, 0); 71 WSADATA wsaData; 72 char[255] name; 73 74 if(WSAStartup(versionRequested, &wsaData) == 0 && gethostname(name.ptr, 255) == 0) { 75 76 addrinfo* result, ptr; 77 78 addrinfo hints; 79 hints.ai_family = AF_UNSPEC; 80 hints.ai_socktype = SOCK_STREAM; 81 hints.ai_protocol = IPPROTO_TCP; 82 83 if(getaddrinfo(name.ptr, null, &hints, &result) == 0) { 84 85 for(ptr=result; ptr !is null; ptr=ptr.ai_next) { 86 switch(ptr.ai_family) { 87 case AF_INET: 88 add4(ptr.ai_addr); 89 break; 90 case AF_INET6: 91 add6(ptr.ai_addr); 92 break; 93 default: 94 break; 95 } 96 } 97 98 freeaddrinfo(result); 99 100 } 101 102 } 103 104 } else version(Posix) { 105 106 ifaddrs* ifap, ifa; 107 void* in_addr; 108 109 if(getifaddrs(&ifap) == 0) { 110 111 for(ifa=ifap; ifa; ifa=ifa.ifa_next) { 112 if(ifa.ifa_addr) { 113 switch(ifa.ifa_addr.sa_family) { 114 case AF_INET: 115 add4(ifa.ifa_addr); 116 break; 117 case AF_INET6: 118 add6(ifa.ifa_addr); 119 break; 120 default: 121 continue; 122 } 123 } 124 } 125 126 freeifaddrs(ifap); 127 128 } 129 130 } 131 132 return addresses; 133 134 } 135 136 nothrow string[] privateAddresses4() { 137 return privateAddresses(Exclude.IPV6); 138 } 139 140 nothrow string[] privateAddresses6(bool excludeInterface=false) { 141 if(excludeInterface) return privateAddresses(Exclude.IPV4 | Exclude.INTERFACE); 142 else return privateAddresses(Exclude.IPV4); 143 } 144 145 version(Posix) { 146 147 extern (C): 148 nothrow: 149 @nogc: 150 151 struct ifaddrs { 152 153 ifaddrs* ifa_next; 154 char* ifa_name; 155 uint ifa_flags; 156 sockaddr* ifa_addr; 157 sockaddr* ifa_netmask; 158 159 union { 160 161 sockaddr* ifu_broadaddr; 162 sockaddr* ifu_dstaddr; 163 164 } 165 166 void* ifa_data; 167 168 } 169 170 int getifaddrs(ifaddrs**); 171 void freeifaddrs(ifaddrs*); 172 173 int getnameinfo(const(sockaddr)*, socklen_t, char*, socklen_t, char*, socklen_t, int); 174 175 }