make.tmpl: add missing compiler attribute to build_progs
[AROS.git] / arch / all-unix / hidd / unixio / unixpkt_class.c
blob267013a4a14fc737527c13fbe9b675b1c1f0d9f3
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Unix filedescriptor/socket IO
6 Lang: english
7 */
9 /* Unix includes */
10 #define timeval sys_timeval /* We don't want the unix timeval to interfere with the AROS one */
11 #include <sys/types.h>
12 #include <fcntl.h>
13 #include <unistd.h>
14 #include <sys/stat.h>
15 #include <sys/ioctl.h>
16 #include <signal.h>
17 #include <string.h>
18 #include <errno.h>
20 #undef timeval
22 #define SDEBUG 0
23 #define DEBUG 0
24 #include <aros/debug.h>
26 #define __OOP_NOATTRBASES__
28 #include <exec/types.h>
29 #include <exec/lists.h>
30 #include <exec/interrupts.h>
31 #include <exec/execbase.h>
32 #include <exec/semaphores.h>
33 #include <exec/memory.h>
34 #include <exec/resident.h>
35 #include <exec/tasks.h>
36 #include <exec/ports.h>
37 #include <exec/nodes.h>
38 #include <intuition/intuition.h>
39 #include <utility/tagitem.h>
40 #include <utility/hooks.h>
41 #include <hidd/unixio.h>
42 #include <aros/asmcall.h>
43 #include <aros/symbolsets.h>
45 #include <oop/oop.h>
46 #include <proto/exec.h>
47 #include <proto/hostlib.h>
48 #include <proto/intuition.h>
49 #include <proto/kernel.h>
50 #include <proto/oop.h>
51 #include <proto/utility.h>
52 #include <proto/alib.h>
54 #include <devices/timer.h>
56 #include "unixio.h"
58 #include LC_LIBDEFS_FILE
60 #include <aros/asmcall.h>
62 #define HostLibBase data->HostLibBase
63 #define KernelBase data->KernelBase
65 struct uioPacket {
66 int fd;
67 struct sockaddr ifaddr;
68 short ifindex;
71 /*****************************************************************************************
73 NAME
74 moHidd_UnixIO_OpenPacket
76 SYNOPSIS
77 OOP_DoMethod(OOP_Object *obj, struct pHidd_UnixIO_OpenPacket *msg);
79 int Hidd_UnixIO_OpenPacket (OOP_Object *obj, const char *Interface, int *errno_ptr);
81 LOCATION
82 unixio.hidd
84 FUNCTION
85 Open a UNIX packet descriptor to a raw network interface
87 INPUTS
88 obj - An pointer to a UnixIO object
89 interface - Name of a network interace (ie eth0)
90 errno_ptr - An optional pointer to a location where error code (value of
91 UNIX errno variable) will be written
93 RESULT
94 A number of the opened packet descriptor or -1 for an error.
96 NOTES
98 EXAMPLE
100 BUGS
102 SEE ALSO
103 moHidd_UnixIO_ClosePacket
105 INTERNALS
107 TODO
109 *****************************************************************************************/
111 #ifdef HOST_OS_linux
112 #include <net/if.h>
113 #include <linux/if_ether.h>
114 #include <linux/if_packet.h>
115 #include <stdio.h> // for snprintf
117 #define htons(x) AROS_WORD2BE(x)
119 struct uioPacket *linux_OpenPacket(struct LibCInterface *SysIFace, const char *interface)
121 struct ifreq ifr = {};
122 struct uioPacket *pd;
124 D(bug("%s: interface='%s'\n", __func__, interface));
125 if (strlen(interface) <= (sizeof(ifr.ifr_name)-1)) {
126 if ((pd = AllocVec(sizeof(*pd), MEMF_ANY | MEMF_CLEAR))) {
127 int sd;
128 sd = SysIFace->socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
130 pd->fd = sd;
132 D(bug("%s: sd=%d\n", __func__, sd));
133 if (sd >= 0) {
135 strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name));
136 ifr.ifr_name[sizeof(ifr.ifr_name)-1]=0;
138 if (SysIFace->ioctl(sd, SIOCGIFFLAGS, &ifr) >= 0) {
139 ifr.ifr_flags |= IFF_PROMISC;
140 if (SysIFace->ioctl(sd, SIOCSIFFLAGS, &ifr) >= 0) {
141 if (SysIFace->ioctl(sd, SIOCGIFINDEX, &ifr) >= 0) {
142 pd->ifindex = ifr.ifr_ifindex;
143 if (SysIFace->ioctl(sd, SIOCGIFHWADDR, &ifr) >= 0) {
144 pd->ifaddr = ifr.ifr_hwaddr;
145 struct sockaddr_ll sll = {};
146 sll.sll_family = AF_PACKET;
147 sll.sll_ifindex = pd->ifindex;
148 sll.sll_protocol = htons(ETH_P_ALL);
149 if (SysIFace->bind(sd, (struct sockaddr *)&sll, sizeof(sll)) >= 0) {
150 return pd;
151 } else {
152 D(bug("%s: sd=%d bind\n", __func__, sd));
154 } else {
155 D(bug("%s: sd=%d SIOCGIFHWADDR\n", __func__, sd));
157 } else {
158 D(bug("%s: sd=%d SIOCGIFINDEX, errno=%d\n", __func__, sd, *(SysIFace->__error())));
160 } else {
161 D(bug("%s: sd=%d SIOCSIFFLAGS, errno=%d\n", __func__, sd, *(SysIFace->__error())));
163 } else {
164 D(bug("%s: sd=%d SIOCGIFFLAGS, errno=%d\n", __func__, sd, *(SysIFace->__error())));
166 SysIFace->close(sd);
168 FreeVec(pd);
172 return NULL;
174 #endif
176 IPTR UXIO__Hidd_UnixIO__OpenPacket(OOP_Class *cl, OOP_Object *o, struct pHidd_UnixIO_OpenPacket *msg)
178 struct unixio_base *data = UD(cl);
179 IPTR retval;
181 D(bug("[UnixIO] OpenFile(%s, 0x%04X, %o)\n", msg->FileName, msg->Flags, msg->Mode));
183 HostLib_Lock();
185 #ifdef HOST_OS_linux
186 retval = (IPTR)linux_OpenPacket(data->SysIFace, msg->Interface);
187 AROS_HOST_BARRIER
188 #else
189 retval = (IPTR)NULL;
190 #endif
192 if (msg->ErrNoPtr)
193 *msg->ErrNoPtr = *data->uio_Public.uio_ErrnoPtr;
195 HostLib_Unlock();
197 D(bug("[UnixIO] PD is %d, errno is %d\n", retval, *data->uio_Public.uio_ErrnoPtr));
199 return retval;
202 /*****************************************************************************************
204 NAME
205 moHidd_UnixIO_ClosePacket
207 SYNOPSIS
208 OOP_DoMethod(OOP_Object *obj, struct pHidd_UnixIO_ClosePacket *msg);
210 int Hidd_UnixIO_ClosePacket (OOP_Object *obj, int fd, int *errno_ptr);
212 LOCATION
213 unixio.hidd
215 FUNCTION
216 Close a UNIX packet descriptor.
218 INPUTS
219 obj - A pointer to a UnixIO object.
220 pd - A packet descriptor to close.
221 errno_ptr - An optional pointer to a location where error code (a value of UNIX
222 errno variable) will be written.
224 RESULT
225 0 in case of success and -1 on failure.
227 NOTES
228 Despite there's no return value, error code still can be set.
230 EXAMPLE
232 BUGS
234 SEE ALSO
235 moHidd_UnixIO_OpenPacket
237 INTERNALS
239 TODO
241 *****************************************************************************************/
242 IPTR UXIO__Hidd_UnixIO__ClosePacket(OOP_Class *cl, OOP_Object *o, struct pHidd_UnixIO_ClosePacket *msg)
244 struct unixio_base *data = UD(cl);
245 int ret = 0;
247 if (msg->PD)
249 struct uioPacket *pd = msg->PD;
251 HostLib_Lock();
253 ret = data->SysIFace->close(pd->fd);
254 AROS_HOST_BARRIER
256 if (msg->ErrNoPtr)
257 *msg->ErrNoPtr = *data->uio_Public.uio_ErrnoPtr;
259 HostLib_Unlock();
261 FreeVec(pd);
264 return ret;
267 /*****************************************************************************************
269 NAME
270 moHidd_UnixIO_RecvPacket
272 SYNOPSIS
273 OOP_DoMethod(OOP_Object *obj, struct pHidd_UnixIO_RecvPacket *msg);
275 int Hidd_UnixIO_RecvPacket(OOP_Object *obj, int fd, void *buffer, int count, int *errno_ptr);
277 LOCATION
278 unixio.hidd
280 FUNCTION
281 Read packet from a Unix packet descriptor
283 INPUTS
284 obj - A pointer to a UnixIO object.
285 pd - A packet descriptor to read from.
286 buffer - A pointer to a buffer for data.
287 count - Number of bytes to read.
288 errno_ptr - An optional pointer to a location where error code (a value of UNIX
289 errno variable) will be written.
291 RESULT
292 Number of bytes actually read or -1 if error happened.
294 NOTES
295 If there's no errno pointer supplied read operation will be automatically repeated if one
296 of EINTR or EAGAIN error happens. If you supplied valid own errno_ptr you should be ready
297 to handle these conditions yourself.
299 This method can be called from within interrupts.
301 EXAMPLE
303 BUGS
305 SEE ALSO
306 moHidd_UnixIO_SendPacket
308 INTERNALS
310 TODO
312 *****************************************************************************************/
313 IPTR UXIO__Hidd_UnixIO__RecvPacket(OOP_Class *cl, OOP_Object *o, struct pHidd_UnixIO_RecvPacket *msg)
315 struct unixio_base *data = UD(cl);
316 int retval = -1;
317 volatile int err = EINVAL;
319 if (msg->PD)
321 struct uioPacket *pd = msg->PD;
322 int user = !KrnIsSuper();
324 if (user)
325 HostLib_Lock();
327 #ifdef HOST_OS_linux
330 retval = data->SysIFace->recvfrom(pd->fd, (void *)msg->Buffer, (size_t)msg->Length, MSG_DONTWAIT, NULL, NULL);
331 AROS_HOST_BARRIER
333 err = *data->uio_Public.uio_ErrnoPtr;
334 D(kprintf(" UXIO__Hidd_UnixIO__RecvPacket: retval %d errno %d buff %x count %d\n", retval, err, msg->Buffer, msg->Length));
336 if (msg->ErrNoPtr)
337 break;
339 } while((err == EINTR) || (err == EAGAIN));
340 #else
341 (void)pd;
342 #endif /* HOST_OS_linux */
344 if (user)
345 HostLib_Unlock();
348 if (msg->ErrNoPtr)
349 *msg->ErrNoPtr = err;
351 D(if (retval == -1) kprintf("UXIO__Hidd_UnixIO__RecvPacket: errno %d buff %x count %d\n", err, msg->Buffer, msg->Length));
353 return retval;
356 /*****************************************************************************************
358 NAME
359 moHidd_UnixIO_SendPacket
361 SYNOPSIS
362 OOP_DoMethod(OOP_Object *obj, struct pHidd_UnixIO_SendPacket *msg);
364 int Hidd_UnixIO_SendPacket(OOP_Object *obj, int fd, void *buffer, int count, int *errno_ptr);
366 LOCATION
367 unixio.hidd
369 FUNCTION
370 Write data to a UNIX packet descriptor.
372 INPUTS
373 obj - A pointer to a UnixIO object.
374 pd - A packet descriptor to write to.
375 buffer - A pointer to a buffer containing data.
376 count - Number of bytes to write.
377 errno_ptr - An optional pointer to a location where error code (a value of UNIX
378 errno variable) will be written.
380 RESULT
381 Number of bytes actually written or -1 if error happened.
383 NOTES
384 If there's no errno pointer supplied read operation will be automatically repeated if one
385 of EINTR or EAGAIN error happens. If you supplied valid own errno_ptr you should be ready
386 to handle these conditions yourself.
388 This method can be called from within interrupts.
390 EXAMPLE
392 BUGS
394 SEE ALSO
395 moHidd_UnixIO_RecvPacket
397 INTERNALS
399 TODO
401 *****************************************************************************************/
402 IPTR UXIO__Hidd_UnixIO__SendPacket(OOP_Class *cl, OOP_Object *o, struct pHidd_UnixIO_SendPacket *msg)
404 struct unixio_base *data = UD(cl);
405 int retval = -1;
406 volatile int err = EINVAL;
408 if (msg->PD)
410 struct uioPacket *pd = msg->PD;
411 int user = !KrnIsSuper();
413 if (user)
414 HostLib_Lock();
416 #ifdef HOST_OS_linux
417 struct sockaddr_ll device = {};
419 device.sll_ifindex = pd->ifindex;
420 device.sll_family = AF_PACKET;
421 memcpy(device.sll_addr, pd->ifaddr.sa_data, 6);
422 device.sll_halen = htons(6);
426 retval = data->SysIFace->sendto(pd->fd, (const void *)msg->Buffer, (size_t)msg->Length, 0, (struct sockaddr *)&device, sizeof(device));
427 AROS_HOST_BARRIER
429 err = *data->uio_Public.uio_ErrnoPtr;
430 D(kprintf(" UXIO__Hidd_UnixIO__SendPacket: retval %d errno %d buff %x count %d\n", retval, err, msg->Buffer, msg->Length));
432 if (msg->ErrNoPtr)
433 break;
435 } while((retval < 1) && ((err == EINTR) || (err == EAGAIN) || (err == 0)));
436 #else
437 (void)pd;
438 #endif /* HOST_OS_linux */
440 if (user)
441 HostLib_Unlock();
444 if (msg->ErrNoPtr)
445 *msg->ErrNoPtr = err;
447 D(if (retval == -1) kprintf("UXIO__Hidd_UnixIO__SendPacket: errno %d buff %x count %d\n", err, msg->Buffer, msg->Length));
449 return retval;
452 IPTR UXIO__Hidd_UnixIO__PacketGetFileDescriptor(OOP_Class *cl, OOP_Object *o, struct pHidd_UnixIO_PacketGetFileDescriptor *msg)
454 if (msg->PD)
456 struct uioPacket *pd = msg->PD;
458 return pd->fd;
461 return -1;
464 IPTR UXIO__Hidd_UnixIO__PacketGetMACAddress(OOP_Class *cl, OOP_Object *o, struct pHidd_UnixIO_PacketGetMACAddress *msg)
466 if (msg->PD)
468 struct uioPacket *pd = msg->PD;
470 if (msg->MACAddress)
471 memcpy(msg->MACAddress, pd->ifaddr.sa_data, 6);
473 return 6;
476 return -1;