forked from Imagelibrary/rtems
Made to compile after hacking tftp driver into beginnings of a mini-filesystem.
This commit is contained in:
@@ -13,6 +13,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -25,6 +26,12 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#ifndef set_errno_and_return_minus_one
|
||||||
|
#define set_errno_and_return_minus_one( _error ) \
|
||||||
|
do { errno = (_error); return -1; } while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Range of UDP ports to try
|
* Range of UDP ports to try
|
||||||
*/
|
*/
|
||||||
@@ -136,6 +143,50 @@ static rtems_id tftp_mutex;
|
|||||||
static int nStreams;
|
static int nStreams;
|
||||||
static struct tftpStream ** volatile tftpStreams;
|
static struct tftpStream ** volatile tftpStreams;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
rtems_id tftp_mutex;
|
||||||
|
int nStreams;
|
||||||
|
struct tftpStream ** volatile tftpStreams;
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry;
|
||||||
|
} tftp_fs_info;
|
||||||
|
|
||||||
|
int rtems_tftp_mount_me(
|
||||||
|
rtems_filesystem_mount_table_entry_t *temp_mt_entry
|
||||||
|
)
|
||||||
|
{
|
||||||
|
tftp_fs_info *fs_info;
|
||||||
|
rtems_status_code sc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate stuff for this file system.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fs_info = calloc( 1, sizeof( tftp_fs_info ));
|
||||||
|
if ( !fs_info )
|
||||||
|
set_errno_and_return_minus_one( ENOMEM );
|
||||||
|
|
||||||
|
temp_mt_entry->fs_info = fs_info;
|
||||||
|
temp_mt_entry->mt_fs_root.node_access = fs_info;
|
||||||
|
|
||||||
|
|
||||||
|
sc = rtems_semaphore_create (
|
||||||
|
rtems_build_name('T', 'F', 'T', 'P'),
|
||||||
|
1,
|
||||||
|
RTEMS_FIFO |
|
||||||
|
RTEMS_BINARY_SEMAPHORE |
|
||||||
|
RTEMS_NO_INHERIT_PRIORITY |
|
||||||
|
RTEMS_NO_PRIORITY_CEILING |
|
||||||
|
RTEMS_LOCAL,
|
||||||
|
0,
|
||||||
|
&fs_info->tftp_mutex
|
||||||
|
);
|
||||||
|
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one( ENOMEM ); /* ??? */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the TFTP driver
|
* Initialize the TFTP driver
|
||||||
*/
|
*/
|
||||||
@@ -147,19 +198,7 @@ rtems_device_driver rtems_tftp_initialize(
|
|||||||
void *pargp
|
void *pargp
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
rtems_status_code sc;
|
|
||||||
|
|
||||||
sc = rtems_semaphore_create (rtems_build_name('T', 'F', 'T', 'P'),
|
|
||||||
1,
|
|
||||||
RTEMS_FIFO |
|
|
||||||
RTEMS_BINARY_SEMAPHORE |
|
|
||||||
RTEMS_NO_INHERIT_PRIORITY |
|
|
||||||
RTEMS_NO_PRIORITY_CEILING |
|
|
||||||
RTEMS_LOCAL,
|
|
||||||
0,
|
|
||||||
&tftp_mutex);
|
|
||||||
if (sc != RTEMS_SUCCESSFUL)
|
|
||||||
return sc;
|
|
||||||
/* XXX change to a mount */
|
/* XXX change to a mount */
|
||||||
rtems_io_register_name (TFTP_PATHNAME_PREFIX, major, minor);
|
rtems_io_register_name (TFTP_PATHNAME_PREFIX, major, minor);
|
||||||
return RTEMS_SUCCESSFUL;
|
return RTEMS_SUCCESSFUL;
|
||||||
@@ -293,39 +332,44 @@ releaseStream (int s)
|
|||||||
rtems_semaphore_release (tftp_mutex);
|
rtems_semaphore_release (tftp_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
int rtems_tftp_evaluate_for_make(
|
||||||
* Open a TFTP stream
|
const char *path, /* IN */
|
||||||
*/
|
rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
|
||||||
rtems_device_driver rtems_tftp_open(
|
const char **name /* OUT */
|
||||||
rtems_device_major_number major,
|
|
||||||
rtems_device_minor_number minor,
|
|
||||||
void *pargp
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
rtems_libio_open_close_args_t *ap = pargp;
|
set_errno_and_return_minus_one( EIO );
|
||||||
struct tftpStream *tp;
|
}
|
||||||
int retryCount;
|
/*
|
||||||
rtems_unsigned32 farAddress;
|
* XXX - Fix return values.
|
||||||
int s;
|
|
||||||
int len;
|
|
||||||
char *cp1, *cp2;
|
|
||||||
char *remoteFilename;
|
|
||||||
rtems_interval now;
|
|
||||||
rtems_status_code sc;
|
|
||||||
|
|
||||||
/* XXX change to eval_path/open */
|
|
||||||
/*
|
|
||||||
* Read-only for now
|
|
||||||
*/
|
*/
|
||||||
if (ap->flags & LIBIO_FLAGS_WRITE)
|
|
||||||
return RTEMS_NOT_IMPLEMENTED;
|
int TFTP_eval_path(
|
||||||
|
const char *pathname, /* IN */
|
||||||
|
int flags, /* IN */
|
||||||
|
rtems_filesystem_location_info_t *pathloc /* IN/OUT */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
rtems_unsigned32 farAddress;
|
||||||
|
int len;
|
||||||
|
const char *remoteFilename;
|
||||||
|
|
||||||
|
tftp_fs_info *fs_info;
|
||||||
|
const char *cp1, *cp2;
|
||||||
|
|
||||||
|
fs_info = pathloc->node_access;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pick apart the name into a host:pathname pair
|
* Pick apart the name into a host:pathname pair
|
||||||
*/
|
*/
|
||||||
if (strlen (ap->iop->pathname) <= strlen (TFTP_PATHNAME_PREFIX))
|
/*
|
||||||
return RTEMS_INVALID_NAME;
|
* XXX - I think this is handled by the caller of
|
||||||
cp2 = ap->iop->pathname + strlen (TFTP_PATHNAME_PREFIX);
|
* the evaluate routine. ? Am I starting at the right
|
||||||
|
* place?
|
||||||
|
*/
|
||||||
|
|
||||||
|
cp2 = pathname+1;
|
||||||
|
|
||||||
if (*cp2 == '/') {
|
if (*cp2 == '/') {
|
||||||
farAddress = rtems_bsdnet_bootp_server_address.s_addr;
|
farAddress = rtems_bsdnet_bootp_server_address.s_addr;
|
||||||
}
|
}
|
||||||
@@ -355,6 +399,37 @@ rtems_device_driver rtems_tftp_open(
|
|||||||
if (strlen (remoteFilename) > (TFTP_BUFSIZE - 10))
|
if (strlen (remoteFilename) > (TFTP_BUFSIZE - 10))
|
||||||
return RTEMS_INVALID_NAME;
|
return RTEMS_INVALID_NAME;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open a TFTP stream
|
||||||
|
*/
|
||||||
|
rtems_device_driver rtems_tftp_open(
|
||||||
|
rtems_device_major_number major,
|
||||||
|
rtems_device_minor_number minor,
|
||||||
|
void *pargp
|
||||||
|
)
|
||||||
|
{
|
||||||
|
rtems_libio_open_close_args_t *ap = pargp;
|
||||||
|
struct tftpStream *tp;
|
||||||
|
int retryCount;
|
||||||
|
rtems_unsigned32 farAddress = 0; /* XXX - node parameter */
|
||||||
|
int s;
|
||||||
|
int len;
|
||||||
|
char *cp1, *cp2;
|
||||||
|
char *remoteFilename = NULL; /* XXX - node parameter */
|
||||||
|
rtems_interval now;
|
||||||
|
rtems_status_code sc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read-only for now
|
||||||
|
*/
|
||||||
|
/* XXX - Move to the open routine */
|
||||||
|
if (ap->flags & LIBIO_FLAGS_WRITE)
|
||||||
|
return RTEMS_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find a free stream
|
* Find a free stream
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#if defined(__rtems__)
|
#if defined(__rtems__)
|
||||||
u_int16_t _getshort(const u_char *src);
|
u_int16_t _getshort(const u_char *src);
|
||||||
u_int32_t _getlong(const u_char *src);
|
u_int32_t _getlong(const u_char *src);
|
||||||
int gethostname (char *name, int namelen);
|
int gethostname (char *name, size_t namelen);
|
||||||
int sethostname (char *name, int namelen);
|
int sethostname (char *name, size_t namelen);
|
||||||
int issetugid (void);
|
int issetugid (void);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ extern int rtems_bsdnet_nameserver_count;
|
|||||||
/*
|
/*
|
||||||
* Some extra prototypes
|
* Some extra prototypes
|
||||||
*/
|
*/
|
||||||
int sethostname (char *name, int namelen);
|
int sethostname (char *name, size_t namelen);
|
||||||
void domaininit (void *);
|
void domaininit (void *);
|
||||||
void ifinit (void *);
|
void ifinit (void *);
|
||||||
void ipintr (void);
|
void ipintr (void);
|
||||||
@@ -174,5 +174,19 @@ void arpintr (void);
|
|||||||
void bootpc_init(void);
|
void bootpc_init(void);
|
||||||
int socket (int, int, int);
|
int socket (int, int, int);
|
||||||
int ioctl (int, unsigned long, ...);
|
int ioctl (int, unsigned long, ...);
|
||||||
|
struct socket *rtems_bsdnet_fdToSocket (int fd);
|
||||||
|
int rtems_bsdnet_makeFdForSocket (struct socket *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Events used by networking routines.
|
||||||
|
* Everything will break if the application
|
||||||
|
* tries to use these events or if the `sleep'
|
||||||
|
* events are equal to any of the NETISR * events.
|
||||||
|
*/
|
||||||
|
#define SBWAIT_EVENT RTEMS_EVENT_24
|
||||||
|
#define SOSLEEP_EVENT RTEMS_EVENT_25
|
||||||
|
#define NETISR_IP_EVENT (1 << NETISR_IP)
|
||||||
|
#define NETISR_ARP_EVENT (1 << NETISR_ARP)
|
||||||
|
#define NETISR_EVENTS (NETISR_IP_EVENT|NETISR_ARP_EVENT)
|
||||||
|
|
||||||
#endif /* _RTEMS_BSDNET_INTERNAL_H_ */
|
#endif /* _RTEMS_BSDNET_INTERNAL_H_ */
|
||||||
|
|||||||
171
c/src/exec/libnetworking/rtems/rtems_select.c
Normal file
171
c/src/exec/libnetworking/rtems/rtems_select.c
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio.h>
|
||||||
|
#include <rtems/error.h>
|
||||||
|
#include <rtems/rtems_bsdnet.h>
|
||||||
|
|
||||||
|
#include <sys/errno.h>
|
||||||
|
#include <sys/fcntl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/mbuf.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/socketvar.h>
|
||||||
|
#include <sys/protosw.h>
|
||||||
|
#include <sys/proc.h>
|
||||||
|
#include <sys/filio.h>
|
||||||
|
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/route.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
*********************************************************************
|
||||||
|
* RTEMS implementation of select() system call *
|
||||||
|
*********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This implementation is quite restricted:
|
||||||
|
* Works on sockets only -- no support for other devices!
|
||||||
|
* A given socket can be in a read-select or a read/recv* by only
|
||||||
|
* one task at a time.
|
||||||
|
* A given socket can be in a write-select or a write/send* by only
|
||||||
|
* one task at a time.
|
||||||
|
*
|
||||||
|
* NOTE - select() is a very expensive system call. It should be avoided
|
||||||
|
* if at all possible. In many cases, rewriting the application
|
||||||
|
* to use multiple tasks (one per socket) is a better solution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static __inline int imin(int a, int b) { return (a < b ? a : b); }
|
||||||
|
|
||||||
|
static int
|
||||||
|
socket_select (struct socket *so, int which, rtems_id tid)
|
||||||
|
{
|
||||||
|
switch (which) {
|
||||||
|
|
||||||
|
case FREAD:
|
||||||
|
if (soreadable(so))
|
||||||
|
return (1);
|
||||||
|
so->so_rcv.sb_sel.si_pid = tid;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FWRITE:
|
||||||
|
if (sowriteable(so))
|
||||||
|
return (1);
|
||||||
|
so->so_snd.sb_sel.si_pid = tid;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
if (so->so_oobmark || (so->so_state & SS_RCVATMARK))
|
||||||
|
return (1);
|
||||||
|
so->so_rcv.sb_sel.si_pid = tid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
selscan (rtems_id tid, fd_mask **ibits, fd_mask **obits, int nfd, int *retval)
|
||||||
|
{
|
||||||
|
struct socket *so;
|
||||||
|
int msk, i, fd;
|
||||||
|
fd_mask bits, bit;
|
||||||
|
int n = 0;
|
||||||
|
static int flag[3] = { FREAD, FWRITE, 0 };
|
||||||
|
|
||||||
|
for (msk = 0; msk < 3; msk++) {
|
||||||
|
if (ibits[msk] == NULL)
|
||||||
|
continue;
|
||||||
|
for (i = 0; i < nfd; i += NFDBITS) {
|
||||||
|
bits = ibits[msk][i/NFDBITS];
|
||||||
|
for (fd = i, bit = 1 ; bits && (fd < nfd) ; fd++, bit <<= 1) {
|
||||||
|
if ((bits & bit) == 0)
|
||||||
|
continue;
|
||||||
|
bits &= ~bit;
|
||||||
|
so = rtems_bsdnet_fdToSocket (fd);
|
||||||
|
if (so == NULL)
|
||||||
|
return (EBADF);
|
||||||
|
if (socket_select (so, flag[msk], tid)) {
|
||||||
|
obits[msk][fd/NFDBITS] |=
|
||||||
|
(1 << (fd % NFDBITS));
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*retval = n;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *tv)
|
||||||
|
{
|
||||||
|
fd_mask *ibits[3], *obits[3];
|
||||||
|
fd_set ob[3];
|
||||||
|
int error, timo;
|
||||||
|
int retval;
|
||||||
|
rtems_id tid;
|
||||||
|
rtems_interval then, now;
|
||||||
|
rtems_event_set events;
|
||||||
|
|
||||||
|
if (nfds < 0)
|
||||||
|
return (EINVAL);
|
||||||
|
if (tv) {
|
||||||
|
timo = tv->tv_sec * hz + tv->tv_usec / tick;
|
||||||
|
if (timo == 0)
|
||||||
|
timo = 1;
|
||||||
|
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
timo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define getbits(name,i) if (name) { \
|
||||||
|
ibits[i] = &name->fds_bits[0]; \
|
||||||
|
obits[i] = &ob[i].fds_bits[0]; \
|
||||||
|
FD_ZERO(&ob[i]); \
|
||||||
|
} \
|
||||||
|
else ibits[i] = NULL
|
||||||
|
getbits (readfds, 0);
|
||||||
|
getbits (writefds, 1);
|
||||||
|
getbits (exceptfds, 2);
|
||||||
|
#undef getbits
|
||||||
|
|
||||||
|
rtems_task_ident (RTEMS_SELF, 0, &tid);
|
||||||
|
rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
|
||||||
|
for (;;) {
|
||||||
|
rtems_bsdnet_semaphore_obtain ();
|
||||||
|
error = selscan(tid, ibits, obits, nfds, &retval);
|
||||||
|
rtems_bsdnet_semaphore_release ();
|
||||||
|
if (error || retval)
|
||||||
|
break;
|
||||||
|
if (timo) {
|
||||||
|
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
|
||||||
|
timo -= now - then;
|
||||||
|
if (timo <= 0)
|
||||||
|
break;
|
||||||
|
then = now;
|
||||||
|
}
|
||||||
|
rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, timo, &events);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define putbits(name,i) if (name) *name = ob[i]
|
||||||
|
putbits (readfds, 0);
|
||||||
|
putbits (writefds, 1);
|
||||||
|
putbits (exceptfds, 2);
|
||||||
|
#undef putbits
|
||||||
|
if (error) {
|
||||||
|
errno = error;
|
||||||
|
retval = -1;
|
||||||
|
}
|
||||||
|
return (retval);
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
static char *rtems_hostname;
|
static char *rtems_hostname;
|
||||||
|
|
||||||
int
|
int
|
||||||
gethostname (char *name, int namelen)
|
gethostname (char *name, size_t namelen)
|
||||||
{
|
{
|
||||||
char *cp = rtems_hostname;
|
char *cp = rtems_hostname;
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ gethostname (char *name, int namelen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sethostname (char *name, int namelen)
|
sethostname (char *name, size_t namelen)
|
||||||
{
|
{
|
||||||
char *old, *new;
|
char *old, *new;
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -25,6 +26,12 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#ifndef set_errno_and_return_minus_one
|
||||||
|
#define set_errno_and_return_minus_one( _error ) \
|
||||||
|
do { errno = (_error); return -1; } while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Range of UDP ports to try
|
* Range of UDP ports to try
|
||||||
*/
|
*/
|
||||||
@@ -136,6 +143,50 @@ static rtems_id tftp_mutex;
|
|||||||
static int nStreams;
|
static int nStreams;
|
||||||
static struct tftpStream ** volatile tftpStreams;
|
static struct tftpStream ** volatile tftpStreams;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
rtems_id tftp_mutex;
|
||||||
|
int nStreams;
|
||||||
|
struct tftpStream ** volatile tftpStreams;
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry;
|
||||||
|
} tftp_fs_info;
|
||||||
|
|
||||||
|
int rtems_tftp_mount_me(
|
||||||
|
rtems_filesystem_mount_table_entry_t *temp_mt_entry
|
||||||
|
)
|
||||||
|
{
|
||||||
|
tftp_fs_info *fs_info;
|
||||||
|
rtems_status_code sc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate stuff for this file system.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fs_info = calloc( 1, sizeof( tftp_fs_info ));
|
||||||
|
if ( !fs_info )
|
||||||
|
set_errno_and_return_minus_one( ENOMEM );
|
||||||
|
|
||||||
|
temp_mt_entry->fs_info = fs_info;
|
||||||
|
temp_mt_entry->mt_fs_root.node_access = fs_info;
|
||||||
|
|
||||||
|
|
||||||
|
sc = rtems_semaphore_create (
|
||||||
|
rtems_build_name('T', 'F', 'T', 'P'),
|
||||||
|
1,
|
||||||
|
RTEMS_FIFO |
|
||||||
|
RTEMS_BINARY_SEMAPHORE |
|
||||||
|
RTEMS_NO_INHERIT_PRIORITY |
|
||||||
|
RTEMS_NO_PRIORITY_CEILING |
|
||||||
|
RTEMS_LOCAL,
|
||||||
|
0,
|
||||||
|
&fs_info->tftp_mutex
|
||||||
|
);
|
||||||
|
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one( ENOMEM ); /* ??? */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the TFTP driver
|
* Initialize the TFTP driver
|
||||||
*/
|
*/
|
||||||
@@ -147,19 +198,7 @@ rtems_device_driver rtems_tftp_initialize(
|
|||||||
void *pargp
|
void *pargp
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
rtems_status_code sc;
|
|
||||||
|
|
||||||
sc = rtems_semaphore_create (rtems_build_name('T', 'F', 'T', 'P'),
|
|
||||||
1,
|
|
||||||
RTEMS_FIFO |
|
|
||||||
RTEMS_BINARY_SEMAPHORE |
|
|
||||||
RTEMS_NO_INHERIT_PRIORITY |
|
|
||||||
RTEMS_NO_PRIORITY_CEILING |
|
|
||||||
RTEMS_LOCAL,
|
|
||||||
0,
|
|
||||||
&tftp_mutex);
|
|
||||||
if (sc != RTEMS_SUCCESSFUL)
|
|
||||||
return sc;
|
|
||||||
/* XXX change to a mount */
|
/* XXX change to a mount */
|
||||||
rtems_io_register_name (TFTP_PATHNAME_PREFIX, major, minor);
|
rtems_io_register_name (TFTP_PATHNAME_PREFIX, major, minor);
|
||||||
return RTEMS_SUCCESSFUL;
|
return RTEMS_SUCCESSFUL;
|
||||||
@@ -293,39 +332,44 @@ releaseStream (int s)
|
|||||||
rtems_semaphore_release (tftp_mutex);
|
rtems_semaphore_release (tftp_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
int rtems_tftp_evaluate_for_make(
|
||||||
* Open a TFTP stream
|
const char *path, /* IN */
|
||||||
*/
|
rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
|
||||||
rtems_device_driver rtems_tftp_open(
|
const char **name /* OUT */
|
||||||
rtems_device_major_number major,
|
|
||||||
rtems_device_minor_number minor,
|
|
||||||
void *pargp
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
rtems_libio_open_close_args_t *ap = pargp;
|
set_errno_and_return_minus_one( EIO );
|
||||||
struct tftpStream *tp;
|
}
|
||||||
int retryCount;
|
/*
|
||||||
rtems_unsigned32 farAddress;
|
* XXX - Fix return values.
|
||||||
int s;
|
|
||||||
int len;
|
|
||||||
char *cp1, *cp2;
|
|
||||||
char *remoteFilename;
|
|
||||||
rtems_interval now;
|
|
||||||
rtems_status_code sc;
|
|
||||||
|
|
||||||
/* XXX change to eval_path/open */
|
|
||||||
/*
|
|
||||||
* Read-only for now
|
|
||||||
*/
|
*/
|
||||||
if (ap->flags & LIBIO_FLAGS_WRITE)
|
|
||||||
return RTEMS_NOT_IMPLEMENTED;
|
int TFTP_eval_path(
|
||||||
|
const char *pathname, /* IN */
|
||||||
|
int flags, /* IN */
|
||||||
|
rtems_filesystem_location_info_t *pathloc /* IN/OUT */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
rtems_unsigned32 farAddress;
|
||||||
|
int len;
|
||||||
|
const char *remoteFilename;
|
||||||
|
|
||||||
|
tftp_fs_info *fs_info;
|
||||||
|
const char *cp1, *cp2;
|
||||||
|
|
||||||
|
fs_info = pathloc->node_access;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pick apart the name into a host:pathname pair
|
* Pick apart the name into a host:pathname pair
|
||||||
*/
|
*/
|
||||||
if (strlen (ap->iop->pathname) <= strlen (TFTP_PATHNAME_PREFIX))
|
/*
|
||||||
return RTEMS_INVALID_NAME;
|
* XXX - I think this is handled by the caller of
|
||||||
cp2 = ap->iop->pathname + strlen (TFTP_PATHNAME_PREFIX);
|
* the evaluate routine. ? Am I starting at the right
|
||||||
|
* place?
|
||||||
|
*/
|
||||||
|
|
||||||
|
cp2 = pathname+1;
|
||||||
|
|
||||||
if (*cp2 == '/') {
|
if (*cp2 == '/') {
|
||||||
farAddress = rtems_bsdnet_bootp_server_address.s_addr;
|
farAddress = rtems_bsdnet_bootp_server_address.s_addr;
|
||||||
}
|
}
|
||||||
@@ -355,6 +399,37 @@ rtems_device_driver rtems_tftp_open(
|
|||||||
if (strlen (remoteFilename) > (TFTP_BUFSIZE - 10))
|
if (strlen (remoteFilename) > (TFTP_BUFSIZE - 10))
|
||||||
return RTEMS_INVALID_NAME;
|
return RTEMS_INVALID_NAME;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open a TFTP stream
|
||||||
|
*/
|
||||||
|
rtems_device_driver rtems_tftp_open(
|
||||||
|
rtems_device_major_number major,
|
||||||
|
rtems_device_minor_number minor,
|
||||||
|
void *pargp
|
||||||
|
)
|
||||||
|
{
|
||||||
|
rtems_libio_open_close_args_t *ap = pargp;
|
||||||
|
struct tftpStream *tp;
|
||||||
|
int retryCount;
|
||||||
|
rtems_unsigned32 farAddress = 0; /* XXX - node parameter */
|
||||||
|
int s;
|
||||||
|
int len;
|
||||||
|
char *cp1, *cp2;
|
||||||
|
char *remoteFilename = NULL; /* XXX - node parameter */
|
||||||
|
rtems_interval now;
|
||||||
|
rtems_status_code sc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read-only for now
|
||||||
|
*/
|
||||||
|
/* XXX - Move to the open routine */
|
||||||
|
if (ap->flags & LIBIO_FLAGS_WRITE)
|
||||||
|
return RTEMS_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find a free stream
|
* Find a free stream
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#if defined(__rtems__)
|
#if defined(__rtems__)
|
||||||
u_int16_t _getshort(const u_char *src);
|
u_int16_t _getshort(const u_char *src);
|
||||||
u_int32_t _getlong(const u_char *src);
|
u_int32_t _getlong(const u_char *src);
|
||||||
int gethostname (char *name, int namelen);
|
int gethostname (char *name, size_t namelen);
|
||||||
int sethostname (char *name, int namelen);
|
int sethostname (char *name, size_t namelen);
|
||||||
int issetugid (void);
|
int issetugid (void);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ extern int rtems_bsdnet_nameserver_count;
|
|||||||
/*
|
/*
|
||||||
* Some extra prototypes
|
* Some extra prototypes
|
||||||
*/
|
*/
|
||||||
int sethostname (char *name, int namelen);
|
int sethostname (char *name, size_t namelen);
|
||||||
void domaininit (void *);
|
void domaininit (void *);
|
||||||
void ifinit (void *);
|
void ifinit (void *);
|
||||||
void ipintr (void);
|
void ipintr (void);
|
||||||
@@ -174,5 +174,19 @@ void arpintr (void);
|
|||||||
void bootpc_init(void);
|
void bootpc_init(void);
|
||||||
int socket (int, int, int);
|
int socket (int, int, int);
|
||||||
int ioctl (int, unsigned long, ...);
|
int ioctl (int, unsigned long, ...);
|
||||||
|
struct socket *rtems_bsdnet_fdToSocket (int fd);
|
||||||
|
int rtems_bsdnet_makeFdForSocket (struct socket *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Events used by networking routines.
|
||||||
|
* Everything will break if the application
|
||||||
|
* tries to use these events or if the `sleep'
|
||||||
|
* events are equal to any of the NETISR * events.
|
||||||
|
*/
|
||||||
|
#define SBWAIT_EVENT RTEMS_EVENT_24
|
||||||
|
#define SOSLEEP_EVENT RTEMS_EVENT_25
|
||||||
|
#define NETISR_IP_EVENT (1 << NETISR_IP)
|
||||||
|
#define NETISR_ARP_EVENT (1 << NETISR_ARP)
|
||||||
|
#define NETISR_EVENTS (NETISR_IP_EVENT|NETISR_ARP_EVENT)
|
||||||
|
|
||||||
#endif /* _RTEMS_BSDNET_INTERNAL_H_ */
|
#endif /* _RTEMS_BSDNET_INTERNAL_H_ */
|
||||||
|
|||||||
171
c/src/lib/libnetworking/rtems/rtems_select.c
Normal file
171
c/src/lib/libnetworking/rtems/rtems_select.c
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio.h>
|
||||||
|
#include <rtems/error.h>
|
||||||
|
#include <rtems/rtems_bsdnet.h>
|
||||||
|
|
||||||
|
#include <sys/errno.h>
|
||||||
|
#include <sys/fcntl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/mbuf.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/socketvar.h>
|
||||||
|
#include <sys/protosw.h>
|
||||||
|
#include <sys/proc.h>
|
||||||
|
#include <sys/filio.h>
|
||||||
|
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/route.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
*********************************************************************
|
||||||
|
* RTEMS implementation of select() system call *
|
||||||
|
*********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This implementation is quite restricted:
|
||||||
|
* Works on sockets only -- no support for other devices!
|
||||||
|
* A given socket can be in a read-select or a read/recv* by only
|
||||||
|
* one task at a time.
|
||||||
|
* A given socket can be in a write-select or a write/send* by only
|
||||||
|
* one task at a time.
|
||||||
|
*
|
||||||
|
* NOTE - select() is a very expensive system call. It should be avoided
|
||||||
|
* if at all possible. In many cases, rewriting the application
|
||||||
|
* to use multiple tasks (one per socket) is a better solution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static __inline int imin(int a, int b) { return (a < b ? a : b); }
|
||||||
|
|
||||||
|
static int
|
||||||
|
socket_select (struct socket *so, int which, rtems_id tid)
|
||||||
|
{
|
||||||
|
switch (which) {
|
||||||
|
|
||||||
|
case FREAD:
|
||||||
|
if (soreadable(so))
|
||||||
|
return (1);
|
||||||
|
so->so_rcv.sb_sel.si_pid = tid;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FWRITE:
|
||||||
|
if (sowriteable(so))
|
||||||
|
return (1);
|
||||||
|
so->so_snd.sb_sel.si_pid = tid;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
if (so->so_oobmark || (so->so_state & SS_RCVATMARK))
|
||||||
|
return (1);
|
||||||
|
so->so_rcv.sb_sel.si_pid = tid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
selscan (rtems_id tid, fd_mask **ibits, fd_mask **obits, int nfd, int *retval)
|
||||||
|
{
|
||||||
|
struct socket *so;
|
||||||
|
int msk, i, fd;
|
||||||
|
fd_mask bits, bit;
|
||||||
|
int n = 0;
|
||||||
|
static int flag[3] = { FREAD, FWRITE, 0 };
|
||||||
|
|
||||||
|
for (msk = 0; msk < 3; msk++) {
|
||||||
|
if (ibits[msk] == NULL)
|
||||||
|
continue;
|
||||||
|
for (i = 0; i < nfd; i += NFDBITS) {
|
||||||
|
bits = ibits[msk][i/NFDBITS];
|
||||||
|
for (fd = i, bit = 1 ; bits && (fd < nfd) ; fd++, bit <<= 1) {
|
||||||
|
if ((bits & bit) == 0)
|
||||||
|
continue;
|
||||||
|
bits &= ~bit;
|
||||||
|
so = rtems_bsdnet_fdToSocket (fd);
|
||||||
|
if (so == NULL)
|
||||||
|
return (EBADF);
|
||||||
|
if (socket_select (so, flag[msk], tid)) {
|
||||||
|
obits[msk][fd/NFDBITS] |=
|
||||||
|
(1 << (fd % NFDBITS));
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*retval = n;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *tv)
|
||||||
|
{
|
||||||
|
fd_mask *ibits[3], *obits[3];
|
||||||
|
fd_set ob[3];
|
||||||
|
int error, timo;
|
||||||
|
int retval;
|
||||||
|
rtems_id tid;
|
||||||
|
rtems_interval then, now;
|
||||||
|
rtems_event_set events;
|
||||||
|
|
||||||
|
if (nfds < 0)
|
||||||
|
return (EINVAL);
|
||||||
|
if (tv) {
|
||||||
|
timo = tv->tv_sec * hz + tv->tv_usec / tick;
|
||||||
|
if (timo == 0)
|
||||||
|
timo = 1;
|
||||||
|
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
timo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define getbits(name,i) if (name) { \
|
||||||
|
ibits[i] = &name->fds_bits[0]; \
|
||||||
|
obits[i] = &ob[i].fds_bits[0]; \
|
||||||
|
FD_ZERO(&ob[i]); \
|
||||||
|
} \
|
||||||
|
else ibits[i] = NULL
|
||||||
|
getbits (readfds, 0);
|
||||||
|
getbits (writefds, 1);
|
||||||
|
getbits (exceptfds, 2);
|
||||||
|
#undef getbits
|
||||||
|
|
||||||
|
rtems_task_ident (RTEMS_SELF, 0, &tid);
|
||||||
|
rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
|
||||||
|
for (;;) {
|
||||||
|
rtems_bsdnet_semaphore_obtain ();
|
||||||
|
error = selscan(tid, ibits, obits, nfds, &retval);
|
||||||
|
rtems_bsdnet_semaphore_release ();
|
||||||
|
if (error || retval)
|
||||||
|
break;
|
||||||
|
if (timo) {
|
||||||
|
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
|
||||||
|
timo -= now - then;
|
||||||
|
if (timo <= 0)
|
||||||
|
break;
|
||||||
|
then = now;
|
||||||
|
}
|
||||||
|
rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, timo, &events);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define putbits(name,i) if (name) *name = ob[i]
|
||||||
|
putbits (readfds, 0);
|
||||||
|
putbits (writefds, 1);
|
||||||
|
putbits (exceptfds, 2);
|
||||||
|
#undef putbits
|
||||||
|
if (error) {
|
||||||
|
errno = error;
|
||||||
|
retval = -1;
|
||||||
|
}
|
||||||
|
return (retval);
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
static char *rtems_hostname;
|
static char *rtems_hostname;
|
||||||
|
|
||||||
int
|
int
|
||||||
gethostname (char *name, int namelen)
|
gethostname (char *name, size_t namelen)
|
||||||
{
|
{
|
||||||
char *cp = rtems_hostname;
|
char *cp = rtems_hostname;
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ gethostname (char *name, int namelen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sethostname (char *name, int namelen)
|
sethostname (char *name, size_t namelen)
|
||||||
{
|
{
|
||||||
char *old, *new;
|
char *old, *new;
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -25,6 +26,12 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#ifndef set_errno_and_return_minus_one
|
||||||
|
#define set_errno_and_return_minus_one( _error ) \
|
||||||
|
do { errno = (_error); return -1; } while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Range of UDP ports to try
|
* Range of UDP ports to try
|
||||||
*/
|
*/
|
||||||
@@ -136,6 +143,50 @@ static rtems_id tftp_mutex;
|
|||||||
static int nStreams;
|
static int nStreams;
|
||||||
static struct tftpStream ** volatile tftpStreams;
|
static struct tftpStream ** volatile tftpStreams;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
rtems_id tftp_mutex;
|
||||||
|
int nStreams;
|
||||||
|
struct tftpStream ** volatile tftpStreams;
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry;
|
||||||
|
} tftp_fs_info;
|
||||||
|
|
||||||
|
int rtems_tftp_mount_me(
|
||||||
|
rtems_filesystem_mount_table_entry_t *temp_mt_entry
|
||||||
|
)
|
||||||
|
{
|
||||||
|
tftp_fs_info *fs_info;
|
||||||
|
rtems_status_code sc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate stuff for this file system.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fs_info = calloc( 1, sizeof( tftp_fs_info ));
|
||||||
|
if ( !fs_info )
|
||||||
|
set_errno_and_return_minus_one( ENOMEM );
|
||||||
|
|
||||||
|
temp_mt_entry->fs_info = fs_info;
|
||||||
|
temp_mt_entry->mt_fs_root.node_access = fs_info;
|
||||||
|
|
||||||
|
|
||||||
|
sc = rtems_semaphore_create (
|
||||||
|
rtems_build_name('T', 'F', 'T', 'P'),
|
||||||
|
1,
|
||||||
|
RTEMS_FIFO |
|
||||||
|
RTEMS_BINARY_SEMAPHORE |
|
||||||
|
RTEMS_NO_INHERIT_PRIORITY |
|
||||||
|
RTEMS_NO_PRIORITY_CEILING |
|
||||||
|
RTEMS_LOCAL,
|
||||||
|
0,
|
||||||
|
&fs_info->tftp_mutex
|
||||||
|
);
|
||||||
|
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one( ENOMEM ); /* ??? */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the TFTP driver
|
* Initialize the TFTP driver
|
||||||
*/
|
*/
|
||||||
@@ -147,19 +198,7 @@ rtems_device_driver rtems_tftp_initialize(
|
|||||||
void *pargp
|
void *pargp
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
rtems_status_code sc;
|
|
||||||
|
|
||||||
sc = rtems_semaphore_create (rtems_build_name('T', 'F', 'T', 'P'),
|
|
||||||
1,
|
|
||||||
RTEMS_FIFO |
|
|
||||||
RTEMS_BINARY_SEMAPHORE |
|
|
||||||
RTEMS_NO_INHERIT_PRIORITY |
|
|
||||||
RTEMS_NO_PRIORITY_CEILING |
|
|
||||||
RTEMS_LOCAL,
|
|
||||||
0,
|
|
||||||
&tftp_mutex);
|
|
||||||
if (sc != RTEMS_SUCCESSFUL)
|
|
||||||
return sc;
|
|
||||||
/* XXX change to a mount */
|
/* XXX change to a mount */
|
||||||
rtems_io_register_name (TFTP_PATHNAME_PREFIX, major, minor);
|
rtems_io_register_name (TFTP_PATHNAME_PREFIX, major, minor);
|
||||||
return RTEMS_SUCCESSFUL;
|
return RTEMS_SUCCESSFUL;
|
||||||
@@ -293,39 +332,44 @@ releaseStream (int s)
|
|||||||
rtems_semaphore_release (tftp_mutex);
|
rtems_semaphore_release (tftp_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
int rtems_tftp_evaluate_for_make(
|
||||||
* Open a TFTP stream
|
const char *path, /* IN */
|
||||||
*/
|
rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
|
||||||
rtems_device_driver rtems_tftp_open(
|
const char **name /* OUT */
|
||||||
rtems_device_major_number major,
|
|
||||||
rtems_device_minor_number minor,
|
|
||||||
void *pargp
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
rtems_libio_open_close_args_t *ap = pargp;
|
set_errno_and_return_minus_one( EIO );
|
||||||
struct tftpStream *tp;
|
}
|
||||||
int retryCount;
|
/*
|
||||||
rtems_unsigned32 farAddress;
|
* XXX - Fix return values.
|
||||||
int s;
|
|
||||||
int len;
|
|
||||||
char *cp1, *cp2;
|
|
||||||
char *remoteFilename;
|
|
||||||
rtems_interval now;
|
|
||||||
rtems_status_code sc;
|
|
||||||
|
|
||||||
/* XXX change to eval_path/open */
|
|
||||||
/*
|
|
||||||
* Read-only for now
|
|
||||||
*/
|
*/
|
||||||
if (ap->flags & LIBIO_FLAGS_WRITE)
|
|
||||||
return RTEMS_NOT_IMPLEMENTED;
|
int TFTP_eval_path(
|
||||||
|
const char *pathname, /* IN */
|
||||||
|
int flags, /* IN */
|
||||||
|
rtems_filesystem_location_info_t *pathloc /* IN/OUT */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
rtems_unsigned32 farAddress;
|
||||||
|
int len;
|
||||||
|
const char *remoteFilename;
|
||||||
|
|
||||||
|
tftp_fs_info *fs_info;
|
||||||
|
const char *cp1, *cp2;
|
||||||
|
|
||||||
|
fs_info = pathloc->node_access;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pick apart the name into a host:pathname pair
|
* Pick apart the name into a host:pathname pair
|
||||||
*/
|
*/
|
||||||
if (strlen (ap->iop->pathname) <= strlen (TFTP_PATHNAME_PREFIX))
|
/*
|
||||||
return RTEMS_INVALID_NAME;
|
* XXX - I think this is handled by the caller of
|
||||||
cp2 = ap->iop->pathname + strlen (TFTP_PATHNAME_PREFIX);
|
* the evaluate routine. ? Am I starting at the right
|
||||||
|
* place?
|
||||||
|
*/
|
||||||
|
|
||||||
|
cp2 = pathname+1;
|
||||||
|
|
||||||
if (*cp2 == '/') {
|
if (*cp2 == '/') {
|
||||||
farAddress = rtems_bsdnet_bootp_server_address.s_addr;
|
farAddress = rtems_bsdnet_bootp_server_address.s_addr;
|
||||||
}
|
}
|
||||||
@@ -355,6 +399,37 @@ rtems_device_driver rtems_tftp_open(
|
|||||||
if (strlen (remoteFilename) > (TFTP_BUFSIZE - 10))
|
if (strlen (remoteFilename) > (TFTP_BUFSIZE - 10))
|
||||||
return RTEMS_INVALID_NAME;
|
return RTEMS_INVALID_NAME;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open a TFTP stream
|
||||||
|
*/
|
||||||
|
rtems_device_driver rtems_tftp_open(
|
||||||
|
rtems_device_major_number major,
|
||||||
|
rtems_device_minor_number minor,
|
||||||
|
void *pargp
|
||||||
|
)
|
||||||
|
{
|
||||||
|
rtems_libio_open_close_args_t *ap = pargp;
|
||||||
|
struct tftpStream *tp;
|
||||||
|
int retryCount;
|
||||||
|
rtems_unsigned32 farAddress = 0; /* XXX - node parameter */
|
||||||
|
int s;
|
||||||
|
int len;
|
||||||
|
char *cp1, *cp2;
|
||||||
|
char *remoteFilename = NULL; /* XXX - node parameter */
|
||||||
|
rtems_interval now;
|
||||||
|
rtems_status_code sc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read-only for now
|
||||||
|
*/
|
||||||
|
/* XXX - Move to the open routine */
|
||||||
|
if (ap->flags & LIBIO_FLAGS_WRITE)
|
||||||
|
return RTEMS_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find a free stream
|
* Find a free stream
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#if defined(__rtems__)
|
#if defined(__rtems__)
|
||||||
u_int16_t _getshort(const u_char *src);
|
u_int16_t _getshort(const u_char *src);
|
||||||
u_int32_t _getlong(const u_char *src);
|
u_int32_t _getlong(const u_char *src);
|
||||||
int gethostname (char *name, int namelen);
|
int gethostname (char *name, size_t namelen);
|
||||||
int sethostname (char *name, int namelen);
|
int sethostname (char *name, size_t namelen);
|
||||||
int issetugid (void);
|
int issetugid (void);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ extern int rtems_bsdnet_nameserver_count;
|
|||||||
/*
|
/*
|
||||||
* Some extra prototypes
|
* Some extra prototypes
|
||||||
*/
|
*/
|
||||||
int sethostname (char *name, int namelen);
|
int sethostname (char *name, size_t namelen);
|
||||||
void domaininit (void *);
|
void domaininit (void *);
|
||||||
void ifinit (void *);
|
void ifinit (void *);
|
||||||
void ipintr (void);
|
void ipintr (void);
|
||||||
@@ -174,5 +174,19 @@ void arpintr (void);
|
|||||||
void bootpc_init(void);
|
void bootpc_init(void);
|
||||||
int socket (int, int, int);
|
int socket (int, int, int);
|
||||||
int ioctl (int, unsigned long, ...);
|
int ioctl (int, unsigned long, ...);
|
||||||
|
struct socket *rtems_bsdnet_fdToSocket (int fd);
|
||||||
|
int rtems_bsdnet_makeFdForSocket (struct socket *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Events used by networking routines.
|
||||||
|
* Everything will break if the application
|
||||||
|
* tries to use these events or if the `sleep'
|
||||||
|
* events are equal to any of the NETISR * events.
|
||||||
|
*/
|
||||||
|
#define SBWAIT_EVENT RTEMS_EVENT_24
|
||||||
|
#define SOSLEEP_EVENT RTEMS_EVENT_25
|
||||||
|
#define NETISR_IP_EVENT (1 << NETISR_IP)
|
||||||
|
#define NETISR_ARP_EVENT (1 << NETISR_ARP)
|
||||||
|
#define NETISR_EVENTS (NETISR_IP_EVENT|NETISR_ARP_EVENT)
|
||||||
|
|
||||||
#endif /* _RTEMS_BSDNET_INTERNAL_H_ */
|
#endif /* _RTEMS_BSDNET_INTERNAL_H_ */
|
||||||
|
|||||||
171
c/src/libnetworking/rtems/rtems_select.c
Normal file
171
c/src/libnetworking/rtems/rtems_select.c
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio.h>
|
||||||
|
#include <rtems/error.h>
|
||||||
|
#include <rtems/rtems_bsdnet.h>
|
||||||
|
|
||||||
|
#include <sys/errno.h>
|
||||||
|
#include <sys/fcntl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/mbuf.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/socketvar.h>
|
||||||
|
#include <sys/protosw.h>
|
||||||
|
#include <sys/proc.h>
|
||||||
|
#include <sys/filio.h>
|
||||||
|
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/route.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
*********************************************************************
|
||||||
|
* RTEMS implementation of select() system call *
|
||||||
|
*********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This implementation is quite restricted:
|
||||||
|
* Works on sockets only -- no support for other devices!
|
||||||
|
* A given socket can be in a read-select or a read/recv* by only
|
||||||
|
* one task at a time.
|
||||||
|
* A given socket can be in a write-select or a write/send* by only
|
||||||
|
* one task at a time.
|
||||||
|
*
|
||||||
|
* NOTE - select() is a very expensive system call. It should be avoided
|
||||||
|
* if at all possible. In many cases, rewriting the application
|
||||||
|
* to use multiple tasks (one per socket) is a better solution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static __inline int imin(int a, int b) { return (a < b ? a : b); }
|
||||||
|
|
||||||
|
static int
|
||||||
|
socket_select (struct socket *so, int which, rtems_id tid)
|
||||||
|
{
|
||||||
|
switch (which) {
|
||||||
|
|
||||||
|
case FREAD:
|
||||||
|
if (soreadable(so))
|
||||||
|
return (1);
|
||||||
|
so->so_rcv.sb_sel.si_pid = tid;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FWRITE:
|
||||||
|
if (sowriteable(so))
|
||||||
|
return (1);
|
||||||
|
so->so_snd.sb_sel.si_pid = tid;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
if (so->so_oobmark || (so->so_state & SS_RCVATMARK))
|
||||||
|
return (1);
|
||||||
|
so->so_rcv.sb_sel.si_pid = tid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
selscan (rtems_id tid, fd_mask **ibits, fd_mask **obits, int nfd, int *retval)
|
||||||
|
{
|
||||||
|
struct socket *so;
|
||||||
|
int msk, i, fd;
|
||||||
|
fd_mask bits, bit;
|
||||||
|
int n = 0;
|
||||||
|
static int flag[3] = { FREAD, FWRITE, 0 };
|
||||||
|
|
||||||
|
for (msk = 0; msk < 3; msk++) {
|
||||||
|
if (ibits[msk] == NULL)
|
||||||
|
continue;
|
||||||
|
for (i = 0; i < nfd; i += NFDBITS) {
|
||||||
|
bits = ibits[msk][i/NFDBITS];
|
||||||
|
for (fd = i, bit = 1 ; bits && (fd < nfd) ; fd++, bit <<= 1) {
|
||||||
|
if ((bits & bit) == 0)
|
||||||
|
continue;
|
||||||
|
bits &= ~bit;
|
||||||
|
so = rtems_bsdnet_fdToSocket (fd);
|
||||||
|
if (so == NULL)
|
||||||
|
return (EBADF);
|
||||||
|
if (socket_select (so, flag[msk], tid)) {
|
||||||
|
obits[msk][fd/NFDBITS] |=
|
||||||
|
(1 << (fd % NFDBITS));
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*retval = n;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *tv)
|
||||||
|
{
|
||||||
|
fd_mask *ibits[3], *obits[3];
|
||||||
|
fd_set ob[3];
|
||||||
|
int error, timo;
|
||||||
|
int retval;
|
||||||
|
rtems_id tid;
|
||||||
|
rtems_interval then, now;
|
||||||
|
rtems_event_set events;
|
||||||
|
|
||||||
|
if (nfds < 0)
|
||||||
|
return (EINVAL);
|
||||||
|
if (tv) {
|
||||||
|
timo = tv->tv_sec * hz + tv->tv_usec / tick;
|
||||||
|
if (timo == 0)
|
||||||
|
timo = 1;
|
||||||
|
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
timo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define getbits(name,i) if (name) { \
|
||||||
|
ibits[i] = &name->fds_bits[0]; \
|
||||||
|
obits[i] = &ob[i].fds_bits[0]; \
|
||||||
|
FD_ZERO(&ob[i]); \
|
||||||
|
} \
|
||||||
|
else ibits[i] = NULL
|
||||||
|
getbits (readfds, 0);
|
||||||
|
getbits (writefds, 1);
|
||||||
|
getbits (exceptfds, 2);
|
||||||
|
#undef getbits
|
||||||
|
|
||||||
|
rtems_task_ident (RTEMS_SELF, 0, &tid);
|
||||||
|
rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
|
||||||
|
for (;;) {
|
||||||
|
rtems_bsdnet_semaphore_obtain ();
|
||||||
|
error = selscan(tid, ibits, obits, nfds, &retval);
|
||||||
|
rtems_bsdnet_semaphore_release ();
|
||||||
|
if (error || retval)
|
||||||
|
break;
|
||||||
|
if (timo) {
|
||||||
|
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
|
||||||
|
timo -= now - then;
|
||||||
|
if (timo <= 0)
|
||||||
|
break;
|
||||||
|
then = now;
|
||||||
|
}
|
||||||
|
rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, timo, &events);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define putbits(name,i) if (name) *name = ob[i]
|
||||||
|
putbits (readfds, 0);
|
||||||
|
putbits (writefds, 1);
|
||||||
|
putbits (exceptfds, 2);
|
||||||
|
#undef putbits
|
||||||
|
if (error) {
|
||||||
|
errno = error;
|
||||||
|
retval = -1;
|
||||||
|
}
|
||||||
|
return (retval);
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
static char *rtems_hostname;
|
static char *rtems_hostname;
|
||||||
|
|
||||||
int
|
int
|
||||||
gethostname (char *name, int namelen)
|
gethostname (char *name, size_t namelen)
|
||||||
{
|
{
|
||||||
char *cp = rtems_hostname;
|
char *cp = rtems_hostname;
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ gethostname (char *name, int namelen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sethostname (char *name, int namelen)
|
sethostname (char *name, size_t namelen)
|
||||||
{
|
{
|
||||||
char *old, *new;
|
char *old, *new;
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -25,6 +26,12 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#ifndef set_errno_and_return_minus_one
|
||||||
|
#define set_errno_and_return_minus_one( _error ) \
|
||||||
|
do { errno = (_error); return -1; } while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Range of UDP ports to try
|
* Range of UDP ports to try
|
||||||
*/
|
*/
|
||||||
@@ -136,6 +143,50 @@ static rtems_id tftp_mutex;
|
|||||||
static int nStreams;
|
static int nStreams;
|
||||||
static struct tftpStream ** volatile tftpStreams;
|
static struct tftpStream ** volatile tftpStreams;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
rtems_id tftp_mutex;
|
||||||
|
int nStreams;
|
||||||
|
struct tftpStream ** volatile tftpStreams;
|
||||||
|
rtems_filesystem_mount_table_entry_t *mt_entry;
|
||||||
|
} tftp_fs_info;
|
||||||
|
|
||||||
|
int rtems_tftp_mount_me(
|
||||||
|
rtems_filesystem_mount_table_entry_t *temp_mt_entry
|
||||||
|
)
|
||||||
|
{
|
||||||
|
tftp_fs_info *fs_info;
|
||||||
|
rtems_status_code sc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate stuff for this file system.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fs_info = calloc( 1, sizeof( tftp_fs_info ));
|
||||||
|
if ( !fs_info )
|
||||||
|
set_errno_and_return_minus_one( ENOMEM );
|
||||||
|
|
||||||
|
temp_mt_entry->fs_info = fs_info;
|
||||||
|
temp_mt_entry->mt_fs_root.node_access = fs_info;
|
||||||
|
|
||||||
|
|
||||||
|
sc = rtems_semaphore_create (
|
||||||
|
rtems_build_name('T', 'F', 'T', 'P'),
|
||||||
|
1,
|
||||||
|
RTEMS_FIFO |
|
||||||
|
RTEMS_BINARY_SEMAPHORE |
|
||||||
|
RTEMS_NO_INHERIT_PRIORITY |
|
||||||
|
RTEMS_NO_PRIORITY_CEILING |
|
||||||
|
RTEMS_LOCAL,
|
||||||
|
0,
|
||||||
|
&fs_info->tftp_mutex
|
||||||
|
);
|
||||||
|
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
set_errno_and_return_minus_one( ENOMEM ); /* ??? */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the TFTP driver
|
* Initialize the TFTP driver
|
||||||
*/
|
*/
|
||||||
@@ -147,19 +198,7 @@ rtems_device_driver rtems_tftp_initialize(
|
|||||||
void *pargp
|
void *pargp
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
rtems_status_code sc;
|
|
||||||
|
|
||||||
sc = rtems_semaphore_create (rtems_build_name('T', 'F', 'T', 'P'),
|
|
||||||
1,
|
|
||||||
RTEMS_FIFO |
|
|
||||||
RTEMS_BINARY_SEMAPHORE |
|
|
||||||
RTEMS_NO_INHERIT_PRIORITY |
|
|
||||||
RTEMS_NO_PRIORITY_CEILING |
|
|
||||||
RTEMS_LOCAL,
|
|
||||||
0,
|
|
||||||
&tftp_mutex);
|
|
||||||
if (sc != RTEMS_SUCCESSFUL)
|
|
||||||
return sc;
|
|
||||||
/* XXX change to a mount */
|
/* XXX change to a mount */
|
||||||
rtems_io_register_name (TFTP_PATHNAME_PREFIX, major, minor);
|
rtems_io_register_name (TFTP_PATHNAME_PREFIX, major, minor);
|
||||||
return RTEMS_SUCCESSFUL;
|
return RTEMS_SUCCESSFUL;
|
||||||
@@ -293,39 +332,44 @@ releaseStream (int s)
|
|||||||
rtems_semaphore_release (tftp_mutex);
|
rtems_semaphore_release (tftp_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
int rtems_tftp_evaluate_for_make(
|
||||||
* Open a TFTP stream
|
const char *path, /* IN */
|
||||||
*/
|
rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
|
||||||
rtems_device_driver rtems_tftp_open(
|
const char **name /* OUT */
|
||||||
rtems_device_major_number major,
|
|
||||||
rtems_device_minor_number minor,
|
|
||||||
void *pargp
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
rtems_libio_open_close_args_t *ap = pargp;
|
set_errno_and_return_minus_one( EIO );
|
||||||
struct tftpStream *tp;
|
}
|
||||||
int retryCount;
|
/*
|
||||||
rtems_unsigned32 farAddress;
|
* XXX - Fix return values.
|
||||||
int s;
|
|
||||||
int len;
|
|
||||||
char *cp1, *cp2;
|
|
||||||
char *remoteFilename;
|
|
||||||
rtems_interval now;
|
|
||||||
rtems_status_code sc;
|
|
||||||
|
|
||||||
/* XXX change to eval_path/open */
|
|
||||||
/*
|
|
||||||
* Read-only for now
|
|
||||||
*/
|
*/
|
||||||
if (ap->flags & LIBIO_FLAGS_WRITE)
|
|
||||||
return RTEMS_NOT_IMPLEMENTED;
|
int TFTP_eval_path(
|
||||||
|
const char *pathname, /* IN */
|
||||||
|
int flags, /* IN */
|
||||||
|
rtems_filesystem_location_info_t *pathloc /* IN/OUT */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
rtems_unsigned32 farAddress;
|
||||||
|
int len;
|
||||||
|
const char *remoteFilename;
|
||||||
|
|
||||||
|
tftp_fs_info *fs_info;
|
||||||
|
const char *cp1, *cp2;
|
||||||
|
|
||||||
|
fs_info = pathloc->node_access;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pick apart the name into a host:pathname pair
|
* Pick apart the name into a host:pathname pair
|
||||||
*/
|
*/
|
||||||
if (strlen (ap->iop->pathname) <= strlen (TFTP_PATHNAME_PREFIX))
|
/*
|
||||||
return RTEMS_INVALID_NAME;
|
* XXX - I think this is handled by the caller of
|
||||||
cp2 = ap->iop->pathname + strlen (TFTP_PATHNAME_PREFIX);
|
* the evaluate routine. ? Am I starting at the right
|
||||||
|
* place?
|
||||||
|
*/
|
||||||
|
|
||||||
|
cp2 = pathname+1;
|
||||||
|
|
||||||
if (*cp2 == '/') {
|
if (*cp2 == '/') {
|
||||||
farAddress = rtems_bsdnet_bootp_server_address.s_addr;
|
farAddress = rtems_bsdnet_bootp_server_address.s_addr;
|
||||||
}
|
}
|
||||||
@@ -355,6 +399,37 @@ rtems_device_driver rtems_tftp_open(
|
|||||||
if (strlen (remoteFilename) > (TFTP_BUFSIZE - 10))
|
if (strlen (remoteFilename) > (TFTP_BUFSIZE - 10))
|
||||||
return RTEMS_INVALID_NAME;
|
return RTEMS_INVALID_NAME;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open a TFTP stream
|
||||||
|
*/
|
||||||
|
rtems_device_driver rtems_tftp_open(
|
||||||
|
rtems_device_major_number major,
|
||||||
|
rtems_device_minor_number minor,
|
||||||
|
void *pargp
|
||||||
|
)
|
||||||
|
{
|
||||||
|
rtems_libio_open_close_args_t *ap = pargp;
|
||||||
|
struct tftpStream *tp;
|
||||||
|
int retryCount;
|
||||||
|
rtems_unsigned32 farAddress = 0; /* XXX - node parameter */
|
||||||
|
int s;
|
||||||
|
int len;
|
||||||
|
char *cp1, *cp2;
|
||||||
|
char *remoteFilename = NULL; /* XXX - node parameter */
|
||||||
|
rtems_interval now;
|
||||||
|
rtems_status_code sc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read-only for now
|
||||||
|
*/
|
||||||
|
/* XXX - Move to the open routine */
|
||||||
|
if (ap->flags & LIBIO_FLAGS_WRITE)
|
||||||
|
return RTEMS_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find a free stream
|
* Find a free stream
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#if defined(__rtems__)
|
#if defined(__rtems__)
|
||||||
u_int16_t _getshort(const u_char *src);
|
u_int16_t _getshort(const u_char *src);
|
||||||
u_int32_t _getlong(const u_char *src);
|
u_int32_t _getlong(const u_char *src);
|
||||||
int gethostname (char *name, int namelen);
|
int gethostname (char *name, size_t namelen);
|
||||||
int sethostname (char *name, int namelen);
|
int sethostname (char *name, size_t namelen);
|
||||||
int issetugid (void);
|
int issetugid (void);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ extern int rtems_bsdnet_nameserver_count;
|
|||||||
/*
|
/*
|
||||||
* Some extra prototypes
|
* Some extra prototypes
|
||||||
*/
|
*/
|
||||||
int sethostname (char *name, int namelen);
|
int sethostname (char *name, size_t namelen);
|
||||||
void domaininit (void *);
|
void domaininit (void *);
|
||||||
void ifinit (void *);
|
void ifinit (void *);
|
||||||
void ipintr (void);
|
void ipintr (void);
|
||||||
@@ -174,5 +174,19 @@ void arpintr (void);
|
|||||||
void bootpc_init(void);
|
void bootpc_init(void);
|
||||||
int socket (int, int, int);
|
int socket (int, int, int);
|
||||||
int ioctl (int, unsigned long, ...);
|
int ioctl (int, unsigned long, ...);
|
||||||
|
struct socket *rtems_bsdnet_fdToSocket (int fd);
|
||||||
|
int rtems_bsdnet_makeFdForSocket (struct socket *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Events used by networking routines.
|
||||||
|
* Everything will break if the application
|
||||||
|
* tries to use these events or if the `sleep'
|
||||||
|
* events are equal to any of the NETISR * events.
|
||||||
|
*/
|
||||||
|
#define SBWAIT_EVENT RTEMS_EVENT_24
|
||||||
|
#define SOSLEEP_EVENT RTEMS_EVENT_25
|
||||||
|
#define NETISR_IP_EVENT (1 << NETISR_IP)
|
||||||
|
#define NETISR_ARP_EVENT (1 << NETISR_ARP)
|
||||||
|
#define NETISR_EVENTS (NETISR_IP_EVENT|NETISR_ARP_EVENT)
|
||||||
|
|
||||||
#endif /* _RTEMS_BSDNET_INTERNAL_H_ */
|
#endif /* _RTEMS_BSDNET_INTERNAL_H_ */
|
||||||
|
|||||||
171
cpukit/libnetworking/rtems/rtems_select.c
Normal file
171
cpukit/libnetworking/rtems/rtems_select.c
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/libio.h>
|
||||||
|
#include <rtems/error.h>
|
||||||
|
#include <rtems/rtems_bsdnet.h>
|
||||||
|
|
||||||
|
#include <sys/errno.h>
|
||||||
|
#include <sys/fcntl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/mbuf.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/socketvar.h>
|
||||||
|
#include <sys/protosw.h>
|
||||||
|
#include <sys/proc.h>
|
||||||
|
#include <sys/filio.h>
|
||||||
|
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/route.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
*********************************************************************
|
||||||
|
* RTEMS implementation of select() system call *
|
||||||
|
*********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This implementation is quite restricted:
|
||||||
|
* Works on sockets only -- no support for other devices!
|
||||||
|
* A given socket can be in a read-select or a read/recv* by only
|
||||||
|
* one task at a time.
|
||||||
|
* A given socket can be in a write-select or a write/send* by only
|
||||||
|
* one task at a time.
|
||||||
|
*
|
||||||
|
* NOTE - select() is a very expensive system call. It should be avoided
|
||||||
|
* if at all possible. In many cases, rewriting the application
|
||||||
|
* to use multiple tasks (one per socket) is a better solution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static __inline int imin(int a, int b) { return (a < b ? a : b); }
|
||||||
|
|
||||||
|
static int
|
||||||
|
socket_select (struct socket *so, int which, rtems_id tid)
|
||||||
|
{
|
||||||
|
switch (which) {
|
||||||
|
|
||||||
|
case FREAD:
|
||||||
|
if (soreadable(so))
|
||||||
|
return (1);
|
||||||
|
so->so_rcv.sb_sel.si_pid = tid;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FWRITE:
|
||||||
|
if (sowriteable(so))
|
||||||
|
return (1);
|
||||||
|
so->so_snd.sb_sel.si_pid = tid;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
if (so->so_oobmark || (so->so_state & SS_RCVATMARK))
|
||||||
|
return (1);
|
||||||
|
so->so_rcv.sb_sel.si_pid = tid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
selscan (rtems_id tid, fd_mask **ibits, fd_mask **obits, int nfd, int *retval)
|
||||||
|
{
|
||||||
|
struct socket *so;
|
||||||
|
int msk, i, fd;
|
||||||
|
fd_mask bits, bit;
|
||||||
|
int n = 0;
|
||||||
|
static int flag[3] = { FREAD, FWRITE, 0 };
|
||||||
|
|
||||||
|
for (msk = 0; msk < 3; msk++) {
|
||||||
|
if (ibits[msk] == NULL)
|
||||||
|
continue;
|
||||||
|
for (i = 0; i < nfd; i += NFDBITS) {
|
||||||
|
bits = ibits[msk][i/NFDBITS];
|
||||||
|
for (fd = i, bit = 1 ; bits && (fd < nfd) ; fd++, bit <<= 1) {
|
||||||
|
if ((bits & bit) == 0)
|
||||||
|
continue;
|
||||||
|
bits &= ~bit;
|
||||||
|
so = rtems_bsdnet_fdToSocket (fd);
|
||||||
|
if (so == NULL)
|
||||||
|
return (EBADF);
|
||||||
|
if (socket_select (so, flag[msk], tid)) {
|
||||||
|
obits[msk][fd/NFDBITS] |=
|
||||||
|
(1 << (fd % NFDBITS));
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*retval = n;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *tv)
|
||||||
|
{
|
||||||
|
fd_mask *ibits[3], *obits[3];
|
||||||
|
fd_set ob[3];
|
||||||
|
int error, timo;
|
||||||
|
int retval;
|
||||||
|
rtems_id tid;
|
||||||
|
rtems_interval then, now;
|
||||||
|
rtems_event_set events;
|
||||||
|
|
||||||
|
if (nfds < 0)
|
||||||
|
return (EINVAL);
|
||||||
|
if (tv) {
|
||||||
|
timo = tv->tv_sec * hz + tv->tv_usec / tick;
|
||||||
|
if (timo == 0)
|
||||||
|
timo = 1;
|
||||||
|
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
timo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define getbits(name,i) if (name) { \
|
||||||
|
ibits[i] = &name->fds_bits[0]; \
|
||||||
|
obits[i] = &ob[i].fds_bits[0]; \
|
||||||
|
FD_ZERO(&ob[i]); \
|
||||||
|
} \
|
||||||
|
else ibits[i] = NULL
|
||||||
|
getbits (readfds, 0);
|
||||||
|
getbits (writefds, 1);
|
||||||
|
getbits (exceptfds, 2);
|
||||||
|
#undef getbits
|
||||||
|
|
||||||
|
rtems_task_ident (RTEMS_SELF, 0, &tid);
|
||||||
|
rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
|
||||||
|
for (;;) {
|
||||||
|
rtems_bsdnet_semaphore_obtain ();
|
||||||
|
error = selscan(tid, ibits, obits, nfds, &retval);
|
||||||
|
rtems_bsdnet_semaphore_release ();
|
||||||
|
if (error || retval)
|
||||||
|
break;
|
||||||
|
if (timo) {
|
||||||
|
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
|
||||||
|
timo -= now - then;
|
||||||
|
if (timo <= 0)
|
||||||
|
break;
|
||||||
|
then = now;
|
||||||
|
}
|
||||||
|
rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, timo, &events);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define putbits(name,i) if (name) *name = ob[i]
|
||||||
|
putbits (readfds, 0);
|
||||||
|
putbits (writefds, 1);
|
||||||
|
putbits (exceptfds, 2);
|
||||||
|
#undef putbits
|
||||||
|
if (error) {
|
||||||
|
errno = error;
|
||||||
|
retval = -1;
|
||||||
|
}
|
||||||
|
return (retval);
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
static char *rtems_hostname;
|
static char *rtems_hostname;
|
||||||
|
|
||||||
int
|
int
|
||||||
gethostname (char *name, int namelen)
|
gethostname (char *name, size_t namelen)
|
||||||
{
|
{
|
||||||
char *cp = rtems_hostname;
|
char *cp = rtems_hostname;
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ gethostname (char *name, int namelen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sethostname (char *name, int namelen)
|
sethostname (char *name, size_t namelen)
|
||||||
{
|
{
|
||||||
char *old, *new;
|
char *old, *new;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user