2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: Unix filedescriptor/socket IO
10 #define timeval sys_timeval /* We don't want the unix timeval to interfere with the AROS one */
11 #include <sys/types.h>
15 #include <sys/ioctl.h>
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>
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>
58 #include LC_LIBDEFS_FILE
60 #include <aros/asmcall.h>
62 #define HostLibBase data->HostLibBase
63 #define KernelBase data->KernelBase
67 struct sockaddr ifaddr
;
71 /*****************************************************************************************
74 moHidd_UnixIO_OpenPacket
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);
85 Open a UNIX packet descriptor to a raw network interface
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
94 A number of the opened packet descriptor or -1 for an error.
103 moHidd_UnixIO_ClosePacket
109 *****************************************************************************************/
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
))) {
128 sd
= SysIFace
->socket(PF_PACKET
, SOCK_RAW
, htons(ETH_P_ALL
));
132 D(bug("%s: sd=%d\n", __func__
, sd
));
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) {
152 D(bug("%s: sd=%d bind\n", __func__
, sd
));
155 D(bug("%s: sd=%d SIOCGIFHWADDR\n", __func__
, sd
));
158 D(bug("%s: sd=%d SIOCGIFINDEX, errno=%d\n", __func__
, sd
, *(SysIFace
->__error())));
161 D(bug("%s: sd=%d SIOCSIFFLAGS, errno=%d\n", __func__
, sd
, *(SysIFace
->__error())));
164 D(bug("%s: sd=%d SIOCGIFFLAGS, errno=%d\n", __func__
, sd
, *(SysIFace
->__error())));
176 IPTR
UXIO__Hidd_UnixIO__OpenPacket(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_UnixIO_OpenPacket
*msg
)
178 struct unixio_base
*data
= UD(cl
);
181 D(bug("[UnixIO] OpenFile(%s, 0x%04X, %o)\n", msg
->FileName
, msg
->Flags
, msg
->Mode
));
186 retval
= (IPTR
)linux_OpenPacket(data
->SysIFace
, msg
->Interface
);
193 *msg
->ErrNoPtr
= *data
->uio_Public
.uio_ErrnoPtr
;
197 D(bug("[UnixIO] PD is %d, errno is %d\n", retval
, *data
->uio_Public
.uio_ErrnoPtr
));
202 /*****************************************************************************************
205 moHidd_UnixIO_ClosePacket
208 OOP_DoMethod(OOP_Object *obj, struct pHidd_UnixIO_ClosePacket *msg);
210 int Hidd_UnixIO_ClosePacket (OOP_Object *obj, int fd, int *errno_ptr);
216 Close a UNIX packet descriptor.
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.
225 0 in case of success and -1 on failure.
228 Despite there's no return value, error code still can be set.
235 moHidd_UnixIO_OpenPacket
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
);
249 struct uioPacket
*pd
= msg
->PD
;
253 ret
= data
->SysIFace
->close(pd
->fd
);
257 *msg
->ErrNoPtr
= *data
->uio_Public
.uio_ErrnoPtr
;
267 /*****************************************************************************************
270 moHidd_UnixIO_RecvPacket
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);
281 Read packet from a Unix packet descriptor
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.
292 Number of bytes actually read or -1 if error happened.
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.
306 moHidd_UnixIO_SendPacket
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
);
317 volatile int err
= EINVAL
;
321 struct uioPacket
*pd
= msg
->PD
;
322 int user
= !KrnIsSuper();
330 retval
= data
->SysIFace
->recvfrom(pd
->fd
, (void *)msg
->Buffer
, (size_t)msg
->Length
, MSG_DONTWAIT
, NULL
, NULL
);
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
));
339 } while((err
== EINTR
) || (err
== EAGAIN
));
342 #endif /* HOST_OS_linux */
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
));
356 /*****************************************************************************************
359 moHidd_UnixIO_SendPacket
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);
370 Write data to a UNIX packet descriptor.
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.
381 Number of bytes actually written or -1 if error happened.
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.
395 moHidd_UnixIO_RecvPacket
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
);
406 volatile int err
= EINVAL
;
410 struct uioPacket
*pd
= msg
->PD
;
411 int user
= !KrnIsSuper();
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
));
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
));
435 } while((retval
< 1) && ((err
== EINTR
) || (err
== EAGAIN
) || (err
== 0)));
438 #endif /* HOST_OS_linux */
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
));
452 IPTR
UXIO__Hidd_UnixIO__PacketGetFileDescriptor(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_UnixIO_PacketGetFileDescriptor
*msg
)
456 struct uioPacket
*pd
= msg
->PD
;
464 IPTR
UXIO__Hidd_UnixIO__PacketGetMACAddress(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_UnixIO_PacketGetMACAddress
*msg
)
468 struct uioPacket
*pd
= msg
->PD
;
471 memcpy(msg
->MACAddress
, pd
->ifaddr
.sa_data
, 6);