forked from jwise/HoRNDIS
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathHoRNDIS.h
319 lines (268 loc) · 10.4 KB
/
HoRNDIS.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
/* HoRNDIS.h
* Declaration of IOKit-derived classes
* HoRNDIS, a RNDIS driver for Mac OS X
*
* Copyright (c) 2012 Joshua Wise.
*
* IOKit examples from Apple's USBCDCEthernet.cpp; not much of that code remains.
*
* RNDIS logic is from linux/drivers/net/usb/rndis_host.c, which is:
*
* Copyright (c) 2005 David Brownell.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <machine/limits.h> /* UINT_MAX */
#include <libkern/OSByteOrder.h>
#include <libkern/OSTypes.h>
#include <IOKit/network/IOEthernetController.h>
#include <IOKit/network/IOEthernetInterface.h>
#include <IOKit/network/IOGatedOutputQueue.h>
#include <IOKit/IOTimerEventSource.h>
#include <IOKit/assert.h>
#include <IOKit/IOLib.h>
#include <IOKit/IOService.h>
#include <IOKit/IOBufferMemoryDescriptor.h>
#include <IOKit/IOMessage.h>
#include <IOKit/pwr_mgt/RootDomain.h>
#include <IOKit/usb/IOUSBBus.h>
#include <IOKit/usb/IOUSBNub.h>
#include <IOKit/usb/IOUSBDevice.h>
#include <IOKit/usb/IOUSBPipe.h>
#include <IOKit/usb/USB.h>
#include <IOKit/usb/IOUSBInterface.h>
#include <UserNotification/KUNCUserNotifications.h>
extern "C"
{
#include <sys/param.h>
#include <sys/mbuf.h>
}
#define cpu_to_le32(x) (uint32_t)OSSwapHostToLittleInt32(x)
#define le32_to_cpu(x) (uint32_t)OSSwapLittleToHostInt32(x)
#define TRANSMIT_QUEUE_SIZE 256
#define MAX_BLOCK_SIZE PAGE_SIZE
#define kPipeStalled 1
#define N_OUT_BUFS 16
#define OUT_BUF_MAX_TRIES 10 /* 50ms total */
#define OUT_BUF_WAIT_TIME 5000000 /* ns */
#define MAX_MTU 1536
/***** RNDIS definitions -- from linux/include/linux/usb/rndis_host.h ****/
#define RNDIS_CMD_BUF_SZ 1052
struct rndis_msg_hdr {
uint32_t msg_type;
uint32_t msg_len;
uint32_t request_id;
uint32_t status;
} __attribute__((packed));
struct rndis_data_hdr {
uint32_t msg_type;
uint32_t msg_len;
uint32_t data_offset;
uint32_t data_len;
uint32_t oob_data_offset;
uint32_t oob_data_len;
uint32_t num_oob;
uint32_t packet_data_offset;
uint32_t packet_data_len;
uint32_t vc_handle;
uint32_t reserved;
} __attribute__((packed));
struct rndis_query {
uint32_t msg_type;
uint32_t msg_len;
uint32_t request_id;
uint32_t oid;
uint32_t len;
uint32_t offset;
uint32_t handle;
} __attribute__((packed));
struct rndis_query_c {
uint32_t msg_type;
uint32_t msg_len;
uint32_t request_id;
uint32_t status;
uint32_t len;
uint32_t offset;
} __attribute__((packed));
struct rndis_init {
uint32_t msg_type;
uint32_t msg_len;
uint32_t request_id;
uint32_t major_version;
uint32_t minor_version;
uint32_t mtu;
} __attribute__((packed));
struct rndis_init_c {
uint32_t msg_type;
uint32_t msg_len;
uint32_t request_id;
uint32_t status;
uint32_t major_version;
uint32_t minor_version;
uint32_t device_flags;
uint32_t medium;
uint32_t max_packets_per_message;
uint32_t mtu;
uint32_t packet_alignment;
uint32_t af_list_offset;
uint32_t af_list_size;
} __attribute__((packed));
struct rndis_set {
uint32_t msg_type;
uint32_t msg_len;
uint32_t request_id;
uint32_t oid;
uint32_t len;
uint32_t offset;
uint32_t handle;
} __attribute__((packed));
struct rndis_set_c {
uint32_t msg_type;
uint32_t msg_len;
uint32_t request_id;
uint32_t status;
} __attribute__((packed));
#define RNDIS_MSG_COMPLETION cpu_to_le32(0x80000000)
#define RNDIS_MSG_PACKET cpu_to_le32(0x00000001) /* 1-N packets */
#define RNDIS_MSG_INIT cpu_to_le32(0x00000002)
#define RNDIS_MSG_INIT_C (RNDIS_MSG_INIT|RNDIS_MSG_COMPLETION)
#define RNDIS_MSG_HALT cpu_to_le32(0x00000003)
#define RNDIS_MSG_QUERY cpu_to_le32(0x00000004)
#define RNDIS_MSG_QUERY_C (RNDIS_MSG_QUERY|RNDIS_MSG_COMPLETION)
#define RNDIS_MSG_SET cpu_to_le32(0x00000005)
#define RNDIS_MSG_SET_C (RNDIS_MSG_SET|RNDIS_MSG_COMPLETION)
#define RNDIS_MSG_RESET cpu_to_le32(0x00000006)
#define RNDIS_MSG_RESET_C (RNDIS_MSG_RESET|RNDIS_MSG_COMPLETION)
#define RNDIS_MSG_INDICATE cpu_to_le32(0x00000007)
#define RNDIS_MSG_KEEPALIVE cpu_to_le32(0x00000008)
#define RNDIS_MSG_KEEPALIVE_C (RNDIS_MSG_KEEPALIVE|RNDIS_MSG_COMPLETION)
#define RNDIS_STATUS_SUCCESS cpu_to_le32(0x00000000)
#define RNDIS_STATUS_FAILURE cpu_to_le32(0xc0000001)
#define RNDIS_STATUS_INVALID_DATA cpu_to_le32(0xc0010015)
#define RNDIS_STATUS_NOT_SUPPORTED cpu_to_le32(0xc00000bb)
#define RNDIS_STATUS_MEDIA_CONNECT cpu_to_le32(0x4001000b)
#define RNDIS_STATUS_MEDIA_DISCONNECT cpu_to_le32(0x4001000c)
#define RNDIS_STATUS_MEDIA_SPECIFIC_INDICATION cpu_to_le32(0x40010012)
#define RNDIS_PHYSICAL_MEDIUM_UNSPECIFIED cpu_to_le32(0x00000000)
#define RNDIS_PHYSICAL_MEDIUM_WIRELESS_LAN cpu_to_le32(0x00000001)
#define RNDIS_PHYSICAL_MEDIUM_CABLE_MODEM cpu_to_le32(0x00000002)
#define RNDIS_PHYSICAL_MEDIUM_PHONE_LINE cpu_to_le32(0x00000003)
#define RNDIS_PHYSICAL_MEDIUM_POWER_LINE cpu_to_le32(0x00000004)
#define RNDIS_PHYSICAL_MEDIUM_DSL cpu_to_le32(0x00000005)
#define RNDIS_PHYSICAL_MEDIUM_FIBRE_CHANNEL cpu_to_le32(0x00000006)
#define RNDIS_PHYSICAL_MEDIUM_1394 cpu_to_le32(0x00000007)
#define RNDIS_PHYSICAL_MEDIUM_WIRELESS_WAN cpu_to_le32(0x00000008)
#define RNDIS_PHYSICAL_MEDIUM_MAX cpu_to_le32(0x00000009)
#define OID_802_3_PERMANENT_ADDRESS cpu_to_le32(0x01010101)
#define OID_GEN_MAXIMUM_FRAME_SIZE cpu_to_le32(0x00010106)
#define OID_GEN_CURRENT_PACKET_FILTER cpu_to_le32(0x0001010e)
#define OID_GEN_PHYSICAL_MEDIUM cpu_to_le32(0x00010202)
/* packet filter bits used by OID_GEN_CURRENT_PACKET_FILTER */
#define RNDIS_PACKET_TYPE_DIRECTED cpu_to_le32(0x00000001)
#define RNDIS_PACKET_TYPE_MULTICAST cpu_to_le32(0x00000002)
#define RNDIS_PACKET_TYPE_ALL_MULTICAST cpu_to_le32(0x00000004)
#define RNDIS_PACKET_TYPE_BROADCAST cpu_to_le32(0x00000008)
#define RNDIS_PACKET_TYPE_SOURCE_ROUTING cpu_to_le32(0x00000010)
#define RNDIS_PACKET_TYPE_PROMISCUOUS cpu_to_le32(0x00000020)
#define RNDIS_PACKET_TYPE_SMT cpu_to_le32(0x00000040)
#define RNDIS_PACKET_TYPE_ALL_LOCAL cpu_to_le32(0x00000080)
#define RNDIS_PACKET_TYPE_GROUP cpu_to_le32(0x00001000)
#define RNDIS_PACKET_TYPE_ALL_FUNCTIONAL cpu_to_le32(0x00002000)
#define RNDIS_PACKET_TYPE_FUNCTIONAL cpu_to_le32(0x00004000)
#define RNDIS_PACKET_TYPE_MAC_FRAME cpu_to_le32(0x00008000)
/* default filter used with RNDIS devices */
#define RNDIS_DEFAULT_FILTER ( \
RNDIS_PACKET_TYPE_DIRECTED | \
RNDIS_PACKET_TYPE_BROADCAST | \
RNDIS_PACKET_TYPE_ALL_MULTICAST | \
RNDIS_PACKET_TYPE_PROMISCUOUS)
#define USB_CDC_SEND_ENCAPSULATED_COMMAND 0x00
#define USB_CDC_GET_ENCAPSULATED_RESPONSE 0x01
/***** Actual class definitions *****/
typedef struct {
bool inuse;
IOBufferMemoryDescriptor *mdp;
void *buf;
IOUSBCompletion comp;
} pipebuf_t;
class HoRNDIS : public IOEthernetController {
OSDeclareDefaultStructors(HoRNDIS); // Constructor & Destructor stuff
private:
bool fTerminate; // being terminated now (i.e., device being unplugged)
IOEthernetInterface *fNetworkInterface;
IONetworkStats *fpNetStats;
OSDictionary *fMediumDict;
bool fNetifEnabled;
bool fDataDead;
IOUSBInterface *fCommInterface;
IOUSBInterface *fDataInterface;
IOUSBPipe *fInPipe;
IOUSBPipe *fOutPipe;
IOLock *xid_lock;
uint32_t xid;
uint32_t mtu;
IOLock *outbuf_lock;
pipebuf_t outbufs[N_OUT_BUFS];
static void dataWriteComplete(void *obj, void *param, IOReturn ior, UInt32 remaining);
pipebuf_t inbuf;
static void dataReadComplete(void *obj, void *param, IOReturn ior, UInt32 remaining);
bool rndisInit();
int rndisCommand(struct rndis_msg_hdr *buf, int buflen);
int rndisQuery(void *buf, uint32_t oid, uint32_t in_len, void **reply, int *reply_len);
bool rndisSetPacketFilter(uint32_t filter);
bool createMediumTables(void);
bool allocateResources(void);
void releaseResources(void);
bool openInterfaces();
bool createNetworkInterface(void);
UInt32 outputPacket(mbuf_t pkt, void *param);
IOReturn clearPipeStall(IOUSBPipe *thePipe);
void receivePacket(void *packet, UInt32 size);
IOWorkLoop *workloop;
public:
IOUSBDevice *fpDevice;
// IOKit overrides
virtual bool init(OSDictionary *properties = 0);
virtual bool start(IOService *provider);
virtual void stop(IOService *provider);
virtual bool createWorkLoop();
virtual IOWorkLoop *getWorkLoop() const;
virtual IOReturn message(UInt32 type, IOService *provider, void *argument = 0);
// IOEthernetController overrides
virtual IOReturn enable(IONetworkInterface *netif);
virtual IOReturn disable(IONetworkInterface *netif);
virtual IOReturn getPacketFilters(const OSSymbol *group, UInt32 *filters ) const;
virtual IOReturn getMaxPacketSize(UInt32 * maxSize) const;
virtual IOReturn selectMedium(const IONetworkMedium *medium);
virtual IOReturn getHardwareAddress(IOEthernetAddress *addr);
virtual IOReturn setPromiscuousMode(bool active);
virtual IOOutputQueue *createOutputQueue(void);
virtual bool configureInterface(IONetworkInterface *netif);
virtual IONetworkInterface *createInterface();
};
/* If there are other ways to get access to a device, we probably want them here. */
class HoRNDISUSBInterface : public HoRNDIS {
OSDeclareDefaultStructors(HoRNDISUSBInterface);
public:
virtual bool start(IOService *provider);
};
class HoRNDISInterface : public IOEthernetInterface {
OSDeclareDefaultStructors(HoRNDISInterface);
int maxmtu;
public:
virtual bool init(IONetworkController * controller, int mtu);
virtual bool setMaxTransferUnit(UInt32 mtu);
};