Edit: Later found out that neither Wireshark nor libpcap gives a list of MAC addresses.
Answer: To get a list of internet device names, Wireless uses dumpcap's pcap_findalldevs().
I. I looked for MAC address
II. I looked for just the simple list of devices Wireshark shows
I. I grep-ed for "MAC address" and found over 500 entries, under these big categories:
- epan/dissectors (huge)
- plugins
- airpcap
Interesting things found:
- Ulf Lamping, ulf.lamping[at]web.de, put the source and destination MAC addresses into the top-level item for Ethernet.
- "manuf" contains Ethernet vendor codes (i.e. the first half of MAC Addresses), and well-known MAC addresses. So I checked the MAC Addresses from my ifconfig -a. eth0's first half is 00:21:70, which manuf says is Dell (yes I have a Dell computer). vmnet*'s first half is 00:50:56, which manuf says is VMware. wlan0's is 00:1c:26, which manuf says is Hon Hai Precision Ind. Co. Cool.
- Looking at epan/dissectors doesn't seem right. Hmm,
- Talked to Victor about it, he told me to look at the RubyGem (see other post) first
II. Give up. So what if I just track it down? The list at the beginning of Wireshark appears below the words "Start capture on interface:". So I grep-ed for those words and found that it appears in ./gtk/main_welcome.c.
There are 2 ways to go in main_welcome.c
1. WIRESHARK_STOCK_CAPTURE_INTERFACES from clicking on "Interface List" button on the main page. This is from
812 welcome_button(WIRESHARK_STOCK_CAPTURE_INTERFACES,
813 "Interface List",
814 "Live list of the capture interfaces\n(counts incoming packets)", ...
But searching down this path wasn't very fruitful813 "Interface List",
814 "Live list of the capture interfaces\n(counts incoming packets)", ...
2a. By looking at how the list of devices is generated directly with the welcome_if_panel_load() function.
653 /* load the list of interfaces */
654 static void
655 welcome_if_panel_load(void)
661 GList *if_list;
662 int err;
663 gchar *err_str = NULL;
669 /* LOAD THE INTERFACES */
670 if_list = capture_interface_list(&err, &err_str);
654 static void
655 welcome_if_panel_load(void)
661 GList *if_list;
662 int err;
663 gchar *err_str = NULL;
669 /* LOAD THE INTERFACES */
670 if_list = capture_interface_list(&err, &err_str);
btw, the g_blah() functions come from GLib
2b. So I now grep-ed for capture_interface_list(), which attempts to open all adapters it finds in order to check whether they can be captured on.
capture_interface_list() in ./capture_ifinfo.c
1 /* capture_ifinfo.c
2 * Routines for getting interface information from dumpcap
23 */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #ifdef HAVE_LIBPCAP
30
31 #include <stdlib.h>
32 #include <string.h>
33
34 #ifdef HAVE_ARPA_INET_H
35 #include <arpa/inet.h>
36 #endif
37
38 #ifdef HAVE_SYS_SOCKET_H
39 #include <sys/socket.h> /* needed to define AF_ values on UNIX */
40 #endif
41
42 #ifdef HAVE_WINSOCK2_H
43 #include <winsock2.h> /* needed to define AF_ values on Windows */
2 * Routines for getting interface information from dumpcap
23 */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #ifdef HAVE_LIBPCAP
30
31 #include <stdlib.h>
32 #include <string.h>
33
34 #ifdef HAVE_ARPA_INET_H
35 #include <arpa/inet.h>
36 #endif
37
38 #ifdef HAVE_SYS_SOCKET_H
39 #include <sys/socket.h> /* needed to define AF_ values on UNIX */
40 #endif
41
42 #ifdef HAVE_WINSOCK2_H
43 #include <winsock2.h> /* needed to define AF_ values on Windows */
44 #endif
45
46 #ifdef NEED_INET_V6DEFS_H
47 # include "wsutil/inet_v6defs.h"
48 #endif
49
50 #include <glib.h>
51
52 #include "capture_opts.h"
53 #include "capture_sync.h"
54 #include "log.h"
55
56 #include "capture_ifinfo.h"
57
58 /**
59 * Fetch the interface list from a child process (dumpcap).
60 *
61 * @return A GList containing if_info_t structs if successful, NULL (with err and possibly err_str set) otherwise.
62 *
63 */
64
65 /* XXX - We parse simple text output to get our interface list. Should
66 * we use "real" data serialization instead, e.g. via XML? */
67 GList *
68 capture_interface_list(int *err, char **err_str)
69 {
70 int ret;
71 GList *if_list = NULL;
72 int i, j;
73 gchar *data, *primary_msg, *secondary_msg;
74 gchar **raw_list, **if_parts, **addr_parts;
75 gchar *name;
76 if_info_t *if_info;
77 if_addr_t *if_addr;
78
79 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface List ...");
80
81 /* Try to get our interface list */
82 ret = sync_interface_list_open(&data, &primary_msg, &secondary_msg);
83 if (ret != 0) {
84 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface List failed!");
85 if (err_str) {
86 *err_str = primary_msg;
87 } else {
88 g_free(primary_msg);
89 }
90 g_free(secondary_msg);
91 *err = CANT_GET_INTERFACE_LIST;
92 return NULL;
93 }
94
95 /* Split our lines */
96 #ifdef _WIN32
97 raw_list = g_strsplit(data, "\r\n", 0);
98 #else
99 raw_list = g_strsplit(data, "\n", 0);
100 #endif
101 g_free(data);
102
103 for (i = 0; raw_list[i] != NULL; i++) {
104 if_parts = g_strsplit(raw_list[i], "\t", 4);
105 if (if_parts[0] == NULL || if_parts[1] == NULL || if_parts[2] == NULL ||
106 if_parts[3] == NULL) {
107 g_strfreev(if_parts);
108 continue;
109 }
110
111 /* Number followed by the name, e.g "1. eth0" */
112 name = strchr(if_parts[0], ' '); /*strchr searches to see if there is a single
space chr in if_parts[0] */
space chr in if_parts[0] */
113 if (name) {
114 name++;
115 } else {
116 g_strfreev(if_parts);
117 continue;
118 }
119
120 if_info = g_malloc0(sizeof(if_info_t));
121 if_info->name = g_strdup(name);
122 if (strlen(if_parts[1]) > 0)
123 if_info->description = g_strdup(if_parts[1]);
124 addr_parts = g_strsplit(if_parts[2], ",", 0);
125 for (j = 0; addr_parts[j] != NULL; j++) {
126 if_addr = g_malloc0(sizeof(if_addr_t));
127 if (inet_pton(AF_INET, addr_parts[j], &if_addr->addr.ip4_addr)) {
128 if_addr->ifat_type = IF_AT_IPv4;
129 } else if (inet_pton(AF_INET6, addr_parts[j],
130 &if_addr->addr.ip6_addr)) {
131 if_addr->ifat_type = IF_AT_IPv6;
132 } else {
133 g_free(if_addr);
134 if_addr = NULL;
135 }
136 if (if_addr) {
137 if_info->addrs = g_slist_append(if_info->addrs, if_addr);
138 }
139 }
140 if (strcmp(if_parts[3], "loopback") == 0)
141 if_info->loopback = TRUE;
142 g_strfreev(if_parts);
143 g_strfreev(addr_parts);
144 if_list = g_list_append(if_list, if_info);
145 }
146 g_strfreev(raw_list);
147
148 /* Check to see if we built a list */
149 if (if_list == NULL) {
150 *err = NO_INTERFACES_FOUND;
151 if (err_str)
152 *err_str = g_strdup("No interfaces found");
153 }
154 return if_list;
155 }
2c. Then look at: sync_interface_list_open(), which is found in ./capture_sync.c:
1073 /*
1074 * Get the list of interfaces using dumpcap.
1075 *
1076 * On success, *data points to a buffer containing the dumpcap output,
1077 * *primary_msg and *secondary_msg are NULL, and 0 is returned. *data
1078 * must be freed with g_free().
1079 *
1080 * On failure, *data is NULL, *primary_msg points to an error message,
1081 * *secondary_msg either points to an additional error message or is
1082 * NULL, and -1 is returned; *primary_msg, and *secondary_msg if not NULL,
1083 * must be freed with g_free().
1084 */
1085 int
1086 sync_interface_list_open(gchar **data, gchar **primary_msg,
1087 gchar **secondary_msg)
1088 {
1089 int argc;
1090 const char **argv;
1091
1092 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_interface_list_open");
1093
1094 argv = init_pipe_args(&argc);
1095
1096 if (!argv) {
1097 *primary_msg = g_strdup("We don't know where to find dumpcap.");
1098 *secondary_msg = NULL;
1099 *data = NULL;
1100 return -1;
1101 }
1102
1103 /* Ask for the interface list */
1104 argv = sync_pipe_add_arg(argv, &argc, "-D");
1105
1106 #ifndef DEBUG_CHILD
1107 /* Run dumpcap in capture child mode */
1108 argv = sync_pipe_add_arg(argv, &argc, "-Z");
1109 argv = sync_pipe_add_arg(argv, &argc, SIGNAL_PIPE_CTRL_ID_NONE);
1110 #endif
1111 return sync_pipe_run_command(argv, data, primary_msg, secondary_msg);
1112 }
It's passing in an argument to get the devices, and the argument is "dumpcap"1074 * Get the list of interfaces using dumpcap.
1075 *
1076 * On success, *data points to a buffer containing the dumpcap output,
1077 * *primary_msg and *secondary_msg are NULL, and 0 is returned. *data
1078 * must be freed with g_free().
1079 *
1080 * On failure, *data is NULL, *primary_msg points to an error message,
1081 * *secondary_msg either points to an additional error message or is
1082 * NULL, and -1 is returned; *primary_msg, and *secondary_msg if not NULL,
1083 * must be freed with g_free().
1084 */
1085 int
1086 sync_interface_list_open(gchar **data, gchar **primary_msg,
1087 gchar **secondary_msg)
1088 {
1089 int argc;
1090 const char **argv;
1091
1092 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_interface_list_open");
1093
1094 argv = init_pipe_args(&argc);
1095
1096 if (!argv) {
1097 *primary_msg = g_strdup("We don't know where to find dumpcap.");
1098 *secondary_msg = NULL;
1099 *data = NULL;
1100 return -1;
1101 }
1102
1103 /* Ask for the interface list */
1104 argv = sync_pipe_add_arg(argv, &argc, "-D");
1105
1106 #ifndef DEBUG_CHILD
1107 /* Run dumpcap in capture child mode */
1108 argv = sync_pipe_add_arg(argv, &argc, "-Z");
1109 argv = sync_pipe_add_arg(argv, &argc, SIGNAL_PIPE_CTRL_ID_NONE);
1110 #endif
1111 return sync_pipe_run_command(argv, data, primary_msg, secondary_msg);
1112 }
2d. dumpcap and dumpcap.c
dumpcap is cross platform. :)
man dumpcap told me that the option "-D" prints a list of the interfaces on which Dumpcap can capture.
I found dumpcap's code in "dumpcap.c":
3792 * "-D" requires no interface to be selected; it's supposed to list 3793 * all interfaces. 3794 */ 3795 if (list_interfaces) { 3796 /* Get the list of interfaces */ 3797 GList *if_list; 3798 int err; 3799 gchar *err_str; 3800 3801 if_list = capture_interface_list(&err, &err_str);
So then I track down this function
796 GList *
797 capture_interface_list(int *err, char **err_str)
798 {
799 return get_interface_list(err, err_str);
800 }
after "grep -ir get_interface_list ." I found it in:
2e. capture-wpcap.c
676 /* 677 * This will use "pcap_findalldevs()" if we have it, otherwise it'll 678 * fall back on "pcap_lookupdev()". 679 */ 680 GList * 681 get_interface_list(int *err, char **err_str) 682 { 683 GList *il = NULL; 684 wchar_t *names; 685 char *win95names; 686 char ascii_name[MAX_WIN_IF_NAME_LEN + 1]; 687 char ascii_desc[MAX_WIN_IF_NAME_LEN + 1]; 688 int i, j; 689 char errbuf[PCAP_ERRBUF_SIZE]; 690 691 #ifdef HAVE_PCAP_FINDALLDEVS 692 if (p_pcap_findalldevs != NULL) 693 return get_interface_list_findalldevs(err, err_str); 694 #endif ... 738 739 names = (wchar_t *)pcap_lookupdev(errbuf);
There are 2 methods, get_interface_list_findalldevs() or pcap_lookupdev()
Both methods will require code from libpcap, which I found on this site.
Working out the 2 different ways
2d.1. First, let's try with get_interface_list_findalldevs()
Inside capture-pcap-util.c
2d.2 Now, let's try with the other method pcap_lookupdev()
2d.2b. Now we have to look at libpcap's code for pcap_lookupdev, which will also lead to
Inside capture-pcap-util.c
107 #ifdef HAVE_PCAP_FINDALLDEVS ... 166 GList * 167 get_interface_list_findalldevs(int *err, char **err_str) 168 { 169 GList *il = NULL; 170 pcap_if_t *alldevs, *dev; 171 if_info_t *if_info; 172 char errbuf[PCAP_ERRBUF_SIZE]; 173 174 if (pcap_findalldevs(&alldevs, errbuf) == -1) { 175 *err = CANT_GET_INTERFACE_LIST; 176 if (err_str != NULL) 177 *err_str = cant_get_if_list_error_message(errbuf); 178 return NULL; 179 } 180 181 if (alldevs == NULL) { 182 /* 183 * No interfaces found. 184 */ 185 *err = NO_INTERFACES_FOUND; 186 if (err_str != NULL) 187 *err_str = NULL; 188 return NULL; 189 } 190 191 for (dev = alldevs; dev != NULL; dev = dev->next) { 192 if_info = if_info_new(dev->name, dev->description); 193 il = g_list_append(il, if_info); 194 if_info_ip(if_info, dev); 195 } 196 pcap_freealldevs(alldevs); 197 198 return il; 199 } 200 #endif /* HAVE_PCAP_FINDALLDEVS */
2d.2 Now, let's try with the other method pcap_lookupdev()
233 char*
234 pcap_lookupdev (char *a)
235 {
236 if (!has_wpcap) {
237 return NULL;
238 }
239 return p_pcap_lookupdev(a);
240 }
which is a pointer56 static char* (*p_pcap_lookupdev) (char *);
2d.2b. Now we have to look at libpcap's code for pcap_lookupdev, which will also lead to
pcap_findalldevs()Found it in inet.c
635 #if !defined(WIN32) && !defined(MSDOS) 636 637 /* 638 * Return the name of a network interface attached to the system, or NULL 639 * if none can be found. The interface must be configured up; the 640 * lowest unit number is preferred; loopback is ignored. 641 */ 642 char * 643 pcap_lookupdev(errbuf) 644 register char *errbuf; 645 { ... 654 if (pcap_findalldevs(&alldevs, errbuf) == -1) 777 #elif defined(WIN32) 778 779 /* 780 * Return the name of a network interface attached to the system, or NULL 781 * if none can be found. The interface must be configured up; the 782 * lowest unit number is preferred; loopback is ignored. 783 */ 784 char * 785 pcap_lookupdev(errbuf) 786 register char *errbuf; 787 { 788 DWORD dwVersion; 789 DWORD dwWindowsMajorVersion; 790 dwVersion = GetVersion(); /* get the OS version */ 791 dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); 792 793 if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) { 794 /* 795 * Windows 95, 98, ME. 796 */ 797 ULONG NameLength = 8192; 798 static char AdaptersName[8192]; 799 800 if (PacketGetAdapterNames(AdaptersName,&NameLength) ) 801 return (AdaptersName); 802 else 803 return NULL; 804 } else { 805 /* 806 * Windows NT (NT 4.0, W2K, WXP). Convert the names to UNICODE for backward compatibiliy
3. Now we need to look inside libpcap-1.1.1 for pcap_findalldevs()
Method description from pcap-sita.html:
SMP The Supervisory Management Processor where Wireshark (or equivalent) runs in conjuction with a libpcap front-end.
IOP I/O Processors where the monitored ports exist in conjunction with a custom device driver/libpcap back-end.
pcap_findalldevs constructs a list of network devices that can be opened with pcap_open_live().
SMP It obtains a list of IOPs currently available (via /etc/hosts).
SMP -> IOP The SMP will sequentially open a connection to each IOP on its 'sniffer' port to ensure the IOP is available. It sends a null terminated empty interface ID followed by the query request command.
IOP -> SMP The IOP returns an error response and its list of devices.
SMP -> IOP The SMP closes the TCP connection with each IOP.
SMP The SMP adds the received information to its internal structure.
=========================
SMP/IOP Inter-Process Communication Protocol
between an ephemeral port on the SMP and the well known port of 49152
(which is the first available port in the 'dynamic and/or private port'
range) on an IOP.
'interface ID' string to determine the type of operation that follows:
occur before executing the received command.
Obviously monitoring and forwarding is also stopped at that time.
Note: All multi-octet entities are sent in network neutral order.
SMP -> IOP | Open socket (to each IOP), and sends:
| |||||||||||||||||||||||||||||||||||||||||||||||||||
IOP -> SMP | Send its (possibly empty) NULL terminated error response string. | |||||||||||||||||||||||||||||||||||||||||||||||||||
SMP -> IOP | Sends the 'interface query request':
| |||||||||||||||||||||||||||||||||||||||||||||||||||
IOP -> SMP | The IOP returns a list of sequences of information as defined by the return parameter of this function call (as shown in the following table). Elements are specified by providing an unsigned byte preceeding the actual data that contains length information.
| |||||||||||||||||||||||||||||||||||||||||||||||||||
SMP -> IOP | Close the socket. | |||||||||||||||||||||||||||||||||||||||||||||||||||
IOP -> SMP | Close the socket. |
I have "pcap_findalldevs" source from the following files in libpcap-1.1.1:
they all take the same arguments
fad-win32.c - for Windows OS
216 * Win32 implementation, based on WinPcap 217 */ 218 int 219 pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
fad-gifc.c - This is the implementation used on platforms that have SIOCGIFCONF but don't have any other mechanism for getting a list of interfaces.
fad-getad.c - This is the implementation used on platforms that have "getifaddrs()"
(btw MacOS uses free bsd.)
Already have a gem to get Linux list MAC Address working
MacOS can be on hold
Focus on getting Windows to work! look at fad-win32.c in more detail
No comments:
Post a Comment