Indentation fix, cleanup.
[AROS.git] / arch / all-unix / devs / networks / tap / command.c
blob3abf4dcaaeb3d3df91625f04d6285b6b61143f32
1 /*
2 * tap - TUN/TAP network driver for AROS
3 * Copyright (c) 2007 Robert Norris. All rights reserved.
4 * Copyright © 2010, The AROS Development Team. All rights reserved.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the same terms as AROS itself.
8 */
10 #define DEBUG 0
11 #define DWRITE(x)
13 #include "tap.h"
15 static const UWORD tap_supported_commands[] = {
16 S2_DEVICEQUERY,
17 S2_GETSTATIONADDRESS,
18 S2_CONFIGINTERFACE,
19 S2_ONLINE,
20 S2_OFFLINE,
21 S2_BROADCAST,
22 CMD_READ,
23 CMD_WRITE,
24 CMD_FLUSH,
25 S2_TRACKTYPE,
26 S2_UNTRACKTYPE,
27 S2_GETTYPESTATS,
28 S2_GETGLOBALSTATS,
29 #if NEWSTYLE_DEVICE
30 NSCMD_DEVICEQUERY,
31 #endif
35 static BOOL tap_device_query(struct IOSana2Req *req, struct tap_unit *unit) {
36 CopyMem(&(unit->info), req->ios2_StatData, sizeof(struct Sana2DeviceQuery));
38 return TRUE;
41 static BOOL tap_get_station_address(struct IOSana2Req *req, struct tap_unit *unit) {
42 CopyMem(unit->hwaddr, &req->ios2_SrcAddr, ETH_ALEN);
43 CopyMem(unit->hwaddr, &req->ios2_DstAddr, ETH_ALEN);
45 return TRUE;
48 static BOOL tap_config_interface(struct IOSana2Req *req, struct tap_unit *unit) {
49 if (unit->flags & tu_CONFIGURED) {
50 D(bug("[tap] [%d] already configured\n", unit->num));
52 req->ios2_Req.io_Error = S2ERR_BAD_STATE;
53 req->ios2_WireError = S2WERR_IS_CONFIGURED;
55 return TRUE;
58 CopyMem(unit->hwaddr, &req->ios2_SrcAddr, ETH_ALEN);
59 CopyMem(unit->hwaddr, &req->ios2_DstAddr, ETH_ALEN);
61 unit->flags |= tu_CONFIGURED;
63 return TRUE;
66 static BOOL tap_online(struct IOSana2Req *req, struct tap_unit *unit) {
67 if (unit->flags & tu_ONLINE) {
68 D(bug("[tap] [%d] already online\n", unit->num));
70 req->ios2_Req.io_Error = S2ERR_BAD_STATE;
71 req->ios2_WireError = S2WERR_UNIT_ONLINE;
73 return TRUE;
76 if (!(unit->flags & tu_CONFIGURED)) {
77 D(bug("[tap] [%d] not configured\n", unit->num));
79 req->ios2_Req.io_Error = S2ERR_BAD_STATE;
80 req->ios2_WireError = S2WERR_UNIT_ONLINE;
82 return TRUE;
85 unit->flags |= tu_ONLINE;
87 D(bug("[tap] [%d] online\n", unit->num));
89 return TRUE;
92 static BOOL tap_offline(struct IOSana2Req *req, struct tap_unit *unit) {
93 if (!(unit->flags & tu_ONLINE)) {
94 D(bug("[tap] [%d] already offline\n", unit->num));
96 req->ios2_Req.io_Error = S2ERR_BAD_STATE;
97 req->ios2_WireError = S2WERR_UNIT_OFFLINE;
99 return TRUE;
102 unit->flags &= ~tu_ONLINE;
104 D(bug("[tap] [%d] offline\n", unit->num));
106 return TRUE;
109 static BOOL tap_read(struct IOSana2Req *req, struct tap_unit *unit) {
110 struct tap_opener *opener;
112 if (!(unit->flags & tu_ONLINE)) {
113 D(bug("[tap] [%d] not online\n", unit->num));
115 req->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
116 req->ios2_WireError = S2WERR_UNIT_OFFLINE;
118 return TRUE;
121 opener = req->ios2_BufferManagement;
123 req->ios2_Req.io_Flags &= ~IOF_QUICK;
124 PutMsg(&(opener->read_pending), (struct Message *) req);
126 D(bug("[tap] [%d] queued read request\n", unit->num));
128 return FALSE;
131 static BOOL tap_write(struct IOSana2Req *req, struct tap_unit *unit) {
132 if (!(unit->flags & tu_ONLINE)) {
133 DWRITE(bug("[tap] [%d] not online\n", unit->num));
135 req->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
136 req->ios2_WireError = S2WERR_UNIT_OFFLINE;
138 return TRUE;
141 req->ios2_Req.io_Flags &= ~IOF_QUICK;
142 PutMsg(unit->write_queue, (struct Message *) req);
144 DWRITE(bug("[tap] [%d] queued write request\n", unit->num));
146 return FALSE;
149 static BOOL tap_track_type(struct IOSana2Req *req, struct tap_unit *unit) {
150 struct tap_tracker *tracker, *tracker_next;
151 WORD packet_type = req->ios2_PacketType;
153 D(bug("[tap] [%d] track of packet type 0x%04x requested\n", unit->num, packet_type));
155 ForeachNodeSafe(&(unit->trackers), tracker, tracker_next) {
156 if (tracker->packet_type == packet_type) {
157 D(bug("[tap] [%d] already tracking, incrementing the refcount\n", unit->num));
158 tracker->refcount ++;
159 return TRUE;
163 tracker = AllocVec(sizeof(struct tap_tracker), MEMF_PUBLIC | MEMF_CLEAR);
164 tracker->refcount = 1;
165 tracker->packet_type = packet_type;
167 Disable();
168 AddTail((APTR) &(unit->trackers), (APTR) tracker);
169 Enable();
171 D(bug("[tap] [%d] now tracking\n", unit->num));
173 return TRUE;
176 static BOOL tap_untrack_type(struct IOSana2Req *req, struct tap_unit *unit) {
177 struct tap_tracker *tracker, *tracker_next;
178 WORD packet_type = req->ios2_PacketType;
180 D(bug("[tap] [%d] untrack of packet type 0x%04x requested\n", unit->num, packet_type));
182 ForeachNodeSafe(&(unit->trackers), tracker, tracker_next) {
183 if (tracker->packet_type == packet_type) {
184 D(bug("[tap] [%d] found it, decrementing the refcount\n", unit->num));
185 tracker->refcount --;
187 if (tracker->refcount == 0) {
188 D(bug("[tap] [%d] refcount is 0, not tracking any longer\n", unit->num));
190 Disable();
191 Remove((APTR) tracker);
192 Enable();
194 FreeVec(tracker);
197 return TRUE;
201 D(bug("[tap] [%d] no tracking, nothing to do\n", unit->num));
203 return TRUE;
206 static BOOL tap_get_type_stats(struct IOSana2Req *req, struct tap_unit *unit) {
207 struct tap_tracker *tracker, *tracker_next;
208 WORD packet_type = req->ios2_PacketType;
210 D(bug("[tap] [%d] get stats for packet type 0x%04x requested\n", unit->num, packet_type));
212 ForeachNodeSafe(&(unit->trackers), tracker, tracker_next) {
213 if (tracker->packet_type == packet_type) {
214 D(bug("[tap] [%d] found it, copying to caller\n", unit->num));
216 CopyMem(&(tracker->stats), req->ios2_StatData, sizeof(struct Sana2PacketTypeStats));
218 return TRUE;
222 D(bug("[tap] [%d] not tracking this type\n", unit->num));
224 req->ios2_Req.io_Error = S2ERR_BAD_STATE;
225 req->ios2_WireError = S2WERR_NOT_TRACKED;
227 return TRUE;
230 static BOOL tap_get_global_stats(struct IOSana2Req *req, struct tap_unit *unit) {
231 D(bug("[tap] [%d] returning global stats\n", unit->num));
233 CopyMem(&(unit->stats), req->ios2_StatData, sizeof(struct Sana2DeviceStats));
235 return TRUE;
238 static BOOL tap_broadcast(struct IOSana2Req *req, struct tap_unit *unit) {
239 /* just fill in the broadcast address as the dest, and write as normal */
240 char *addr = req->ios2_DstAddr;
241 *((ULONG *) addr) = 0xffffffff;
242 *((UWORD *) (addr + 4)) = 0xffff;
244 return tap_write(req, unit);
247 void tap_handle_request(struct IOSana2Req *req) {
248 struct tap_unit *unit = (struct tap_unit *) req->ios2_Req.io_Unit;
249 BOOL completed = FALSE;
251 switch (req->ios2_Req.io_Command) {
252 #if NEWSTYLE_DEVICE
253 case NSCMD_DEVICEQUERY:
255 struct NSDeviceQueryResult *d;
256 LONG error = 0;
257 struct IOStdReq *iotd;
258 iotd = (struct IOStdReq *)req;
259 D(bug("[tap] [%d] NSCMD_DEVICEQUERY\n", unit->num));
260 if(iotd->io_Length >= sizeof(struct NSDeviceQueryResult))
262 if((d = (struct NSDeviceQueryResult *)iotd->io_Data))
264 if ((d->DevQueryFormat == 0) && (d->SizeAvailable == 0))
266 d->SizeAvailable = sizeof(struct NSDeviceQueryResult);
267 d->DeviceType = NSDEVTYPE_SANA2;
268 d->DeviceSubType = 0;
269 d->SupportedCommands = (UWORD *)tap_supported_commands;
270 iotd->io_Actual = sizeof(struct NSDeviceQueryResult);
271 } else error = IOERR_BADLENGTH;
272 } else error = IOERR_BADADDRESS;
273 } else error = IOERR_BADLENGTH;
274 iotd->io_Error = error;
275 completed = error ? FALSE : TRUE;
276 break;
278 #endif
279 case S2_DEVICEQUERY:
280 D(bug("[tap] [%d] S2_DEVICEQUERY\n", unit->num));
281 completed = tap_device_query(req, unit);
282 break;
284 case S2_GETSTATIONADDRESS:
285 D(bug("[tap] [%d] S2_GETSTATIONADDRESS\n", unit->num));
286 completed = tap_get_station_address(req, unit);
287 break;
289 case S2_CONFIGINTERFACE:
290 D(bug("[tap] [%d] S2_CONFIGINTERFACE\n", unit->num));
291 completed = tap_config_interface(req, unit);
292 break;
294 case S2_ONLINE:
295 D(bug("[tap] [%d] S2_ONLINE\n", unit->num));
296 completed = tap_online(req, unit);
297 break;
299 case S2_OFFLINE:
300 D(bug("[tap] [%d] S2_OFFLINE\n", unit->num));
301 completed = tap_offline(req, unit);
302 break;
304 case CMD_READ:
305 D(bug("[tap] [%d] CMD_READ\n", unit->num));
306 completed = tap_read(req, unit);
307 break;
309 case CMD_WRITE:
310 D(bug("[tap] [%d] CMD_WRITE\n", unit->num));
311 completed = tap_write(req, unit);
312 break;
314 case CMD_FLUSH:
315 D(bug("[tap] [%d] CMD_FLUSH\n", unit->num));
316 break;
318 case S2_BROADCAST:
319 D(bug("[tap] [%d] S2_BROADCAST\n", unit->num));
320 completed = tap_broadcast(req, unit);
321 break;
323 case S2_TRACKTYPE:
324 D(bug("[tap] [%d] S2_TRACKTYPE\n", unit->num));
325 completed = tap_track_type(req, unit);
326 break;
328 case S2_UNTRACKTYPE:
329 D(bug("[tap] [%d] S2_UNTRACKTYPE\n", unit->num));
330 completed = tap_untrack_type(req, unit);
331 break;
333 case S2_GETTYPESTATS:
334 D(bug("[tap] [%d] S2_GETTYPESTATS\n", unit->num));
335 completed = tap_get_type_stats(req, unit);
336 break;
338 case S2_GETGLOBALSTATS:
339 D(bug("[tap] [%d] S2_GETGLOBALSTATS\n", unit->num));
340 completed = tap_get_global_stats(req, unit);
341 break;
343 default:
344 D(bug("[tap] [%d] unknown command (%d)\n", unit->num, req->ios2_Req.io_Command));
345 req->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
346 completed = TRUE;
347 break;
350 if (completed && ! (req->ios2_Req.io_Flags & IOF_QUICK))
351 ReplyMsg((APTR) req);