How to Get Ip Address in Swift

Swift - Get device's WIFI IP Address

According to several SO threads (e.g. What exactly means iOS networking interface name? what's pdp_ip ? what's ap?), the WiFi interface on an iOS device always has then name "en0".

Your code (which seems to be what I answered at How to get Ip address in swift :) retrieves a list of the IP addresses of all running network interfaces. It can easily be modified to return only the IP address
of the "en0" interface, and actually that is what I originally had
answered at that thread (and this is just a Swift translation of the
answer to how to get ip address of iphone programmatically):

// Return IP address of WiFi interface (en0) as a String, or `nil`
func getWiFiAddress() -> String? {
var address : String?

// Get list of all interfaces on the local machine:
var ifaddr : UnsafeMutablePointer<ifaddrs> = nil
if getifaddrs(&ifaddr) == 0 {

// For each interface ...
var ptr = ifaddr
while ptr != nil {
defer { ptr = ptr.memory.ifa_next }

let interface = ptr.memory

// Check for IPv4 or IPv6 interface:
let addrFamily = interface.ifa_addr.memory.sa_family
if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {

// Check interface name:
if let name = String.fromCString(interface.ifa_name) where name == "en0" {

// Convert interface address to a human readable string:
var hostname = [CChar](count: Int(NI_MAXHOST), repeatedValue: 0)
getnameinfo(interface.ifa_addr, socklen_t(interface.ifa_addr.memory.sa_len),
&hostname, socklen_t(hostname.count),
nil, socklen_t(0), NI_NUMERICHOST)
address = String.fromCString(hostname)
}
}
}
freeifaddrs(ifaddr)
}

return address
}

Usage:

if let addr = getWiFiAddress() {
print(addr)
} else {
print("No WiFi address")
}

Update for Swift 3: In addition to adopting the code to the
many changes in Swift 3,
iterating over all interfaces can now use the new generalized
sequence() function:

Do NOT forget to add #include <ifaddrs.h> in your bridging header

// Return IP address of WiFi interface (en0) as a String, or `nil`
func getWiFiAddress() -> 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
}

For those of you who came looking for more than the WIFI IP you could modify this code a little

func getAddress(for network: Network) -> 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 == network.rawValue {

// 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
}
enum Network: String {
case wifi = "en0"
case cellular = "pdp_ip0"
//... case ipv4 = "ipv4"
//... case ipv6 = "ipv6"
}

Then we have access to the cellular IP as well.

guard let wifiIp = getAddress(for: .wifi) else { return }

&

guard let cellularIp = getAddress(for: .cellular) else { return }

Get IPAddress of iPhone or iPad device Using Swift 3

Add #include<ifaddrs.h> in your bridging header.

This is the framework needed to get IP address.

Also you can refer the following link:

Swift - Get device's IP Address

Get Network (Not device) IP address iOS swift

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

How to get Ip address in swift

As it turned out in the discussion, OP needs the interface address on a Mac and not on an iOS device as I thought initially. The code referenced in the question checks for the
interface name "en0", which is the WiFi interface on the iPhone. On a Mac it makes more
sense to check for any "up-and-running" interface instead.
Therefore I have rewritten the answer. It is now a Swift translation of the code in
Detect any connected network.


getifaddrs() is defined in <ifaddrs.h>, which is not included by default.
Therefore you have to create a bridging header and add

#include <ifaddrs.h>

The following function returns
an array with the names of all local "up-and-running" network interfaces.

func getIFAddresses() -> [String] {
var addresses = [String]()

// Get list of all interfaces on the local machine:
var ifaddr : UnsafeMutablePointer<ifaddrs> = nil
if getifaddrs(&ifaddr) == 0 {

// For each interface ...
var ptr = ifaddr
while ptr != nil {
defer { ptr = ptr.memory.ifa_next }

let flags = Int32(ptr.memory.ifa_flags)
let addr = ptr.memory.ifa_addr.memory

// Check for running IPv4, IPv6 interfaces. Skip the loopback interface.
if (flags & (IFF_UP|IFF_RUNNING|IFF_LOOPBACK)) == (IFF_UP|IFF_RUNNING) {
if addr.sa_family == UInt8(AF_INET) || addr.sa_family == UInt8(AF_INET6) {

// Convert interface address to a human readable string:
var hostname = [CChar](count: Int(NI_MAXHOST), repeatedValue: 0)
if (getnameinfo(ptr.memory.ifa_addr, socklen_t(addr.sa_len), &hostname, socklen_t(hostname.count),
nil, socklen_t(0), NI_NUMERICHOST) == 0) {
if let address = String.fromCString(hostname) {
addresses.append(address)
}
}
}
}
}
freeifaddrs(ifaddr)
}

return addresses
}

Update for Swift 3: In addition to adopting the code to the
many changes in Swift 3,
iterating over all interfaces can now use the new generalized
sequence() function:

func getIFAddresses() -> [String] {
var addresses = [String]()

// Get list of all interfaces on the local machine:
var ifaddr : UnsafeMutablePointer<ifaddrs>?
guard getifaddrs(&ifaddr) == 0 else { return [] }
guard let firstAddr = ifaddr else { return [] }

// For each interface ...
for ptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
let flags = Int32(ptr.pointee.ifa_flags)
let addr = ptr.pointee.ifa_addr.pointee

// Check for running IPv4, IPv6 interfaces. Skip the loopback interface.
if (flags & (IFF_UP|IFF_RUNNING|IFF_LOOPBACK)) == (IFF_UP|IFF_RUNNING) {
if addr.sa_family == UInt8(AF_INET) || addr.sa_family == UInt8(AF_INET6) {

// Convert interface address to a human readable string:
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
if (getnameinfo(ptr.pointee.ifa_addr, socklen_t(addr.sa_len), &hostname, socklen_t(hostname.count),
nil, socklen_t(0), NI_NUMERICHOST) == 0) {
let address = String(cString: hostname)
addresses.append(address)
}
}
}
}

freeifaddrs(ifaddr)
return addresses
}

How to build Http Request with IP address in Swift?(Moya)

var baseURL: URL = URL(string: "http://github.com/apple/swift")

try this ?

How to get client IP address in Vapor 3.0?

Thanks to the Vapor community, I have got an answer.

You can use req.http.remotePeer.hostname for Vapor 3.0 project.

Cocoa: How to get broadcast IP address in Swift?

let acceptedInterfaces = ["en0", "en2", "en3", "en4", "pdp_ip0", "pdp_ip1", "pdp_ip2", "pdp_ip3"]
func getBroadCastAddress() {
var interfaceAddresses : [String : String] = [:]
var ifaddr: UnsafeMutablePointer<ifaddrs>? = nil

if getifaddrs(&ifaddr) == 0 {
defer { freeifaddrs(ifaddr) }

var currentInterface = ifaddr
while currentInterface != nil {
defer { currentInterface = currentInterface!.pointee.ifa_next }

let interface = currentInterface!.pointee
let addrFamily = interface.ifa_addr.pointee.sa_family
guard addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) else { continue }

let interfaceName = String(cString: interface.ifa_name)
if acceptedInterfaces.contains(interfaceName) {
currentInterface!.withMemoryRebound(to: sockaddr_in.self, capacity: 1) {
sockaddr in

if let addressCString = inet_ntoa(sockaddr.pointee.sin_addr) {
interfaceAddresses[interfaceName] = String(cString: addressCString)
}
}
}
}
}

debugPrint(interfaceAddresses)
}

it prints:

["en0": "194.127.0.0"]


Related Topics



Leave a reply



Submit