1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 /** 6 * Network interfaces. 7 * 8 * Copyright: Eugene Wissner 2018-2020. 9 * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, 10 * Mozilla Public License, v. 2.0). 11 * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) 12 * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/net/iface.d, 13 * tanya/net/iface.d) 14 */ 15 module tanya.net.iface; 16 17 import tanya.algorithm.mutation; 18 import tanya.container.string; 19 import tanya.meta.trait; 20 import tanya.meta.transform; 21 import tanya.range; 22 23 version (Windows) 24 { 25 private union NET_LUID_LH { ulong Value, Info; } 26 private alias NET_LUID = NET_LUID_LH; 27 private alias NET_IFINDEX = uint; 28 private enum IF_MAX_STRING_SIZE = 256; 29 extern(Windows) @nogc nothrow private @system 30 { 31 uint ConvertInterfaceNameToLuidA(const(char)* InterfaceName, 32 NET_LUID* InterfaceLuid); 33 uint ConvertInterfaceLuidToIndex(const(NET_LUID)* InterfaceLuid, 34 NET_IFINDEX* InterfaceIndex); 35 uint ConvertInterfaceIndexToLuid(NET_IFINDEX InterfaceIndex, 36 NET_LUID* InterfaceLuid); 37 uint ConvertInterfaceLuidToNameA(const(NET_LUID)* InterfaceLuid, 38 char* InterfaceName, 39 size_t Length); 40 } 41 } 42 else version (Posix) 43 { 44 import core.sys.posix.net.if_; 45 } 46 47 /** 48 * Converts the name of a network interface to its index. 49 * 50 * If an interface with the name $(D_PARAM name) cannot be found or another 51 * error occurres, returns 0. 52 * 53 * Params: 54 * name = Interface name. 55 * 56 * Returns: Returns interface index or 0. 57 */ 58 uint nameToIndex(R)(R name) @trusted 59 if (isInputRange!R && is(Unqual!(ElementType!R) == char) && hasLength!R) 60 { 61 version (Windows) 62 { 63 if (name.length > IF_MAX_STRING_SIZE) 64 { 65 return 0; 66 } 67 char[IF_MAX_STRING_SIZE + 1] buffer; 68 NET_LUID luid; 69 70 copy(name, buffer[]); 71 buffer[name.length] = '\0'; 72 73 if (ConvertInterfaceNameToLuidA(buffer.ptr, &luid) != 0) 74 { 75 return 0; 76 } 77 NET_IFINDEX index; 78 if (ConvertInterfaceLuidToIndex(&luid, &index) == 0) 79 { 80 return index; 81 } 82 return 0; 83 } 84 else version (Posix) 85 { 86 if (name.length >= IF_NAMESIZE) 87 { 88 return 0; 89 } 90 char[IF_NAMESIZE] buffer; 91 92 copy(name, buffer[]); 93 buffer[name.length] = '\0'; 94 95 return if_nametoindex(buffer.ptr); 96 } 97 } 98 99 /// 100 @nogc nothrow @safe unittest 101 { 102 version (linux) 103 { 104 assert(nameToIndex("lo") == 1); 105 } 106 else version (Windows) 107 { 108 assert(nameToIndex("loopback_0") == 1); 109 } 110 else 111 { 112 assert(nameToIndex("lo0") == 1); 113 } 114 assert(nameToIndex("ecafretni") == 0); 115 } 116 117 /** 118 * Converts the index of a network interface to its name. 119 * 120 * If an interface with the $(D_PARAM index) cannot be found or another 121 * error occurres, returns an empty $(D_PSYMBOL String). 122 * 123 * Params: 124 * index = Interface index. 125 * 126 * Returns: Returns interface name or an empty $(D_PSYMBOL String). 127 */ 128 String indexToName(uint index) @nogc nothrow @trusted 129 { 130 import tanya.memory.op : findNullTerminated; 131 132 version (Windows) 133 { 134 NET_LUID luid; 135 if (ConvertInterfaceIndexToLuid(index, &luid) != 0) 136 { 137 return String(); 138 } 139 140 char[IF_MAX_STRING_SIZE + 1] buffer; 141 if (ConvertInterfaceLuidToNameA(&luid, 142 buffer.ptr, 143 IF_MAX_STRING_SIZE + 1) != 0) 144 { 145 return String(); 146 } 147 return String(findNullTerminated(buffer)); 148 } 149 else version (Posix) 150 { 151 char[IF_NAMESIZE] buffer; 152 if (if_indextoname(index, buffer.ptr) is null) 153 { 154 return String(); 155 } 156 return String(findNullTerminated(buffer)); 157 } 158 } 159 160 /** 161 * $(D_PSYMBOL AddressFamily) specifies a communication domain; this selects 162 * the protocol family which will be used for communication. 163 */ 164 enum AddressFamily : int 165 { 166 unspec = 0, /// Unspecified. 167 local = 1, /// Local to host (pipes and file-domain). 168 unix = local, /// POSIX name for PF_LOCAL. 169 inet = 2, /// IP protocol family. 170 ax25 = 3, /// Amateur Radio AX.25. 171 ipx = 4, /// Novell Internet Protocol. 172 appletalk = 5, /// Appletalk DDP. 173 netrom = 6, /// Amateur radio NetROM. 174 bridge = 7, /// Multiprotocol bridge. 175 atmpvc = 8, /// ATM PVCs. 176 x25 = 9, /// Reserved for X.25 project. 177 inet6 = 10, /// IP version 6. 178 }