unix/unixio.hidd: Replace snprintf() with strncpy
[AROS.git] / arch / all-unix / hidd / unixio / unixpkt_class.c
blobee01fdd68dc8d3e8fbdc167c0c8d771906c4e1a0
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 #endif /* HOST_OS_linux */
342 if (user)
343 HostLib_Unlock();
346 if (msg->ErrNoPtr)
347 *msg->ErrNoPtr = err;
349 D(if (retval == -1) kprintf("UXIO__Hidd_UnixIO__RecvPacket: errno %d buff %x count %d\n", err, msg->Buffer, msg->Length));
351 return retval;
354 /*****************************************************************************************
356 NAME
357 moHidd_UnixIO_SendPacket
359 SYNOPSIS
360 OOP_DoMethod(OOP_Object *obj, struct pHidd_UnixIO_SendPacket *msg);
362 int Hidd_UnixIO_SendPacket(OOP_Object *obj, int fd, void *buffer, int count, int *errno_ptr);
364 LOCATION
365 unixio.hidd
367 FUNCTION
368 Write data to a UNIX packet descriptor.
370 INPUTS
371 obj - A pointer to a UnixIO object.
372 pd - A packet descriptor to write to.
373 buffer - A pointer to a buffer containing data.
374 count - Number of bytes to write.
375 errno_ptr - An optional pointer to a location where error code (a value of UNIX
376 errno variable) will be written.
378 RESULT
379 Number of bytes actually written or -1 if error happened.
381 NOTES
382 If there's no errno pointer supplied read operation will be automatically repeated if one
383 of EINTR or EAGAIN error happens. If you supplied valid own errno_ptr you should be ready
384 to handle these conditions yourself.
386 This method can be called from within interrupts.
388 EXAMPLE
390 BUGS
392 SEE ALSO
393 moHidd_UnixIO_RecvPacket
395 INTERNALS
397 TODO
399 *****************************************************************************************/
400 IPTR UXIO__Hidd_UnixIO__SendPacket(OOP_Class *cl, OOP_Object *o, struct pHidd_UnixIO_SendPacket *msg)
402 struct unixio_base *data = UD(cl);
403 int retval = -1;
404 volatile int err = EINVAL;
406 if (msg->PD)
408 struct uioPacket *pd = msg->PD;
409 int user = !KrnIsSuper();
411 if (user)
412 HostLib_Lock();
414 #ifdef HOST_OS_linux
415 struct sockaddr_ll device = {};
417 device.sll_ifindex = pd->ifindex;
418 device.sll_family = AF_PACKET;
419 memcpy(device.sll_addr, pd->ifaddr.sa_data, 6);
420 device.sll_halen = htons(6);
424 retval = data->SysIFace->sendto(pd->fd, (const void *)msg->Buffer, (size_t)msg->Length, 0, (struct sockaddr *)&device, sizeof(device));
425 AROS_HOST_BARRIER
427 err = *data->uio_Public.uio_ErrnoPtr;
428 D(kprintf(" UXIO__Hidd_UnixIO__SendPacket: retval %d errno %d buff %x count %d\n", retval, err, msg->Buffer, msg->Length));
430 if (msg->ErrNoPtr)
431 break;
433 } while((retval < 1) && ((err == EINTR) || (err == EAGAIN) || (err == 0)));
434 #endif /* HOST_OS_linux */
436 if (user)
437 HostLib_Unlock();
440 if (msg->ErrNoPtr)
441 *msg->ErrNoPtr = err;
443 D(if (retval == -1) kprintf("UXIO__Hidd_UnixIO__SendPacket: errno %d buff %x count %d\n", err, msg->Buffer, msg->Length));
445 return retval;
448 IPTR UXIO__Hidd_UnixIO__PacketGetFileDescriptor(OOP_Class *cl, OOP_Object *o, struct pHidd_UnixIO_PacketGetFileDescriptor *msg)
450 if (msg->PD)
452 struct uioPacket *pd = msg->PD;
454 return pd->fd;
457 return -1;
460 IPTR UXIO__Hidd_UnixIO__PacketGetMACAddress(OOP_Class *cl, OOP_Object *o, struct pHidd_UnixIO_PacketGetMACAddress *msg)
462 if (msg->PD)
464 struct uioPacket *pd = msg->PD;
466 if (msg->MACAddress)
467 memcpy(msg->MACAddress, pd->ifaddr.sa_data, 6);
469 return 6;
472 return -1;