1/*
2    This file is part of Kismet
3
4    Kismet is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8
9    Kismet is distributed in the hope that it will be useful,
10      but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with Kismet; if not, write to the Free Software
16    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17*/
18
19
20#define __IN_OBJC_FILE__
21
22#include "config.h"
23
24#ifdef SYS_DARWIN
25
26// Is this a bad idea, to try to merge obj-c and c++ code into one codebase?
27// Yes, probably.
28// Code derived from kismac by KF
29
30#import <Foundation/Foundation.h>
31#include <unistd.h>
32#include <sys/types.h>
33#include <sys/stat.h>
34#include <errno.h>
35#include "apple80211.h"
36#include <Carbon/Carbon.h>
37#include "darwin_control_wrapper.h"
38#import "darwin_wificontrol.h"
39
40
41int darwin_bcom_testmonitor()
42{
43	NSDictionary *dict;
44	NSData *fileData;
45	NSString *error;
46	NSAutoreleasePool *pool;
47	pool  = [[NSAutoreleasePool alloc] init];
48
49	fileData = [NSData dataWithContentsOfFile:@"/System/Library/PrivateFrameworks/AppleTV.framework/Versions/Current/Resources/Info.plist"];
50	dict = [NSPropertyListSerialization propertyListFromData:fileData mutabilityOption:kCFPropertyListImmutable format:NULL errorDescription:&error];
51	if(!dict)
52	{
53		NSLog(@"%s", error);
54	}
55	else
56	{
57		if (strcmp([[dict valueForKeyPath:@"CFBundleExecutable"] cString], "AppleTV") == 0) return 1;
58	}
59	// This may work on AppleTV 1.1 also but I am not sure. This is a quick hack to force 1.0 to work.
60	fileData = [NSData dataWithContentsOfFile:@"/System/Library/MonitorPanels/AppleDisplay.monitorPanels/Contents/Resources/TVOptions.monitorPanel/Contents/Info.plist"];
61	dict = [NSPropertyListSerialization propertyListFromData:fileData mutabilityOption:kCFPropertyListImmutable format:NULL errorDescription:&error];
62	if(!dict)
63	{
64		NSLog(@"%s", error);
65	}
66	else
67	{
68		if (strcmp([[dict valueForKeyPath:@"CFBundleExecutable"] cString], "TVOptions") == 0) return 1;
69	}
70	fileData = [NSData dataWithContentsOfFile:@"/System/Library/Extensions/AppleAirPort2.kext/Contents/Info.plist"];
71	dict = [NSPropertyListSerialization propertyListFromData:fileData mutabilityOption:kCFPropertyListImmutable format:NULL errorDescription:&error];
72	if(!dict)
73	{
74		NSLog(@"%s", error);
75	}
76	else
77	{
78
79		if ([[dict valueForKeyPath:@"IOKitPersonalities.Broadcom PCI.APMonitorMode"] boolValue]) return 1;
80	}
81	fileData = [NSData dataWithContentsOfFile:@"/System/Library/Extensions/IO80211Family.kext/Contents/PlugIns/AppleAirPortBrcm4311.kext/Contents/Info.plist"];
82	dict = [NSPropertyListSerialization propertyListFromData:fileData mutabilityOption:kCFPropertyListImmutable format:NULL errorDescription:&error];
83	if(!dict)
84	{
85		NSLog(@"%s", error);
86	}
87	else
88	{
89		if ([[dict valueForKeyPath:@"IOKitPersonalities.Broadcom PCI.APMonitorMode"] boolValue]) return 1;
90	}
91	return -1;
92}
93
94int darwin_bcom_enablemonitorfile(const char *c_filename)
95{
96	NSDictionary *dict;
97	NSData *data;
98	NSString *fileName;
99	NSAutoreleasePool *pool;
100
101	pool  = [[NSAutoreleasePool alloc] init];
102	fileName = [[NSString alloc] initWithCString:c_filename];
103
104	if (chmod([fileName cString],
105		(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) < 0 &&
106		errno != ENOENT) {
107		return -1;
108	}
109
110	data = [NSData dataWithContentsOfFile:fileName];
111	if(!data) return 0;
112	dict = [NSPropertyListSerialization propertyListFromData:data mutabilityOption:kCFPropertyListMutableContainers format:NULL errorDescription:Nil];
113	if(!dict) return 0;
114	[dict setValue:[NSNumber numberWithBool:true] forKeyPath:@"IOKitPersonalities.Broadcom PCI.APMonitorMode"];
115	[[NSPropertyListSerialization dataFromPropertyList:dict format:kCFPropertyListXMLFormat_v1_0 errorDescription:nil] writeToFile:fileName atomically:NO];
116
117	if (chmod([fileName cString],
118		(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0 && errno != ENOENT) {
119		return -1;
120	}
121
122	return 1;
123}
124
125int darwin_bcom_enablemonitor()
126{
127	int ret, i;
128	NSAutoreleasePool *pool;
129	pool  = [[NSAutoreleasePool alloc] init];
130	char cmd[1024];
131
132	ret = darwin_bcom_enablemonitorfile("/System/Library/Extensions/AppleAirPort2.kext/Contents/Info.plist") ||
133		darwin_bcom_enablemonitorfile("/System/Library/Extensions/IO80211Family.kext/Contents/PlugIns/AppleAirPortBrcm4311.kext/Contents/Info.plist");
134
135	if (ret == 0) {
136		return -1;
137	}
138
139	if (unlink("/System/Library/Extensions.kextcache") < 0 && errno != ENOENT)
140		return -1;
141
142	snprintf(cmd, 1024, "/usr/sbin/kextcache -k /System/Library/Extensions");
143	if (system(cmd) != 0)
144		return -1;
145
146	if (unlink("/System/Library/Extensions.mkext") < 0 && errno != ENOENT)
147		return -1;
148
149	/* Throw a warning at the user and wait */
150	fprintf(stderr, "ATTENTION:  Kismet has enabled rfmon on your devices, however "
151			"to activate it, the kernel modules must be reloaded.  There have "
152			"been reports of this causing a system crash.  Kismet will wait 10 "
153			"seconds before attempting to reload the kernel modules.  Press "
154			"control-c now to cancel reloading modules and reboot manually if "
155			"you do not want to proceed!\n\n");
156
157	sleep(10);
158
159	/* we don't check the failure codes since we don't know which driver we're
160	 * using... Also according to geordi we have to thrash the unload because
161	 * sometimes it just refuses to unload the module.  Highly inelegant. */
162	for (i = 0; i < 10; i++) {
163		snprintf(cmd, 1024, "/sbin/kextunload -b com.apple.driver.AppleAirPort2"
164				 ">/dev/null 2>/dev/null");
165		system(cmd);
166
167		snprintf(cmd, 1024, "/sbin/kextunload -b "
168				 "com.apple.driver.AppleAirPortBrcm4311 >/dev/null 2>/dev/null");
169		system(cmd);
170	}
171
172	/* Try to reload them */
173	snprintf(cmd, 1024, "/sbin/kextload /System/Library/Extensions/AppleAirPort2.kext"
174			 ">/dev/null 2>/dev/null");
175	system(cmd);
176
177	snprintf(cmd, 1024, "/sbin/kextload "
178			 "/System/Library/Extensions/AppleAirPortBrcm4311.kext "
179			 ">/dev/null 2>/dev/null");
180	system(cmd);
181
182	fprintf(stderr, "ATTENTION:  Completed trying to reload the kernel modules.  "
183			"Sometimes this doesn't work, if Kismet does not start properly "
184			"you will need to manually reboot.\n");
185	sleep(5);
186
187	return 1;
188}
189
190void *darwin_allocate_interface(const char *in_iface) {
191	DarwinWifi *darwin = [[DarwinWifi alloc] initWithInterface:[[NSString alloc] initWithUTF8String:in_iface]];
192
193	return (void *) darwin;
194}
195
196void darwin_free_interface(void *in_darwin) {
197	// TODO
198}
199
200int darwin_set_channel(unsigned int in_channel, char *ret_err, void *in_darwin) {
201	DarwinWifi *darwin = (DarwinWifi *) in_darwin;
202	BOOL result;
203	NSError *err;
204
205	result = [darwin setChannel:in_channel error:ret_err];
206
207	if (!result) {
208		return -1;
209	}
210
211	return 1;
212}
213
214int darwin_get_corewifi(void *in_darwin) {
215	DarwinWifi *darwin = (DarwinWifi *) in_darwin;
216
217	return [darwin getCoreWireless];
218}
219
220void darwin_disassociate(void *in_darwin) {
221	DarwinWifi *darwin = (DarwinWifi *) in_darwin;
222
223	[darwin disAssociate];
224}
225
226int darwin_get_channels(const char *in_iface, int **ret_channels) {
227	NSArray *supported;
228	int *ret = NULL;
229	int x = 0;
230
231	DarwinWifi *darwin = [[DarwinWifi alloc] initWithInterface:[[NSString alloc] initWithUTF8String:in_iface]];
232
233	supported = [darwin getSupportedChannels];
234
235	if (supported == nil) {
236		*ret_channels = NULL;
237		return 0;
238	}
239
240	ret = (int *) malloc(sizeof(int) * [supported count]);
241
242	for (id sup in supported) {
243		ret[x++] = [sup intValue];
244	}
245
246	*ret_channels = ret;
247
248	x = [supported count];
249
250	return x;
251}
252
253#endif
254
255