diff options
author | Vijay Kumar Banerjee <vijay@rtems.org> | 2021-02-03 19:46:50 -0700 |
---|---|---|
committer | Vijay Kumar Banerjee <vijay@rtems.org> | 2021-02-24 19:01:17 -0700 |
commit | fbc7459c2c3a86a4d94e19463417b759900ff51c (patch) | |
tree | 19d5451b8cee3d0c51a432c23bd598eafe9a53b0 /lib | |
download | rtems-net-legacy-fbc7459c2c3a86a4d94e19463417b759900ff51c.tar.bz2 |
Initial Commit: Add all files from RTEMS libnetworking directory
Diffstat (limited to 'lib')
-rw-r--r-- | lib/README | 1 | ||||
-rw-r--r-- | lib/getprotoby.c | 48 | ||||
-rw-r--r-- | lib/rtems_bsdnet_ntp.c | 219 | ||||
-rw-r--r-- | lib/syslog.c | 170 |
4 files changed, 438 insertions, 0 deletions
diff --git a/lib/README b/lib/README new file mode 100644 index 0000000..787c24c --- /dev/null +++ b/lib/README @@ -0,0 +1 @@ +Sources from application-level (as opposed to kernel-level) libraries. diff --git a/lib/getprotoby.c b/lib/getprotoby.c new file mode 100644 index 0000000..4eeec59 --- /dev/null +++ b/lib/getprotoby.c @@ -0,0 +1,48 @@ +#include <machine/rtems-bsd-user-space.h> + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <netdb.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> + +static const struct protoent prototab[] = { + { "ip", NULL, IPPROTO_IP }, + { "icmp", NULL, IPPROTO_ICMP }, + { "tcp", NULL, IPPROTO_TCP }, + { "udp", NULL, IPPROTO_UDP }, + }; + +/* + * Dummy version of BSD getprotobyname() + */ +struct protoent * +getprotobyname_static (const char *name) +{ + int i; + + for (i = 0 ; i < (sizeof prototab / sizeof prototab[0]) ; i++) { + if (strcmp (name, prototab[i].p_name) == 0) + return (struct protoent *) &prototab[i]; + } + return NULL; +} + +/* + * Dummy version of BSD getprotobynumber() + */ +struct protoent * +getprotobynumber_static (int proto) +{ + int i; + + for (i = 0 ; i < (sizeof prototab / sizeof prototab[0]) ; i++) { + if (proto == prototab[i].p_proto) + return (struct protoent *) &prototab[i]; + } + return NULL; +} diff --git a/lib/rtems_bsdnet_ntp.c b/lib/rtems_bsdnet_ntp.c new file mode 100644 index 0000000..e675759 --- /dev/null +++ b/lib/rtems_bsdnet_ntp.c @@ -0,0 +1,219 @@ +#include <machine/rtems-bsd-user-space.h> + +/* + * Synchronize with an NTP server + * + * This program may be distributed and used for any purpose. + * I ask only that you: + * 1. Leave this author information intact. + * 2. Document any changes you make. + * + * W. Eric Norum + * Canadian Light Source + * University of Saskatchewan + * Saskatoon, Saskatchewan, CANADA + * eric@cls.usask.ca + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <unistd.h> /* close */ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <time.h> +#include <limits.h> +#include <rtems.h> +#include <rtems/rtems_bsdnet.h> +#include <rtems/error.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> + +#include <rtems/bsdnet/servers.h> + +/* + * RTEMS base: 1988, January 1 + * UNIX base: 1970, January 1 + * NTP base: 1900, January 1 + */ +#define UNIX_BASE_TO_NTP_BASE (uint32_t)(((70UL*365UL)+17UL) * (24UL*60UL*60UL)) + +struct ntpPacket { + struct ntpPacketSmall ntp; + char authenticator[96]; +}; + +static int +processPacket (struct ntpPacketSmall *p, int state, void *unused) +{ + time_t tbuf; + struct tm *lt; + rtems_time_of_day rt; + rtems_interval ticks_per_second; + + if ( state ) + return 0; + + ticks_per_second = rtems_clock_get_ticks_per_second(); + tbuf = ntohl (p->transmit_timestamp.integer) - UNIX_BASE_TO_NTP_BASE - rtems_bsdnet_timeoffset; + lt = gmtime (&tbuf); + rt.year = lt->tm_year + 1900; + rt.month = lt->tm_mon + 1; + rt.day = lt->tm_mday; + rt.hour = lt->tm_hour; + rt.minute = lt->tm_min; + rt.second = lt->tm_sec; + rt.ticks = ntohl (p->transmit_timestamp.fraction) / (ULONG_MAX / ticks_per_second); + if (rt.ticks >= ticks_per_second) + rt.ticks = ticks_per_second - 1; + rtems_clock_set (&rt); + return 0; +} + +static int +getServerTimespec(struct ntpPacketSmall *p, int state, void *usr_data) +{ +struct timespec *ts = usr_data; +unsigned long long tmp; + + if ( 0 == state ) { + ts->tv_sec = ntohl( p->transmit_timestamp.integer ); + ts->tv_sec -= rtems_bsdnet_timeoffset + UNIX_BASE_TO_NTP_BASE; + + tmp = 1000000000 * (unsigned long long)ntohl(p->transmit_timestamp.fraction); + + ts->tv_nsec = (unsigned long) (tmp>>32); + } + return 0; +} + +int rtems_bsdnet_ntp_retry_count = 5; +int rtems_bsdnet_ntp_timeout_secs = 5; +int rtems_bsdnet_ntp_bcast_timeout_secs = 80; + +static int +tryServer (int i, int s, rtems_bsdnet_ntp_callback_t callback, void *usr_data) +{ + int l = 0; + struct timeval tv; + socklen_t farlen; + struct sockaddr_in farAddr; + struct ntpPacketSmall packet; + + if (i < 0) + tv.tv_sec = rtems_bsdnet_ntp_bcast_timeout_secs; + else + tv.tv_sec = rtems_bsdnet_ntp_timeout_secs; + tv.tv_usec = 0; + if (setsockopt (s, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof tv) < 0) { + fprintf (stderr, "rtems_bsdnet_get_ntp() Can't set socket receive timeout: %s\n", strerror (errno)); + close (s); + return -1; + } + if (i >= 0) { + memset (&farAddr, 0, sizeof farAddr); + farAddr.sin_family = AF_INET; + farAddr.sin_port = htons (123); + farAddr.sin_addr = rtems_bsdnet_ntpserver[i]; + memset (&packet, 0, sizeof packet); + packet.li_vn_mode = (3 << 3) | 3; /* NTP version 3, client */ + if ( callback( &packet, 1, usr_data ) ) + return -1; + l = sendto (s, &packet, sizeof packet, 0, (struct sockaddr *)&farAddr, sizeof farAddr); + if (l != sizeof packet) { + fprintf (stderr, "rtems_bsdnet_get_ntp() Can't send: %s\n", strerror (errno)); + return -1; + } + } else { + if ( callback( &packet, -1, usr_data ) ) + return -1; + } + farlen = sizeof farAddr; + i = recvfrom (s, &packet, sizeof packet, 0, (struct sockaddr *)&farAddr, &farlen); + if (i == 0) + fprintf (stderr, "rtems_bsdnet_get_ntp() Unexpected EOF"); + if (i < 0) { + if ((errno == EWOULDBLOCK) || (errno == EAGAIN)) + return -1; + fprintf (stderr, "rtems_bsdnet_get_ntp() Can't receive: %s\n", strerror (errno)); + } + + if ( i >= sizeof packet && + (((packet.li_vn_mode & (0x7 << 3)) == (3 << 3)) || + ((packet.li_vn_mode & (0x7 << 3)) == (4 << 3))) && + ((packet.transmit_timestamp.integer != 0) || (packet.transmit_timestamp.fraction != 0)) && + 0 == callback( &packet, 0 , usr_data) ) + return 0; + + return -1; +} + +int rtems_bsdnet_get_ntp(int sock, rtems_bsdnet_ntp_callback_t callback, void *usr_data) +{ +int s = -1; +int i; +int retry; +struct sockaddr_in myAddr; +int reuseFlag; +int ret; + + if ( !callback ) + callback = getServerTimespec; + + if ( sock < 0 ) { + s = socket (AF_INET, SOCK_DGRAM, 0); + if (s < 0) { + fprintf (stderr, "rtems_bsdnet_get_ntp() Can't create socket: %s\n", strerror (errno)); + return -1; + } + reuseFlag = 1; + if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR, (char *)&reuseFlag, sizeof reuseFlag) < 0) { + fprintf (stderr, "rtems_bsdnet_get_ntp() Can't set socket reuse: %s\n", strerror (errno)); + close (s); + return -1; + } + memset (&myAddr, 0, sizeof myAddr); + myAddr.sin_family = AF_INET; + myAddr.sin_port = htons (123); + myAddr.sin_addr.s_addr = htonl (INADDR_ANY); + if (bind (s, (struct sockaddr *)&myAddr, sizeof myAddr) < 0) { + fprintf (stderr, "rtems_bsdnet_get_ntp() Can't bind socket: %s\n", strerror (errno)); + close (s); + return -1; + } + sock = s; + } + ret = -1; + for (retry = 0 ; (ret == -1) && (retry < rtems_bsdnet_ntp_retry_count) ; retry++) { + /* + * If there's no server we just have to wait + * and hope that there's an NTP broadcast + * server out there somewhere. + */ + if (rtems_bsdnet_ntpserver_count <= 0) { + ret = tryServer (-1, sock, callback, usr_data); + } + else { + for (i = 0 ; (ret == -1) && (i < rtems_bsdnet_ntpserver_count) ; i++) { + ret = tryServer (i, sock, callback, usr_data); + } + } + } + if ( s >= 0 ) + close (s); + return ret; +} + +int +rtems_bsdnet_synchronize_ntp (int interval, rtems_task_priority priority) +{ + if (interval != 0) { + fprintf (stderr, "Daemon-mode note yet supported.\n"); + errno = EINVAL; + return -1; + } + return rtems_bsdnet_get_ntp( -1, processPacket, 0); +} diff --git a/lib/syslog.c b/lib/syslog.c new file mode 100644 index 0000000..8e167a4 --- /dev/null +++ b/lib/syslog.c @@ -0,0 +1,170 @@ +#include <machine/rtems-bsd-user-space.h> + +/* + * RTEMS version of syslog and associated routines + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems.h> +#include <rtems/thread.h> +#include <stdio.h> +#include <stdarg.h> +#include <errno.h> +#include <syslog.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <string.h> + +#include <unistd.h> + +static int LogStatus = LOG_CONS; +static const char *LogTag = "syslog"; +static int LogFacility = LOG_USER; +static int LogMask = 0xff; + +static int LogFd = -1; +static rtems_recursive_mutex LogSemaphore = + RTEMS_RECURSIVE_MUTEX_INITIALIZER("syslog"); +extern struct in_addr rtems_bsdnet_log_host_address; + +#define SYSLOG_PORT 514 + +void +syslog (int pri, const char *fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + vsyslog (pri, fmt, ap); + va_end (ap); +} + +/* + * FIXME: Should cbuf be static? It could be if we put the mutex + * around the entire body of this routine. Then we wouldn't + * have to worry about blowing stacks with a local variable + * that large. Could make cbuf bigger, too. + */ +void +vsyslog (int pri, const char *fmt, va_list ap) +{ + int cnt; + char *msgp, cbuf[200]; + int sent; + + if (pri & ~(LOG_PRIMASK|LOG_FACMASK)) { + syslog (LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID, + "syslog: unknown facility/priority: %#x", pri); + pri &= LOG_PRIMASK|LOG_FACMASK; + } + + if (!(LOG_MASK(LOG_PRI(pri)) & LogMask)) + return; + + if ((pri & LOG_FACMASK) == 0) + pri |= LogFacility; + + cnt = snprintf (cbuf, sizeof (cbuf), "<%d>", pri); + msgp = cbuf + (cnt < sizeof (cbuf) ? cnt : sizeof (cbuf) - 1); + if (LogTag && cnt < sizeof (cbuf) - 1) + cnt += snprintf (cbuf + cnt, sizeof (cbuf) - cnt, "%s", LogTag); + if (LogStatus & LOG_PID && cnt < sizeof (cbuf) - 1) { + rtems_id tid; + rtems_task_ident (RTEMS_SELF, 0, &tid); + cnt += snprintf (cbuf + cnt, sizeof (cbuf) - cnt, "[%#lx]", (unsigned long)tid); + } + if (LogTag && cnt < sizeof (cbuf) - 1) + cnt += snprintf (cbuf + cnt, sizeof (cbuf) - cnt, ": "); + cnt += vsnprintf (cbuf + cnt, sizeof (cbuf) - cnt, fmt, ap); + if (cnt > sizeof (cbuf) - 1) + cnt = sizeof (cbuf) - 1; + while (cnt > 0 && cbuf[cnt-1] == '\n') + cbuf[--cnt] = '\0'; + + if (LogStatus & LOG_PERROR) + printf ("%s\n", cbuf); + + /* + * Grab the mutex + */ + sent = 0; + if ((rtems_bsdnet_log_host_address.s_addr != INADDR_ANY) + && (LogFd >= 0)) { + /* + * Set the destination address/port + */ + struct sockaddr_in farAddress; + farAddress.sin_family = AF_INET; + farAddress.sin_port = htons (SYSLOG_PORT); + farAddress.sin_addr = rtems_bsdnet_log_host_address; + memset (farAddress.sin_zero, '\0', sizeof farAddress.sin_zero); + + rtems_recursive_mutex_lock (&LogSemaphore); + /* + * Send the message + */ + if (sendto (LogFd, cbuf, cnt, 0, (struct sockaddr *)&farAddress, sizeof farAddress) >= 0) + sent = 1; + rtems_recursive_mutex_unlock (&LogSemaphore); + } + if (!sent && (LogStatus & LOG_CONS) && !(LogStatus & LOG_PERROR)) + printf ("%s\n", msgp); +} + +void +openlog (const char *ident, int logstat, int logfac) +{ + struct sockaddr_in myAddress; + + if (ident != NULL) + LogTag = ident; + LogStatus = logstat; + if (logfac != 0 && (logfac & ~LOG_FACMASK) == 0) + LogFacility = logfac; + + /* + * Create the socket + */ + if ((LogFd = socket (AF_INET, SOCK_DGRAM, 0)) < 0) { + printf ("Can't create syslog socket: %d\n", errno); + return; + } + + /* + * Bind socket to name + */ + myAddress.sin_family = AF_INET; + myAddress.sin_addr.s_addr = INADDR_ANY; + myAddress.sin_port = htons (SYSLOG_PORT);; + memset (myAddress.sin_zero, '\0', sizeof myAddress.sin_zero); + if (bind (LogFd, (struct sockaddr *)&myAddress, sizeof (myAddress)) < 0) { + close (LogFd); + LogFd = -1; + printf ("Can't bind syslog socket: %d\n", errno); + return; + } +} + +void +closelog(void) +{ + if (LogFd >= 0) { + close (LogFd); + LogFd = -1; + } +} + +int +setlogmask (int pmask) +{ + int omask; + + omask = LogMask; + if (pmask != 0) + LogMask = pmask; + return (omask); +} |