(Disclaimer: These are only notes from research, not implementation.)
Problem:
You and your friends all have iPads and are all in a room, i.e. physically close to each other. You all would like to share some data among yourselves, but not through the cloud where each of you individually uploads then downloads data from.
Solution:
1. The iOS devices need to discover each other, i.e. each iPad in the room needs to know the presence/"name" of all the other iPads in the room.
For this device discovery, you will need to use Bonjour, and Bonjour's link 2.
2. Once the devices know the identity of each other, they will need to communicate through a network, which is a medium for their data transfer. This network can either be Bluetooth or WiFi. Bluetooth is more commonly used, and you can even use it for communications between iOS and Android devices.
But perhaps you want to use both Bluetooth and WiFi. Luckily, GameKit abstracts local network connections. GameKit's GKSession discovers and connects nearby iOS devices using either Bluetooth or WiFi, whichever one works.
Update: I'm told that GKSession also discovers devices.
Links:
Bonjour link 1
Bonjour link 2
GameKit GKSession link
Bonjour useful info, perhaps
GameKit GKSession useful info, perhaps
Sample application for GameKit GKSession
Showing posts with label network. Show all posts
Showing posts with label network. Show all posts
Thursday, January 17, 2013
Sunday, May 1, 2011
PF_PACKET Protocol Family
source
When you open a socket with the standard call sock = socket(domain, type, protocol) you have to specify which domain (or protocol family) you are going to use with that socket. Commonly used families are PF_UNIX, for communications bounded on the local machine, and PF_INET, for communications based on IPv4 protocols. Furthermore, you have to specify a type for your socket and possible values depend on the family you specified. Common values for type, when dealing with the PF_INET family, include SOCK_STREAM (typically associated with TCP) and SOCK_DGRAM (associated with UDP). Socket types influence how packets are handled by the kernel before being passed up to the application. Finally, you specify the protocol that will handle the packets flowing through the socket (more details on this can be found on the socket(3) man page).
In recent versions [original article was written in 2001] of the Linux kernel (post-2.0 releases) a new protocol family has been introduced, named PF_PACKET. This family allows an application to send and receive packets dealing directly with the network card driver, thus avoiding the usual protocol stack-handling (e.g., IP/TCP or IP/UDP processing). That is, any packet sent through the socket will be directly passed to the Ethernet interface, and any packet received through the interface will be directly passed to the application.
The PF_PACKET family supports two slightly different socket types, SOCK_DGRAM and SOCK_RAW. The former leaves to the kernel the burden of adding and removing Ethernet level headers. The latter gives the application complete control over the Ethernet header. The protocol field in the socket() call must match one of the Ethernet IDs defined in /usr/include/linux/if_ether.h [IEEE 802.3 Ethernet magic constants], which represents the registered protocols that can be shipped in an Ethernet frame. Unless dealing with very specific protocols, you typically use ETH_P_IP, which encompasses all of the IP-suite protocols (e.g., TCP, UDP, ICMP, raw IP and so on).
Since they have pretty serious security implications (for example, you may forge a frame with a spoofed MAC address), PF_PACKET-family sockets may only be used by root.
When you open a socket with the standard call sock = socket(domain, type, protocol) you have to specify which domain (or protocol family) you are going to use with that socket. Commonly used families are PF_UNIX, for communications bounded on the local machine, and PF_INET, for communications based on IPv4 protocols. Furthermore, you have to specify a type for your socket and possible values depend on the family you specified. Common values for type, when dealing with the PF_INET family, include SOCK_STREAM (typically associated with TCP) and SOCK_DGRAM (associated with UDP). Socket types influence how packets are handled by the kernel before being passed up to the application. Finally, you specify the protocol that will handle the packets flowing through the socket (more details on this can be found on the socket(3) man page).
In recent versions [original article was written in 2001] of the Linux kernel (post-2.0 releases) a new protocol family has been introduced, named PF_PACKET. This family allows an application to send and receive packets dealing directly with the network card driver, thus avoiding the usual protocol stack-handling (e.g., IP/TCP or IP/UDP processing). That is, any packet sent through the socket will be directly passed to the Ethernet interface, and any packet received through the interface will be directly passed to the application.
The PF_PACKET family supports two slightly different socket types, SOCK_DGRAM and SOCK_RAW. The former leaves to the kernel the burden of adding and removing Ethernet level headers. The latter gives the application complete control over the Ethernet header. The protocol field in the socket() call must match one of the Ethernet IDs defined in /usr/include/linux/if_ether.h [IEEE 802.3 Ethernet magic constants], which represents the registered protocols that can be shipped in an Ethernet frame. Unless dealing with very specific protocols, you typically use ETH_P_IP, which encompasses all of the IP-suite protocols (e.g., TCP, UDP, ICMP, raw IP and so on).
Since they have pretty serious security implications (for example, you may forge a frame with a spoofed MAC address), PF_PACKET-family sockets may only be used by root.
Ruby Raw Socket for Windows
About Raw Sockets in general:
- Wikipedia article: A raw socket is a socket that allows direct sending and receiving of network packets by applications, bypassing all encapsulation in the networking software of the operating system.
Linux specific:
- terminal type:
- might be useful #1
- might be useful #2
Windows specific:
- libpcap-1.1.1./pcap-win32.c has the wsockinit() function, not very useful though
- Windows uses Winsock(Wiki article)
- Very good Windows raw socket explaination also with code: Raw Sockets and Windows
First of all, it must be understood very clearly that raw sockets is not a feature of the network API (although it must be present there as an option) but of the OS protocol stack. To implement raw sockets, all we have to do is to inform the OS that the packet buffer we are providing will have the header and so the OS should transmit it as is without "adding any header"; that's all, nothing more to do. The Unix operating system has raw socket support since ancient times. But the problem is with Windows. None of Windows 95, 98, 98SE supported raw sockets. Raw sockets became available on Windows from Windows 2000; Windows XP continued this. But suddenly, raw socket support was removed from Windows XP through a patch in SP2. Vista probably doesn't have it. Windows 95, 98, 98SE do not support raw sockets, but this doesn't end the story. If you want the facility, then the solution is to use a third party packet driver like Winpcap. Such packet drivers will do your task irrespective of what the OS likes and dislikes. Windows XP and XP SP1 have full raw socket support and so life is easy. So if you want to do raw socketing on Windows, then either use Winpcap or don't feel desperate to install SP2, or otherwise use Windows 2003 which, as per my knowledge, has raw socket support. So let's brief up.
-----
Windows 95, 98, 98SE, NT4.0 -- Only raw ICMP and IGMP with restricted features.
Windows 2000, XP, XP SP1, 2003 -- Full raw socket support for both receiving and sending purposes.
Windows XP SP2 -- Only raw ICMP, IGMP, and UDP with proper source address (IP spoofing restricted) can be sent. But, full raw sockets can be received, which means you can sniff all incoming data and read their headers.
Note : Winsock Ver. >=2.0
----
So if your system doesn't support raw sockets, then switch to Linux or use Winpcap.
- Very useful Winsock FAQ
--- question: Do I must have a TCP/IP?
) What do I need to run WinSock applications?
----------------------------------------------
Interesting how after "rake install" in Windows, the Gemfile.lock shows "x86-mingw32" as well as "ruby" under "PLATFORMS"
----------
Using WinSock applications to access the Internet requires:
- A suitable connection to the Internet.
- A TCP/IP stack (which includes it's own WINSOCK.DLL).
=====================
Trying to see if existing Linux socket would work on Windows:
commit 9a5b019bea6f62f22cf90e2c6eaf0c0637387e7f
take out unnecessary raise exception. Hopefully windows socket can work?
Currently, I have all the errors because of the highlighted line above. Looking at that:
1. so ether_type, if it's false or nil, is going to be replaced by "3", how can that be compatible with the 4-digit ether_type?
2. is 3 the Gateway-to-Gateway protocol?
answer: The number comes from cat /usr/include/linux/if_ether.h | grep ETH_P_ALL, which along with PF_Packet, make up a socket.
Also for this:
Sweet! Found the Windows equivalent of socket.h -- winsock.h!! I hope it's up to date. So it says that AF_LINK is 18. :D
Victor says: "I googled around, and it seems that AF_LINK won't work on Windows. The header you have is for Winsock 1.1, and all modern systems use Winsock 2.0. MSDN says that Windows removed raw socket support as of Windows XP SP2." This was done for security reasons.
Window's (Winsock/WSA/Windows Socket API) Raw Socket. Raw Socket is a kind of Windows socket (also containing some common choices for domain, type, and protocol), following the format of Berkeley's raw socket.
domain: AF_LINK, same as /darwin/
type: SOCK_RAW, same :D
protocol: hope that 3, eth_p_all would work
:P
commit b458ffaebeabc408c9649c37b9e1951316852ab5
try still. Fixed some Windows socket stuff, found AF_LINK in winsock.h
./Win32/Src/getaddrinfo.c: { PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
I need raw socket for an application that i am trying to execute from cygwin in 'Windows XP with SP2' & Vista . How can this be achieved ?
Use a driver that doesn't use the Windows TCP/IP stack, maybe try WinPcap.
====
- Download WinPcap source
-> install NDIS driver
Nice Site
- Wikipedia article: A raw socket is a socket that allows direct sending and receiving of network packets by applications, bypassing all encapsulation in the networking software of the operating system.
Linux specific:
- terminal type:
man 7 raw
to read about raw sockets- might be useful #1
- might be useful #2
Windows specific:
- libpcap-1.1.1./pcap-win32.c has the wsockinit() function, not very useful though
- Windows uses Winsock(Wiki article)
- Very good Windows raw socket explaination also with code: Raw Sockets and Windows
First of all, it must be understood very clearly that raw sockets is not a feature of the network API (although it must be present there as an option) but of the OS protocol stack. To implement raw sockets, all we have to do is to inform the OS that the packet buffer we are providing will have the header and so the OS should transmit it as is without "adding any header"; that's all, nothing more to do. The Unix operating system has raw socket support since ancient times. But the problem is with Windows. None of Windows 95, 98, 98SE supported raw sockets. Raw sockets became available on Windows from Windows 2000; Windows XP continued this. But suddenly, raw socket support was removed from Windows XP through a patch in SP2. Vista probably doesn't have it. Windows 95, 98, 98SE do not support raw sockets, but this doesn't end the story. If you want the facility, then the solution is to use a third party packet driver like Winpcap. Such packet drivers will do your task irrespective of what the OS likes and dislikes. Windows XP and XP SP1 have full raw socket support and so life is easy. So if you want to do raw socketing on Windows, then either use Winpcap or don't feel desperate to install SP2, or otherwise use Windows 2003 which, as per my knowledge, has raw socket support. So let's brief up.
-----
Windows 95, 98, 98SE, NT4.0 -- Only raw ICMP and IGMP with restricted features.
Windows 2000, XP, XP SP1, 2003 -- Full raw socket support for both receiving and sending purposes.
Windows XP SP2 -- Only raw ICMP, IGMP, and UDP with proper source address (IP spoofing restricted) can be sent. But, full raw sockets can be received, which means you can sniff all incoming data and read their headers.
Note : Winsock Ver. >=2.0
----
So if your system doesn't support raw sockets, then switch to Linux or use Winpcap.
- Very useful Winsock FAQ
--- question: Do I must have a TCP/IP?
) What do I need to run WinSock applications?
----------------------------------------------
Interesting how after "rake install" in Windows, the Gemfile.lock shows "x86-mingw32" as well as "ruby" under "PLATFORMS"
----------
Using WinSock applications to access the Internet requires:
- A suitable connection to the Internet.
- A TCP/IP stack (which includes it's own WINSOCK.DLL).
=====================
Trying to see if existing Linux socket would work on Windows:
commit 9a5b019bea6f62f22cf90e2c6eaf0c0637387e7f
take out unnecessary raise exception. Hopefully windows socket can work?
Administrator@HAOQI-4F34C3203 ~/Desktop/ethernet/spec/ethernet (master) $ rspec raw_socket_spec.rb FFFFFF Failures: 1) RawSocket mac should have 6 bytes Failure/Error: let(:mac) { Ethernet::RawSocket.mac eth_device } RuntimeError: Unsupported platform i386-mingw32 # c:/Documents and Settings/Administrator/Desktop/ethernet/lib/ethernet/raw _socket.rb:121:in `all_ethernet_protocols' # c:/Documents and Settings/Administrator/Desktop/ethernet/lib/ethernet/raw _socket.rb:24:in `socket' # c:/Documents and Settings/Administrator/Desktop/ethernet/lib/ethernet/raw _socket.rb:49:in `mac' # ./raw_socket_spec.rb:8:in `block (2 levels) in' # ./raw_socket_spec.rb:17:in `block (3 levels) in ' 2) RawSocket mac should match ifconfig output same as above 3) RawSocket socket should be able to receive data Failure/Error: before { @socket = Ethernet::RawSocket.socket eth_device } RuntimeError: Unsupported platform i386-mingw32 # c:/Documents and Settings/Administrator/Desktop/ethernet/lib/ethernet/raw _socket.rb:121:in `all_ethernet_protocols' # c:/Documents and Settings/Administrator/Desktop/ethernet/lib/ethernet/raw _socket.rb:24:in `socket' # ./raw_socket_spec.rb:28:in `block (3 levels) in ' 4) RawSocket socket should output a packet same as above 5) RawSocket socket should receive some network noise same as above 6) RawSocket testing listing all network devices should list the devices Failure/Error: device_macaddrs.each do |key, value| NoMethodError: undefined method `each' for nil:NilClass # ./raw_socket_spec.rb:48:in `block (3 levels) in ' Finished in 0 seconds 6 examples, 6 failures
Currently, I have all the errors because of the highlighted line above. Looking at that:
23 def self.socket(eth_device = nil, ether_type = nil) 24 ether_type ||= all_ethernet_protocols 25 socket = Socket.new raw_address_family, Socket::SOCK_RAW, htons(ether_type) ... 115 # The protocol number for listening to all ethernet protocols. 116 def all_ethernet_protocols 117 case RUBY_PLATFORM 118 when /linux/ 119 3 120 else 121 raise "Unsupported platform #{RUBY_PLATFORM}" 122 end 123 end
What "||=" means in "ether_type ||= all_ethernet_protocols"
Victor's answer:
It's a trick in modern languages. || is boolean OR, and the way it's implemented is a || b returns a if it is a true value, otherwise it returns b. You can think of it for a bit and convince yourself that this fulfills the contract for OR. ||= is used to specify default values -- if ether_type was nil or false, it becomes all_ethernet_protocols. Otherwise it doesn't change.
It's a trick in modern languages. || is boolean OR, and the way it's implemented is a || b returns a if it is a true value, otherwise it returns b. You can think of it for a bit and convince yourself that this fulfills the contract for OR. ||= is used to specify default values -- if ether_type was nil or false, it becomes all_ethernet_protocols. Otherwise it doesn't change.
1. so ether_type, if it's false or nil, is going to be replaced by "3", how can that be compatible with the 4-digit ether_type?
2. is 3 the Gateway-to-Gateway protocol?
answer: The number comes from cat /usr/include/linux/if_ether.h | grep ETH_P_ALL, which along with PF_Packet, make up a socket.
Also for this:
140 # The AF / PF number for raw sockets. 141 def raw_address_family 142 case RUBY_PLATFORM 143 when /linux/ 144 17 # cat /usr/include/bits/socket.h | grep PF_PACKET 145 when /darwin/ 146 18 # cat /usr/include/sys/socket.h | grep AF_LINK
147 when /i386-mingw32/ 148 18 # winsock.h | grep AF_LINK 149 else 150 raise "Unsupported platform #{RUBY_PLATFORM}" 151 end 152 end
Victor says: "I googled around, and it seems that AF_LINK won't work on Windows. The header you have is for Winsock 1.1, and all modern systems use Winsock 2.0. MSDN says that Windows removed raw socket support as of Windows XP SP2." This was done for security reasons.
Window's (Winsock/WSA/Windows Socket API) Raw Socket. Raw Socket is a kind of Windows socket (also containing some common choices for domain, type, and protocol), following the format of Berkeley's raw socket.
domain: AF_LINK, same as /darwin/
type: SOCK_RAW, same :D
protocol: hope that 3, eth_p_all would work
:P
commit b458ffaebeabc408c9649c37b9e1951316852ab5
try still. Fixed some Windows socket stuff, found AF_LINK in winsock.h
Administrator@HAOQI-4F34C3203 ~/Desktop/ethernet/spec/ethernet (master) $ rspec raw_socket_spec.rb FFFFFF Failures: 1) RawSocket mac should have 6 bytes Failure/Error: let(:mac) { Ethernet::RawSocket.mac eth_device } Errno::EAFNOSUPPORT: An address incompatible with the requested protocol was used. - socket(2) # c:/Documents and Settings/Administrator/Desktop/ethernet/lib/ethernet/raw _socket.rb:25:in `initialize' # c:/Documents and Settings/Administrator/Desktop/ethernet/lib/ethernet/raw _socket.rb:25:in `new' # c:/Documents and Settings/Administrator/Desktop/ethernet/lib/ethernet/raw _socket.rb:25:in `socket' # c:/Documents and Settings/Administrator/Desktop/ethernet/lib/ethernet/raw _socket.rb:49:in `mac' # ./raw_socket_spec.rb:8:in `block (2 levels) in' # ./raw_socket_spec.rb:17:in `block (3 levels) in ' ... same stuff Finished in 0.01562 seconds 6 examples, 6 failures
Failure/Error: let(:mac) { Ethernet::RawSocket.mac eth_device }
NameError:
uninitialized constant Module::ANY
# c:/Documents and Settings/Administrator/Desktop/ethernet/lib/ethernet/raw
_socket.rb:133:in `all_ethernet_protocols'
./Win32/Src/getaddrinfo.c: { PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
Try instead of htons(ETH_P_ALL) , which we have here as 3, do htons(ANY)
commit 6be0d35378b021a8981dfbec4b920317123bc64d
try. switch htons(3) to htons(ANY)
question for Victor:
Do you have any hints of looking for the Windows equivalent of if_ether.h or know what I should put in for ether_type?
Continued from Victor's quote above ... "All solutions seem to revolve around installing some NDIS driver and talking to it. Winpcap seems to be the easiest and most well-maintained library for that."
Do you have any hints of looking for the Windows equivalent of if_ether.h or know what I should put in for ether_type?
Continued from Victor's quote above ... "All solutions seem to revolve around installing some NDIS driver and talking to it. Winpcap seems to be the easiest and most well-maintained library for that."
I need raw socket for an application that i am trying to execute from cygwin in 'Windows XP with SP2' & Vista . How can this be achieved ?
Use a driver that doesn't use the Windows TCP/IP stack, maybe try WinPcap.
====
- Download WinPcap source
-> install NDIS driver
Nice Site
Wednesday, April 20, 2011
system-getifaddrs
The creator of system-getifaddrs, Bruno Coimbra, is so awesome! He helped me fix the problems I had here.
Setting up system-getifaddrs:
Inside the system-getifaddrs directory, I did:
Then I did:
$ irb
irb(main):001:0> require 'rubygems'
=> true
irb(main):002:0> require 'system/getifaddrs'
=> true
irb(main):003:0> p System.get_ifaddrs
Bruno: are you connected on wireless?
me: I'm on wireless
Bruno: you are using
eth0 should be down
Making test.rb work. Add the first line, so it's like:
1 require "rubygems"
2 require "pp"
3 require "system/getifaddrs"
4 pp System.get_ifaddrs
Where pp is for "pretty print".
$ ruby test.rb
Without the first line, the result would be as below. I need the "rubygems" because I am running system-wide ruby instead of rvm, changed to it here. (which ruby, gives "/usr/bin/ruby")
Where is the *.gem file?
me: is system-getifaddrs a ruby gem?
Bruno: yep
me: how come it doesn't have a *.gem file anywhere?
Bruno: ah, on github have only source files
me: so the *.gem file is not necessary for it to run?
Bruno: *.gem file is the package file like deb packages for debian
after installing, files are unpacked under ruby lib dir and gem file is discarted
me: so, on github you put the state after unpackaging, that's why .gem doesn't need to be there
Bruno: nope, on github is development sources. with that sources you can packaging its into a gem file
Setting up system-getifaddrs:
Inside the system-getifaddrs directory, I did:
$ sudo gem install system-getifaddrs
[sudo] password for haoqili:
Fetching: system-getifaddrs-0.1.1.gem (100%)
Building native extensions. This could take a while...
Successfully installed system-getifaddrs-0.1.1
1 gem installed
Installing ri documentation for system-getifaddrs-0.1.1...
Installing RDoc documentation for system-getifaddrs-0.1.1...
Fetching: system-getifaddrs-0.1.1.gem (100%)
Building native extensions. This could take a while...
Successfully installed system-getifaddrs-0.1.1
1 gem installed
Installing ri documentation for system-getifaddrs-0.1.1...
Installing RDoc documentation for system-getifaddrs-0.1.1...
Then I did:
$ irb
irb(main):001:0> require 'rubygems'
=> true
irb(main):002:0> require 'system/getifaddrs'
=> true
irb(main):003:0> p System.get_ifaddrs
{:wlan0=>{:inet_addr=>"18.111.61.140", :netmask=>"18.111.61.140"}, :vmnet1=>{:inet_addr=>"172.16.76.1", :netmask=>"172.16.76.1"}, :vmnet8=>{:inet_addr=>"172.16.197.1", :netmask=>"172.16.197.1"}, :lo=>{:inet_addr=>"127.0.0.1", :netmask=>"127.0.0.1"}}
=> nil
me: how come eth0 is not in the list?=> nil
Bruno: are you connected on wireless?
me: I'm on wireless
Bruno: you are using
eth0 should be down
Making test.rb work. Add the first line, so it's like:
1 require "rubygems"
2 require "pp"
3 require "system/getifaddrs"
4 pp System.get_ifaddrs
Where pp is for "pretty print".
$ ruby test.rb
{:wlan0=>{:inet_addr=>"18.111.61.140", :netmask=>"18.111.61.140"},
:vmnet1=>{:inet_addr=>"172.16.76.1", :netmask=>"172.16.76.1"},
:vmnet8=>{:inet_addr=>"172.16.197.1", :netmask=>"172.16.197.1"},
:lo=>{:inet_addr=>"127.0.0.1", :netmask=>"127.0.0.1"}}
:vmnet1=>{:inet_addr=>"172.16.76.1", :netmask=>"172.16.76.1"},
:vmnet8=>{:inet_addr=>"172.16.197.1", :netmask=>"172.16.197.1"},
:lo=>{:inet_addr=>"127.0.0.1", :netmask=>"127.0.0.1"}}
Without the first line, the result would be as below. I need the "rubygems" because I am running system-wide ruby instead of rvm, changed to it here. (which ruby, gives "/usr/bin/ruby")
test.rb:2:in `require': no such file to load -- system/getifaddrs (LoadError)
from test.rb:2
from test.rb:2
Where is the *.gem file?
me: is system-getifaddrs a ruby gem?
Bruno: yep
me: how come it doesn't have a *.gem file anywhere?
Bruno: ah, on github have only source files
me: so the *.gem file is not necessary for it to run?
Bruno: *.gem file is the package file like deb packages for debian
after installing, files are unpacked under ruby lib dir and gem file is discarted
me: so, on github you put the state after unpackaging, that's why .gem doesn't need to be there
Bruno: nope, on github is development sources. with that sources you can packaging its into a gem file
Tuesday, April 12, 2011
Listing All Network Devices on Linux: finding how
A continuation of my previous post. (thanks for the help from hly).
int main(int argc, char **argv)
char **argv is the same as char * argv[]
To find how to list all network devices, use the ifconfig source code, starting with the "ifconfig.c" file.
Goal: find the code that generates the "Iface" devices (left-most column of below).
Inside "ifconfig.c", I searched for "-s" and got
So then I searched for "ife_short", and found it inside "if_print()", which:
1. prints out the top row of text.
-. Since we don't have an ifname specified (like "eth0" or "vmnet8"), we can't just simply lookup_interface(ifname) to get the ife and use
-. do_if_fetch(ife) to check that the ife interface/device is still good (it uses if_fetch())
-. if so, print that ife with ife_print_short(), the column we want is printf("%-5.5s ", ptr->name);
2. We'll instead do "for_all_interfaces()", which gets all the interfaces (see lib/interface.c)
Stuck. Victor told me to look at if_readlist(). "It seems that this function is iterating over the return array and feeding each item to a callback."
to-do ask:
1. Is my above resoning correct?
2. If so, how does for_all_interfaces() work? lib/interface.c Look at if_readlist()
3. How do I make this so I can test it? (I don't want it to screw up my ifconfig, test it in the directory (+m ifconfig.c and then ./ doesn't work))
4. is getting interface from IP addresses helpful at all? with the getifaddrs(): from stack overflow question and from IBM.
int main(int argc, char **argv)
char **argv is the same as char * argv[]
To find how to list all network devices, use the ifconfig source code, starting with the "ifconfig.c" file.
Goal: find the code that generates the "Iface" devices (left-most column of below).
$ ifconfig -s Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg eth0 1500 0 0 0 0 0 0 0 0 0 BMU lo 16436 0 9359 0 0 0 9359 0 0 0 LRU vmnet1 1500 0 0 0 0 0 1122 0 0 0 BMRU vmnet8 1500 0 0 0 0 0 1122 0 0 0 BMRU wlan0 1500 0 275975 0 0 0 223090 0 0 0 BMRU
Inside "ifconfig.c", I searched for "-s" and got
263 else if (!strcmp(*argv, "-s")) 264 ife_short = 1;
So then I searched for "ife_short", and found it inside "if_print()", which:
1. prints out the top row of text.
-. Since we don't have an ifname specified (like "eth0" or "vmnet8"), we can't just simply lookup_interface(ifname) to get the ife and use
-. do_if_fetch(ife) to check that the ife interface/device is still good (it uses if_fetch())
-. if so, print that ife with ife_print_short(), the column we want is printf("%-5.5s ", ptr->name);
103 static int if_print(char *ifname)
104 {
105 int res;
106
107 if (ife_short)
108 printf(_("Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX -OVR Flg\n"));
109
110 if (!ifname) {
111 res = for_all_interfaces(do_if_print, &opt_a);
112 } else {
113 struct interface *ife;
114
115 ife = lookup_interface(ifname); //ife means "interface"
116 res = do_if_fetch(ife);
117 if (res >= 0)
118 ife_print(ife);
119 }
120 return res;
121 }
2. We'll instead do "for_all_interfaces()", which gets all the interfaces (see lib/interface.c)
128 int for_all_interfaces(int (*doit) (struct interface *, void *), void *cookie)
129 {
130 struct interface *ife;
131
132 if (!int_list && (if_readlist() < 0))
133 return -1;
134 for (ife = int_list; ife; ife = ife->next) {
135 int err = doit(ife, cookie);
136 if (err)
137 return err;
138 }
139 return 0;
140 }
Stuck. Victor told me to look at if_readlist(). "It seems that this function is iterating over the return array and feeding each item to a callback."
to-do ask:
3. How do I make this so I can test it? (I don't want it to screw up my ifconfig, test it in the directory (+m ifconfig.c and then ./ doesn't work))
4. is getting interface from IP addresses helpful at all? with the getifaddrs(): from stack overflow question and from IBM.
Wednesday, April 6, 2011
Listing All Network Devices on Linux: ifconfig vs "ip addr" in iproute2
To list all the networking interfaces on Linux, don't use ifconfig because it's deprecated, use ip addr instead. Ip addr is found in a utilities collection called iproute2. The wiki link points to where to download iproute2 source code, which was last updated on March 17, 2011 as I write this. I also finally found ifconfig's source code (in C) from net-tools. Note that its last update was in 2001, a decade ago!
See, they both give the same list!
Net-tools-1.60's "ifconfig.c" file has about 1100 lines of code.
Iproute2-2.6.38/ip/ipaddress.c file has about 1200 lines of code.
ifconfig
eth0 Link encap:Ethernet HWaddr 00:21:70:92:5b:c5
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Interrupt:17
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:20236 errors:0 dropped:0 overruns:0 frame:0
TX packets:20236 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:3259142 (3.2 MB) TX bytes:3259142 (3.2 MB)
vmnet1 Link encap:Ethernet HWaddr 00:50:56:c0:00:01
inet addr:172.16.76.1 Bcast:172.16.76.255 Mask:255.255.255.0
inet6 addr: fe80::250:56ff:fec0:1/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:2461 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
vmnet8 Link encap:Ethernet HWaddr 00:50:56:c0:00:08
inet addr:172.16.197.1 Bcast:172.16.197.255 Mask:255.255.255.0
inet6 addr: fe80::250:56ff:fec0:8/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:2461 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
wlan0 Link encap:Ethernet HWaddr 00:1c:26:64:0f:ac
inet addr:18.111.100.150 Bcast:18.111.127.255 Mask:255.255.224.0
inet6 addr: fe80::21c:26ff:fe64:fac/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:191734 errors:0 dropped:0 overruns:0 frame:0
TX packets:156739 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:224807742 (224.8 MB) TX bytes:28859347 (28.8 MB)
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Interrupt:17
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:20236 errors:0 dropped:0 overruns:0 frame:0
TX packets:20236 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:3259142 (3.2 MB) TX bytes:3259142 (3.2 MB)
vmnet1 Link encap:Ethernet HWaddr 00:50:56:c0:00:01
inet addr:172.16.76.1 Bcast:172.16.76.255 Mask:255.255.255.0
inet6 addr: fe80::250:56ff:fec0:1/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:2461 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
vmnet8 Link encap:Ethernet HWaddr 00:50:56:c0:00:08
inet addr:172.16.197.1 Bcast:172.16.197.255 Mask:255.255.255.0
inet6 addr: fe80::250:56ff:fec0:8/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:2461 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
wlan0 Link encap:Ethernet HWaddr 00:1c:26:64:0f:ac
inet addr:18.111.100.150 Bcast:18.111.127.255 Mask:255.255.224.0
inet6 addr: fe80::21c:26ff:fe64:fac/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:191734 errors:0 dropped:0 overruns:0 frame:0
TX packets:156739 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:224807742 (224.8 MB) TX bytes:28859347 (28.8 MB)
See, they both give the same list!
ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN qlen 1000
link/ether 00:21:70:92:5b:c5 brd ff:ff:ff:ff:ff:ff
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
link/ether 00:1c:26:64:0f:ac brd ff:ff:ff:ff:ff:ff
inet 18.111.100.150/19 brd 18.111.127.255 scope global wlan0
inet6 fe80::21c:26ff:fe64:fac/64 scope link
valid_lft forever preferred_lft forever
4: vmnet1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
link/ether 00:50:56:c0:00:01 brd ff:ff:ff:ff:ff:ff
inet 172.16.76.1/24 brd 172.16.76.255 scope global vmnet1
inet6 fe80::250:56ff:fec0:1/64 scope link
valid_lft forever preferred_lft forever
5: vmnet8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
link/ether 00:50:56:c0:00:08 brd ff:ff:ff:ff:ff:ff
inet 172.16.197.1/24 brd 172.16.197.255 scope global vmnet8
inet6 fe80::250:56ff:fec0:8/64 scope link
valid_lft forever preferred_lft forever
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN qlen 1000
link/ether 00:21:70:92:5b:c5 brd ff:ff:ff:ff:ff:ff
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
link/ether 00:1c:26:64:0f:ac brd ff:ff:ff:ff:ff:ff
inet 18.111.100.150/19 brd 18.111.127.255 scope global wlan0
inet6 fe80::21c:26ff:fe64:fac/64 scope link
valid_lft forever preferred_lft forever
4: vmnet1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
link/ether 00:50:56:c0:00:01 brd ff:ff:ff:ff:ff:ff
inet 172.16.76.1/24 brd 172.16.76.255 scope global vmnet1
inet6 fe80::250:56ff:fec0:1/64 scope link
valid_lft forever preferred_lft forever
5: vmnet8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
link/ether 00:50:56:c0:00:08 brd ff:ff:ff:ff:ff:ff
inet 172.16.197.1/24 brd 172.16.197.255 scope global vmnet8
inet6 fe80::250:56ff:fec0:8/64 scope link
valid_lft forever preferred_lft forever
Net-tools-1.60's "ifconfig.c" file has about 1100 lines of code.
Iproute2-2.6.38/ip/ipaddress.c file has about 1200 lines of code.
Thursday, March 10, 2011
Ping and Traceroute for internet
From the 6.033 assignment on "Internet Routes and Measuring Round Trip Times," I learned to use ping, which sends ICMP (similar to IP) request packets, for example: ping -c 10 -s 56 www.csail.mit.edu
But ping doesn't work for www.microsoft.com and some other sites, because they block ICMP due to security reasons. But most sites don't block ICMP because, ICMP is way, way more than "traceroute" and "ping." It is used for feedback when you run a DNS server (port unreachable) which, in a modern DNS server, may actually help select a different machine to query faster. (source)
Then we used traceroute, which prints the route packets trace to network host. According to its man page, It utilizes the IP protocol's time to live (TTL) field and attempts to elicit an ICMP TIME_EXCEEDED response from each gateway along the path to the host.
But ping doesn't work for www.microsoft.com and some other sites, because they block ICMP due to security reasons. But most sites don't block ICMP because, ICMP is way, way more than "traceroute" and "ping." It is used for feedback when you run a DNS server (port unreachable) which, in a modern DNS server, may actually help select a different machine to query faster. (source)
Then we used traceroute, which prints the route packets trace to network host. According to its man page, It utilizes the IP protocol's time to live (TTL) field and attempts to elicit an ICMP TIME_EXCEEDED response from each gateway along the path to the host.
Subscribe to:
Posts (Atom)