1

I have made some code for getting the Wi-Fi current SSID and device current IP but i need to get the Network IP Address so if my device's IP is 192.168.4.3 i Know it is connected to 192.168.4.1 Network but I need not to make this assumption in the code ...

Get SSID:

private func fetchSSIDInfo() -> String? { var ssid: String? if let interfaces = CNCopySupportedInterfaces() as NSArray? { for interface in interfaces { if let interfaceInfo = CNCopyCurrentNetworkInfo(interface as! CFString) as NSDictionary? { ssid = interfaceInfo[kCNNetworkInfoKeySSID as String] as? String break } } } return ssid } 

Get Device's IP

static func getIPAddress()->String?{ var address : String? // Get list of all interfaces on the local machine: var ifaddr : UnsafeMutablePointer<ifaddrs>? guard getifaddrs(&ifaddr) == 0 else { return nil } guard let firstAddr = ifaddr else { return nil } // For each interface ... for ifptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) { let interface = ifptr.pointee // Check for IPv4 or IPv6 interface: let addrFamily = interface.ifa_addr.pointee.sa_family if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) { // Check interface name: let name = String(cString: interface.ifa_name) if name == "en0" { // Convert interface address to a human readable string: var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST)) getnameinfo(interface.ifa_addr, socklen_t(interface.ifa_addr.pointee.sa_len), &hostname, socklen_t(hostname.count), nil, socklen_t(0), NI_NUMERICHOST) address = String(cString: hostname) } } } freeifaddrs(ifaddr) return address } 

¿¿Network IP address??

** Edit ** if I call ifa_netmask it returns the netmask which it 255.255.255.0 for a 192.168.4.2/24 IP

4
  • maybe it can help you github.com/Feghal/FGRoute Commented Nov 6, 2018 at 15:53
  • You need to use the ifa_netmask in the ifaddrs struct Commented Nov 6, 2018 at 16:14
  • Thank you, i will check it out. I thought netmask was returning 255.255.255.0 ... Commented Nov 6, 2018 at 19:22
  • yes it is giving me the netmask which it 255.255.255.0 for a 192.168.4.2/24 Commented Nov 7, 2018 at 8:22

1 Answer 1

1

It seems that you are looking for your external IP, while your local IP is 192.168.4.1. Without the help of some external service, it is impossible ...

UPDATE see rfc1533 rfc2131 for details, try in Playground :-)

import Foundation func pack<T:FixedWidthInteger>(_ fi: T)->Data { var nfi = fi if 1 == 1.littleEndian { nfi = fi.bigEndian } return withUnsafeBytes(of: nfi) { un -> Data in var data = Data() un.forEach({ (byte) in data.append(byte) }) return data } } enum StringPack { case ipv4, ipv6, mac } func pack(_ txt: String, type: StringPack)->Data { var data = Data() switch type { case .ipv4: txt.split(separator: ".", omittingEmptySubsequences: false).forEach { s in data.append(UInt8(s) ?? 0) } while data.count < 4 { // padding with 0 data.append(0) } case .ipv6: txt.split(separator: ":", omittingEmptySubsequences: false).forEach { (s) in data.append(pack(UInt16(s, radix: 16) ?? 0)) } while data.count < 8 { // padding with 0 data.append(0) } case .mac: txt.split(separator: ":", omittingEmptySubsequences: false).forEach { s in s UInt8(s, radix:16) data.append(UInt8(s, radix:16) ?? 0) } while data.count < 16 { // padding with 0 data.append(0) } } return data } func dhcp_packet( // all parameters have default value (https://www.ietf.org/rfc/rfc2131.txt) for client using wifi interface op: UInt8 = 1, htype: UInt8 = 1, hlen: UInt8 = 6, hops: UInt8 = 0, xid: UInt32 = UInt32.random(in: UInt32.min...UInt32.max), secs: UInt16 = 0, flags: UInt16 = 0, ciaddr: String = "...", yiaddr: String = "...", siaddr: String = "...", giaddr: String = "...", chaddr: String = ":::::", sname: String = "", file: String = "" )->Data { // data represents dhcp_packet var data = Data() // sd tuple represents predefined fixed size data var sd:(Data, Int) data.append(op) data.append(htype) data.append(hlen) data.append(hops) data.append(pack(xid)) data.append(pack(secs)) data.append(pack(flags)) data.append(pack(ciaddr, type: .ipv4)) data.append(pack(yiaddr, type: .ipv4)) data.append(pack(siaddr, type: .ipv4)) data.append(pack(giaddr, type: .ipv4)) data.append(pack(chaddr, type: .mac)) sd = (Data(count: 64), min(sname.utf8.count, 64)) sd.0.replaceSubrange(0..<sd.1, with: Data(sname.utf8)[0..<sd.1]) data.append(sd.0) sd = (Data(count: 128), min(file.utf8.count, 128)) sd.0.replaceSubrange(0..<sd.1, with: Data(sname.utf8)[0..<sd.1]) data.append(sd.0) return data } import Darwin func getWiFiAddress() -> (ip4: String, mac: String, addr: sockaddr_in) { var address : String = "..." var mac: String = ":::::" var success: Bool var addr_in = sockaddr_in() var ifaddr : UnsafeMutablePointer<ifaddrs>? success = getifaddrs(&ifaddr) == 0 assert(success) assert(ifaddr != nil) let firstAddr = ifaddr! for ifptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) { let interface = ifptr.pointee let addrFamily = interface.ifa_addr.pointee.sa_family let name = String(cString: interface.ifa_name) if name == "en0" { if addrFamily == UInt8(AF_INET) { var addr = interface.ifa_addr.pointee var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST)) success = getnameinfo(&addr, socklen_t(interface.ifa_addr.pointee.sa_len), &hostname, socklen_t(hostname.count), nil, socklen_t(0), NI_NUMERICHOST) == 0 assert(success) addr_in = withUnsafePointer(to: &addr) { $0.withMemoryRebound(to: sockaddr_in.self, capacity: 1) { $0.pointee } } address = String(cString: hostname) } if addrFamily == UInt8(AF_LINK) { interface.ifa_addr.withMemoryRebound(to: sockaddr_dl.self, capacity: 1) { (sdl) -> Void in var hw = sdl.pointee.sdl_data withUnsafeBytes(of: &hw, { (p) -> Void in mac = p[Int(sdl.pointee.sdl_nlen)..<Int(sdl.pointee.sdl_alen + sdl.pointee.sdl_nlen)].map({ (u) -> String in var s = String(u, radix:16) if s.count < 2 { s.append("0") s = String(s.reversed()) } return s }).joined(separator: ":") }) } } } } freeifaddrs(ifaddr) return (address, mac, addr_in) } func sendBroadcast(data: Data, toPort: UInt16, waitForReplayOn: sockaddr_in)->Data { var wifiInterface: UInt32 var fd: Int32 var success: Bool var destAddr = sockaddr_in() var response = Data() wifiInterface = if_nametoindex("en0") assert(wifiInterface != 0) fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP) assert(fd >= 0) var kOne = 1 success = setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &kOne, socklen_t(MemoryLayout.size(ofValue: kOne))) == 0 assert(success) success = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &kOne, socklen_t(MemoryLayout.size(ofValue: kOne))) == 0 assert(success) success = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &kOne, socklen_t(MemoryLayout.size(ofValue: kOne))) == 0 assert(success) var wait = timeval(tv_sec: 0, tv_usec: 64000) success = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &wait, socklen_t(MemoryLayout.size(ofValue: wait))) == 0 assert(success) success = setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &wifiInterface, socklen_t(MemoryLayout.size(ofValue: wifiInterface))) == 0 assert(success) var addr_in = waitForReplayOn success = bindresvport(fd, &addr_in) == 0 assert(success) destAddr.sin_family = sa_family_t(AF_INET) destAddr.sin_len = __uint8_t(MemoryLayout.size(ofValue: destAddr)) destAddr.sin_addr.s_addr = INADDR_BROADCAST destAddr.sin_port = in_port_t(toPort.bigEndian) let bytesSent = data.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) -> Int in let destAddrSize = socklen_t(MemoryLayout.size(ofValue: destAddr)) return withUnsafePointer(to: &destAddr) { $0.withMemoryRebound(to: sockaddr.self, capacity: 1) { sendto(fd, bytes, data.count, 0, $0, destAddrSize) } } } if (bytesSent >= 0) { print("DHCP packet with \(bytesSent) bytes broadcasted to UDP port \(toPort)") var receiveBuffer = [UInt8](repeating: 0, count: 1024) let bytes = recv(fd, &receiveBuffer, receiveBuffer.count, 0) response.append(contentsOf: receiveBuffer[0..<bytes]) } else { print("error", errno) } success = close(fd) == 0 assert(success) return response } var en0info = getWiFiAddress() var packet = dhcp_packet(/*ciaddr: en0info.ip4,*/ chaddr: en0info.mac) let dhcp_MAGIC_COOKIE: [UInt8] = [0x63, 0x82, 0x53, 0x63] // DHCP_OPTIONS [code, length, value] let dhcp_DHCPINFORM : [UInt8] = [53, 1, 8] // we request router(s) address (it is standart report, but ... :-) // see https://www.ietf.org/rfc/rfc1533.txt let dhcp_PARAMETER_REQUEST_LIST: [UInt8] = [55, 1, 3] let dhcp_OPTIONS_END: UInt8 = 0xFF packet.append(contentsOf: dhcp_MAGIC_COOKIE) packet.append(contentsOf: dhcp_DHCPINFORM) packet.append(contentsOf: dhcp_PARAMETER_REQUEST_LIST) packet.append(dhcp_OPTIONS_END) en0info.addr.sin_len = __uint8_t(MemoryLayout.size(ofValue: sockaddr_in())) en0info.addr.sin_port = in_port_t(UInt16(68).bigEndian) en0info.addr.sin_addr.s_addr = INADDR_ANY var success = false var attempt = 5 var response = Data() repeat { response = sendBroadcast(data: packet, toPort: 67, waitForReplayOn: en0info.addr) // if succes is false, response is not for us, or invalid success = response[1..<240] == packet[1..<240] attempt -= 1 } while success == false && attempt > 0 if success == true { success = false var index = 240 let maxIndex = response.count var option = (code: UInt8, length: UInt8, value: [UInt8])(0,0,[]) var options = [UInt8: [UInt8]]() repeat { option.code = response[index] index += 1 if option.code == 0 { continue } if option.code == 255 { success = true break } option.length = response[index] index += 1 let nexti = index + Int(option.length) if nexti <= maxIndex { option.value = Array(response[index..<nexti]) options[option.code] = option.value } index = nexti } while index < maxIndex print(options, success ? "OK" : "incoplete") } else { print("DHCPINFORM failed") } 

On my environment it prints

DHCP packet with 244 bytes broadcasted to UDP port 67 [3: [192, 168, 8, 1], 6: [192, 168, 8, 1, 192, 168, 8, 1], 53: [5], 54: [192, 168, 8, 1], 1: [255, 255, 255, 0]] 

where:

option 3 represents a list of the routers

option 6 represents a list of DNS servers

option 53 means DHCP Message Type DHCPACK

option 54 means DHCP Server Identifier (where is this particular response from)

option 1 represents Subnet Mask

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for your reply but as I mentioned before I am not looking for local device IP. I have actually provide the code fo that in my question. Neither I am looking the external IP. I am trying to get the local Network IP so if a device has the IP 192.168.1.74/24 I need to get 192.168.1.1 (Network IP)
So what you would like to find is your gateway IP (LAN IP of your router)?
it is a little bit more complex, check en.wikipedia.org/wiki/… to have a basic idea. There is any public iOS framework to mimic "ipconfig getpacket en0". getpacket option outputs the DHCP/BOOTP packet that the client accepted from the DHCP/BOOTP server
@ReimondHill I tried to do this with Network.framework without succsess (broadcasting is unsupported :-().

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.