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 import tanya.sys.windows.ifdef; 26 import tanya.sys.windows.iphlpapi; 27 } 28 else version (Posix) 29 { 30 import core.sys.posix.net.if_; 31 } 32 33 /** 34 * Converts the name of a network interface to its index. 35 * 36 * If an interface with the name $(D_PARAM name) cannot be found or another 37 * error occurres, returns 0. 38 * 39 * Params: 40 * name = Interface name. 41 * 42 * Returns: Returns interface index or 0. 43 */ 44 uint nameToIndex(R)(R name) @trusted 45 if (isInputRange!R && is(Unqual!(ElementType!R) == char) && hasLength!R) 46 { 47 version (Windows) 48 { 49 if (name.length > IF_MAX_STRING_SIZE) 50 { 51 return 0; 52 } 53 char[IF_MAX_STRING_SIZE + 1] buffer; 54 NET_LUID luid; 55 56 copy(name, buffer[]); 57 buffer[name.length] = '\0'; 58 59 if (ConvertInterfaceNameToLuidA(buffer.ptr, &luid) != 0) 60 { 61 return 0; 62 } 63 NET_IFINDEX index; 64 if (ConvertInterfaceLuidToIndex(&luid, &index) == 0) 65 { 66 return index; 67 } 68 return 0; 69 } 70 else version (Posix) 71 { 72 if (name.length >= IF_NAMESIZE) 73 { 74 return 0; 75 } 76 char[IF_NAMESIZE] buffer; 77 78 copy(name, buffer[]); 79 buffer[name.length] = '\0'; 80 81 return if_nametoindex(buffer.ptr); 82 } 83 } 84 85 /// 86 @nogc nothrow @safe unittest 87 { 88 version (linux) 89 { 90 assert(nameToIndex("lo") == 1); 91 } 92 else version (Windows) 93 { 94 assert(nameToIndex("loopback_0") == 1); 95 } 96 else 97 { 98 assert(nameToIndex("lo0") == 1); 99 } 100 assert(nameToIndex("ecafretni") == 0); 101 } 102 103 /** 104 * Converts the index of a network interface to its name. 105 * 106 * If an interface with the $(D_PARAM index) cannot be found or another 107 * error occurres, returns an empty $(D_PSYMBOL String). 108 * 109 * Params: 110 * index = Interface index. 111 * 112 * Returns: Returns interface name or an empty $(D_PSYMBOL String). 113 */ 114 String indexToName(uint index) @nogc nothrow @trusted 115 { 116 import tanya.memory.op : findNullTerminated; 117 118 version (Windows) 119 { 120 NET_LUID luid; 121 if (ConvertInterfaceIndexToLuid(index, &luid) != 0) 122 { 123 return String(); 124 } 125 126 char[IF_MAX_STRING_SIZE + 1] buffer; 127 if (ConvertInterfaceLuidToNameA(&luid, 128 buffer.ptr, 129 IF_MAX_STRING_SIZE + 1) != 0) 130 { 131 return String(); 132 } 133 return String(findNullTerminated(buffer)); 134 } 135 else version (Posix) 136 { 137 char[IF_NAMESIZE] buffer; 138 if (if_indextoname(index, buffer.ptr) is null) 139 { 140 return String(); 141 } 142 return String(findNullTerminated(buffer)); 143 } 144 } 145 146 /** 147 * $(D_PSYMBOL AddressFamily) specifies a communication domain; this selects 148 * the protocol family which will be used for communication. 149 */ 150 enum AddressFamily : int 151 { 152 unspec = 0, /// Unspecified. 153 local = 1, /// Local to host (pipes and file-domain). 154 unix = local, /// POSIX name for PF_LOCAL. 155 inet = 2, /// IP protocol family. 156 ax25 = 3, /// Amateur Radio AX.25. 157 ipx = 4, /// Novell Internet Protocol. 158 appletalk = 5, /// Appletalk DDP. 159 netrom = 6, /// Amateur radio NetROM. 160 bridge = 7, /// Multiprotocol bridge. 161 atmpvc = 8, /// ATM PVCs. 162 x25 = 9, /// Reserved for X.25 project. 163 inet6 = 10, /// IP version 6. 164 }