diff options
author | darylm503 <darylm503@6f19259b-4bc3-4df7-8a09-765794883524> | 2011-07-30 00:30:44 +0000 |
---|---|---|
committer | darylm503 <darylm503@6f19259b-4bc3-4df7-8a09-765794883524> | 2011-07-30 00:30:44 +0000 |
commit | d7ce700605e1af0e455e31ec11f19ff21d26b525 (patch) | |
tree | 243b582ac3350e8c6ce6ca96fff13805318fd65c /StdLib | |
parent | f766dd76fde231ecd4f2e9faf99293e90902cebb (diff) | |
download | edk2-platforms-d7ce700605e1af0e455e31ec11f19ff21d26b525.tar.xz |
Add Socket Libraries.
Add Posix functions for porting compatibility.
Fix compliance issues with ISO/IEC 9899:199409
New Functions:
setenv(), fparseln(), GetFileNameFromPath(), rename(),
realpath(), setprogname(), getprogname(), strlcat(), strlcpy(),
strsep(), setitimer(), getitimer(), timegm(), getopt(), basename(),
mkstemp(), ffs(), vsnprintf(), snprintf(), getpass(), usleep(), select(),
writev(), strcasecmp(), getcwd(), chdir(), tcgetpgrp(), getpgrp(), gettimeofday(),
bcopy(),
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12061 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'StdLib')
199 files changed, 36115 insertions, 686 deletions
diff --git a/StdLib/BsdSocketLib/BsdSocketLib.inf b/StdLib/BsdSocketLib/BsdSocketLib.inf new file mode 100644 index 0000000000..3337acb3a9 --- /dev/null +++ b/StdLib/BsdSocketLib/BsdSocketLib.inf @@ -0,0 +1,115 @@ +#/** @file
+# Component description file for the socket library.
+#
+# This module implements the socket library.
+# Copyright (c) 2011, Intel Corporation
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BsdSocketLib
+ FILE_GUID = E7A79769-DD6E-48f7-B90B-D4C510AC1741
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = BsdSocketLib
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ accept.c
+ base64.c
+ bind.c
+ close.c
+ connect.c
+ gethostbydns.c
+ gethostbyht.c
+ gethostbynis.c
+ gethostname.c
+ gethostnamadr.c
+ gethostbynis.c
+ getnetbydns.c
+ getnetbynis.c
+ getnetbyht.c
+ getnetnamadr.c
+ getpeername.c
+ getprotoent.c
+ getprotoname.c
+ getproto.c
+ getservbyname.c
+ getservbyport.c
+ getservent.c
+ getsockname.c
+ getsockopt.c
+ herror.c
+# inet_addr.c
+# inet_lnaof.c
+# inet_makeaddr.c
+ inet_net_ntop.c
+ inet_net_pton.c
+ inet_neta.c
+# inet_netof.c
+# inet_network.c
+# inet_ntoa.c
+# inet_ntop.c
+ inet_pton.c
+ listen.c
+ map_v4v6.c
+ ns_addr.c
+ ns_name.c
+ ns_netint.c
+ ns_ntoa.c
+ ns_parse.c
+ ns_print.c
+ ns_ttl.c
+ nsap_addr.c
+ poll.c
+ read.c
+ recv.c
+ recvfrom.c
+ res_comp.c
+ res_config.h
+ res_data.c
+ res_debug.c
+ res_init.c
+ res_mkquery.c
+ res_mkupdate.c
+ res_query.c
+ res_send.c
+ res_update.c
+ send.c
+ sendto.c
+ sethostname.c
+ setsockopt.c
+ shutdown.c
+ socket.c
+ SocketInternals.h
+ write.c
+
+[Packages]
+ StdLib/StdLib.dec
+ StdLibPrivateInternalFiles/DoNotUse.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+# SocketPkg/SocketPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ DevUtility
+ UefiBootServicesTableLib
+ UefiLib
+
+[Protocols]
+ gEfiSocketServiceBindingProtocolGuid
+ gEfiSocketProtocolGuid
diff --git a/StdLib/BsdSocketLib/SocketInternals.h b/StdLib/BsdSocketLib/SocketInternals.h new file mode 100644 index 0000000000..57eed94f3c --- /dev/null +++ b/StdLib/BsdSocketLib/SocketInternals.h @@ -0,0 +1,190 @@ +/** @file
+ Definitions for the socket library.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SOCKET_INTERNALS_H_
+#define _SOCKET_INTERNALS_H_
+
+#include <Uefi.h>
+
+//----------------------------------------------------------------------
+//
+// The following private files are required to support file descriptors
+//
+
+#include <kfile.h>
+#include <MainData.h>
+
+#include <efi/SysEfi.h>
+
+//
+// End of private files
+//
+//----------------------------------------------------------------------
+
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include <Protocol/EfiSocket.h>
+#include <Protocol/ServiceBinding.h>
+
+#include <sys/errno.h>
+#include <sys/poll.h>
+#include <sys/EfiSysCall.h>
+#include <sys/socket.h>
+
+//------------------------------------------------------------------------------
+// Support Routines
+//------------------------------------------------------------------------------
+
+/**
+ Translate from the socket file descriptor to the socket protocol.
+
+ @param [in] s Socket file descriptor returned from ::socket.
+
+ @param [in] ppDescriptor Address to receive the descriptor structure
+ address for the file
+ @param [in] pErrno Address of the errno variable
+
+ @returns A pointer to the socket protocol structure or NULL if
+ an invalid file descriptor was passed in.
+
+ **/
+EFI_SOCKET_PROTOCOL *
+BslFdToSocketProtocol (
+ int s,
+ struct __filedes ** ppDescriptor,
+ int * pErrno
+ );
+
+/**
+ Close the socket
+
+ @param [in] pDescriptor Descriptor address for the file
+
+ @returns This routine returns 0 upon success and -1 upon failure.
+ In the case of failure, errno contains more information.
+
+**/
+INT32
+BslSocketClose (
+ struct __filedes * pDescriptor
+ );
+
+/**
+ Worker routine to close the socket.
+
+ @param [in] pSocketProtocol Socket protocol structure address
+
+ @param [in] pErrno Address of the errno variable
+
+ @retval EFI_SUCCESS Successfully closed the socket
+
+**/
+EFI_STATUS
+BslSocketCloseWork (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN int * pErrno
+ );
+
+/**
+ Poll the socket for activity
+
+ @param [in] pDescriptor Descriptor address for the file
+
+ @param [in] Events Mask of events to detect
+
+ @returns Detected events for the socket
+
+ **/
+short
+BslSocketPoll (
+ IN struct __filedes * pDescriptor,
+ IN short Events
+ );
+
+/**
+ Build a file descriptor for a socket.
+
+ @param [in] pSocketProtocol Socket protocol structure address
+
+ @param [in] pErrno Address of the errno variable
+
+ @returns The file descriptor for the socket or -1 if an error occurs.
+
+ **/
+int
+BslSocketProtocolToFd (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN int * pErrno
+ );
+
+/**
+ Read support routine for sockets
+
+ @param [in] pDescriptor Descriptor address for the file
+ @param [in] pOffset File offset
+ @param [in] LengthInBytes Number of bytes to read
+ @param [in] pBuffer Address of the buffer to receive the data
+
+ @returns The number of bytes read or -1 if an error occurs.
+
+**/
+ssize_t
+BslSocketRead (
+ struct __filedes *pDescriptor,
+ off_t * pOffset,
+ size_t LengthInBytes,
+ void * pBuffer
+ );
+
+/**
+ Write support routine for sockets
+
+ @param [in] pDescriptor Descriptor address for the file
+ @param [in] pOffset File offset
+ @param [in] LengthInBytes Number of bytes to write
+ @param [in] pBuffer Address of the data
+
+ @returns The number of bytes written or -1 if an error occurs.
+
+**/
+ssize_t
+BslSocketWrite (
+ struct __filedes *pDescriptor,
+ off_t * pOffset,
+ size_t LengthInBytes,
+ const void * pBuffer
+ );
+
+/**
+ Validate the socket's file descriptor
+
+ @param [in] pDescriptor Descriptor for the file
+
+ @param [in] pErrno Address of the errno variable
+
+ @returns A pointer to the socket protocol structure or NULL if
+ an invalid file descriptor was passed in.
+
+ **/
+EFI_SOCKET_PROTOCOL *
+BslValidateSocketFd (
+ struct __filedes * pDescriptor,
+ int * pErrno
+ );
+
+//------------------------------------------------------------------------------
+
+#endif // _SOCKET_INTERNALS_H_
diff --git a/StdLib/BsdSocketLib/Socklib_internals.h b/StdLib/BsdSocketLib/Socklib_internals.h new file mode 100644 index 0000000000..802aaebcc6 --- /dev/null +++ b/StdLib/BsdSocketLib/Socklib_internals.h @@ -0,0 +1,42 @@ +/** @file
+ Definitions for the socket library functions that are used internally.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SOCKLIB_INTERNALS_H_
+#define _SOCKLIB_INTERNALS_H_
+
+void _sethosthtent(int);
+void _endhosthtent(void);
+void _sethostdnsent(int);
+void _endhostdnsent(void);
+void _setnethtent(int);
+void _endnethtent(void);
+void _setnetdnsent(int);
+void _endnetdnsent(void);
+
+struct hostent * _gethostbyhtname(const char *, int);
+struct hostent * _gethostbydnsname(const char *, int);
+struct hostent * _gethostbynisname(const char *, int);
+struct hostent * _gethostbyhtaddr(const char *, int, int);
+struct hostent * _gethostbydnsaddr(const char *, int, int);
+struct hostent * _gethostbynisaddr(const char *, int, int);
+struct netent * _getnetbyhtname(const char *);
+struct netent * _getnetbydnsname(const char *);
+struct netent * _getnetbynisname(const char *);
+struct netent * _getnetbyhtaddr(unsigned long, int);
+struct netent * _getnetbydnsaddr(unsigned long, int);
+struct netent * _getnetbynisaddr(unsigned long, int);
+void _map_v4v6_address(const char *src, char *dst);
+void _map_v4v6_hostent(struct hostent *hp, char **bp, int *len);
+#endif
+
diff --git a/StdLib/BsdSocketLib/accept.c b/StdLib/BsdSocketLib/accept.c new file mode 100644 index 0000000000..3dbfe97013 --- /dev/null +++ b/StdLib/BsdSocketLib/accept.c @@ -0,0 +1,157 @@ +/** @file
+ Implement the accept API.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <SocketInternals.h>
+
+
+/**
+ Worker routine for ::Accept and ::AcceptNB
+
+ @param [in] s Socket file descriptor returned from ::socket.
+
+ @param [in] bBlocking TRUE if this is a blocking call
+ @param [in] address Address of a buffer to receive the remote network address.
+
+ @param [in, out] address_len Address of a buffer containing the Length in bytes
+ of the remote network address buffer. Upon return,
+ contains the length of the remote network address.
+
+ @returns ::accept returns zero if successful and -1 when an error occurs.
+ In the case of an error, errno contains more details.
+
+ **/
+int
+AcceptWork (
+ int s,
+ BOOLEAN bBlocking,
+ struct sockaddr * address,
+ socklen_t * address_len
+ )
+{
+ INT32 NewSocketFd;
+ struct __filedes * pDescriptor;
+ EFI_SOCKET_PROTOCOL * pNewSocket;
+ EFI_SOCKET_PROTOCOL * pSocketProtocol;
+ EFI_STATUS Status;
+
+ //
+ // Assume failure
+ //
+ NewSocketFd = -1;
+
+ //
+ // Locate the context for this socket
+ //
+ pSocketProtocol = BslFdToSocketProtocol ( s,
+ &pDescriptor,
+ &errno );
+ if ( NULL != pSocketProtocol ) {
+ //
+ // TODO: Update bBlocking by anding with check for NON_BLOCKING
+ //
+
+ //
+ // Attempt to accept a new network connection
+ //
+ do {
+ Status = pSocketProtocol->pfnAccept ( pSocketProtocol,
+ address,
+ address_len,
+ &pNewSocket,
+ &errno );
+ } while ( bBlocking && ( EFI_NOT_READY == Status ));
+
+ //
+ // Convert the protocol to a socket
+ //
+ NewSocketFd = BslSocketProtocolToFd ( pNewSocket, &errno );
+ if ( -1 == NewSocketFd ) {
+ //
+ // Close the socket
+ //
+ BslSocketCloseWork ( pNewSocket, NULL );
+ }
+ }
+
+ //
+ // Return the new socket file descriptor
+ //
+ return NewSocketFd;
+}
+
+
+/**
+ Accept a network connection.
+
+ The ::accept routine waits for a network connection to the socket.
+ It is able to return the remote network address to the caller if
+ requested. The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html">POSIX</a>
+ documentation is available online.
+
+ @param [in] s Socket file descriptor returned from ::socket.
+
+ @param [in] address Address of a buffer to receive the remote network address.
+
+ @param [in, out] address_len Address of a buffer containing the Length in bytes
+ of the remote network address buffer. Upon return,
+ contains the length of the remote network address.
+
+ @returns ::accept returns zero if successful and -1 when an error occurs.
+ In the case of an error, errno contains more details.
+
+ **/
+int
+accept (
+ int s,
+ struct sockaddr * address,
+ socklen_t * address_len
+ )
+{
+ //
+ // Wait for the accept call to complete
+ //
+ return AcceptWork ( s, TRUE, address, address_len );
+}
+
+
+/**
+ Non blocking version of accept.
+
+ See ::accept
+
+ @param [in] s Socket file descriptor returned from ::socket.
+
+ @param [in] address Address of a buffer to receive the remote network address.
+
+ @param [in, out] address_len Address of a buffer containing the Length in bytes
+ of the remote network address buffer. Upon return,
+ contains the length of the remote network address.
+
+ @returns This routine returns zero if successful and -1 when an error occurs.
+ In the case of an error, errno contains more details.
+
+ **/
+int
+AcceptNB (
+ int s,
+ struct sockaddr * address,
+ socklen_t * address_len
+ )
+{
+ //
+ // Attempt to accept a network connection
+ //
+ return AcceptWork ( s, FALSE, address, address_len );
+}
diff --git a/StdLib/BsdSocketLib/base64.c b/StdLib/BsdSocketLib/base64.c new file mode 100644 index 0000000000..593360535c --- /dev/null +++ b/StdLib/BsdSocketLib/base64.c @@ -0,0 +1,357 @@ +/*
+ * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software. No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+/*
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by Intel Corporation and
+ * its contributors.
+ *
+ * 4. Neither the name of Intel Corporation or its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#if !defined(LINT) && !defined(CODECENTER)
+static char rcsid[] = "$Id: base64.c,v 1.1.1.1 2003/11/19 01:51:25 kyu3 Exp $";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define Assert(Cond) if (!(Cond)) abort()
+
+static const char Base64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char Pad64 = '=';
+
+/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
+ The following encoding technique is taken from RFC 1521 by Borenstein
+ and Freed. It is reproduced here in a slightly edited form for
+ convenience.
+
+ A 65-character subset of US-ASCII is used, enabling 6 bits to be
+ represented per printable character. (The extra 65th character, "=",
+ is used to signify a special processing function.)
+
+ The encoding process represents 24-bit groups of input bits as output
+ strings of 4 encoded characters. Proceeding from left to right, a
+ 24-bit input group is formed by concatenating 3 8-bit input groups.
+ These 24 bits are then treated as 4 concatenated 6-bit groups, each
+ of which is translated into a single digit in the base64 alphabet.
+
+ Each 6-bit group is used as an index into an array of 64 printable
+ characters. The character referenced by the index is placed in the
+ output string.
+
+ Table 1: The Base64 Alphabet
+
+ Value Encoding Value Encoding Value Encoding Value Encoding
+ 0 A 17 R 34 i 51 z
+ 1 B 18 S 35 j 52 0
+ 2 C 19 T 36 k 53 1
+ 3 D 20 U 37 l 54 2
+ 4 E 21 V 38 m 55 3
+ 5 F 22 W 39 n 56 4
+ 6 G 23 X 40 o 57 5
+ 7 H 24 Y 41 p 58 6
+ 8 I 25 Z 42 q 59 7
+ 9 J 26 a 43 r 60 8
+ 10 K 27 b 44 s 61 9
+ 11 L 28 c 45 t 62 +
+ 12 M 29 d 46 u 63 /
+ 13 N 30 e 47 v
+ 14 O 31 f 48 w (pad) =
+ 15 P 32 g 49 x
+ 16 Q 33 h 50 y
+
+ Special processing is performed if fewer than 24 bits are available
+ at the end of the data being encoded. A full encoding quantum is
+ always completed at the end of a quantity. When fewer than 24 input
+ bits are available in an input group, zero bits are added (on the
+ right) to form an integral number of 6-bit groups. Padding at the
+ end of the data is performed using the '=' character.
+
+ Since all base64 input is an integral number of octets, only the
+ -------------------------------------------------
+ following cases can arise:
+
+ (1) the final quantum of encoding input is an integral
+ multiple of 24 bits; here, the final unit of encoded
+ output will be an integral multiple of 4 characters
+ with no "=" padding,
+ (2) the final quantum of encoding input is exactly 8 bits;
+ here, the final unit of encoded output will be two
+ characters followed by two "=" padding characters, or
+ (3) the final quantum of encoding input is exactly 16 bits;
+ here, the final unit of encoded output will be three
+ characters followed by one "=" padding character.
+ */
+
+int
+b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) {
+ size_t datalength = 0;
+ u_char input[3];
+ u_char output[4];
+ size_t i;
+
+ while (2 < srclength) {
+ input[0] = *src++;
+ input[1] = *src++;
+ input[2] = *src++;
+ srclength -= 3;
+
+ output[0] = input[0] >> 2;
+ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+ output[3] = input[2] & 0x3f;
+ Assert(output[0] < 64);
+ Assert(output[1] < 64);
+ Assert(output[2] < 64);
+ Assert(output[3] < 64);
+
+ if (datalength + 4 > targsize)
+ return (-1);
+ target[datalength++] = Base64[output[0]];
+ target[datalength++] = Base64[output[1]];
+ target[datalength++] = Base64[output[2]];
+ target[datalength++] = Base64[output[3]];
+ }
+
+ /* Now we worry about padding. */
+ if (0 != srclength) {
+ /* Get what's left. */
+ input[0] = input[1] = input[2] = '\0';
+ for (i = 0; i < srclength; i++)
+ input[i] = *src++;
+
+ output[0] = input[0] >> 2;
+ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+ Assert(output[0] < 64);
+ Assert(output[1] < 64);
+ Assert(output[2] < 64);
+
+ if (datalength + 4 > targsize)
+ return (-1);
+ target[datalength++] = Base64[output[0]];
+ target[datalength++] = Base64[output[1]];
+ if (srclength == 1)
+ target[datalength++] = Pad64;
+ else
+ target[datalength++] = Base64[output[2]];
+ target[datalength++] = Pad64;
+ }
+ if (datalength >= targsize)
+ return (-1);
+ target[datalength] = '\0'; /* Returned value doesn't count \0. */
+ return ((int)datalength);
+}
+
+/* skips all whitespace anywhere.
+ converts characters, four at a time, starting at (or after)
+ src from base - 64 numbers into three 8 bit bytes in the target area.
+ it returns the number of data bytes stored at the target, or -1 on error.
+ */
+
+int
+b64_pton(
+ char const *src,
+ u_char *target,
+ size_t targsize
+ )
+{
+ int tarindex, state, ch;
+ char *pos;
+
+ state = 0;
+ tarindex = 0;
+
+ while ((ch = *src++) != '\0') {
+ if (isspace(ch)) /* Skip whitespace anywhere. */
+ continue;
+
+ if (ch == Pad64)
+ break;
+
+ pos = strchr(Base64, ch);
+ if (pos == 0) /* A non-base64 character. */
+ return (-1);
+
+ switch (state) {
+ case 0:
+ if (target) {
+ if ((size_t)tarindex >= targsize)
+ return (-1);
+ target[tarindex] = (u_char)((pos - Base64) << 2);
+ }
+ state = 1;
+ break;
+ case 1:
+ if (target) {
+ if ((size_t)tarindex + 1 >= targsize)
+ return (-1);
+ target[tarindex] |= (u_char)((pos - Base64) >> 4);
+ target[tarindex+1] = (u_char)(((pos - Base64) & 0x0f)
+ << 4) ;
+ }
+ tarindex++;
+ state = 2;
+ break;
+ case 2:
+ if (target) {
+ if ((size_t)tarindex + 1 >= targsize)
+ return (-1);
+ target[tarindex] |= (u_char)((pos - Base64) >> 2);
+ target[tarindex+1] = (u_char)(((pos - Base64) & 0x03)
+ << 6);
+ }
+ tarindex++;
+ state = 3;
+ break;
+ case 3:
+ if (target) {
+ if ((size_t)tarindex >= targsize)
+ return (-1);
+ target[tarindex] |= (u_char)(pos - Base64);
+ }
+ tarindex++;
+ state = 0;
+ break;
+ default:
+ abort();
+ }
+ }
+
+ /*
+ * We are done decoding Base-64 chars. Let's see if we ended
+ * on a byte boundary, and/or with erroneous trailing characters.
+ */
+
+ if (ch == Pad64) { /* We got a pad char. */
+ ch = *src++; /* Skip it, get next. */
+ switch (state) {
+ case 0: /* Invalid = in first position */
+ case 1: /* Invalid = in second position */
+ return (-1);
+
+ case 2: /* Valid, means one byte of info */
+ /* Skip any number of spaces. */
+ for ((void)NULL; ch != '\0'; ch = *src++)
+ if (!isspace(ch))
+ break;
+ /* Make sure there is another trailing = sign. */
+ if (ch != Pad64)
+ return (-1);
+ ch = *src++; /* Skip the = */
+ /* Fall through to "single trailing =" case. */
+ /* FALLTHROUGH */
+
+ case 3: /* Valid, means two bytes of info */
+ /*
+ * We know this char is an =. Is there anything but
+ * whitespace after it?
+ */
+ for ((void)NULL; ch != '\0'; ch = *src++)
+ if (!isspace(ch))
+ return (-1);
+
+ /*
+ * Now make sure for cases 2 and 3 that the "extra"
+ * bits that slopped past the last full byte were
+ * zeros. If we don't check them, they become a
+ * subliminal channel.
+ */
+ if (target && target[tarindex] != 0)
+ return (-1);
+ }
+ } else {
+ /*
+ * We ended by seeing the end of the string. Make sure we
+ * have no partial bytes lying around.
+ */
+ if (state != 0)
+ return (-1);
+ }
+
+ return (tarindex);
+}
diff --git a/StdLib/BsdSocketLib/bind.c b/StdLib/BsdSocketLib/bind.c new file mode 100644 index 0000000000..fc24ea420a --- /dev/null +++ b/StdLib/BsdSocketLib/bind.c @@ -0,0 +1,72 @@ +/** @file
+ Implement the bind API.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <SocketInternals.h>
+
+
+/**
+ Bind a name to a socket.
+
+ The ::bind routine connects a name to a socket on the local machine. The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html">POSIX</a>
+ documentation for the bind routine is available online for reference.
+
+ @param [in] s Socket file descriptor returned from ::socket.
+
+ @param [in] name Address of a sockaddr structure that contains the
+ connection point on the local machine. An IPv4 address
+ of INADDR_ANY specifies that the connection is made to
+ all of the network stacks on the platform. Specifying a
+ specific IPv4 address restricts the connection to the
+ network stack supporting that address. Specifying zero
+ for the port causes the network layer to assign a port
+ number from the dynamic range. Specifying a specific
+ port number causes the network layer to use that port.
+
+ @param [in] namelen Specifies the length in bytes of the sockaddr structure.
+
+ @returns The bind routine returns zero (0) if successful and -1 upon failure.
+
+ **/
+int
+bind (
+ IN int s,
+ IN const struct sockaddr * name,
+ IN socklen_t namelen
+ )
+{
+ int BindStatus;
+ EFI_SOCKET_PROTOCOL * pSocketProtocol;
+ EFI_STATUS Status;
+
+ //
+ // Locate the context for this socket
+ //
+ pSocketProtocol = BslFdToSocketProtocol ( s, NULL, &errno );
+ if ( NULL != pSocketProtocol ) {
+ //
+ // Bind the socket
+ //
+ Status = pSocketProtocol->pfnBind ( pSocketProtocol,
+ name,
+ namelen,
+ &errno );
+ }
+
+ //
+ // Return the operation stauts
+ //
+ BindStatus = ( 0 == errno ) ? 0 : -1;
+ return BindStatus;
+}
diff --git a/StdLib/BsdSocketLib/close.c b/StdLib/BsdSocketLib/close.c new file mode 100644 index 0000000000..7d70e4f126 --- /dev/null +++ b/StdLib/BsdSocketLib/close.c @@ -0,0 +1,116 @@ +/** @file
+ Implement the close API.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <SocketInternals.h>
+
+
+/**
+ Worker routine to close the socket.
+
+ @param [in] pSocketProtocol Socket protocol structure address
+
+ @param [in] pErrno Address of the errno variable
+
+ @retval EFI_SUCCESS Successfully closed the socket
+
+**/
+EFI_STATUS
+BslSocketCloseWork (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN int * pErrno
+ )
+{
+ EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding;
+ EFI_STATUS Status;
+
+ //
+ // Start closing the socket
+ //
+ Status = pSocketProtocol->pfnCloseStart ( pSocketProtocol,
+ FALSE,
+ pErrno );
+
+ //
+ // Wait for the socket to close or an error
+ //
+ while ( EFI_NOT_READY == Status ) {
+ Status = pSocketProtocol->pfnClosePoll ( pSocketProtocol,
+ pErrno );
+ }
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Locate the socket protocol
+ //
+ Status = gBS->LocateProtocol ( &gEfiSocketServiceBindingProtocolGuid,
+ NULL,
+ (VOID **) &pServiceBinding );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Release the handle
+ //
+ Status = pServiceBinding->DestroyChild ( pServiceBinding,
+ pSocketProtocol->SocketHandle );
+ }
+ if ( EFI_ERROR ( Status )) {
+ *pErrno = EIO;
+ }
+ }
+ else {
+ DEBUG (( DEBUG_ERROR,
+ "ERROR - Failed to close the socket: %r\r\n",
+ Status ));
+ *pErrno = EIO;
+ }
+
+ //
+ // Return the close status
+ //
+ return Status;
+}
+
+
+/**
+ Close the socket
+
+ @param [in] pDescriptor Descriptor address for the file
+
+ @returns This routine returns 0 upon success and -1 upon failure.
+ In the case of failure, errno contains more information.
+
+**/
+int
+BslSocketClose (
+ struct __filedes * pDescriptor
+ )
+{
+ int CloseStatus;
+ EFI_SOCKET_PROTOCOL * pSocketProtocol;
+
+ //
+ // Locate the socket protocol
+ //
+ pSocketProtocol = BslValidateSocketFd ( pDescriptor, &errno );
+ if ( NULL != pSocketProtocol ) {
+ //
+ // Close the socket
+ //
+ BslSocketCloseWork ( pSocketProtocol, &errno );
+ }
+
+ //
+ // Return the close status
+ //
+ CloseStatus = ( errno == 0 ) ? 0 : -1;
+ return CloseStatus;
+}
diff --git a/StdLib/BsdSocketLib/connect.c b/StdLib/BsdSocketLib/connect.c new file mode 100644 index 0000000000..e02762efa3 --- /dev/null +++ b/StdLib/BsdSocketLib/connect.c @@ -0,0 +1,94 @@ +/** @file
+ Implement the connect API.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <SocketInternals.h>
+
+
+/**
+ Connect to a remote system via the network.
+
+ The ::connect routine attempts to establish a connection to a
+ socket on the local or remote system using the specified address.
+ The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html">POSIX</a>
+ documentation is available online.
+
+ There are three states associated with a connection:
+ <ul>
+ <li>Not connected</li>
+ <li>Connection in progress</li>
+ <li>Connected</li>
+ </ul>
+ In the "Not connected" state, calls to ::connect start the connection
+ processing and update the state to "Connection in progress". During
+ the "Connection in progress" state, connect polls for connection completion
+ and moves the state to "Connected" after the connection is established.
+ Note that these states are only visible when the file descriptor is marked
+ with O_NONBLOCK. Also, the POLL_WRITE bit is set when the connection
+ completes and may be used by poll or select as an indicator to call
+ connect again.
+
+ @param [in] s Socket file descriptor returned from ::socket.
+
+ @param [in] address Network address of the remote system
+
+ @param [in] address_len Length of the remote network address
+
+ @returns ::connect returns zero if successful and -1 when an error occurs.
+ In the case of an error, errno contains more details.
+
+ **/
+int
+connect (
+ int s,
+ const struct sockaddr * address,
+ socklen_t address_len
+ )
+{
+ BOOLEAN bBlocking;
+ int ConnectStatus;
+ struct __filedes * pDescriptor;
+ EFI_SOCKET_PROTOCOL * pSocketProtocol;
+ EFI_STATUS Status;
+
+ //
+ // Locate the context for this socket
+ //
+ pSocketProtocol = BslFdToSocketProtocol ( s,
+ &pDescriptor,
+ &errno );
+ if ( NULL != pSocketProtocol ) {
+ //
+ // TODO: Check for NON_BLOCKING
+ //
+ bBlocking = TRUE;
+
+ //
+ // Attempt to connect to a remote system
+ //
+ do {
+ errno = 0;
+ Status = pSocketProtocol->pfnConnect ( pSocketProtocol,
+ address,
+ address_len,
+ &errno );
+ } while ( bBlocking && ( EFI_NOT_READY == Status ));
+ }
+
+ //
+ // Return the new socket file descriptor
+ //
+ ConnectStatus = (0 == errno) ? 0 : -1;
+ return ConnectStatus;
+}
diff --git a/StdLib/BsdSocketLib/errno.c b/StdLib/BsdSocketLib/errno.c new file mode 100644 index 0000000000..360609bd80 --- /dev/null +++ b/StdLib/BsdSocketLib/errno.c @@ -0,0 +1,18 @@ +/** @file
+ errno variable
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <sys/errno.h>
+
+
+int errno;
diff --git a/StdLib/BsdSocketLib/gethostbydns.c b/StdLib/BsdSocketLib/gethostbydns.c new file mode 100644 index 0000000000..25e7c3b142 --- /dev/null +++ b/StdLib/BsdSocketLib/gethostbydns.c @@ -0,0 +1,814 @@ +/*
+ * ++Copyright++ 1985, 1988, 1993
+ * -
+ * Copyright (c) 1985, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+/*
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by Intel Corporation and
+ * its contributors.
+ *
+ * 4. Neither the name of Intel Corporation or its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
+static char fromrcsid[] = "From: Id: gethnamaddr.c,v 8.23 1998/04/07 04:59:46 vixie Exp $";
+static char rcsid[] = "$Id: gethostbydns.c,v 1.1.1.1 2003/11/19 01:51:27 kyu3 Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <ctype.h>
+#include <errno.h>
+#ifdef _ORG_FREEBSD_
+#include <syslog.h>
+#else
+#include <stdlib.h>
+u_int32_t _getlong(const u_char *src);
+u_int16_t _getshort(const u_char *src);
+#endif
+
+#include "res_config.h"
+#include "Socklib_internals.h"
+
+#define SPRINTF(x) ((size_t)sprintf x)
+
+#define MAXALIASES 35
+#define MAXADDRS 35
+
+static const char AskedForGot[] =
+ "gethostby*.gethostanswer: asked for \"%s\", got \"%s\"";
+
+static char *h_addr_ptrs[MAXADDRS + 1];
+
+static struct hostent host;
+static char *host_aliases[MAXALIASES];
+static char hostbuf[8*1024];
+static u_char host_addr[16]; /* IPv4 or IPv6 */
+
+#ifdef RESOLVSORT
+static void addrsort(char **, int);
+#endif
+
+#if PACKETSZ > 1024
+#define MAXPACKET PACKETSZ
+#else
+#define MAXPACKET 1024
+#endif
+
+typedef union {
+ HEADER hdr;
+ u_char buf[MAXPACKET];
+} querybuf;
+
+typedef union {
+ int32_t al;
+ char ac;
+} align;
+
+extern int h_errno;
+int _dns_ttl_;
+
+#ifdef DEBUG_RES
+static void
+dprintf(char *msg, int num)
+{
+ if (_res.options & RES_DEBUG) {
+ int save = errno;
+
+ printf(msg, num);
+ errno = save;
+ }
+}
+#else
+# define dprintf(msg, num) /*nada*/
+#endif
+
+#define BOUNDED_INCR(x) \
+ do { \
+ cp += x; \
+ if (cp > eom) { \
+ h_errno = NO_RECOVERY; \
+ return (NULL); \
+ } \
+ } while (0)
+
+#define BOUNDS_CHECK(ptr, count) \
+ do { \
+ if ((ptr) + (count) > eom) { \
+ h_errno = NO_RECOVERY; \
+ return (NULL); \
+ } \
+ } while (0)
+
+static struct hostent *
+gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype)
+{
+ register const HEADER *hp;
+ register const u_char *cp;
+ register int n;
+ const u_char *eom, *erdata;
+ char *bp, **ap, **hap;
+ int type, class, buflen, ancount, qdcount;
+ int haveanswer, had_error;
+ int toobig = 0;
+ char tbuf[MAXDNAME];
+ const char *tname;
+ int (*name_ok)(const char *);
+
+ tname = qname;
+ host.h_name = NULL;
+ eom = answer->buf + anslen;
+ switch (qtype) {
+ case T_A:
+ case T_AAAA:
+ name_ok = res_hnok;
+ break;
+ case T_PTR:
+ name_ok = res_dnok;
+ break;
+ default:
+ h_errno = NO_RECOVERY;
+ return (NULL); /* XXX should be abort(); */
+ }
+ /*
+ * find first satisfactory answer
+ */
+ hp = &answer->hdr;
+ ancount = ntohs(hp->ancount);
+ qdcount = ntohs(hp->qdcount);
+ bp = hostbuf;
+ buflen = sizeof hostbuf;
+ cp = answer->buf;
+ BOUNDED_INCR(HFIXEDSZ);
+ if (qdcount != 1) {
+ h_errno = NO_RECOVERY;
+ return (NULL);
+ }
+ n = dn_expand(answer->buf, eom, cp, bp, buflen);
+ if ((n < 0) || !(*name_ok)(bp)) {
+ h_errno = NO_RECOVERY;
+ return (NULL);
+ }
+ BOUNDED_INCR(n + QFIXEDSZ);
+ if (qtype == T_A || qtype == T_AAAA) {
+ /* res_send() has already verified that the query name is the
+ * same as the one we sent; this just gets the expanded name
+ * (i.e., with the succeeding search-domain tacked on).
+ */
+ n = (int)strlen(bp) + 1; /* for the \0 */
+ if (n >= MAXHOSTNAMELEN) {
+ h_errno = NO_RECOVERY;
+ return (NULL);
+ }
+ host.h_name = bp;
+ bp += n;
+ buflen -= n;
+ /* The qname can be abbreviated, but h_name is now absolute. */
+ qname = host.h_name;
+ }
+ ap = host_aliases;
+ *ap = NULL;
+ host.h_aliases = host_aliases;
+ hap = h_addr_ptrs;
+ *hap = NULL;
+ host.h_addr_list = h_addr_ptrs;
+ haveanswer = 0;
+ had_error = 0;
+ _dns_ttl_ = -1;
+ while (ancount-- > 0 && cp < eom && !had_error) {
+ n = dn_expand(answer->buf, eom, cp, bp, buflen);
+ if ((n < 0) || !(*name_ok)(bp)) {
+ had_error++;
+ continue;
+ }
+ cp += n; /* name */
+ BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
+ type = _getshort(cp);
+ cp += INT16SZ; /* type */
+ class = _getshort(cp);
+ cp += INT16SZ; /* class */
+ if (qtype == T_A && type == T_A)
+ _dns_ttl_ = _getlong(cp);
+ cp += INT32SZ; /* TTL */
+ n = _getshort(cp);
+ cp += INT16SZ; /* len */
+ BOUNDS_CHECK(cp, n);
+ erdata = cp + n;
+ if (class != C_IN) {
+ /* XXX - debug? syslog? */
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
+ if (ap >= &host_aliases[MAXALIASES-1])
+ continue;
+ n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
+ if ((n < 0) || !(*name_ok)(tbuf)) {
+ had_error++;
+ continue;
+ }
+ cp += n;
+ if (cp != erdata) {
+ h_errno = NO_RECOVERY;
+ return (NULL);
+ }
+ /* Store alias. */
+ *ap++ = bp;
+ n = (int)strlen(bp) + 1; /* for the \0 */
+ if (n >= MAXHOSTNAMELEN) {
+ had_error++;
+ continue;
+ }
+ bp += n;
+ buflen -= n;
+ /* Get canonical name. */
+ n = (int)strlen(tbuf) + 1; /* for the \0 */
+ if (n > buflen || n >= MAXHOSTNAMELEN) {
+ had_error++;
+ continue;
+ }
+ strcpy(bp, tbuf);
+ host.h_name = bp;
+ bp += n;
+ buflen -= n;
+ continue;
+ }
+ if (qtype == T_PTR && type == T_CNAME) {
+ n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
+ if (n < 0 || !res_dnok(tbuf)) {
+ had_error++;
+ continue;
+ }
+ cp += n;
+ if (cp != erdata) {
+ h_errno = NO_RECOVERY;
+ return (NULL);
+ }
+ /* Get canonical name. */
+ n = (int)strlen(tbuf) + 1; /* for the \0 */
+ if (n > buflen || n >= MAXHOSTNAMELEN) {
+ had_error++;
+ continue;
+ }
+ strcpy(bp, tbuf);
+ tname = bp;
+ bp += n;
+ buflen -= n;
+ continue;
+ }
+ if (type != qtype) {
+#ifdef _ORG_FREEBSD_
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "gethostby*.gethostanswer: asked for \"%s %s %s\", got type \"%s\"",
+ qname, p_class(C_IN), p_type(qtype),
+ p_type(type));
+#endif
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ switch (type) {
+ case T_PTR:
+ if (strcasecmp(tname, bp) != 0) {
+#ifdef _ORG_FREEBSD_
+ syslog(LOG_NOTICE|LOG_AUTH,
+ AskedForGot, qname, bp);
+#endif
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ n = dn_expand(answer->buf, eom, cp, bp, buflen);
+ if ((n < 0) || !res_hnok(bp)) {
+ had_error++;
+ break;
+ }
+#if MULTI_PTRS_ARE_ALIASES
+ cp += n;
+ if (cp != erdata) {
+ h_errno = NO_RECOVERY;
+ return (NULL);
+ }
+ if (!haveanswer)
+ host.h_name = bp;
+ else if (ap < &host_aliases[MAXALIASES-1])
+ *ap++ = bp;
+ else
+ n = -1;
+ if (n != -1) {
+ n = (int)strlen(bp) + 1; /* for the \0 */
+ if (n >= MAXHOSTNAMELEN) {
+ had_error++;
+ break;
+ }
+ bp += n;
+ buflen -= n;
+ }
+ break;
+#else
+ host.h_name = bp;
+ if (_res.options & RES_USE_INET6) {
+ n = strlen(bp) + 1; /* for the \0 */
+ if (n >= MAXHOSTNAMELEN) {
+ had_error++;
+ break;
+ }
+ bp += n;
+ buflen -= n;
+ _map_v4v6_hostent(&host, &bp, &buflen);
+ }
+ h_errno = NETDB_SUCCESS;
+ return (&host);
+#endif
+ case T_A:
+ case T_AAAA:
+ if (strcasecmp(host.h_name, bp) != 0) {
+#ifdef _ORG_FREEBSD_
+ syslog(LOG_NOTICE|LOG_AUTH,
+ AskedForGot, host.h_name, bp);
+#endif
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ if (n != host.h_length) {
+ cp += n;
+ continue;
+ }
+ if (!haveanswer) {
+ register int nn;
+
+ host.h_name = bp;
+ nn = (int)strlen(bp) + 1; /* for the \0 */
+ bp += nn;
+ buflen -= nn;
+ }
+
+ bp += sizeof(align) - ((size_t)bp % sizeof(align));
+
+ if (bp + n >= &hostbuf[sizeof hostbuf]) {
+ dprintf("size (%d) too big\n", n);
+ had_error++;
+ continue;
+ }
+ if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
+ if (!toobig++)
+ dprintf("Too many addresses (%d)\n",
+ MAXADDRS);
+ cp += n;
+ continue;
+ }
+ *hap++ = bp;
+ bcopy(cp, bp, n);
+ bp += n;
+ buflen -= n;
+ cp += n;
+ if (cp != erdata) {
+ h_errno = NO_RECOVERY;
+ return (NULL);
+ }
+ break;
+ default:
+ dprintf("Impossible condition (type=%d)\n", type);
+ h_errno = NO_RECOVERY;
+ return (NULL);
+ /* BIND has abort() here, too risky on bad data */
+ }
+ if (!had_error)
+ haveanswer++;
+ }
+ if (haveanswer) {
+ *ap = NULL;
+ *hap = NULL;
+# if defined(RESOLVSORT)
+ /*
+ * Note: we sort even if host can take only one address
+ * in its return structures - should give it the "best"
+ * address in that case, not some random one
+ */
+ if (_res.nsort && haveanswer > 1 && qtype == T_A)
+ addrsort(h_addr_ptrs, haveanswer);
+# endif /*RESOLVSORT*/
+ if (!host.h_name) {
+ n = (int)strlen(qname) + 1; /* for the \0 */
+ if (n > buflen || n >= MAXHOSTNAMELEN)
+ goto no_recovery;
+ strcpy(bp, qname);
+ host.h_name = bp;
+ bp += n;
+ buflen -= n;
+ }
+ if (_res.options & RES_USE_INET6)
+ _map_v4v6_hostent(&host, &bp, &buflen);
+ h_errno = NETDB_SUCCESS;
+ return (&host);
+ }
+ no_recovery:
+ h_errno = NO_RECOVERY;
+ return (NULL);
+}
+
+struct hostent *
+__dns_getanswer(const char *answer, int anslen, const char *qname, int qtype)
+{
+ switch(qtype) {
+ case T_AAAA:
+ host.h_addrtype = AF_INET6;
+ host.h_length = IN6ADDRSZ;
+ break;
+ case T_A:
+ default:
+ host.h_addrtype = AF_INET;
+ host.h_length = INADDRSZ;
+ break;
+ }
+
+ return(gethostanswer((const querybuf *)answer, anslen, qname, qtype));
+}
+
+struct hostent *
+_gethostbydnsname(const char *name, int af)
+{
+ querybuf buf;
+ register const char *cp;
+ char *bp;
+ int n, size, type, len;
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+
+ switch (af) {
+ case AF_INET:
+ size = INADDRSZ;
+ type = T_A;
+ break;
+ case AF_INET6:
+ size = IN6ADDRSZ;
+ type = T_AAAA;
+ break;
+ default:
+ h_errno = NETDB_INTERNAL;
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+
+ host.h_addrtype = af;
+ host.h_length = size;
+
+ /*
+ * if there aren't any dots, it could be a user-level alias.
+ * this is also done in res_query() since we are not the only
+ * function that looks up host names.
+ */
+ if (!strchr(name, '.') && ( NULL != (cp = __hostalias(name))))
+ name = cp;
+
+ /*
+ * disallow names consisting only of digits/dots, unless
+ * they end in a dot.
+ */
+ if (isdigit(name[0]))
+ for (cp = name;; ++cp) {
+ if (!*cp) {
+ if (*--cp == '.')
+ break;
+ /*
+ * All-numeric, no dot at the end.
+ * Fake up a hostent as if we'd actually
+ * done a lookup.
+ */
+ if (inet_pton(af, name, host_addr) <= 0) {
+ h_errno = HOST_NOT_FOUND;
+ return (NULL);
+ }
+ strncpy(hostbuf, name, MAXDNAME);
+ hostbuf[MAXDNAME] = '\0';
+ bp = hostbuf + MAXDNAME;
+ len = sizeof hostbuf - MAXDNAME;
+ host.h_name = hostbuf;
+ host.h_aliases = host_aliases;
+ host_aliases[0] = NULL;
+ h_addr_ptrs[0] = (char *)host_addr;
+ h_addr_ptrs[1] = NULL;
+ host.h_addr_list = h_addr_ptrs;
+ if (_res.options & RES_USE_INET6)
+ _map_v4v6_hostent(&host, &bp, &len);
+ h_errno = NETDB_SUCCESS;
+ return (&host);
+ }
+ if (!isdigit(*cp) && *cp != '.')
+ break;
+ }
+ if ((isxdigit(name[0]) && strchr(name, ':') != NULL) ||
+ name[0] == ':')
+ for (cp = name;; ++cp) {
+ if (!*cp) {
+ if (*--cp == '.')
+ break;
+ /*
+ * All-IPv6-legal, no dot at the end.
+ * Fake up a hostent as if we'd actually
+ * done a lookup.
+ */
+ if (inet_pton(af, name, host_addr) <= 0) {
+ h_errno = HOST_NOT_FOUND;
+ return (NULL);
+ }
+ strncpy(hostbuf, name, MAXDNAME);
+ hostbuf[MAXDNAME] = '\0';
+ bp = hostbuf + MAXDNAME;
+ len = sizeof hostbuf - MAXDNAME;
+ host.h_name = hostbuf;
+ host.h_aliases = host_aliases;
+ host_aliases[0] = NULL;
+ h_addr_ptrs[0] = (char *)host_addr;
+ h_addr_ptrs[1] = NULL;
+ host.h_addr_list = h_addr_ptrs;
+ h_errno = NETDB_SUCCESS;
+ return (&host);
+ }
+ if (!isxdigit(*cp) && *cp != ':' && *cp != '.')
+ break;
+ }
+
+ if ((n = res_search(name, C_IN, type, buf.buf, sizeof(buf))) < 0) {
+ dprintf("res_search failed (%d)\n", n);
+ return (NULL);
+ }
+ return (gethostanswer(&buf, n, name, type));
+}
+
+struct hostent *
+_gethostbydnsaddr(const char *addr, int len, int af)
+{
+ const u_char *uaddr = (const u_char *)addr;
+ static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
+ static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
+ int n, size;
+ querybuf buf;
+ register struct hostent *hp;
+ char qbuf[MAXDNAME+1], *qp;
+#ifdef SUNSECURITY
+ register struct hostent *rhp;
+ char **haddr;
+ u_long old_options;
+ char hname2[MAXDNAME+1];
+#endif /*SUNSECURITY*/
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+ if (af == AF_INET6 && len == IN6ADDRSZ &&
+ (!bcmp(uaddr, mapped, sizeof mapped) ||
+ !bcmp(uaddr, tunnelled, sizeof tunnelled))) {
+ /* Unmap. */
+ addr += sizeof mapped;
+ uaddr += sizeof mapped;
+ af = AF_INET;
+ len = INADDRSZ;
+ }
+ switch (af) {
+ case AF_INET:
+ size = INADDRSZ;
+ break;
+ case AF_INET6:
+ size = IN6ADDRSZ;
+ break;
+ default:
+ errno = EAFNOSUPPORT;
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+ if (size != len) {
+ errno = EINVAL;
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+ switch (af) {
+ case AF_INET:
+ (void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
+ (uaddr[3] & 0xff),
+ (uaddr[2] & 0xff),
+ (uaddr[1] & 0xff),
+ (uaddr[0] & 0xff));
+ break;
+ case AF_INET6:
+ qp = qbuf;
+ for (n = IN6ADDRSZ - 1; n >= 0; n--) {
+ qp += SPRINTF((qp, "%x.%x.",
+ uaddr[n] & 0xf,
+ (uaddr[n] >> 4) & 0xf));
+ }
+ strcpy(qp, "ip6.int");
+ break;
+ default:
+ abort();
+ }
+ n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf);
+ if (n < 0) {
+ dprintf("res_query failed (%d)\n", n);
+ return (NULL);
+ }
+ if ( NULL == (hp = gethostanswer(&buf, n, qbuf, T_PTR)))
+ return (NULL); /* h_errno was set by gethostanswer() */
+#ifdef SUNSECURITY
+ if (af == AF_INET) {
+ /*
+ * turn off search as the name should be absolute,
+ * 'localhost' should be matched by defnames
+ */
+ strncpy(hname2, hp->h_name, MAXDNAME);
+ hname2[MAXDNAME] = '\0';
+ old_options = _res.options;
+ _res.options &= ~RES_DNSRCH;
+ _res.options |= RES_DEFNAMES;
+ if (!(rhp = gethostbyname(hname2))) {
+#ifdef _ORG_FREEBSD_
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "gethostbyaddr: No A record for %s (verifying [%s])",
+ hname2, inet_ntoa(*((struct in_addr *)addr)));
+#endif
+ _res.options = old_options;
+ h_errno = HOST_NOT_FOUND;
+ return (NULL);
+ }
+ _res.options = old_options;
+ for (haddr = rhp->h_addr_list; *haddr; haddr++)
+ if (!memcmp(*haddr, addr, INADDRSZ))
+ break;
+ if (!*haddr) {
+#ifdef _ORG_FREEBSD_
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "gethostbyaddr: A record of %s != PTR record [%s]",
+ hname2, inet_ntoa(*((struct in_addr *)addr)));
+#endif
+ h_errno = HOST_NOT_FOUND;
+ return (NULL);
+ }
+ }
+#endif /*SUNSECURITY*/
+ hp->h_addrtype = af;
+ hp->h_length = len;
+ bcopy(addr, host_addr, len);
+ h_addr_ptrs[0] = (char *)host_addr;
+ h_addr_ptrs[1] = NULL;
+ if (af == AF_INET && (_res.options & RES_USE_INET6)) {
+ _map_v4v6_address((char*)host_addr, (char*)host_addr);
+ hp->h_addrtype = AF_INET6;
+ hp->h_length = IN6ADDRSZ;
+ }
+ h_errno = NETDB_SUCCESS;
+ return (hp);
+}
+
+#ifdef RESOLVSORT
+static void
+addrsort(char **ap, int num)
+{
+ short i, j;
+ char **p;
+ short aval[MAXADDRS];
+ short needsort = 0;
+
+ p = ap;
+ for (i = 0; i < num; i++, p++) {
+ for (j = 0 ; (unsigned)j < _res.nsort; j++)
+ if (_res.sort_list[j].addr.s_addr ==
+ (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
+ break;
+ aval[i] = j;
+ if (needsort == 0 && i > 0 && j < aval[i-1])
+ needsort = i;
+ }
+ if (!needsort)
+ return;
+
+ while (needsort < num) {
+ for (j = needsort - 1; j >= 0; j--) {
+ if (aval[j] > aval[j+1]) {
+ char *hp;
+
+ i = aval[j];
+ aval[j] = aval[j+1];
+ aval[j+1] = i;
+
+ hp = ap[j];
+ ap[j] = ap[j+1];
+ ap[j+1] = hp;
+
+ } else
+ break;
+ }
+ needsort++;
+ }
+}
+#endif
+void
+_sethostdnsent(int stayopen)
+{
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ return;
+ if (stayopen)
+ _res.options |= RES_STAYOPEN | RES_USEVC;
+}
+
+void
+_endhostdnsent()
+{
+ _res.options &= ~(RES_STAYOPEN | RES_USEVC);
+ res_close();
+}
diff --git a/StdLib/BsdSocketLib/gethostbyht.c b/StdLib/BsdSocketLib/gethostbyht.c new file mode 100644 index 0000000000..ac31f8c915 --- /dev/null +++ b/StdLib/BsdSocketLib/gethostbyht.c @@ -0,0 +1,207 @@ +/*-
+ * Copyright (c) 1985, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by the University of
+ * California, Berkeley, Intel Corporation, and its contributors.
+ *
+ * 4. Neither the name of University, Intel Corporation, or their respective
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS,
+ * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$Id: gethostbyht.c,v 1.1.1.1 2003/11/19 01:51:27 kyu3 Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <arpa/nameser.h> /* XXX */
+#include <resolv.h> /* XXX */
+#include "Socklib_internals.h"
+
+#define MAXALIASES 35
+
+static struct hostent host;
+static char *host_aliases[MAXALIASES];
+static char hostbuf[BUFSIZ+1];
+static FILE *hostf = NULL;
+static u_char host_addr[16]; /* IPv4 or IPv6 */
+static char *h_addr_ptrs[2];
+static int stayopen = 0;
+
+void
+_sethosthtent(int f)
+{
+ if (!hostf)
+ hostf = fopen(_PATH_HOSTS, "r" );
+ else
+ rewind(hostf);
+ stayopen = f;
+}
+
+void
+_endhosthtent()
+{
+ if (hostf && !stayopen) {
+ (void) fclose(hostf);
+ hostf = NULL;
+ }
+}
+
+struct hostent *
+gethostent()
+{
+ char *p;
+ register char *cp, **q;
+ int af, len;
+
+ if (!hostf && ( NULL == (hostf = fopen(_PATH_HOSTS, "r" )))) {
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+ again:
+ if ( NULL == (p = fgets(hostbuf, sizeof hostbuf, hostf))) {
+ h_errno = HOST_NOT_FOUND;
+ return (NULL);
+ }
+ if (*p == '#')
+ goto again;
+ if ( NULL == (cp = strpbrk(p, "#\n")))
+ goto again;
+ *cp = '\0';
+ if ( NULL == (cp = strpbrk(p, " \t")))
+ goto again;
+ *cp++ = '\0';
+ if (inet_pton(AF_INET6, p, host_addr) > 0) {
+ af = AF_INET6;
+ len = IN6ADDRSZ;
+ } else if (inet_pton(AF_INET, p, host_addr) > 0) {
+ if (_res.options & RES_USE_INET6) {
+ _map_v4v6_address((char*)host_addr, (char*)host_addr);
+ af = AF_INET6;
+ len = IN6ADDRSZ;
+ } else {
+ af = AF_INET;
+ len = INADDRSZ;
+ }
+ } else {
+ goto again;
+ }
+ h_addr_ptrs[0] = (char *)host_addr;
+ h_addr_ptrs[1] = NULL;
+ host.h_addr_list = h_addr_ptrs;
+ host.h_length = len;
+ host.h_addrtype = af;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ host.h_name = cp;
+ q = host.h_aliases = host_aliases;
+ if ((cp = strpbrk(cp, " \t\r")) != NULL)
+ *cp++ = '\0';
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &host_aliases[MAXALIASES - 1])
+ *q++ = cp;
+ if ((cp = strpbrk(cp, " \t\r")) != NULL)
+ *cp++ = '\0';
+ }
+ *q = NULL;
+ h_errno = NETDB_SUCCESS;
+ return (&host);
+}
+
+struct hostent *
+_gethostbyhtname(const char *name, int af)
+{
+ register struct hostent *p;
+ register char **cp;
+
+ sethostent(0);
+ while ((p = gethostent()) != NULL) {
+ if (p->h_addrtype != af)
+ continue;
+ if (strcasecmp(p->h_name, name) == 0)
+ break;
+ for (cp = p->h_aliases; *cp != 0; cp++)
+ if (strcasecmp(*cp, name) == 0)
+ goto found;
+ }
+found:
+ endhostent();
+ return (p);
+}
+
+struct hostent *
+_gethostbyhtaddr(const char *addr, int len, int af)
+{
+ register struct hostent *p;
+
+ sethostent(0);
+ while ((p = gethostent()) != NULL)
+ if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len))
+ break;
+ endhostent();
+ return (p);
+}
diff --git a/StdLib/BsdSocketLib/gethostbynis.c b/StdLib/BsdSocketLib/gethostbynis.c new file mode 100644 index 0000000000..72081dc265 --- /dev/null +++ b/StdLib/BsdSocketLib/gethostbynis.c @@ -0,0 +1,134 @@ +/*-
+ * Copyright (c) 1994, Garrett Wollman
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)$Id: gethostbynis.c,v 1.1.1.1 2003/11/19 01:51:27 kyu3 Exp $";
+static char rcsid[] = "$Id: gethostbynis.c,v 1.1.1.1 2003/11/19 01:51:27 kyu3 Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+
+#define MAXALIASES 35
+#define MAXADDRS 35
+
+#ifdef YP
+static char *host_aliases[MAXALIASES];
+static char hostaddr[MAXADDRS];
+static char *host_addrs[2];
+#endif /* YP */
+
+static struct hostent *
+_gethostbynis(const char *name, char *map, int af)
+{
+#ifdef YP
+ register char *cp, **q;
+ char *result;
+ int resultlen;
+ static struct hostent h;
+ static char *domain = (char *)NULL;
+ static char ypbuf[YPMAXRECORD + 2];
+
+ switch(af) {
+ case AF_INET:
+ break;
+ default:
+ case AF_INET6:
+ errno = EAFNOSUPPORT;
+ return NULL;
+ }
+
+ if (domain == (char *)NULL)
+ if (yp_get_default_domain (&domain))
+ return ((struct hostent *)NULL);
+
+ if (yp_match(domain, map, name, strlen(name), &result, &resultlen))
+ return ((struct hostent *)NULL);
+
+ /* avoid potential memory leak */
+ bcopy((char *)result, (char *)&ypbuf, resultlen);
+ ypbuf[resultlen] = '\0';
+ free(result);
+ result = (char *)&ypbuf;
+
+ if ((cp = index(result, '\n')))
+ *cp = '\0';
+
+ cp = strpbrk(result, " \t");
+ *cp++ = '\0';
+ h.h_addr_list = host_addrs;
+ h.h_addr = hostaddr;
+ *((u_long *)h.h_addr) = inet_addr(result);
+ h.h_length = sizeof(u_long);
+ h.h_addrtype = AF_INET;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ h.h_name = cp;
+ q = h.h_aliases = host_aliases;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &host_aliases[MAXALIASES - 1])
+ *q++ = cp;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+ *q = NULL;
+ return (&h);
+#else
+ return (NULL);
+#endif /* YP */
+}
+
+struct hostent *
+_gethostbynisname(const char *name, int af)
+{
+ return _gethostbynis(name, "hosts.byname", af);
+}
+
+struct hostent *
+_gethostbynisaddr(const char *addr, int len, int af)
+{
+ return _gethostbynis(inet_ntoa(*(struct in_addr *)addr),"hosts.byaddr", af);
+}
diff --git a/StdLib/BsdSocketLib/gethostnamadr.c b/StdLib/BsdSocketLib/gethostnamadr.c new file mode 100644 index 0000000000..74a9ea1def --- /dev/null +++ b/StdLib/BsdSocketLib/gethostnamadr.c @@ -0,0 +1,225 @@ +/*-
+ * Copyright (c) 1994, Garrett Wollman
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)$Id: gethostnamadr.c,v 1.1.1.1 2003/11/19 01:51:27 kyu3 Exp $";
+static char rcsid[] = "$Id: gethostnamadr.c,v 1.1.1.1 2003/11/19 01:51:27 kyu3 Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <paths.h>
+#include <string.h>
+#include <arpa/nameser.h> /* XXX hack for _res */
+#include <resolv.h> /* XXX hack for _res */
+
+#include "Socklib_internals.h"
+
+
+enum service_type {
+ SERVICE_NONE = 0,
+ SERVICE_BIND,
+ SERVICE_HOSTS,
+ SERVICE_NIS };
+#define SERVICE_MAX SERVICE_NIS
+
+static struct {
+ const char *name;
+ enum service_type type;
+} service_names[] = {
+ { "hosts", SERVICE_HOSTS },
+ { _PATH_HOSTS, SERVICE_HOSTS },
+ { "hosttable", SERVICE_HOSTS },
+ { "htable", SERVICE_HOSTS },
+ { "bind", SERVICE_BIND },
+ { "dns", SERVICE_BIND },
+ { "domain", SERVICE_BIND },
+ { "yp", SERVICE_NIS },
+ { "yellowpages", SERVICE_NIS },
+ { "nis", SERVICE_NIS },
+ { 0, SERVICE_NONE }
+};
+
+static enum service_type service_order[SERVICE_MAX + 1];
+static int service_done = 0;
+
+static enum service_type
+get_service_name(const char *name) {
+ int i;
+ for(i = 0; service_names[i].type != SERVICE_NONE; i++) {
+ if(!strcasecmp(name, service_names[i].name)) {
+ return service_names[i].type;
+ }
+ }
+ return SERVICE_NONE;
+}
+
+static void
+init_services()
+{
+ char *cp, *p, buf[BUFSIZ];
+ register int cc = 0;
+ FILE *fd;
+
+ if ((fd = (FILE *)fopen(_PATH_HOSTCONF, "r")) == NULL) {
+ /* make some assumptions */
+ service_order[0] = SERVICE_HOSTS;
+ service_order[1] = SERVICE_BIND;
+ service_order[2] = SERVICE_NONE;
+ } else {
+ while (fgets(buf, BUFSIZ, fd) != NULL && cc < SERVICE_MAX) {
+ if(buf[0] == '#')
+ continue;
+
+ p = buf;
+ while ((cp = strsep(&p, "\n \t,:;")) != NULL && *cp == '\0')
+ ;
+ if (cp == NULL)
+ continue;
+ do {
+ if (isalpha(cp[0])) {
+ service_order[cc] = get_service_name(cp);
+ if(service_order[cc] != SERVICE_NONE)
+ cc++;
+ }
+ while ((cp = strsep(&p, "\n \t,:;")) != NULL && *cp == '\0')
+ ;
+ } while(cp != NULL && cc < SERVICE_MAX);
+ }
+ service_order[cc] = SERVICE_NONE;
+ fclose(fd);
+ }
+ service_done = 1;
+}
+
+struct hostent *
+gethostbyname(const char *name)
+{
+ struct hostent *hp;
+
+ if (_res.options & RES_USE_INET6) { /* XXX */
+ hp = gethostbyname2(name, AF_INET6); /* XXX */
+ if (hp) /* XXX */
+ return (hp); /* XXX */
+ } /* XXX */
+ return (gethostbyname2(name, AF_INET));
+}
+
+struct hostent *
+gethostbyname2(const char *name, int type)
+{
+ struct hostent *hp = 0;
+ int nserv = 0;
+
+ if (!service_done)
+ init_services();
+
+ while (!hp) {
+ switch (service_order[nserv]) {
+ case SERVICE_NONE:
+ return NULL;
+ case SERVICE_HOSTS:
+ hp = _gethostbyhtname(name, type);
+ break;
+ case SERVICE_BIND:
+ hp = _gethostbydnsname(name, type);
+ break;
+ case SERVICE_NIS:
+ hp = _gethostbynisname(name, type);
+ break;
+ }
+ nserv++;
+ }
+ return hp;
+}
+
+struct hostent *
+gethostbyaddr(const char *addr, socklen_t len, int type)
+{
+ struct hostent *hp = 0;
+ int nserv = 0;
+
+ if (!service_done)
+ init_services();
+
+ while (!hp) {
+ switch (service_order[nserv]) {
+ case SERVICE_NONE:
+ return 0;
+ case SERVICE_HOSTS:
+ hp = _gethostbyhtaddr(addr, len, type);
+ break;
+ case SERVICE_BIND:
+ hp = _gethostbydnsaddr(addr, len, type);
+ break;
+ case SERVICE_NIS:
+ hp = _gethostbynisaddr(addr, len, type);
+ break;
+ }
+ nserv++;
+ }
+ return hp;
+}
+
+#ifdef _THREAD_SAFE
+struct hostent_data;
+
+/*
+ * Temporary function (not thread safe)
+ */
+int gethostbyaddr_r(const char *addr, int len, int type,
+ struct hostent *result, struct hostent_data *buffer)
+{
+ struct hostent *hp;
+ int ret;
+ if ((hp = gethostbyaddr(addr, len, type)) == NULL) {
+ ret = -1;
+ } else {
+ memcpy(result, hp, sizeof(struct hostent));
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
+
+void
+sethostent(int stayopen)
+{
+ _sethosthtent(stayopen);
+ _sethostdnsent(stayopen);
+}
+
+void
+endhostent()
+{
+ _endhosthtent();
+ _endhostdnsent();
+}
diff --git a/StdLib/BsdSocketLib/gethostname.c b/StdLib/BsdSocketLib/gethostname.c new file mode 100644 index 0000000000..1b0742ad7f --- /dev/null +++ b/StdLib/BsdSocketLib/gethostname.c @@ -0,0 +1,92 @@ +/*
+ * Copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software must
+ * display the following acknowledgement:
+ *
+ * This product includes software developed by Intel Corporation and its
+ * contributors.
+ *
+ * 4. Neither the name of Intel Corporation or its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/*++
+
+Module Name:
+
+ gethostname.c
+
+Abstract:
+
+ Map FreeBSD gethostname call to EFI Interface
+
+
+Revision History
+
+--*/
+
+int
+gethostname(
+ char *name,
+ size_t namelen
+ )
+/*++
+
+Routine Description:
+
+ Get the hostname for this system.
+
+Arguments:
+
+ name - Pointer to storage for hostname.
+ namelen - Length of name
+
+Returns:
+
+ 0 on success, -1 if not set
+
+--*/
+{
+ char *pHost;
+
+ pHost = getenv ("HOSTNAME");
+
+ if ( pHost == NULL ) {
+ *name = 0;
+ } else {
+ strncpy (name, pHost, namelen);
+ name[namelen-1] = 0;
+ }
+
+ return (0);
+}
diff --git a/StdLib/BsdSocketLib/getnetbydns.c b/StdLib/BsdSocketLib/getnetbydns.c new file mode 100644 index 0000000000..b0fdef5d03 --- /dev/null +++ b/StdLib/BsdSocketLib/getnetbydns.c @@ -0,0 +1,318 @@ +/*-
+ * Copyright (c) 1985, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by the University of
+ * California, Berkeley, Intel Corporation, and its contributors.
+ *
+ * 4. Neither the name of University, Intel Corporation, or their respective
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS,
+ * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+/* Portions Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
+ * Dep. Matematica Universidade de Coimbra, Portugal, Europe
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$Id: getnetbydns.c,v 1.1.1.1 2003/11/19 01:51:27 kyu3 Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <stdio.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef _ORG_FREEBSD_
+#include <syslog.h>
+#endif
+
+#include "res_config.h"
+#include "Socklib_internals.h"
+
+extern int h_errno;
+
+#define BYADDR 0
+#define BYNAME 1
+#define MAXALIASES 35
+
+#if PACKETSZ > 1024
+#define MAXPACKET PACKETSZ
+#else
+#define MAXPACKET 1024
+#endif
+
+typedef union {
+ HEADER hdr;
+ u_char buf[MAXPACKET];
+} querybuf;
+
+typedef union {
+ long al;
+ char ac;
+} align;
+
+static struct netent *
+getnetanswer(querybuf *answer, int anslen, int net_i)
+{
+
+ register HEADER *hp;
+ register u_char *cp;
+ register int n;
+ u_char *eom;
+ int type, class, buflen, ancount, qdcount, haveanswer, i, nchar;
+ char aux1[MAXHOSTNAMELEN], aux2[MAXHOSTNAMELEN], ans[MAXHOSTNAMELEN];
+ char *in, *st, *pauxt, *bp, **ap;
+ char *paux1 = &aux1[0], *paux2 = &aux2[0], flag = 0;
+static struct netent net_entry;
+static char *net_aliases[MAXALIASES], netbuf[PACKETSZ];
+
+ /*
+ * find first satisfactory answer
+ *
+ * answer --> +------------+ ( MESSAGE )
+ * | Header |
+ * +------------+
+ * | Question | the question for the name server
+ * +------------+
+ * | Answer | RRs answering the question
+ * +------------+
+ * | Authority | RRs pointing toward an authority
+ * | Additional | RRs holding additional information
+ * +------------+
+ */
+ eom = answer->buf + anslen;
+ hp = &answer->hdr;
+ ancount = ntohs(hp->ancount); /* #/records in the answer section */
+ qdcount = ntohs(hp->qdcount); /* #/entries in the question section */
+ bp = netbuf;
+ buflen = sizeof(netbuf);
+ cp = answer->buf + HFIXEDSZ;
+ if (!qdcount) {
+ if (hp->aa)
+ h_errno = HOST_NOT_FOUND;
+ else
+ h_errno = TRY_AGAIN;
+ return (NULL);
+ }
+ while (qdcount-- > 0)
+ cp += __dn_skipname(cp, eom) + QFIXEDSZ;
+ ap = net_aliases;
+ *ap = NULL;
+ net_entry.n_aliases = net_aliases;
+ haveanswer = 0;
+ while (--ancount >= 0 && cp < eom) {
+ n = dn_expand(answer->buf, eom, cp, bp, buflen);
+ if ((n < 0) || !res_dnok(bp))
+ break;
+ cp += n;
+ ans[0] = '\0';
+ (void)strncpy(&ans[0], bp, sizeof(ans) - 1);
+ ans[sizeof(ans) - 1] = '\0';
+ GETSHORT(type, cp);
+ GETSHORT(class, cp);
+ cp += INT32SZ; /* TTL */
+ GETSHORT(n, cp);
+ if (class == C_IN && type == T_PTR) {
+ n = dn_expand(answer->buf, eom, cp, bp, buflen);
+ if ((n < 0) || !res_hnok(bp)) {
+ cp += n;
+ return (NULL);
+ }
+ cp += n;
+ *ap++ = bp;
+ bp += strlen(bp) + 1;
+ net_entry.n_addrtype =
+ (class == C_IN) ? AF_INET : AF_UNSPEC;
+ haveanswer++;
+ }
+ }
+ if (haveanswer) {
+ *ap = NULL;
+ switch (net_i) {
+ case BYADDR:
+ net_entry.n_name = *net_entry.n_aliases;
+ net_entry.n_net = 0L;
+ break;
+ case BYNAME:
+ in = *net_entry.n_aliases;
+ net_entry.n_name = &ans[0];
+ aux2[0] = '\0';
+ for (i = 0; i < 4; i++) {
+ for (st = in, nchar = 0;
+ *st != '.';
+ st++, nchar++)
+ ;
+ if (nchar != 1 || *in != '0' || flag) {
+ flag = 1;
+ (void)strncpy(paux1,
+ (i==0) ? in : in-1,
+ (i==0) ?nchar : nchar+1);
+ paux1[(i==0) ? nchar : nchar+1] = '\0';
+ pauxt = paux2;
+ paux2 = strcat(paux1, paux2);
+ paux1 = pauxt;
+ }
+ in = ++st;
+ }
+ net_entry.n_net = inet_network(paux2);
+ break;
+ }
+ net_entry.n_aliases++;
+ return (&net_entry);
+ }
+ h_errno = TRY_AGAIN;
+ return (NULL);
+}
+
+struct netent *
+_getnetbydnsaddr(register unsigned long net, register int net_type)
+{
+ unsigned int netbr[4];
+ int nn, anslen;
+ querybuf buf;
+ char qbuf[MAXDNAME];
+ unsigned long net2;
+ struct netent *net_entry;
+
+ if (net_type != AF_INET)
+ return (NULL);
+
+ for (nn = 4, net2 = net; net2; net2 >>= 8)
+ netbr[--nn] = net2 & 0xff;
+ switch (nn) {
+ case 3: /* Class A */
+ sprintf(qbuf, "0.0.0.%u.in-addr.arpa", netbr[3]);
+ break;
+ case 2: /* Class B */
+ sprintf(qbuf, "0.0.%u.%u.in-addr.arpa", netbr[3], netbr[2]);
+ break;
+ case 1: /* Class C */
+ sprintf(qbuf, "0.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2],
+ netbr[1]);
+ break;
+ case 0: /* Class D - E */
+ sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2],
+ netbr[1], netbr[0]);
+ break;
+ }
+ anslen = res_query(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf));
+ if (anslen < 0) {
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf("res_query failed\n");
+#endif
+ return (NULL);
+ }
+ net_entry = getnetanswer(&buf, anslen, BYADDR);
+ if (net_entry) {
+ unsigned u_net = net; /* maybe net should be unsigned ? */
+
+ /* Strip trailing zeros */
+ while ((u_net & 0xff) == 0 && u_net != 0)
+ u_net >>= 8;
+ net_entry->n_net = u_net;
+ return (net_entry);
+ }
+ return (NULL);
+}
+
+struct netent *
+_getnetbydnsname(register const char *net)
+{
+ int anslen;
+ querybuf buf;
+ char qbuf[MAXDNAME];
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+ strncpy(qbuf, net, sizeof(qbuf) - 1);
+ qbuf[sizeof(qbuf) - 1] = '\0';
+ anslen = res_search(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf));
+ if (anslen < 0) {
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf("res_query failed\n");
+#endif
+ return (NULL);
+ }
+ return getnetanswer(&buf, anslen, BYNAME);
+}
+
+void
+_setnetdnsent(int stayopen)
+{
+ if (stayopen)
+ _res.options |= RES_STAYOPEN | RES_USEVC;
+}
+
+void
+_endnetdnsent()
+{
+ _res.options &= ~(RES_STAYOPEN | RES_USEVC);
+ res_close();
+}
diff --git a/StdLib/BsdSocketLib/getnetbyht.c b/StdLib/BsdSocketLib/getnetbyht.c new file mode 100644 index 0000000000..08b80423b8 --- /dev/null +++ b/StdLib/BsdSocketLib/getnetbyht.c @@ -0,0 +1,169 @@ +/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* Portions Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
+ * Dep. Matematica Universidade de Coimbra, Portugal, Europe
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * from getnetent.c 1.1 (Coimbra) 93/06/02
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getnetent.c 8.1 (Berkeley) 6/4/93";
+static char orig_rcsid[] = "From: Id: getnetent.c,v 8.4 1997/06/01 20:34:37 vixie Exp";
+static chat rcsid[] = "$Id: getnetbyht.c,v 1.1.1.1 2003/11/19 01:51:27 kyu3 Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+
+#define MAXALIASES 35
+
+static FILE *netf;
+static char line[BUFSIZ+1];
+static struct netent net;
+static char *net_aliases[MAXALIASES];
+static int _net_stayopen;
+
+void
+_setnethtent(int f)
+{
+
+ if (netf == NULL)
+ netf = fopen(_PATH_NETWORKS, "r" );
+ else
+ rewind(netf);
+ _net_stayopen |= f;
+}
+
+void
+_endnethtent()
+{
+
+ if (netf) {
+ fclose(netf);
+ netf = NULL;
+ }
+ _net_stayopen = 0;
+}
+
+struct netent *
+getnetent()
+{
+ char *p;
+ register char *cp, **q;
+
+ if (netf == NULL && (netf = fopen(_PATH_NETWORKS, "r" )) == NULL)
+ return (NULL);
+again:
+ p = fgets(line, sizeof line, netf);
+ if (p == NULL)
+ return (NULL);
+ if (*p == '#')
+ goto again;
+ cp = strpbrk(p, "#\n");
+ if (cp == NULL)
+ goto again;
+ *cp = '\0';
+ net.n_name = p;
+ cp = strpbrk(p, " \t");
+ if (cp == NULL)
+ goto again;
+ *cp++ = '\0';
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ p = strpbrk(cp, " \t");
+ if (p != NULL)
+ *p++ = '\0';
+ net.n_net = inet_network(cp);
+ net.n_addrtype = AF_INET;
+ q = net.n_aliases = net_aliases;
+ if (p != NULL)
+ cp = p;
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &net_aliases[MAXALIASES - 1])
+ *q++ = cp;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+ *q = NULL;
+ return (&net);
+}
+
+struct netent *
+_getnetbyhtname(register const char *name)
+{
+ register struct netent *p;
+ register char **cp;
+
+ setnetent(_net_stayopen);
+ while ( NULL != (p = getnetent()) ) {
+ if (strcasecmp(p->n_name, name) == 0)
+ break;
+ for (cp = p->n_aliases; *cp != 0; cp++)
+ if (strcasecmp(*cp, name) == 0)
+ goto found;
+ }
+found:
+ if (!_net_stayopen)
+ endnetent();
+ return (p);
+}
+
+struct netent *
+_getnetbyhtaddr(register unsigned long net, register int type)
+{
+ register struct netent *p;
+
+ setnetent(_net_stayopen);
+ while ( NULL != (p = getnetent()) )
+ if (p->n_addrtype == type && p->n_net == net)
+ break;
+ if (!_net_stayopen)
+ endnetent();
+ return (p);
+}
diff --git a/StdLib/BsdSocketLib/getnetbynis.c b/StdLib/BsdSocketLib/getnetbynis.c new file mode 100644 index 0000000000..f81ca03c76 --- /dev/null +++ b/StdLib/BsdSocketLib/getnetbynis.c @@ -0,0 +1,171 @@ +/*-
+ * Copyright (c) 1994, Garrett Wollman
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)$Id: getnetbynis.c,v 1.1.1.1 2003/11/19 01:51:28 kyu3 Exp $";
+static char rcsid[] = "$Id: getnetbynis.c,v 1.1.1.1 2003/11/19 01:51:28 kyu3 Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <arpa/nameser.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+
+#define MAXALIASES 35
+#define MAXADDRS 35
+
+#ifdef YP
+static char *host_aliases[MAXALIASES];
+#endif /* YP */
+
+static struct netent *
+_getnetbynis(const char *name, char *map, int af)
+{
+#ifdef YP
+ register char *cp, **q;
+ static char *result;
+ int resultlen;
+ static struct netent h;
+ static char *domain = (char *)NULL;
+ static char ypbuf[YPMAXRECORD + 2];
+
+ switch(af) {
+ case AF_INET:
+ break;
+ default:
+ case AF_INET6:
+ errno = EAFNOSUPPORT;
+ return NULL;
+ }
+
+ if (domain == (char *)NULL)
+ if (yp_get_default_domain (&domain))
+ return (NULL);
+
+ if (yp_match(domain, map, name, strlen(name), &result, &resultlen))
+ return (NULL);
+
+ bcopy((char *)result, (char *)&ypbuf, resultlen);
+ ypbuf[resultlen] = '\0';
+ free(result);
+ result = (char *)&ypbuf;
+
+ if ((cp = index(result, '\n')))
+ *cp = '\0';
+
+ cp = strpbrk(result, " \t");
+ *cp++ = '\0';
+ h.n_name = result;
+
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+
+ h.n_net = inet_network(cp);
+ h.n_addrtype = AF_INET;
+
+ q = h.n_aliases = host_aliases;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &host_aliases[MAXALIASES - 1])
+ *q++ = cp;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+ *q = NULL;
+ return (&h);
+#else
+ return (NULL);
+#endif
+}
+
+struct netent *
+_getnetbynisname(const char *name)
+{
+ return _getnetbynis(name, "networks.byname", AF_INET);
+}
+
+struct netent *
+_getnetbynisaddr(unsigned long addr, int af)
+{
+ char *str, *cp;
+ unsigned long net2;
+ int nn;
+ unsigned int netbr[4];
+ char buf[MAXDNAME];
+
+ if (af != AF_INET) {
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+
+ for (nn = 4, net2 = addr; net2; net2 >>= 8) {
+ netbr[--nn] = net2 & 0xff;
+ }
+
+ switch (nn) {
+ case 3: /* Class A */
+ sprintf(buf, "%u", netbr[3]);
+ break;
+ case 2: /* Class B */
+ sprintf(buf, "%u.%u", netbr[2], netbr[3]);
+ break;
+ case 1: /* Class C */
+ sprintf(buf, "%u.%u.%u", netbr[1], netbr[2], netbr[3]);
+ break;
+ case 0: /* Class D - E */
+ sprintf(buf, "%u.%u.%u.%u", netbr[0], netbr[1],
+ netbr[2], netbr[3]);
+ break;
+ }
+
+ str = (char *)&buf;
+ cp = str + (strlen(str) - 2);
+
+ while(!strcmp(cp, ".0")) {
+ *cp = '\0';
+ cp = str + (strlen(str) - 2);
+ }
+
+ return _getnetbynis(str, "networks.byaddr", af);
+}
diff --git a/StdLib/BsdSocketLib/getnetnamadr.c b/StdLib/BsdSocketLib/getnetnamadr.c new file mode 100644 index 0000000000..b2eb73753a --- /dev/null +++ b/StdLib/BsdSocketLib/getnetnamadr.c @@ -0,0 +1,186 @@ +/*-
+ * Copyright (c) 1994, Garrett Wollman
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] = "$Id: getnetnamadr.c,v 1.1.1.1 2003/11/19 01:51:28 kyu3 Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <paths.h>
+#include <string.h>
+
+#include "Socklib_internals.h"
+
+enum service_type {
+ SERVICE_NONE = 0,
+ SERVICE_BIND,
+ SERVICE_TABLE,
+ SERVICE_NIS };
+#define SERVICE_MAX SERVICE_NIS
+
+static struct {
+ const char *name;
+ enum service_type type;
+} service_names[] = {
+ { "hosts", SERVICE_TABLE },
+ { _PATH_HOSTS, SERVICE_TABLE },
+ { "hosttable", SERVICE_TABLE },
+ { "htable", SERVICE_TABLE },
+ { "bind", SERVICE_BIND },
+ { "dns", SERVICE_BIND },
+ { "domain", SERVICE_BIND },
+ { "yp", SERVICE_NIS },
+ { "yellowpages", SERVICE_NIS },
+ { "nis", SERVICE_NIS },
+ { 0, SERVICE_NONE }
+};
+
+static enum service_type service_order[SERVICE_MAX + 1];
+static int service_done = 0;
+
+static enum service_type
+get_service_name(const char *name) {
+ int i;
+ for(i = 0; service_names[i].type != SERVICE_NONE; i++) {
+ if(!strcasecmp(name, service_names[i].name)) {
+ return service_names[i].type;
+ }
+ }
+ return SERVICE_NONE;
+}
+
+static void
+init_services()
+{
+ char *cp, *p, buf[BUFSIZ];
+ register int cc = 0;
+ FILE *fd;
+
+ if ((fd = (FILE *)fopen(_PATH_NETCONF, "r")) == NULL) {
+ /* make some assumptions */
+ service_order[0] = SERVICE_TABLE;
+ service_order[1] = SERVICE_NONE;
+ } else {
+ while (fgets(buf, BUFSIZ, fd) != NULL && cc < SERVICE_MAX) {
+ if(buf[0] == '#')
+ continue;
+
+ p = buf;
+ while ((cp = strsep(&p, "\n \t,:;")) != NULL && *cp == '\0')
+ ;
+ if (cp == NULL)
+ continue;
+ do {
+ if (isalpha(cp[0])) {
+ service_order[cc] = get_service_name(cp);
+ if(service_order[cc] != SERVICE_NONE)
+ cc++;
+ }
+ while ((cp = strsep(&p, "\n \t,:;")) != NULL && *cp == '\0')
+ ;
+ } while(cp != NULL && cc < SERVICE_MAX);
+ }
+ service_order[cc] = SERVICE_NONE;
+ fclose(fd);
+ }
+ service_done = 1;
+}
+
+struct netent *
+getnetbyname(const char *name)
+{
+ struct netent *hp = 0;
+ int nserv = 0;
+
+ if (!service_done)
+ init_services();
+
+ while (!hp) {
+ switch (service_order[nserv]) {
+ case SERVICE_NONE:
+ return NULL;
+ case SERVICE_TABLE:
+ hp = _getnetbyhtname(name);
+ break;
+ case SERVICE_BIND:
+ hp = _getnetbydnsname(name);
+ break;
+ case SERVICE_NIS:
+ hp = _getnetbynisname(name);
+ break;
+ }
+ nserv++;
+ }
+ return hp;
+}
+
+struct netent *
+getnetbyaddr(uint32_t addr, int af)
+{
+ struct netent *hp = 0;
+ int nserv = 0;
+
+ if (!service_done)
+ init_services();
+
+ while (!hp) {
+ switch (service_order[nserv]) {
+ case SERVICE_NONE:
+ return 0;
+ case SERVICE_TABLE:
+ hp = _getnetbyhtaddr(addr, af);
+ break;
+ case SERVICE_BIND:
+ hp = _getnetbydnsaddr(addr, af);
+ break;
+ case SERVICE_NIS:
+ hp = _getnetbynisaddr(addr, af);
+ break;
+ }
+ nserv++;
+ }
+ return hp;
+}
+
+void
+setnetent(int stayopen)
+{
+ _setnethtent(stayopen);
+ _setnetdnsent(stayopen);
+}
+
+void
+endnetent()
+{
+ _endnethtent();
+ _endnetdnsent();
+}
diff --git a/StdLib/BsdSocketLib/getpeername.c b/StdLib/BsdSocketLib/getpeername.c new file mode 100644 index 0000000000..850308a401 --- /dev/null +++ b/StdLib/BsdSocketLib/getpeername.c @@ -0,0 +1,73 @@ +/** @file
+ Implement the getpeername API.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <SocketInternals.h>
+
+
+/**
+ Get the remote address
+
+ The ::getpeername routine retrieves the remote system address from the socket.
+ The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html#">POSIX</a>
+ documentation is available online.
+
+ @param [in] s Socket file descriptor returned from ::socket.
+
+ @param [out] address Network address to receive the remote system address
+
+ @param [in] address_len Length of the remote network address structure
+
+ @returns ::getpeername returns zero (0) if successful or -1 when an error occurs.
+ In the case of an error, errno contains more details.
+
+ **/
+int
+getpeername (
+ int s,
+ struct sockaddr * address,
+ socklen_t * address_len
+ )
+{
+ int RetVal;
+ EFI_SOCKET_PROTOCOL * pSocketProtocol;
+ EFI_STATUS Status;
+
+ //
+ // Assume failure
+ //
+ RetVal = -1;
+
+ //
+ // Locate the context for this socket
+ //
+ pSocketProtocol = BslFdToSocketProtocol ( s, NULL, &errno );
+ if ( NULL != pSocketProtocol ) {
+ //
+ // Get the remote address
+ //
+ Status = pSocketProtocol->pfnGetPeer ( pSocketProtocol,
+ address,
+ address_len,
+ &errno );
+ if ( !EFI_ERROR ( Status )) {
+ RetVal = 0;
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ return RetVal;
+}
diff --git a/StdLib/BsdSocketLib/getproto.c b/StdLib/BsdSocketLib/getproto.c new file mode 100644 index 0000000000..9924d000bd --- /dev/null +++ b/StdLib/BsdSocketLib/getproto.c @@ -0,0 +1,54 @@ +/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getproto.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <netdb.h>
+
+extern int _proto_stayopen;
+
+struct protoent *
+getprotobynumber(register int proto)
+{
+ register struct protoent *p;
+
+ setprotoent(_proto_stayopen);
+ while ( NULL != (p = getprotoent()) )
+ if (p->p_proto == proto)
+ break;
+ if (!_proto_stayopen)
+ endprotoent();
+ return (p);
+}
diff --git a/StdLib/BsdSocketLib/getprotoent.c b/StdLib/BsdSocketLib/getprotoent.c new file mode 100644 index 0000000000..3360812c49 --- /dev/null +++ b/StdLib/BsdSocketLib/getprotoent.c @@ -0,0 +1,118 @@ +/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getprotoent.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MAXALIASES 35
+
+static FILE *protof = NULL;
+static char line[BUFSIZ+1];
+static struct protoent proto;
+static char *proto_aliases[MAXALIASES];
+int _proto_stayopen;
+
+void
+setprotoent(int f)
+{
+ if (protof == NULL)
+ protof = fopen(_PATH_PROTOCOLS, "r" );
+ else
+ rewind(protof);
+ _proto_stayopen |= f;
+}
+
+void
+endprotoent()
+{
+ if (protof) {
+ fclose(protof);
+ protof = NULL;
+ }
+ _proto_stayopen = 0;
+}
+
+struct protoent *
+getprotoent()
+{
+ char *p;
+ register char *cp, **q;
+
+ if (protof == NULL && (protof = fopen(_PATH_PROTOCOLS, "r" )) == NULL)
+ return (NULL);
+again:
+ if ((p = fgets(line, BUFSIZ, protof)) == NULL)
+ return (NULL);
+ if (*p == '#')
+ goto again;
+ cp = strpbrk(p, "#\n");
+ if (cp == NULL)
+ goto again;
+ *cp = '\0';
+ proto.p_name = p;
+ cp = strpbrk(p, " \t");
+ if (cp == NULL)
+ goto again;
+ *cp++ = '\0';
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ p = strpbrk(cp, " \t");
+ if (p != NULL)
+ *p++ = '\0';
+ proto.p_proto = atoi(cp);
+ q = proto.p_aliases = proto_aliases;
+ if (p != NULL) {
+ cp = p;
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &proto_aliases[MAXALIASES - 1])
+ *q++ = cp;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+ }
+ *q = NULL;
+ return (&proto);
+}
diff --git a/StdLib/BsdSocketLib/getprotoname.c b/StdLib/BsdSocketLib/getprotoname.c new file mode 100644 index 0000000000..71b35e61b9 --- /dev/null +++ b/StdLib/BsdSocketLib/getprotoname.c @@ -0,0 +1,61 @@ +/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getprotoname.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <netdb.h>
+#include <string.h>
+
+extern int _proto_stayopen;
+
+struct protoent *
+getprotobyname(register const char *name)
+{
+ register struct protoent *p;
+ register char **cp;
+
+ setprotoent(_proto_stayopen);
+ while ( NULL != (p = getprotoent()) ) {
+ if (strcmp(p->p_name, name) == 0)
+ break;
+ for (cp = p->p_aliases; *cp != 0; cp++)
+ if (strcmp(*cp, name) == 0)
+ goto found;
+ }
+found:
+ if (!_proto_stayopen)
+ endprotoent();
+ return (p);
+}
diff --git a/StdLib/BsdSocketLib/getservbyname.c b/StdLib/BsdSocketLib/getservbyname.c new file mode 100644 index 0000000000..f17c240b37 --- /dev/null +++ b/StdLib/BsdSocketLib/getservbyname.c @@ -0,0 +1,77 @@ +/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getservbyname.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <netdb.h>
+#include <string.h>
+
+extern int _serv_stayopen;
+
+struct servent *
+getservbyname(IN const char *name, IN const char *proto)
+{
+ register struct servent *p;
+ register char **cp;
+
+#ifdef YP
+ extern char *___getservbyname_yp;
+ extern char *___getservbyproto_yp;
+
+ ___getservbyname_yp = (char *)name;
+ ___getservbyproto_yp = (char *)proto;
+#endif
+
+ setservent(_serv_stayopen);
+ while ( NULL != (p = getservent()) ) {
+ if (strcmp(name, p->s_name) == 0)
+ goto gotname;
+ for (cp = p->s_aliases; *cp; cp++)
+ if (strcmp(name, *cp) == 0)
+ goto gotname;
+ continue;
+gotname:
+ if (proto == 0 || strcmp(p->s_proto, proto) == 0)
+ break;
+ }
+ if (!_serv_stayopen)
+ endservent();
+
+#ifdef YP
+ ___getservbyname_yp = NULL;
+ ___getservbyproto_yp = NULL;
+#endif
+
+ return (p);
+}
diff --git a/StdLib/BsdSocketLib/getservbyport.c b/StdLib/BsdSocketLib/getservbyport.c new file mode 100644 index 0000000000..d93d8135b5 --- /dev/null +++ b/StdLib/BsdSocketLib/getservbyport.c @@ -0,0 +1,72 @@ +/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getservbyport.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <netdb.h>
+#include <string.h>
+
+extern int _serv_stayopen;
+
+struct servent *
+getservbyport(int port, const char *proto)
+{
+ register struct servent *p;
+
+#ifdef YP
+ extern int ___getservbyport_yp;
+ extern char *___getservbyproto_yp;
+
+ ___getservbyport_yp = port;
+ ___getservbyproto_yp = (char *)proto;
+#endif
+
+ setservent(_serv_stayopen);
+ while ( NULL != (p = getservent()) ) {
+ if (p->s_port != port)
+ continue;
+ if (proto == 0 || strcmp(p->s_proto, proto) == 0)
+ break;
+ }
+ if (!_serv_stayopen)
+ endservent();
+
+#ifdef YP
+ ___getservbyport_yp = 0;
+ ___getservbyproto_yp = NULL;
+#endif
+
+ return (p);
+}
diff --git a/StdLib/BsdSocketLib/getservent.c b/StdLib/BsdSocketLib/getservent.c new file mode 100644 index 0000000000..572b5978fc --- /dev/null +++ b/StdLib/BsdSocketLib/getservent.c @@ -0,0 +1,277 @@ +/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getservent.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+static int serv_stepping_yp = 0;
+extern int _yp_check __P(( char ** ));
+#endif
+
+
+#define MAXALIASES 35
+
+static FILE *servf = NULL;
+static char line[BUFSIZ+1];
+static struct servent serv;
+static char *serv_aliases[MAXALIASES];
+int _serv_stayopen;
+
+#ifdef YP
+char *___getservbyname_yp = NULL;
+char *___getservbyproto_yp = NULL;
+int ___getservbyport_yp = 0;
+static char *yp_domain = NULL;
+
+static int
+_getservbyport_yp(line)
+ char *line;
+{
+ char *result;
+ int resultlen;
+ char buf[YPMAXRECORD + 2];
+ int rv;
+
+ snprintf(buf, sizeof(buf), "%d/%s", ntohs(___getservbyport_yp),
+ ___getservbyproto_yp);
+
+ ___getservbyport_yp = 0;
+ ___getservbyproto_yp = NULL;
+
+ if(!yp_domain) {
+ if(yp_get_default_domain(&yp_domain))
+ return (0);
+ }
+
+ /*
+ * We have to be a little flexible here. Ideally you're supposed
+ * to have both a services.byname and a services.byport map, but
+ * some systems have only services.byname. FreeBSD cheats a little
+ * by putting the services.byport information in the same map as
+ * services.byname so that either case will work. We allow for both
+ * possibilities here: if there is no services.byport map, we try
+ * services.byname instead.
+ */
+ if ((rv = yp_match(yp_domain, "services.byport", buf, strlen(buf),
+ &result, &resultlen))) {
+ if (rv == YPERR_MAP) {
+ if (yp_match(yp_domain, "services.byname", buf,
+ strlen(buf), &result, &resultlen))
+ return(0);
+ } else
+ return(0);
+ }
+
+ /* getservent() expects lines terminated with \n -- make it happy */
+ snprintf(line, BUFSIZ, "%.*s\n", resultlen, result);
+
+ free(result);
+ return(1);
+}
+
+static int
+_getservbyname_yp(line)
+ char *line;
+{
+ char *result;
+ int resultlen;
+ char buf[YPMAXRECORD + 2];
+
+ if(!yp_domain) {
+ if(yp_get_default_domain(&yp_domain))
+ return (0);
+ }
+
+ snprintf(buf, sizeof(buf), "%s/%s", ___getservbyname_yp,
+ ___getservbyproto_yp);
+
+ ___getservbyname_yp = 0;
+ ___getservbyproto_yp = NULL;
+
+ if (yp_match(yp_domain, "services.byname", buf, strlen(buf),
+ &result, &resultlen)) {
+ return(0);
+ }
+
+ /* getservent() expects lines terminated with \n -- make it happy */
+ snprintf(line, BUFSIZ, "%.*s\n", resultlen, result);
+
+ free(result);
+ return(1);
+}
+
+static int
+_getservent_yp(line)
+ char *line;
+{
+ static char *key = NULL;
+ static int keylen;
+ char *lastkey, *result;
+ int resultlen;
+ int rv;
+
+ if(!yp_domain) {
+ if(yp_get_default_domain(&yp_domain))
+ return (0);
+ }
+
+ if (!serv_stepping_yp) {
+ if (key)
+ free(key);
+ if ((rv = yp_first(yp_domain, "services.byname", &key, &keylen,
+ &result, &resultlen))) {
+ serv_stepping_yp = 0;
+ return(0);
+ }
+ serv_stepping_yp = 1;
+ } else {
+ lastkey = key;
+ rv = yp_next(yp_domain, "services.byname", key, keylen, &key,
+ &keylen, &result, &resultlen);
+ free(lastkey);
+ if (rv) {
+ serv_stepping_yp = 0;
+ return (0);
+ }
+ }
+
+ /* getservent() expects lines terminated with \n -- make it happy */
+ snprintf(line, BUFSIZ, "%.*s\n", resultlen, result);
+
+ free(result);
+
+ return(1);
+}
+#endif
+
+void
+setservent(int f)
+{
+ if (servf == NULL)
+ servf = fopen(_PATH_SERVICES, "r" );
+ else
+ rewind(servf);
+ _serv_stayopen |= f;
+}
+
+void
+endservent()
+{
+ if (servf) {
+ fclose(servf);
+ servf = NULL;
+ }
+ _serv_stayopen = 0;
+}
+
+struct servent *
+getservent()
+{
+ char *p;
+ register char *cp, **q;
+
+#ifdef YP
+ if (serv_stepping_yp && _getservent_yp(line)) {
+ p = (char *)&line;
+ goto unpack;
+ }
+tryagain:
+#endif
+ if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL)
+ return (NULL);
+again:
+ if ((p = fgets(line, BUFSIZ, servf)) == NULL)
+ return (NULL);
+#ifdef YP
+ if (*p == '+' && _yp_check(NULL)) {
+ if (___getservbyname_yp != NULL) {
+ if (!_getservbyname_yp(line))
+ goto tryagain;
+ }
+ else if (___getservbyport_yp != 0) {
+ if (!_getservbyport_yp(line))
+ goto tryagain;
+ }
+ else if (!_getservent_yp(line))
+ goto tryagain;
+ }
+unpack:
+#endif
+ if (*p == '#')
+ goto again;
+ cp = strpbrk(p, "#\n");
+ if (cp == NULL)
+ goto again;
+ *cp = '\0';
+ serv.s_name = p;
+ p = strpbrk(p, " \t");
+ if (p == NULL)
+ goto again;
+ *p++ = '\0';
+ while (*p == ' ' || *p == '\t')
+ p++;
+ cp = strpbrk(p, ",/");
+ if (cp == NULL)
+ goto again;
+ *cp++ = '\0';
+ serv.s_port = htons((u_short)atoi(p));
+ serv.s_proto = cp;
+ q = serv.s_aliases = serv_aliases;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &serv_aliases[MAXALIASES - 1])
+ *q++ = cp;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+ *q = NULL;
+ return (&serv);
+}
diff --git a/StdLib/BsdSocketLib/getsockname.c b/StdLib/BsdSocketLib/getsockname.c new file mode 100644 index 0000000000..0b72edcf29 --- /dev/null +++ b/StdLib/BsdSocketLib/getsockname.c @@ -0,0 +1,73 @@ +/** @file
+ Implement the getsockname API.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <SocketInternals.h>
+
+
+/**
+ Get the local socket address.
+
+ The ::getsockname routine retrieves the local system address from the socket.
+ The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html#">POSIX</a>
+ documentation is available online.
+
+ @param [in] s Socket file descriptor returned from ::socket.
+
+ @param [out] address Network address to receive the local system address
+
+ @param [in] address_len Length of the local network address structure
+
+ @returns ::getsockname returns zero (0) if successful or -1 when an error occurs.
+ In the case of an error, errno contains more details.
+
+ **/
+int
+getsockname (
+ int s,
+ struct sockaddr * address,
+ socklen_t * address_len
+ )
+{
+ int RetVal;
+ EFI_SOCKET_PROTOCOL * pSocketProtocol;
+ EFI_STATUS Status;
+
+ //
+ // Assume failure
+ //
+ RetVal = -1;
+
+ //
+ // Locate the context for this socket
+ //
+ pSocketProtocol = BslFdToSocketProtocol ( s, NULL, &errno );
+ if ( NULL != pSocketProtocol ) {
+ //
+ // Get the local socket address
+ //
+ Status = pSocketProtocol->pfnGetLocal ( pSocketProtocol,
+ address,
+ address_len,
+ &errno );
+ if ( !EFI_ERROR ( Status )) {
+ RetVal = 0;
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ return RetVal;
+}
diff --git a/StdLib/BsdSocketLib/getsockopt.c b/StdLib/BsdSocketLib/getsockopt.c new file mode 100644 index 0000000000..eac10544de --- /dev/null +++ b/StdLib/BsdSocketLib/getsockopt.c @@ -0,0 +1,66 @@ +/** @file
+ Implement the getsockopt API.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <SocketInternals.h>
+
+
+/**
+ Get the socket options
+
+ @param [in] s Socket file descriptor returned from ::socket.
+ @param [in] level Option protocol level
+ @param [in] option_name Name of the option
+ @param [out] option_value Buffer to receive the option value
+ @param [in,out] option_len Length of the buffer in bytes,
+ upon return length of the option value in bytes
+
+ @retval Zero (0) upon success
+ @retval Minus one (-1) upon failure, errno set with additional error information
+
+**/
+int
+getsockopt (
+ IN int s,
+ IN int level,
+ IN int option_name,
+ OUT void * __restrict option_value,
+ IN OUT socklen_t * __restrict option_len
+ )
+{
+ int OptionStatus;
+ EFI_SOCKET_PROTOCOL * pSocketProtocol;
+ EFI_STATUS Status;
+
+ //
+ // Locate the context for this socket
+ //
+ pSocketProtocol = BslFdToSocketProtocol ( s, NULL, &errno );
+ if ( NULL != pSocketProtocol ) {
+ //
+ // Get the socket option
+ //
+ Status = pSocketProtocol->pfnOptionGet ( pSocketProtocol,
+ level,
+ option_name,
+ option_value,
+ option_len,
+ &errno );
+ }
+
+ //
+ // Return the operation stauts
+ //
+ OptionStatus = ( 0 == errno ) ? 0 : -1;
+ return OptionStatus;
+}
diff --git a/StdLib/BsdSocketLib/herror.c b/StdLib/BsdSocketLib/herror.c new file mode 100644 index 0000000000..e1c9b41f87 --- /dev/null +++ b/StdLib/BsdSocketLib/herror.c @@ -0,0 +1,134 @@ +/*
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by the University of
+ * California, Berkeley, Intel Corporation, and its contributors.
+ *
+ * 4. Neither the name of University, Intel Corporation, or their respective
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS,
+ * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Portions Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$Id: herror.c,v 1.1.1.1 2003/11/19 01:51:28 kyu3 Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+const char *h_errlist[] = {
+ "Resolver Error 0 (no error)",
+ "Unknown host", /* 1 HOST_NOT_FOUND */
+ "Host name lookup failure", /* 2 TRY_AGAIN */
+ "Unknown server error", /* 3 NO_RECOVERY */
+ "No address associated with name", /* 4 NO_ADDRESS */
+};
+int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] };
+
+int h_errno;
+
+const char *
+hstrerror(
+ int err
+ );
+
+/*
+ * herror --
+ * print the error indicated by the h_errno value.
+ */
+void
+herror(
+ const char *s
+ )
+{
+ struct iovec iov[4];
+ register struct iovec *v = iov;
+ int i;
+
+ if (s && *s) {
+ v->iov_base = (char *)s;
+ v->iov_len = strlen(s);
+ v++;
+ v->iov_base = ": ";
+ v->iov_len = 2;
+ v++;
+ }
+ v->iov_base = (char *)hstrerror(h_errno);
+ v->iov_len = strlen(v->iov_base);
+ v++;
+ v->iov_base = "\n";
+ v->iov_len = 1;
+#ifdef _ORG_FREEBSD_
+ writev(STDERR_FILENO, iov, (v - iov) + 1);
+#else
+ for (i = 0; i < (v - iov) + 1; i++)
+ fprintf( stderr, iov[i].iov_base);
+#endif
+
+}
+
+const char *
+hstrerror(
+ int err
+ )
+{
+ if (err < 0)
+ return ("Resolver internal error");
+ else if (err < h_nerr)
+ return (h_errlist[err]);
+ return ("Unknown resolver error");
+}
diff --git a/StdLib/BsdSocketLib/inet_net_ntop.c b/StdLib/BsdSocketLib/inet_net_ntop.c new file mode 100644 index 0000000000..3925727878 --- /dev/null +++ b/StdLib/BsdSocketLib/inet_net_ntop.c @@ -0,0 +1,142 @@ +/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char orig_rcsid[] = "From Id: inet_net_ntop.c,v 8.2 1996/08/08 06:54:44 vixie Exp";
+static const char rcsid[] = "$Id: inet_net_ntop.c,v 1.1.1.1 2003/11/19 01:51:29 kyu3 Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+static char * inet_net_ntop_ipv4 (const u_char *src, int bits,
+ char *dst, size_t size);
+
+/*
+ * char *
+ * inet_net_ntop(af, src, bits, dst, size)
+ * convert network number from network to presentation format.
+ * generates CIDR style result always.
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * author:
+ * Paul Vixie (ISC), July 1996
+ */
+char *
+inet_net_ntop(
+ int af,
+ const void *src,
+ int bits,
+ char *dst,
+ size_t size
+ )
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_net_ntop_ipv4(src, bits, dst, size));
+ default:
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+}
+
+/*
+ * static char *
+ * inet_net_ntop_ipv4(src, bits, dst, size)
+ * convert IPv4 network number from network to presentation format.
+ * generates CIDR style result always.
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * network byte order assumed. this means 192.5.5.240/28 has
+ * 0x11110000 in its fourth octet.
+ * author:
+ * Paul Vixie (ISC), July 1996
+ */
+static char *
+inet_net_ntop_ipv4(
+ const u_char *src,
+ int bits,
+ char *dst,
+ size_t size
+ )
+{
+ char *odst = dst;
+ char *t;
+ u_int m;
+ int b;
+
+ if (bits < 0 || bits > 32) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ if (bits == 0) {
+ if (size < sizeof "0")
+ goto emsgsize;
+ *dst++ = '0';
+ *dst = '\0';
+ }
+
+ /* Format whole octets. */
+ for (b = bits / 8; b > 0; b--) {
+ if (size < sizeof "255.")
+ goto emsgsize;
+ t = dst;
+ dst += SPRINTF((dst, "%u", *src++));
+ if (b > 1) {
+ *dst++ = '.';
+ *dst = '\0';
+ }
+ size -= (size_t)(dst - t);
+ }
+
+ /* Format partial octet. */
+ b = bits % 8;
+ if (b > 0) {
+ if (size < sizeof ".255")
+ goto emsgsize;
+ t = dst;
+ if (dst != odst)
+ *dst++ = '.';
+ m = ((1 << b) - 1) << (8 - b);
+ dst += SPRINTF((dst, "%u", *src & m));
+ size -= (size_t)(dst - t);
+ }
+
+ /* Format CIDR /width. */
+ if (size < sizeof "/32")
+ goto emsgsize;
+ dst += SPRINTF((dst, "/%u", bits));
+ return (odst);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (NULL);
+}
diff --git a/StdLib/BsdSocketLib/inet_net_pton.c b/StdLib/BsdSocketLib/inet_net_pton.c new file mode 100644 index 0000000000..4e4424a0c0 --- /dev/null +++ b/StdLib/BsdSocketLib/inet_net_pton.c @@ -0,0 +1,252 @@ +/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by Intel Corporation and
+ * its contributors.
+ *
+ * 4. Neither the name of Intel Corporation or its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char orig_rcsid[] = "From Id: inet_net_pton.c,v 1.8 1996/11/21 10:28:12 vixie Exp $";
+static const char rcsid[] = "$Id: inet_net_pton.c,v 1.1.1.1 2003/11/19 01:51:29 kyu3 Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+static int inet_net_pton_ipv4 (const char *src, u_char *dst,
+ size_t size);
+
+/*
+ * static int
+ * inet_net_pton(af, src, dst, size)
+ * convert network number from presentation to network format.
+ * accepts hex octets, hex strings, decimal octets, and /CIDR.
+ * "size" is in bytes and describes "dst".
+ * return:
+ * number of bits, either imputed classfully or specified with /CIDR,
+ * or -1 if some failure occurred (check errno). ENOENT means it was
+ * not a valid network specification.
+ * author:
+ * Paul Vixie (ISC), June 1996
+ */
+int
+inet_net_pton(
+ int af,
+ const char *src,
+ void *dst,
+ size_t size
+ )
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_net_pton_ipv4(src, dst, size));
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+}
+
+/*
+ * static int
+ * inet_net_pton_ipv4(src, dst, size)
+ * convert IPv4 network number from presentation to network format.
+ * accepts hex octets, hex strings, decimal octets, and /CIDR.
+ * "size" is in bytes and describes "dst".
+ * return:
+ * number of bits, either imputed classfully or specified with /CIDR,
+ * or -1 if some failure occurred (check errno). ENOENT means it was
+ * not an IPv4 network specification.
+ * note:
+ * network byte order assumed. this means 192.5.5.240/28 has
+ * 0x11110000 in its fourth octet.
+ * author:
+ * Paul Vixie (ISC), June 1996
+ */
+static int
+inet_net_pton_ipv4(
+ const char *src,
+ u_char *dst,
+ size_t size
+ )
+{
+ static const char xdigits[] = "0123456789abcdef";
+ static const char digits[] = "0123456789";
+ int n;
+ int ch;
+ int tmp;
+ int dirty;
+ int bits;
+ const u_char *odst = dst;
+
+ ch = *src++;
+ if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
+ && isascii(src[1]) && isxdigit(src[1])) {
+ /* Hexadecimal: Eat nybble string. */
+ if (size <= 0)
+ goto emsgsize;
+ *dst = 0, dirty = 0;
+ src++; /* skip x or X. */
+ while ((ch = *src++) != '\0' &&
+ isascii(ch) && isxdigit(ch)) {
+ if (isupper(ch))
+ ch = tolower(ch);
+ n = (int)(strchr(xdigits, ch) - xdigits);
+ assert(n >= 0 && n <= 15);
+ *dst |= n;
+ if (!dirty++)
+ *dst <<= 4;
+ else if (size-- > 0)
+ *++dst = 0, dirty = 0;
+ else
+ goto emsgsize;
+ }
+ if (dirty)
+ size--;
+ } else if (isascii(ch) && isdigit(ch)) {
+ /* Decimal: eat dotted digit string. */
+ for (;;) {
+ tmp = 0;
+ do {
+ n = (int)(strchr(digits, ch) - digits);
+ assert(n >= 0 && n <= 9);
+ tmp *= 10;
+ tmp += n;
+ if (tmp > 255)
+ goto enoent;
+ } while ((ch = *src++) != '\0' &&
+ isascii(ch) && isdigit(ch));
+ if (size-- <= 0)
+ goto emsgsize;
+ *dst++ = (u_char) tmp;
+ if (ch == '\0' || ch == '/')
+ break;
+ if (ch != '.')
+ goto enoent;
+ ch = *src++;
+ if (!isascii(ch) || !isdigit(ch))
+ goto enoent;
+ }
+ } else
+ goto enoent;
+
+ bits = -1;
+ if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) {
+ /* CIDR width specifier. Nothing can follow it. */
+ ch = *src++; /* Skip over the /. */
+ bits = 0;
+ do {
+ n = (int)(strchr(digits, ch) - digits);
+ assert(n >= 0 && n <= 9);
+ bits *= 10;
+ bits += n;
+ } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
+ if (ch != '\0')
+ goto enoent;
+ if (bits > 32)
+ goto emsgsize;
+ }
+
+ /* Firey death and destruction unless we prefetched EOS. */
+ if (ch != '\0')
+ goto enoent;
+
+ /* If nothing was written to the destination, we found no address. */
+ if (dst == odst)
+ goto enoent;
+ /* If no CIDR spec was given, infer width from net class. */
+ if (bits == -1) {
+ if (*odst >= 240) /* Class E */
+ bits = 32;
+ else if (*odst >= 224) /* Class D */
+ bits = 4;
+ else if (*odst >= 192) /* Class C */
+ bits = 24;
+ else if (*odst >= 128) /* Class B */
+ bits = 16;
+ else /* Class A */
+ bits = 8;
+ /* If imputed mask is narrower than specified octets, widen. */
+ if (bits >= 8 && bits < ((dst - odst) * 8))
+ bits = (int)(dst - odst) * 8;
+ }
+ /* Extend network to cover the actual mask. */
+ while (bits > ((dst - odst) * 8)) {
+ if (size-- <= 0)
+ goto emsgsize;
+ *dst++ = '\0';
+ }
+ return (bits);
+
+ enoent:
+ errno = ENOENT;
+ return (-1);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+}
diff --git a/StdLib/BsdSocketLib/inet_neta.c b/StdLib/BsdSocketLib/inet_neta.c new file mode 100644 index 0000000000..b313b13505 --- /dev/null +++ b/StdLib/BsdSocketLib/inet_neta.c @@ -0,0 +1,125 @@ +/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by Intel Corporation and
+ * its contributors.
+ *
+ * 4. Neither the name of Intel Corporation or its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char orig_rcsid[] = "From Id: inet_neta.c,v 8.2 1996/08/08 06:54:44 vixie Exp";
+static const char rcsid[] = "$Id: inet_neta.c,v 1.1.1.1 2003/11/19 01:51:29 kyu3 Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+/*
+ * char *
+ * inet_neta(src, dst, size)
+ * format a u_long network number into presentation format.
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * format of ``src'' is as for inet_network().
+ * author:
+ * Paul Vixie (ISC), July 1996
+ */
+char *
+inet_neta(
+ u_long src,
+ char *dst,
+ size_t size
+ )
+{
+ char *odst = dst;
+ char *tp;
+
+ while (src & 0xffffffff) {
+ u_char b = (u_char)((src & 0xff000000) >> 24);
+
+ src <<= 8;
+ if (b) {
+ if (size < sizeof "255.")
+ goto emsgsize;
+ tp = dst;
+ dst += SPRINTF((dst, "%u", b));
+ if (src != 0L) {
+ *dst++ = '.';
+ *dst = '\0';
+ }
+ size -= (size_t)(dst - tp);
+ }
+ }
+ if (dst == odst) {
+ if (size < sizeof "0.0.0.0")
+ goto emsgsize;
+ strcpy(dst, "0.0.0.0");
+ }
+ return (odst);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (NULL);
+}
diff --git a/StdLib/BsdSocketLib/inet_pton.c b/StdLib/BsdSocketLib/inet_pton.c new file mode 100644 index 0000000000..32e1ab8690 --- /dev/null +++ b/StdLib/BsdSocketLib/inet_pton.c @@ -0,0 +1,257 @@ +/* Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by Intel Corporation and
+ * its contributors.
+ *
+ * 4. Neither the name of Intel Corporation or its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] = "$Id: inet_pton.c,v 1.1.1.1 2003/11/19 01:51:30 kyu3 Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <string.h>
+#include <errno.h>
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static int inet_pton4 (const char *src, u_char *dst);
+static int inet_pton6 (const char *src, u_char *dst);
+
+/* int
+ * inet_pton(af, src, dst)
+ * convert from presentation format (which usually means ASCII printable)
+ * to network format (which is usually some kind of binary format).
+ * return:
+ * 1 if the address was valid for the specified address family
+ * 0 if the address wasn't valid (`dst' is untouched in this case)
+ * -1 if some other error occurred (`dst' is untouched in this case, too)
+ * author:
+ * Paul Vixie, 1996.
+ */
+int
+inet_pton(
+ int af,
+ const char *src,
+ void *dst
+ )
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_pton4(src, dst));
+ case AF_INET6:
+ return (inet_pton6(src, dst));
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+ /* NOTREACHED */
+}
+
+/* int
+ * inet_pton4(src, dst)
+ * like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ * 1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ * does not touch `dst' unless it's returning 1.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton4(
+ const char *src,
+ u_char *dst
+ )
+{
+ static const char digits[] = "0123456789";
+ int saw_digit, octets, ch;
+ u_char tmp[NS_INADDRSZ], *tp;
+
+ saw_digit = 0;
+ octets = 0;
+ *(tp = tmp) = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr(digits, ch)) != NULL) {
+ u_int new = *tp * 10 + (u_int)(pch - digits);
+
+ if (new > 255)
+ return (0);
+ *tp = (u_char)new;
+ if (! saw_digit) {
+ if (++octets > 4)
+ return (0);
+ saw_digit = 1;
+ }
+ } else if (ch == '.' && saw_digit) {
+ if (octets == 4)
+ return (0);
+ *++tp = 0;
+ saw_digit = 0;
+ } else
+ return (0);
+ }
+ if (octets < 4)
+ return (0);
+
+ memcpy(dst, tmp, NS_INADDRSZ);
+ return (1);
+}
+
+/* int
+ * inet_pton6(src, dst)
+ * convert presentation level address to network order binary form.
+ * return:
+ * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ * (1) does not touch `dst' unless it's returning 1.
+ * (2) :: in a full address is silently ignored.
+ * credit:
+ * inspired by Mark Andrews.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton6(
+ const char *src,
+ u_char *dst
+ )
+{
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, saw_xdigit;
+ u_int val;
+
+ memset((tp = tmp), '\0', NS_IN6ADDRSZ);
+ endp = tp + NS_IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ if (*++src != ':')
+ return (0);
+ curtok = src;
+ saw_xdigit = 0;
+ val = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if (pch != NULL) {
+ val <<= 4;
+ val |= (pch - xdigits);
+ if (val > 0xffff)
+ return (0);
+ saw_xdigit = 1;
+ continue;
+ }
+ if (ch == ':') {
+ curtok = src;
+ if (!saw_xdigit) {
+ if (colonp)
+ return (0);
+ colonp = tp;
+ continue;
+ }
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ saw_xdigit = 0;
+ val = 0;
+ continue;
+ }
+ if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+ inet_pton4(curtok, tp) > 0) {
+ tp += NS_INADDRSZ;
+ saw_xdigit = 0;
+ break; /* '\0' was seen by inet_pton4(). */
+ }
+ return (0);
+ }
+ if (saw_xdigit) {
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ }
+ if (colonp != NULL) {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const int n = (int)(tp - colonp);
+ int i;
+
+ for (i = 1; i <= n; i++) {
+ endp[- i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+ tp = endp;
+ }
+ if (tp != endp)
+ return (0);
+ memcpy(dst, tmp, NS_IN6ADDRSZ);
+ return (1);
+}
diff --git a/StdLib/BsdSocketLib/listen.c b/StdLib/BsdSocketLib/listen.c new file mode 100644 index 0000000000..5e14876652 --- /dev/null +++ b/StdLib/BsdSocketLib/listen.c @@ -0,0 +1,65 @@ +/** @file
+ Implement the listen API.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <SocketInternals.h>
+
+
+/**
+ Establish the known port to listen for network connections.
+
+ The ::listen routine places the port into a state that enables connection
+ attempts. Connections are placed into FIFO order in a queue to be serviced
+ by the application. The application calls the ::accept routine to remove
+ the next connection from the queue and get the associated socket. The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html">POSIX</a>
+ documentation for the bind routine is available online for reference.
+
+ @param [in] s Socket file descriptor returned from ::socket.
+
+ @param [in] backlog backlog specifies the maximum FIFO depth for the connections
+ waiting for the application to call accept. Connection attempts
+ received while the queue is full are refused.
+
+ @returns The listen routine returns zero (0) if successful and -1 upon failure.
+
+ **/
+int
+listen (
+ IN int s,
+ IN int backlog
+ )
+{
+ int ListenStatus;
+ EFI_SOCKET_PROTOCOL * pSocketProtocol;
+ EFI_STATUS Status;
+
+ //
+ // Locate the context for this socket
+ //
+ pSocketProtocol = BslFdToSocketProtocol ( s, NULL, &errno );
+ if ( NULL != pSocketProtocol ) {
+ //
+ // Enable connections on the known port
+ //
+ Status = pSocketProtocol->pfnListen ( pSocketProtocol,
+ backlog,
+ &errno );
+ }
+
+ //
+ // Return the operation stauts
+ //
+ ListenStatus = ( 0 == errno ) ? 0 : -1;
+ return ListenStatus;
+}
diff --git a/StdLib/BsdSocketLib/map_v4v6.c b/StdLib/BsdSocketLib/map_v4v6.c new file mode 100644 index 0000000000..5ad73c85ce --- /dev/null +++ b/StdLib/BsdSocketLib/map_v4v6.c @@ -0,0 +1,135 @@ +/*
+ * ++Copyright++ 1985, 1988, 1993
+ * -
+ * Copyright (c) 1985, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by the University of
+ * California, Berkeley, Intel Corporation, and its contributors.
+ *
+ * 4. Neither the name of University, Intel Corporation, or their respective
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS,
+ * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$Id: map_v4v6.c,v 1.1.1.1 2003/11/19 01:51:31 kyu3 Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <ctype.h>
+#include <errno.h>
+#ifdef _ORG_FREEBSD_
+#include <syslog.h>
+#endif
+#include "Socklib_internals.h"
+
+typedef union {
+ int32_t al;
+ char ac;
+} align;
+
+void
+_map_v4v6_address(const char *src, char *dst)
+{
+ u_char *p = (u_char *)dst;
+ char tmp[INADDRSZ];
+ int i;
+
+ /* Stash a temporary copy so our caller can update in place. */
+ bcopy(src, tmp, INADDRSZ);
+ /* Mark this ipv6 addr as a mapped ipv4. */
+ for (i = 0; i < 10; i++)
+ *p++ = 0x00;
+ *p++ = 0xff;
+ *p++ = 0xff;
+ /* Retrieve the saved copy and we're done. */
+ bcopy(tmp, (void*)p, INADDRSZ);
+}
+
+void
+_map_v4v6_hostent(struct hostent *hp, char **bpp, int *lenp)
+{
+ char **ap;
+
+ if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
+ return;
+ hp->h_addrtype = AF_INET6;
+ hp->h_length = IN6ADDRSZ;
+ for (ap = hp->h_addr_list; *ap; ap++) {
+ int i = (int)(sizeof(align) - ((size_t)*bpp % sizeof(align)));
+
+ if (*lenp < (i + IN6ADDRSZ)) {
+ /* Out of memory. Truncate address list here. XXX */
+ *ap = NULL;
+ return;
+ }
+ *bpp += i;
+ *lenp -= i;
+ _map_v4v6_address(*ap, *bpp);
+ *ap = *bpp;
+ *bpp += IN6ADDRSZ;
+ *lenp -= IN6ADDRSZ;
+ }
+}
diff --git a/StdLib/BsdSocketLib/ns_addr.c b/StdLib/BsdSocketLib/ns_addr.c new file mode 100644 index 0000000000..81fd6253e7 --- /dev/null +++ b/StdLib/BsdSocketLib/ns_addr.c @@ -0,0 +1,240 @@ +/*
+ * Copyright (c) 1986, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * J.Q. Johnson.
+ *
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by the University of
+ * California, Berkeley, Intel Corporation, and its contributors.
+ *
+ * 4. Neither the name of University, Intel Corporation, or their respective
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS,
+ * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ns_addr.c 8.1 (Berkeley) 6/7/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <netns/ns.h>
+#include <stdio.h>
+#include <string.h>
+
+static struct ns_addr addr, zero_addr;
+
+static void Field(), cvtbase();
+
+struct ns_addr
+ns_addr(
+ const char *name
+ )
+{
+ char separator;
+ char *hostname, *socketname, *cp;
+ char buf[50];
+
+ (void)strncpy(buf, name, sizeof(buf) - 1);
+ buf[sizeof(buf) - 1] = '\0';
+
+ /*
+ * First, figure out what he intends as a field separtor.
+ * Despite the way this routine is written, the prefered
+ * form 2-272.AA001234H.01777, i.e. XDE standard.
+ * Great efforts are made to insure backward compatability.
+ */
+ if ((hostname = strchr(buf, '#')) != NULL)
+ separator = '#';
+ else {
+ hostname = strchr(buf, '.');
+ if ((cp = strchr(buf, ':')) &&
+ ((hostname && cp < hostname) || (hostname == 0))) {
+ hostname = cp;
+ separator = ':';
+ } else
+ separator = '.';
+ }
+ if (hostname)
+ *hostname++ = 0;
+
+ addr = zero_addr;
+ Field(buf, addr.x_net.c_net, 4);
+ if (hostname == 0)
+ return (addr); /* No separator means net only */
+
+ socketname = strchr(hostname, separator);
+ if (socketname) {
+ *socketname++ = 0;
+ Field(socketname, (u_char *)&addr.x_port, 2);
+ }
+
+ Field(hostname, addr.x_host.c_host, 6);
+
+ return (addr);
+}
+
+static void
+Field(
+ char *buf,
+ u_char *out,
+ int len
+ )
+{
+ register char *bp = buf;
+ int i, ibase, base16 = 0, base10 = 0, clen = 0;
+ int hb[6], *hp;
+ char *fmt;
+
+ /*
+ * first try 2-273#2-852-151-014#socket
+ */
+ if ((*buf != '-') &&
+ (1 < (i = sscanf(buf, "%d-%d-%d-%d-%d",
+ &hb[0], &hb[1], &hb[2], &hb[3], &hb[4])))) {
+ cvtbase(1000L, 256, hb, i, out, len);
+ return;
+ }
+ /*
+ * try form 8E1#0.0.AA.0.5E.E6#socket
+ */
+ if (1 < (i = sscanf(buf,"%x.%x.%x.%x.%x.%x",
+ &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
+ cvtbase(256L, 256, hb, i, out, len);
+ return;
+ }
+ /*
+ * try form 8E1#0:0:AA:0:5E:E6#socket
+ */
+ if (1 < (i = sscanf(buf,"%x:%x:%x:%x:%x:%x",
+ &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
+ cvtbase(256L, 256, hb, i, out, len);
+ return;
+ }
+ /*
+ * This is REALLY stretching it but there was a
+ * comma notation separting shorts -- definitely non standard
+ */
+ if (1 < (i = sscanf(buf,"%x,%x,%x",
+ &hb[0], &hb[1], &hb[2]))) {
+ hb[0] = htons(hb[0]); hb[1] = htons(hb[1]);
+ hb[2] = htons(hb[2]);
+ cvtbase(65536L, 256, hb, i, out, len);
+ return;
+ }
+
+ /* Need to decide if base 10, 16 or 8 */
+ while (*bp) switch (*bp++) {
+
+ case '0': case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '-':
+ break;
+
+ case '8': case '9':
+ base10 = 1;
+ break;
+
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ base16 = 1;
+ break;
+
+ case 'x': case 'X':
+ *--bp = '0';
+ base16 = 1;
+ break;
+
+ case 'h': case 'H':
+ base16 = 1;
+ /* fall into */
+
+ default:
+ *--bp = 0; /* Ends Loop */
+ }
+ if (base16) {
+ fmt = "%3x";
+ ibase = 4096;
+ } else if (base10 == 0 && *buf == '0') {
+ fmt = "%3o";
+ ibase = 512;
+ } else {
+ fmt = "%3d";
+ ibase = 1000;
+ }
+
+ for (bp = buf; *bp++; ) clen++;
+ if (clen == 0) clen++;
+ if (clen > 18) clen = 18;
+ i = ((clen - 1) / 3) + 1;
+ bp = clen + buf - 3;
+ hp = hb + i - 1;
+
+ while (hp > hb) {
+ (void)sscanf(bp, fmt, hp);
+ bp[0] = 0;
+ hp--;
+ bp -= 3;
+ }
+ (void)sscanf(buf, fmt, hp);
+ cvtbase((long)ibase, 256, hb, i, out, len);
+}
+
+static void
+cvtbase(
+ long oldbase,
+ int newbase,
+ int input[],
+ int inlen,
+ unsigned char result[],
+ int reslen
+ )
+{
+ int d, e;
+ long sum;
+
+ e = 1;
+ while (e > 0 && reslen > 0) {
+ d = 0; e = 0; sum = 0;
+ /* long division: input=input/newbase */
+ while (d < inlen) {
+ sum = sum*oldbase + (long) input[d];
+ e += (sum > 0);
+ input[d++] = sum / newbase;
+ sum %= newbase;
+ }
+ result[--reslen] = (u_char)sum; /* accumulate remainder */
+ }
+ for (d=0; d < reslen; d++)
+ result[d] = 0;
+}
diff --git a/StdLib/BsdSocketLib/ns_name.c b/StdLib/BsdSocketLib/ns_name.c new file mode 100644 index 0000000000..9303b3f437 --- /dev/null +++ b/StdLib/BsdSocketLib/ns_name.c @@ -0,0 +1,633 @@ +/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by Intel Corporation and
+ * its contributors.
+ *
+ * 4. Neither the name of Intel Corporation or its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: ns_name.c,v 1.1.1.1 2003/11/19 01:51:32 kyu3 Exp $";
+#endif
+
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <resolv.h>
+#include <string.h>
+
+/* Data. */
+
+static char digits[] = "0123456789";
+
+/* Forward. */
+
+static int special(int);
+static int printable(int);
+static int dn_find(const u_char *, const u_char *,
+ const u_char * const *,
+ const u_char * const *);
+
+/* Public. */
+
+/*
+ * ns_name_ntop(src, dst, dstsiz)
+ * Convert an encoded domain name to printable ascii as per RFC1035.
+ * return:
+ * Number of bytes written to buffer, or -1 (with errno set)
+ * notes:
+ * The root is returned as "."
+ * All other domains are returned in non absolute form
+ */
+int
+ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) {
+ const u_char *cp;
+ char *dn, *eom;
+ u_char c;
+ u_int n;
+
+ cp = src;
+ dn = dst;
+ eom = dst + dstsiz;
+
+ while ((n = *cp++) != 0) {
+ if ((n & NS_CMPRSFLGS) != 0) {
+ /* Some kind of compression pointer. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (dn != dst) {
+ if (dn >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '.';
+ }
+ if (dn + n >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ for ((void)NULL; n > 0; n--) {
+ c = *cp++;
+ if (special(c)) {
+ if (dn + 1 >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '\\';
+ *dn++ = (char)c;
+ } else if (!printable(c)) {
+ if (dn + 3 >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '\\';
+ *dn++ = digits[c / 100];
+ *dn++ = digits[(c % 100) / 10];
+ *dn++ = digits[c % 10];
+ } else {
+ if (dn >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = (char)c;
+ }
+ }
+ }
+ if (dn == dst) {
+ if (dn >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '.';
+ }
+ if (dn >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '\0';
+ return ((int)(dn - dst));
+}
+
+/*
+ * ns_name_pton(src, dst, dstsiz)
+ * Convert a ascii string into an encoded domain name as per RFC1035.
+ * return:
+ * -1 if it fails
+ * 1 if string was fully qualified
+ * 0 is string was not fully qualified
+ * notes:
+ * Enforces label and domain length limits.
+ */
+
+int
+ns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
+ u_char *label, *bp, *eom;
+ int c, n, escaped;
+ char *cp;
+
+ escaped = 0;
+ bp = dst;
+ eom = dst + dstsiz;
+ label = bp++;
+
+ while ((c = *src++) != 0) {
+ if (escaped) {
+ if ((cp = strchr(digits, c)) != NULL) {
+ n = (int)(cp - digits) * 100;
+ if ((c = *src++) == 0 ||
+ (cp = strchr(digits, c)) == NULL) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ n += (int)(cp - digits) * 10;
+ if ((c = *src++) == 0 ||
+ (cp = strchr(digits, c)) == NULL) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ n += (int)(cp - digits);
+ if (n > 255) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ c = n;
+ }
+ escaped = 0;
+ } else if (c == '\\') {
+ escaped = 1;
+ continue;
+ } else if (c == '.') {
+ c = ((int)(bp - label) - 1);
+ if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (label >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *label = (u_char)c;
+ /* Fully qualified ? */
+ if (*src == '\0') {
+ if (c != 0) {
+ if (bp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *bp++ = '\0';
+ }
+ if ((bp - dst) > MAXCDNAME) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ return (1);
+ }
+ if (c == 0) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ label = bp++;
+ continue;
+ }
+ if (bp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *bp++ = (u_char)c;
+ }
+ c = ((int)(bp - label) - 1);
+ if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (label >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *label = (u_char)c;
+ if (c != 0) {
+ if (bp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *bp++ = 0;
+ }
+ if ((bp - dst) > MAXCDNAME) { /* src too big */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * ns_name_unpack(msg, eom, src, dst, dstsiz)
+ * Unpack a domain name from a message, source may be compressed.
+ * return:
+ * -1 if it fails, or consumed octets if it succeeds.
+ */
+int
+ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
+ u_char *dst, size_t dstsiz)
+{
+ const u_char *srcp, *dstlim;
+ u_char *dstp;
+ int n, len, checked;
+
+ len = -1;
+ checked = 0;
+ dstp = dst;
+ srcp = src;
+ dstlim = dst + dstsiz;
+ if (srcp < msg || srcp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ /* Fetch next label in domain name. */
+ while ((n = *srcp++) != 0) {
+ /* Check for indirection. */
+ switch (n & NS_CMPRSFLGS) {
+ case 0:
+ /* Limit checks. */
+ if (dstp + n + 1 >= dstlim || srcp + n >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ checked += n + 1;
+ *dstp++ = (u_char)n;
+ memcpy(dstp, srcp, n);
+ dstp += n;
+ srcp += n;
+ break;
+
+ case NS_CMPRSFLGS:
+ if (srcp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (len < 0)
+ len = (int)(srcp - src) + 1;
+ srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
+ if (srcp < msg || srcp >= eom) { /* Out of range. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ checked += 2;
+ /*
+ * Check for loops in the compressed name;
+ * if we've looked at the whole message,
+ * there must be a loop.
+ */
+ if (checked >= eom - msg) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ break;
+
+ default:
+ errno = EMSGSIZE;
+ return (-1); /* flag error */
+ }
+ }
+ *dstp = '\0';
+ if (len < 0)
+ len = (int)(srcp - src);
+ return (len);
+}
+
+/*
+ * ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr)
+ * Pack domain name 'domain' into 'comp_dn'.
+ * return:
+ * Size of the compressed name, or -1.
+ * notes:
+ * 'dnptrs' is an array of pointers to previous compressed names.
+ * dnptrs[0] is a pointer to the beginning of the message. The array
+ * ends with NULL.
+ * 'lastdnptr' is a pointer to the end of the array pointed to
+ * by 'dnptrs'.
+ * Side effects:
+ * The list of pointers in dnptrs is updated for labels inserted into
+ * the message as we compress the name. If 'dnptr' is NULL, we don't
+ * try to compress names. If 'lastdnptr' is NULL, we don't update the
+ * list.
+ */
+int
+ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
+ const u_char **dnptrs, const u_char **lastdnptr)
+{
+ u_char *dstp;
+ const u_char **cpp, **lpp, *eob, *msg;
+ const u_char *srcp;
+ int n, l;
+
+ srcp = src;
+ dstp = dst;
+ eob = dstp + dstsiz;
+ lpp = cpp = NULL;
+ if (dnptrs != NULL) {
+ if ((msg = *dnptrs++) != NULL) {
+ for (cpp = dnptrs; *cpp != NULL; cpp++)
+ (void)NULL;
+ lpp = cpp; /* end of list to search */
+ }
+ } else
+ msg = NULL;
+
+ /* make sure the domain we are about to add is legal */
+ l = 0;
+ do {
+ n = *srcp;
+ if ((n & NS_CMPRSFLGS) != 0) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ l += n + 1;
+ if (l > MAXCDNAME) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ srcp += n + 1;
+ } while (n != 0);
+
+ srcp = src;
+ do {
+ /* Look to see if we can use pointers. */
+ n = *srcp;
+ if (n != 0 && msg != NULL) {
+ l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
+ (const u_char * const *)lpp);
+ if (l >= 0) {
+ if (dstp + 1 >= eob) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dstp++ = (u_char)((l >> 8) | NS_CMPRSFLGS );
+ *dstp++ = (u_char)( l % 256 );
+ return ((int)(dstp - dst));
+ }
+ /* Not found, save it. */
+ if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
+ (dstp - msg) < 0x4000) {
+ *cpp++ = dstp;
+ *cpp = NULL;
+ }
+ }
+ /* copy label to buffer */
+ if (n & NS_CMPRSFLGS) { /* Should not happen. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (dstp + 1 + n >= eob) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ memcpy(dstp, srcp, n + 1);
+ srcp += n + 1;
+ dstp += n + 1;
+ } while (n != 0);
+
+ if (dstp > eob) {
+ if (msg != NULL)
+ *lpp = NULL;
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ return ((int)(dstp - dst));
+}
+
+/*
+ * ns_name_uncompress(msg, eom, src, dst, dstsiz)
+ * Expand compressed domain name to presentation format.
+ * return:
+ * Number of bytes read out of `src', or -1 (with errno set).
+ * note:
+ * Root domain returns as "." not "".
+ */
+int
+ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
+ char *dst, size_t dstsiz)
+{
+ u_char tmp[NS_MAXCDNAME];
+ int n;
+
+ if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
+ return (-1);
+ if (ns_name_ntop(tmp, dst, dstsiz) == -1)
+ return (-1);
+ return (n);
+}
+
+/*
+ * ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr)
+ * Compress a domain name into wire format, using compression pointers.
+ * return:
+ * Number of bytes consumed in `dst' or -1 (with errno set).
+ * notes:
+ * 'dnptrs' is an array of pointers to previous compressed names.
+ * dnptrs[0] is a pointer to the beginning of the message.
+ * The list ends with NULL. 'lastdnptr' is a pointer to the end of the
+ * array pointed to by 'dnptrs'. Side effect is to update the list of
+ * pointers for labels inserted into the message as we compress the name.
+ * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
+ * is NULL, we don't update the list.
+ */
+int
+ns_name_compress(const char *src, u_char *dst, size_t dstsiz,
+ const u_char **dnptrs, const u_char **lastdnptr)
+{
+ u_char tmp[NS_MAXCDNAME];
+
+ if (ns_name_pton(src, tmp, sizeof tmp) == -1)
+ return (-1);
+ return (ns_name_pack(tmp, dst, (int)dstsiz, dnptrs, lastdnptr));
+}
+
+/*
+ * ns_name_skip(ptrptr, eom)
+ * Advance *ptrptr to skip over the compressed name it points at.
+ * return:
+ * 0 on success, -1 (with errno set) on failure.
+ */
+int
+ns_name_skip(const u_char **ptrptr, const u_char *eom) {
+ const u_char *cp;
+ u_int n;
+
+ cp = *ptrptr;
+ while (cp < eom && (n = *cp++) != 0) {
+ /* Check for indirection. */
+ switch (n & NS_CMPRSFLGS) {
+ case 0: /* normal case, n == len */
+ cp += n;
+ continue;
+ case NS_CMPRSFLGS: /* indirection */
+ cp++;
+ break;
+ default: /* illegal type */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ break;
+ }
+ if (cp > eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *ptrptr = cp;
+ return (0);
+}
+
+/* Private. */
+
+/*
+ * special(ch)
+ * Thinking in noninternationalized USASCII (per the DNS spec),
+ * is this characted special ("in need of quoting") ?
+ * return:
+ * boolean.
+ */
+static int
+special(int ch) {
+ switch (ch) {
+ case 0x22: /* '"' */
+ case 0x2E: /* '.' */
+ case 0x3B: /* ';' */
+ case 0x5C: /* '\\' */
+ /* Special modifiers in zone files. */
+ case 0x40: /* '@' */
+ case 0x24: /* '$' */
+ return (1);
+ default:
+ return (0);
+ }
+}
+
+/*
+ * printable(ch)
+ * Thinking in noninternationalized USASCII (per the DNS spec),
+ * is this character visible and not a space when printed ?
+ * return:
+ * boolean.
+ */
+static int
+printable(int ch) {
+ return (ch > 0x20 && ch < 0x7f);
+}
+
+/*
+ * Thinking in noninternationalized USASCII (per the DNS spec),
+ * convert this character to lower case if it's upper case.
+ */
+static int
+mklower(int ch) {
+ if (ch >= 0x41 && ch <= 0x5A)
+ return (ch + 0x20);
+ return (ch);
+}
+
+/*
+ * dn_find(domain, msg, dnptrs, lastdnptr)
+ * Search for the counted-label name in an array of compressed names.
+ * return:
+ * offset from msg if found, or -1.
+ * notes:
+ * dnptrs is the pointer to the first name on the list,
+ * not the pointer to the start of the message.
+ */
+static int
+dn_find(const u_char *domain, const u_char *msg,
+ const u_char * const *dnptrs,
+ const u_char * const *lastdnptr)
+{
+ const u_char *dn, *cp, *sp;
+ const u_char * const *cpp;
+ u_int n;
+
+ for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
+ dn = domain;
+ sp = cp = *cpp;
+ while ((n = *cp++) != 0) {
+ /*
+ * check for indirection
+ */
+ switch (n & NS_CMPRSFLGS) {
+ case 0: /* normal case, n == len */
+ if (n != *dn++)
+ goto next;
+ for ((void)NULL; n > 0; n--)
+ if (mklower(*dn++) != mklower(*cp++))
+ goto next;
+ /* Is next root for both ? */
+ if (*dn == '\0' && *cp == '\0')
+ return ((int)(sp - msg));
+ if (*dn)
+ continue;
+ goto next;
+
+ case NS_CMPRSFLGS: /* indirection */
+ cp = msg + (((n & 0x3f) << 8) | *cp);
+ break;
+
+ default: /* illegal type */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ }
+ next: ;
+ }
+ errno = ENOENT;
+ return (-1);
+}
diff --git a/StdLib/BsdSocketLib/ns_netint.c b/StdLib/BsdSocketLib/ns_netint.c new file mode 100644 index 0000000000..6a3b290ead --- /dev/null +++ b/StdLib/BsdSocketLib/ns_netint.c @@ -0,0 +1,54 @@ +/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: ns_netint.c,v 1.1.1.1 2003/11/19 01:51:33 kyu3 Exp $";
+#endif
+
+/* Import. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+uint16_t
+ns_get16(const u_char *src) {
+ uint16_t dst;
+
+ NS_GET16(dst, src);
+ return (dst);
+}
+
+uint32_t
+ns_get32(const u_char *src) {
+ uint32_t dst;
+
+ NS_GET32(dst, src);
+ return (dst);
+}
+
+void
+ns_put16(uint16_t src, u_char *dst) {
+ NS_PUT16(src, dst);
+}
+
+void
+ns_put32(uint32_t src, u_char *dst) {
+ NS_PUT32(src, dst);
+}
diff --git a/StdLib/BsdSocketLib/ns_ntoa.c b/StdLib/BsdSocketLib/ns_ntoa.c new file mode 100644 index 0000000000..1162b4d69a --- /dev/null +++ b/StdLib/BsdSocketLib/ns_ntoa.c @@ -0,0 +1,103 @@ +/*
+ * Copyright (c) 1986, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ns_ntoa.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <netns/ns.h>
+#include <stdio.h>
+
+static char *spectHex();
+
+char *
+ns_ntoa(
+ struct ns_addr addr
+ )
+{
+ static char obuf[40];
+ union { union ns_net net_e; u_long long_e; } net;
+ u_short port = htons(addr.x_port);
+ register char *cp;
+ char *cp2;
+ register u_char *up = addr.x_host.c_host;
+ u_char *uplim = up + 6;
+
+ net.net_e = addr.x_net;
+ sprintf(obuf, "%lx", (u_long)ntohl(net.long_e));
+ cp = spectHex(obuf);
+ cp2 = cp + 1;
+ while (*up==0 && up < uplim) up++;
+ if (up == uplim) {
+ if (port) {
+ sprintf(cp, ".0");
+ cp += 2;
+ }
+ } else {
+ sprintf(cp, ".%x", *up++);
+ while (up < uplim) {
+ while (*cp) cp++;
+ sprintf(cp, "%02x", *up++);
+ }
+ cp = spectHex(cp2);
+ }
+ if (port) {
+ sprintf(cp, ".%x", port);
+ spectHex(cp + 1);
+ }
+ return (obuf);
+}
+
+static char *
+spectHex(
+ char *p0
+ )
+{
+ int ok = 0;
+ int nonzero = 0;
+ register char *p = p0;
+ for (; *p; p++) switch (*p) {
+
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ *p += ('A' - 'a');
+ /* fall into . . . */
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ ok = 1;
+ case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9':
+ nonzero = 1;
+ }
+ if (nonzero && !ok) { *p++ = 'H'; *p = 0; }
+ return (p);
+}
diff --git a/StdLib/BsdSocketLib/ns_parse.c b/StdLib/BsdSocketLib/ns_parse.c new file mode 100644 index 0000000000..b050cdee1f --- /dev/null +++ b/StdLib/BsdSocketLib/ns_parse.c @@ -0,0 +1,230 @@ +/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by Intel Corporation and
+ * its contributors.
+ *
+ * 4. Neither the name of Intel Corporation or its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: ns_parse.c,v 1.1.1.1 2003/11/19 01:51:33 kyu3 Exp $";
+#endif
+
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <resolv.h>
+#include <string.h>
+
+/* These need to be in the same order as the nres.h:ns_flag enum. */
+struct _ns_flagdata _ns_flagdata[16] = {
+ { 0x8000, 15 }, /* qr. */
+ { 0x7800, 11 }, /* opcode. */
+ { 0x0400, 10 }, /* aa. */
+ { 0x0200, 9 }, /* tc. */
+ { 0x0100, 8 }, /* rd. */
+ { 0x0080, 7 }, /* ra. */
+ { 0x0040, 6 }, /* z. */
+ { 0x0020, 5 }, /* ad. */
+ { 0x0010, 4 }, /* cd. */
+ { 0x000f, 0 }, /* rcode. */
+ { 0x0000, 0 }, /* expansion (1/6). */
+ { 0x0000, 0 }, /* expansion (2/6). */
+ { 0x0000, 0 }, /* expansion (3/6). */
+ { 0x0000, 0 }, /* expansion (4/6). */
+ { 0x0000, 0 }, /* expansion (5/6). */
+ { 0x0000, 0 }, /* expansion (6/6). */
+};
+
+static int
+skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) {
+ const u_char *optr = ptr;
+
+ for ((void)NULL; count > 0; count--) {
+ int b, rdlength;
+
+ b = dn_skipname(ptr, eom);
+ if (b < 0)
+ goto emsgsize;
+ ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/;
+ if (section != ns_s_qd) {
+ if (ptr + NS_INT32SZ > eom)
+ goto emsgsize;
+ ptr += NS_INT32SZ/*TTL*/;
+ if (ptr + NS_INT16SZ > eom)
+ goto emsgsize;
+ NS_GET16(rdlength, ptr);
+ ptr += rdlength/*RData*/;
+ }
+ }
+ if (ptr > eom)
+ goto emsgsize;
+ return ((int)(ptr - optr));
+ emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+}
+
+int
+ns_initparse(const u_char *msg, int msglen, ns_msg *handle) {
+ const u_char *eom = msg + msglen;
+ int i;
+
+ memset(handle, 0x5e, sizeof *handle);
+ handle->_msg = msg;
+ handle->_eom = eom;
+ if (msg + NS_INT16SZ > eom)
+ goto emsgsize;
+ NS_GET16(handle->_id, msg);
+ if (msg + NS_INT16SZ > eom)
+ goto emsgsize;
+ NS_GET16(handle->_flags, msg);
+ for (i = 0; i < ns_s_max; i++) {
+ if (msg + NS_INT16SZ > eom)
+ goto emsgsize;
+ NS_GET16(handle->_counts[i], msg);
+ }
+ for (i = 0; i < ns_s_max; i++)
+ if (handle->_counts[i] == 0)
+ handle->_sections[i] = NULL;
+ else {
+ int b = skiprr(msg, eom, (ns_sect)i,
+ handle->_counts[i]);
+
+ if (b < 0)
+ return (-1);
+ handle->_sections[i] = msg;
+ msg += b;
+ }
+ if (msg != eom)
+ goto emsgsize;
+ handle->_sect = ns_s_max;
+ handle->_rrnum = -1;
+ handle->_msg_ptr = NULL;
+ return (0);
+ emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+}
+
+int
+ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) {
+ int b;
+
+ /* Make section right. */
+ if (section < 0 || section >= ns_s_max)
+ goto enodev;
+ if ((int)section != (int)handle->_sect) {
+ handle->_sect = section;
+ handle->_rrnum = 0;
+ handle->_msg_ptr = handle->_sections[(int)section];
+ }
+
+ /* Make rrnum right. */
+ if (rrnum == -1)
+ rrnum = handle->_rrnum;
+ if (rrnum < 0 || rrnum >= handle->_counts[(int)section])
+ goto enodev;
+ if (rrnum < handle->_rrnum) {
+ handle->_rrnum = 0;
+ handle->_msg_ptr = handle->_sections[(int)section];
+ }
+
+ b = skiprr(handle->_msg, handle->_eom, section,
+ rrnum - handle->_rrnum);
+ if (b < 0)
+ return (-1);
+ handle->_msg_ptr += b;
+ handle->_rrnum = rrnum;
+
+ /* Do the parse. */
+ b = dn_expand(handle->_msg, handle->_eom,
+ handle->_msg_ptr, rr->name, NS_MAXDNAME);
+ if (b < 0)
+ return (-1);
+ handle->_msg_ptr += b;
+ if (handle->_msg_ptr + NS_INT16SZ > handle->_eom)
+ goto emsgsize;
+ NS_GET16(rr->type, handle->_msg_ptr);
+ if (handle->_msg_ptr + NS_INT16SZ > handle->_eom)
+ goto emsgsize;
+ NS_GET16(rr->rr_class, handle->_msg_ptr);
+ if (section == ns_s_qd) {
+ rr->ttl = 0;
+ rr->rdlength = 0;
+ rr->rdata = NULL;
+ } else {
+ if (handle->_msg_ptr + NS_INT32SZ > handle->_eom)
+ goto emsgsize;
+ NS_GET32(rr->ttl, handle->_msg_ptr);
+ if (handle->_msg_ptr + NS_INT16SZ > handle->_eom)
+ goto emsgsize;
+ NS_GET16(rr->rdlength, handle->_msg_ptr);
+ if (handle->_msg_ptr + rr->rdlength > handle->_eom)
+ goto emsgsize;
+ rr->rdata = handle->_msg_ptr;
+ handle->_msg_ptr += rr->rdlength;
+ }
+ handle->_rrnum++;
+
+ /* All done. */
+ return (0);
+ enodev:
+ errno = ENODEV;
+ return (-1);
+ emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+}
diff --git a/StdLib/BsdSocketLib/ns_print.c b/StdLib/BsdSocketLib/ns_print.c new file mode 100644 index 0000000000..83aeeb32a0 --- /dev/null +++ b/StdLib/BsdSocketLib/ns_print.c @@ -0,0 +1,780 @@ +/*
+ * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by Intel Corporation and
+ * its contributors.
+ *
+ * 4. Neither the name of Intel Corporation or its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: ns_print.c,v 1.1.1.1 2003/11/19 01:51:34 kyu3 Exp $";
+#endif
+
+/* Import. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <resolv.h>
+#include <string.h>
+#include <ctype.h>
+
+#define SPRINTF(x) (sprintf x)
+
+/* Forward. */
+
+static size_t prune_origin(const char *name, const char *origin);
+static int charstr(const u_char *rdata, const u_char *edata,
+ char **buf, size_t *buflen);
+static int addname(const u_char *msg, size_t msglen,
+ const u_char **p, const char *origin,
+ char **buf, size_t *buflen);
+static void addlen(size_t len, char **buf, size_t *buflen);
+static int addstr(const char *src, size_t len,
+ char **buf, size_t *buflen);
+static int addtab(size_t len, size_t target, int spaced,
+ char **buf, size_t *buflen);
+
+/* Macros. */
+
+#define T(x) \
+ do { \
+ if ((ssize_t)(x) < 0) \
+ return (-1); \
+ } while (0)
+
+/* Public. */
+
+/*
+ * int
+ * ns_sprintrr(handle, rr, name_ctx, origin, buf, buflen)
+ * Convert an RR to presentation format.
+ * return:
+ * Number of characters written to buf, or -1 (check errno).
+ */
+int
+ns_sprintrr(const ns_msg *handle, const ns_rr *rr,
+ const char *name_ctx, const char *origin,
+ char *buf, size_t buflen)
+{
+ int n;
+
+ n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle),
+ ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr),
+ ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr),
+ name_ctx, origin, buf, buflen);
+ return (n);
+}
+
+/*
+ * int
+ * ns_sprintrrf(msg, msglen, name, class, type, ttl, rdata, rdlen,
+ * name_ctx, origin, buf, buflen)
+ * Convert the fields of an RR into presentation format.
+ * return:
+ * Number of characters written to buf, or -1 (check errno).
+ */
+int
+ns_sprintrrf(const u_char *msg, size_t msglen,
+ const char *name, ns_class class, ns_type type,
+ u_long ttl, const u_char *rdata, size_t rdlen,
+ const char *name_ctx, const char *origin,
+ char *buf, size_t buflen)
+{
+ const char *obuf = buf;
+ const u_char *edata = rdata + rdlen;
+ int spaced = 0;
+
+ const char *comment;
+ char tmp[100];
+ int x;
+ size_t len;
+
+ static char base64_key[NS_MD5RSA_MAX_BASE64];
+ static char t[255*3];
+
+ /*
+ * Owner.
+ */
+ if (name_ctx != NULL && strcasecmp(name_ctx, name) == 0) {
+ T(addstr("\t\t\t", 3, &buf, &buflen));
+ } else {
+ len = prune_origin(name, origin);
+ if (len == 0) {
+ T(addstr("@\t\t\t", 4, &buf, &buflen));
+ } else {
+ T(addstr(name, len, &buf, &buflen));
+ /* Origin not used and no trailing dot? */
+ if ((!origin || !origin[0] || name[len] == '\0') &&
+ name[len - 1] != '.') {
+ T(addstr(".", 1, &buf, &buflen));
+ len++;
+ }
+ T(spaced = addtab(len, 24, spaced, &buf, &buflen));
+ }
+ }
+
+ /*
+ * TTL, Class, Type.
+ */
+ T(x = ns_format_ttl(ttl, buf, buflen));
+ addlen(x, &buf, &buflen);
+ len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type)));
+ T(addstr(tmp, len, &buf, &buflen));
+ T(spaced = addtab(x + len, 16, spaced, &buf, &buflen));
+
+ /*
+ * RData.
+ */
+ switch (type) {
+ case ns_t_a:
+ if (rdlen != NS_INADDRSZ)
+ goto formerr;
+ (void) inet_ntop(AF_INET, rdata, buf, (socklen_t)buflen);
+ addlen(strlen(buf), &buf, &buflen);
+ break;
+
+ case ns_t_cname:
+ case ns_t_mb:
+ case ns_t_mg:
+ case ns_t_mr:
+ case ns_t_ns:
+ case ns_t_ptr:
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ break;
+
+ case ns_t_hinfo:
+ case ns_t_isdn:
+ /* First word. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Second word. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ break;
+
+ case ns_t_soa: {
+ u_long t;
+
+ /* Server name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Administrator name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" (\n", 3, &buf, &buflen));
+ spaced = 0;
+
+ if ((edata - rdata) != 5*NS_INT32SZ)
+ goto formerr;
+
+ /* Serial number. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ len = SPRINTF((tmp, "%lu", t));
+ T(addstr(tmp, len, &buf, &buflen));
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; serial\n", 9, &buf, &buflen));
+ spaced = 0;
+
+ /* Refresh interval. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ T(len = ns_format_ttl(t, buf, buflen));
+ addlen(len, &buf, &buflen);
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; refresh\n", 10, &buf, &buflen));
+ spaced = 0;
+
+ /* Retry interval. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ T(len = ns_format_ttl(t, buf, buflen));
+ addlen(len, &buf, &buflen);
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; retry\n", 8, &buf, &buflen));
+ spaced = 0;
+
+ /* Expiry. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ T(len = ns_format_ttl(t, buf, buflen));
+ addlen(len, &buf, &buflen);
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; expiry\n", 9, &buf, &buflen));
+ spaced = 0;
+
+ /* Minimum TTL. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ T(len = ns_format_ttl(t, buf, buflen));
+ addlen(len, &buf, &buflen);
+ T(addstr(" )", 2, &buf, &buflen));
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; minimum\n", 10, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_mx:
+ case ns_t_afsdb:
+ case ns_t_rt: {
+ u_int t;
+
+ if (rdlen < NS_INT16SZ)
+ goto formerr;
+
+ /* Priority. */
+ t = ns_get16(rdata);
+ rdata += NS_INT16SZ;
+ len = SPRINTF((tmp, "%u ", t));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Target. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_px: {
+ u_int t;
+
+ if (rdlen < NS_INT16SZ)
+ goto formerr;
+
+ /* Priority. */
+ t = ns_get16(rdata);
+ rdata += NS_INT16SZ;
+ len = SPRINTF((tmp, "%u ", t));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Name1. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Name2. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_x25:
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ break;
+
+ case ns_t_txt:
+ while (rdata < edata) {
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ if (rdata < edata)
+ T(addstr(" ", 1, &buf, &buflen));
+ }
+ break;
+
+ case ns_t_nsap: {
+
+ (void) inet_nsap_ntoa((int)rdlen, rdata, t);
+ T(addstr(t, strlen(t), &buf, &buflen));
+ break;
+ }
+
+ case ns_t_aaaa:
+ if (rdlen != NS_IN6ADDRSZ)
+ goto formerr;
+ (void) inet_ntop(AF_INET6, rdata, buf, (socklen_t)buflen);
+ addlen(strlen(buf), &buf, &buflen);
+ break;
+
+ case ns_t_loc: {
+ /* XXX protocol format checking? */
+ (void) loc_ntoa(rdata, t);
+ T(addstr(t, strlen(t), &buf, &buflen));
+ break;
+ }
+
+ case ns_t_naptr: {
+ u_int order, preference;
+
+ if (rdlen < 2*NS_INT16SZ)
+ goto formerr;
+
+ /* Order, Precedence. */
+ order = ns_get16(rdata); rdata += NS_INT16SZ;
+ preference = ns_get16(rdata); rdata += NS_INT16SZ;
+ len = SPRINTF((t, "%u %u ", order, preference));
+ T(addstr(t, len, &buf, &buflen));
+
+ /* Flags. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Service. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Regexp. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if ((ssize_t)len < 0)
+ return (-1);
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Server. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ break;
+ }
+
+ case ns_t_srv: {
+ u_int priority, weight, port;
+
+ if (rdlen < NS_INT16SZ*3)
+ goto formerr;
+
+ /* Priority, Weight, Port. */
+ priority = ns_get16(rdata); rdata += NS_INT16SZ;
+ weight = ns_get16(rdata); rdata += NS_INT16SZ;
+ port = ns_get16(rdata); rdata += NS_INT16SZ;
+ len = SPRINTF((t, "%u %u %u ", priority, weight, port));
+ T(addstr(t, len, &buf, &buflen));
+
+ /* Server. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ break;
+ }
+
+ case ns_t_minfo:
+ case ns_t_rp:
+ /* Name1. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Name2. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ break;
+
+ case ns_t_wks: {
+ int n, lcnt;
+
+ if (rdlen < NS_INT32SZ + 1)
+ goto formerr;
+
+ /* Address. */
+ (void) inet_ntop(AF_INET, rdata, buf, (socklen_t)buflen);
+ addlen(strlen(buf), &buf, &buflen);
+ rdata += NS_INADDRSZ;
+
+ /* Protocol. */
+ len = SPRINTF((tmp, " %u ( ", *rdata));
+ T(addstr(tmp, len, &buf, &buflen));
+ rdata += NS_INT8SZ;
+
+ /* Bit map. */
+ n = 0;
+ lcnt = 0;
+ while (rdata < edata) {
+ u_int c = *rdata++;
+ do {
+ if (c & 0200) {
+ if (lcnt == 0) {
+ T(addstr("\n\t\t\t\t", 5,
+ &buf, &buflen));
+ lcnt = 10;
+ spaced = 0;
+ }
+ len = SPRINTF((tmp, "%d ", n));
+ T(addstr(tmp, len, &buf, &buflen));
+ lcnt--;
+ }
+ c <<= 1;
+ } while (++n & 07);
+ }
+ T(addstr(")", 1, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_key: {
+ u_int keyflags, protocol, algorithm;
+ const char *leader;
+ int n;
+
+ if (rdlen < NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)
+ goto formerr;
+
+ /* Key flags, Protocol, Algorithm. */
+ keyflags = ns_get16(rdata); rdata += NS_INT16SZ;
+ protocol = *rdata++;
+ algorithm = *rdata++;
+ len = SPRINTF((tmp, "0x%04x %u %u",
+ keyflags, protocol, algorithm));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Public key data. */
+ len = b64_ntop(rdata, edata - rdata,
+ base64_key, sizeof base64_key);
+ if ((ssize_t)len < 0)
+ goto formerr;
+ if (len > 15) {
+ T(addstr(" (", 2, &buf, &buflen));
+ leader = "\n\t\t";
+ spaced = 0;
+ } else
+ leader = " ";
+ for (n = 0; n < (int)len; n += 48) {
+ T(addstr(leader, strlen(leader), &buf, &buflen));
+ T(addstr(base64_key + n, MIN(len - n, 48),
+ &buf, &buflen));
+ }
+ if (len > 15)
+ T(addstr(" )", 2, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_sig: {
+ u_int type, algorithm, labels, footprint;
+ const char *leader;
+ u_long t;
+ int n;
+
+ if (rdlen < 22)
+ goto formerr;
+
+ /* Type covered, Algorithm, Label count, Original TTL. */
+ type = ns_get16(rdata); rdata += NS_INT16SZ;
+ algorithm = *rdata++;
+ labels = *rdata++;
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ len = SPRINTF((tmp, " %s %d %lu ",
+ p_type((int)type), algorithm, t));
+ T(addstr(tmp, len, &buf, &buflen));
+ if (labels != (u_int)dn_count_labels(name))
+ goto formerr;
+
+ /* Signature expiry. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ len = SPRINTF((tmp, "%s ", p_secstodate(t)));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Time signed. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ len = SPRINTF((tmp, "%s ", p_secstodate(t)));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Signature Footprint. */
+ footprint = ns_get16(rdata); rdata += NS_INT16SZ;
+ len = SPRINTF((tmp, "%u ", footprint));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Signer's name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ /* Signature. */
+ len = b64_ntop(rdata, edata - rdata,
+ base64_key, sizeof base64_key);
+ if (len > 15) {
+ T(addstr(" (", 2, &buf, &buflen));
+ leader = "\n\t\t";
+ spaced = 0;
+ } else
+ leader = " ";
+ if ((ssize_t)len < 0)
+ goto formerr;
+ for (n = 0; n < (int)len; n += 48) {
+ T(addstr(leader, strlen(leader), &buf, &buflen));
+ T(addstr(base64_key + n, MIN(len - n, 48),
+ &buf, &buflen));
+ }
+ if (len > 15)
+ T(addstr(" )", 2, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_nxt: {
+ int n, c;
+
+ /* Next domain name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ /* Type bit map. */
+ n = (int)(edata - rdata);
+ for (c = 0; c < n*8; c++)
+ if (NS_NXT_BIT_ISSET(c, rdata)) {
+ len = SPRINTF((tmp, " %s", p_type(c)));
+ T(addstr(tmp, len, &buf, &buflen));
+ }
+ break;
+ }
+
+ default:
+ comment = "unknown RR type";
+ goto hexify;
+ }
+ return ((int)(buf - obuf));
+ formerr:
+ comment = "RR format error";
+ hexify: {
+ int n, m;
+ char *p;
+
+ len = SPRINTF((tmp, "\\#(\t\t; %s", comment));
+ T(addstr(tmp, len, &buf, &buflen));
+ while (rdata < edata) {
+ p = tmp;
+ p += SPRINTF((p, "\n\t"));
+ spaced = 0;
+ n = MIN(16, (int)(edata - rdata));
+ for (m = 0; m < n; m++)
+ p += SPRINTF((p, "%02x ", rdata[m]));
+ T(addstr(tmp, (u_int)(p - tmp), &buf, &buflen));
+ if (n < 16) {
+ T(addstr(")", 1, &buf, &buflen));
+ T(addtab((u_int)(p - tmp) + 1, 48, spaced, &buf, &buflen));
+ }
+ p = tmp;
+ p += SPRINTF((p, "; "));
+ for (m = 0; m < n; m++)
+ *p++ = (isascii(rdata[m]) && isprint(rdata[m]))
+ ? rdata[m]
+ : '.';
+ T(addstr(tmp, (u_int)(p - tmp), &buf, &buflen));
+ rdata += n;
+ }
+ return ((int)(buf - obuf));
+ }
+}
+
+/* Private. */
+
+/*
+ * size_t
+ * prune_origin(name, origin)
+ * Find out if the name is at or under the current origin.
+ * return:
+ * Number of characters in name before start of origin,
+ * or length of name if origin does not match.
+ * notes:
+ * This function should share code with samedomain().
+ */
+static size_t
+prune_origin(const char *name, const char *origin) {
+ const char *oname = name;
+
+ while (*name != '\0') {
+ if (origin != NULL && strcasecmp(name, origin) == 0)
+ return ((size_t)(name - oname) - (name > oname));
+ while (*name != '\0') {
+ if (*name == '\\') {
+ name++;
+ /* XXX need to handle \nnn form. */
+ if (*name == '\0')
+ break;
+ } else if (*name == '.') {
+ name++;
+ break;
+ }
+ name++;
+ }
+ }
+ return ((size_t)(name - oname));
+}
+
+/*
+ * int
+ * charstr(rdata, edata, buf, buflen)
+ * Format a <character-string> into the presentation buffer.
+ * return:
+ * Number of rdata octets consumed
+ * 0 for protocol format error
+ * -1 for output buffer error
+ * side effects:
+ * buffer is advanced on success.
+ */
+static int
+charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) {
+ const u_char *odata = rdata;
+ size_t save_buflen = *buflen;
+ char *save_buf = *buf;
+
+ if (addstr("\"", 1, buf, buflen) < 0)
+ goto enospc;
+ if (rdata < edata) {
+ int n = *rdata;
+
+ if (rdata + 1 + n <= edata) {
+ rdata++;
+ while (n-- > 0) {
+ if (strchr("\n\"\\", *rdata) != NULL)
+ if (addstr("\\", 1, buf, buflen) < 0)
+ goto enospc;
+ if (addstr((const char *)rdata, 1,
+ buf, buflen) < 0)
+ goto enospc;
+ rdata++;
+ }
+ }
+ }
+ if (addstr("\"", 1, buf, buflen) < 0)
+ goto enospc;
+ return ((int)(rdata - odata));
+ enospc:
+ errno = ENOSPC;
+ *buf = save_buf;
+ *buflen = save_buflen;
+ return (-1);
+}
+
+static int
+addname(const u_char *msg, size_t msglen,
+ const u_char **pp, const char *origin,
+ char **buf, size_t *buflen)
+{
+ size_t newlen, save_buflen = *buflen;
+ char *save_buf = *buf;
+ int n;
+
+ n = dn_expand(msg, msg + msglen, *pp, *buf, (int)(*buflen));
+ if (n < 0)
+ goto enospc; /* Guess. */
+ newlen = prune_origin(*buf, origin);
+ if ((origin == NULL || origin[0] == '\0' || (*buf)[newlen] == '\0') &&
+ (newlen == 0 || (*buf)[newlen - 1] != '.')) {
+ /* No trailing dot. */
+ if (newlen + 2 > *buflen)
+ goto enospc; /* No room for ".\0". */
+ (*buf)[newlen++] = '.';
+ (*buf)[newlen] = '\0';
+ }
+ if (newlen == 0) {
+ /* Use "@" instead of name. */
+ if (newlen + 2 > *buflen)
+ goto enospc; /* No room for "@\0". */
+ (*buf)[newlen++] = '@';
+ (*buf)[newlen] = '\0';
+ }
+ *pp += n;
+ addlen(newlen, buf, buflen);
+ **buf = '\0';
+ return ((int)newlen);
+ enospc:
+ errno = ENOSPC;
+ *buf = save_buf;
+ *buflen = save_buflen;
+ return (-1);
+}
+
+static void
+addlen(size_t len, char **buf, size_t *buflen) {
+ assert(len <= *buflen);
+ *buf += len;
+ *buflen -= len;
+}
+
+static int
+addstr(const char *src, size_t len, char **buf, size_t *buflen) {
+ if (len > *buflen) {
+ errno = ENOSPC;
+ return (-1);
+ }
+ memcpy(*buf, src, len);
+ addlen(len, buf, buflen);
+ **buf = '\0';
+ return (0);
+}
+
+static int
+addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) {
+ size_t save_buflen = *buflen;
+ char *save_buf = *buf;
+ int t;
+
+ if (spaced || len >= target - 1) {
+ T(addstr(" ", 2, buf, buflen));
+ spaced = 1;
+ } else {
+ for (t = (int)(target - len - 1) / 8; t >= 0; t--)
+ if (addstr("\t", 1, buf, buflen) < 0) {
+ *buflen = save_buflen;
+ *buf = save_buf;
+ return (-1);
+ }
+ spaced = 0;
+ }
+ return (spaced);
+}
diff --git a/StdLib/BsdSocketLib/ns_ttl.c b/StdLib/BsdSocketLib/ns_ttl.c new file mode 100644 index 0000000000..a5a57449eb --- /dev/null +++ b/StdLib/BsdSocketLib/ns_ttl.c @@ -0,0 +1,191 @@ +/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by Intel Corporation and
+ * its contributors.
+ *
+ * 4. Neither the name of Intel Corporation or its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: ns_ttl.c,v 1.1.1.1 2003/11/19 01:51:34 kyu3 Exp $";
+#endif
+
+/* Import. */
+
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#define SPRINTF(x) ((size_t)sprintf x)
+
+/* Forward. */
+
+static int fmt1(int t, char s, char **buf, size_t *buflen);
+
+/* Macros. */
+
+#define T(x) if ((x) < 0) return (-1); else (void)NULL
+
+/* Public. */
+
+int
+ns_format_ttl(u_long src, char *dst, size_t dstlen) {
+ char *odst = dst;
+ int secs, mins, hours, days, weeks, x;
+ char *p;
+
+ secs = (int)(src % 60); src /= 60;
+ mins = (int)(src % 60); src /= 60;
+ hours = (int)(src % 24); src /= 24;
+ days = (int)(src % 7); src /= 7;
+ weeks = (int)src; src = 0;
+
+ x = 0;
+ if (weeks) {
+ T(fmt1(weeks, 'W', &dst, &dstlen));
+ x++;
+ }
+ if (days) {
+ T(fmt1(days, 'D', &dst, &dstlen));
+ x++;
+ }
+ if (hours) {
+ T(fmt1(hours, 'H', &dst, &dstlen));
+ x++;
+ }
+ if (mins) {
+ T(fmt1(mins, 'M', &dst, &dstlen));
+ x++;
+ }
+ if (secs || !(weeks || days || hours || mins)) {
+ T(fmt1(secs, 'S', &dst, &dstlen));
+ x++;
+ }
+
+ if (x > 1) {
+ int ch;
+
+ for (p = odst; (ch = *p) != '\0'; p++)
+ if (isascii(ch) && isupper(ch))
+ *p = (char)( tolower(ch));
+ }
+
+ return ((int)(dst - odst));
+}
+
+int
+ns_parse_ttl(const char *src, u_long *dst) {
+ u_long ttl, tmp;
+ int ch, digits, dirty;
+
+ ttl = 0;
+ tmp = 0;
+ digits = 0;
+ dirty = 0;
+ while ((ch = *src++) != '\0') {
+ if (!isascii(ch) || !isprint(ch))
+ goto einval;
+ if (isdigit(ch)) {
+ tmp *= 10;
+ tmp += (ch - '0');
+ digits++;
+ continue;
+ }
+ if (digits == 0)
+ goto einval;
+ if (islower(ch))
+ ch = toupper(ch);
+ switch (ch) {
+ case 'W': tmp *= 7;
+ case 'D': tmp *= 24;
+ case 'H': tmp *= 60;
+ case 'M': tmp *= 60;
+ case 'S': break;
+ default: goto einval;
+ }
+ ttl += tmp;
+ tmp = 0;
+ digits = 0;
+ dirty = 1;
+ }
+ if (digits > 0) {
+ if (dirty)
+ goto einval;
+ else
+ ttl += tmp;
+ }
+ *dst = ttl;
+ return (0);
+
+ einval:
+ errno = EINVAL;
+ return (-1);
+}
+
+/* Private. */
+
+static int
+fmt1(int t, char s, char **buf, size_t *buflen) {
+ char tmp[50];
+ size_t len;
+
+ len = SPRINTF((tmp, "%d%c", t, s));
+ if (len + 1 > *buflen)
+ return (-1);
+ strcpy(*buf, tmp);
+ *buf += len;
+ *buflen -= len;
+ return (0);
+}
diff --git a/StdLib/BsdSocketLib/nsap_addr.c b/StdLib/BsdSocketLib/nsap_addr.c new file mode 100644 index 0000000000..957c97f55f --- /dev/null +++ b/StdLib/BsdSocketLib/nsap_addr.c @@ -0,0 +1,108 @@ +/*
+ * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] = "$Id: nsap_addr.c,v 1.1.1.1 2003/11/19 01:51:31 kyu3 Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <ctype.h>
+#include <resolv.h>
+
+static char
+xtob(
+ register int c
+ )
+{
+ return (char)(c - (((c >= '0') && (c <= '9')) ? '0' : '7'));
+}
+
+u_int
+inet_nsap_addr(
+ const char *ascii,
+ u_char *binary,
+ int maxlen
+ )
+{
+ u_char c, nib;
+ u_int len = 0;
+
+ while ((c = *ascii++) != '\0' && len < (u_int)maxlen) {
+ if (c == '.' || c == '+' || c == '/')
+ continue;
+ if (!isascii(c))
+ return (0);
+ if (islower(c))
+ c = (u_char)( toupper(c));
+ if (isxdigit(c)) {
+ nib = xtob(c);
+ c = *ascii++;
+ if (c != '\0') {
+ c = (u_char)( toupper(c));
+ if (isxdigit(c)) {
+ *binary++ = (nib << 4) | xtob(c);
+ len++;
+ } else
+ return (0);
+ }
+ else
+ return (0);
+ }
+ else
+ return (0);
+ }
+ return (len);
+}
+
+char *
+inet_nsap_ntoa(
+ int binlen,
+ register const u_char *binary,
+ register char *ascii
+ )
+{
+ register int nib;
+ int i;
+ static char tmpbuf[255*3];
+ char *start;
+
+ if (ascii)
+ start = ascii;
+ else {
+ ascii = tmpbuf;
+ start = tmpbuf;
+ }
+
+ if (binlen > 255)
+ binlen = 255;
+
+ for (i = 0; i < binlen; i++) {
+ nib = *binary >> 4;
+ *ascii++ = (char)( nib + (nib < 10 ? '0' : '7'));
+ nib = *binary++ & 0x0f;
+ *ascii++ = (char)( nib + (nib < 10 ? '0' : '7'));
+ if (((i % 2) == 0 && (i + 1) < binlen))
+ *ascii++ = '.';
+ }
+ *ascii = '\0';
+ return (start);
+}
diff --git a/StdLib/BsdSocketLib/poll.c b/StdLib/BsdSocketLib/poll.c new file mode 100644 index 0000000000..fdf50e8b68 --- /dev/null +++ b/StdLib/BsdSocketLib/poll.c @@ -0,0 +1,57 @@ +/** @file
+ Implement the poll API.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <SocketInternals.h>
+
+
+/**
+ Poll the socket for activity
+
+ @param [in] pDescriptor Descriptor address for the file
+
+ @param [in] Events Mask of events to detect
+
+ @returns Detected events for the socket
+
+ **/
+short
+BslSocketPoll (
+ IN struct __filedes * pDescriptor,
+ IN short Events
+ )
+{
+ short DetectedEvents;
+ EFI_SOCKET_PROTOCOL * pSocketProtocol;
+ EFI_STATUS Status;
+
+ //
+ // Locate the socket protocol
+ //
+ DetectedEvents = 0;
+ pSocketProtocol = BslValidateSocketFd ( pDescriptor, &errno );
+ if ( NULL != pSocketProtocol ) {
+ //
+ // Poll the socket
+ //
+ Status = pSocketProtocol->pfnPoll ( pSocketProtocol,
+ Events,
+ &DetectedEvents,
+ &errno );
+ }
+
+ //
+ // Return the detected events
+ //
+ return DetectedEvents;
+}
diff --git a/StdLib/BsdSocketLib/read.c b/StdLib/BsdSocketLib/read.c new file mode 100644 index 0000000000..eb72f5cbf7 --- /dev/null +++ b/StdLib/BsdSocketLib/read.c @@ -0,0 +1,53 @@ +/** @file
+ Implement the read API.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <SocketInternals.h>
+
+
+/**
+ Read support routine for sockets
+
+ @param [in] pDescriptor Descriptor address for the file
+ @param [in] pOffset File offset
+ @param [in] LengthInBytes Number of bytes to read
+ @param [in] pBuffer Address of the buffer to receive the data
+
+ @returns The number of bytes read or -1 if an error occurs.
+
+**/
+ssize_t
+BslSocketRead (
+ struct __filedes *pDescriptor,
+ off_t * pOffset,
+ size_t LengthInBytes,
+ void * pBuffer
+ )
+{
+ ssize_t BytesRead;
+
+ //
+ // Receive the data from the remote system
+ //
+ BytesRead = recvfrom ( pDescriptor->MyFD,
+ pBuffer,
+ LengthInBytes,
+ 0,
+ NULL,
+ NULL );
+
+ //
+ // Return the number of bytes read
+ //
+ return BytesRead;
+}
diff --git a/StdLib/BsdSocketLib/recv.c b/StdLib/BsdSocketLib/recv.c new file mode 100644 index 0000000000..735e1dbddd --- /dev/null +++ b/StdLib/BsdSocketLib/recv.c @@ -0,0 +1,63 @@ +/** @file
+ Implement the recv API.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <SocketInternals.h>
+
+
+/**
+ Receive data from a network connection.
+
+ The ::recv routine waits for receive data from a remote network
+ connection. The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html">POSIX</a>
+ documentation is available online.
+
+ @param [in] s Socket file descriptor returned from ::socket.
+
+ @param [in] buffer Address of a buffer to receive the data.
+
+ @param [in] length Length of the buffer in bytes.
+
+ @param [in] flags Message control flags
+
+ @returns ::recv returns the number of valid bytes in the buffer,
+ zero if no data was received, and -1 when an error occurs.
+ In the case of an error, errno contains more details.
+
+ **/
+ssize_t
+recv (
+ int s,
+ void * buffer,
+ size_t length,
+ int flags
+ )
+{
+ ssize_t BytesRead;
+
+ //
+ // Receive the data from the remote system
+ //
+ BytesRead = recvfrom ( s,
+ buffer,
+ length,
+ flags,
+ NULL,
+ NULL );
+
+ //
+ // Return the number of bytes read
+ //
+ return BytesRead;
+}
diff --git a/StdLib/BsdSocketLib/recvfrom.c b/StdLib/BsdSocketLib/recvfrom.c new file mode 100644 index 0000000000..a8d1ab54ee --- /dev/null +++ b/StdLib/BsdSocketLib/recvfrom.c @@ -0,0 +1,197 @@ +/** @file
+ Implement the recvfrom API.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <SocketInternals.h>
+
+
+/**
+ Receive data from a network connection and return the remote system's address.
+
+ The ::recvfrom routine waits for receive data from a remote network
+ connection. The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html">POSIX</a>
+ documentation is available online.
+
+ @param [in] s Socket file descriptor returned from ::socket.
+
+ @param [in] buffer Address of a buffer to receive the data.
+
+ @param [in] length Length of the buffer in bytes.
+
+ @param [in] flags Message control flags
+
+ @param [out] address Network address to receive the remote system address
+
+ @param [in] address_len Length of the remote network address structure
+
+ @returns ::recvfrom returns the number of valid bytes in the buffer,
+ zero if no data was received, and -1 when an error occurs.
+ In the case of an error, errno contains more details.
+
+ **/
+ssize_t
+recvfrom (
+ int s,
+ void * buffer,
+ size_t length,
+ int flags,
+ struct sockaddr * address,
+ socklen_t * address_len
+ )
+{
+ socklen_t ByteCount;
+ ssize_t LengthInBytes;
+ UINT8 * pData;
+ EFI_SOCKET_PROTOCOL * pSocketProtocol;
+ EFI_STATUS Status;
+ struct timeval TimeVal;
+ EFI_EVENT pTimer;
+ UINT64 Timeout;
+ ssize_t TotalBytes;
+
+ //
+ // Assume failure
+ //
+ LengthInBytes = -1;
+
+ //
+ // Locate the context for this socket
+ //
+ pSocketProtocol = BslFdToSocketProtocol ( s, NULL, &errno );
+ if ( NULL != pSocketProtocol ) {
+ //
+ // Receive the data from the socket
+ //
+ Status = pSocketProtocol->pfnReceive ( pSocketProtocol,
+ flags,
+ length,
+ buffer,
+ (size_t *)&LengthInBytes,
+ address,
+ address_len,
+ &errno );
+ if ( EFI_ERROR ( Status )) {
+ LengthInBytes = -1;
+ if ( EAGAIN == errno ) {
+ //
+ // Get the timeout
+ //
+ ByteCount = sizeof ( TimeVal );
+ LengthInBytes = getsockopt ( s,
+ SOL_SOCKET,
+ SO_RCVTIMEO,
+ &TimeVal,
+ &ByteCount );
+ if ( 0 == LengthInBytes ) {
+ //
+ // Compute the timeout
+ //
+ Timeout = TimeVal.tv_sec;
+ Timeout *= 1000 * 1000;
+ Timeout += TimeVal.tv_usec;
+ Timeout *= 10;
+
+ //
+ // The timer is only necessary if a timeout is running
+ //
+ LengthInBytes = -1;
+ Status = EFI_SUCCESS;
+ pTimer = NULL;
+ if ( 0 != Timeout ) {
+ Status = gBS->CreateEvent ( EVT_TIMER,
+ TPL_NOTIFY,
+ NULL,
+ NULL,
+ &pTimer );
+ }
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Start the timer
+ //
+ if ( NULL != pTimer ) {
+ Status = gBS->SetTimer ( pTimer,
+ TimerRelative,
+ Timeout );
+ }
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Loop until data is received or the timeout
+ // expires
+ //
+ TotalBytes = 0;
+ pData = (UINT8 *)buffer;
+ do {
+ //
+ // Determine if the timeout expired
+ //
+ if ( NULL != pTimer ) {
+ Status = gBS->CheckEvent ( pTimer );
+ if ( EFI_SUCCESS == Status ) {
+ errno = ETIMEDOUT;
+ if ( 0 == TotalBytes ) {
+ TotalBytes = -1;
+ }
+ break;
+ }
+ }
+
+ //
+ // Attempt to receive some data
+ //
+ Status = pSocketProtocol->pfnReceive ( pSocketProtocol,
+ flags,
+ length,
+ pData,
+ (size_t *)&LengthInBytes,
+ address,
+ address_len,
+ &errno );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Account for the data received
+ //
+ TotalBytes += LengthInBytes;
+ pData += LengthInBytes;
+ length -= LengthInBytes;
+ }
+ } while ( EFI_NOT_READY == Status );
+ LengthInBytes = TotalBytes;
+
+ //
+ // Stop the timer
+ //
+ if ( NULL != pTimer ) {
+ gBS->SetTimer ( pTimer,
+ TimerCancel,
+ 0 );
+ }
+ }
+
+ //
+ // Release the timer
+ //
+ if ( NULL != pTimer ) {
+ gBS->CloseEvent ( pTimer );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // Return the receive data length, -1 for errors
+ //
+ return LengthInBytes;
+}
diff --git a/StdLib/BsdSocketLib/res_comp.c b/StdLib/BsdSocketLib/res_comp.c new file mode 100644 index 0000000000..cddda3e150 --- /dev/null +++ b/StdLib/BsdSocketLib/res_comp.c @@ -0,0 +1,272 @@ +/*
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by the University of
+ * California, Berkeley, Intel Corporation, and its contributors.
+ *
+ * 4. Neither the name of University, Intel Corporation, or their respective
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS,
+ * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93";
+static char orig_rcsid[] = "From: Id: res_comp.c,v 8.11 1997/05/21 19:31:04 halley Exp $";
+static char rcsid[] = "$Id: res_comp.c,v 1.1.1.1 2003/11/19 01:51:35 kyu3 Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <ctype.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#define BIND_4_COMPAT
+
+/*
+ * Expand compressed domain name 'comp_dn' to full domain name.
+ * 'msg' is a pointer to the begining of the message,
+ * 'eomorig' points to the first location after the message,
+ * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
+ * Return size of compressed name or -1 if there was an error.
+ */
+int
+dn_expand(const u_char *msg, const u_char *eom, const u_char *src,
+ char *dst, int dstsiz)
+{
+ int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz);
+
+ if (n > 0 && dst[0] == '.')
+ dst[0] = '\0';
+ return (n);
+}
+
+/*
+ * Pack domain name 'exp_dn' in presentation form into 'comp_dn'.
+ * Return the size of the compressed name or -1.
+ * 'length' is the size of the array pointed to by 'comp_dn'.
+ */
+int
+dn_comp(const char *src, u_char *dst, int dstsiz,
+ u_char **dnptrs, u_char **lastdnptr)
+{
+ return (ns_name_compress(src, dst, (size_t)dstsiz,
+ (const u_char **)dnptrs,
+ (const u_char **)lastdnptr));
+}
+
+/*
+ * Skip over a compressed domain name. Return the size or -1.
+ */
+int
+dn_skipname(const u_char *ptr, const u_char *eom) {
+ const u_char *saveptr = ptr;
+
+ if (ns_name_skip(&ptr, eom) == -1)
+ return (-1);
+ return ((int)(ptr - saveptr));
+}
+
+/*
+ * Verify that a domain name uses an acceptable character set.
+ */
+
+/*
+ * Note the conspicuous absence of ctype macros in these definitions. On
+ * non-ASCII hosts, we can't depend on string literals or ctype macros to
+ * tell us anything about network-format data. The rest of the BIND system
+ * is not careful about this, but for some reason, we're doing it right here.
+ */
+#define PERIOD 0x2e
+#define hyphenchar(c) ((c) == 0x2d)
+#define bslashchar(c) ((c) == 0x5c)
+#define periodchar(c) ((c) == PERIOD)
+#define asterchar(c) ((c) == 0x2a)
+#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
+ || ((c) >= 0x61 && (c) <= 0x7a))
+#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
+
+#define borderchar(c) (alphachar(c) || digitchar(c))
+#define middlechar(c) (borderchar(c) || hyphenchar(c))
+#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
+
+int
+res_hnok(
+ const char *dn
+ )
+{
+ int ppch = '\0', pch = PERIOD, ch = *dn++;
+
+ while (ch != '\0') {
+ int nch = *dn++;
+
+ if (periodchar(ch)) {
+ (void)NULL;
+ } else if (periodchar(pch)) {
+ if (!borderchar(ch))
+ return (0);
+ } else if (periodchar(nch) || nch == '\0') {
+ if (!borderchar(ch))
+ return (0);
+ } else {
+ if (!middlechar(ch))
+ return (0);
+ }
+ ppch = pch, pch = ch, ch = nch;
+ }
+ return (1);
+}
+
+/*
+ * hostname-like (A, MX, WKS) owners can have "*" as their first label
+ * but must otherwise be as a host name.
+ */
+int
+res_ownok(
+ const char *dn
+ )
+{
+ if (asterchar(dn[0])) {
+ if (periodchar(dn[1]))
+ return (res_hnok(dn+2));
+ if (dn[1] == '\0')
+ return (1);
+ }
+ return (res_hnok(dn));
+}
+
+/*
+ * SOA RNAMEs and RP RNAMEs can have any printable character in their first
+ * label, but the rest of the name has to look like a host name.
+ */
+int
+res_mailok(
+ const char *dn
+ )
+{
+ int ch, escaped = 0;
+
+ /* "." is a valid missing representation */
+ if (*dn == '\0')
+ return (1);
+
+ /* otherwise <label>.<hostname> */
+ while ((ch = *dn++) != '\0') {
+ if (!domainchar(ch))
+ return (0);
+ if (!escaped && periodchar(ch))
+ break;
+ if (escaped)
+ escaped = 0;
+ else if (bslashchar(ch))
+ escaped = 1;
+ }
+ if (periodchar(ch))
+ return (res_hnok(dn));
+ return (0);
+}
+
+/*
+ * This function is quite liberal, since RFC 1034's character sets are only
+ * recommendations.
+ */
+int
+res_dnok(
+ const char *dn
+ )
+{
+ int ch;
+
+ while ((ch = *dn++) != '\0')
+ if (!domainchar(ch))
+ return (0);
+ return (1);
+}
+
+#ifdef BIND_4_COMPAT
+/*
+ * This module must export the following externally-visible symbols:
+ * ___putlong
+ * ___putshort
+ * __getlong
+ * __getshort
+ * Note that one _ comes from C and the others come from us.
+ */
+void __putlong(u_int32_t src, u_char *dst) { ns_put32(src, dst); }
+void __putshort(u_int16_t src, u_char *dst) { ns_put16(src, dst); }
+u_int32_t _getlong(const u_char *src) { return (ns_get32(src)); }
+u_int16_t _getshort(const u_char *src) { return (ns_get16(src)); }
+#endif /*BIND_4_COMPAT*/
diff --git a/StdLib/BsdSocketLib/res_config.h b/StdLib/BsdSocketLib/res_config.h new file mode 100644 index 0000000000..4f4afdff5c --- /dev/null +++ b/StdLib/BsdSocketLib/res_config.h @@ -0,0 +1,8 @@ +#define DEBUG 1 /* enable debugging code (needed for dig) */
+#define RESOLVSORT /* allow sorting of addresses in gethostbyname */
+#define RFC1535 /* comply with RFC1535 (STRONGLY reccomended by vixie)*/
+#undef USELOOPBACK /* res_init() bind to localhost */
+#undef SUNSECURITY /* verify gethostbyaddr() calls - WE DONT NEED IT */
+#define MULTI_PTRS_ARE_ALIASES 1 /* fold multiple PTR records into aliases */
+#define CHECK_SRVR_ADDR 1 /* confirm that the server requested sent the reply */
+#define BIND_UPDATE 1 /* update support */
diff --git a/StdLib/BsdSocketLib/res_data.c b/StdLib/BsdSocketLib/res_data.c new file mode 100644 index 0000000000..8831653e4d --- /dev/null +++ b/StdLib/BsdSocketLib/res_data.c @@ -0,0 +1,83 @@ +/*
+ * Copyright (c) 1995,1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] = "$Id: res_data.c,v 1.1.1.1 2003/11/19 01:51:35 kyu3 Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <ctype.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "res_config.h"
+
+const char *_res_opcodes[] = {
+ "QUERY",
+ "IQUERY",
+ "CQUERYM",
+ "CQUERYU", /* experimental */
+ "NOTIFY", /* experimental */
+ "UPDATE",
+ "6",
+ "7",
+ "8",
+ "9",
+ "10",
+ "11",
+ "12",
+ "13",
+ "ZONEINIT",
+ "ZONEREF",
+};
+
+const char *_res_resultcodes[] = {
+ "NOERROR",
+ "FORMERR",
+ "SERVFAIL",
+ "NXDOMAIN",
+ "NOTIMP",
+ "REFUSED",
+ "YXDOMAIN",
+ "YXRRSET",
+ "NXRRSET",
+ "NOTAUTH",
+ "ZONEERR",
+ "11",
+ "12",
+ "13",
+ "14",
+ "NOCHANGE",
+};
+
+#ifdef BIND_UPDATE
+const char *_res_sectioncodes[] = {
+ "ZONE",
+ "PREREQUISITES",
+ "UPDATE",
+ "ADDITIONAL",
+};
+#endif
diff --git a/StdLib/BsdSocketLib/res_debug.c b/StdLib/BsdSocketLib/res_debug.c new file mode 100644 index 0000000000..5cdc674572 --- /dev/null +++ b/StdLib/BsdSocketLib/res_debug.c @@ -0,0 +1,988 @@ +/*
+ * Copyright (c) 1985
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by the University of
+ * California, Berkeley, Intel Corporation, and its contributors.
+ *
+ * 4. Neither the name of University, Intel Corporation, or their respective
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS,
+ * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software. No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+/*
+ * Portions Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$Id: res_debug.c,v 1.1.1.1 2003/11/19 01:51:36 kyu3 Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <math.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#define SPRINTF(x) sprintf x
+
+extern const char *_res_opcodes[];
+extern const char *_res_resultcodes[];
+extern const char *_res_sectioncodes[];
+
+/*
+ * Print the current options.
+ */
+void
+fp_resstat(struct __res_state *statp, FILE *file) {
+ u_long mask;
+
+ fprintf(file, ";; res options:");
+ if (!statp)
+ statp = &_res;
+ for (mask = 1; mask != 0; mask <<= 1)
+ if (statp->options & mask)
+ fprintf(file, " %s", p_option(mask));
+ putc('\n', file);
+}
+
+static void
+do_section(ns_msg *handle, ns_sect section, int pflag, FILE *file) {
+ int n, sflag, rrnum;
+ ns_opcode opcode;
+ ns_rr rr;
+
+ /*
+ * Print answer records.
+ */
+ sflag = (int)(_res.pfcode & pflag);
+ if (_res.pfcode && !sflag)
+ return;
+
+ opcode = ns_msg_getflag(*handle, ns_f_opcode);
+ rrnum = 0;
+ for (;;) {
+ if (ns_parserr(handle, section, rrnum, &rr)) {
+ if (errno != ENODEV)
+ fprintf(file, ";; ns_parserr: %s\n",
+ strerror(errno));
+ else if (rrnum > 0 && sflag != 0 &&
+ (_res.pfcode & RES_PRF_HEAD1))
+ putc('\n', file);
+ return;
+ }
+ if (rrnum == 0 && sflag != 0 && (_res.pfcode & RES_PRF_HEAD1))
+ fprintf(file, ";; %s SECTION:\n",
+ p_section(section, opcode));
+ if (section == ns_s_qd)
+ fprintf(file, ";;\t%s, type = %s, class = %s\n",
+ ns_rr_name(rr),
+ p_type(ns_rr_type(rr)),
+ p_class(ns_rr_class(rr)));
+ else {
+ char *buf;
+ buf = (char*)malloc(2024);
+ if (buf) {
+ n = ns_sprintrr(handle, &rr, NULL, NULL,
+ buf, sizeof buf);
+ if (n < 0) {
+ fprintf(file, ";; ns_sprintrr: %s\n",
+ strerror(errno));
+ free(buf);
+ return;
+ }
+ fputs(buf, file);
+ fputc('\n', file);
+ free(buf);
+ }
+ }
+ rrnum++;
+ }
+}
+
+void
+p_query(const u_char *msg) {
+ fp_query(msg, stdout);
+}
+
+void
+fp_query(const u_char *msg, FILE *file) {
+ fp_nquery(msg, PACKETSZ, file);
+}
+
+/*
+ * Print the contents of a query.
+ * This is intended to be primarily a debugging routine.
+ */
+void
+fp_nquery(const u_char *msg, int len, FILE *file) {
+ ns_msg handle;
+ int qdcount, ancount, nscount, arcount;
+ u_int opcode, rcode, id;
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ return;
+
+ if (ns_initparse(msg, len, &handle) < 0) {
+ fprintf(file, ";; ns_initparse: %s\n", strerror(errno));
+ return;
+ }
+ opcode = ns_msg_getflag(handle, ns_f_opcode);
+ rcode = ns_msg_getflag(handle, ns_f_rcode);
+ id = ns_msg_id(handle);
+ qdcount = ns_msg_count(handle, ns_s_qd);
+ ancount = ns_msg_count(handle, ns_s_an);
+ nscount = ns_msg_count(handle, ns_s_ns);
+ arcount = ns_msg_count(handle, ns_s_ar);
+
+ /*
+ * Print header fields.
+ */
+ if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || rcode)
+ fprintf(file,
+ ";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n",
+ _res_opcodes[opcode], _res_resultcodes[rcode], id);
+ if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX))
+ putc(';', file);
+ if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {
+ fprintf(file, "; flags:");
+ if (ns_msg_getflag(handle, ns_f_qr))
+ fprintf(file, " qr");
+ if (ns_msg_getflag(handle, ns_f_aa))
+ fprintf(file, " aa");
+ if (ns_msg_getflag(handle, ns_f_tc))
+ fprintf(file, " tc");
+ if (ns_msg_getflag(handle, ns_f_rd))
+ fprintf(file, " rd");
+ if (ns_msg_getflag(handle, ns_f_ra))
+ fprintf(file, " ra");
+ if (ns_msg_getflag(handle, ns_f_z))
+ fprintf(file, " ??");
+ if (ns_msg_getflag(handle, ns_f_ad))
+ fprintf(file, " ad");
+ if (ns_msg_getflag(handle, ns_f_cd))
+ fprintf(file, " cd");
+ }
+ if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) {
+ fprintf(file, "; %s: %d",
+ p_section(ns_s_qd, (int)opcode), qdcount);
+ fprintf(file, ", %s: %d",
+ p_section(ns_s_an, (int)opcode), ancount);
+ fprintf(file, ", %s: %d",
+ p_section(ns_s_ns, (int)opcode), nscount);
+ fprintf(file, ", %s: %d",
+ p_section(ns_s_ar, (int)opcode), arcount);
+ }
+ if ((!_res.pfcode) || (_res.pfcode &
+ (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
+ putc('\n',file);
+ }
+ /*
+ * Print the various sections.
+ */
+ do_section(&handle, ns_s_qd, RES_PRF_QUES, file);
+ do_section(&handle, ns_s_an, RES_PRF_ANS, file);
+ do_section(&handle, ns_s_ns, RES_PRF_AUTH, file);
+ do_section(&handle, ns_s_ar, RES_PRF_ADD, file);
+ if (qdcount == 0 && ancount == 0 &&
+ nscount == 0 && arcount == 0)
+ putc('\n', file);
+}
+
+const u_char *
+p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) {
+ char name[MAXDNAME];
+ int n;
+
+ if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
+ return (NULL);
+ if (name[0] == '\0')
+ putc('.', file);
+ else
+ fputs(name, file);
+ return (cp + n);
+}
+
+const u_char *
+p_cdname(const u_char *cp, const u_char *msg, FILE *file) {
+ return (p_cdnname(cp, msg, PACKETSZ, file));
+}
+
+/* Return a fully-qualified domain name from a compressed name (with
+ length supplied). */
+
+const u_char *
+p_fqnname(
+ const u_char *cp,
+ const u_char *msg,
+ int msglen,
+ char *name,
+ int namelen
+ )
+{
+ int n, newlen;
+
+ if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
+ return (NULL);
+ newlen = (int)strlen(name);
+ if (newlen == 0 || name[newlen - 1] != '.') {
+ if (newlen + 1 >= namelen) /* Lack space for final dot */
+ return (NULL);
+ else
+ strcpy(name + newlen, ".");
+ }
+ return (cp + n);
+}
+
+/* XXX: the rest of these functions need to become length-limited, too. */
+
+const u_char *
+p_fqname(const u_char *cp, const u_char *msg, FILE *file) {
+ char name[MAXDNAME];
+ const u_char *n;
+
+ n = p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
+ if (n == NULL)
+ return (NULL);
+ fputs(name, file);
+ return (n);
+}
+
+/*
+ * Names of RR classes and qclasses. Classes and qclasses are the same, except
+ * that C_ANY is a qclass but not a class. (You can ask for records of class
+ * C_ANY, but you can't have any records of that class in the database.)
+ */
+const struct res_sym __p_class_syms[] = {
+ {C_IN, "IN"},
+ {C_CHAOS, "CHAOS"},
+ {C_HS, "HS"},
+ {C_HS, "HESIOD"},
+ {C_ANY, "ANY"},
+ {C_NONE, "NONE"},
+ {C_IN, (char *)0}
+};
+
+/*
+ * Names of message sections.
+ */
+const struct res_sym __p_default_section_syms[] = {
+ {ns_s_qd, "QUERY"},
+ {ns_s_an, "ANSWER"},
+ {ns_s_ns, "AUTHORITY"},
+ {ns_s_ar, "ADDITIONAL"},
+ {0, (char *)0}
+};
+
+const struct res_sym __p_update_section_syms[] = {
+ {S_ZONE, "ZONE"},
+ {S_PREREQ, "PREREQUISITE"},
+ {S_UPDATE, "UPDATE"},
+ {S_ADDT, "ADDITIONAL"},
+ {0, (char *)0}
+};
+
+/*
+ * Names of RR types and qtypes. Types and qtypes are the same, except
+ * that T_ANY is a qtype but not a type. (You can ask for records of type
+ * T_ANY, but you can't have any records of that type in the database.)
+ */
+const struct res_sym __p_type_syms[] = {
+ {T_A, "A", "address"},
+ {T_NS, "NS", "name server"},
+ {T_MD, "MD", "mail destination (deprecated)"},
+ {T_MF, "MF", "mail forwarder (deprecated)"},
+ {T_CNAME, "CNAME", "canonical name"},
+ {T_SOA, "SOA", "start of authority"},
+ {T_MB, "MB", "mailbox"},
+ {T_MG, "MG", "mail group member"},
+ {T_MR, "MR", "mail rename"},
+ {T_NULL, "NULL", "null"},
+ {T_WKS, "WKS", "well-known service (deprecated)"},
+ {T_PTR, "PTR", "domain name pointer"},
+ {T_HINFO, "HINFO", "host information"},
+ {T_MINFO, "MINFO", "mailbox information"},
+ {T_MX, "MX", "mail exchanger"},
+ {T_TXT, "TXT", "text"},
+ {T_RP, "RP", "responsible person"},
+ {T_AFSDB, "AFSDB", "DCE or AFS server"},
+ {T_X25, "X25", "X25 address"},
+ {T_ISDN, "ISDN", "ISDN address"},
+ {T_RT, "RT", "router"},
+ {T_NSAP, "NSAP", "nsap address"},
+ {T_NSAP_PTR, "NSAP_PTR", "domain name pointer"},
+ {T_SIG, "SIG", "signature"},
+ {T_KEY, "KEY", "key"},
+ {T_PX, "PX", "mapping information"},
+ {T_GPOS, "GPOS", "geographical position (withdrawn)"},
+ {T_AAAA, "AAAA", "IPv6 address"},
+ {T_LOC, "LOC", "location"},
+ {T_NXT, "NXT", "next valid name (unimplemented)"},
+ {T_EID, "EID", "endpoint identifier (unimplemented)"},
+ {T_NIMLOC, "NIMLOC", "NIMROD locator (unimplemented)"},
+ {T_SRV, "SRV", "server selection"},
+ {T_ATMA, "ATMA", "ATM address (unimplemented)"},
+ {T_IXFR, "IXFR", "incremental zone transfer"},
+ {T_AXFR, "AXFR", "zone transfer"},
+ {T_MAILB, "MAILB", "mailbox-related data (deprecated)"},
+ {T_MAILA, "MAILA", "mail agent (deprecated)"},
+ {T_NAPTR, "NAPTR", "URN Naming Authority"},
+ {T_ANY, "ANY", "\"any\""},
+ {0, NULL, NULL}
+};
+
+int
+sym_ston(const struct res_sym *syms, const char *name, int *success) {
+ for ((void)NULL; syms->name != 0; syms++) {
+ if (strcasecmp (name, syms->name) == 0) {
+ if (success)
+ *success = 1;
+ return (syms->number);
+ }
+ }
+ if (success)
+ *success = 0;
+ return (syms->number); /* The default value. */
+}
+
+const char *
+sym_ntos(const struct res_sym *syms, int number, int *success) {
+ static char unname[20];
+
+ for ((void)NULL; syms->name != 0; syms++) {
+ if (number == syms->number) {
+ if (success)
+ *success = 1;
+ return (syms->name);
+ }
+ }
+
+ sprintf(unname, "%d", number);
+ if (success)
+ *success = 0;
+ return (unname);
+}
+
+const char *
+sym_ntop(const struct res_sym *syms, int number, int *success) {
+ static char unname[20];
+
+ for ((void)NULL; syms->name != 0; syms++) {
+ if (number == syms->number) {
+ if (success)
+ *success = 1;
+ return (syms->humanname);
+ }
+ }
+ sprintf(unname, "%d", number);
+ if (success)
+ *success = 0;
+ return (unname);
+}
+
+/*
+ * Return a string for the type.
+ */
+const char *
+p_type(int type) {
+ return (sym_ntos(__p_type_syms, type, (int *)0));
+}
+
+/*
+ * Return a string for the type.
+ */
+const char *
+p_section(int section, int opcode) {
+ const struct res_sym *symbols;
+
+ switch (opcode) {
+ case ns_o_update:
+ symbols = __p_update_section_syms;
+ break;
+ default:
+ symbols = __p_default_section_syms;
+ break;
+ }
+ return (sym_ntos(symbols, section, (int *)0));
+}
+
+/*
+ * Return a mnemonic for class.
+ */
+const char *
+p_class(int class) {
+ return (sym_ntos(__p_class_syms, class, (int *)0));
+}
+
+/*
+ * Return a mnemonic for an option
+ */
+const char *
+p_option(u_long option) {
+ static char nbuf[40];
+
+ switch (option) {
+ case RES_INIT: return "init";
+ case RES_DEBUG: return "debug";
+ case RES_AAONLY: return "aaonly(unimpl)";
+ case RES_USEVC: return "usevc";
+ case RES_PRIMARY: return "primry(unimpl)";
+ case RES_IGNTC: return "igntc";
+ case RES_RECURSE: return "recurs";
+ case RES_DEFNAMES: return "defnam";
+ case RES_STAYOPEN: return "styopn";
+ case RES_DNSRCH: return "dnsrch";
+ case RES_INSECURE1: return "insecure1";
+ case RES_INSECURE2: return "insecure2";
+ default: sprintf(nbuf, "?0x%lx?", (u_long)option);
+ return (nbuf);
+ }
+}
+
+/*
+ * Return a mnemonic for a time to live.
+ */
+const char *
+p_time(u_int32_t value) {
+ static char nbuf[40];
+
+ if (ns_format_ttl(value, nbuf, sizeof nbuf) < 0)
+ sprintf(nbuf, "%u", value);
+ return (nbuf);
+}
+
+
+/*
+ * routines to convert between on-the-wire RR format and zone file format.
+ * Does not contain conversion to/from decimal degrees; divide or multiply
+ * by 60*60*1000 for that.
+ */
+
+static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
+ 1000000,10000000,100000000,1000000000};
+
+/* takes an XeY precision/size value, returns a string representation. */
+static const char *
+precsize_ntoa(
+ u_int8_t prec
+ )
+{
+ static char retbuf[sizeof "90000000.00"];
+ unsigned long val;
+ int mantissa, exponent;
+
+ mantissa = (int)((prec >> 4) & 0x0f) % 10;
+ exponent = (int)((prec >> 0) & 0x0f) % 10;
+
+ val = mantissa * poweroften[exponent];
+
+ (void) sprintf(retbuf, "%ld.%.2ld", val/100, val%100);
+ return (retbuf);
+}
+
+/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
+static u_int8_t
+precsize_aton(
+ char **strptr
+ )
+{
+ unsigned int mval = 0, cmval = 0;
+ u_int8_t retval = 0;
+ char *cp;
+ int exponent;
+ int mantissa;
+
+ cp = *strptr;
+
+ while (isdigit(*cp))
+ mval = mval * 10 + (*cp++ - '0');
+
+ if (*cp == '.') { /* centimeters */
+ cp++;
+ if (isdigit(*cp)) {
+ cmval = (*cp++ - '0') * 10;
+ if (isdigit(*cp)) {
+ cmval += (*cp++ - '0');
+ }
+ }
+ }
+ cmval = (mval * 100) + cmval;
+
+ for (exponent = 0; exponent < 9; exponent++)
+ if (cmval < poweroften[exponent+1])
+ break;
+
+ mantissa = cmval / poweroften[exponent];
+ if (mantissa > 9)
+ mantissa = 9;
+
+ retval = (u_int8_t)((mantissa << 4) | exponent);
+
+ *strptr = cp;
+
+ return (retval);
+}
+
+/* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
+static u_int32_t
+latlon2ul(
+ char **latlonstrptr,
+ int *which
+ )
+{
+ char *cp;
+ u_int32_t retval;
+ int deg = 0, min = 0, secs = 0, secsfrac = 0;
+
+ cp = *latlonstrptr;
+
+ while (isdigit(*cp))
+ deg = deg * 10 + (*cp++ - '0');
+
+ while (isspace(*cp))
+ cp++;
+
+ if (!(isdigit(*cp)))
+ goto fndhemi;
+
+ while (isdigit(*cp))
+ min = min * 10 + (*cp++ - '0');
+
+ while (isspace(*cp))
+ cp++;
+
+ if (!(isdigit(*cp)))
+ goto fndhemi;
+
+ while (isdigit(*cp))
+ secs = secs * 10 + (*cp++ - '0');
+
+ if (*cp == '.') { /* decimal seconds */
+ cp++;
+ if (isdigit(*cp)) {
+ secsfrac = (*cp++ - '0') * 100;
+ if (isdigit(*cp)) {
+ secsfrac += (*cp++ - '0') * 10;
+ if (isdigit(*cp)) {
+ secsfrac += (*cp++ - '0');
+ }
+ }
+ }
+ }
+
+ while (!isspace(*cp)) /* if any trailing garbage */
+ cp++;
+
+ while (isspace(*cp))
+ cp++;
+
+ fndhemi:
+ switch (*cp) {
+ case 'N': case 'n':
+ case 'E': case 'e':
+ retval = ((unsigned)1<<31)
+ + (((((deg * 60) + min) * 60) + secs) * 1000)
+ + secsfrac;
+ break;
+ case 'S': case 's':
+ case 'W': case 'w':
+ retval = ((unsigned)1<<31)
+ - (((((deg * 60) + min) * 60) + secs) * 1000)
+ - secsfrac;
+ break;
+ default:
+ retval = 0; /* invalid value -- indicates error */
+ break;
+ }
+
+ switch (*cp) {
+ case 'N': case 'n':
+ case 'S': case 's':
+ *which = 1; /* latitude */
+ break;
+ case 'E': case 'e':
+ case 'W': case 'w':
+ *which = 2; /* longitude */
+ break;
+ default:
+ *which = 0; /* error */
+ break;
+ }
+
+ cp++; /* skip the hemisphere */
+
+ while (!isspace(*cp)) /* if any trailing garbage */
+ cp++;
+
+ while (isspace(*cp)) /* move to next field */
+ cp++;
+
+ *latlonstrptr = cp;
+
+ return (retval);
+}
+
+/* converts a zone file representation in a string to an RDATA on-the-wire
+ * representation. */
+int
+loc_aton(
+ const char *ascii,
+ u_char *binary
+ )
+{
+ const char *cp, *maxcp;
+ u_char *bcp;
+
+ u_int32_t latit = 0, longit = 0, alt = 0;
+ u_int32_t lltemp1 = 0, lltemp2 = 0;
+ int altmeters = 0, altfrac = 0, altsign = 1;
+ u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
+ u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */
+ u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
+ int which1 = 0, which2 = 0;
+
+ cp = ascii;
+ maxcp = cp + strlen(ascii);
+
+ lltemp1 = latlon2ul((char **)&cp, &which1);
+
+ lltemp2 = latlon2ul((char **)&cp, &which2);
+
+ switch (which1 + which2) {
+ case 3: /* 1 + 2, the only valid combination */
+ if ((which1 == 1) && (which2 == 2)) { /* normal case */
+ latit = lltemp1;
+ longit = lltemp2;
+ } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
+ longit = lltemp1;
+ latit = lltemp2;
+ } else { /* some kind of brokenness */
+ return (0);
+ }
+ break;
+ default: /* we didn't get one of each */
+ return (0);
+ }
+
+ /* altitude */
+ if (*cp == '-') {
+ altsign = -1;
+ cp++;
+ }
+
+ if (*cp == '+')
+ cp++;
+
+ while (isdigit(*cp))
+ altmeters = altmeters * 10 + (*cp++ - '0');
+
+ if (*cp == '.') { /* decimal meters */
+ cp++;
+ if (isdigit(*cp)) {
+ altfrac = (*cp++ - '0') * 10;
+ if (isdigit(*cp)) {
+ altfrac += (*cp++ - '0');
+ }
+ }
+ }
+
+ alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
+
+ while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
+ cp++;
+
+ while (isspace(*cp) && (cp < maxcp))
+ cp++;
+
+ if (cp >= maxcp)
+ goto defaults;
+
+ siz = precsize_aton((char **)&cp);
+
+ while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
+ cp++;
+
+ while (isspace(*cp) && (cp < maxcp))
+ cp++;
+
+ if (cp >= maxcp)
+ goto defaults;
+
+ hp = precsize_aton((char **)&cp);
+
+ while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
+ cp++;
+
+ while (isspace(*cp) && (cp < maxcp))
+ cp++;
+
+ if (cp >= maxcp)
+ goto defaults;
+
+ vp = precsize_aton((char **)&cp);
+
+ defaults:
+
+ bcp = binary;
+ *bcp++ = (u_int8_t) 0; /* version byte */
+ *bcp++ = siz;
+ *bcp++ = hp;
+ *bcp++ = vp;
+ PUTLONG(latit,bcp);
+ PUTLONG(longit,bcp);
+ PUTLONG(alt,bcp);
+
+ return (16); /* size of RR in octets */
+}
+
+/* takes an on-the-wire LOC RR and formats it in a human readable format. */
+const char *
+loc_ntoa(
+ const u_char *binary,
+ char *ascii
+ )
+{
+ static char *error = "?";
+ const u_char *cp = binary;
+
+ int latdeg, latmin, latsec, latsecfrac;
+ int longdeg, longmin, longsec, longsecfrac;
+ char northsouth, eastwest;
+ int altmeters, altfrac, altsign;
+
+ const u_int32_t referencealt = 100000 * 100;
+
+ int32_t latval, longval, altval;
+ u_int32_t templ;
+ u_int8_t sizeval, hpval, vpval, versionval;
+
+ char *sizestr, *hpstr, *vpstr;
+
+ versionval = *cp++;
+
+ if (versionval) {
+ (void) sprintf(ascii, "; error: unknown LOC RR version");
+ return (ascii);
+ }
+
+ sizeval = *cp++;
+
+ hpval = *cp++;
+ vpval = *cp++;
+
+ GETLONG(templ, cp);
+ latval = (templ - ((unsigned)1<<31));
+
+ GETLONG(templ, cp);
+ longval = (templ - ((unsigned)1<<31));
+
+ GETLONG(templ, cp);
+ if (templ < referencealt) { /* below WGS 84 spheroid */
+ altval = referencealt - templ;
+ altsign = -1;
+ } else {
+ altval = templ - referencealt;
+ altsign = 1;
+ }
+
+ if (latval < 0) {
+ northsouth = 'S';
+ latval = -latval;
+ } else
+ northsouth = 'N';
+
+ latsecfrac = latval % 1000;
+ latval = latval / 1000;
+ latsec = latval % 60;
+ latval = latval / 60;
+ latmin = latval % 60;
+ latval = latval / 60;
+ latdeg = latval;
+
+ if (longval < 0) {
+ eastwest = 'W';
+ longval = -longval;
+ } else
+ eastwest = 'E';
+
+ longsecfrac = longval % 1000;
+ longval = longval / 1000;
+ longsec = longval % 60;
+ longval = longval / 60;
+ longmin = longval % 60;
+ longval = longval / 60;
+ longdeg = longval;
+
+ altfrac = altval % 100;
+ altmeters = (altval / 100) * altsign;
+
+ if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
+ sizestr = error;
+ if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
+ hpstr = error;
+ if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
+ vpstr = error;
+
+ sprintf(ascii,
+ "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
+ latdeg, latmin, latsec, latsecfrac, northsouth,
+ longdeg, longmin, longsec, longsecfrac, eastwest,
+ altmeters, altfrac, sizestr, hpstr, vpstr);
+
+ if (sizestr != error)
+ free(sizestr);
+ if (hpstr != error)
+ free(hpstr);
+ if (vpstr != error)
+ free(vpstr);
+
+ return (ascii);
+}
+
+
+/* Return the number of DNS hierarchy levels in the name. */
+int
+dn_count_labels(const char *name) {
+ int i, len, count;
+
+ len = (int)strlen(name);
+ for (i = 0, count = 0; i < len; i++) {
+ /* XXX need to check for \. or use named's nlabels(). */
+ if (name[i] == '.')
+ count++;
+ }
+
+ /* don't count initial wildcard */
+ if (name[0] == '*')
+ if (count)
+ count--;
+
+ /* don't count the null label for root. */
+ /* if terminating '.' not found, must adjust */
+ /* count to include last label */
+ if (len > 0 && name[len-1] != '.')
+ count++;
+ return (count);
+}
+
+
+/*
+ * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
+ * SIG records are required to be printed like this, by the Secure DNS RFC.
+ */
+char *
+p_secstodate (u_long secs) {
+ static char output[15]; /* YYYYMMDDHHMMSS and null */
+ time_t clock = (time_t)secs;
+ struct tm *time;
+
+ time = gmtime(&clock);
+ time->tm_year += 1900;
+ time->tm_mon += 1;
+ sprintf(output, "%04d%02d%02d%02d%02d%02d",
+ time->tm_year, time->tm_mon, time->tm_mday,
+ time->tm_hour, time->tm_min, time->tm_sec);
+ return (output);
+}
diff --git a/StdLib/BsdSocketLib/res_init.c b/StdLib/BsdSocketLib/res_init.c new file mode 100644 index 0000000000..613a76a6b3 --- /dev/null +++ b/StdLib/BsdSocketLib/res_init.c @@ -0,0 +1,514 @@ +/*
+ * Copyright (c) 1985, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by the University of
+ * California, Berkeley, Intel Corporation, and its contributors.
+ *
+ * 4. Neither the name of University, Intel Corporation, or their respective
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS,
+ * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
+static char orig_rcsid[] = "From: Id: res_init.c,v 8.7 1996/11/18 09:10:04 vixie Exp $";
+static char rcsid[] = "$Id: res_init.c,v 1.1.1.1 2003/11/19 01:51:37 kyu3 Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <ctype.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "res_config.h"
+
+static void res_setoptions __P((char *, char *));
+
+#ifdef RESOLVSORT
+static const char sort_mask[] = "/&";
+#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
+static u_int32_t net_mask __P((struct in_addr));
+#endif
+
+#if !defined(isascii) /* XXX - could be a function */
+# define isascii(c) (!(c & 0200))
+#endif
+
+/*
+ * Resolver state default settings.
+ */
+
+struct __res_state _res
+# if defined(__BIND_RES_TEXT)
+ = { RES_TIMEOUT, } /* Motorola, et al. */
+# endif
+ ;
+
+
+/*
+ * Set up default settings. If the configuration file exist, the values
+ * there will have precedence. Otherwise, the server address is set to
+ * INADDR_ANY and the default domain name comes from the gethostname().
+ *
+ * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
+ * rather than INADDR_ANY ("0.0.0.0") as the default name server address
+ * since it was noted that INADDR_ANY actually meant ``the first interface
+ * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
+ * it had to be "up" in order for you to reach your own name server. It
+ * was later decided that since the recommended practice is to always
+ * install local static routes through 127.0.0.1 for all your network
+ * interfaces, that we could solve this problem without a code change.
+ *
+ * The configuration file should always be used, since it is the only way
+ * to specify a default domain. If you are running a server on your local
+ * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
+ * in the configuration file.
+ *
+ * Return 0 if completes successfully, -1 on error
+ */
+int
+res_init()
+{
+ register FILE *fp;
+ register char *cp, **pp;
+ register int n;
+ char buf[MAXDNAME];
+ int nserv = 0; /* number of nameserver records read from file */
+ int haveenv = 0;
+ int havesearch = 0;
+#ifdef RESOLVSORT
+ int nsort = 0;
+ char *net;
+#endif
+#ifndef RFC1535
+ int dots;
+#endif
+
+ /*
+ * These three fields used to be statically initialized. This made
+ * it hard to use this code in a shared library. It is necessary,
+ * now that we're doing dynamic initialization here, that we preserve
+ * the old semantics: if an application modifies one of these three
+ * fields of _res before res_init() is called, res_init() will not
+ * alter them. Of course, if an application is setting them to
+ * _zero_ before calling res_init(), hoping to override what used
+ * to be the static default, we can't detect it and unexpected results
+ * will follow. Zero for any of these fields would make no sense,
+ * so one can safely assume that the applications were already getting
+ * unexpected results.
+ *
+ * _res.options is tricky since some apps were known to diddle the bits
+ * before res_init() was first called. We can't replicate that semantic
+ * with dynamic initialization (they may have turned bits off that are
+ * set in RES_DEFAULT). Our solution is to declare such applications
+ * "broken". They could fool us by setting RES_INIT but none do (yet).
+ */
+ if (!_res.retrans)
+ _res.retrans = RES_TIMEOUT;
+ if (!_res.retry)
+ _res.retry = 4;
+ if (!(_res.options & RES_INIT))
+ _res.options = RES_DEFAULT;
+
+ /*
+ * This one used to initialize implicitly to zero, so unless the app
+ * has set it to something in particular, we can randomize it now.
+ */
+ if (!_res.id)
+ _res.id = (u_short)res_randomid();
+
+#ifdef USELOOPBACK
+ _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
+#else
+ _res.nsaddr.sin_addr.s_addr = INADDR_ANY;
+#endif
+ _res.nsaddr.sin_family = AF_INET;
+ _res.nsaddr.sin_port = htons(NAMESERVER_PORT);
+ _res.nscount = 1;
+ _res.ndots = 1;
+ _res.pfcode = 0;
+
+ /* Allow user to override the local domain definition */
+#ifdef _ORG_FREEBSD_
+ if (issetugid() == 0 && (cp = getenv("LOCALDOMAIN")) != NULL)
+#else
+ if ((cp = getenv("LOCALDOMAIN")) != NULL)
+#endif
+ {
+ (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
+ _res.defdname[sizeof(_res.defdname) - 1] = '\0';
+ haveenv++;
+
+ /*
+ * Set search list to be blank-separated strings
+ * from rest of env value. Permits users of LOCALDOMAIN
+ * to still have a search list, and anyone to set the
+ * one that they want to use as an individual (even more
+ * important now that the rfc1535 stuff restricts searches)
+ */
+ cp = _res.defdname;
+ pp = _res.dnsrch;
+ *pp++ = cp;
+ for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
+ if (*cp == '\n') /* silly backwards compat */
+ break;
+ else if (*cp == ' ' || *cp == '\t') {
+ *cp = 0;
+ n = 1;
+ } else if (n) {
+ *pp++ = cp;
+ n = 0;
+ havesearch = 1;
+ }
+ }
+ /* null terminate last domain if there are excess */
+ while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
+ cp++;
+ *cp = '\0';
+ *pp++ = 0;
+ }
+
+#define MATCH(line, name) \
+ (!strncmp(line, name, sizeof(name) - 1) && \
+ (line[sizeof(name) - 1] == ' ' || \
+ line[sizeof(name) - 1] == '\t'))
+
+ if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
+ /* read the config file */
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ /* skip comments */
+ if (*buf == ';' || *buf == '#')
+ continue;
+ /* read default domain name */
+ if (MATCH(buf, "domain")) {
+ if (haveenv) /* skip if have from environ */
+ continue;
+ cp = buf + sizeof("domain") - 1;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if ((*cp == '\0') || (*cp == '\n'))
+ continue;
+ strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
+ _res.defdname[sizeof(_res.defdname) - 1] = '\0';
+ if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL)
+ *cp = '\0';
+ havesearch = 0;
+ continue;
+ }
+ /* set search list */
+ if (MATCH(buf, "search")) {
+ if (haveenv) /* skip if have from environ */
+ continue;
+ cp = buf + sizeof("search") - 1;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if ((*cp == '\0') || (*cp == '\n'))
+ continue;
+ strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
+ _res.defdname[sizeof(_res.defdname) - 1] = '\0';
+ if ((cp = strchr(_res.defdname, '\n')) != NULL)
+ *cp = '\0';
+ /*
+ * Set search list to be blank-separated strings
+ * on rest of line.
+ */
+ cp = _res.defdname;
+ pp = _res.dnsrch;
+ *pp++ = cp;
+ for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
+ if (*cp == ' ' || *cp == '\t') {
+ *cp = 0;
+ n = 1;
+ } else if (n) {
+ *pp++ = cp;
+ n = 0;
+ }
+ }
+ /* null terminate last domain if there are excess */
+ while (*cp != '\0' && *cp != ' ' && *cp != '\t')
+ cp++;
+ *cp = '\0';
+ *pp++ = 0;
+ havesearch = 1;
+ continue;
+ }
+ /* read nameservers to query */
+ if (MATCH(buf, "nameserver") && nserv < MAXNS) {
+ struct in_addr a;
+
+ cp = buf + sizeof("nameserver") - 1;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) {
+ _res.nsaddr_list[nserv].sin_addr = a;
+ _res.nsaddr_list[nserv].sin_family = AF_INET;
+ _res.nsaddr_list[nserv].sin_port =
+ htons(NAMESERVER_PORT);
+ nserv++;
+ }
+ continue;
+ }
+#ifdef RESOLVSORT
+ if (MATCH(buf, "sortlist")) {
+ struct in_addr a;
+
+ cp = buf + sizeof("sortlist") - 1;
+ while (nsort < MAXRESOLVSORT) {
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if (*cp == '\0' || *cp == '\n' || *cp == ';')
+ break;
+ net = cp;
+ while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
+ isascii(*cp) && !isspace(*cp))
+ cp++;
+ n = *cp;
+ *cp = 0;
+ if (inet_aton(net, &a)) {
+ _res.sort_list[nsort].addr = a;
+ if (ISSORTMASK(n)) {
+ *cp++ = (char)n;
+ net = cp;
+ while (*cp && *cp != ';' &&
+ isascii(*cp) && !isspace(*cp))
+ cp++;
+ n = *cp;
+ *cp = 0;
+ if (inet_aton(net, &a)) {
+ _res.sort_list[nsort].mask = a.s_addr;
+ } else {
+ _res.sort_list[nsort].mask =
+ net_mask(_res.sort_list[nsort].addr);
+ }
+ } else {
+ _res.sort_list[nsort].mask =
+ net_mask(_res.sort_list[nsort].addr);
+ }
+ nsort++;
+ }
+ *cp = (char)n;
+ }
+ continue;
+ }
+#endif
+ if (MATCH(buf, "options")) {
+ res_setoptions(buf + sizeof("options") - 1, "conf");
+ continue;
+ }
+ }
+ if (nserv > 1)
+ _res.nscount = nserv;
+#ifdef RESOLVSORT
+ _res.nsort = nsort;
+#endif
+ (void) fclose(fp);
+ }
+ if (_res.defdname[0] == 0 &&
+ gethostname(buf, sizeof(_res.defdname) - 1) == 0 &&
+ (cp = strchr(buf, '.')) != NULL)
+ strcpy(_res.defdname, cp + 1);
+
+ /* find components of local domain that might be searched */
+ if (havesearch == 0) {
+ pp = _res.dnsrch;
+ *pp++ = _res.defdname;
+ *pp = NULL;
+
+#ifndef RFC1535
+ dots = 0;
+ for (cp = _res.defdname; *cp; cp++)
+ dots += (*cp == '.');
+
+ cp = _res.defdname;
+ while (pp < _res.dnsrch + MAXDFLSRCH) {
+ if (dots < LOCALDOMAINPARTS)
+ break;
+ cp = strchr(cp, '.') + 1; /* we know there is one */
+ *pp++ = cp;
+ dots--;
+ }
+ *pp = NULL;
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG) {
+ printf(";; res_init()... default dnsrch list:\n");
+ for (pp = _res.dnsrch; *pp; pp++)
+ printf(";;\t%s\n", *pp);
+ printf(";;\t..END..\n");
+ }
+#endif
+#endif /* !RFC1535 */
+ }
+
+#ifdef _ORG_FREEBSD_
+ if (issetugid())
+#else
+ if (1)
+#endif
+ _res.options |= RES_NOALIASES;
+ else if ((cp = getenv("RES_OPTIONS")) != NULL)
+ res_setoptions(cp, "env");
+ _res.options |= RES_INIT;
+ if ( 0 == nserv ) {
+ return -1;
+ }
+ return (0);
+}
+
+static void
+res_setoptions(
+ char *options,
+ char *source
+ )
+{
+ char *cp = options;
+ int i;
+
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf(";; res_setoptions(\"%s\", \"%s\")...\n",
+ options, source);
+#endif
+ while (*cp) {
+ /* skip leading and inner runs of spaces */
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ /* search for and process individual options */
+ if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
+ i = atoi(cp + sizeof("ndots:") - 1);
+ if (i <= RES_MAXNDOTS)
+ _res.ndots = i;
+ else
+ _res.ndots = RES_MAXNDOTS;
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf(";;\tndots=%d\n", _res.ndots);
+#endif
+ } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
+#ifdef DEBUG
+ if (!(_res.options & RES_DEBUG)) {
+ printf(";; res_setoptions(\"%s\", \"%s\")..\n",
+ options, source);
+ _res.options |= RES_DEBUG;
+ }
+ printf(";;\tdebug\n");
+#endif
+ } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
+ _res.options |= RES_USE_INET6;
+ } else if (!strncmp(cp, "no_tld_query", sizeof("no_tld_query") - 1)) {
+ _res.options |= RES_NOTLDQUERY;
+ } else {
+ /* XXX - print a warning here? */
+ }
+ /* skip to next run of spaces */
+ while (*cp && *cp != ' ' && *cp != '\t')
+ cp++;
+ }
+}
+
+#ifdef RESOLVSORT
+/* XXX - should really support CIDR which means explicit masks always. */
+static u_int32_t
+net_mask(
+ struct in_addr in
+ )
+{
+ register u_int32_t i = ntohl(in.s_addr);
+
+ if (IN_CLASSA(i))
+ return (htonl(IN_CLASSA_NET));
+ else if (IN_CLASSB(i))
+ return (htonl(IN_CLASSB_NET));
+ return (htonl(IN_CLASSC_NET));
+}
+#endif
+
+u_int
+res_randomid()
+{
+ struct timeval now;
+
+ gettimeofday(&now, NULL);
+ return (0xffff & (now.tv_sec ^ now.tv_usec /* ^ getpid() */));
+}
diff --git a/StdLib/BsdSocketLib/res_mkquery.c b/StdLib/BsdSocketLib/res_mkquery.c new file mode 100644 index 0000000000..2559f227c5 --- /dev/null +++ b/StdLib/BsdSocketLib/res_mkquery.c @@ -0,0 +1,211 @@ +/*
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by the University of
+ * California, Berkeley, Intel Corporation, and its contributors.
+ *
+ * 4. Neither the name of University, Intel Corporation, or their respective
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS,
+ * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93";
+static char orig_rcsid[] = "From: Id: res_mkquery.c,v 8.9 1997/04/24 22:22:36 vixie Exp $";
+static char rcsid[] = "$Id: res_mkquery.c,v 1.1.1.1 2003/11/19 01:51:37 kyu3 Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "res_config.h"
+
+/*
+ * Form all types of queries.
+ * Returns the size of the result or -1.
+ */
+int
+res_mkquery(
+ int op, /* opcode of query */
+ const char *dname, /* domain name */
+ int class, /* class of query */
+ int type, /* type of query */
+ const u_char *data, /* resource record data */
+ int datalen, /* length of data */
+ const u_char *newrr_in, /* new rr for modify or append */
+ u_char *buf, /* buffer to put query */
+ int buflen /* size of buffer */
+ )
+{
+ register HEADER *hp;
+ register u_char *cp;
+ register int n;
+ u_char *dnptrs[20], **dpp, **lastdnptr;
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (-1);
+ }
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf(";; res_mkquery(%d, %s, %d, %d)\n",
+ op, dname, class, type);
+#endif
+ /*
+ * Initialize header fields.
+ */
+ if ((buf == NULL) || (buflen < HFIXEDSZ))
+ return (-1);
+ memset(buf, 0, HFIXEDSZ);
+ hp = (HEADER *) buf;
+ hp->id = htons(++_res.id);
+ hp->opcode = op;
+ hp->rd = (_res.options & RES_RECURSE) != 0;
+ hp->rcode = NOERROR;
+ cp = buf + HFIXEDSZ;
+ buflen -= HFIXEDSZ;
+ dpp = dnptrs;
+ *dpp++ = buf;
+ *dpp++ = NULL;
+ lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
+ /*
+ * perform opcode specific processing
+ */
+ switch (op) {
+ case QUERY: /*FALLTHROUGH*/
+ case NS_NOTIFY_OP:
+ if ((buflen -= QFIXEDSZ) < 0)
+ return (-1);
+ if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
+ return (-1);
+ cp += n;
+ buflen -= n;
+ __putshort((u_int16_t)type, cp);
+ cp += INT16SZ;
+ __putshort((u_int16_t)class, cp);
+ cp += INT16SZ;
+ hp->qdcount = htons(1);
+ if (op == QUERY || data == NULL)
+ break;
+ /*
+ * Make an additional record for completion domain.
+ */
+ buflen -= RRFIXEDSZ;
+ n = dn_comp((char *)data, cp, buflen, dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ buflen -= n;
+ __putshort(T_NULL, cp);
+ cp += INT16SZ;
+ __putshort((u_int16_t)class, cp);
+ cp += INT16SZ;
+ __putlong(0, cp);
+ cp += INT32SZ;
+ __putshort(0, cp);
+ cp += INT16SZ;
+ hp->arcount = htons(1);
+ break;
+
+ case IQUERY:
+ /*
+ * Initialize answer section
+ */
+ if (buflen < 1 + RRFIXEDSZ + datalen)
+ return (-1);
+ *cp++ = '\0'; /* no domain name */
+ __putshort((u_int16_t)type, cp);
+ cp += INT16SZ;
+ __putshort((u_int16_t)class, cp);
+ cp += INT16SZ;
+ __putlong(0, cp);
+ cp += INT32SZ;
+ __putshort((u_int16_t)datalen, cp);
+ cp += INT16SZ;
+ if (datalen) {
+ memcpy(cp, data, datalen);
+ cp += datalen;
+ }
+ hp->ancount = htons(1);
+ break;
+
+ default:
+ return (-1);
+ }
+ return ((int)(cp - buf));
+}
diff --git a/StdLib/BsdSocketLib/res_mkupdate.c b/StdLib/BsdSocketLib/res_mkupdate.c new file mode 100644 index 0000000000..b27c2e460b --- /dev/null +++ b/StdLib/BsdSocketLib/res_mkupdate.c @@ -0,0 +1,454 @@ +/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by Intel Corporation and
+ * its contributors.
+ *
+ * 4. Neither the name of Intel Corporation or its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Based on the Dynamic DNS reference implementation by Viraj Bais
+ * <viraj_bais@ccm.fm.intel.com>
+ */
+
+#if !defined(lint) && !defined(SABER)
+static char rcsid[] = "$Id: res_mkupdate.c,v 1.1.1.1 2003/11/19 01:51:38 kyu3 Exp $";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include "res_config.h"
+
+static int getnum_str(u_char **, u_char *);
+static int getword_str(char *, int, u_char **, u_char *);
+
+#define ShrinkBuffer(x) if ((buflen -= x) < 0) return (-2);
+
+/*
+ * Form update packets.
+ * Returns the size of the resulting packet if no error
+ * On error,
+ * returns -1 if error in reading a word/number in rdata
+ * portion for update packets
+ * -2 if length of buffer passed is insufficient
+ * -3 if zone section is not the first section in
+ * the linked list, or section order has a problem
+ * -4 on a number overflow
+ * -5 unknown operation or no records
+ */
+int
+res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) {
+ ns_updrec *rrecp_start = rrecp_in;
+ HEADER *hp;
+ u_char *cp, *sp1, *sp2, *startp, *endp;
+ int n, i, soanum, multiline;
+ ns_updrec *rrecp;
+ struct in_addr ina;
+ char buf2[MAXDNAME];
+ int section, numrrs = 0, counts[ns_s_max];
+ u_int16_t rtype, rclass;
+ u_int32_t n1, rttl;
+ u_char *dnptrs[20], **dpp, **lastdnptr;
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (-1);
+ }
+
+ /*
+ * Initialize header fields.
+ */
+ if ((buf == NULL) || (buflen < HFIXEDSZ))
+ return (-1);
+ memset(buf, 0, HFIXEDSZ);
+ hp = (HEADER *) buf;
+ hp->id = htons(++_res.id);
+ hp->opcode = ns_o_update;
+ hp->rcode = NOERROR;
+ sp1 = buf + 2*INT16SZ; /* save pointer to zocount */
+ cp = buf + HFIXEDSZ;
+ buflen -= HFIXEDSZ;
+ dpp = dnptrs;
+ *dpp++ = buf;
+ *dpp++ = NULL;
+ lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
+
+ if (rrecp_start == NULL)
+ return (-5);
+ else if (rrecp_start->r_section != S_ZONE)
+ return (-3);
+
+ memset(counts, 0, sizeof counts);
+ for (rrecp = rrecp_start; rrecp; rrecp = rrecp->r_grpnext) {
+ numrrs++;
+ section = rrecp->r_section;
+ if (section < 0 || section >= ns_s_max)
+ return (-1);
+ counts[section]++;
+ for (i = section + 1; i < ns_s_max; i++)
+ if (counts[i])
+ return (-3);
+ rtype = rrecp->r_type;
+ rclass = rrecp->r_class;
+ rttl = rrecp->r_ttl;
+ /* overload class and type */
+ if (section == S_PREREQ) {
+ rttl = 0;
+ switch (rrecp->r_opcode) {
+ case YXDOMAIN:
+ rclass = C_ANY;
+ rtype = T_ANY;
+ rrecp->r_size = 0;
+ break;
+ case NXDOMAIN:
+ rclass = C_NONE;
+ rtype = T_ANY;
+ rrecp->r_size = 0;
+ break;
+ case NXRRSET:
+ rclass = C_NONE;
+ rrecp->r_size = 0;
+ break;
+ case YXRRSET:
+ if (rrecp->r_size == 0)
+ rclass = C_ANY;
+ break;
+ default:
+ fprintf(stderr,
+ "res_mkupdate: incorrect opcode: %d\n",
+ rrecp->r_opcode);
+ fflush(stderr);
+ return (-1);
+ }
+ } else if (section == S_UPDATE) {
+ switch (rrecp->r_opcode) {
+ case DELETE:
+ rclass = rrecp->r_size == 0 ? C_ANY : C_NONE;
+ break;
+ case ADD:
+ break;
+ default:
+ fprintf(stderr,
+ "res_mkupdate: incorrect opcode: %d\n",
+ rrecp->r_opcode);
+ fflush(stderr);
+ return (-1);
+ }
+ }
+
+ /*
+ * XXX appending default domain to owner name is omitted,
+ * fqdn must be provided
+ */
+ if ((n = dn_comp(rrecp->r_dname, cp, buflen, dnptrs,
+ lastdnptr)) < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n + 2*INT16SZ);
+ PUTSHORT(rtype, cp);
+ PUTSHORT(rclass, cp);
+ if (section == S_ZONE) {
+ if (numrrs != 1 || rrecp->r_type != T_SOA)
+ return (-3);
+ continue;
+ }
+ ShrinkBuffer(INT32SZ + INT16SZ);
+ PUTLONG(rttl, cp);
+ sp2 = cp; /* save pointer to length byte */
+ cp += INT16SZ;
+ if (rrecp->r_size == 0) {
+ if (section == S_UPDATE && rclass != C_ANY)
+ return (-1);
+ else {
+ PUTSHORT(0, sp2);
+ continue;
+ }
+ }
+ startp = rrecp->r_data;
+ endp = startp + rrecp->r_size - 1;
+ /* XXX this should be done centrally. */
+ switch (rrecp->r_type) {
+ case T_A:
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ if (!inet_aton(buf2, &ina))
+ return (-1);
+ n1 = ntohl(ina.s_addr);
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(n1, cp);
+ break;
+ case T_CNAME:
+ case T_MB:
+ case T_MG:
+ case T_MR:
+ case T_NS:
+ case T_PTR:
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ break;
+ case T_MINFO:
+ case T_SOA:
+ case T_RP:
+ for (i = 0; i < 2; i++) {
+ if (!getword_str(buf2, sizeof buf2, &startp,
+ endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen,
+ dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ }
+ if (rrecp->r_type == T_SOA) {
+ ShrinkBuffer(5 * INT32SZ);
+ while (isspace(*startp) || !*startp)
+ startp++;
+ if (*startp == '(') {
+ multiline = 1;
+ startp++;
+ } else
+ multiline = 0;
+ /* serial, refresh, retry, expire, minimum */
+ for (i = 0; i < 5; i++) {
+ soanum = getnum_str(&startp, endp);
+ if (soanum < 0)
+ return (-1);
+ PUTLONG(soanum, cp);
+ }
+ if (multiline) {
+ while (isspace(*startp) || !*startp)
+ startp++;
+ if (*startp != ')')
+ return (-1);
+ }
+ }
+ break;
+ case T_MX:
+ case T_AFSDB:
+ case T_RT:
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ PUTSHORT(n, cp);
+ ShrinkBuffer(INT16SZ);
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ break;
+ case T_PX:
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ PUTSHORT(n, cp);
+ ShrinkBuffer(INT16SZ);
+ for (i = 0; i < 2; i++) {
+ if (!getword_str(buf2, sizeof buf2, &startp,
+ endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, dnptrs,
+ lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ }
+ break;
+ case T_WKS:
+ case T_HINFO:
+ case T_TXT:
+ case T_X25:
+ case T_ISDN:
+ case T_NSAP:
+ case T_LOC:
+ /* XXX - more fine tuning needed here */
+ ShrinkBuffer(rrecp->r_size);
+ memcpy(cp, rrecp->r_data, rrecp->r_size);
+ cp += rrecp->r_size;
+ break;
+ default:
+ return (-1);
+ } /*switch*/
+ n = (u_int16_t)((cp - sp2) - INT16SZ);
+ PUTSHORT(n, sp2);
+ } /*for*/
+
+ hp->qdcount = htons(counts[0]);
+ hp->ancount = htons(counts[1]);
+ hp->nscount = htons(counts[2]);
+ hp->arcount = htons(counts[3]);
+ return ((int)(cp - buf));
+}
+
+/*
+ * Get a whitespace delimited word from a string (not file)
+ * into buf. modify the start pointer to point after the
+ * word in the string.
+ */
+static int
+getword_str(char *buf, int size, u_char **startpp, u_char *endp) {
+ char *cp;
+ int c;
+
+ for (cp = buf; *startpp <= endp; ) {
+ c = **startpp;
+ if (isspace(c) || c == '\0') {
+ if (cp != buf) /* trailing whitespace */
+ break;
+ else { /* leading whitespace */
+ (*startpp)++;
+ continue;
+ }
+ }
+ (*startpp)++;
+ if (cp >= buf+size-1)
+ break;
+ *cp++ = (u_char)c;
+ }
+ *cp = '\0';
+ return (cp != buf);
+}
+
+/*
+ * Get a whitespace delimited number from a string (not file) into buf
+ * update the start pointer to point after the number in the string.
+ */
+static int
+getnum_str(u_char **startpp, u_char *endp) {
+ int c;
+ int n;
+ int seendigit = 0;
+ int m = 0;
+
+ for (n = 0; *startpp <= endp; ) {
+ c = **startpp;
+ if (isspace(c) || c == '\0') {
+ if (seendigit) /* trailing whitespace */
+ break;
+ else { /* leading whitespace */
+ (*startpp)++;
+ continue;
+ }
+ }
+ if (c == ';') {
+ while ((*startpp <= endp) &&
+ ((c = **startpp) != '\n'))
+ (*startpp)++;
+ if (seendigit)
+ break;
+ continue;
+ }
+ if (!isdigit(c)) {
+ if (c == ')' && seendigit) {
+ (*startpp)--;
+ break;
+ }
+ return (-1);
+ }
+ (*startpp)++;
+ n = n * 10 + (c - '0');
+ seendigit = 1;
+ }
+ return (n + m);
+}
+
+/*
+ * Allocate a resource record buffer & save rr info.
+ */
+ns_updrec *
+res_mkupdrec(int section, const char *dname,
+ u_int class, u_int type, u_long ttl) {
+ ns_updrec *rrecp = (ns_updrec *)calloc(1, sizeof(ns_updrec));
+
+ if (!rrecp || !(rrecp->r_dname = strdup(dname)))
+ return (NULL);
+ rrecp->r_class = (u_int16_t)class;
+ rrecp->r_type = (u_int16_t)type;
+ rrecp->r_ttl = (u_int32_t)ttl;
+ rrecp->r_section = (u_int8_t)section;
+ return (rrecp);
+}
+
+/*
+ * Free a resource record buffer created by res_mkupdrec.
+ */
+void
+res_freeupdrec(ns_updrec *rrecp) {
+ /* Note: freeing r_dp is the caller's responsibility. */
+ if (rrecp->r_dname != NULL)
+ free(rrecp->r_dname);
+ free(rrecp);
+}
diff --git a/StdLib/BsdSocketLib/res_query.c b/StdLib/BsdSocketLib/res_query.c new file mode 100644 index 0000000000..791ff018f1 --- /dev/null +++ b/StdLib/BsdSocketLib/res_query.c @@ -0,0 +1,430 @@ +/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by the University of
+ * California, Berkeley, Intel Corporation, and its contributors.
+ *
+ * 4. Neither the name of University, Intel Corporation, or their respective
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS,
+ * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
+static char orig_rcsid = "From: Id: res_query.c,v 8.14 1997/06/09 17:47:05 halley Exp $";
+static char rcsid[] = "$Id: res_query.c,v 1.1.1.1 2003/11/19 01:51:38 kyu3 Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "res_config.h"
+
+#if PACKETSZ > 1024
+#define MAXPACKET PACKETSZ
+#else
+#define MAXPACKET 1024
+#endif
+
+/*
+ * Formulate a normal query, send, and await answer.
+ * Returned answer is placed in supplied buffer "answer".
+ * Perform preliminary check of answer, returning success only
+ * if no error is indicated and the answer count is nonzero.
+ * Return the size of the response on success, -1 on error.
+ * Error number is left in h_errno.
+ *
+ * Caller must parse answer and determine whether it answers the question.
+ */
+int
+res_query(
+ const char *name, /* domain name */
+ int class, /* class of query */
+ int type, /* type of query */
+ u_char *answer, /* buffer to put answer */
+ int anslen /* size of answer buffer */
+ )
+{
+ u_char buf[MAXPACKET];
+ HEADER *hp = (HEADER *) answer;
+ int n;
+
+ hp->rcode = NOERROR; /* default */
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (-1);
+ }
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf(";; res_query(%s, %d, %d)\n", name, class, type);
+#endif
+
+ n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
+ buf, sizeof(buf));
+ if (n <= 0) {
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf(";; res_query: mkquery failed\n");
+#endif
+ h_errno = NO_RECOVERY;
+ return (n);
+ }
+ n = res_send(buf, n, answer, anslen);
+ if (n < 0) {
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf(";; res_query: send error\n");
+#endif
+ h_errno = TRY_AGAIN;
+ return (n);
+ }
+
+ if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf(";; rcode = %d, ancount=%d\n", hp->rcode,
+ ntohs(hp->ancount));
+#endif
+ switch (hp->rcode) {
+ case NXDOMAIN:
+ h_errno = HOST_NOT_FOUND;
+ break;
+ case SERVFAIL:
+ h_errno = TRY_AGAIN;
+ break;
+ case NOERROR:
+ h_errno = NO_DATA;
+ break;
+ case FORMERR:
+ case NOTIMP:
+ case REFUSED:
+ default:
+ h_errno = NO_RECOVERY;
+ break;
+ }
+ return (-1);
+ }
+ return (n);
+}
+
+/*
+ * Formulate a normal query, send, and retrieve answer in supplied buffer.
+ * Return the size of the response on success, -1 on error.
+ * If enabled, implement search rules until answer or unrecoverable failure
+ * is detected. Error code, if any, is left in h_errno.
+ */
+int
+res_search(
+ const char *name, /* domain name */
+ int class, /* class of query */
+ int type, /* type of query */
+ u_char *answer, /* buffer to put answer */
+ int anslen /* size of answer */
+ )
+{
+ const char *cp, * const *domain;
+ HEADER *hp = (HEADER *) answer;
+ u_int dots;
+ int trailing_dot, ret, saved_herrno;
+ int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (-1);
+ }
+ errno = 0;
+ h_errno = HOST_NOT_FOUND; /* default, if we never query */
+ dots = 0;
+ for (cp = name; *cp; cp++)
+ dots += (*cp == '.');
+ trailing_dot = 0;
+ if (cp > name && *--cp == '.')
+ trailing_dot++;
+
+ /* If there aren't any dots, it could be a user-level alias */
+ if (!dots && (cp = hostalias(name)) != NULL)
+ return (res_query(cp, class, type, answer, anslen));
+
+ /*
+ * If there are dots in the name already, let's just give it a try
+ * 'as is'. The threshold can be set with the "ndots" option.
+ */
+ saved_herrno = -1;
+ if (dots >= _res.ndots) {
+ ret = res_querydomain(name, NULL, class, type, answer, anslen);
+ if (ret > 0)
+ return (ret);
+ saved_herrno = h_errno;
+ tried_as_is++;
+ }
+
+ /*
+ * We do at least one level of search if
+ * - there is no dot and RES_DEFNAME is set, or
+ * - there is at least one dot, there is no trailing dot,
+ * and RES_DNSRCH is set.
+ */
+ if ((!dots && (_res.options & RES_DEFNAMES)) ||
+ (dots && !trailing_dot && (_res.options & RES_DNSRCH))) {
+ int done = 0;
+
+ for (domain = (const char * const *)_res.dnsrch;
+ *domain && !done;
+ domain++) {
+
+ ret = res_querydomain(name, *domain, class, type,
+ answer, anslen);
+ if (ret > 0)
+ return (ret);
+
+ /*
+ * If no server present, give up.
+ * If name isn't found in this domain,
+ * keep trying higher domains in the search list
+ * (if that's enabled).
+ * On a NO_DATA error, keep trying, otherwise
+ * a wildcard entry of another type could keep us
+ * from finding this entry higher in the domain.
+ * If we get some other error (negative answer or
+ * server failure), then stop searching up,
+ * but try the input name below in case it's
+ * fully-qualified.
+ */
+ if (errno == ECONNREFUSED) {
+ h_errno = TRY_AGAIN;
+ return (-1);
+ }
+
+ switch (h_errno) {
+ case NO_DATA:
+ got_nodata++;
+ /* FALLTHROUGH */
+ case HOST_NOT_FOUND:
+ /* keep trying */
+ break;
+ case TRY_AGAIN:
+ if (hp->rcode == SERVFAIL) {
+ /* try next search element, if any */
+ got_servfail++;
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ /* anything else implies that we're done */
+ done++;
+ }
+
+ /* if we got here for some reason other than DNSRCH,
+ * we only wanted one iteration of the loop, so stop.
+ */
+ if (!(_res.options & RES_DNSRCH))
+ done++;
+ }
+ }
+
+ /*
+ * If we have not already tried the name "as is", do that now.
+ * note that we do this regardless of how many dots were in the
+ * name or whether it ends with a dot unless NOTLDQUERY is set.
+ */
+ if (!tried_as_is && (dots || !(_res.options & RES_NOTLDQUERY))) {
+ ret = res_querydomain(name, NULL, class, type, answer, anslen);
+ if (ret > 0)
+ return (ret);
+ }
+
+ /* if we got here, we didn't satisfy the search.
+ * if we did an initial full query, return that query's h_errno
+ * (note that we wouldn't be here if that query had succeeded).
+ * else if we ever got a nodata, send that back as the reason.
+ * else send back meaningless h_errno, that being the one from
+ * the last DNSRCH we did.
+ */
+ if (saved_herrno != -1)
+ h_errno = saved_herrno;
+ else if (got_nodata)
+ h_errno = NO_DATA;
+ else if (got_servfail)
+ h_errno = TRY_AGAIN;
+ return (-1);
+}
+
+/*
+ * Perform a call on res_query on the concatenation of name and domain,
+ * removing a trailing dot from name if domain is NULL.
+ */
+int
+res_querydomain(
+ const char *name,
+ const char *domain,
+ int class, /* class of query */
+ int type, /* type of query */
+ u_char *answer, /* buffer to put answer */
+ int anslen /* size of answer */
+ )
+{
+ char nbuf[MAXDNAME];
+ const char *longname = nbuf;
+ int n, d;
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (-1);
+ }
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf(";; res_querydomain(%s, %s, %d, %d)\n",
+ name, domain?domain:"<Nil>", class, type);
+#endif
+ if (domain == NULL) {
+ /*
+ * Check for trailing '.';
+ * copy without '.' if present.
+ */
+ n = (int)strlen(name);
+ if (n >= MAXDNAME) {
+ h_errno = NO_RECOVERY;
+ return (-1);
+ }
+ n--;
+ if (n >= 0 && name[n] == '.') {
+ strncpy(nbuf, name, n);
+ nbuf[n] = '\0';
+ } else
+ longname = name;
+ } else {
+ n = (int)strlen(name);
+ d = (int)strlen(domain);
+ if (n + d + 1 >= MAXDNAME) {
+ h_errno = NO_RECOVERY;
+ return (-1);
+ }
+ sprintf(nbuf, "%s.%s", name, domain);
+ }
+ return (res_query(longname, class, type, answer, anslen));
+}
+
+const char *
+hostalias(
+ const char *name
+ )
+{
+ register char *cp1, *cp2;
+ FILE *fp;
+ char *file;
+ char buf[BUFSIZ];
+ static char abuf[MAXDNAME];
+
+ if (_res.options & RES_NOALIASES)
+ return (NULL);
+#ifdef _ORG_FREEBSD_
+ if (issetugid())
+ return (NULL);
+#endif
+ file = getenv("HOSTALIASES");
+ if (file == NULL || (fp = fopen(file, "r")) == NULL)
+ return (NULL);
+ setbuf(fp, NULL);
+ buf[sizeof(buf) - 1] = '\0';
+ while (fgets(buf, sizeof(buf), fp)) {
+ for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1)
+ ;
+ if (!*cp1)
+ break;
+ *cp1 = '\0';
+ if (!strcasecmp(buf, name)) {
+ while (isspace(*++cp1))
+ ;
+ if (!*cp1)
+ break;
+ for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2)
+ ;
+ abuf[sizeof(abuf) - 1] = *cp2 = '\0';
+ strncpy(abuf, cp1, sizeof(abuf) - 1);
+ fclose(fp);
+ return (abuf);
+ }
+ }
+ fclose(fp);
+ return (NULL);
+}
diff --git a/StdLib/BsdSocketLib/res_send.c b/StdLib/BsdSocketLib/res_send.c new file mode 100644 index 0000000000..82addc9745 --- /dev/null +++ b/StdLib/BsdSocketLib/res_send.c @@ -0,0 +1,934 @@ +/*
+ * Copyright (c) 1985, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by the University of
+ * California, Berkeley, Intel Corporation, and its contributors.
+ *
+ * 4. Neither the name of University, Intel Corporation, or their respective
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS,
+ * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
+static char orig_rcsid[] = "From: Id: res_send.c,v 8.20 1998/04/06 23:27:51 halley Exp $";
+static char rcsid[] = "$Id: res_send.c,v 1.1.1.1 2003/11/19 01:51:39 kyu3 Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Send query to name server and wait for reply.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "res_config.h"
+
+#ifndef _ORG_FREEBSD_
+#define NOPOLL
+#endif
+
+#ifdef NOPOLL /* libc_r doesn't wrap poll yet() */
+static int use_poll = 0;
+#else
+#include <poll.h>
+static int use_poll = 1; /* adapt to poll() syscall availability */
+ /* 0 = not present, 1 = try it, 2 = exists */
+#endif
+
+static int s = -1; /* socket used for communications */
+static int connected = 0; /* is the socket connected */
+static int vc = 0; /* is the socket a virtual circuit? */
+static res_send_qhook Qhook = NULL;
+static res_send_rhook Rhook = NULL;
+
+
+#define CAN_RECONNECT 1
+
+#ifndef DEBUG
+# define Dprint(cond, args) /*empty*/
+# define DprintQ(cond, args, query, size) /*empty*/
+# define Aerror(file, string, error, address) /*empty*/
+# define Perror(file, string, error) /*empty*/
+#else
+# define Dprint(cond, args) if (cond) {fprintf args;} else {}
+# define DprintQ(cond, args, query, size) if (cond) {\
+ fprintf args;\
+ __fp_nquery(query, size, stdout);\
+ } else {}
+
+static void
+Aerror(
+ FILE *file,
+ char *string,
+ int error,
+ struct sockaddr_in address
+ )
+{
+ int save = errno;
+
+ if (_res.options & RES_DEBUG) {
+ fprintf(file, "res_send: %s ([%s].%u): %s\n",
+ string,
+ inet_ntoa(address.sin_addr),
+ ntohs(address.sin_port),
+ strerror(error));
+ }
+ errno = save;
+}
+
+
+static void
+Perror(
+ FILE *file,
+ char *string,
+ int error
+ )
+{
+ int save = errno;
+
+ if (_res.options & RES_DEBUG) {
+ fprintf(file, "res_send: %s: %s\n",
+ string, strerror(error));
+ }
+ errno = save;
+}
+#endif
+
+void
+res_send_setqhook(
+ res_send_qhook hook
+ )
+{
+
+ Qhook = hook;
+}
+
+void
+res_send_setrhook(
+ res_send_rhook hook
+ )
+{
+
+ Rhook = hook;
+}
+
+/* int
+ * res_isourserver(ina)
+ * looks up "ina" in _res.ns_addr_list[]
+ * returns:
+ * 0 : not found
+ * >0 : found
+ * author:
+ * paul vixie, 29may94
+ */
+int
+res_isourserver(
+ const struct sockaddr_in *inp
+ )
+{
+ struct sockaddr_in ina;
+ int ns, ret;
+
+ ina = *inp;
+ ret = 0;
+ for (ns = 0; ns < _res.nscount; ns++) {
+ const struct sockaddr_in *srv = &_res.nsaddr_list[ns];
+
+ if (srv->sin_family == ina.sin_family &&
+ srv->sin_port == ina.sin_port &&
+ (srv->sin_addr.s_addr == INADDR_ANY ||
+ srv->sin_addr.s_addr == ina.sin_addr.s_addr)) {
+ ret++;
+ break;
+ }
+ }
+ return (ret);
+}
+
+/* int
+ * res_nameinquery(name, type, class, buf, eom)
+ * look for (name,type,class) in the query section of packet (buf,eom)
+ * requires:
+ * buf + HFIXEDSZ <= eom
+ * returns:
+ * -1 : format error
+ * 0 : not found
+ * >0 : found
+ * author:
+ * paul vixie, 29may94
+ */
+int
+res_nameinquery(
+ const char *name,
+ int type,
+ int class,
+ const u_char *buf,
+ const u_char *eom
+ )
+{
+ const u_char *cp = buf + HFIXEDSZ;
+ int qdcount = ntohs(((HEADER*)buf)->qdcount);
+
+ while (qdcount-- > 0) {
+ char tname[MAXDNAME+1];
+ int n, ttype, tclass;
+
+ n = dn_expand(buf, eom, cp, tname, sizeof tname);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ if (cp + 2 * INT16SZ > eom)
+ return (-1);
+ ttype = ns_get16(cp); cp += INT16SZ;
+ tclass = ns_get16(cp); cp += INT16SZ;
+ if (ttype == type &&
+ tclass == class &&
+ strcasecmp(tname, name) == 0)
+ return (1);
+ }
+ return (0);
+}
+
+/* int
+ * res_queriesmatch(buf1, eom1, buf2, eom2)
+ * is there a 1:1 mapping of (name,type,class)
+ * in (buf1,eom1) and (buf2,eom2)?
+ * returns:
+ * -1 : format error
+ * 0 : not a 1:1 mapping
+ * >0 : is a 1:1 mapping
+ * author:
+ * paul vixie, 29may94
+ */
+int
+res_queriesmatch(
+ const u_char *buf1,
+ const u_char *eom1,
+ const u_char *buf2,
+ const u_char *eom2
+ )
+{
+ const u_char *cp = buf1 + HFIXEDSZ;
+ int qdcount = ntohs(((HEADER*)buf1)->qdcount);
+
+ if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
+ return (-1);
+
+ /*
+ * Only header section present in replies to
+ * dynamic update packets.
+ */
+ if ( (((HEADER *)buf1)->opcode == ns_o_update) &&
+ (((HEADER *)buf2)->opcode == ns_o_update) )
+ return (1);
+
+ if (qdcount != ntohs(((HEADER*)buf2)->qdcount))
+ return (0);
+ while (qdcount-- > 0) {
+ char tname[MAXDNAME+1];
+ int n, ttype, tclass;
+
+ n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ if (cp + 2 * INT16SZ > eom1)
+ return (-1);
+ ttype = ns_get16(cp); cp += INT16SZ;
+ tclass = ns_get16(cp); cp += INT16SZ;
+ if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
+ return (0);
+ }
+ return (1);
+}
+
+int
+res_send(
+ const u_char *buf,
+ int buflen,
+ u_char *ans,
+ int anssiz
+ )
+{
+ HEADER *hp = (HEADER *) buf;
+ HEADER *anhp = (HEADER *) ans;
+ int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns;
+ ssize_t n;
+ u_int32_t badns; /* XXX NSMAX can't exceed #/bits in this variable */
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ /* errno should have been set by res_init() in this case. */
+ return (-1);
+ }
+ if (anssiz < HFIXEDSZ) {
+ errno = EINVAL;
+ return (-1);
+ }
+ DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY),
+ (stdout, ";; res_send()\n"), buf, buflen);
+ v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
+ gotsomewhere = 0;
+ connreset = 0;
+ terrno = ETIMEDOUT;
+ badns = 0;
+
+ /*
+ * Send request, RETRY times, or until successful
+ */
+ for (try = 0; try < _res.retry; try++) {
+ for (ns = 0; ns < _res.nscount; ns++) {
+ struct sockaddr_in *nsap = &_res.nsaddr_list[ns];
+ same_ns:
+ if (badns & (1 << ns)) {
+ res_close();
+ goto next_ns;
+ }
+
+ if (Qhook) {
+ int done = 0, loops = 0;
+
+ do {
+ res_sendhookact act;
+
+ act = (*Qhook)(&nsap, &buf, &buflen,
+ ans, anssiz, &resplen);
+ switch (act) {
+ case res_goahead:
+ done = 1;
+ break;
+ case res_nextns:
+ res_close();
+ goto next_ns;
+ case res_done:
+ return (resplen);
+ case res_modified:
+ /* give the hook another try */
+ if (++loops < 42) /*doug adams*/
+ break;
+ /*FALLTHROUGH*/
+ case res_error:
+ /*FALLTHROUGH*/
+ default:
+ return (-1);
+ }
+ } while (!done);
+ }
+
+ Dprint(_res.options & RES_DEBUG,
+ (stdout, ";; Querying server (# %d) address = %s\n",
+ ns + 1, inet_ntoa(nsap->sin_addr)));
+
+ if (v_circuit) {
+ int truncated;
+ struct iovec iov[2];
+ u_short len;
+ u_char *cp;
+
+ /*
+ * Use virtual circuit;
+ * at most one attempt per server.
+ */
+ try = _res.retry;
+ truncated = 0;
+ if (s < 0 || !vc || hp->opcode == ns_o_update) {
+ if (s >= 0)
+ res_close();
+
+ s = socket(PF_INET, SOCK_STREAM, 0);
+ if (s < 0) {
+ terrno = errno;
+ Perror(stderr, "socket(vc)", errno);
+ return (-1);
+ }
+ errno = 0;
+ nsap->sin_len = sizeof ( *nsap );
+ if (connect(s, (struct sockaddr *)nsap,
+ sizeof *nsap) < 0) {
+ terrno = errno;
+ Aerror(stderr, "connect/vc",
+ errno, *nsap);
+ badns |= (1 << ns);
+ res_close();
+ goto next_ns;
+ }
+ vc = 1;
+ }
+ /*
+ * Send length & message
+ */
+ putshort((u_short)buflen, (u_char*)&len);
+ iov[0].iov_base = (caddr_t)&len;
+ iov[0].iov_len = INT16SZ;
+ iov[1].iov_base = (caddr_t)buf;
+ iov[1].iov_len = buflen;
+ if (writev(s, iov, 2) != (INT16SZ + buflen)) {
+ terrno = errno;
+ Perror(stderr, "write failed", errno);
+ badns |= (1 << ns);
+ res_close();
+ goto next_ns;
+ }
+ /*
+ * Receive length & response
+ */
+read_len:
+ cp = ans;
+ len = INT16SZ;
+ while ((n = read(s, (char *)cp, (int)len)) > 0) {
+ cp += n;
+ len = (u_short)( len - n );
+ if (len <= 0)
+ break;
+ }
+ if (n <= 0) {
+ terrno = errno;
+ Perror(stderr, "read failed", errno);
+ res_close();
+ /*
+ * A long running process might get its TCP
+ * connection reset if the remote server was
+ * restarted. Requery the server instead of
+ * trying a new one. When there is only one
+ * server, this means that a query might work
+ * instead of failing. We only allow one reset
+ * per query to prevent looping.
+ */
+ if (terrno == ECONNRESET && !connreset) {
+ connreset = 1;
+ res_close();
+ goto same_ns;
+ }
+ res_close();
+ goto next_ns;
+ }
+ resplen = ns_get16(ans);
+ if (resplen > anssiz) {
+ Dprint(_res.options & RES_DEBUG,
+ (stdout, ";; response truncated\n")
+ );
+ truncated = 1;
+ len = (ushort)anssiz;
+ } else
+ len = (ushort)resplen;
+ if (len < HFIXEDSZ) {
+ /*
+ * Undersized message.
+ */
+ Dprint(_res.options & RES_DEBUG,
+ (stdout, ";; undersized: %d\n", len));
+ terrno = EMSGSIZE;
+ badns |= (1 << ns);
+ res_close();
+ goto next_ns;
+ }
+ cp = ans;
+ while (len != 0 &&
+ (n = read(s, (char *)cp, (int)len)) > 0) {
+ cp += n;
+ len = (u_short)( len - n );
+ }
+ if (n <= 0) {
+ terrno = errno;
+ Perror(stderr, "read(vc)", errno);
+ res_close();
+ goto next_ns;
+ }
+ if (truncated) {
+ /*
+ * Flush rest of answer
+ * so connection stays in synch.
+ */
+ anhp->tc = 1;
+ len = (ushort)( resplen - anssiz );
+ while (len != 0) {
+ char junk[PACKETSZ];
+
+ n = (len > sizeof(junk)
+ ? sizeof(junk)
+ : len);
+ if ((n = read(s, junk, n)) > 0)
+ len = (u_short)( len - n );
+ else
+ break;
+ }
+ }
+ /*
+ * The calling applicating has bailed out of
+ * a previous call and failed to arrange to have
+ * the circuit closed or the server has got
+ * itself confused. Anyway drop the packet and
+ * wait for the correct one.
+ */
+ if (hp->id != anhp->id) {
+ DprintQ((_res.options & RES_DEBUG) ||
+ (_res.pfcode & RES_PRF_REPLY),
+ (stdout, ";; old answer (unexpected):\n"),
+ ans, (resplen>anssiz)?anssiz:resplen);
+ goto read_len;
+ }
+ } else {
+ /*
+ * Use datagrams.
+ */
+#ifndef NOPOLL
+ struct pollfd pfd;
+ int msec;
+#endif
+ struct timeval timeout;
+ fd_set dsmask, *dsmaskp;
+ int dsmasklen;
+ struct sockaddr_in from;
+ int fromlen;
+
+ if ((s < 0) || vc) {
+ if (vc)
+ res_close();
+ s = socket(PF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+#ifndef CAN_RECONNECT
+ bad_dg_sock:
+#endif
+ terrno = errno;
+ Perror(stderr, "socket(dg)", errno);
+ return (-1);
+ }
+ connected = 0;
+ }
+#ifndef CANNOT_CONNECT_DGRAM
+ /*
+ * On a 4.3BSD+ machine (client and server,
+ * actually), sending to a nameserver datagram
+ * port with no nameserver will cause an
+ * ICMP port unreachable message to be returned.
+ * If our datagram socket is "connected" to the
+ * server, we get an ECONNREFUSED error on the next
+ * socket operation, and select returns if the
+ * error message is received. We can thus detect
+ * the absence of a nameserver without timing out.
+ * If we have sent queries to at least two servers,
+ * however, we don't want to remain connected,
+ * as we wish to receive answers from the first
+ * server to respond.
+ */
+ if (_res.nscount == 1 || (try == 0 && ns == 0)) {
+ /*
+ * Connect only if we are sure we won't
+ * receive a response from another server.
+ */
+ if (!connected) {
+ nsap->sin_len = sizeof ( *nsap );
+ if (connect(s, (struct sockaddr *)nsap,
+ sizeof *nsap
+ ) < 0) {
+ Aerror(stderr,
+ "connect(dg)",
+ errno, *nsap);
+ badns |= (1 << ns);
+ res_close();
+ goto next_ns;
+ }
+ connected = 1;
+ }
+ if (send(s, (char*)buf, buflen, 0) != buflen) {
+ Perror(stderr, "send", errno);
+ badns |= (1 << ns);
+ res_close();
+ goto next_ns;
+ }
+ } else {
+ /*
+ * Disconnect if we want to listen
+ * for responses from more than one server.
+ */
+ if (connected) {
+#ifdef CAN_RECONNECT
+ struct sockaddr_in no_addr;
+
+ no_addr.sin_family = AF_INET;
+ no_addr.sin_addr.s_addr = INADDR_ANY;
+ no_addr.sin_port = 0;
+ (void) connect(s,
+ (struct sockaddr *)
+ &no_addr,
+ sizeof no_addr);
+#else
+ int s1 = socket(PF_INET, SOCK_DGRAM,0);
+ if (s1 < 0)
+ goto bad_dg_sock;
+ (void) dup2(s1, s);
+ (void) close(s1);
+ Dprint(_res.options & RES_DEBUG,
+ (stdout, ";; new DG socket\n"))
+#endif /* CAN_RECONNECT */
+ connected = 0;
+ errno = 0;
+ }
+#endif /* !CANNOT_CONNECT_DGRAM */
+ if (sendto(s, (char*)buf, buflen, 0,
+ (struct sockaddr *)nsap,
+ sizeof *nsap)
+ != buflen) {
+ Aerror(stderr, "sendto", errno, *nsap);
+ badns |= (1 << ns);
+ res_close();
+ goto next_ns;
+ }
+#ifndef CANNOT_CONNECT_DGRAM
+ }
+#endif /* !CANNOT_CONNECT_DGRAM */
+
+ /*
+ * Wait for reply
+ */
+#ifndef NOPOLL
+ othersyscall:
+ if (use_poll) {
+ msec = (_res.retrans << try) * 1000;
+ if (try > 0)
+ msec /= _res.nscount;
+ if (msec <= 0)
+ msec = 1000;
+ } else {
+#endif
+ timeout.tv_sec = (_res.retrans << try);
+ if (try > 0)
+ timeout.tv_sec /= _res.nscount;
+ if ((long) timeout.tv_sec <= 0)
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+#ifndef NOPOLL
+ }
+#endif
+ wait:
+ if (s < 0) {
+ Perror(stderr, "s out-of-bounds", EMFILE);
+ res_close();
+ goto next_ns;
+ }
+#ifndef NOPOLL
+ if (use_poll) {
+ struct sigaction sa, osa;
+ int sigsys_installed = 0;
+
+ pfd.fd = s;
+ pfd.events = POLLIN;
+ if (use_poll == 1) {
+ bzero(&sa, sizeof(sa));
+ sa.sa_handler = SIG_IGN;
+ if (sigaction(SIGSYS, &sa, &osa) >= 0)
+ sigsys_installed = 1;
+ }
+ n = poll(&pfd, 1, msec);
+ if (sigsys_installed == 1) {
+ int oerrno = errno;
+ sigaction(SIGSYS, &osa, NULL);
+ errno = oerrno;
+ }
+ /* XXX why does nosys() return EINVAL? */
+ if (n < 0 && (errno == ENOSYS ||
+ errno == EINVAL)) {
+ use_poll = 0;
+ goto othersyscall;
+ } else if (use_poll == 1)
+ use_poll = 2;
+ if (n < 0) {
+ if (errno == EINTR)
+ goto wait;
+ Perror(stderr, "poll", errno);
+ res_close();
+ goto next_ns;
+ }
+ } else {
+#endif
+ dsmasklen = howmany(s + 1, NFDBITS) *
+ sizeof(fd_mask);
+ if (dsmasklen > sizeof(fd_set)) {
+ dsmaskp = (fd_set *)malloc(dsmasklen);
+ if (dsmaskp == NULL) {
+ res_close();
+ goto next_ns;
+ }
+ } else
+ dsmaskp = &dsmask;
+ /* only zero what we need */
+ memset((char *)dsmaskp, 0, dsmasklen);
+ FD_SET(s, dsmaskp);
+ n = select(s + 1, dsmaskp, (fd_set *)NULL,
+ (fd_set *)NULL, &timeout);
+ if (dsmaskp != &dsmask)
+ free(dsmaskp);
+ if (n < 0) {
+ if (errno == EINTR)
+ goto wait;
+ Perror(stderr, "select", errno);
+ res_close();
+ goto next_ns;
+ }
+#ifndef NOPOLL
+ }
+#endif
+
+ if (n == 0) {
+ /*
+ * timeout
+ */
+ Dprint(_res.options & RES_DEBUG,
+ (stdout, ";; timeout\n"));
+ gotsomewhere = 1;
+ res_close();
+ goto next_ns;
+ }
+ errno = 0;
+ fromlen = sizeof(struct sockaddr_in);
+ resplen = (int)recvfrom(s, (char*)ans, anssiz, 0,
+ (struct sockaddr *)&from, &fromlen);
+ if (resplen <= 0) {
+ Perror(stderr, "recvfrom", errno);
+ res_close();
+ goto next_ns;
+ }
+ gotsomewhere = 1;
+ if (resplen < HFIXEDSZ) {
+ /*
+ * Undersized message.
+ */
+ Dprint(_res.options & RES_DEBUG,
+ (stdout, ";; undersized: %d\n",
+ resplen));
+ terrno = EMSGSIZE;
+ badns |= (1 << ns);
+ res_close();
+ goto next_ns;
+ }
+ if (hp->id != anhp->id) {
+ /*
+ * response from old query, ignore it.
+ * XXX - potential security hazard could
+ * be detected here.
+ */
+ DprintQ((_res.options & RES_DEBUG) ||
+ (_res.pfcode & RES_PRF_REPLY),
+ (stdout, ";; old answer:\n"),
+ ans, (resplen>anssiz)?anssiz:resplen);
+ goto wait;
+ }
+#ifdef CHECK_SRVR_ADDR
+ if (!(_res.options & RES_INSECURE1) &&
+ !res_isourserver(&from)) {
+ /*
+ * response from wrong server? ignore it.
+ * XXX - potential security hazard could
+ * be detected here.
+ */
+ DprintQ((_res.options & RES_DEBUG) ||
+ (_res.pfcode & RES_PRF_REPLY),
+ (stdout, ";; not our server:\n"),
+ ans, (resplen>anssiz)?anssiz:resplen);
+ goto wait;
+ }
+#endif
+ if (!(_res.options & RES_INSECURE2) &&
+ !res_queriesmatch(buf, buf + buflen,
+ ans, ans + anssiz)) {
+ /*
+ * response contains wrong query? ignore it.
+ * XXX - potential security hazard could
+ * be detected here.
+ */
+ DprintQ((_res.options & RES_DEBUG) ||
+ (_res.pfcode & RES_PRF_REPLY),
+ (stdout, ";; wrong query name:\n"),
+ ans, (resplen>anssiz)?anssiz:resplen);
+ goto wait;
+ }
+ if (anhp->rcode == SERVFAIL ||
+ anhp->rcode == NOTIMP ||
+ anhp->rcode == REFUSED) {
+ DprintQ(_res.options & RES_DEBUG,
+ (stdout, "server rejected query:\n"),
+ ans, (resplen>anssiz)?anssiz:resplen);
+ badns |= (1 << ns);
+ res_close();
+ /* don't retry if called from dig */
+ if (!_res.pfcode)
+ goto next_ns;
+ }
+ if (!(_res.options & RES_IGNTC) && anhp->tc) {
+ /*
+ * get rest of answer;
+ * use TCP with same server.
+ */
+ Dprint(_res.options & RES_DEBUG,
+ (stdout, ";; truncated answer\n"));
+ v_circuit = 1;
+ res_close();
+ goto same_ns;
+ }
+ } /*if vc/dg*/
+ Dprint((_res.options & RES_DEBUG) ||
+ ((_res.pfcode & RES_PRF_REPLY) &&
+ (_res.pfcode & RES_PRF_HEAD1)),
+ (stdout, ";; got answer:\n"));
+ DprintQ((_res.options & RES_DEBUG) ||
+ (_res.pfcode & RES_PRF_REPLY),
+ (stdout, ""),
+ ans, (resplen>anssiz)?anssiz:resplen);
+ /*
+ * If using virtual circuits, we assume that the first server
+ * is preferred over the rest (i.e. it is on the local
+ * machine) and only keep that one open.
+ * If we have temporarily opened a virtual circuit,
+ * or if we haven't been asked to keep a socket open,
+ * close the socket.
+ */
+ if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) ||
+ !(_res.options & RES_STAYOPEN)) {
+ res_close();
+ }
+ if (Rhook) {
+ int done = 0, loops = 0;
+
+ do {
+ res_sendhookact act;
+
+ act = (*Rhook)(nsap, buf, buflen,
+ ans, anssiz, &resplen);
+ switch (act) {
+ case res_goahead:
+ case res_done:
+ done = 1;
+ break;
+ case res_nextns:
+ res_close();
+ goto next_ns;
+ case res_modified:
+ /* give the hook another try */
+ if (++loops < 42) /*doug adams*/
+ break;
+ /*FALLTHROUGH*/
+ case res_error:
+ /*FALLTHROUGH*/
+ default:
+ return (-1);
+ }
+ } while (!done);
+
+ }
+ return (resplen);
+ next_ns: ;
+ } /*foreach ns*/
+ } /*foreach retry*/
+ res_close();
+ if (!v_circuit) {
+ if (!gotsomewhere)
+ errno = ECONNREFUSED; /* no nameservers found */
+ else
+ errno = ETIMEDOUT; /* no answer obtained */
+ } else
+ errno = terrno;
+ return (-1);
+}
+
+/*
+ * This routine is for closing the socket if a virtual circuit is used and
+ * the program wants to close it. This provides support for endhostent()
+ * which expects to close the socket.
+ *
+ * This routine is not expected to be user visible.
+ */
+void
+res_close()
+{
+ if (s >= 0) {
+ (void) close(s);
+ s = -1;
+ connected = 0;
+ vc = 0;
+ }
+}
diff --git a/StdLib/BsdSocketLib/res_update.c b/StdLib/BsdSocketLib/res_update.c new file mode 100644 index 0000000000..1ad8a8719e --- /dev/null +++ b/StdLib/BsdSocketLib/res_update.c @@ -0,0 +1,556 @@ +#if !defined(lint) && !defined(SABER)
+static char rcsid[] = "$Id: res_update.c,v 1.1.1.1 2003/11/19 01:51:39 kyu3 Exp $";
+#endif /* not lint */
+
+/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by Intel Corporation and
+ * its contributors.
+ *
+ * 4. Neither the name of Intel Corporation or its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Based on the Dynamic DNS reference implementation by Viraj Bais
+ * <viraj_bais@ccm.fm.intel.com>
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <errno.h>
+#include <limits.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * Separate a linked list of records into groups so that all records
+ * in a group will belong to a single zone on the nameserver.
+ * Create a dynamic update packet for each zone and send it to the
+ * nameservers for that zone, and await answer.
+ * Abort if error occurs in updating any zone.
+ * Return the number of zones updated on success, < 0 on error.
+ *
+ * On error, caller must deal with the unsynchronized zones
+ * eg. an A record might have been successfully added to the forward
+ * zone but the corresponding PTR record would be missing if error
+ * was encountered while updating the reverse zone.
+ */
+
+#define NSMAX 16
+
+struct ns1 {
+ char nsname[MAXDNAME];
+ struct in_addr nsaddr1;
+};
+
+struct zonegrp {
+ char z_origin[MAXDNAME];
+ int16_t z_class;
+ char z_soardata[MAXDNAME + 5 * INT32SZ];
+ struct ns1 z_ns[NSMAX];
+ int z_nscount;
+ ns_updrec * z_rr;
+ struct zonegrp *z_next;
+};
+
+
+int
+res_update(ns_updrec *rrecp_in) {
+ ns_updrec *rrecp, *tmprrecp;
+ u_char buf[PACKETSZ], answer[PACKETSZ], packet[2*PACKETSZ];
+ char name[MAXDNAME], zname[MAXDNAME], primary[MAXDNAME],
+ mailaddr[MAXDNAME];
+ u_char soardata[2*MAXCDNAME+5*INT32SZ];
+ char *dname, *svdname, *cp1, *target;
+ u_char *cp, *eom;
+ HEADER *hp = (HEADER *) answer;
+ struct zonegrp *zptr = NULL, *tmpzptr, *prevzptr, *zgrp_start = NULL;
+ int i, j, k = 0, n, ancount, nscount, arcount, rcode, rdatasize,
+ newgroup, done, myzone, seen_before, numzones = 0;
+ u_int16_t dlen, class, qclass, type, qtype;
+ u_int32_t ttl;
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (-1);
+ }
+
+ for (rrecp = rrecp_in; rrecp; rrecp = rrecp->r_next) {
+ dname = rrecp->r_dname;
+ n = (int)strlen(dname);
+ if (dname[n-1] == '.')
+ dname[n-1] = '\0';
+ qtype = T_SOA;
+ qclass = rrecp->r_class;
+ done = 0;
+ seen_before = 0;
+
+ while (!done && dname) {
+ if (qtype == T_SOA) {
+ for (tmpzptr = zgrp_start;
+ tmpzptr && !seen_before;
+ tmpzptr = tmpzptr->z_next) {
+ if (strcasecmp(dname,
+ tmpzptr->z_origin) == 0 &&
+ tmpzptr->z_class == qclass)
+ seen_before++;
+ for (tmprrecp = tmpzptr->z_rr;
+ tmprrecp && !seen_before;
+ tmprrecp = tmprrecp->r_grpnext)
+ if (strcasecmp(dname, tmprrecp->r_dname) == 0
+ && tmprrecp->r_class == qclass) {
+ seen_before++;
+ break;
+ }
+ if (seen_before) {
+ /*
+ * Append to the end of
+ * current group.
+ */
+ for (tmprrecp = tmpzptr->z_rr;
+ tmprrecp->r_grpnext;
+ tmprrecp = tmprrecp->r_grpnext)
+ (void)NULL;
+ tmprrecp->r_grpnext = rrecp;
+ rrecp->r_grpnext = NULL;
+ done = 1;
+ break;
+ }
+ }
+ } else if (qtype == T_A) {
+ for (tmpzptr = zgrp_start;
+ tmpzptr && !done;
+ tmpzptr = tmpzptr->z_next)
+ for (i = 0; i < tmpzptr->z_nscount; i++)
+ if (tmpzptr->z_class == qclass &&
+ strcasecmp(tmpzptr->z_ns[i].nsname,
+ dname) == 0 &&
+ tmpzptr->z_ns[i].nsaddr1.s_addr != 0) {
+ zptr->z_ns[k].nsaddr1.s_addr =
+ tmpzptr->z_ns[i].nsaddr1.s_addr;
+ done = 1;
+ break;
+ }
+ }
+ if (done)
+ break;
+ n = res_mkquery(QUERY, dname, qclass, qtype, NULL,
+ 0, NULL, buf, sizeof buf);
+ if (n <= 0) {
+ fprintf(stderr, "res_update: mkquery failed\n");
+ return (n);
+ }
+ n = res_send(buf, n, answer, sizeof answer);
+ if (n < 0) {
+ fprintf(stderr, "res_update: send error for %s\n",
+ rrecp->r_dname);
+ return (n);
+ }
+ if (n < HFIXEDSZ)
+ return (-1);
+ ancount = ntohs(hp->ancount);
+ nscount = ntohs(hp->nscount);
+ arcount = ntohs(hp->arcount);
+ rcode = hp->rcode;
+ cp = answer + HFIXEDSZ;
+ eom = answer + n;
+ /* skip the question section */
+ n = dn_skipname(cp, eom);
+ if (n < 0 || cp + n + 2 * INT16SZ > eom)
+ return (-1);
+ cp += n + 2 * INT16SZ;
+
+ if (qtype == T_SOA) {
+ if (ancount == 0 && nscount == 0 && arcount == 0) {
+ /*
+ * if (rcode == NOERROR) then the dname exists but
+ * has no soa record associated with it.
+ * if (rcode == NXDOMAIN) then the dname does not
+ * exist and the server is replying out of NCACHE.
+ * in either case, proceed with the next try
+ */
+ dname = strchr(dname, '.');
+ if (dname != NULL)
+ dname++;
+ continue;
+ } else if ((rcode == NOERROR || rcode == NXDOMAIN) &&
+ ancount == 0 &&
+ nscount == 1 && arcount == 0) {
+ /*
+ * name/data does not exist, soa record supplied in the
+ * authority section
+ */
+ /* authority section must contain the soa record */
+ if ((n = dn_expand(answer, eom, cp, zname,
+ sizeof zname)) < 0)
+ return (n);
+ cp += n;
+ if (cp + 2 * INT16SZ > eom)
+ return (-1);
+ GETSHORT(type, cp);
+ GETSHORT(class, cp);
+ if (type != T_SOA || class != qclass) {
+ fprintf(stderr, "unknown answer\n");
+ return (-1);
+ }
+ myzone = 0;
+ svdname = dname;
+ while (dname)
+ if (strcasecmp(dname, zname) == 0) {
+ myzone = 1;
+ break;
+ } else if ((dname = strchr(dname, '.')) != NULL)
+ dname++;
+ if (!myzone) {
+ dname = strchr(svdname, '.');
+ if (dname != NULL)
+ dname++;
+ continue;
+ }
+ nscount = 0;
+ /* fallthrough */
+ } else if (rcode == NOERROR && ancount == 1) {
+ /*
+ * found the zone name
+ * new servers will supply NS records for the zone
+ * in authority section and A records for those
+ * nameservers in the additional section
+ * older servers have to be explicitly queried for
+ * NS records for the zone
+ */
+ /* answer section must contain the soa record */
+ if ((n = dn_expand(answer, eom, cp, zname,
+ sizeof zname)) < 0)
+ return (n);
+ else
+ cp += n;
+ if (cp + 2 * INT16SZ > eom)
+ return (-1);
+ GETSHORT(type, cp);
+ GETSHORT(class, cp);
+ if (type == T_CNAME) {
+ dname = strchr(dname, '.');
+ if (dname != NULL)
+ dname++;
+ continue;
+ }
+ if (strcasecmp(dname, zname) != 0 ||
+ type != T_SOA ||
+ class != rrecp->r_class) {
+ fprintf(stderr, "unknown answer\n");
+ return (-1);
+ }
+ /* FALLTHROUGH */
+ } else {
+ fprintf(stderr,
+ "unknown response: ans=%d, auth=%d, add=%d, rcode=%d\n",
+ ancount, nscount, arcount, hp->rcode);
+ return (-1);
+ }
+ if (cp + INT32SZ + INT16SZ > eom)
+ return (-1);
+ /* continue processing the soa record */
+ GETLONG(ttl, cp);
+ GETSHORT(dlen, cp);
+ if (cp + dlen > eom)
+ return (-1);
+ newgroup = 1;
+ zptr = zgrp_start;
+ prevzptr = NULL;
+ while (zptr) {
+ if (strcasecmp(zname, zptr->z_origin) == 0 &&
+ type == T_SOA && class == qclass) {
+ newgroup = 0;
+ break;
+ }
+ prevzptr = zptr;
+ zptr = zptr->z_next;
+ }
+ if (!newgroup) {
+ for (tmprrecp = zptr->z_rr;
+ tmprrecp->r_grpnext;
+ tmprrecp = tmprrecp->r_grpnext)
+ ;
+ tmprrecp->r_grpnext = rrecp;
+ rrecp->r_grpnext = NULL;
+ done = 1;
+ cp += dlen;
+ break;
+ } else {
+ if ((n = dn_expand(answer, eom, cp, primary,
+ sizeof primary)) < 0)
+ return (n);
+ cp += n;
+ /*
+ * We don't have to bounds check here because the
+ * next use of 'cp' is in dn_expand().
+ */
+ cp1 = (char *)soardata;
+ strcpy(cp1, primary);
+ cp1 += strlen(cp1) + 1;
+ if ((n = dn_expand(answer, eom, cp, mailaddr,
+ sizeof mailaddr)) < 0)
+ return (n);
+ cp += n;
+ strcpy(cp1, mailaddr);
+ cp1 += strlen(cp1) + 1;
+ if (cp + 5*INT32SZ > eom)
+ return (-1);
+ memcpy(cp1, cp, 5*INT32SZ);
+ cp += 5*INT32SZ;
+ cp1 += 5*INT32SZ;
+ rdatasize = (int)((u_char *)cp1 - soardata);
+ zptr = calloc(1, sizeof(struct zonegrp));
+ if (zptr == NULL)
+ return (-1);
+ if (zgrp_start == NULL)
+ zgrp_start = zptr;
+ else
+ prevzptr->z_next = zptr;
+ zptr->z_rr = rrecp;
+ rrecp->r_grpnext = NULL;
+ strcpy(zptr->z_origin, zname);
+ zptr->z_class = class;
+ memcpy(zptr->z_soardata, soardata, rdatasize);
+ /* fallthrough to process NS and A records */
+ }
+ } else if (qtype == T_NS) {
+ if (rcode == NOERROR && ancount > 0) {
+ strcpy(zname, dname);
+ for (zptr = zgrp_start; zptr; zptr = zptr->z_next) {
+ if (strcasecmp(zname, zptr->z_origin) == 0)
+ break;
+ }
+ if (zptr == NULL)
+ /* should not happen */
+ return (-1);
+ if (nscount > 0) {
+ /*
+ * answer and authority sections contain
+ * the same information, skip answer section
+ */
+ for (j = 0; j < ancount; j++) {
+ n = dn_skipname(cp, eom);
+ if (n < 0)
+ return (-1);
+ n += 2*INT16SZ + INT32SZ;
+ if (cp + n + INT16SZ > eom)
+ return (-1);
+ cp += n;
+ GETSHORT(dlen, cp);
+ cp += dlen;
+ }
+ } else
+ nscount = ancount;
+ /* fallthrough to process NS and A records */
+ } else {
+ fprintf(stderr, "cannot determine nameservers for %s:\
+ans=%d, auth=%d, add=%d, rcode=%d\n",
+ dname, ancount, nscount, arcount, hp->rcode);
+ return (-1);
+ }
+ } else if (qtype == T_A) {
+ if (rcode == NOERROR && ancount > 0) {
+ arcount = ancount;
+ ancount = nscount = 0;
+ /* fallthrough to process A records */
+ } else {
+ fprintf(stderr, "cannot determine address for %s:\
+ans=%d, auth=%d, add=%d, rcode=%d\n",
+ dname, ancount, nscount, arcount, hp->rcode);
+ return (-1);
+ }
+ }
+ /* process NS records for the zone */
+ j = 0;
+ for (i = 0; i < nscount; i++) {
+ if ((n = dn_expand(answer, eom, cp, name,
+ sizeof name)) < 0)
+ return (n);
+ cp += n;
+ if (cp + 3 * INT16SZ + INT32SZ > eom)
+ return (-1);
+ GETSHORT(type, cp);
+ GETSHORT(class, cp);
+ GETLONG(ttl, cp);
+ GETSHORT(dlen, cp);
+ if (cp + dlen > eom)
+ return (-1);
+ if (strcasecmp(name, zname) == 0 &&
+ type == T_NS && class == qclass) {
+ if ((n = dn_expand(answer, eom, cp,
+ name, sizeof name)) < 0)
+ return (n);
+ target = zptr->z_ns[j++].nsname;
+ strcpy(target, name);
+ }
+ cp += dlen;
+ }
+ if (zptr->z_nscount == 0)
+ zptr->z_nscount = j;
+ /* get addresses for the nameservers */
+ for (i = 0; i < arcount; i++) {
+ if ((n = dn_expand(answer, eom, cp, name,
+ sizeof name)) < 0)
+ return (n);
+ cp += n;
+ if (cp + 3 * INT16SZ + INT32SZ > eom)
+ return (-1);
+ GETSHORT(type, cp);
+ GETSHORT(class, cp);
+ GETLONG(ttl, cp);
+ GETSHORT(dlen, cp);
+ if (cp + dlen > eom)
+ return (-1);
+ if (type == T_A && dlen == INT32SZ && class == qclass) {
+ for (j = 0; j < zptr->z_nscount; j++)
+ if (strcasecmp(name, zptr->z_ns[j].nsname) == 0) {
+ memcpy(&zptr->z_ns[j].nsaddr1.s_addr, cp,
+ INT32SZ);
+ break;
+ }
+ }
+ cp += dlen;
+ }
+ if (zptr->z_nscount == 0) {
+ dname = zname;
+ qtype = T_NS;
+ continue;
+ }
+ done = 1;
+ for (k = 0; k < zptr->z_nscount; k++)
+ if (zptr->z_ns[k].nsaddr1.s_addr == 0) {
+ done = 0;
+ dname = zptr->z_ns[k].nsname;
+ qtype = T_A;
+ }
+
+ } /* while */
+ }
+
+ _res.options |= RES_DEBUG;
+ for (zptr = zgrp_start; zptr; zptr = zptr->z_next) {
+
+ /* append zone section */
+ rrecp = res_mkupdrec(ns_s_zn, zptr->z_origin,
+ zptr->z_class, ns_t_soa, 0);
+ if (rrecp == NULL) {
+ fprintf(stderr, "saverrec error\n");
+ fflush(stderr);
+ return (-1);
+ }
+ rrecp->r_grpnext = zptr->z_rr;
+ zptr->z_rr = rrecp;
+
+ n = res_mkupdate(zptr->z_rr, packet, sizeof packet);
+ if (n < 0) {
+ fprintf(stderr, "res_mkupdate error\n");
+ fflush(stderr);
+ return (-1);
+ } else
+ fprintf(stdout, "res_mkupdate: packet size = %d\n", n);
+
+ /*
+ * Override the list of NS records from res_init() with
+ * the authoritative nameservers for the zone being updated.
+ * Sort primary to be the first in the list of nameservers.
+ */
+ for (i = 0; i < zptr->z_nscount; i++) {
+ if (strcasecmp(zptr->z_ns[i].nsname,
+ zptr->z_soardata) == 0) {
+ struct in_addr tmpaddr;
+
+ if (i != 0) {
+ strcpy(zptr->z_ns[i].nsname,
+ zptr->z_ns[0].nsname);
+ strcpy(zptr->z_ns[0].nsname,
+ zptr->z_soardata);
+ tmpaddr = zptr->z_ns[i].nsaddr1;
+ zptr->z_ns[i].nsaddr1 =
+ zptr->z_ns[0].nsaddr1;
+ zptr->z_ns[0].nsaddr1 = tmpaddr;
+ }
+ break;
+ }
+ }
+ for (i = 0; i < MAXNS; i++) {
+ _res.nsaddr_list[i].sin_addr = zptr->z_ns[i].nsaddr1;
+ _res.nsaddr_list[i].sin_family = AF_INET;
+ _res.nsaddr_list[i].sin_port = htons(NAMESERVER_PORT);
+ }
+ _res.nscount = (zptr->z_nscount < MAXNS) ?
+ zptr->z_nscount : MAXNS;
+ n = res_send(packet, n, answer, sizeof(answer));
+ if (n < 0) {
+ fprintf(stderr, "res_send: send error, n=%d\n", n);
+ break;
+ } else
+ numzones++;
+ }
+
+ /* free malloc'ed memory */
+ while(zgrp_start) {
+ zptr = zgrp_start;
+ zgrp_start = zgrp_start->z_next;
+ res_freeupdrec(zptr->z_rr); /* Zone section we allocated. */
+ free((char *)zptr);
+ }
+
+ return (numzones);
+}
diff --git a/StdLib/BsdSocketLib/send.c b/StdLib/BsdSocketLib/send.c new file mode 100644 index 0000000000..e0ec64367c --- /dev/null +++ b/StdLib/BsdSocketLib/send.c @@ -0,0 +1,97 @@ +/** @file
+ Implement the send API.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <SocketInternals.h>
+
+
+/**
+ Send data using a network connection.
+
+ The ::send routine queues data to the network for transmission.
+ The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html">POSIX</a>
+ documentation is available online.
+
+ @param [in] s Socket file descriptor returned from ::socket.
+
+ @param [in] buffer Address of a buffer containing the data to send.
+
+ @param [in] length Length of the buffer in bytes.
+
+ @param [in] flags Message control flags
+
+ @returns ::send returns the number of data bytes that were
+ sent and -1 when an error occurs. In the case of
+ an error, errno contains more details.
+
+ **/
+ssize_t
+send (
+ int s,
+ CONST void * buffer,
+ size_t length,
+ int flags
+ )
+{
+ ssize_t LengthInBytes;
+ CONST UINT8 * pData;
+ struct __filedes * pDescriptor;
+ EFI_SOCKET_PROTOCOL * pSocketProtocol;
+ EFI_STATUS Status;
+
+ //
+ // Assume failure
+ //
+ LengthInBytes = -1;
+
+ //
+ // Locate the context for this socket
+ //
+ pSocketProtocol = BslFdToSocketProtocol ( s,
+ &pDescriptor,
+ &errno );
+ if ( NULL != pSocketProtocol ) {
+ //
+ // Send the data using the socket
+ //
+ pData = buffer;
+ do {
+ errno = 0;
+ Status = pSocketProtocol->pfnSend ( pSocketProtocol,
+ flags,
+ length,
+ pData,
+ (size_t *)&LengthInBytes,
+ NULL,
+ 0,
+ &errno );
+ if ( EFI_ERROR ( Status )) {
+ LengthInBytes = -1;
+ break;
+ }
+
+ //
+ // Account for the data sent
+ //
+ pData += LengthInBytes;
+ length -= LengthInBytes;
+ // TODO: Add non-blocking check
+ } while (( 0 != length ) && ( EFI_NOT_READY == Status ));
+ }
+
+ //
+ // Return the number of data bytes sent, -1 for errors
+ //
+ return (INT32)LengthInBytes;
+}
diff --git a/StdLib/BsdSocketLib/sendto.c b/StdLib/BsdSocketLib/sendto.c new file mode 100644 index 0000000000..338eb36eb9 --- /dev/null +++ b/StdLib/BsdSocketLib/sendto.c @@ -0,0 +1,103 @@ +/** @file
+ Implement the sendto API.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <SocketInternals.h>
+
+
+/**
+ Send data using a network connection.
+
+ The ::send routine queues data to the network for transmission.
+ The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html">POSIX</a>
+ documentation is available online.
+
+ @param [in] s Socket file descriptor returned from ::socket.
+
+ @param [in] buffer Address of a buffer containing the data to send.
+
+ @param [in] length Length of the buffer in bytes.
+
+ @param [in] flags Message control flags
+
+ @param [in] to Remote system address
+
+ @param [in] tolen Length of remote system address structure
+
+ @returns ::send returns the number of data bytes that were
+ sent and -1 when an error occurs. In the case of
+ an error, errno contains more details.
+
+ **/
+ssize_t
+sendto (
+ int s,
+ const void * buffer,
+ size_t length,
+ int flags,
+ const struct sockaddr * to,
+ socklen_t tolen
+ )
+{
+ ssize_t LengthInBytes;
+ CONST UINT8 * pData;
+ struct __filedes * pDescriptor;
+ EFI_SOCKET_PROTOCOL * pSocketProtocol;
+ EFI_STATUS Status;
+
+ //
+ // Assume failure
+ //
+ LengthInBytes = -1;
+
+ //
+ // Locate the context for this socket
+ //
+ pSocketProtocol = BslFdToSocketProtocol ( s,
+ &pDescriptor,
+ &errno );
+ if ( NULL != pSocketProtocol ) {
+ //
+ // Send the data using the socket
+ //
+ pData = buffer;
+ do {
+ errno = 0;
+ Status = pSocketProtocol->pfnSend ( pSocketProtocol,
+ flags,
+ length,
+ pData,
+ (size_t *)&LengthInBytes,
+ to,
+ tolen,
+ &errno );
+ if ( EFI_ERROR ( Status )) {
+ LengthInBytes = -1;
+ break;
+ }
+
+ //
+ // Account for the data sent
+ //
+ pData += LengthInBytes;
+ length -= LengthInBytes;
+ // TODO: Add non-blocking check
+ } while (( 0 != length ) && ( EFI_NOT_READY == Status ));
+ }
+
+ //
+ // Return the number of data bytes sent, -1 for errors
+ //
+ return (INT32)LengthInBytes;
+}
diff --git a/StdLib/BsdSocketLib/sethostname.c b/StdLib/BsdSocketLib/sethostname.c new file mode 100644 index 0000000000..7863e8ce45 --- /dev/null +++ b/StdLib/BsdSocketLib/sethostname.c @@ -0,0 +1,117 @@ +/*
+ * Copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software must
+ * display the following acknowledgement:
+ *
+ * This product includes software developed by Intel Corporation and its
+ * contributors.
+ *
+ * 4. Neither the name of Intel Corporation or its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <Uefi.h>
+#include <unistd.h>
+#include <wchar.h>
+
+/*++
+
+Module Name:
+
+ sethostname.c
+
+Abstract:
+
+ Map FreeBSD sethostname call to EFI Interface
+
+
+Revision History
+
+--*/
+
+int
+sethostname(
+ const char * name,
+ size_t namelen
+ )
+/*++
+
+Routine Description:
+
+ Set the hostname for this system.
+
+Arguments:
+
+ name - Pointer to hostname.
+ namelen - Length of name
+
+Returns:
+
+ 0 on success, -1 if not set
+
+--*/
+{
+ int SetStatus;
+ char * pName;
+
+ //
+ // Allocate a new buffer for name since the input value
+ // does not need to be zero terminated
+ //
+ pName = malloc ( namelen + 1 );
+ if ( NULL == pName ) {
+ errno = ENOMEM;
+ SetStatus = -1;
+ }
+ else {
+ //
+ // Create a zero terminated string for name
+ //
+ memcpy ( pName, name, namelen );
+ pName [ namelen ] = 0;
+
+ //
+ // Set the environment variable
+ //
+ SetStatus = setenv ("HOSTNAME", pName, TRUE);
+
+ //
+ // Free the temporary buffer
+ //
+ free ( pName );
+ }
+
+ //
+ // Return the results
+ //
+ return SetStatus;
+}
diff --git a/StdLib/BsdSocketLib/setsockopt.c b/StdLib/BsdSocketLib/setsockopt.c new file mode 100644 index 0000000000..74c948c783 --- /dev/null +++ b/StdLib/BsdSocketLib/setsockopt.c @@ -0,0 +1,65 @@ +/** @file
+ Implement the setsockopt API.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <SocketInternals.h>
+
+
+/**
+ Set the socket options
+
+ @param [in] s Socket file descriptor returned from ::socket.
+ @param [in] level Option protocol level
+ @param [in] option_name Name of the option
+ @param [in] option_value Buffer containing the option value
+ @param [in] option_len Length of the value in bytes
+
+ @retval Zero (0) upon success
+ @retval Minus one (-1) upon failure, errno set with additional error information
+
+**/
+int
+setsockopt (
+ IN int s,
+ IN int level,
+ IN int option_name,
+ IN CONST void * option_value,
+ IN socklen_t option_len
+ )
+{
+ int OptionStatus;
+ EFI_SOCKET_PROTOCOL * pSocketProtocol;
+ EFI_STATUS Status;
+
+ //
+ // Locate the context for this socket
+ //
+ pSocketProtocol = BslFdToSocketProtocol ( s, NULL, &errno );
+ if ( NULL != pSocketProtocol ) {
+ //
+ // Set the socket option
+ //
+ Status = pSocketProtocol->pfnOptionSet ( pSocketProtocol,
+ level,
+ option_name,
+ option_value,
+ option_len,
+ &errno );
+ }
+
+ //
+ // Return the operation stauts
+ //
+ OptionStatus = ( 0 == errno ) ? 0 : -1;
+ return OptionStatus;
+}
diff --git a/StdLib/BsdSocketLib/shutdown.c b/StdLib/BsdSocketLib/shutdown.c new file mode 100644 index 0000000000..4c00feade7 --- /dev/null +++ b/StdLib/BsdSocketLib/shutdown.c @@ -0,0 +1,72 @@ +/** @file
+ Implement the shutdown API.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <SocketInternals.h>
+
+
+/**
+ Shutdown the socket receive and transmit operations
+
+ The ::shutdown routine stops socket receive and transmit operations.
+ The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html">POSIX</a>
+ documentation is available online.
+
+ @param [in] s Socket file descriptor returned from ::socket.
+
+ @param [in] how Which operations to shutdown
+
+ @returns ::shutdown returns the zero (0) if successful or -1 when an
+ error occurs. In the latter case, errno contains more details.
+
+ **/
+int
+shutdown (
+ int s,
+ int how
+ )
+{
+ int RetVal;
+ EFI_SOCKET_PROTOCOL * pSocketProtocol;
+ EFI_STATUS Status;
+
+ //
+ // Assume failure
+ //
+ RetVal = -1;
+
+ //
+ // Locate the context for this socket
+ //
+ pSocketProtocol = BslFdToSocketProtocol ( s, NULL, &errno );
+ if ( NULL != pSocketProtocol ) {
+ //
+ // Receive the data from the socket
+ //
+ Status = pSocketProtocol->pfnShutdown ( pSocketProtocol,
+ how,
+ &errno );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Success
+ //
+ RetVal = 0;
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ return RetVal;
+}
diff --git a/StdLib/BsdSocketLib/socket.c b/StdLib/BsdSocketLib/socket.c new file mode 100644 index 0000000000..3754a29eb0 --- /dev/null +++ b/StdLib/BsdSocketLib/socket.c @@ -0,0 +1,286 @@ +/** @file
+ Implement the socket API.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <SocketInternals.h>
+
+
+const struct fileops SocketOperations = {
+ BslSocketClose, // close
+ BslSocketRead, // read
+ BslSocketWrite, // write
+
+ //
+ // Not supported
+ //
+ fnullop_fcntl, // fcntl
+ BslSocketPoll, // poll
+ fnullop_flush, // flush
+
+ fbadop_stat, // stat
+ fbadop_ioctl, // ioctl
+ fbadop_delete, // delete
+ fbadop_rmdir, // rmdir
+ fbadop_mkdir, // mkdir
+ fbadop_rename, // rename
+
+ NULL // lseek
+};
+
+
+/**
+ Translate from the socket file descriptor to the socket protocol.
+
+ @param [in] s Socket file descriptor returned from ::socket.
+
+ @param [in] ppDescriptor Address to receive the descriptor structure
+ address for the file
+ @param [in] pErrno Address of the errno variable
+
+ @returns A pointer to the socket protocol structure or NULL if
+ an invalid file descriptor was passed in.
+
+ **/
+EFI_SOCKET_PROTOCOL *
+BslFdToSocketProtocol (
+ int s,
+ struct __filedes ** ppDescriptor,
+ int * pErrno
+ )
+{
+ struct __filedes * pDescriptor;
+ EFI_SOCKET_PROTOCOL * pSocketProtocol;
+
+ //
+ // Assume failure
+ //
+ pSocketProtocol = NULL;
+
+ //
+ // Validate the file descriptor
+ //
+ if ( !ValidateFD ( s, TRUE )) {
+ //
+ // Bad file descriptor
+ //
+ *pErrno = EBADF;
+ }
+ else {
+ //
+ // Get the descriptor for the file
+ //
+ pDescriptor = &gMD->fdarray [ s ];
+
+ //
+ // Validate that the descriptor is associated with sockets
+ //
+ pSocketProtocol = BslValidateSocketFd ( pDescriptor, pErrno );
+ if (( NULL != ppDescriptor ) && ( NULL != pSocketProtocol )) {
+ *ppDescriptor = pDescriptor;
+ }
+ }
+
+ //
+ // Return the socket protocol
+ //
+ return pSocketProtocol;
+}
+
+
+/**
+ Build a file descriptor for a socket.
+
+ @param [in] pSocketProtocol Socket protocol structure address
+
+ @param [in] pErrno Address of the errno variable
+
+ @returns The file descriptor for the socket or -1 if an error occurs.
+
+ **/
+int
+BslSocketProtocolToFd (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN int * pErrno
+ )
+{
+ int FileDescriptor;
+ struct __filedes * pDescriptor;
+
+ //
+ // Assume failure
+ //
+ FileDescriptor = -1;
+
+ //
+ // Locate a file descriptor
+ //
+ FileDescriptor = FindFreeFD ( VALID_CLOSED );
+ if( FileDescriptor < 0 ) {
+ //
+ // All available FDs are in use
+ //
+ errno = EMFILE;
+ }
+ else {
+ //
+ // Initialize the file descriptor
+ //
+ pDescriptor = &gMD->fdarray [ FileDescriptor ];
+ pDescriptor->f_offset = 0;
+ pDescriptor->f_flag = 0;
+ pDescriptor->f_iflags = DTYPE_SOCKET;
+ pDescriptor->MyFD = (UINT16)FileDescriptor;
+ pDescriptor->Oflags = 0;
+ pDescriptor->Omode = S_ACC_READ | S_ACC_WRITE;
+ pDescriptor->RefCount = 1;
+ FILE_SET_MATURE ( pDescriptor );
+
+ //
+ // Socket specific file descriptor initialization
+ //
+ pDescriptor->devdata = pSocketProtocol;
+ pDescriptor->f_ops = &SocketOperations;
+ }
+
+ //
+ // Return the socket's file descriptor
+ //
+ return FileDescriptor;
+}
+
+
+/**
+ Creates an endpoint for network communication.
+
+ The ::Socket routine initializes the communication endpoint by providing
+ the support for the socket library function ::socket. The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html">POSIX</a>
+ documentation for the socket routine is available online for reference.
+
+ @param [in] domain Select the family of protocols for the client or server
+ application.
+
+ @param [in] type Specifies how to make the network connection. The following values
+ are supported:
+ <ul>
+ <li>
+ SOCK_STREAM - Connect to TCP, provides a byte stream
+ that is manipluated by read, recv, send and write.
+ </li>
+ <li>
+ SOCK_SEQPACKET - Connect to TCP, provides sequenced packet stream
+ that is manipulated by read, recv, send and write.
+ </li>
+ <li>
+ SOCK_DGRAM - Connect to UDP, provides a datagram service that is
+ manipulated by recvfrom and sendto.
+ </li>
+ </ul>
+
+ @param [in] protocol Specifies the lower layer protocol to use. The following
+ values are supported:
+ <ul>
+ <li>IPPROTO_TCP</li> - This value must be combined with SOCK_STREAM.</li>
+ <li>IPPROTO_UDP</li> - This value must be combined with SOCK_DGRAM.</li>
+ </ul>
+
+ @returns This routine returns a file descriptor for the socket.
+
+ **/
+INT32
+socket (
+ IN INT32 domain,
+ IN INT32 type,
+ IN INT32 protocol
+ )
+{
+ INT32 FileDescriptor;
+ EFI_SOCKET_PROTOCOL * pSocketProtocol;
+ EFI_STATUS Status;
+
+ //
+ // Assume failure
+ //
+ FileDescriptor = -1;
+
+ //
+ // Locate the socket protocol
+ //
+ errno = EslServiceGetProtocol ( &pSocketProtocol );
+ if ( 0 == errno ) {
+ //
+ // Initialize the socket
+ //
+ Status = pSocketProtocol->pfnSocket ( pSocketProtocol,
+ domain,
+ type,
+ protocol,
+ &errno );
+ if ( !EFI_ERROR ( Status ))
+ {
+ //
+ // Build the file descriptor for the socket
+ //
+ FileDescriptor = BslSocketProtocolToFd ( pSocketProtocol,
+ &errno );
+ }
+ }
+
+ //
+ // Return the socket's file descriptor
+ //
+ return FileDescriptor;
+}
+
+
+/**
+ Validate the socket's file descriptor
+
+ @param [in] pDescriptor Descriptor for the file
+
+ @param [in] pErrno Address of the errno variable
+
+ @returns A pointer to the socket protocol structure or NULL if
+ an invalid file descriptor was passed in.
+
+ **/
+EFI_SOCKET_PROTOCOL *
+BslValidateSocketFd (
+ struct __filedes * pDescriptor,
+ int * pErrno
+ )
+{
+ EFI_SOCKET_PROTOCOL * pSocketProtocol;
+
+ //
+ // Assume failure
+ //
+ *pErrno = ENOTSOCK;
+ pSocketProtocol = NULL;
+
+ //
+ // Validate that the descriptor is associated with sockets
+ //
+ if ( DTYPE_SOCKET == ( pDescriptor->f_iflags & DTYPE_MASK )) {
+ //
+ // Locate the socket protocol
+ //
+ pSocketProtocol = pDescriptor->devdata;
+ *pErrno = 0;
+ }
+
+ //
+ // Return the socket protocol
+ //
+ return pSocketProtocol;
+}
diff --git a/StdLib/BsdSocketLib/write.c b/StdLib/BsdSocketLib/write.c new file mode 100644 index 0000000000..d04dda9c39 --- /dev/null +++ b/StdLib/BsdSocketLib/write.c @@ -0,0 +1,51 @@ +/** @file
+ Implement the write API.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <SocketInternals.h>
+
+
+/**
+ Write support routine for sockets
+
+ @param [in] pDescriptor Descriptor address for the file
+ @param [in] pOffset File offset
+ @param [in] LengthInBytes Number of bytes to write
+ @param [in] pBuffer Address of the data
+
+ @returns The number of bytes written or -1 if an error occurs.
+
+**/
+ssize_t
+BslSocketWrite (
+ struct __filedes *pDescriptor,
+ off_t * pOffset,
+ size_t LengthInBytes,
+ const void * pBuffer
+ )
+{
+ ssize_t BytesWritten;
+
+ //
+ // Send the data using the socket
+ //
+ BytesWritten = send ( pDescriptor->MyFD,
+ pBuffer,
+ LengthInBytes,
+ 0 );
+
+ //
+ // Return the number of bytes written
+ //
+ return BytesWritten;
+}
diff --git a/StdLib/Efi/etc/host.conf b/StdLib/Efi/etc/host.conf new file mode 100644 index 0000000000..1d765415b4 --- /dev/null +++ b/StdLib/Efi/etc/host.conf @@ -0,0 +1,4 @@ +# Order to perform name searches +dns, nis +hosts + diff --git a/StdLib/Efi/etc/hosts b/StdLib/Efi/etc/hosts new file mode 100644 index 0000000000..60cd861e4c --- /dev/null +++ b/StdLib/Efi/etc/hosts @@ -0,0 +1,9 @@ +# IPv4 hosts
+127.0.0.1 localhost
+
+# IPv6 hosts
+::1 localhost ip6-localhost ip6-loopback
+fe00::0 ip6-localnet
+ff00::0 ip6-mcastprefix
+ff02::1 ip6-allnodes
+ff02::2 ip6-allrouters
diff --git a/StdLib/Efi/etc/networks b/StdLib/Efi/etc/networks new file mode 100644 index 0000000000..b0101c4017 --- /dev/null +++ b/StdLib/Efi/etc/networks @@ -0,0 +1,3 @@ +# symbolic names for networks, see networks(5) for more information +link-local 169.254.0.0 +loopback 127.0.0.1 diff --git a/StdLib/Efi/etc/protocols b/StdLib/Efi/etc/protocols new file mode 100644 index 0000000000..10e277ce27 --- /dev/null +++ b/StdLib/Efi/etc/protocols @@ -0,0 +1,59 @@ +# Internet (IP) protocols +# +# Updated from http://www.iana.org/assignments/protocol-numbers and other +# sources. +# New protocols will be added on request if they have been officially +# assigned by IANA and are not historical. +# If you need a huge list of used numbers please install the nmap package. + +ip 0 IP # internet protocol, pseudo protocol number +#hopopt 0 HOPOPT # IPv6 Hop-by-Hop Option [RFC1883] +icmp 1 ICMP # internet control message protocol +igmp 2 IGMP # Internet Group Management +ggp 3 GGP # gateway-gateway protocol +ipencap 4 IP-ENCAP # IP encapsulated in IP (officially ``IP'') +st 5 ST # ST datagram mode +tcp 6 TCP # transmission control protocol +egp 8 EGP # exterior gateway protocol +igp 9 IGP # any private interior gateway (Cisco) +pup 12 PUP # PARC universal packet protocol +udp 17 UDP # user datagram protocol +hmp 20 HMP # host monitoring protocol +xns-idp 22 XNS-IDP # Xerox NS IDP +rdp 27 RDP # "reliable datagram" protocol +iso-tp4 29 ISO-TP4 # ISO Transport Protocol class 4 [RFC905] +xtp 36 XTP # Xpress Transfer Protocol +ddp 37 DDP # Datagram Delivery Protocol +idpr-cmtp 38 IDPR-CMTP # IDPR Control Message Transport +ipv6 41 IPv6 # Internet Protocol, version 6 +ipv6-route 43 IPv6-Route # Routing Header for IPv6 +ipv6-frag 44 IPv6-Frag # Fragment Header for IPv6 +idrp 45 IDRP # Inter-Domain Routing Protocol +rsvp 46 RSVP # Reservation Protocol +gre 47 GRE # General Routing Encapsulation +esp 50 IPSEC-ESP # Encap Security Payload [RFC2406] +ah 51 IPSEC-AH # Authentication Header [RFC2402] +skip 57 SKIP # SKIP +ipv6-icmp 58 IPv6-ICMP # ICMP for IPv6 +ipv6-nonxt 59 IPv6-NoNxt # No Next Header for IPv6 +ipv6-opts 60 IPv6-Opts # Destination Options for IPv6 +rspf 73 RSPF CPHB # Radio Shortest Path First (officially CPHB) +vmtp 81 VMTP # Versatile Message Transport +eigrp 88 EIGRP # Enhanced Interior Routing Protocol (Cisco) +ospf 89 OSPFIGP # Open Shortest Path First IGP +ax.25 93 AX.25 # AX.25 frames +ipip 94 IPIP # IP-within-IP Encapsulation Protocol +etherip 97 ETHERIP # Ethernet-within-IP Encapsulation [RFC3378] +encap 98 ENCAP # Yet Another IP encapsulation [RFC1241] +# 99 # any private encryption scheme +pim 103 PIM # Protocol Independent Multicast +ipcomp 108 IPCOMP # IP Payload Compression Protocol +vrrp 112 VRRP # Virtual Router Redundancy Protocol +l2tp 115 L2TP # Layer Two Tunneling Protocol [RFC2661] +isis 124 ISIS # IS-IS over IPv4 +sctp 132 SCTP # Stream Control Transmission Protocol +fc 133 FC # Fibre Channel +udplite 136 UDPLite # UDP-Lite +mpls-in-ip 137 MPLS-in-IP # MPLS-in-IP [RFC4023] +manet 138 # MANET Protocols +hip 139 HIP # Host Identity Protocol diff --git a/StdLib/Efi/etc/resolv.conf b/StdLib/Efi/etc/resolv.conf new file mode 100644 index 0000000000..3ac16ac230 --- /dev/null +++ b/StdLib/Efi/etc/resolv.conf @@ -0,0 +1,19 @@ +#
+# Domain name
+#
+domain intel.com
+
+;
+; Name Servers
+;
+nameserver 206.63.63.61
+nameserver 216.251.100.1
+
+; nameserver 10.248.2.1
+; nameserver 10.22.224.204
+
+#
+# Enable debugging
+#
+#options debug
+
diff --git a/StdLib/Efi/etc/services b/StdLib/Efi/etc/services new file mode 100644 index 0000000000..c95b1bf774 --- /dev/null +++ b/StdLib/Efi/etc/services @@ -0,0 +1,576 @@ +# Network services, Internet style +# +# Note that it is presently the policy of IANA to assign a single well-known +# port number for both TCP and UDP; hence, officially ports have two entries +# even if the protocol doesn't support UDP operations. +# +# Updated from http://www.iana.org/assignments/port-numbers and other +# sources like http://www.freebsd.org/cgi/cvsweb.cgi/src/etc/services . +# New ports will be added on request if they have been officially assigned +# by IANA and used in the real-world or are needed by a debian package. +# If you need a huge list of used numbers please install the nmap package. + +tcpmux 1/tcp # TCP port service multiplexer +echo 7/tcp +echo 7/udp +discard 9/tcp sink null +discard 9/udp sink null +systat 11/tcp users +daytime 13/tcp +daytime 13/udp +netstat 15/tcp +qotd 17/tcp quote +msp 18/tcp # message send protocol +msp 18/udp +chargen 19/tcp ttytst source +chargen 19/udp ttytst source +ftp-data 20/tcp +ftp 21/tcp +fsp 21/udp fspd +ssh 22/tcp # SSH Remote Login Protocol +ssh 22/udp +telnet 23/tcp +smtp 25/tcp mail +time 37/tcp timserver +time 37/udp timserver +rlp 39/udp resource # resource location +nameserver 42/tcp name # IEN 116 +whois 43/tcp nicname +tacacs 49/tcp # Login Host Protocol (TACACS) +tacacs 49/udp +re-mail-ck 50/tcp # Remote Mail Checking Protocol +re-mail-ck 50/udp +domain 53/tcp # name-domain server +domain 53/udp +mtp 57/tcp # deprecated +tacacs-ds 65/tcp # TACACS-Database Service +tacacs-ds 65/udp +bootps 67/tcp # BOOTP server +bootps 67/udp +bootpc 68/tcp # BOOTP client +bootpc 68/udp +tftp 69/udp +gopher 70/tcp # Internet Gopher +gopher 70/udp +rje 77/tcp netrjs +finger 79/tcp +www 80/tcp http # WorldWideWeb HTTP +www 80/udp # HyperText Transfer Protocol +link 87/tcp ttylink +kerberos 88/tcp kerberos5 krb5 kerberos-sec # Kerberos v5 +kerberos 88/udp kerberos5 krb5 kerberos-sec # Kerberos v5 +supdup 95/tcp +hostnames 101/tcp hostname # usually from sri-nic +iso-tsap 102/tcp tsap # part of ISODE +acr-nema 104/tcp dicom # Digital Imag. & Comm. 300 +acr-nema 104/udp dicom # Digital Imag. & Comm. 300 +csnet-ns 105/tcp cso-ns # also used by CSO name server +csnet-ns 105/udp cso-ns +rtelnet 107/tcp # Remote Telnet +rtelnet 107/udp +pop2 109/tcp postoffice pop-2 # POP version 2 +pop2 109/udp pop-2 +pop3 110/tcp pop-3 # POP version 3 +pop3 110/udp pop-3 +sunrpc 111/tcp portmapper # RPC 4.0 portmapper +sunrpc 111/udp portmapper +auth 113/tcp authentication tap ident +sftp 115/tcp +uucp-path 117/tcp +nntp 119/tcp readnews untp # USENET News Transfer Protocol +ntp 123/tcp +ntp 123/udp # Network Time Protocol +pwdgen 129/tcp # PWDGEN service +pwdgen 129/udp # PWDGEN service +loc-srv 135/tcp epmap # Location Service +loc-srv 135/udp epmap +netbios-ns 137/tcp # NETBIOS Name Service +netbios-ns 137/udp +netbios-dgm 138/tcp # NETBIOS Datagram Service +netbios-dgm 138/udp +netbios-ssn 139/tcp # NETBIOS session service +netbios-ssn 139/udp +imap2 143/tcp imap # Interim Mail Access P 2 and 4 +imap2 143/udp imap +snmp 161/tcp # Simple Net Mgmt Protocol +snmp 161/udp # Simple Net Mgmt Protocol +snmp-trap 162/tcp snmptrap # Traps for SNMP +snmp-trap 162/udp snmptrap # Traps for SNMP +cmip-man 163/tcp # ISO mgmt over IP (CMOT) +cmip-man 163/udp +cmip-agent 164/tcp +cmip-agent 164/udp +mailq 174/tcp # Mailer transport queue for Zmailer +mailq 174/udp # Mailer transport queue for Zmailer +xdmcp 177/tcp # X Display Mgr. Control Proto +xdmcp 177/udp +nextstep 178/tcp NeXTStep NextStep # NeXTStep window +nextstep 178/udp NeXTStep NextStep # server +bgp 179/tcp # Border Gateway Protocol +bgp 179/udp +prospero 191/tcp # Cliff Neuman's Prospero +prospero 191/udp +irc 194/tcp # Internet Relay Chat +irc 194/udp +smux 199/tcp # SNMP Unix Multiplexer +smux 199/udp +at-rtmp 201/tcp # AppleTalk routing +at-rtmp 201/udp +at-nbp 202/tcp # AppleTalk name binding +at-nbp 202/udp +at-echo 204/tcp # AppleTalk echo +at-echo 204/udp +at-zis 206/tcp # AppleTalk zone information +at-zis 206/udp +qmtp 209/tcp # Quick Mail Transfer Protocol +qmtp 209/udp # Quick Mail Transfer Protocol +z3950 210/tcp wais # NISO Z39.50 database +z3950 210/udp wais +ipx 213/tcp # IPX +ipx 213/udp +imap3 220/tcp # Interactive Mail Access +imap3 220/udp # Protocol v3 +pawserv 345/tcp # Perf Analysis Workbench +pawserv 345/udp +zserv 346/tcp # Zebra server +zserv 346/udp +fatserv 347/tcp # Fatmen Server +fatserv 347/udp +rpc2portmap 369/tcp +rpc2portmap 369/udp # Coda portmapper +codaauth2 370/tcp +codaauth2 370/udp # Coda authentication server +clearcase 371/tcp Clearcase +clearcase 371/udp Clearcase +ulistserv 372/tcp # UNIX Listserv +ulistserv 372/udp +ldap 389/tcp # Lightweight Directory Access Protocol +ldap 389/udp +imsp 406/tcp # Interactive Mail Support Protocol +imsp 406/udp +https 443/tcp # http protocol over TLS/SSL +https 443/udp +snpp 444/tcp # Simple Network Paging Protocol +snpp 444/udp +microsoft-ds 445/tcp # Microsoft Naked CIFS +microsoft-ds 445/udp +kpasswd 464/tcp +kpasswd 464/udp +saft 487/tcp # Simple Asynchronous File Transfer +saft 487/udp +isakmp 500/tcp # IPsec - Internet Security Association +isakmp 500/udp # and Key Management Protocol +rtsp 554/tcp # Real Time Stream Control Protocol +rtsp 554/udp # Real Time Stream Control Protocol +nqs 607/tcp # Network Queuing system +nqs 607/udp +npmp-local 610/tcp dqs313_qmaster # npmp-local / DQS +npmp-local 610/udp dqs313_qmaster +npmp-gui 611/tcp dqs313_execd # npmp-gui / DQS +npmp-gui 611/udp dqs313_execd +hmmp-ind 612/tcp dqs313_intercell # HMMP Indication / DQS +hmmp-ind 612/udp dqs313_intercell +qmqp 628/tcp +qmqp 628/udp +ipp 631/tcp # Internet Printing Protocol +ipp 631/udp +# +# UNIX specific services +# +exec 512/tcp +biff 512/udp comsat +login 513/tcp +who 513/udp whod +shell 514/tcp cmd # no passwords used +syslog 514/udp +printer 515/tcp spooler # line printer spooler +talk 517/udp +ntalk 518/udp +route 520/udp router routed # RIP +timed 525/udp timeserver +tempo 526/tcp newdate +courier 530/tcp rpc +conference 531/tcp chat +netnews 532/tcp readnews +netwall 533/udp # for emergency broadcasts +gdomap 538/tcp # GNUstep distributed objects +gdomap 538/udp +uucp 540/tcp uucpd # uucp daemon +klogin 543/tcp # Kerberized `rlogin' (v5) +kshell 544/tcp krcmd # Kerberized `rsh' (v5) +afpovertcp 548/tcp # AFP over TCP +afpovertcp 548/udp +remotefs 556/tcp rfs_server rfs # Brunhoff remote filesystem +nntps 563/tcp snntp # NNTP over SSL +nntps 563/udp snntp +submission 587/tcp # Submission [RFC4409] +submission 587/udp +ldaps 636/tcp # LDAP over SSL +ldaps 636/udp +tinc 655/tcp # tinc control port +tinc 655/udp +silc 706/tcp +silc 706/udp +kerberos-adm 749/tcp # Kerberos `kadmin' (v5) +# +webster 765/tcp # Network dictionary +webster 765/udp +rsync 873/tcp +rsync 873/udp +ftps-data 989/tcp # FTP over SSL (data) +ftps 990/tcp +telnets 992/tcp # Telnet over SSL +telnets 992/udp +imaps 993/tcp # IMAP over SSL +imaps 993/udp +ircs 994/tcp # IRC over SSL +ircs 994/udp +pop3s 995/tcp # POP-3 over SSL +pop3s 995/udp +# +# From ``Assigned Numbers'': +# +#> The Registered Ports are not controlled by the IANA and on most systems +#> can be used by ordinary user processes or programs executed by ordinary +#> users. +# +#> Ports are used in the TCP [45,106] to name the ends of logical +#> connections which carry long term conversations. For the purpose of +#> providing services to unknown callers, a service contact port is +#> defined. This list specifies the port used by the server process as its +#> contact port. While the IANA can not control uses of these ports it +#> does register or list uses of these ports as a convienence to the +#> community. +# +socks 1080/tcp # socks proxy server +socks 1080/udp +proofd 1093/tcp +proofd 1093/udp +rootd 1094/tcp +rootd 1094/udp +openvpn 1194/tcp +openvpn 1194/udp +rmiregistry 1099/tcp # Java RMI Registry +rmiregistry 1099/udp +kazaa 1214/tcp +kazaa 1214/udp +nessus 1241/tcp # Nessus vulnerability +nessus 1241/udp # assessment scanner +lotusnote 1352/tcp lotusnotes # Lotus Note +lotusnote 1352/udp lotusnotes +ms-sql-s 1433/tcp # Microsoft SQL Server +ms-sql-s 1433/udp +ms-sql-m 1434/tcp # Microsoft SQL Monitor +ms-sql-m 1434/udp +ingreslock 1524/tcp +ingreslock 1524/udp +prospero-np 1525/tcp # Prospero non-privileged +prospero-np 1525/udp +datametrics 1645/tcp old-radius +datametrics 1645/udp old-radius +sa-msg-port 1646/tcp old-radacct +sa-msg-port 1646/udp old-radacct +kermit 1649/tcp +kermit 1649/udp +l2f 1701/tcp l2tp +l2f 1701/udp l2tp +radius 1812/tcp +radius 1812/udp +radius-acct 1813/tcp radacct # Radius Accounting +radius-acct 1813/udp radacct +msnp 1863/tcp # MSN Messenger +msnp 1863/udp +unix-status 1957/tcp # remstats unix-status server +log-server 1958/tcp # remstats log server +remoteping 1959/tcp # remstats remoteping server +cisco-sccp 2000/tcp sieve # Cisco SCCP +cisco-sccp 2000/udp +search 2010/tcp ndtp +pipe_server 2010/tcp +nfs 2049/tcp # Network File System +nfs 2049/udp # Network File System +gnunet 2086/tcp +gnunet 2086/udp +rtcm-sc104 2101/tcp # RTCM SC-104 IANA 1/29/99 +rtcm-sc104 2101/udp +gsigatekeeper 2119/tcp +gsigatekeeper 2119/udp +gris 2135/tcp # Grid Resource Information Server +gris 2135/udp # Grid Resource Information Server +cvspserver 2401/tcp # CVS client/server operations +cvspserver 2401/udp +venus 2430/tcp # codacon port +venus 2430/udp # Venus callback/wbc interface +venus-se 2431/tcp # tcp side effects +venus-se 2431/udp # udp sftp side effect +codasrv 2432/tcp # not used +codasrv 2432/udp # server port +codasrv-se 2433/tcp # tcp side effects +codasrv-se 2433/udp # udp sftp side effect +mon 2583/tcp # MON traps +mon 2583/udp +dict 2628/tcp # Dictionary server +dict 2628/udp +gsiftp 2811/tcp +gsiftp 2811/udp +gpsd 2947/tcp +gpsd 2947/udp +gds_db 3050/tcp # InterBase server +gds_db 3050/udp +icpv2 3130/tcp icp # Internet Cache Protocol +icpv2 3130/udp icp +mysql 3306/tcp +mysql 3306/udp +nut 3493/tcp # Network UPS Tools +nut 3493/udp +distcc 3632/tcp # distributed compiler +distcc 3632/udp +daap 3689/tcp # Digital Audio Access Protocol +daap 3689/udp +svn 3690/tcp subversion # Subversion protocol +svn 3690/udp subversion +suucp 4031/tcp # UUCP over SSL +suucp 4031/udp # UUCP over SSL +sysrqd 4094/tcp # sysrq daemon +sysrqd 4094/udp # sysrq daemon +remctl 4373/tcp # Remote Authenticated Command Service +remctl 4373/udp # Remote Authenticated Command Service +iax 4569/tcp # Inter-Asterisk eXchange +iax 4569/udp +radmin-port 4899/tcp # RAdmin Port +radmin-port 4899/udp +rfe 5002/udp # Radio Free Ethernet +rfe 5002/tcp +mmcc 5050/tcp # multimedia conference control tool (Yahoo IM) +mmcc 5050/udp +sip 5060/tcp # Session Initiation Protocol +sip 5060/udp +sip-tls 5061/tcp +sip-tls 5061/udp +aol 5190/tcp # AIM +aol 5190/udp +xmpp-client 5222/tcp jabber-client # Jabber Client Connection +xmpp-client 5222/udp jabber-client +xmpp-server 5269/tcp jabber-server # Jabber Server Connection +xmpp-server 5269/udp jabber-server +cfengine 5308/tcp +cfengine 5308/udp +mdns 5353/tcp # Multicast DNS +mdns 5353/udp # Multicast DNS +postgresql 5432/tcp postgres # PostgreSQL Database +postgresql 5432/udp postgres +freeciv 5556/tcp rptp # Freeciv gameplay +freeciv 5556/udp +amqp 5672/tcp +amqp 5672/udp +amqp 5672/sctp +ggz 5688/tcp # GGZ Gaming Zone +ggz 5688/udp # GGZ Gaming Zone +x11 6000/tcp x11-0 # X Window System +x11 6000/udp x11-0 +x11-1 6001/tcp +x11-1 6001/udp +x11-2 6002/tcp +x11-2 6002/udp +x11-3 6003/tcp +x11-3 6003/udp +x11-4 6004/tcp +x11-4 6004/udp +x11-5 6005/tcp +x11-5 6005/udp +x11-6 6006/tcp +x11-6 6006/udp +x11-7 6007/tcp +x11-7 6007/udp +gnutella-svc 6346/tcp # gnutella +gnutella-svc 6346/udp +gnutella-rtr 6347/tcp # gnutella +gnutella-rtr 6347/udp +sge_qmaster 6444/tcp # Grid Engine Qmaster Service +sge_qmaster 6444/udp # Grid Engine Qmaster Service +sge_execd 6445/tcp # Grid Engine Execution Service +sge_execd 6445/udp # Grid Engine Execution Service +afs3-fileserver 7000/tcp bbs # file server itself +afs3-fileserver 7000/udp bbs +afs3-callback 7001/tcp # callbacks to cache managers +afs3-callback 7001/udp +afs3-prserver 7002/tcp # users & groups database +afs3-prserver 7002/udp +afs3-vlserver 7003/tcp # volume location database +afs3-vlserver 7003/udp +afs3-kaserver 7004/tcp # AFS/Kerberos authentication +afs3-kaserver 7004/udp +afs3-volser 7005/tcp # volume managment server +afs3-volser 7005/udp +afs3-errors 7006/tcp # error interpretation service +afs3-errors 7006/udp +afs3-bos 7007/tcp # basic overseer process +afs3-bos 7007/udp +afs3-update 7008/tcp # server-to-server updater +afs3-update 7008/udp +afs3-rmtsys 7009/tcp # remote cache manager service +afs3-rmtsys 7009/udp +font-service 7100/tcp xfs # X Font Service +font-service 7100/udp xfs +http-alt 8080/tcp webcache # WWW caching service +http-alt 8080/udp # WWW caching service +bacula-dir 9101/tcp # Bacula Director +bacula-dir 9101/udp +bacula-fd 9102/tcp # Bacula File Daemon +bacula-fd 9102/udp +bacula-sd 9103/tcp # Bacula Storage Daemon +bacula-sd 9103/udp +xmms2 9667/tcp # Cross-platform Music Multiplexing System +xmms2 9667/udp # Cross-platform Music Multiplexing System +amanda 10080/tcp # amanda backup services +amanda 10080/udp +hkp 11371/tcp # OpenPGP HTTP Keyserver +hkp 11371/udp # OpenPGP HTTP Keyserver +bprd 13720/tcp # VERITAS NetBackup +bprd 13720/udp +bpdbm 13721/tcp # VERITAS NetBackup +bpdbm 13721/udp +bpjava-msvc 13722/tcp # BP Java MSVC Protocol +bpjava-msvc 13722/udp +vnetd 13724/tcp # Veritas Network Utility +vnetd 13724/udp +bpcd 13782/tcp # VERITAS NetBackup +bpcd 13782/udp +vopied 13783/tcp # VERITAS NetBackup +vopied 13783/udp +wnn6 22273/tcp # wnn6 +wnn6 22273/udp + +# +# Datagram Delivery Protocol services +# +rtmp 1/ddp # Routing Table Maintenance Protocol +nbp 2/ddp # Name Binding Protocol +echo 4/ddp # AppleTalk Echo Protocol +zip 6/ddp # Zone Information Protocol + +#========================================================================= +# The remaining port numbers are not as allocated by IANA. +#========================================================================= + +# Kerberos (Project Athena/MIT) services +# Note that these are for Kerberos v4, and are unofficial. Sites running +# v4 should uncomment these and comment out the v5 entries above. +# +kerberos4 750/udp kerberos-iv kdc # Kerberos (server) +kerberos4 750/tcp kerberos-iv kdc +kerberos_master 751/udp # Kerberos authentication +kerberos_master 751/tcp +passwd_server 752/udp # Kerberos passwd server +krb_prop 754/tcp krb5_prop hprop # Kerberos slave propagation +krbupdate 760/tcp kreg # Kerberos registration +swat 901/tcp # swat +kpop 1109/tcp # Pop with Kerberos +knetd 2053/tcp # Kerberos de-multiplexor +zephyr-srv 2102/udp # Zephyr server +zephyr-clt 2103/udp # Zephyr serv-hm connection +zephyr-hm 2104/udp # Zephyr hostmanager +eklogin 2105/tcp # Kerberos encrypted rlogin +# Hmmm. Are we using Kv4 or Kv5 now? Worrying. +# The following is probably Kerberos v5 --- ajt@debian.org (11/02/2000) +kx 2111/tcp # X over Kerberos +iprop 2121/tcp # incremental propagation +# +# Unofficial but necessary (for NetBSD) services +# +supfilesrv 871/tcp # SUP server +supfiledbg 1127/tcp # SUP debugging + +# +# Services added for the Debian GNU/Linux distribution +# +linuxconf 98/tcp # LinuxConf +poppassd 106/tcp # Eudora +poppassd 106/udp +ssmtp 465/tcp smtps # SMTP over SSL +moira_db 775/tcp # Moira database +moira_update 777/tcp # Moira update protocol +moira_ureg 779/udp # Moira user registration +spamd 783/tcp # spamassassin daemon +omirr 808/tcp omirrd # online mirror +omirr 808/udp omirrd +customs 1001/tcp # pmake customs server +customs 1001/udp +skkserv 1178/tcp # skk jisho server port +predict 1210/udp # predict -- satellite tracking +rmtcfg 1236/tcp # Gracilis Packeten remote config server +wipld 1300/tcp # Wipl network monitor +xtel 1313/tcp # french minitel +xtelw 1314/tcp # french minitel +support 1529/tcp # GNATS +cfinger 2003/tcp # GNU Finger +frox 2121/tcp # frox: caching ftp proxy +ninstall 2150/tcp # ninstall service +ninstall 2150/udp +zebrasrv 2600/tcp # zebra service +zebra 2601/tcp # zebra vty +ripd 2602/tcp # ripd vty (zebra) +ripngd 2603/tcp # ripngd vty (zebra) +ospfd 2604/tcp # ospfd vty (zebra) +bgpd 2605/tcp # bgpd vty (zebra) +ospf6d 2606/tcp # ospf6d vty (zebra) +ospfapi 2607/tcp # OSPF-API +isisd 2608/tcp # ISISd vty (zebra) +afbackup 2988/tcp # Afbackup system +afbackup 2988/udp +afmbackup 2989/tcp # Afmbackup system +afmbackup 2989/udp +xtell 4224/tcp # xtell server +fax 4557/tcp # FAX transmission service (old) +hylafax 4559/tcp # HylaFAX client-server protocol (new) +distmp3 4600/tcp # distmp3host daemon +munin 4949/tcp lrrd # Munin +enbd-cstatd 5051/tcp # ENBD client statd +enbd-sstatd 5052/tcp # ENBD server statd +pcrd 5151/tcp # PCR-1000 Daemon +noclog 5354/tcp # noclogd with TCP (nocol) +noclog 5354/udp # noclogd with UDP (nocol) +hostmon 5355/tcp # hostmon uses TCP (nocol) +hostmon 5355/udp # hostmon uses UDP (nocol) +rplay 5555/udp # RPlay audio service +nsca 5667/tcp # Nagios Agent - NSCA +mrtd 5674/tcp # MRT Routing Daemon +bgpsim 5675/tcp # MRT Routing Simulator +canna 5680/tcp # cannaserver +sane-port 6566/tcp sane saned # SANE network scanner daemon +ircd 6667/tcp # Internet Relay Chat +zope-ftp 8021/tcp # zope management by ftp +tproxy 8081/tcp # Transparent Proxy +omniorb 8088/tcp # OmniORB +omniorb 8088/udp +clc-build-daemon 8990/tcp # Common lisp build daemon +xinetd 9098/tcp +mandelspawn 9359/udp mandelbrot # network mandelbrot +git 9418/tcp # Git Version Control System +zope 9673/tcp # zope server +webmin 10000/tcp +kamanda 10081/tcp # amanda backup services (Kerberos) +kamanda 10081/udp +amandaidx 10082/tcp # amanda backup services +amidxtape 10083/tcp # amanda backup services +smsqp 11201/tcp # Alamin SMS gateway +smsqp 11201/udp +xpilot 15345/tcp # XPilot Contact Port +xpilot 15345/udp +sgi-cmsd 17001/udp # Cluster membership services daemon +sgi-crsd 17002/udp +sgi-gcd 17003/udp # SGI Group membership daemon +sgi-cad 17004/tcp # Cluster Admin daemon +isdnlog 20011/tcp # isdn logging system +isdnlog 20011/udp +vboxd 20012/tcp # voice box system +vboxd 20012/udp +binkp 24554/tcp # binkp fidonet protocol +asp 27374/tcp # Address Search Protocol +asp 27374/udp +csync2 30865/tcp # cluster synchronization tool +dircproxy 57000/tcp # Detachable IRC Proxy +tfido 60177/tcp # fidonet EMSI over telnet +fido 60179/tcp # fidonet EMSI over TCP + +# Local services diff --git a/StdLib/EfiSocketLib/EfiSocketLib.inf b/StdLib/EfiSocketLib/EfiSocketLib.inf new file mode 100644 index 0000000000..9a30193f84 --- /dev/null +++ b/StdLib/EfiSocketLib/EfiSocketLib.inf @@ -0,0 +1,56 @@ +#/** @file
+# Component description file for the EFI socket library.
+#
+# This module implements the socket layer.
+# Copyright (c) 2011, Intel Corporation
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = EfiSocketLib
+ FILE_GUID = C33E0B7C-9D0F-41df-BDFD-08F5E4C39EE8
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = EfiSocketLib
+ CONSTRUCTOR = EslConstructor
+ DESTRUCTOR = EslDestructor
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ Init.c
+ Service.c
+ Socket.c
+ Tcp4.c
+ Udp4.c
+ UseEfiSocketLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ StdLib/StdLib.dec
+# SocketPkg/SocketPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ UefiBootServicesTableLib
+ UefiLib
+
+[Protocols]
+ gEfiTcp4ProtocolGuid
+ gEfiTcp4ServiceBindingProtocolGuid
+ gEfiUdp4ProtocolGuid
+ gEfiUdp4ServiceBindingProtocolGuid
+ gEfiSocketProtocolGuid
+ gEfiSocketServiceBindingProtocolGuid
diff --git a/StdLib/EfiSocketLib/Init.c b/StdLib/EfiSocketLib/Init.c new file mode 100644 index 0000000000..7a1b89da87 --- /dev/null +++ b/StdLib/EfiSocketLib/Init.c @@ -0,0 +1,87 @@ +/** @file
+ Implement the constructor and destructor for the EFI socket library
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <socket.h>
+
+
+/**
+ EFI Socket Library Constructor
+
+ @retval EFI_SUCCESS The initialization was successful
+
+ **/
+EFI_STATUS
+EFIAPI
+EslConstructor (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume success
+ //
+ Status = EFI_SUCCESS;
+
+ //
+ // Call the image dependent constructor if available
+ //
+ if ( NULL != mpfnEslConstructor ) {
+ Status = mpfnEslConstructor ( );
+ }
+
+ //
+ // Return the constructor status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ EFI Socket Library Destructor
+
+ @retval EFI_SUCCESS The shutdown was successful
+
+ **/
+EFI_STATUS
+EFIAPI
+EslDestructor (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume success
+ //
+ Status = EFI_SUCCESS;
+
+ //
+ // Call the image dependent destructor if available
+ //
+ if ( NULL != mpfnEslDestructor ) {
+ Status = mpfnEslDestructor ( );
+ }
+
+ //
+ // Return the constructor status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
diff --git a/StdLib/EfiSocketLib/Service.c b/StdLib/EfiSocketLib/Service.c new file mode 100644 index 0000000000..49c8884612 --- /dev/null +++ b/StdLib/EfiSocketLib/Service.c @@ -0,0 +1,529 @@ +/** @file
+ Connect to and disconnect from the various network layers
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Socket.h"
+
+EFI_TCP4_PROTOCOL * mpEfiTcpClose4 [ 1024 ];
+
+
+/**
+ Connect to the network service bindings
+
+ Walk the network service protocols on the controller handle and
+ locate any that are not in use. Create service structures to
+ manage the service binding for the socket driver.
+
+ @param [in] BindingHandle Handle for protocol binding.
+ @param [in] Controller Handle of device to work with.
+
+ @retval EFI_SUCCESS This driver is added to Controller.
+ @retval other This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+EslServiceConnect (
+ IN EFI_HANDLE BindingHandle,
+ IN EFI_HANDLE Controller
+ )
+{
+ BOOLEAN bInUse;
+ UINTN LengthInBytes;
+ CONST DT_SOCKET_BINDING * pEnd;
+ VOID * pJunk;
+ VOID * pInterface;
+ DT_SERVICE * pService;
+ CONST DT_SOCKET_BINDING * pSocketBinding;
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume the list is empty
+ //
+ Status = EFI_UNSUPPORTED;
+ bInUse = FALSE;
+
+ //
+ // Walk the list of network connection points
+ //
+ pSocketBinding = &cEslSocketBinding[0];
+ pEnd = &pSocketBinding[ cEslSocketBindingEntries ];
+ while ( pEnd > pSocketBinding ) {
+ //
+ // Determine if the controller supports the network protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ pSocketBinding->pNetworkBinding,
+ &pInterface,
+ BindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Determine if the socket layer is already connected
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ (EFI_GUID *)pSocketBinding->pTagGuid,
+ &pJunk,
+ BindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if ( EFI_UNSUPPORTED == Status ) {
+ //
+ // Allocate a service structure since the tag is not present
+ //
+ LengthInBytes = sizeof ( *pService );
+ Status = gBS->AllocatePool (
+ EfiRuntimeServicesData,
+ LengthInBytes,
+ (VOID **) &pService
+ );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_POOL | DEBUG_INIT,
+ "0x%08x: Allocate pService, %d bytes\r\n",
+ pService,
+ LengthInBytes ));
+
+ //
+ // Set the structure signature and service binding
+ //
+ ZeroMem ( pService, LengthInBytes );
+ pService->Signature = SERVICE_SIGNATURE;
+ pService->pSocketBinding = pSocketBinding;
+ pService->Controller = Controller;
+ pService->pInterface = pInterface;
+
+ //
+ // Mark the controller in use
+ //
+ if ( !bInUse ) {
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Controller,
+ &gEfiCallerIdGuid,
+ NULL,
+ NULL
+ );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
+ "Installed: gEfiCallerIdGuid on 0x%08x\r\n",
+ Controller ));
+ bInUse = TRUE;
+ }
+ else {
+ if ( EFI_INVALID_PARAMETER == Status ) {
+ Status = EFI_SUCCESS;
+ }
+ }
+ }
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Mark the network service protocol in use
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Controller,
+ pSocketBinding->pTagGuid,
+ pService,
+ NULL
+ );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
+ "Installed: %s TagGuid on 0x%08x\r\n",
+ pSocketBinding->pName,
+ Controller ));
+
+ //
+ // Synchronize with the socket layer
+ //
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );
+
+ //
+ // Initialize the service
+ //
+ Status = pSocketBinding->pfnInitialize ( pService );
+
+ //
+ // Release the socket layer synchronization
+ //
+ RESTORE_TPL ( TplPrevious );
+
+ //
+ // Determine if the initialization was successful
+ //
+ if ( EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,
+ "ERROR - Failed to initialize service %s on 0x%08x, Status: %r\r\n",
+ pSocketBinding->pName,
+ Controller,
+ Status ));
+
+ //
+ // Free the network service binding if necessary
+ //
+ gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ pSocketBinding->pTagGuid,
+ pService,
+ NULL );
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
+ "Removed: %s TagGuid from 0x%08x\r\n",
+ pSocketBinding->pName,
+ Controller ));
+ }
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,
+ "ERROR - Failed to install %s TagGuid on 0x%08x, Status: %r\r\n",
+ pSocketBinding->pName,
+ Controller,
+ Status ));
+ }
+
+ if ( EFI_ERROR ( Status )) {
+ //
+ // The controller is no longer in use
+ //
+ if ( bInUse ) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiCallerIdGuid,
+ NULL,
+ NULL );
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
+ "Removed: gEfiCallerIdGuid from 0x%08x\r\n",
+ Controller ));
+ }
+ }
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_INIT,
+ "ERROR - Failed to install gEfiCallerIdGuid on 0x%08x, Status: %r\r\n",
+ Controller,
+ Status ));
+ }
+
+ //
+ // Release the service if necessary
+ //
+ if ( EFI_ERROR ( Status )) {
+ gBS->FreePool ( pService );
+ DEBUG (( DEBUG_POOL | DEBUG_INIT,
+ "0x%08x: Free pService, %d bytes\r\n",
+ pService,
+ sizeof ( *pService )));
+ pService = NULL;
+ }
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_INIT,
+ "ERROR - Failed service allocation, Status: %r\r\n",
+ Status ));
+ }
+ }
+ }
+
+ //
+ // Set the next network protocol
+ //
+ pSocketBinding += 1;
+ }
+
+ //
+ // Display the driver start status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Shutdown the network connections to this controller by removing
+ NetworkInterfaceIdentifier protocol and closing the DevicePath
+ and PciIo protocols on Controller.
+
+ @param [in] BindingHandle Handle for protocol binding.
+ @param [in] Controller Handle of device to stop driver on.
+
+ @retval EFI_SUCCESS This driver is removed Controller.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+ @retval other This driver was not removed from this device.
+
+**/
+EFI_STATUS
+EFIAPI
+EslServiceDisconnect (
+ IN EFI_HANDLE BindingHandle,
+ IN EFI_HANDLE Controller
+ )
+{
+ CONST DT_SOCKET_BINDING * pEnd;
+ DT_SERVICE * pService;
+ CONST DT_SOCKET_BINDING * pSocketBinding;
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+
+ DBG_ENTER ( );
+
+ //
+ // Walk the list of network connection points in reverse order
+ //
+ pEnd = &cEslSocketBinding[0];
+ pSocketBinding = &pEnd[ cEslSocketBindingEntries ];
+ while ( pEnd < pSocketBinding ) {
+ //
+ // Set the next network protocol
+ //
+ pSocketBinding -= 1;
+
+ //
+ // Determine if the driver connected
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ (EFI_GUID *)pSocketBinding->pTagGuid,
+ (VOID **)&pService,
+ BindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if ( !EFI_ERROR ( Status )) {
+
+ //
+ // Synchronize with the socket layer
+ //
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );
+
+ //
+ // Shutdown the service
+ //
+ pSocketBinding->pfnShutdown ( pService );
+
+ //
+ // Release the socket layer synchronization
+ //
+ RESTORE_TPL ( TplPrevious );
+
+ //
+ // Break the driver connection
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ pSocketBinding->pTagGuid,
+ pService,
+ NULL );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_POOL | DEBUG_INIT,
+ "Removed: %s TagGuid from 0x%08x\r\n",
+ pSocketBinding->pName,
+ Controller ));
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,
+ "ERROR - Failed to removed %s TagGuid from 0x%08x, Status: %r\r\n",
+ pSocketBinding->pName,
+ Controller,
+ Status ));
+ }
+
+ //
+ // Free the service structure
+ //
+ Status = gBS->FreePool ( pService );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_POOL | DEBUG_INIT,
+ "0x%08x: Free pService, %d bytes\r\n",
+ pService,
+ sizeof ( *pService )));
+ }
+ else {
+ DEBUG (( DEBUG_POOL | DEBUG_INIT,
+ "ERROR - Failed to free pService 0x%08x, Status: %r\r\n",
+ pService,
+ Status ));
+ }
+ pService = NULL;
+ }
+ }
+
+ //
+ // The controller is no longer in use
+ //
+ gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiCallerIdGuid,
+ NULL,
+ NULL );
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
+ "Removed: gEfiCallerIdGuid from 0x%08x\r\n",
+ Controller ));
+
+ //
+ // The driver is disconnected from the network controller
+ //
+ Status = EFI_SUCCESS;
+
+ //
+ // Display the driver start status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+
+/**
+Install the socket service
+
+@param [in] pImageHandle Address of the image handle
+
+@retval EFI_SUCCESS Service installed successfully
+**/
+EFI_STATUS
+EFIAPI
+EslServiceInstall (
+ IN EFI_HANDLE * pImageHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install the socket service binding protocol
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ pImageHandle,
+ &gEfiSocketServiceBindingProtocolGuid,
+ &mEslLayer.ServiceBinding,
+ NULL
+ );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
+ "Installed: gEfiSocketServiceBindingProtocolGuid on 0x%08x\r\n",
+ *pImageHandle ));
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,
+ "ERROR - InstallMultipleProtocolInterfaces failed, Status: %r\r\n",
+ Status ));
+ }
+
+ //
+ // Return the operation status
+ //
+ return Status;
+}
+
+
+/**
+Initialize the service layer
+
+@param [in] ImageHandle Handle for the image.
+
+**/
+VOID
+EFIAPI
+EslServiceLoad (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ DT_LAYER * pLayer;
+
+ //
+ // Save the image handle
+ //
+ pLayer = &mEslLayer;
+ pLayer->Signature = LAYER_SIGNATURE;
+ pLayer->ImageHandle = ImageHandle;
+
+ //
+ // Initialize the TCP4 close
+ //
+ pLayer->TcpCloseMax4 = DIM ( mpEfiTcpClose4 );
+ pLayer->ppTcpClose4 = mpEfiTcpClose4;
+
+ //
+ // Connect the service binding protocol to the image handle
+ //
+ pLayer->ServiceBinding.CreateChild = EslSocketCreateChild;
+ pLayer->ServiceBinding.DestroyChild = EslSocketDestroyChild;
+}
+
+
+/**
+Uninstall the socket service
+
+@param [in] ImageHandle Handle for the image.
+
+@retval EFI_SUCCESS Service installed successfully
+**/
+EFI_STATUS
+EFIAPI
+EslServiceUninstall (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install the socket service binding protocol
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ ImageHandle,
+ &gEfiSocketServiceBindingProtocolGuid,
+ &mEslLayer.ServiceBinding,
+ NULL
+ );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_POOL | DEBUG_INIT,
+ "Removed: gEfiSocketServiceBindingProtocolGuid from 0x%08x\r\n",
+ ImageHandle ));
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,
+ "ERROR - Failed to remove gEfiSocketServiceBindingProtocolGuid from 0x%08x, Status: %r\r\n",
+ ImageHandle,
+ Status ));
+ }
+
+ //
+ // Return the operation status
+ //
+ return Status;
+}
+
+
+/**
+ Shutdown the service layer
+
+**/
+VOID
+EFIAPI
+EslServiceUnload (
+ VOID
+ )
+{
+ DT_LAYER * pLayer;
+
+ //
+ // Undo the work by ServiceLoad
+ //
+ pLayer = &mEslLayer;
+ pLayer->ImageHandle = NULL;
+ pLayer->ServiceBinding.CreateChild = NULL;
+ pLayer->ServiceBinding.DestroyChild = NULL;
+}
diff --git a/StdLib/EfiSocketLib/Socket.c b/StdLib/EfiSocketLib/Socket.c new file mode 100644 index 0000000000..bad888cdf5 --- /dev/null +++ b/StdLib/EfiSocketLib/Socket.c @@ -0,0 +1,3091 @@ +/** @file
+ Implement the socket support for the socket layer.
+
+ Socket States:
+ * Bound - pSocket->PortList is not NULL
+ * Listen - AcceptWait event is not NULL
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Socket.h"
+
+
+/**
+ Socket driver connection points
+
+ List the network stack connection points for the socket driver.
+**/
+CONST DT_SOCKET_BINDING cEslSocketBinding [] = {
+ { L"Tcp4",
+ &gEfiTcp4ServiceBindingProtocolGuid,
+ &mEslTcp4ServiceGuid,
+ EslTcpInitialize4,
+ EslTcpShutdown4 },
+ { L"Udp4",
+ &gEfiUdp4ServiceBindingProtocolGuid,
+ &mEslUdp4ServiceGuid,
+ EslUdpInitialize4,
+ EslUdpShutdown4 }
+};
+
+CONST UINTN cEslSocketBindingEntries = DIM ( cEslSocketBinding );
+
+DT_LAYER mEslLayer;
+
+
+/**
+ Initialize an endpoint for network communication.
+
+ The ::Socket routine initializes the communication endpoint by providing
+ the support for the socket library function ::socket. The
+ <a href="http://www.linuxhowtos.org/manpages/2/socket.htm">Linux</a>,
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html">POSIX</a>
+ and <a href="http://msdn.microsoft.com/en-us/library/ms740506(v=VS.85).aspx">Windows</a>
+ documentation for the socket routine are available online for reference.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+ @param [in] domain Select the family of protocols for the client or server
+ application.
+
+ @param [in] type Specifies how to make the network connection. The following values
+ are supported:
+ <ul>
+ <li>
+ SOCK_STREAM - Connect to TCP, provides a byte stream
+ that is manipluated by read, recv, send and write.
+ </li>
+ <li>
+ SOCK_SEQPACKET - Connect to TCP, provides sequenced packet stream
+ that is manipulated by read, recv, send and write.
+ </li>
+ <li>
+ SOCK_DGRAM - Connect to UDP, provides a datagram service that is
+ manipulated by recvfrom and sendto.
+ </li>
+ </ul>
+
+ @param [in] protocol Specifies the lower layer protocol to use. The following
+ values are supported:
+ <ul>
+ <li>IPPROTO_TCP</li> - This value must be combined with SOCK_STREAM.</li>
+ <li>IPPROTO_UDP</li> - This value must be combined with SOCK_DGRAM.</li>
+ </ul>
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket successfully created
+ @retval EFI_INVALID_PARAMETER - Invalid domain value, errno = EAFNOSUPPORT
+ @retval EFI_INVALID_PARAMETER - Invalid type value, errno = EINVAL
+ @retval EFI_INVALID_PARAMETER - Invalid protocol value, errno = EINVAL
+
+ **/
+EFI_STATUS
+EslSocket (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN int domain,
+ IN int type,
+ IN int protocol,
+ IN int * pErrno
+ )
+{
+ DT_SOCKET * pSocket;
+ EFI_STATUS Status;
+ int errno;
+
+ DBG_ENTER ( );
+
+ //
+ // Locate the socket
+ //
+ pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
+
+ //
+ // Set the default domain if necessary
+ //
+ if ( AF_UNSPEC == domain ) {
+ domain = AF_INET;
+ }
+
+ //
+ // Assume success
+ //
+ errno = 0;
+ Status = EFI_SUCCESS;
+
+ //
+ // Use break instead of goto
+ //
+ for ( ; ; ) {
+ //
+ // Validate the domain value
+ //
+ if (( AF_INET != domain )
+ && ( AF_LOCAL != domain ))
+ {
+ DEBUG (( DEBUG_ERROR | DEBUG_SOCKET,
+ "ERROR - Invalid domain value" ));
+ Status = EFI_INVALID_PARAMETER;
+ errno = EAFNOSUPPORT;
+ break;
+ }
+
+ //
+ // Set the default type if necessary
+ //
+ if ( 0 == type ) {
+ type = SOCK_STREAM;
+ }
+
+ //
+ // Validate the type value
+ //
+ if (( SOCK_STREAM == type )
+ || ( SOCK_SEQPACKET == type )) {
+ //
+ // Set the default protocol if necessary
+ //
+ if ( 0 == protocol ) {
+ protocol = IPPROTO_TCP;
+ }
+ }
+ else if ( SOCK_DGRAM == type ) {
+ //
+ // Set the default protocol if necessary
+ //
+ if ( 0 == protocol ) {
+ protocol = IPPROTO_UDP;
+ }
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_SOCKET,
+ "ERROR - Invalid type value" ));
+ Status = EFI_INVALID_PARAMETER;
+ errno = EINVAL;
+ break;
+ }
+
+ //
+ // Validate the protocol value
+ //
+ if (( IPPROTO_TCP != protocol )
+ && ( IPPROTO_UDP != protocol )) {
+ DEBUG (( DEBUG_ERROR | DEBUG_SOCKET,
+ "ERROR - Invalid protocol value" ));
+ Status = EFI_INVALID_PARAMETER;
+ errno = EINVAL;
+ break;
+ }
+
+ //
+ // Save the socket attributes
+ //
+ pSocket->Domain = domain;
+ pSocket->Type = type;
+ pSocket->Protocol = protocol;
+
+ //
+ // Done
+ //
+ break;
+ }
+
+ //
+ // Return the operation status
+ //
+ if ( NULL != pErrno ) {
+ *pErrno = errno;
+ }
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Accept a network connection.
+
+ The SocketAccept routine waits for a network connection to the socket.
+ It is able to return the remote network address to the caller if
+ requested.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [in] pSockAddr Address of a buffer to receive the remote
+ network address.
+
+ @param [in, out] pSockAddrLength Length in bytes of the address buffer.
+ On output specifies the length of the
+ remote network address.
+
+ @param [out] ppSocketProtocol Address of a buffer to receive the socket protocol
+ instance associated with the new socket.
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS New connection successfully created
+ @retval EFI_NOT_READY No connection is available
+
+ **/
+EFI_STATUS
+EslSocketAccept (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN struct sockaddr * pSockAddr,
+ IN OUT socklen_t * pSockAddrLength,
+ IN EFI_SOCKET_PROTOCOL ** ppSocketProtocol,
+ IN int * pErrno
+ )
+{
+ DT_SOCKET * pNewSocket;
+ DT_SOCKET * pSocket;
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume success
+ //
+ Status = EFI_SUCCESS;
+
+ //
+ // Validate the socket
+ //
+ pSocket = NULL;
+ pNewSocket = NULL;
+ if ( NULL != pSocketProtocol ) {
+ pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
+
+ //
+ // Validate the sockaddr
+ //
+ if (( NULL != pSockAddr )
+ && ( NULL == pSockAddrLength )) {
+ DEBUG (( DEBUG_ACCEPT,
+ "ERROR - pSockAddr is NULL!\r\n" ));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EFAULT;
+ }
+ else {
+ //
+ // Synchronize with the socket layer
+ //
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );
+
+ //
+ // Verify that the socket is in the listen state
+ //
+ if ( SOCKET_STATE_LISTENING != pSocket->State ) {
+ DEBUG (( DEBUG_ACCEPT,
+ "ERROR - Socket is not listening!\r\n" ));
+ Status = EFI_NOT_STARTED;
+ pSocket->errno = EOPNOTSUPP;
+ }
+ else {
+ //
+ // Determine if a socket is available
+ //
+ if ( 0 == pSocket->FifoDepth ) {
+ //
+ // No connections available
+ // Determine if any ports are available
+ //
+ if ( NULL == pSocket->pPortList ) {
+ //
+ // No ports available
+ //
+ Status = EFI_DEVICE_ERROR;
+ pSocket->errno = EINVAL;
+
+ //
+ // Update the socket state
+ //
+ pSocket->State = SOCKET_STATE_NO_PORTS;
+ }
+ else {
+ //
+ // Ports are available
+ // No connection requests at this time
+ //
+ Status = EFI_NOT_READY;
+ pSocket->errno = EAGAIN;
+ }
+ }
+ else {
+
+ //
+ // Get the remote network address
+ //
+ pNewSocket = pSocket->pFifoHead;
+ ASSERT ( NULL != pNewSocket );
+ switch ( pSocket->Domain ) {
+ default:
+ DEBUG (( DEBUG_ACCEPT,
+ "ERROR - Invalid socket address family: %d\r\n",
+ pSocket->Domain ));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case AF_INET:
+ //
+ // Determine the connection point within the network stack
+ //
+ switch ( pSocket->Type ) {
+ default:
+ DEBUG (( DEBUG_ACCEPT,
+ "ERROR - Invalid socket type: %d\r\n",
+ pSocket->Type));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case SOCK_STREAM:
+ case SOCK_SEQPACKET:
+ Status = EslTcpAccept4 ( pNewSocket,
+ pSockAddr,
+ pSockAddrLength );
+ break;
+
+ /*
+ case SOCK_DGRAM:
+ Status = UdpAccept4 ( pSocket );
+ break;
+ */
+ }
+ break;
+ }
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Remove the new socket from the list
+ //
+ pSocket->pFifoHead = pNewSocket->pNextConnection;
+ if ( NULL == pSocket->pFifoHead ) {
+ pSocket->pFifoTail = NULL;
+ }
+
+ //
+ // Account for this socket
+ //
+ pSocket->FifoDepth -= 1;
+
+ //
+ // Update the new socket's state
+ //
+ pNewSocket->State = SOCKET_STATE_CONNECTED;
+ pNewSocket->bConfigured = TRUE;
+ DEBUG (( DEBUG_ACCEPT,
+ "0x%08x: Socket connected\r\n",
+ pNewSocket ));
+ }
+ }
+ }
+
+ //
+ // Release the socket layer synchronization
+ //
+ RESTORE_TPL ( TplPrevious );
+ }
+ }
+
+ //
+ // Return the new socket
+ //
+ if (( NULL != ppSocketProtocol )
+ && ( NULL != pNewSocket )) {
+ *ppSocketProtocol = &pNewSocket->SocketProtocol;
+ }
+
+ //
+ // Return the operation status
+ //
+ if ( NULL != pErrno ) {
+ if ( NULL != pSocket ) {
+ *pErrno = pSocket->errno;
+ }
+ else
+ {
+ Status = EFI_INVALID_PARAMETER;
+ *pErrno = EBADF;
+ }
+ }
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Allocate and initialize a DT_SOCKET structure.
+
+ The ::SocketAllocate() function allocates a DT_SOCKET structure
+ and installs a protocol on ChildHandle. If pChildHandle is a
+ pointer to NULL, then a new handle is created and returned in
+ pChildHandle. If pChildHandle is not a pointer to NULL, then
+ the protocol installs on the existing pChildHandle.
+
+ @param [in, out] pChildHandle Pointer to the handle of the child to create.
+ If it is NULL, then a new handle is created.
+ If it is a pointer to an existing UEFI handle,
+ then the protocol is added to the existing UEFI
+ handle.
+ @param [in] DebugFlags Flags for debug messages
+ @param [in, out] ppSocket The buffer to receive the DT_SOCKET structure address.
+
+ @retval EFI_SUCCESS The protocol was added to ChildHandle.
+ @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
+ the child
+ @retval other The child handle was not created
+
+**/
+EFI_STATUS
+EFIAPI
+EslSocketAllocate (
+ IN OUT EFI_HANDLE * pChildHandle,
+ IN UINTN DebugFlags,
+ IN OUT DT_SOCKET ** ppSocket
+ )
+{
+ UINTN LengthInBytes;
+ DT_LAYER * pLayer;
+ DT_SOCKET * pSocket;
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+
+ DBG_ENTER ( );
+
+ //
+ // Create a socket structure
+ //
+ LengthInBytes = sizeof ( *pSocket );
+ Status = gBS->AllocatePool (
+ EfiRuntimeServicesData,
+ LengthInBytes,
+ (VOID **) &pSocket
+ );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT,
+ "0x%08x: Allocate pSocket, %d bytes\r\n",
+ pSocket,
+ LengthInBytes ));
+
+ //
+ // Initialize the socket protocol
+ //
+ ZeroMem ( pSocket, LengthInBytes );
+
+ pSocket->Signature = SOCKET_SIGNATURE;
+ pSocket->SocketProtocol.pfnAccept = EslSocketAccept;
+ pSocket->SocketProtocol.pfnBind = EslSocketBind;
+ pSocket->SocketProtocol.pfnClosePoll = EslSocketClosePoll;
+ pSocket->SocketProtocol.pfnCloseStart = EslSocketCloseStart;
+ pSocket->SocketProtocol.pfnConnect = EslSocketConnect;
+ pSocket->SocketProtocol.pfnGetLocal = EslSocketGetLocalAddress;
+ pSocket->SocketProtocol.pfnGetPeer = EslSocketGetPeerAddress;
+ pSocket->SocketProtocol.pfnListen = EslSocketListen;
+ pSocket->SocketProtocol.pfnOptionGet = EslSocketOptionGet;
+ pSocket->SocketProtocol.pfnOptionSet = EslSocketOptionSet;
+ pSocket->SocketProtocol.pfnPoll = EslSocketPoll;
+ pSocket->SocketProtocol.pfnReceive = EslSocketReceive;
+ pSocket->SocketProtocol.pfnSend = EslSocketTransmit;
+ pSocket->SocketProtocol.pfnShutdown = EslSocketShutdown;
+ pSocket->SocketProtocol.pfnSocket = EslSocket;
+
+ pSocket->MaxRxBuf = MAX_RX_DATA;
+ pSocket->MaxTxBuf = MAX_TX_DATA;
+
+ //
+ // Install the socket protocol on the specified handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ pChildHandle,
+ &gEfiSocketProtocolGuid,
+ &pSocket->SocketProtocol,
+ NULL
+ );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
+ "Installed: gEfiSocketProtocolGuid on 0x%08x\r\n",
+ *pChildHandle ));
+ pSocket->SocketProtocol.SocketHandle = *pChildHandle;
+
+ //
+ // Synchronize with the socket layer
+ //
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );
+
+ //
+ // Add this socket to the list
+ //
+ pLayer = &mEslLayer;
+ pSocket->pNext = pLayer->pSocketList;
+ pLayer->pSocketList = pSocket;
+
+ //
+ // Release the socket layer synchronization
+ //
+ RESTORE_TPL ( TplPrevious );
+
+ //
+ // Return the socket structure address
+ //
+ *ppSocket = pSocket;
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL | DEBUG_INIT,
+ "ERROR - Failed to install gEfiSocketProtocolGuid on 0x%08x, Status: %r\r\n",
+ *pChildHandle,
+ Status ));
+ }
+
+ //
+ // Release the socket if necessary
+ //
+ if ( EFI_ERROR ( Status )) {
+ gBS->FreePool ( pSocket );
+ DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT,
+ "0x%08x: Free pSocket, %d bytes\r\n",
+ pSocket,
+ sizeof ( *pSocket )));
+ pSocket = NULL;
+ }
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL | DEBUG_INIT,
+ "ERROR - Failed socket allocation, Status: %r\r\n",
+ Status ));
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Bind a name to a socket.
+
+ The ::SocketBind routine connects a name to a socket on the local machine. The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html">POSIX</a>
+ documentation for the bind routine is available online for reference.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [in] pSockAddr Address of a sockaddr structure that contains the
+ connection point on the local machine. An IPv4 address
+ of INADDR_ANY specifies that the connection is made to
+ all of the network stacks on the platform. Specifying a
+ specific IPv4 address restricts the connection to the
+ network stack supporting that address. Specifying zero
+ for the port causes the network layer to assign a port
+ number from the dynamic range. Specifying a specific
+ port number causes the network layer to use that port.
+
+ @param [in] SockAddrLen Specifies the length in bytes of the sockaddr structure.
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket successfully created
+
+ **/
+EFI_STATUS
+EslSocketBind (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN const struct sockaddr * pSockAddr,
+ IN socklen_t SockAddrLength,
+ OUT int * pErrno
+ )
+{
+ DT_SOCKET * pSocket;
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume success
+ //
+ Status = EFI_SUCCESS;
+
+ //
+ // Validate the socket
+ //
+ pSocket = NULL;
+ if ( NULL != pSocketProtocol ) {
+ pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
+
+ //
+ // Validate the structure pointer
+ //
+ if ( NULL == pSockAddr ) {
+ DEBUG (( DEBUG_BIND,
+ "ERROR - pSockAddr is NULL!\r\n" ));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EFAULT;
+ }
+ else{
+ //
+ // Validate the name length
+ //
+ if (( SockAddrLength < ( sizeof ( struct sockaddr ) - sizeof ( pSockAddr->sa_data )))
+ || ( pSockAddr->sa_len < ( sizeof ( struct sockaddr ) - sizeof ( pSockAddr->sa_data )))) {
+ DEBUG (( DEBUG_BIND,
+ "ERROR - Invalid bind name length: %d, sa_len: %d\r\n",
+ SockAddrLength,
+ pSockAddr->sa_len ));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EINVAL;
+ }
+ else {
+ //
+ // Set the socket address length
+ //
+ if ( SockAddrLength > pSockAddr->sa_len ) {
+ SockAddrLength = pSockAddr->sa_len;
+ }
+
+ //
+ // Synchronize with the socket layer
+ //
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );
+
+ //
+ // Validate the local address
+ //
+ switch ( pSockAddr->sa_family ) {
+ default:
+ DEBUG (( DEBUG_BIND,
+ "ERROR - Invalid bind address family: %d\r\n",
+ pSockAddr->sa_family ));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case AF_INET:
+ //
+ // Determine the connection point within the network stack
+ //
+ switch ( pSocket->Type ) {
+ default:
+ DEBUG (( DEBUG_BIND,
+ "ERROR - Invalid socket type: %d\r\n",
+ pSocket->Type));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case SOCK_STREAM:
+ case SOCK_SEQPACKET:
+ Status = EslTcpBind4 ( pSocket,
+ pSockAddr,
+ SockAddrLength );
+ break;
+
+ case SOCK_DGRAM:
+ Status = EslUdpBind4 ( pSocket,
+ pSockAddr,
+ SockAddrLength );
+ break;
+ }
+ break;
+ }
+
+ //
+ // Mark this socket as bound if successful
+ //
+ if ( !EFI_ERROR ( Status )) {
+ pSocket->State = SOCKET_STATE_BOUND;
+ }
+
+ //
+ // Release the socket layer synchronization
+ //
+ RESTORE_TPL ( TplPrevious );
+ }
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ if ( NULL != pErrno ) {
+ if ( NULL != pSocket ) {
+ *pErrno = pSocket->errno;
+ }
+ else
+ {
+ Status = EFI_INVALID_PARAMETER;
+ *pErrno = EBADF;
+ }
+ }
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Determine if the socket is closed
+
+ Reverses the operations of the ::SocketAllocate() routine.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS Socket successfully closed
+ @retval EFI_NOT_READY Close still in progress
+ @retval EFI_ALREADY Close operation already in progress
+ @retval Other Failed to close the socket
+
+**/
+EFI_STATUS
+EslSocketClosePoll (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN int * pErrno
+ )
+{
+ int errno;
+ DT_LAYER * pLayer;
+ DT_SOCKET * pNextSocket;
+ DT_SOCKET * pSocket;
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume success
+ //
+ errno = 0;
+ Status = EFI_SUCCESS;
+
+ //
+ // Synchronize with the socket layer
+ //
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );
+
+ //
+ // Locate the socket
+ //
+ pLayer = &mEslLayer;
+ pNextSocket = pLayer->pSocketList;
+ pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
+ while ( NULL != pNextSocket ) {
+ if ( pNextSocket == pSocket ) {
+ //
+ // Determine if the socket is in the closing state
+ //
+ if ( SOCKET_STATE_CLOSED == pSocket->State ) {
+ //
+ // Walk the list of ports
+ //
+ if ( NULL == pSocket->pPortList ) {
+ //
+ // All the ports are closed
+ // Close the WaitAccept event if necessary
+ //
+ if ( NULL != pSocket->WaitAccept ) {
+ Status = gBS->CloseEvent ( pSocket->WaitAccept );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_SOCKET | DEBUG_CLOSE | DEBUG_POOL,
+ "0x%08x: Closed WaitAccept event\r\n",
+ pSocket->WaitAccept ));
+ //
+ // Return the transmit status
+ //
+ Status = pSocket->TxError;
+ if ( EFI_ERROR ( Status )) {
+ pSocket->errno = EIO;
+ }
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_SOCKET | DEBUG_CLOSE | DEBUG_POOL,
+ "ERROR - Failed to close the WaitAccept event, Status: %r\r\n",
+ Status ));
+ ASSERT ( EFI_SUCCESS == Status );
+ }
+ }
+ }
+ else {
+ //
+ // At least one port is still open
+ //
+ Status = EFI_NOT_READY;
+ errno = EAGAIN;
+ }
+ }
+ else {
+ //
+ // SocketCloseStart was not called
+ //
+ Status = EFI_NOT_STARTED;
+ errno = EPERM;
+ }
+ break;
+ }
+
+ //
+ // Set the next socket
+ //
+ pNextSocket = pNextSocket->pNext;
+ }
+
+ //
+ // Handle the error case where the socket was already closed
+ //
+ if ( NULL == pSocket ) {
+ //
+ // Socket not found
+ //
+ Status = EFI_NOT_FOUND;
+ errno = ENOTSOCK;
+ }
+
+ //
+ // Release the socket layer synchronization
+ //
+ RESTORE_TPL ( TplPrevious );
+
+ //
+ // Return the operation status
+ //
+ if ( NULL != pErrno ) {
+ *pErrno = errno;
+ }
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Start the close operation on the socket
+
+ Start closing the socket by closing all of the ports. Upon
+ completion, the ::SocketPoll() routine finishes closing the
+ socket.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+ @param [in] bCloseNow Boolean to control close behavior
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS Socket successfully closed
+ @retval EFI_NOT_READY Close still in progress
+ @retval EFI_ALREADY Close operation already in progress
+ @retval Other Failed to close the socket
+
+**/
+EFI_STATUS
+EslSocketCloseStart (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN BOOLEAN bCloseNow,
+ IN int * pErrno
+ )
+{
+ int errno;
+ DT_PORT * pNextPort;
+ DT_PORT * pPort;
+ DT_SOCKET * pSocket;
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume success
+ //
+ Status = EFI_SUCCESS;
+ errno = 0;
+
+ //
+ // Synchronize with the socket layer
+ //
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );
+
+ //
+ // Determine if the socket is already closed
+ //
+ pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
+ if ( SOCKET_STATE_CLOSED > pSocket->State ) {
+ //
+ // Update the socket state
+ //
+ pSocket->State = SOCKET_STATE_CLOSED;
+
+ //
+ // Walk the list of ports
+ //
+ pPort = pSocket->pPortList;
+ while ( NULL != pPort ) {
+ //
+ // Start closing the ports
+ //
+ pNextPort = pPort->pLinkSocket;
+ Status = pPort->pfnCloseStart ( pPort,
+ bCloseNow,
+ DEBUG_CLOSE | DEBUG_LISTEN | DEBUG_CONNECTION );
+ if (( EFI_SUCCESS != Status )
+ && ( EFI_NOT_READY != Status )) {
+ errno = EIO;
+ break;
+ }
+
+ //
+ // Set the next port
+ //
+ pPort = pNextPort;
+ }
+
+ //
+ // Attempt to finish closing the socket
+ //
+ if ( NULL == pPort ) {
+ Status = EslSocketClosePoll ( pSocketProtocol, &errno );
+ }
+ }
+ else {
+ Status = EFI_ALREADY_STARTED;
+ errno = EALREADY;
+ }
+
+ //
+ // Release the socket layer synchronization
+ //
+ RESTORE_TPL ( TplPrevious );
+
+ //
+ // Return the operation status
+ //
+ if ( NULL != pErrno ) {
+ *pErrno = errno;
+ }
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Connect to a remote system via the network.
+
+ The ::SocketConnect routine attempts to establish a connection to a
+ socket on the local or remote system using the specified address.
+ The POSIX
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html">connect</a>
+ documentation is available online.
+
+ There are three states associated with a connection:
+ <ul>
+ <li>Not connected</li>
+ <li>Connection in progress</li>
+ <li>Connected</li>
+ </ul>
+ In the "Not connected" state, calls to ::connect start the connection
+ processing and update the state to "Connection in progress". During
+ the "Connection in progress" state, connect polls for connection completion
+ and moves the state to "Connected" after the connection is established.
+ Note that these states are only visible when the file descriptor is marked
+ with O_NONBLOCK. Also, the POLL_WRITE bit is set when the connection
+ completes and may be used by poll or select as an indicator to call
+ connect again.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [in] pSockAddr Network address of the remote system.
+
+ @param [in] SockAddrLength Length in bytes of the network address.
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS The connection was successfully established.
+ @retval EFI_NOT_READY The connection is in progress, call this routine again.
+ @retval Others The connection attempt failed.
+
+ **/
+EFI_STATUS
+EslSocketConnect (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN const struct sockaddr * pSockAddr,
+ IN socklen_t SockAddrLength,
+ IN int * pErrno
+ )
+{
+ DT_SOCKET * pSocket;
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+
+ DEBUG (( DEBUG_CONNECT, "Entering SocketConnect\r\n" ));
+
+ //
+ // Assume success
+ //
+ Status = EFI_SUCCESS;
+
+ //
+ // Validate the socket
+ //
+ pSocket = NULL;
+ if ( NULL != pSocketProtocol ) {
+ pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
+
+ //
+ // Validate the name length
+ //
+ if (( SockAddrLength < ( sizeof ( struct sockaddr ) - sizeof ( pSockAddr->sa_data )))
+ || ( pSockAddr->sa_len < ( sizeof ( struct sockaddr ) - sizeof ( pSockAddr->sa_data )))) {
+ DEBUG (( DEBUG_CONNECT,
+ "ERROR - Invalid bind name length: %d, sa_len: %d\r\n",
+ SockAddrLength,
+ pSockAddr->sa_len ));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EINVAL;
+ }
+ else {
+ //
+ // Assume success
+ //
+ pSocket->errno = 0;
+
+ //
+ // Set the socket address length
+ //
+ if ( SockAddrLength > pSockAddr->sa_len ) {
+ SockAddrLength = pSockAddr->sa_len;
+ }
+
+ //
+ // Synchronize with the socket layer
+ //
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );
+
+ //
+ // Validate the socket state
+ //
+ switch ( pSocket->State ) {
+ default:
+ //
+ // Wrong socket state
+ //
+ pSocket->errno = EIO;
+ Status = EFI_DEVICE_ERROR;
+ break;
+
+ case SOCKET_STATE_NOT_CONFIGURED:
+ case SOCKET_STATE_BOUND:
+ //
+ // Validate the local address
+ //
+ switch ( pSockAddr->sa_family ) {
+ default:
+ DEBUG (( DEBUG_CONNECT,
+ "ERROR - Invalid bind address family: %d\r\n",
+ pSockAddr->sa_family ));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case AF_INET:
+ //
+ // Determine the connection point within the network stack
+ //
+ switch ( pSocket->Type ) {
+ default:
+ DEBUG (( DEBUG_CONNECT,
+ "ERROR - Invalid socket type: %d\r\n",
+ pSocket->Type));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case SOCK_STREAM:
+ case SOCK_SEQPACKET:
+ //
+ // Start the connection processing
+ //
+ Status = EslTcpConnectStart4 ( pSocket,
+ pSockAddr,
+ SockAddrLength );
+
+ //
+ // Set the next state if connecting
+ //
+ if ( EFI_NOT_READY == Status ) {
+ pSocket->State = SOCKET_STATE_CONNECTING;
+ }
+ break;
+
+ case SOCK_DGRAM:
+ Status = EslUdpConnect4 ( pSocket,
+ pSockAddr,
+ SockAddrLength );
+ break;
+ }
+ break;
+ }
+ break;
+
+ case SOCKET_STATE_CONNECTING:
+ //
+ // Validate the local address
+ //
+ switch ( pSockAddr->sa_family ) {
+ default:
+ DEBUG (( DEBUG_CONNECT,
+ "ERROR - Invalid bind address family: %d\r\n",
+ pSockAddr->sa_family ));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case AF_INET:
+ //
+ // Determine the connection point within the network stack
+ //
+ switch ( pSocket->Type ) {
+ default:
+ DEBUG (( DEBUG_CONNECT,
+ "ERROR - Invalid socket type: %d\r\n",
+ pSocket->Type));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case SOCK_STREAM:
+ case SOCK_SEQPACKET:
+ //
+ // Determine if the connection processing is completed
+ //
+ Status = EslTcpConnectPoll4 ( pSocket );
+
+ //
+ // Set the next state if connected
+ //
+ if ( EFI_NOT_READY != Status ) {
+ if ( !EFI_ERROR ( Status )) {
+ pSocket->State = SOCKET_STATE_CONNECTED;
+ }
+ else {
+ pSocket->State = SOCKET_STATE_BOUND;
+ }
+ }
+ break;
+
+ case SOCK_DGRAM:
+ //
+ // Already connected
+ //
+ pSocket->errno = EISCONN;
+ Status = EFI_ALREADY_STARTED;
+ break;
+ }
+ break;
+ }
+ break;
+
+ case SOCKET_STATE_CONNECTED:
+ //
+ // Already connected
+ //
+ pSocket->errno = EISCONN;
+ Status = EFI_ALREADY_STARTED;
+ break;
+ }
+
+ //
+ // Release the socket layer synchronization
+ //
+ RESTORE_TPL ( TplPrevious );
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ if ( NULL != pErrno ) {
+ if ( NULL != pSocket ) {
+ *pErrno = pSocket->errno;
+ }
+ else
+ {
+ //
+ // Bad socket protocol
+ //
+ DEBUG (( DEBUG_ERROR | DEBUG_CONNECT,
+ "ERROR - pSocketProtocol invalid!\r\n" ));
+ Status = EFI_INVALID_PARAMETER;
+ *pErrno = EBADF;
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ DEBUG (( DEBUG_CONNECT, "Exiting SocketConnect, Status: %r\r\n", Status ));
+ return Status;
+}
+
+
+/**
+ Creates a child handle and installs a protocol.
+
+ The CreateChild() function installs a protocol on ChildHandle.
+ If pChildHandle is a pointer to NULL, then a new handle is created and returned in pChildHandle.
+ If pChildHandle is not a pointer to NULL, then the protocol installs on the existing pChildHandle.
+
+ @param [in] pThis Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param [in] pChildHandle Pointer to the handle of the child to create. If it is NULL,
+ then a new handle is created. If it is a pointer to an existing UEFI handle,
+ then the protocol is added to the existing UEFI handle.
+
+ @retval EFI_SUCCESS The protocol was added to ChildHandle.
+ @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
+ the child
+ @retval other The child handle was not created
+
+**/
+EFI_STATUS
+EFIAPI
+EslSocketCreateChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL * pThis,
+ IN OUT EFI_HANDLE * pChildHandle
+ )
+{
+ DT_SOCKET * pSocket;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Create a socket structure
+ //
+ Status = EslSocketAllocate ( pChildHandle,
+ DEBUG_SOCKET,
+ &pSocket );
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Destroys a child handle with a protocol installed on it.
+
+ The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
+ that was installed by CreateChild() from ChildHandle. If the removed protocol is the
+ last protocol on ChildHandle, then ChildHandle is destroyed.
+
+ @param [in] pThis Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param [in] ChildHandle Handle of the child to destroy
+
+ @retval EFI_SUCCESS The protocol was removed from ChildHandle.
+ @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
+ @retval EFI_INVALID_PARAMETER Child handle is not a valid UEFI Handle.
+ @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
+ because its services are being used.
+ @retval other The child handle was not destroyed
+
+**/
+EFI_STATUS
+EFIAPI
+EslSocketDestroyChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL * pThis,
+ IN EFI_HANDLE ChildHandle
+ )
+{
+ DT_LAYER * pLayer;
+ DT_SOCKET * pSocket;
+ DT_SOCKET * pSocketPrevious;
+ EFI_SOCKET_PROTOCOL * pSocketProtocol;
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+
+ DBG_ENTER ( );
+
+ //
+ // Locate the socket control structure
+ //
+ pLayer = &mEslLayer;
+ Status = gBS->OpenProtocol (
+ ChildHandle,
+ &gEfiSocketProtocolGuid,
+ (VOID **)&pSocketProtocol,
+ pLayer->ImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if ( !EFI_ERROR ( Status )) {
+ pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
+
+ //
+ // Synchronize with the socket layer
+ //
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );
+
+ //
+ // Walk the socket list
+ //
+ pSocketPrevious = pLayer->pSocketList;
+ if ( NULL != pSocketPrevious ) {
+ if ( pSocket == pSocketPrevious ) {
+ //
+ // Remove the socket from the head of the list
+ //
+ pLayer->pSocketList = pSocket->pNext;
+ }
+ else {
+ //
+ // Find the socket in the middle of the list
+ //
+ while (( NULL != pSocketPrevious )
+ && ( pSocket != pSocketPrevious->pNext )) {
+ //
+ // Set the next socket
+ //
+ pSocketPrevious = pSocketPrevious->pNext;
+ }
+ if ( NULL != pSocketPrevious ) {
+ //
+ // Remove the socket from the middle of the list
+ //
+ pSocketPrevious = pSocket->pNext;
+ }
+ }
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_POOL,
+ "ERROR - Socket list is empty!\r\n" ));
+ }
+
+ //
+ // Release the socket layer synchronization
+ //
+ RESTORE_TPL ( TplPrevious );
+
+ //
+ // Determine if the socket was found
+ //
+ if ( NULL != pSocketPrevious ) {
+ pSocket->pNext = NULL;
+
+ //
+ // Remove the socket protocol
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ ChildHandle,
+ &gEfiSocketProtocolGuid,
+ &pSocket->SocketProtocol,
+ NULL );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_POOL | DEBUG_INFO,
+ "Removed: gEfiSocketProtocolGuid from 0x%08x\r\n",
+ ChildHandle ));
+
+ //
+ // Free the socket structure
+ //
+ Status = gBS->FreePool ( pSocket );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_POOL,
+ "0x%08x: Free pSocket, %d bytes\r\n",
+ pSocket,
+ sizeof ( *pSocket )));
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_POOL,
+ "ERROR - Failed to free pSocket 0x%08x, Status: %r\r\n",
+ pSocket,
+ Status ));
+ }
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INFO,
+ "ERROR - Failed to remove gEfiSocketProtocolGuid from 0x%08x, Status: %r\r\n",
+ ChildHandle,
+ Status ));
+ }
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_INFO,
+ "ERROR - The socket was not in the socket list!\r\n" ));
+ Status = EFI_NOT_FOUND;
+ }
+ }
+ else {
+ DEBUG (( DEBUG_ERROR,
+ "ERROR - Failed to open socket protocol on 0x%08x, Status; %r\r\n",
+ ChildHandle,
+ Status ));
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Get the local address.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [out] pAddress Network address to receive the local system address
+
+ @param [in,out] pAddressLength Length of the local network address structure
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Local address successfully returned
+
+ **/
+EFI_STATUS
+EslSocketGetLocalAddress (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ OUT struct sockaddr * pAddress,
+ IN OUT socklen_t * pAddressLength,
+ IN int * pErrno
+ )
+{
+ DT_SOCKET * pSocket;
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume success
+ //
+ Status = EFI_SUCCESS;
+
+ //
+ // Validate the socket
+ //
+ pSocket = NULL;
+ if ( NULL != pSocketProtocol ) {
+ pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
+
+ //
+ // Verify the address buffer and length address
+ //
+ if (( NULL != pAddress ) && ( NULL != pAddressLength )) {
+ //
+ // Verify the socket state
+ //
+ if ( SOCKET_STATE_CONNECTED == pSocket->State ) {
+ //
+ // Synchronize with the socket layer
+ //
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );
+
+ //
+ // Validate the local address
+ //
+ switch ( pSocket->Domain ) {
+ default:
+ DEBUG (( DEBUG_RX,
+ "ERROR - Invalid socket address family: %d\r\n",
+ pSocket->Domain ));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case AF_INET:
+ //
+ // Determine the connection point within the network stack
+ //
+ switch ( pSocket->Type ) {
+ default:
+ DEBUG (( DEBUG_RX,
+ "ERROR - Invalid socket type: %d\r\n",
+ pSocket->Type));
+ Status = EFI_INVALID_PARAMETER;
+ break;
+
+ case SOCK_STREAM:
+ case SOCK_SEQPACKET:
+ //
+ // Get the local address
+ //
+ Status = EslTcpGetLocalAddress4 ( pSocket,
+ pAddress,
+ pAddressLength );
+ break;
+
+ case SOCK_DGRAM:
+ //
+ // Get the local address
+ //
+ Status = EslUdpGetLocalAddress4 ( pSocket,
+ pAddress,
+ pAddressLength );
+ break;
+ }
+ break;
+ }
+
+ //
+ // Release the socket layer synchronization
+ //
+ RESTORE_TPL ( TplPrevious );
+ }
+ else {
+ pSocket->errno = ENOTCONN;
+ Status = EFI_NOT_STARTED;
+ }
+ }
+ else {
+ pSocket->errno = EINVAL;
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ if ( NULL != pErrno ) {
+ if ( NULL != pSocket ) {
+ *pErrno = pSocket->errno;
+ }
+ else
+ {
+ Status = EFI_INVALID_PARAMETER;
+ *pErrno = EBADF;
+ }
+ }
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Get the peer address.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [out] pAddress Network address to receive the remote system address
+
+ @param [in,out] pAddressLength Length of the remote network address structure
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Remote address successfully returned
+
+ **/
+EFI_STATUS
+EslSocketGetPeerAddress (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ OUT struct sockaddr * pAddress,
+ IN OUT socklen_t * pAddressLength,
+ IN int * pErrno
+ )
+{
+ DT_SOCKET * pSocket;
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume success
+ //
+ Status = EFI_SUCCESS;
+
+ //
+ // Validate the socket
+ //
+ pSocket = NULL;
+ if ( NULL != pSocketProtocol ) {
+ pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
+
+ //
+ // Verify the address buffer and length address
+ //
+ if (( NULL != pAddress ) && ( NULL != pAddressLength )) {
+ //
+ // Verify the socket state
+ //
+ if ( SOCKET_STATE_CONNECTED == pSocket->State ) {
+ //
+ // Synchronize with the socket layer
+ //
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );
+
+ //
+ // Validate the local address
+ //
+ switch ( pSocket->Domain ) {
+ default:
+ DEBUG (( DEBUG_RX,
+ "ERROR - Invalid socket address family: %d\r\n",
+ pSocket->Domain ));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case AF_INET:
+ //
+ // Determine the connection point within the network stack
+ //
+ switch ( pSocket->Type ) {
+ default:
+ DEBUG (( DEBUG_RX,
+ "ERROR - Invalid socket type: %d\r\n",
+ pSocket->Type));
+ Status = EFI_INVALID_PARAMETER;
+ break;
+
+ case SOCK_STREAM:
+ case SOCK_SEQPACKET:
+ //
+ // Verify the port state
+ //
+ Status = EslTcpGetRemoteAddress4 ( pSocket,
+ pAddress,
+ pAddressLength );
+ break;
+
+ case SOCK_DGRAM:
+ //
+ // Verify the port state
+ //
+ Status = EslUdpGetRemoteAddress4 ( pSocket,
+ pAddress,
+ pAddressLength );
+ break;
+ }
+ break;
+ }
+
+ //
+ // Release the socket layer synchronization
+ //
+ RESTORE_TPL ( TplPrevious );
+ }
+ else {
+ pSocket->errno = ENOTCONN;
+ Status = EFI_NOT_STARTED;
+ }
+ }
+ else {
+ pSocket->errno = EINVAL;
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ if ( NULL != pErrno ) {
+ if ( NULL != pSocket ) {
+ *pErrno = pSocket->errno;
+ }
+ else
+ {
+ Status = EFI_INVALID_PARAMETER;
+ *pErrno = EBADF;
+ }
+ }
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Establish the known port to listen for network connections.
+
+ The ::SocketListen routine places the port into a state that enables connection
+ attempts. Connections are placed into FIFO order in a queue to be serviced
+ by the application. The application calls the ::SocketAccept routine to remove
+ the next connection from the queue and get the associated socket. The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html">POSIX</a>
+ documentation for the listen routine is available online for reference.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [in] Backlog Backlog specifies the maximum FIFO depth for
+ the connections waiting for the application
+ to call accept. Connection attempts received
+ while the queue is full are refused.
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket successfully created
+ @retval Other - Failed to enable the socket for listen
+
+**/
+EFI_STATUS
+EslSocketListen (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN INT32 Backlog,
+ OUT int * pErrno
+ )
+{
+ DT_SOCKET * pSocket;
+ EFI_STATUS Status;
+ EFI_STATUS TempStatus;
+ EFI_TPL TplPrevious;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume success
+ //
+ Status = EFI_SUCCESS;
+
+ //
+ // Validate the socket
+ //
+ pSocket = NULL;
+ if ( NULL != pSocketProtocol ) {
+ pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
+
+ //
+ // Assume success
+ //
+ pSocket->Status = EFI_SUCCESS;
+ pSocket->errno = 0;
+
+ //
+ // Verify that the bind operation was successful
+ //
+ if ( SOCKET_STATE_BOUND == pSocket->State ) {
+ //
+ // Synchronize with the socket layer
+ //
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );
+
+ //
+ // Create the event for SocketAccept completion
+ //
+ Status = gBS->CreateEvent ( 0,
+ TplPrevious,
+ NULL,
+ NULL,
+ &pSocket->WaitAccept );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_POOL,
+ "0x%08x: Created WaitAccept event\r\n",
+ pSocket->WaitAccept ));
+ //
+ // Set the maximum FIFO depth
+ //
+ if ( 0 >= Backlog ) {
+ Backlog = MAX_PENDING_CONNECTIONS;
+ }
+ else {
+ if ( SOMAXCONN < Backlog ) {
+ Backlog = SOMAXCONN;
+ }
+ else {
+ pSocket->MaxFifoDepth = Backlog;
+ }
+ }
+
+ //
+ // Validate the local address
+ //
+ switch ( pSocket->Domain ) {
+ default:
+ DEBUG (( DEBUG_BIND,
+ "ERROR - Invalid socket address family: %d\r\n",
+ pSocket->Domain ));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case AF_INET:
+ //
+ // Determine the connection point within the network stack
+ //
+ switch ( pSocket->Type ) {
+ default:
+ DEBUG (( DEBUG_BIND,
+ "ERROR - Invalid socket type: %d\r\n",
+ pSocket->Type));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case SOCK_STREAM:
+ case SOCK_SEQPACKET:
+ Status = EslTcpListen4 ( pSocket );
+ break;
+
+/*
+ case SOCK_DGRAM:
+ Status = UdpListen4 ( pSocket );
+ break;
+*/
+ }
+ break;
+ }
+
+ //
+ // Place the socket in the listen state if successful
+ //
+ if ( !EFI_ERROR ( Status )) {
+ pSocket->State = SOCKET_STATE_LISTENING;
+ }
+ else {
+ //
+ // Not waiting for SocketAccept to complete
+ //
+ TempStatus = gBS->CloseEvent ( pSocket->WaitAccept );
+ if ( !EFI_ERROR ( TempStatus )) {
+ DEBUG (( DEBUG_POOL,
+ "0x%08x: Closed WaitAccept event\r\n",
+ pSocket->WaitAccept ));
+ pSocket->WaitAccept = NULL;
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_POOL,
+ "ERROR - Failed to close WaitAccept event, Status: %r\r\n",
+ TempStatus ));
+ ASSERT ( EFI_SUCCESS == TempStatus );
+ }
+ }
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_LISTEN,
+ "ERROR - Failed to create the WaitAccept event, Status: %r\r\n",
+ Status ));
+ pSocket->errno = ENOMEM;
+ }
+
+ //
+ // Release the socket layer synchronization
+ //
+ RESTORE_TPL ( TplPrevious );
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_LISTEN,
+ "ERROR - Bind operation must be performed first!\r\n" ));
+ pSocket->errno = EDESTADDRREQ;
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ if ( NULL != pErrno ) {
+ if ( NULL != pSocket ) {
+ *pErrno = pSocket->errno;
+ }
+ else
+ {
+ Status = EFI_INVALID_PARAMETER;
+ *pErrno = EBADF;
+ }
+ }
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Get the socket options
+
+ Retrieve the socket options one at a time by name. The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html">POSIX</a>
+ documentation is available online.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+ @param [in] level Option protocol level
+ @param [in] OptionName Name of the option
+ @param [out] pOptionValue Buffer to receive the option value
+ @param [in,out] pOptionLength Length of the buffer in bytes,
+ upon return length of the option value in bytes
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket data successfully received
+
+ **/
+EFI_STATUS
+EslSocketOptionGet (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN int level,
+ IN int OptionName,
+ OUT void * __restrict pOptionValue,
+ IN OUT socklen_t * __restrict pOptionLength,
+ IN int * pErrno
+ )
+{
+ int errno;
+ socklen_t LengthInBytes;
+ socklen_t MaxBytes;
+ UINT8 * pOptionData;
+ DT_SOCKET * pSocket;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume failure
+ //
+ errno = EINVAL;
+ Status = EFI_INVALID_PARAMETER;
+
+ //
+ // Validate the socket
+ //
+ pSocket = NULL;
+ if (( NULL != pSocketProtocol )
+ && ( NULL != pOptionValue )
+ && ( NULL != pOptionLength )) {
+ pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
+ LengthInBytes = 0;
+ MaxBytes = *pOptionLength;
+ pOptionData = NULL;
+ switch ( level ) {
+ default:
+ //
+ // Protocol level not supported
+ //
+ errno = ENOTSUP;
+ Status = EFI_UNSUPPORTED;
+ break;
+
+ case SOL_SOCKET:
+ switch ( OptionName ) {
+ default:
+ //
+ // Option not supported
+ //
+ errno = ENOTSUP;
+ Status = EFI_UNSUPPORTED;
+ break;
+
+ case SO_RCVTIMEO:
+ //
+ // Return the receive timeout
+ //
+ pOptionData = (UINT8 *)&pSocket->RxTimeout;
+ LengthInBytes = sizeof ( pSocket->RxTimeout );
+ break;
+
+ case SO_RCVBUF:
+ //
+ // Return the maximum transmit buffer size
+ //
+ pOptionData = (UINT8 *)&pSocket->MaxRxBuf;
+ LengthInBytes = sizeof ( pSocket->MaxRxBuf );
+ break;
+
+ case SO_SNDBUF:
+ //
+ // Return the maximum transmit buffer size
+ //
+ pOptionData = (UINT8 *)&pSocket->MaxTxBuf;
+ LengthInBytes = sizeof ( pSocket->MaxTxBuf );
+ break;
+
+ case SO_TYPE:
+ //
+ // Return the socket type
+ //
+ pOptionData = (UINT8 *)&pSocket->Type;
+ LengthInBytes = sizeof ( pSocket->Type );
+ break;
+ }
+ break;
+ }
+
+ //
+ // Return the option length
+ //
+ *pOptionLength = LengthInBytes;
+
+ //
+ // Return the option value
+ //
+ if ( NULL != pOptionData ) {
+ //
+ // Silently truncate the value length
+ //
+ if ( LengthInBytes > MaxBytes ) {
+ LengthInBytes = MaxBytes;
+ }
+ CopyMem ( pOptionValue, pOptionData, LengthInBytes );
+ errno = 0;
+ Status = EFI_SUCCESS;
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ if ( NULL != pErrno ) {
+ *pErrno = errno;
+ }
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Set the socket options
+
+ Adjust the socket options one at a time by name. The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html">POSIX</a>
+ documentation is available online.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+ @param [in] level Option protocol level
+ @param [in] OptionName Name of the option
+ @param [in] pOptionValue Buffer containing the option value
+ @param [in] OptionLength Length of the buffer in bytes
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket data successfully received
+
+ **/
+EFI_STATUS
+EslSocketOptionSet (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN int level,
+ IN int OptionName,
+ IN CONST void * pOptionValue,
+ IN socklen_t OptionLength,
+ IN int * pErrno
+ )
+{
+ int errno;
+ socklen_t LengthInBytes;
+ UINT8 * pOptionData;
+ DT_SOCKET * pSocket;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume failure
+ //
+ errno = EINVAL;
+ Status = EFI_INVALID_PARAMETER;
+
+ //
+ // Validate the socket
+ //
+ pSocket = NULL;
+ if (( NULL != pSocketProtocol )
+ && ( NULL != pOptionValue )) {
+ pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
+ LengthInBytes = 0;
+ pOptionData = NULL;
+ switch ( level ) {
+ default:
+ //
+ // Protocol level not supported
+ //
+ errno = ENOTSUP;
+ Status = EFI_UNSUPPORTED;
+ break;
+
+ case SOL_SOCKET:
+ switch ( OptionName ) {
+ default:
+ //
+ // Option not supported
+ //
+ errno = ENOTSUP;
+ Status = EFI_UNSUPPORTED;
+ break;
+
+ case SO_RCVTIMEO:
+ //
+ // Return the receive timeout
+ //
+ pOptionData = (UINT8 *)&pSocket->RxTimeout;
+ LengthInBytes = sizeof ( pSocket->RxTimeout );
+ break;
+
+ case SO_RCVBUF:
+ //
+ // Return the maximum transmit buffer size
+ //
+ pOptionData = (UINT8 *)&pSocket->MaxRxBuf;
+ LengthInBytes = sizeof ( pSocket->MaxRxBuf );
+ break;
+
+ case SO_SNDBUF:
+ //
+ // Send buffer size
+ //
+ //
+ // Return the maximum transmit buffer size
+ //
+ pOptionData = (UINT8 *)&pSocket->MaxTxBuf;
+ LengthInBytes = sizeof ( pSocket->MaxTxBuf );
+ break;
+ }
+ break;
+ }
+
+ //
+ // Validate the option length
+ //
+ if ( LengthInBytes <= OptionLength ) {
+ //
+ // Set the option value
+ //
+ if ( NULL != pOptionData ) {
+ CopyMem ( pOptionData, pOptionValue, LengthInBytes );
+ errno = 0;
+ Status = EFI_SUCCESS;
+ }
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ if ( NULL != pErrno ) {
+ *pErrno = errno;
+ }
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Allocate a packet for a receive or transmit operation
+
+ @param [in] ppPacket Address to receive the DT_PACKET structure
+ @param [in] LengthInBytes Length of the packet structure
+ @param [in] DebugFlags Flags for debug messages
+
+ @retval EFI_SUCCESS - The packet was allocated successfully
+
+ **/
+EFI_STATUS
+EslSocketPacketAllocate (
+ IN DT_PACKET ** ppPacket,
+ IN size_t LengthInBytes,
+ IN UINTN DebugFlags
+ )
+{
+ DT_PACKET * pPacket;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Allocate a packet structure
+ //
+ LengthInBytes += sizeof ( *pPacket )
+ - sizeof ( pPacket->Op );
+ Status = gBS->AllocatePool ( EfiRuntimeServicesData,
+ LengthInBytes,
+ (VOID **)&pPacket );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT,
+ "0x%08x: Allocate pPacket, %d bytes\r\n",
+ pPacket,
+ LengthInBytes ));
+ pPacket->PacketSize = LengthInBytes;
+ }
+ else {
+ DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INFO,
+ "ERROR - Packet allocation failed for %d bytes, Status: %r\r\n",
+ LengthInBytes,
+ Status ));
+ pPacket = NULL;
+ }
+
+ //
+ // Return the packet
+ //
+ *ppPacket = pPacket;
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Free a packet used for receive or transmit operation
+
+ @param [in] pPacket Address of the DT_PACKET structure
+ @param [in] DebugFlags Flags for debug messages
+
+ @retval EFI_SUCCESS - The packet was allocated successfully
+
+ **/
+EFI_STATUS
+EslSocketPacketFree (
+ IN DT_PACKET * pPacket,
+ IN UINTN DebugFlags
+ )
+{
+ UINTN LengthInBytes;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Allocate a packet structure
+ //
+ LengthInBytes = pPacket->PacketSize;
+ Status = gBS->FreePool ( pPacket );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DebugFlags | DEBUG_POOL,
+ "0x%08x: Free pPacket, %d bytes\r\n",
+ pPacket,
+ LengthInBytes ));
+ }
+ else {
+ DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INFO,
+ "ERROR - Failed to free packet 0x%08x, Status: %r\r\n",
+ pPacket,
+ Status ));
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Poll a socket for pending activity.
+
+ The SocketPoll routine checks a socket for pending activity associated
+ with the event mask. Activity is returned in the detected event buffer.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [in] Events Events of interest for this socket
+
+ @param [in] pEvents Address to receive the detected events
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket successfully polled
+ @retval EFI_INVALID_PARAMETER - When pEvents is NULL
+
+ **/
+EFI_STATUS
+EslSocketPoll (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN short Events,
+ IN short * pEvents,
+ IN int * pErrno
+ )
+{
+ short DetectedEvents;
+ DT_SOCKET * pSocket;
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+ short ValidEvents;
+
+ DEBUG (( DEBUG_POLL, "Entering SocketPoll\r\n" ));
+
+ //
+ // Assume success
+ //
+ Status = EFI_SUCCESS;
+ DetectedEvents = 0;
+ pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
+ pSocket->errno = 0;
+
+ //
+ // Verify the socket state
+ //
+ if ( !pSocket->bConfigured ) {
+ //
+ // Synchronize with the socket layer
+ //
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );
+
+ //
+ // Validate the local address
+ //
+ switch ( pSocket->Domain ) {
+ default:
+ DEBUG (( DEBUG_RX,
+ "ERROR - Invalid socket address family: %d\r\n",
+ pSocket->Domain ));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case AF_INET:
+ //
+ // Determine the connection point within the network stack
+ //
+ switch ( pSocket->Type ) {
+ default:
+ DEBUG (( DEBUG_RX,
+ "ERROR - Invalid socket type: %d\r\n",
+ pSocket->Type));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case SOCK_STREAM:
+ case SOCK_SEQPACKET:
+ //
+ // Verify the port state
+ //
+ Status = EslTcpSocketIsConfigured4 ( pSocket );
+ break;
+
+ case SOCK_DGRAM:
+ //
+ // Verify the port state
+ //
+ Status = EslUdpSocketIsConfigured4 ( pSocket );
+ break;
+ }
+ break;
+ }
+
+ //
+ // Release the socket layer synchronization
+ //
+ RESTORE_TPL ( TplPrevious );
+ }
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Check for invalid events
+ //
+ ValidEvents = POLLIN
+ | POLLPRI
+ | POLLOUT | POLLWRNORM
+ | POLLERR
+ | POLLHUP
+ | POLLNVAL
+ | POLLRDNORM
+ | POLLRDBAND
+ | POLLWRBAND ;
+ if ( 0 != ( Events & ( ~ValidEvents ))) {
+ DetectedEvents |= POLLNVAL;
+ DEBUG (( DEBUG_INFO | DEBUG_POLL,
+ "ERROR - Invalid event mask, Valid Events: 0x%04x, Invalid Events: 0x%04x\r\n",
+ Events & ValidEvents,
+ Events & ( ~ValidEvents )));
+ }
+ else {
+ //
+ // Check for pending connections
+ //
+ if ( 0 != pSocket->FifoDepth ) {
+ //
+ // A connection is waiting for an accept call
+ // See posix connect documentation at
+ // http://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.htm
+ //
+ DetectedEvents |= POLLIN | POLLRDNORM;
+ }
+ if ( pSocket->bConnected ) {
+ //
+ // A connection is present
+ // See posix connect documentation at
+ // http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.htm
+ //
+ DetectedEvents |= POLLOUT | POLLWRNORM;
+ }
+
+ //
+ // The following bits are set based upon the POSIX poll documentation at
+ // http://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html
+ //
+
+ //
+ // Check for urgent receive data
+ //
+ if ( 0 < pSocket->RxOobBytes ) {
+ DetectedEvents |= POLLRDBAND | POLLPRI | POLLIN;
+ }
+
+ //
+ // Check for normal receive data
+ //
+ if (( 0 < pSocket->RxBytes )
+ || ( EFI_SUCCESS != pSocket->RxError )) {
+ DetectedEvents |= POLLRDNORM | POLLIN;
+ }
+
+ //
+ // Handle the receive errors
+ //
+ if (( EFI_SUCCESS != pSocket->RxError )
+ && ( 0 == ( DetectedEvents & POLLIN ))) {
+ DetectedEvents |= POLLERR | POLLIN | POLLRDNORM | POLLRDBAND;
+ }
+
+ //
+ // Check for urgent transmit data buffer space
+ //
+ if (( MAX_TX_DATA > pSocket->TxOobBytes )
+ || ( EFI_SUCCESS != pSocket->TxError )) {
+ DetectedEvents |= POLLWRBAND;
+ }
+
+ //
+ // Check for normal transmit data buffer space
+ //
+ if (( MAX_TX_DATA > pSocket->TxBytes )
+ || ( EFI_SUCCESS != pSocket->TxError )) {
+ DetectedEvents |= POLLWRNORM;
+ }
+
+ //
+ // Handle the transmit error
+ //
+ if ( EFI_ERROR ( pSocket->TxError )) {
+ DetectedEvents |= POLLERR;
+ }
+ }
+ }
+
+ //
+ // Return the detected events
+ //
+ *pEvents = DetectedEvents & ( Events
+ | POLLERR
+ | POLLHUP
+ | POLLNVAL );
+
+ //
+ // Return the operation status
+ //
+ DEBUG (( DEBUG_POLL, "Exiting SocketPoll, Status: %r\r\n", Status ));
+ return Status;
+}
+
+
+/**
+ Receive data from a network connection.
+
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [in] Flags Message control flags
+
+ @param [in] BufferLength Length of the the buffer
+
+ @param [in] pBuffer Address of a buffer to receive the data.
+
+ @param [in] pDataLength Number of received data bytes in the buffer.
+
+ @param [out] pAddress Network address to receive the remote system address
+
+ @param [in,out] pAddressLength Length of the remote network address structure
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket data successfully received
+
+ **/
+EFI_STATUS
+EslSocketReceive (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN INT32 Flags,
+ IN size_t BufferLength,
+ IN UINT8 * pBuffer,
+ OUT size_t * pDataLength,
+ OUT struct sockaddr * pAddress,
+ IN OUT socklen_t * pAddressLength,
+ IN int * pErrno
+ )
+{
+ DT_SOCKET * pSocket;
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume success
+ //
+ Status = EFI_SUCCESS;
+
+ //
+ // Validate the socket
+ //
+ pSocket = NULL;
+ if ( NULL != pSocketProtocol ) {
+ pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
+
+ //
+ // Verify the socket state
+ //
+ if ( !pSocket->bConfigured ) {
+ //
+ // Synchronize with the socket layer
+ //
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );
+
+ //
+ // Validate the local address
+ //
+ switch ( pSocket->Domain ) {
+ default:
+ DEBUG (( DEBUG_RX,
+ "ERROR - Invalid socket address family: %d\r\n",
+ pSocket->Domain ));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case AF_INET:
+ //
+ // Determine the connection point within the network stack
+ //
+ switch ( pSocket->Type ) {
+ default:
+ DEBUG (( DEBUG_RX,
+ "ERROR - Invalid socket type: %d\r\n",
+ pSocket->Type));
+ Status = EFI_INVALID_PARAMETER;
+ break;
+
+ case SOCK_STREAM:
+ case SOCK_SEQPACKET:
+ //
+ // Verify the port state
+ //
+ Status = EslTcpSocketIsConfigured4 ( pSocket );
+ break;
+
+ case SOCK_DGRAM:
+ //
+ // Verify the port state
+ //
+ Status = EslUdpSocketIsConfigured4 ( pSocket );
+ break;
+ }
+ break;
+ }
+
+ //
+ // Release the socket layer synchronization
+ //
+ RESTORE_TPL ( TplPrevious );
+
+ //
+ // Set errno if a failure occurs
+ //
+ if ( EFI_ERROR ( Status )) {
+ pSocket->errno = EADDRNOTAVAIL;
+ }
+ }
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Validate the buffer length
+ //
+ if (( NULL == pDataLength )
+ && ( 0 > pDataLength )
+ && ( NULL == pBuffer )) {
+ if ( NULL == pDataLength ) {
+ DEBUG (( DEBUG_RX,
+ "ERROR - pDataLength is NULL!\r\n" ));
+ }
+ else if ( NULL == pBuffer ) {
+ DEBUG (( DEBUG_RX,
+ "ERROR - pBuffer is NULL!\r\n" ));
+ }
+ else {
+ DEBUG (( DEBUG_RX,
+ "ERROR - Data length < 0!\r\n" ));
+ }
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EFAULT;
+ }
+ else{
+ //
+ // Synchronize with the socket layer
+ //
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );
+
+ //
+ // Validate the local address
+ //
+ switch ( pSocket->Domain ) {
+ default:
+ DEBUG (( DEBUG_RX,
+ "ERROR - Invalid socket address family: %d\r\n",
+ pSocket->Domain ));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case AF_INET:
+ //
+ // Determine the connection point within the network stack
+ //
+ switch ( pSocket->Type ) {
+ default:
+ DEBUG (( DEBUG_RX,
+ "ERROR - Invalid socket type: %d\r\n",
+ pSocket->Type));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case SOCK_STREAM:
+ case SOCK_SEQPACKET:
+ Status = EslTcpReceive4 ( pSocket,
+ Flags,
+ BufferLength,
+ pBuffer,
+ pDataLength,
+ pAddress,
+ pAddressLength );
+ break;
+
+ case SOCK_DGRAM:
+ Status = EslUdpReceive4 ( pSocket,
+ Flags,
+ BufferLength,
+ pBuffer,
+ pDataLength,
+ pAddress,
+ pAddressLength);
+ break;
+ }
+ break;
+ }
+
+ //
+ // Release the socket layer synchronization
+ //
+ RESTORE_TPL ( TplPrevious );
+ }
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ if ( NULL != pErrno ) {
+ if ( NULL != pSocket ) {
+ *pErrno = pSocket->errno;
+ }
+ else
+ {
+ Status = EFI_INVALID_PARAMETER;
+ *pErrno = EBADF;
+ }
+ }
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Shutdown the socket receive and transmit operations
+
+ The SocketShutdown routine stops the socket receive and transmit
+ operations.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [in] How Which operations to stop
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket operations successfully shutdown
+
+ **/
+EFI_STATUS
+EslSocketShutdown (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN int How,
+ IN int * pErrno
+ )
+{
+ DT_SOCKET * pSocket;
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume success
+ //
+ Status = EFI_SUCCESS;
+
+ //
+ // Validate the socket
+ //
+ pSocket = NULL;
+ if ( NULL != pSocketProtocol ) {
+ pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
+
+ //
+ // Verify that the socket is connected
+ //
+ if ( pSocket->bConnected ) {
+ //
+ // Validate the How value
+ //
+ if (( SHUT_RD <= How ) && ( SHUT_RDWR >= How )) {
+ //
+ // Synchronize with the socket layer
+ //
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );
+
+ //
+ // Disable the receiver if requested
+ //
+ if (( SHUT_RD == How ) || ( SHUT_RDWR == How )) {
+ pSocket->bRxDisable = TRUE;
+ }
+
+ //
+ // Disable the transmitter if requested
+ //
+ if (( SHUT_WR == How ) || ( SHUT_RDWR == How )) {
+ pSocket->bTxDisable = TRUE;
+ }
+
+ //
+ // Validate the local address
+ //
+ switch ( pSocket->Domain ) {
+ default:
+ DEBUG (( DEBUG_RX,
+ "ERROR - Invalid socket address family: %d\r\n",
+ pSocket->Domain ));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case AF_INET:
+ //
+ // Determine the connection point within the network stack
+ //
+ switch ( pSocket->Type ) {
+ default:
+ DEBUG (( DEBUG_RX,
+ "ERROR - Invalid socket type: %d\r\n",
+ pSocket->Type));
+ Status = EFI_INVALID_PARAMETER;
+ break;
+
+ case SOCK_STREAM:
+ case SOCK_SEQPACKET:
+ //
+ // Cancel the pending receive operation
+ //
+ Status = EslTcpRxCancel4 ( pSocket );
+ break;
+
+ case SOCK_DGRAM:
+ //
+ // Cancel the pending receive operation
+ //
+ Status = EslUdpRxCancel4 ( pSocket );
+ break;
+ }
+ break;
+ }
+
+ //
+ // Release the socket layer synchronization
+ //
+ RESTORE_TPL ( TplPrevious );
+ }
+ else {
+ //
+ // The socket is not connected
+ //
+ pSocket->errno = ENOTCONN;
+ Status = EFI_NOT_STARTED;
+ }
+ }
+ else {
+ //
+ // Invalid How value
+ //
+ pSocket->errno = EINVAL;
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ if ( NULL != pErrno ) {
+ if ( NULL != pSocket ) {
+ *pErrno = pSocket->errno;
+ }
+ else
+ {
+ Status = EFI_INVALID_PARAMETER;
+ *pErrno = EBADF;
+ }
+ }
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Send data using a network connection.
+
+ The SocketTransmit routine queues the data for transmission to the
+ remote network connection.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [in] Flags Message control flags
+
+ @param [in] BufferLength Length of the the buffer
+
+ @param [in] pBuffer Address of a buffer containing the data to send
+
+ @param [in] pDataLength Address to receive the number of data bytes sent
+
+ @param [in] pAddress Network address of the remote system address
+
+ @param [in] AddressLength Length of the remote network address structure
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket data successfully queued for transmit
+
+ **/
+EFI_STATUS
+EslSocketTransmit (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN int Flags,
+ IN size_t BufferLength,
+ IN CONST UINT8 * pBuffer,
+ OUT size_t * pDataLength,
+ IN const struct sockaddr * pAddress,
+ IN socklen_t AddressLength,
+ IN int * pErrno
+ )
+{
+ DT_SOCKET * pSocket;
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume success
+ //
+ Status = EFI_SUCCESS;
+
+ //
+ // Validate the socket
+ //
+ pSocket = NULL;
+ if ( NULL != pSocketProtocol ) {
+ pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
+
+ //
+ // Verify the socket state
+ //
+ if ( !pSocket->bConfigured ) {
+ //
+ // Synchronize with the socket layer
+ //
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );
+
+ //
+ // Validate the local address
+ //
+ switch ( pSocket->Domain ) {
+ default:
+ DEBUG (( DEBUG_RX,
+ "ERROR - Invalid socket address family: %d\r\n",
+ pSocket->Domain ));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case AF_INET:
+ //
+ // Determine the connection point within the network stack
+ //
+ switch ( pSocket->Type ) {
+ default:
+ DEBUG (( DEBUG_RX,
+ "ERROR - Invalid socket type: %d\r\n",
+ pSocket->Type));
+ Status = EFI_INVALID_PARAMETER;
+ break;
+
+ case SOCK_STREAM:
+ case SOCK_SEQPACKET:
+ //
+ // Verify the port state
+ //
+ Status = EslTcpSocketIsConfigured4 ( pSocket );
+ break;
+
+ case SOCK_DGRAM:
+ //
+ // Verify the port state
+ //
+ Status = EslUdpSocketIsConfigured4 ( pSocket );
+ break;
+ }
+ break;
+ }
+
+ //
+ // Release the socket layer synchronization
+ //
+ RESTORE_TPL ( TplPrevious );
+
+ //
+ // Set errno if a failure occurs
+ //
+ if ( EFI_ERROR ( Status )) {
+ pSocket->errno = EADDRNOTAVAIL;
+ }
+ }
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Verify that transmit is still allowed
+ //
+ if ( !pSocket->bTxDisable ) {
+ //
+ // Validate the buffer length
+ //
+ if (( NULL == pDataLength )
+ && ( 0 > pDataLength )
+ && ( NULL == pBuffer )) {
+ if ( NULL == pDataLength ) {
+ DEBUG (( DEBUG_RX,
+ "ERROR - pDataLength is NULL!\r\n" ));
+ }
+ else if ( NULL == pBuffer ) {
+ DEBUG (( DEBUG_RX,
+ "ERROR - pBuffer is NULL!\r\n" ));
+ }
+ else {
+ DEBUG (( DEBUG_RX,
+ "ERROR - Data length < 0!\r\n" ));
+ }
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EFAULT;
+ }
+ else {
+ //
+ // Validate the remote network address
+ //
+ if (( NULL != pAddress )
+ && ( AddressLength < pAddress->sa_len )) {
+ DEBUG (( DEBUG_TX,
+ "ERROR - Invalid sin_len field in address\r\n" ));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EFAULT;
+ }
+ else {
+ //
+ // Synchronize with the socket layer
+ //
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );
+
+ //
+ // Validate the local address
+ //
+ switch ( pSocket->Domain ) {
+ default:
+ DEBUG (( DEBUG_RX,
+ "ERROR - Invalid socket address family: %d\r\n",
+ pSocket->Domain ));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case AF_INET:
+ //
+ // Determine the connection point within the network stack
+ //
+ switch ( pSocket->Type ) {
+ default:
+ DEBUG (( DEBUG_RX,
+ "ERROR - Invalid socket type: %d\r\n",
+ pSocket->Type));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case SOCK_STREAM:
+ case SOCK_SEQPACKET:
+ Status = EslTcpTxBuffer4 ( pSocket,
+ Flags,
+ BufferLength,
+ pBuffer,
+ pDataLength );
+ break;
+
+ case SOCK_DGRAM:
+ Status = EslUdpTxBuffer4 ( pSocket,
+ Flags,
+ BufferLength,
+ pBuffer,
+ pDataLength,
+ pAddress,
+ AddressLength );
+ break;
+ }
+ break;
+ }
+
+ //
+ // Release the socket layer synchronization
+ //
+ RESTORE_TPL ( TplPrevious );
+ }
+ }
+ }
+ else {
+ //
+ // The transmitter was shutdown
+ //
+ pSocket->errno = EPIPE;
+ Status = EFI_NOT_STARTED;
+ }
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ if ( NULL != pErrno ) {
+ if ( NULL != pSocket ) {
+ *pErrno = pSocket->errno;
+ }
+ else
+ {
+ Status = EFI_INVALID_PARAMETER;
+ *pErrno = EBADF;
+ }
+ }
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Socket layer's service binding protocol delcaration.
+**/
+EFI_SERVICE_BINDING_PROTOCOL mEfiServiceBinding = {
+ EslSocketCreateChild,
+ EslSocketDestroyChild
+};
diff --git a/StdLib/EfiSocketLib/Socket.h b/StdLib/EfiSocketLib/Socket.h new file mode 100644 index 0000000000..42377eb29c --- /dev/null +++ b/StdLib/EfiSocketLib/Socket.h @@ -0,0 +1,1337 @@ +/** @file
+ Definitions for the Socket layer driver.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _SOCKET_H_
+#define _SOCKET_H_
+
+#include <Efi/EfiSocketLib.h>
+
+//------------------------------------------------------------------------------
+// Constants
+//------------------------------------------------------------------------------
+
+#define DEBUG_SOCKET 0x20000000 ///< Display Socket related messages
+#define DEBUG_BIND 0x10000000 ///< Display bind related messages
+#define DEBUG_LISTEN 0x08000000 ///< Display listen related messages
+#define DEBUG_CONNECTION 0x04000000 ///< Display connection list related messages
+#define DEBUG_POLL 0x02000000 ///< Display poll messages
+#define DEBUG_ACCEPT 0x01000000 ///< Display accept related messages
+#define DEBUG_RX 0x00800000 ///< Display receive messages
+#define DEBUG_TX 0x00400000 ///< Display transmit messages
+#define DEBUG_CLOSE 0x00200000 ///< Display close messages
+#define DEBUG_CONNECT 0x00100000 ///< Display connect messages
+
+#define MAX_PENDING_CONNECTIONS 1 ///< Maximum connection FIFO depth
+#define MAX_RX_DATA 65536 ///< Maximum receive data size
+#define MAX_TX_DATA ( MAX_RX_DATA * 2 )
+#define RX_PACKET_DATA 16384 ///< Maximum number of bytes in a RX packet
+
+#define LAYER_SIGNATURE SIGNATURE_32('S','k','t','L') ///< DT_LAYER memory signature
+#define SERVICE_SIGNATURE SIGNATURE_32('S','k','t','S') ///< DT_SERVICE memory signature
+#define SOCKET_SIGNATURE SIGNATURE_32('S','c','k','t') ///< DT_SOCKET memory signature
+#define PORT_SIGNATURE SIGNATURE_32('P','o','r','t') ///< DT_PORT memory signature
+
+typedef enum
+{
+ NETWORK_TYPE_UNKNOWN = 0,
+ NETWORK_TYPE_RAW,
+ NETWORK_TYPE_TCP4,
+ NETWORK_TYPE_TCP6,
+ NETWORK_TYPE_UDP4,
+ NETWORK_TYPE_UDP6
+} NETWORK_TYPE;
+
+typedef enum
+{
+ SOCKET_STATE_NOT_CONFIGURED = 0, ///< socket call was successful
+ SOCKET_STATE_BOUND, ///< bind call was successful
+ SOCKET_STATE_LISTENING, ///< listen call was successful
+ SOCKET_STATE_NO_PORTS, ///< No ports available
+ SOCKET_STATE_IN_FIFO, ///< Socket on FIFO
+ SOCKET_STATE_CONNECTING, ///< Connecting to a remote system
+ SOCKET_STATE_CONNECTED, ///< Accept or connect call was successful
+
+ //
+ // Close state must be the last in the list
+ //
+ SOCKET_STATE_CLOSED ///< Close call was successful
+} SOCKET_STATE;
+
+typedef enum
+{
+ PORT_STATE_ALLOCATED = 0, ///< Port allocated
+ PORT_STATE_OPEN, ///< Port opened
+ PORT_STATE_RX_ERROR, ///< Receive error detected
+
+ //
+ // Close state must be last in the list
+ //
+ PORT_STATE_CLOSE_STARTED, ///< Close started on port
+ PORT_STATE_CLOSE_TX_DONE, ///< Transmits shutdown
+ PORT_STATE_CLOSE_RX_DONE, ///< Receives shutdown
+ PORT_STATE_CLOSE_DONE ///< Port close operation complete
+} PORT_STATE;
+
+//------------------------------------------------------------------------------
+// Data Types
+//------------------------------------------------------------------------------
+
+typedef struct _DT_PACKET DT_PACKET; ///< Forward declaration
+typedef struct _DT_PORT DT_PORT; ///< Forward declaration
+typedef struct _DT_SOCKET DT_SOCKET; ///< Forward declaration
+
+typedef struct
+{
+ EFI_TCP4_RECEIVE_DATA RxData; ///< Receive operation description
+ size_t ValidBytes; ///< Length of valid data in bytes
+ UINT8 * pBuffer; ///< Current data pointer
+ UINT8 Buffer [ RX_PACKET_DATA ]; ///< Data buffer
+} DT_TCP4_RX_DATA;
+
+typedef struct
+{
+ EFI_TCP4_TRANSMIT_DATA TxData; ///< Transmit operation description
+ UINT8 Buffer [ 1 ]; ///< Data buffer
+} DT_TCP4_TX_DATA;
+
+typedef struct
+{
+ EFI_UDP4_SESSION_DATA Session; ///< * Remote network address
+ EFI_UDP4_RECEIVE_DATA * pRxData; ///< * Receive operation description
+} DT_UDP4_RX_DATA;
+
+typedef struct
+{
+ EFI_UDP4_SESSION_DATA Session; ///< Remote network address
+ EFI_UDP4_TRANSMIT_DATA TxData; ///< Transmit operation description
+ UINT8 Buffer [ 1 ]; ///< Data buffer
+} DT_UDP4_TX_DATA;
+
+typedef struct _DT_PACKET {
+ DT_PACKET * pNext; ///< Next packet in the receive list
+ size_t PacketSize; ///< Size of this data structure
+ union {
+ DT_TCP4_RX_DATA Tcp4Rx; ///< Receive operation description
+ DT_TCP4_TX_DATA Tcp4Tx; ///< Transmit operation description
+ DT_UDP4_RX_DATA Udp4Rx; ///< Receive operation description
+ DT_UDP4_TX_DATA Udp4Tx; ///< Transmit operation description
+ } Op;
+} GCC_DT_PACKET;
+
+/**
+ Service control structure
+
+ The driver uses this structure to manage the network devices.
+**/
+typedef struct _DT_SERVICE {
+ UINTN Signature; ///< Structure identification
+
+ //
+ // Links
+ //
+ DT_SERVICE * pNext; ///< Next service in the service list
+
+ //
+ // Service data
+ //
+ CONST DT_SOCKET_BINDING * pSocketBinding; ///< Name and shutdown routine
+ EFI_HANDLE Controller; ///< Controller for the service
+ VOID * pInterface; ///< Network layer service binding interface
+
+ //
+ // Network data
+ //
+ NETWORK_TYPE NetworkType; ///< Type of network service
+ DT_PORT * pPortList; ///< List of ports using this service
+}GCC_DT_SERVICE;
+
+/**
+ Start the close operation on a TCP4 port.
+
+ @param [in] pPort Address of the port structure.
+ @param [in] bAbort Set TRUE to abort active transfers
+ @param [in] DebugFlags Flags for debug messages
+
+**/
+typedef
+EFI_STATUS
+PFN_PORT_CLOSE_START (
+ IN DT_PORT * pPort,
+ IN BOOLEAN bAbort,
+ IN UINTN DebugFlags
+ );
+
+/**
+ TCP4 context structure
+
+ The driver uses this structure to manage the TCP4 connections.
+**/
+typedef struct {
+ //
+ // TCP4 context
+ //
+ EFI_HANDLE Handle; ///< TCP4 port handle
+ EFI_TCP4_PROTOCOL * pProtocol; ///< TCP4 protocol pointer
+ EFI_TCP4_CONFIG_DATA ConfigData; ///< TCP4 configuration data
+ EFI_TCP4_OPTION Option; ///< TCP4 port options
+ BOOLEAN bConfigured; ///< TRUE if configuration was successful
+
+ //
+ // Tokens
+ //
+ EFI_TCP4_LISTEN_TOKEN ListenToken; ///< Listen control
+ EFI_TCP4_CONNECTION_TOKEN ConnectToken; ///< Connection control
+ EFI_TCP4_CLOSE_TOKEN CloseToken; ///< Close control
+
+ //
+ // Receive data management
+ //
+ EFI_TCP4_IO_TOKEN RxToken; ///< Receive token
+ DT_PACKET * pReceivePending; ///< Receive operation in progress
+
+ //
+ // Transmit data management
+ //
+ EFI_TCP4_IO_TOKEN TxOobToken; ///< Urgent data token
+ DT_PACKET * pTxOobPacket; ///< Urgent data in progress
+
+ EFI_TCP4_IO_TOKEN TxToken; ///< Normal data token
+ DT_PACKET * pTxPacket; ///< Normal transmit in progress
+} DT_TCP4_CONTEXT;
+
+/**
+ UDP4 context structure
+
+ The driver uses this structure to manage the UDP4 connections.
+**/
+typedef struct {
+ //
+ // UDP4 context
+ //
+ EFI_HANDLE Handle; ///< UDP4 port handle
+ EFI_UDP4_PROTOCOL * pProtocol; ///< UDP4 protocol pointer
+ EFI_UDP4_CONFIG_DATA ConfigData; ///< UDP4 configuration data
+ BOOLEAN bConfigured; ///< TRUE if configuration was successful
+
+ //
+ // Receive data management
+ //
+ EFI_UDP4_COMPLETION_TOKEN RxToken;///< Receive token
+ DT_PACKET * pReceivePending; ///< Receive operation in progress
+
+ //
+ // Transmit data management
+ //
+ EFI_UDP4_COMPLETION_TOKEN TxToken;///< Transmit token
+ DT_PACKET * pTxPacket; ///< Transmit in progress
+} DT_UDP4_CONTEXT;
+
+
+/**
+ Port control structure
+
+ The driver uses this structure to manager the socket's connection
+ with the network driver.
+**/
+typedef struct _DT_PORT {
+ UINTN Signature; ///< Structure identification
+
+ //
+ // List links
+ //
+ DT_PORT * pLinkService; ///< Link in service port list
+ DT_PORT * pLinkSocket; ///< Link in socket port list
+
+ //
+ // Structures
+ //
+ DT_SERVICE * pService; ///< Service for this port
+ DT_SOCKET * pSocket; ///< Socket for this port
+// PFN_CLOSE_PORT pfnClosePort; ///< Routine to immediately close the port
+ PFN_PORT_CLOSE_START * pfnCloseStart; ///< Routine to start closing the port
+
+ //
+ // Protocol specific management data
+ //
+ PORT_STATE State; ///< State of the port
+ UINTN DebugFlags; ///< Debug flags used to close the port
+ BOOLEAN bCloseNow; ///< TRUE = Close the port immediately
+
+ union {
+ DT_TCP4_CONTEXT Tcp4; ///< TCPv4 management data
+ DT_UDP4_CONTEXT Udp4; ///< UDPv4 management data
+ } Context;
+}GCC_DT_PORT;
+
+/**
+ Socket control structure
+
+ The driver uses this structure to manage the socket.
+**/
+typedef struct _DT_SOCKET {
+ UINTN Signature; ///< Structure identification
+
+ //
+ // Protocol binding
+ //
+ EFI_SOCKET_PROTOCOL SocketProtocol; ///< Socket protocol declaration
+
+ //
+ // Socket management
+ //
+ DT_SOCKET * pNext; ///< Next socket in the list of sockets
+ int errno; ///< Error information for this socket
+ EFI_STATUS Status; ///< Asyncronous error information for this socket
+ SOCKET_STATE State; ///< Socket state
+
+ //
+ // Socket data
+ //
+ int Domain; ///< Specifies family of protocols
+ int Type; ///< Specifies how to make network connection
+ int Protocol; ///< Specifies lower layer protocol to use
+ BOOLEAN bConfigured; ///< Set after the socket is configured
+
+ BOOLEAN bRxDisable; ///< Receive disabled via shutdown
+ size_t RxBytes; ///< Total Rx bytes
+ size_t RxOobBytes; ///< Urgent Rx bytes
+ EFI_STATUS RxError; ///< Error during receive
+
+ BOOLEAN bTxDisable; ///< Transmit disabled via shutdown
+ size_t TxBytes; ///< Normal Tx bytes
+ size_t TxOobBytes; ///< Urgent Tx bytes
+ EFI_STATUS TxError; ///< Error during transmit
+
+ //
+ // Pending connection data
+ //
+ BOOLEAN bConnected; ///< Set when connected, cleared by poll
+ EFI_STATUS ConnectStatus; ///< Connection status
+ UINTN MaxFifoDepth; ///< Maximum FIFO depth
+ UINTN FifoDepth; ///< Number of sockets in the FIFO
+ DT_SOCKET * pFifoHead; ///< Head of the FIFO
+ DT_SOCKET * pFifoTail; ///< Tail of the FIFO
+ DT_SOCKET * pNextConnection; ///< Link in the FIFO
+
+ //
+ // Network use
+ //
+ DT_PORT * pPortList; ///< List of ports managed by this socket
+ EFI_EVENT WaitAccept; ///< Wait for accept completion
+
+ //
+ // Receive data management
+ //
+ UINT32 MaxRxBuf; ///< Maximum size of the receive buffer
+ struct timeval RxTimeout; ///< Receive timeout
+ DT_PACKET * pRxFree; ///< Free packet list
+ DT_PACKET * pRxOobPacketListHead; ///< Urgent data list head
+ DT_PACKET * pRxOobPacketListTail; ///< Urgent data list tail
+ DT_PACKET * pRxPacketListHead; ///< Normal data list head
+ DT_PACKET * pRxPacketListTail; ///< Normal data list tail
+
+ //
+ // Transmit data management
+ //
+ UINT32 MaxTxBuf; ///< Maximum size of the transmit buffer
+ DT_PACKET * pTxOobPacketListHead; ///< Urgent data list head
+ DT_PACKET * pTxOobPacketListTail; ///< Urgent data list tail
+ DT_PACKET * pTxPacketListHead; ///< Normal data list head
+ DT_PACKET * pTxPacketListTail; ///< Normal data list tail
+}GCC_DT_SOCKET;
+
+#define SOCKET_FROM_PROTOCOL(a) CR(a, DT_SOCKET, SocketProtocol, SOCKET_SIGNATURE) ///< Locate DT_SOCKET from protocol
+
+/**
+ Socket layer control structure
+
+ The driver uses this structure to manage the driver.
+**/
+typedef struct {
+ UINTN Signature; ///< Structure identification
+
+ //
+ // Service binding interface
+ //
+ EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;///< Driver's binding
+
+ //
+ // Image data
+ //
+ EFI_HANDLE ImageHandle; ///< Image handle
+
+ //
+ // Network services
+ //
+ DT_SERVICE * pTcp4List; ///< List of Tcp4 services
+ DT_SERVICE * pUdp4List; ///< List of Udp4 services
+
+ //
+ // Socket management
+ //
+ DT_SOCKET * pSocketList; ///< List of sockets
+
+ //
+ // TCP4 service
+ //
+ UINTN TcpCloseMax4; ///< Number of entries in the ring buffer
+ UINTN TcpCloseIn4; ///< Offset into TcpClose4 ring buffer - Close request
+ UINTN TcpCloseOut4; ///< Offset into TcpClose4 ring buffer - Close operation
+ EFI_TCP4_PROTOCOL ** ppTcpClose4; ///< Ring buffer to close TCP4 ports
+} DT_LAYER;
+
+#define LAYER_FROM_SERVICE(a) CR(a, DT_LAYER, ServiceBinding, LAYER_SIGNATURE) ///< Locate DT_LAYER from service binding
+
+//------------------------------------------------------------------------------
+// Data
+//------------------------------------------------------------------------------
+
+extern DT_LAYER mEslLayer;
+
+//------------------------------------------------------------------------------
+// Socket Support Routines
+//------------------------------------------------------------------------------
+
+/**
+ Allocate and initialize a DT_SOCKET structure.
+
+ The ::SocketAllocate() function allocates a DT_SOCKET structure
+ and installs a protocol on ChildHandle. If pChildHandle is a
+ pointer to NULL, then a new handle is created and returned in
+ pChildHandle. If pChildHandle is not a pointer to NULL, then
+ the protocol installs on the existing pChildHandle.
+
+ @param [in, out] pChildHandle Pointer to the handle of the child to create.
+ If it is NULL, then a new handle is created.
+ If it is a pointer to an existing UEFI handle,
+ then the protocol is added to the existing UEFI
+ handle.
+ @param [in] DebugFlags Flags for debug messages
+ @param [in, out] ppSocket The buffer to receive the DT_SOCKET structure address.
+
+ @retval EFI_SUCCESS The protocol was added to ChildHandle.
+ @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
+ the child
+ @retval other The child handle was not created
+
+**/
+EFI_STATUS
+EFIAPI
+EslSocketAllocate (
+ IN OUT EFI_HANDLE * pChildHandle,
+ IN UINTN DebugFlags,
+ IN OUT DT_SOCKET ** ppSocket
+ );
+
+/**
+ Allocate a packet for a receive or transmit operation
+
+ @param [in] ppPacket Address to receive the DT_PACKET structure
+ @param [in] LengthInBytes Length of the packet structure
+ @param [in] DebugFlags Flags for debug messages
+
+ @retval EFI_SUCCESS - The packet was allocated successfully
+
+ **/
+EFI_STATUS
+EslSocketPacketAllocate (
+ IN DT_PACKET ** ppPacket,
+ IN size_t LengthInBytes,
+ IN UINTN DebugFlags
+ );
+
+/**
+ Free a packet used for receive or transmit operation
+
+ @param [in] pPacket Address of the DT_PACKET structure
+ @param [in] DebugFlags Flags for debug messages
+
+ @retval EFI_SUCCESS - The packet was allocated successfully
+
+ **/
+EFI_STATUS
+EslSocketPacketFree (
+ IN DT_PACKET * pPacket,
+ IN UINTN DebugFlags
+ );
+
+//------------------------------------------------------------------------------
+// Tcp4 Routines
+//------------------------------------------------------------------------------
+
+/**
+ Accept a network connection.
+
+ The SocketAccept routine waits for a network connection to the socket.
+ It is able to return the remote network address to the caller if
+ requested.
+
+ @param [in] pSocket Address of the socket structure.
+
+ @param [in] pSockAddr Address of a buffer to receive the remote
+ network address.
+
+ @param [in, out] pSockAddrLength Length in bytes of the address buffer.
+ On output specifies the length of the
+ remote network address.
+
+ @retval EFI_SUCCESS Remote address is available
+ @retval Others Remote address not available
+
+ **/
+EFI_STATUS
+EslTcpAccept4 (
+ IN DT_SOCKET * pSocket,
+ IN struct sockaddr * pSockAddr,
+ IN OUT socklen_t * pSockAddrLength
+ );
+
+/**
+ Bind a name to a socket.
+
+ The ::TcpBind4 routine connects a name to A TCP4 stack on the local machine.
+
+ @param [in] pSocket Address of the socket structure.
+
+ @param [in] pSockAddr Address of a sockaddr structure that contains the
+ connection point on the local machine. An IPv4 address
+ of INADDR_ANY specifies that the connection is made to
+ all of the network stacks on the platform. Specifying a
+ specific IPv4 address restricts the connection to the
+ network stack supporting that address. Specifying zero
+ for the port causes the network layer to assign a port
+ number from the dynamic range. Specifying a specific
+ port number causes the network layer to use that port.
+
+ @param [in] SockAddrLen Specifies the length in bytes of the sockaddr structure.
+
+ @retval EFI_SUCCESS - Socket successfully created
+
+ **/
+EFI_STATUS
+EslTcpBind4 (
+ IN DT_SOCKET * pSocket,
+ IN const struct sockaddr * pSockAddr,
+ IN socklen_t SockAddrLength
+ );
+
+/**
+ Poll for completion of the connection attempt.
+
+ The ::TcpConnectPoll4 routine determines when the connection
+ attempt transitions from being in process to being complete.
+
+ @param [in] pSocket Address of the socket structure.
+
+ @retval EFI_SUCCESS The connection was successfully established.
+ @retval EFI_NOT_READY The connection is in progress, call this routine again.
+ @retval Others The connection attempt failed.
+
+ **/
+EFI_STATUS
+EslTcpConnectPoll4 (
+ IN DT_SOCKET * pSocket
+ );
+
+/**
+ Connect to a remote system via the network.
+
+ The ::TcpConnectStart4= routine starts the connection processing
+ for a TCP4 port.
+
+ @param [in] pSocket Address of the socket structure.
+
+ @param [in] pSockAddr Network address of the remote system.
+
+ @param [in] SockAddrLength Length in bytes of the network address.
+
+ @retval EFI_SUCCESS The connection was successfully established.
+ @retval EFI_NOT_READY The connection is in progress, call this routine again.
+ @retval Others The connection attempt failed.
+
+ **/
+EFI_STATUS
+EslTcpConnectStart4 (
+ IN DT_SOCKET * pSocket,
+ IN const struct sockaddr * pSockAddr,
+ IN socklen_t SockAddrLength
+ );
+
+/**
+ Initialize the TCP4 service.
+
+ This routine initializes the TCP4 service after its service binding
+ protocol was located on a controller.
+
+ @param [in] pService DT_SERVICE structure address
+
+ @retval EFI_SUCCESS The service was properly initialized
+ @retval other A failure occurred during the service initialization
+
+**/
+EFI_STATUS
+EFIAPI
+EslTcpInitialize4 (
+ IN DT_SERVICE * pService
+ );
+
+/**
+ Get the local socket address
+
+ @param [in] pSocket Address of the socket structure.
+
+ @param [out] pAddress Network address to receive the local system address
+
+ @param [in,out] pAddressLength Length of the local network address structure
+
+ @retval EFI_SUCCESS - Address available
+ @retval Other - Failed to get the address
+
+**/
+EFI_STATUS
+EslTcpGetLocalAddress4 (
+ IN DT_SOCKET * pSocket,
+ OUT struct sockaddr * pAddress,
+ IN OUT socklen_t * pAddressLength
+ );
+
+/**
+ Get the remote socket address
+
+ @param [in] pSocket Address of the socket structure.
+
+ @param [out] pAddress Network address to receive the remote system address
+
+ @param [in,out] pAddressLength Length of the remote network address structure
+
+ @retval EFI_SUCCESS - Address available
+ @retval Other - Failed to get the address
+
+**/
+EFI_STATUS
+EslTcpGetRemoteAddress4 (
+ IN DT_SOCKET * pSocket,
+ OUT struct sockaddr * pAddress,
+ IN OUT socklen_t * pAddressLength
+ );
+
+/**
+ Establish the known port to listen for network connections.
+
+ The ::Tcp4Listen routine places the port into a state that enables connection
+ attempts. Connections are placed into FIFO order in a queue to be serviced
+ by the application. The application calls the ::Tcp4Accept routine to remove
+ the next connection from the queue and get the associated socket. The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html">POSIX</a>
+ documentation for the listen routine is available online for reference.
+
+ @param [in] pSocket Address of the socket structure.
+
+ @retval EFI_SUCCESS - Socket successfully created
+ @retval Other - Failed to enable the socket for listen
+
+**/
+EFI_STATUS
+EslTcpListen4 (
+ IN DT_SOCKET * pSocket
+ );
+
+/**
+ Process the connection attempt
+
+ A system has initiated a connection attempt with a socket in the
+ listen state. Attempt to complete the connection.
+
+ @param Event The listeen completion event
+
+ @param pPort The DT_PORT structure address
+
+**/
+VOID
+EslTcpListenComplete4 (
+ IN EFI_EVENT Event,
+ IN DT_PORT * pPort
+ );
+
+/**
+ Allocate and initialize a DT_PORT structure.
+
+ @param [in] pSocket Address of the socket structure.
+ @param [in] pService Address of the DT_SERVICE structure.
+ @param [in] ChildHandle TCP4 child handle
+ @param [in] pIpAddress Buffer containing IP4 network address of the local host
+ @param [in] PortNumber Tcp4 port number
+ @param [in] DebugFlags Flags for debug messages
+ @param [out] ppPort Buffer to receive new DT_PORT structure address
+
+ @retval EFI_SUCCESS - Socket successfully created
+
+ **/
+EFI_STATUS
+EslTcpPortAllocate4 (
+ IN DT_SOCKET * pSocket,
+ IN DT_SERVICE * pService,
+ IN EFI_HANDLE ChildHandle,
+ IN CONST UINT8 *pIpAddress,
+ IN UINT16 PortNumber,
+ IN UINTN DebugFlags,
+ OUT DT_PORT ** ppPort
+ );
+
+/**
+ Close a TCP4 port.
+
+ This routine releases the resources allocated by
+ ::TcpPortAllocate4().
+
+ @param [in] pPort Address of the port structure.
+
+ @retval EFI_SUCCESS The port is closed
+ @retval other Port close error
+
+**/
+EFI_STATUS
+EslTcpPortClose4 (
+ IN DT_PORT * pPort
+ );
+
+/**
+ Process the port close completion
+
+ @param Event The close completion event
+
+ @param pPort The DT_PORT structure address
+
+**/
+VOID
+EslTcpPortCloseComplete4 (
+ IN EFI_EVENT Event,
+ IN DT_PORT * pPort
+ );
+
+/**
+ Port close state 3
+
+ Continue the close operation after the receive is complete.
+
+ @param [in] pPort Address of the port structure.
+
+ @retval EFI_SUCCESS The port is closed
+ @retval EFI_NOT_READY The port is still closing
+ @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
+ most likely the routine was called already.
+
+**/
+EFI_STATUS
+EslTcpPortCloseRxDone4 (
+ IN DT_PORT * pPort
+ );
+
+/**
+ Start the close operation on a TCP4 port.
+
+ @param [in] pPort Address of the port structure.
+ @param [in] bAbort Set TRUE to abort active transfers
+ @param [in] DebugFlags Flags for debug messages
+
+**/
+EFI_STATUS
+EslTcpPortCloseStart4 (
+ IN DT_PORT * pPort,
+ IN BOOLEAN bAbort,
+ IN UINTN DebugFlags
+ );
+
+/**
+ Port close state 2
+
+ Continue the close operation after the transmission is complete.
+
+ @param [in] pPort Address of the port structure.
+
+ @retval EFI_NOT_READY The port is still closing
+ @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
+ most likely the routine was called already.
+
+**/
+EFI_STATUS
+EslTcpPortCloseTxDone4 (
+ IN DT_PORT * pPort
+ );
+
+/**
+ Receive data from a network connection.
+
+
+ @param [in] pSocket Address of a DT_SOCKET structure
+
+ @param [in] Flags Message control flags
+
+ @param [in] BufferLength Length of the the buffer
+
+ @param [in] pBuffer Address of a buffer to receive the data.
+
+ @param [in] pDataLength Number of received data bytes in the buffer.
+
+ @param [out] pAddress Network address to receive the remote system address
+
+ @param [in,out] pAddressLength Length of the remote network address structure
+
+ @retval EFI_SUCCESS - Socket data successfully received
+
+ **/
+EFI_STATUS
+EslTcpReceive4 (
+ IN DT_SOCKET * pSocket,
+ IN INT32 Flags,
+ IN size_t BufferLength,
+ IN UINT8 * pBuffer,
+ OUT size_t * pDataLength,
+ OUT struct sockaddr * pAddress,
+ IN OUT socklen_t * pAddressLength
+ );
+
+/**
+ Cancel the receive operations
+
+ @param [in] pSocket Address of a DT_SOCKET structure
+
+ @retval EFI_SUCCESS - The cancel was successful
+
+ **/
+EFI_STATUS
+EslTcpRxCancel4 (
+ IN DT_SOCKET * pSocket
+ );
+
+/**
+ Process the receive completion
+
+ Buffer the data that was just received.
+
+ @param Event The receive completion event
+
+ @param pPort The DT_PORT structure address
+
+**/
+VOID
+EslTcpRxComplete4 (
+ IN EFI_EVENT Event,
+ IN DT_PORT * pPort
+ );
+
+/**
+ Start a receive operation
+
+ @param [in] pPort Address of the DT_PORT structure.
+
+ **/
+VOID
+EslTcpRxStart4 (
+ IN DT_PORT * pPort
+ );
+
+/**
+ Shutdown the TCP4 service.
+
+ This routine undoes the work performed by ::TcpInitialize4.
+
+ @param [in] pService DT_SERVICE structure address
+
+**/
+VOID
+EFIAPI
+EslTcpShutdown4 (
+ IN DT_SERVICE * pService
+ );
+
+/**
+ Determine if the socket is configured.
+
+
+ @param [in] pSocket Address of a DT_SOCKET structure
+
+ @retval EFI_SUCCESS - The port is connected
+ @retval EFI_NOT_STARTED - The port is not connected
+
+ **/
+ EFI_STATUS
+ EslTcpSocketIsConfigured4 (
+ IN DT_SOCKET * pSocket
+ );
+
+/**
+ Buffer data for transmission over a network connection.
+
+ This routine is called by the socket layer API to buffer
+ data for transmission. When necessary, this routine will
+ start the transmit engine that performs the data transmission
+ on the network connection.
+
+ @param [in] pSocket Address of a DT_SOCKET structure
+
+ @param [in] Flags Message control flags
+
+ @param [in] BufferLength Length of the the buffer
+
+ @param [in] pBuffer Address of a buffer to receive the data.
+
+ @param [in] pDataLength Number of received data bytes in the buffer.
+
+ @retval EFI_SUCCESS - Socket data successfully buffered
+
+ **/
+EFI_STATUS
+EslTcpTxBuffer4 (
+ IN DT_SOCKET * pSocket,
+ IN int Flags,
+ IN size_t BufferLength,
+ IN CONST UINT8 * pBuffer,
+ OUT size_t * pDataLength
+ );
+
+/**
+ Process the normal data transmit completion
+
+ @param Event The normal transmit completion event
+
+ @param pPort The DT_PORT structure address
+
+**/
+VOID
+EslTcpTxComplete4 (
+ IN EFI_EVENT Event,
+ IN DT_PORT * pPort
+ );
+
+/**
+ Process the urgent data transmit completion
+
+ @param Event The urgent transmit completion event
+
+ @param pPort The DT_PORT structure address
+
+**/
+VOID
+EslTcpTxOobComplete4 (
+ IN EFI_EVENT Event,
+ IN DT_PORT * pPort
+ );
+
+/**
+ Transmit data using a network connection.
+
+
+ @param [in] pPort Address of a DT_PORT structure
+ @param [in] pToken Address of either the OOB or normal transmit token
+ @param [in] ppQueueHead Transmit queue head address
+ @param [in] ppQueueTail Transmit queue tail address
+ @param [in] ppPacket Active transmit packet address
+
+ **/
+VOID
+EslTcpTxStart4 (
+ IN DT_PORT * pPort,
+ IN EFI_TCP4_IO_TOKEN * pToken,
+ IN DT_PACKET ** ppQueueHead,
+ IN DT_PACKET ** ppQueueTail,
+ IN DT_PACKET ** ppPacket
+ );
+
+//------------------------------------------------------------------------------
+// Udp4 Routines
+//------------------------------------------------------------------------------
+
+/**
+ Bind a name to a socket.
+
+ The ::UdpBind4 routine connects a name to a UDP4 stack on the local machine.
+
+ @param [in] pSocket Address of the socket structure.
+
+ @param [in] pSockAddr Address of a sockaddr structure that contains the
+ connection point on the local machine. An IPv4 address
+ of INADDR_ANY specifies that the connection is made to
+ all of the network stacks on the platform. Specifying a
+ specific IPv4 address restricts the connection to the
+ network stack supporting that address. Specifying zero
+ for the port causes the network layer to assign a port
+ number from the dynamic range. Specifying a specific
+ port number causes the network layer to use that port.
+
+ @param [in] SockAddrLen Specifies the length in bytes of the sockaddr structure.
+
+ @retval EFI_SUCCESS - Socket successfully created
+
+ **/
+EFI_STATUS
+EslUdpBind4 (
+ IN DT_SOCKET * pSocket,
+ IN const struct sockaddr * pSockAddr,
+ IN socklen_t SockAddrLength
+ );
+
+/**
+ Initialize the UDP4 service.
+
+ This routine initializes the UDP4 service after its service binding
+ protocol was located on a controller.
+
+ @param [in] pService DT_SERVICE structure address
+
+ @retval EFI_SUCCESS The service was properly initialized
+ @retval other A failure occurred during the service initialization
+
+**/
+EFI_STATUS
+EFIAPI
+EslUdpInitialize4 (
+ IN DT_SERVICE * pService
+ );
+
+/**
+ Allocate and initialize a DT_PORT structure.
+
+ @param [in] pSocket Address of the socket structure.
+ @param [in] pService Address of the DT_SERVICE structure.
+ @param [in] ChildHandle Udp4 child handle
+ @param [in] pIpAddress Buffer containing IP4 network address of the local host
+ @param [in] PortNumber Udp4 port number
+ @param [in] DebugFlags Flags for debug messages
+ @param [out] ppPort Buffer to receive new DT_PORT structure address
+
+ @retval EFI_SUCCESS - Socket successfully created
+
+ **/
+EFI_STATUS
+EslUdpPortAllocate4 (
+ IN DT_SOCKET * pSocket,
+ IN DT_SERVICE * pService,
+ IN EFI_HANDLE ChildHandle,
+ IN CONST UINT8 * pIpAddress,
+ IN UINT16 PortNumber,
+ IN UINTN DebugFlags,
+ OUT DT_PORT ** ppPort
+ );
+
+/**
+ Close a UDP4 port.
+
+ This routine releases the resources allocated by
+ ::UdpPortAllocate4().
+
+ @param [in] pPort Address of the port structure.
+
+ @retval EFI_SUCCESS The port is closed
+ @retval other Port close error
+
+**/
+EFI_STATUS
+EslUdpPortClose4 (
+ IN DT_PORT * pPort
+ );
+
+/**
+ Start the close operation on a UDP4 port, state 1.
+
+ Closing a port goes through the following states:
+ 1. Port close starting - Mark the port as closing and wait for transmission to complete
+ 2. Port TX close done - Transmissions complete, close the port and abort the receives
+ 3. Port RX close done - Receive operations complete, close the port
+ 4. Port closed - Release the port resources
+
+ @param [in] pPort Address of the port structure.
+ @param [in] bCloseNow Set TRUE to abort active transfers
+ @param [in] DebugFlags Flags for debug messages
+
+ @retval EFI_SUCCESS The port is closed, not normally returned
+ @retval EFI_NOT_READY The port has started the closing process
+ @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
+ most likely the routine was called already.
+
+**/
+EFI_STATUS
+EslUdpPortCloseStart4 (
+ IN DT_PORT * pPort,
+ IN BOOLEAN bCloseNow,
+ IN UINTN DebugFlags
+ );
+
+/**
+ Port close state 2
+
+ Continue the close operation after the transmission is complete.
+
+ @param [in] pPort Address of the port structure.
+
+ @retval EFI_SUCCESS The port is closed, not normally returned
+ @retval EFI_NOT_READY The port is still closing
+ @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
+ most likely the routine was called already.
+
+**/
+EFI_STATUS
+EslUdpPortCloseTxDone4 (
+ IN DT_PORT * pPort
+ );
+
+/**
+ Connect to a remote system via the network.
+
+ The ::UdpConnectStart4= routine sets the remote address for the connection.
+
+ @param [in] pSocket Address of the socket structure.
+
+ @param [in] pSockAddr Network address of the remote system.
+
+ @param [in] SockAddrLength Length in bytes of the network address.
+
+ @retval EFI_SUCCESS The connection was successfully established.
+ @retval EFI_NOT_READY The connection is in progress, call this routine again.
+ @retval Others The connection attempt failed.
+
+ **/
+EFI_STATUS
+EslUdpConnect4 (
+ IN DT_SOCKET * pSocket,
+ IN const struct sockaddr * pSockAddr,
+ IN socklen_t SockAddrLength
+ );
+
+/**
+ Get the local socket address
+
+ @param [in] pSocket Address of the socket structure.
+
+ @param [out] pAddress Network address to receive the local system address
+
+ @param [in,out] pAddressLength Length of the local network address structure
+
+ @retval EFI_SUCCESS - Address available
+ @retval Other - Failed to get the address
+
+**/
+EFI_STATUS
+EslUdpGetLocalAddress4 (
+ IN DT_SOCKET * pSocket,
+ OUT struct sockaddr * pAddress,
+ IN OUT socklen_t * pAddressLength
+ );
+
+/**
+ Get the remote socket address
+
+ @param [in] pSocket Address of the socket structure.
+
+ @param [out] pAddress Network address to receive the remote system address
+
+ @param [in,out] pAddressLength Length of the remote network address structure
+
+ @retval EFI_SUCCESS - Address available
+ @retval Other - Failed to get the address
+
+**/
+EFI_STATUS
+EslUdpGetRemoteAddress4 (
+ IN DT_SOCKET * pSocket,
+ OUT struct sockaddr * pAddress,
+ IN OUT socklen_t * pAddressLength
+ );
+
+/**
+ Receive data from a network connection.
+
+ To minimize the number of buffer copies, the ::UdpRxComplete4
+ routine queues the UDP4 driver's buffer to a list of datagrams
+ waiting to be received. The socket driver holds on to the
+ buffers from the UDP4 driver until the application layer requests
+ the data or the socket is closed.
+
+ The application calls this routine in the socket layer to
+ receive datagrams from one or more remote systems. This routine
+ removes the next available datagram from the list of datagrams
+ and copies the data from the UDP4 driver's buffer into the
+ application's buffer. The UDP4 driver's buffer is then returned.
+
+ @param [in] pSocket Address of a DT_SOCKET structure
+
+ @param [in] Flags Message control flags
+
+ @param [in] BufferLength Length of the the buffer
+
+ @param [in] pBuffer Address of a buffer to receive the data.
+
+ @param [in] pDataLength Number of received data bytes in the buffer.
+
+ @param [out] pAddress Network address to receive the remote system address
+
+ @param [in,out] pAddressLength Length of the remote network address structure
+
+ @retval EFI_SUCCESS - Socket data successfully received
+
+**/
+EFI_STATUS
+EslUdpReceive4 (
+ IN DT_SOCKET * pSocket,
+ IN INT32 Flags,
+ IN size_t BufferLength,
+ IN UINT8 * pBuffer,
+ OUT size_t * pDataLength,
+ OUT struct sockaddr * pAddress,
+ IN OUT socklen_t * pAddressLength
+ );
+
+/**
+ Cancel the receive operations
+
+ @param [in] pSocket Address of a DT_SOCKET structure
+
+ @retval EFI_SUCCESS - The cancel was successful
+
+ **/
+EFI_STATUS
+EslUdpRxCancel4 (
+ IN DT_SOCKET * pSocket
+ );
+
+/**
+ Process the receive completion
+
+ Keep the UDP4 driver's buffer and append it to the list of
+ datagrams for the application to receive. The UDP4 driver's
+ buffer will be returned by either ::UdpReceive4 or
+ ::UdpPortCloseTxDone4.
+
+ @param Event The receive completion event
+
+ @param pPort The DT_PORT structure address
+
+**/
+VOID
+EslUdpRxComplete4 (
+ IN EFI_EVENT Event,
+ IN DT_PORT * pPort
+ );
+
+/**
+ Start a receive operation
+
+ @param [in] pPort Address of the DT_PORT structure.
+
+ **/
+VOID
+EslUdpRxStart4 (
+ IN DT_PORT * pPort
+ );
+
+/**
+ Determine if the socket is configured.
+
+
+ @param [in] pSocket Address of a DT_SOCKET structure
+
+ @retval EFI_SUCCESS - The port is connected
+ @retval EFI_NOT_STARTED - The port is not connected
+
+ **/
+ EFI_STATUS
+ EslUdpSocketIsConfigured4 (
+ IN DT_SOCKET * pSocket
+ );
+
+/**
+ Process the transmit completion
+
+ @param Event The normal transmit completion event
+
+ @param pPort The DT_PORT structure address
+
+**/
+VOID
+EslUdpTxComplete4 (
+ IN EFI_EVENT Event,
+ IN DT_PORT * pPort
+ );
+
+/**
+ Shutdown the UDP4 service.
+
+ This routine undoes the work performed by ::UdpInitialize4.
+
+ @param [in] pService DT_SERVICE structure address
+
+**/
+VOID
+EFIAPI
+EslUdpShutdown4 (
+ IN DT_SERVICE * pService
+ );
+
+/**
+ Buffer data for transmission over a network connection.
+
+ This routine is called by the socket layer API to buffer
+ data for transmission. The data is copied into a local buffer
+ freeing the application buffer for reuse upon return. When
+ necessary, this routine will start the transmit engine that
+ performs the data transmission on the network connection. The
+ transmit engine transmits the data a packet at a time over the
+ network connection.
+
+ Transmission errors are returned during the next transmission or
+ during the close operation. Only buffering errors are returned
+ during the current transmission attempt.
+
+ @param [in] pSocket Address of a DT_SOCKET structure
+
+ @param [in] Flags Message control flags
+
+ @param [in] BufferLength Length of the the buffer
+
+ @param [in] pBuffer Address of a buffer to receive the data.
+
+ @param [in] pDataLength Number of received data bytes in the buffer.
+
+ @param [in] pAddress Network address of the remote system address
+
+ @param [in] AddressLength Length of the remote network address structure
+
+ @retval EFI_SUCCESS - Socket data successfully buffered
+
+**/
+EFI_STATUS
+EslUdpTxBuffer4 (
+ IN DT_SOCKET * pSocket,
+ IN int Flags,
+ IN size_t BufferLength,
+ IN CONST UINT8 * pBuffer,
+ OUT size_t * pDataLength,
+ IN const struct sockaddr * pAddress,
+ IN socklen_t AddressLength
+ );
+
+/**
+ Transmit data using a network connection.
+
+ @param [in] pPort Address of a DT_PORT structure
+
+ **/
+VOID
+EslUdpTxStart4 (
+ IN DT_PORT * pPort
+ );
+
+//------------------------------------------------------------------------------
+
+#endif // _SOCKET_H_
diff --git a/StdLib/EfiSocketLib/Tcp4.c b/StdLib/EfiSocketLib/Tcp4.c new file mode 100644 index 0000000000..2840dd7e0e --- /dev/null +++ b/StdLib/EfiSocketLib/Tcp4.c @@ -0,0 +1,3415 @@ +/** @file
+ Implement the TCP4 driver support for the socket layer.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Socket.h"
+
+
+/**
+ Accept a network connection.
+
+ The SocketAccept routine waits for a network connection to the socket.
+ It is able to return the remote network address to the caller if
+ requested.
+
+ @param [in] pSocket Address of the socket structure.
+
+ @param [in] pSockAddr Address of a buffer to receive the remote
+ network address.
+
+ @param [in, out] pSockAddrLength Length in bytes of the address buffer.
+ On output specifies the length of the
+ remote network address.
+
+ @retval EFI_SUCCESS Remote address is available
+ @retval Others Remote address not available
+
+ **/
+EFI_STATUS
+EslTcpAccept4 (
+ IN DT_SOCKET * pSocket,
+ IN struct sockaddr * pSockAddr,
+ IN OUT socklen_t * pSockAddrLength
+ )
+{
+ DT_PORT * pPort;
+ struct sockaddr_in * pRemoteAddress;
+ DT_TCP4_CONTEXT * pTcp4;
+ UINT32 RemoteAddress;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Validate the socket length
+ //
+ pRemoteAddress = (struct sockaddr_in *) pSockAddr;
+ if (( NULL == pSockAddrLength )
+ || ( sizeof ( *pRemoteAddress ) > *pSockAddrLength )) {
+ //
+ // Invalid socket address
+ //
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EINVAL;
+ DEBUG (( DEBUG_ACCEPT,
+ "ERROR - Invalid address length\r\n" ));
+ }
+ else {
+ //
+ // Assume success
+ //
+ Status = EFI_SUCCESS;
+
+ //
+ // Locate the address context
+ //
+ pPort = pSocket->pPortList;
+ pTcp4 = &pPort->Context.Tcp4;
+
+ //
+ // Fill-in the remote address structure
+ //
+ ZeroMem ( pRemoteAddress, sizeof ( *pRemoteAddress ));
+ pRemoteAddress->sin_len = sizeof ( *pRemoteAddress );
+ pRemoteAddress->sin_family = AF_INET;
+ pRemoteAddress->sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.RemotePort );
+ RemoteAddress = pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3];
+ RemoteAddress <<= 8;
+ RemoteAddress |= pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2];
+ RemoteAddress <<= 8;
+ RemoteAddress |= pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1];
+ RemoteAddress <<= 8;
+ RemoteAddress |= pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0];
+ pRemoteAddress->sin_addr.s_addr = RemoteAddress;
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Bind a name to a socket.
+
+ The ::TcpBind4 routine connects a name to a TCP4 stack on the local machine.
+
+ @param [in] pSocket Address of the socket structure.
+
+ @param [in] pSockAddr Address of a sockaddr structure that contains the
+ connection point on the local machine. An IPv4 address
+ of INADDR_ANY specifies that the connection is made to
+ all of the network stacks on the platform. Specifying a
+ specific IPv4 address restricts the connection to the
+ network stack supporting that address. Specifying zero
+ for the port causes the network layer to assign a port
+ number from the dynamic range. Specifying a specific
+ port number causes the network layer to use that port.
+
+ @param [in] SockAddrLen Specifies the length in bytes of the sockaddr structure.
+
+ @retval EFI_SUCCESS - Socket successfully created
+
+ **/
+EFI_STATUS
+EslTcpBind4 (
+ IN DT_SOCKET * pSocket,
+ IN const struct sockaddr * pSockAddr,
+ IN socklen_t SockAddrLength
+ )
+{
+ EFI_HANDLE ChildHandle;
+ DT_LAYER * pLayer;
+ DT_PORT * pPort;
+ DT_SERVICE * pService;
+ CONST struct sockaddr_in * pIp4Address;
+ EFI_SERVICE_BINDING_PROTOCOL * pTcp4Service;
+ EFI_STATUS Status;
+ EFI_STATUS TempStatus;
+
+ DBG_ENTER ( );
+
+ //
+ // Verify the socket layer synchronization
+ //
+ VERIFY_TPL ( TPL_SOCKETS );
+
+ //
+ // Assume success
+ //
+ pSocket->errno = 0;
+ Status = EFI_SUCCESS;
+
+ //
+ // Validate the address length
+ //
+ pIp4Address = (CONST struct sockaddr_in *) pSockAddr;
+ if ( SockAddrLength >= ( sizeof ( *pIp4Address )
+ - sizeof ( pIp4Address->sin_zero ))) {
+
+ //
+ // Walk the list of services
+ //
+ pLayer = &mEslLayer;
+ pService = pLayer->pTcp4List;
+ while ( NULL != pService ) {
+ //
+ // Create the TCP port
+ //
+ pTcp4Service = pService->pInterface;
+ ChildHandle = NULL;
+ Status = pTcp4Service->CreateChild ( pTcp4Service,
+ &ChildHandle );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_BIND | DEBUG_POOL,
+ "0x%08x: Tcp4 port handle created\r\n",
+ ChildHandle ));
+
+ //
+ // Open the port
+ //
+ Status = EslTcpPortAllocate4 ( pSocket,
+ pService,
+ ChildHandle,
+ (UINT8 *) &pIp4Address->sin_addr.s_addr,
+ SwapBytes16 ( pIp4Address->sin_port ),
+ DEBUG_BIND,
+ &pPort );
+ }
+ else {
+ DEBUG (( DEBUG_BIND | DEBUG_POOL,
+ "ERROR - Failed to open Tcp4 port handle, Status: %r\r\n",
+ Status ));
+ ChildHandle = NULL;
+ }
+
+ //
+ // Close the port if necessary
+ //
+ if (( EFI_ERROR ( Status )) && ( NULL != ChildHandle )) {
+ TempStatus = pTcp4Service->DestroyChild ( pTcp4Service,
+ ChildHandle );
+ if ( !EFI_ERROR ( TempStatus )) {
+ DEBUG (( DEBUG_BIND | DEBUG_POOL,
+ "0x%08x: Tcp4 port handle destroyed\r\n",
+ ChildHandle ));
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_BIND | DEBUG_POOL,
+ "ERROR - Failed to destroy the Tcp4 port handle 0x%08x, Status: %r\r\n",
+ ChildHandle,
+ TempStatus ));
+ ASSERT ( EFI_SUCCESS == TempStatus );
+ }
+ }
+
+ //
+ // Set the next service
+ //
+ pService = pService->pNext;
+ }
+
+ //
+ // Verify that at least one network connection was found
+ //
+ if ( NULL == pSocket->pPortList ) {
+ DEBUG (( DEBUG_BIND | DEBUG_POOL | DEBUG_INIT,
+ "Socket address %d.%d.%d.%d (0x%08x) is not available!\r\n",
+ ( pIp4Address->sin_addr.s_addr >> 24 ) & 0xff,
+ ( pIp4Address->sin_addr.s_addr >> 16 ) & 0xff,
+ ( pIp4Address->sin_addr.s_addr >> 8 ) & 0xff,
+ pIp4Address->sin_addr.s_addr & 0xff,
+ pIp4Address->sin_addr.s_addr ));
+ pSocket->errno = EADDRNOTAVAIL;
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+ else {
+ DEBUG (( DEBUG_BIND,
+ "ERROR - Invalid TCP4 address length: %d\r\n",
+ SockAddrLength ));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EINVAL;
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Attempt to connect to a remote TCP port
+
+ @param [in] pSocket Address of the socket structure.
+
+ @retval EFI_SUCCESS The connection was successfully established.
+ @retval EFI_NOT_READY The connection is in progress, call this routine again.
+ @retval Others The connection attempt failed.
+
+ **/
+EFI_STATUS
+EslTcpConnectAttempt4 (
+ IN DT_SOCKET * pSocket
+ )
+{
+ DT_PORT * pPort;
+ DT_TCP4_CONTEXT * pTcp4;
+ EFI_TCP4_PROTOCOL * pTcp4Protocol;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Determine if any more local adapters are available
+ //
+ pPort = pSocket->pPortList;
+ if ( NULL != pPort ) {
+ //
+ // Configure the port
+ //
+ pTcp4 = &pPort->Context.Tcp4;
+ pTcp4->ConfigData.AccessPoint.ActiveFlag = TRUE;
+ pTcp4->ConfigData.TimeToLive = 255;
+ pTcp4Protocol = pTcp4->pProtocol;
+ Status = pTcp4Protocol->Configure ( pTcp4Protocol,
+ &pTcp4->ConfigData );
+ if ( EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_CONNECT,
+ "ERROR - Failed to configure the Tcp4 port, Status: %r\r\n",
+ Status ));
+ switch ( Status ) {
+ case EFI_ACCESS_DENIED:
+ pSocket->errno = EACCES;
+ break;
+
+ default:
+ case EFI_DEVICE_ERROR:
+ pSocket->errno = EIO;
+ break;
+
+ case EFI_INVALID_PARAMETER:
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case EFI_NO_MAPPING:
+ pSocket->errno = EAFNOSUPPORT;
+ break;
+
+ case EFI_OUT_OF_RESOURCES:
+ pSocket->errno = ENOBUFS;
+ break;
+
+ case EFI_UNSUPPORTED:
+ pSocket->errno = EOPNOTSUPP;
+ break;
+ }
+ }
+ else {
+ DEBUG (( DEBUG_CONNECT,
+ "0x%08x: Port configured\r\n",
+ pPort ));
+ pTcp4->bConfigured = TRUE;
+
+ //
+ // Attempt the connection to the remote system
+ //
+ Status = pTcp4Protocol->Connect ( pTcp4Protocol,
+ &pTcp4->ConnectToken );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Connection in progress
+ //
+ pSocket->errno = EINPROGRESS;
+ Status = EFI_NOT_READY;
+ DEBUG (( DEBUG_CONNECT,
+ "0x%08x: Port attempting connection to %d.%d.%d.%d:%d\r\n",
+ pPort,
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3],
+ pTcp4->ConfigData.AccessPoint.RemotePort ));
+ }
+ else {
+ //
+ // Connection error
+ //
+ pSocket->errno = EINVAL;
+ DEBUG (( DEBUG_CONNECT,
+ "ERROR - Port 0x%08x not connected, Status: %r\r\n",
+ pPort,
+ Status ));
+ }
+ }
+ }
+ else {
+ //
+ // No more local adapters available
+ //
+ pSocket->errno = ENETUNREACH;
+ Status = EFI_NO_RESPONSE;
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Process the remote connection attempt
+
+ A connection attempt to a remote system has just completed when
+ this routine is invoked. Release the port in the case of an
+ error and start a connection attempt on the next port. If the
+ connection attempt was successful, then release all of the other
+ ports.
+
+ @param Event The connect completion event
+
+ @param pPort The DT_PORT structure address
+
+**/
+VOID
+EslTcpConnectComplete4 (
+ IN EFI_EVENT Event,
+ IN DT_PORT * pPort
+ )
+{
+ BOOLEAN bRemoveFirstPort;
+ BOOLEAN bRemovePorts;
+ DT_PORT * pNextPort;
+ DT_SOCKET * pSocket;
+ DT_TCP4_CONTEXT * pTcp4;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Locate the TCP context
+ //
+ pSocket = pPort->pSocket;
+ pTcp4 = &pPort->Context.Tcp4;
+
+ //
+ // Get the connection status
+ //
+ bRemoveFirstPort = FALSE;
+ bRemovePorts = FALSE;
+ Status = pTcp4->ConnectToken.CompletionToken.Status;
+ pSocket->ConnectStatus = Status;
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // The connection was successful
+ //
+ DEBUG (( DEBUG_CONNECT,
+ "0x%08x: Port connected to %d.%d.%d.%d:%d\r\n",
+ pPort,
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr [0],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr [1],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr [2],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr [3],
+ pTcp4->ConfigData.AccessPoint.RemotePort ));
+
+ //
+ // Remove the rest of the ports
+ //
+ bRemovePorts = TRUE;
+ }
+ else {
+ //
+ // The connection failed
+ //
+ DEBUG (( DEBUG_CONNECT,
+ "0x%08x: Port connection to %d.%d.%d.%d:%d failed, Status: %r\r\n",
+ pPort,
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr [0],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr [1],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr [2],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr [3],
+ pTcp4->ConfigData.AccessPoint.RemotePort,
+ Status ));
+
+ //
+ // Close the current port
+ //
+ Status = EslTcpPortClose4 ( pPort );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_CONNECT,
+ "0x%08x: Port closed\r\n",
+ pPort ));
+ }
+ else {
+ DEBUG (( DEBUG_CONNECT,
+ "ERROR - Failed to close port 0x%08x, Status: %r\r\n",
+ pPort,
+ Status ));
+ }
+
+ //
+ // Try to connect using the next port
+ //
+ Status = EslTcpConnectAttempt4 ( pSocket );
+ if ( EFI_NOT_READY != Status ) {
+ pSocket->ConnectStatus = Status;
+ bRemoveFirstPort = TRUE;
+ }
+ }
+
+ //
+ // Remove the ports if necessary
+ //
+ if ( bRemoveFirstPort || bRemovePorts ) {
+ //
+ // Remove the first port if necessary
+ //
+ pPort = pSocket->pPortList;
+ if (( !bRemoveFirstPort ) && ( NULL != pPort )) {
+ pPort = pPort->pLinkSocket;
+ }
+
+ //
+ // Remove the rest of the list
+ //
+ while ( NULL != pPort ) {
+ pNextPort = pPort->pLinkSocket;
+ EslTcpPortClose4 ( pPort );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_CONNECT,
+ "0x%08x: Port closed\r\n",
+ pPort ));
+ }
+ else {
+ DEBUG (( DEBUG_CONNECT,
+ "ERROR - Failed to close port 0x%08x, Status: %r\r\n",
+ pPort,
+ Status ));
+ }
+ pPort = pNextPort;
+ }
+
+ //
+ // Notify the poll routine
+ //
+ pSocket->bConnected = TRUE;
+ }
+
+ DBG_EXIT ( );
+}
+
+
+/**
+ Poll for completion of the connection attempt.
+
+ The ::TcpConnectPoll4 routine determines when the connection
+ attempt transitions from being in process to being complete.
+
+ @param [in] pSocket Address of the socket structure.
+
+ @retval EFI_SUCCESS The connection was successfully established.
+ @retval EFI_NOT_READY The connection is in progress, call this routine again.
+ @retval Others The connection attempt failed.
+
+ **/
+EFI_STATUS
+EslTcpConnectPoll4 (
+ IN DT_SOCKET * pSocket
+ )
+{
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Determine if the connection is complete
+ //
+ if ( !pSocket->bConnected ) {
+ //
+ // Not connected
+ //
+ pSocket->errno = EAGAIN;
+ Status = EFI_NOT_READY;
+ }
+ else {
+ //
+ // The connection processing is complete
+ //
+ pSocket->bConnected = FALSE;
+
+ //
+ // Translate the connection status
+ //
+ Status = pSocket->ConnectStatus;
+ switch ( Status ) {
+ default:
+ case EFI_DEVICE_ERROR:
+ pSocket->errno = EIO;
+ break;
+
+ case EFI_ABORTED:
+ pSocket->errno = ECONNREFUSED;
+ break;
+
+ case EFI_INVALID_PARAMETER:
+ pSocket->errno = EINVAL;
+ break;
+
+ case EFI_NO_MAPPING:
+ case EFI_NO_RESPONSE:
+ pSocket->errno = EHOSTUNREACH;
+ break;
+
+ case EFI_NO_MEDIA:
+ pSocket->errno = ENETDOWN;
+ break;
+
+ case EFI_OUT_OF_RESOURCES:
+ pSocket->errno = ENOMEM;
+ break;
+
+ case EFI_SUCCESS:
+ pSocket->errno = 0;
+ pSocket->bConfigured = TRUE;
+ break;
+
+ case EFI_TIMEOUT:
+ pSocket->errno = ETIMEDOUT;
+ break;
+
+ case EFI_UNSUPPORTED:
+ pSocket->errno = ENOTSUP;
+ break;
+
+ case 0x80000069:
+ pSocket->errno = ECONNRESET;
+ break;
+ }
+ }
+
+ //
+ // Return the initialization status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Connect to a remote system via the network.
+
+ The ::TcpConnectStart4= routine starts the connection processing
+ for a TCP4 port.
+
+ @param [in] pSocket Address of the socket structure.
+
+ @param [in] pSockAddr Network address of the remote system.
+
+ @param [in] SockAddrLength Length in bytes of the network address.
+
+ @retval EFI_SUCCESS The connection was successfully established.
+ @retval EFI_NOT_READY The connection is in progress, call this routine again.
+ @retval Others The connection attempt failed.
+
+ **/
+EFI_STATUS
+EslTcpConnectStart4 (
+ IN DT_SOCKET * pSocket,
+ IN const struct sockaddr * pSockAddr,
+ IN socklen_t SockAddrLength
+ )
+{
+ struct sockaddr_in LocalAddress;
+ DT_PORT * pPort;
+ DT_TCP4_CONTEXT * pTcp4;
+ CONST struct sockaddr_in * pIp4Address;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Validate the address length
+ //
+ Status = EFI_SUCCESS;
+ pIp4Address = (CONST struct sockaddr_in *) pSockAddr;
+ if ( SockAddrLength >= ( sizeof ( *pIp4Address )
+ - sizeof ( pIp4Address->sin_zero ))) {
+ //
+ // Determine if BIND was already called
+ //
+ if ( NULL == pSocket->pPortList ) {
+ //
+ // Allow any local port
+ //
+ ZeroMem ( &LocalAddress, sizeof ( LocalAddress ));
+ LocalAddress.sin_len = sizeof ( LocalAddress );
+ LocalAddress.sin_family = AF_INET;
+ Status = EslSocketBind ( &pSocket->SocketProtocol,
+ (struct sockaddr *)&LocalAddress,
+ LocalAddress.sin_len,
+ &pSocket->errno );
+ }
+ if ( NULL != pSocket->pPortList ) {
+ //
+ // Walk the list of ports
+ //
+ pPort = pSocket->pPortList;
+ while ( NULL != pPort ) {
+ //
+ // Set the remote address
+ //
+ pTcp4 = &pPort->Context.Tcp4;
+ *(UINT32 *)&pTcp4->ConfigData.AccessPoint.RemoteAddress = pIp4Address->sin_addr.s_addr;
+ pTcp4->ConfigData.AccessPoint.RemotePort = SwapBytes16 ( pIp4Address->sin_port );
+
+ //
+ // Set the next port
+ //
+ pPort = pPort->pLinkSocket;
+ }
+
+ //
+ // Attempt a connection using the first adapter
+ //
+ Status = EslTcpConnectAttempt4 ( pSocket );
+ }
+ }
+ else {
+ DEBUG (( DEBUG_CONNECT,
+ "ERROR - Invalid TCP4 address length: %d\r\n",
+ SockAddrLength ));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EINVAL;
+ }
+
+ //
+ // Return the initialization status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Initialize the TCP4 service.
+
+ This routine initializes the TCP4 service after its service binding
+ protocol was located on a controller.
+
+ @param [in] pService DT_SERVICE structure address
+
+ @retval EFI_SUCCESS The service was properly initialized
+ @retval other A failure occurred during the service initialization
+
+**/
+EFI_STATUS
+EFIAPI
+EslTcpInitialize4 (
+ IN DT_SERVICE * pService
+ )
+{
+ DT_LAYER * pLayer;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Identify the service
+ //
+ pService->NetworkType = NETWORK_TYPE_TCP4;
+
+ //
+ // Connect this service to the service list
+ //
+ pLayer = &mEslLayer;
+ pService->pNext = pLayer->pTcp4List;
+ pLayer->pTcp4List = pService;
+
+ //
+ // Assume the list is empty
+ //
+ Status = EFI_SUCCESS;
+
+ //
+ // Return the initialization status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Get the local socket address
+
+ @param [in] pSocket Address of the socket structure.
+
+ @param [out] pAddress Network address to receive the local system address
+
+ @param [in,out] pAddressLength Length of the local network address structure
+
+ @retval EFI_SUCCESS - Address available
+ @retval Other - Failed to get the address
+
+**/
+EFI_STATUS
+EslTcpGetLocalAddress4 (
+ IN DT_SOCKET * pSocket,
+ OUT struct sockaddr * pAddress,
+ IN OUT socklen_t * pAddressLength
+ )
+{
+ socklen_t LengthInBytes;
+ DT_PORT * pPort;
+ struct sockaddr_in * pLocalAddress;
+ DT_TCP4_CONTEXT * pTcp4;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Verify the socket layer synchronization
+ //
+ VERIFY_TPL ( TPL_SOCKETS );
+
+ //
+ // Verify that there is just a single connection
+ //
+ pPort = pSocket->pPortList;
+ if (( NULL != pPort ) && ( NULL == pPort->pLinkSocket )) {
+ //
+ // Verify the address length
+ //
+ LengthInBytes = sizeof ( struct sockaddr_in );
+ if ( LengthInBytes <= * pAddressLength ) {
+ //
+ // Return the local address
+ //
+ pTcp4 = &pPort->Context.Tcp4;
+ pLocalAddress = (struct sockaddr_in *)pAddress;
+ ZeroMem ( pLocalAddress, LengthInBytes );
+ pLocalAddress->sin_family = AF_INET;
+ pLocalAddress->sin_len = (uint8_t)LengthInBytes;
+ pLocalAddress->sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.StationPort );
+ CopyMem ( &pLocalAddress->sin_addr,
+ &pTcp4->ConfigData.AccessPoint.StationAddress.Addr[0],
+ sizeof ( pLocalAddress->sin_addr ));
+ pSocket->errno = 0;
+ Status = EFI_SUCCESS;
+ }
+ else {
+ pSocket->errno = EINVAL;
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+ else {
+ pSocket->errno = ENOTCONN;
+ Status = EFI_NOT_STARTED;
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Get the remote socket address
+
+ @param [in] pSocket Address of the socket structure.
+
+ @param [out] pAddress Network address to receive the remote system address
+
+ @param [in,out] pAddressLength Length of the remote network address structure
+
+ @retval EFI_SUCCESS - Address available
+ @retval Other - Failed to get the address
+
+**/
+EFI_STATUS
+EslTcpGetRemoteAddress4 (
+ IN DT_SOCKET * pSocket,
+ OUT struct sockaddr * pAddress,
+ IN OUT socklen_t * pAddressLength
+ )
+{
+ socklen_t LengthInBytes;
+ DT_PORT * pPort;
+ struct sockaddr_in * pRemoteAddress;
+ DT_TCP4_CONTEXT * pTcp4;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Verify the socket layer synchronization
+ //
+ VERIFY_TPL ( TPL_SOCKETS );
+
+ //
+ // Verify that there is just a single connection
+ //
+ pPort = pSocket->pPortList;
+ if (( NULL != pPort ) && ( NULL == pPort->pLinkSocket )) {
+ //
+ // Verify the address length
+ //
+ LengthInBytes = sizeof ( struct sockaddr_in );
+ if ( LengthInBytes <= * pAddressLength ) {
+ //
+ // Return the local address
+ //
+ pTcp4 = &pPort->Context.Tcp4;
+ pRemoteAddress = (struct sockaddr_in *)pAddress;
+ ZeroMem ( pRemoteAddress, LengthInBytes );
+ pRemoteAddress->sin_family = AF_INET;
+ pRemoteAddress->sin_len = (uint8_t)LengthInBytes;
+ pRemoteAddress->sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.RemotePort );
+ CopyMem ( &pRemoteAddress->sin_addr,
+ &pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],
+ sizeof ( pRemoteAddress->sin_addr ));
+ pSocket->errno = 0;
+ Status = EFI_SUCCESS;
+ }
+ else {
+ pSocket->errno = EINVAL;
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+ else {
+ pSocket->errno = ENOTCONN;
+ Status = EFI_NOT_STARTED;
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Establish the known port to listen for network connections.
+
+ The ::Tcp4Listen routine places the port into a state that enables connection
+ attempts. Connections are placed into FIFO order in a queue to be serviced
+ by the application. The application calls the ::Tcp4Accept routine to remove
+ the next connection from the queue and get the associated socket. The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html">POSIX</a>
+ documentation for the listen routine is available online for reference.
+
+ @param [in] pSocket Address of the socket structure.
+
+ @retval EFI_SUCCESS - Socket successfully created
+ @retval Other - Failed to enable the socket for listen
+
+**/
+EFI_STATUS
+EslTcpListen4 (
+ IN DT_SOCKET * pSocket
+ )
+{
+ DT_PORT * pNextPort;
+ DT_PORT * pPort;
+ DT_TCP4_CONTEXT * pTcp4;
+ EFI_TCP4_PROTOCOL * pTcp4Protocol;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Verify the socket layer synchronization
+ //
+ VERIFY_TPL ( TPL_SOCKETS );
+
+ //
+ // Use for/break instead of goto
+ //
+ for ( ; ; ) {
+ //
+ // Assume no ports are available
+ //
+ pSocket->errno = EOPNOTSUPP;
+ Status = EFI_NOT_READY;
+
+ //
+ // Walk the list of ports
+ //
+ pPort = pSocket->pPortList;
+ while ( NULL != pPort ) {
+ //
+ // Assume success
+ //
+ pSocket->errno = 0;
+
+ //
+ // Use for/break insteak of goto
+ //
+ for ( ; ; ) {
+ //
+ // Create the listen completion event
+ //
+ pTcp4 = &pPort->Context.Tcp4;
+ Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
+ TPL_SOCKETS,
+ (EFI_EVENT_NOTIFY)EslTcpListenComplete4,
+ pPort,
+ &pTcp4->ListenToken.CompletionToken.Event );
+ if ( EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_ERROR | DEBUG_LISTEN,
+ "ERROR - Failed to create the listen completion event, Status: %r\r\n",
+ Status ));
+ pSocket->errno = ENOMEM;
+ break;
+ }
+ DEBUG (( DEBUG_POOL,
+ "0x%08x: Created listen completion event\r\n",
+ pTcp4->ListenToken.CompletionToken.Event ));
+
+ //
+ // Configure the port
+ //
+ pTcp4Protocol = pTcp4->pProtocol;
+ Status = pTcp4Protocol->Configure ( pTcp4Protocol,
+ &pTcp4->ConfigData );
+ if ( EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_LISTEN,
+ "ERROR - Failed to configure the Tcp4 port, Status: %r\r\n",
+ Status ));
+ switch ( Status ) {
+ case EFI_ACCESS_DENIED:
+ pSocket->errno = EACCES;
+ break;
+
+ default:
+ case EFI_DEVICE_ERROR:
+ pSocket->errno = EIO;
+ break;
+
+ case EFI_INVALID_PARAMETER:
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case EFI_NO_MAPPING:
+ pSocket->errno = EAFNOSUPPORT;
+ break;
+
+ case EFI_OUT_OF_RESOURCES:
+ pSocket->errno = ENOBUFS;
+ break;
+
+ case EFI_UNSUPPORTED:
+ pSocket->errno = EOPNOTSUPP;
+ break;
+ }
+ break;
+ }
+ DEBUG (( DEBUG_LISTEN,
+ "0x%08x: Port configured\r\n",
+ pPort ));
+ pTcp4->bConfigured = TRUE;
+
+ //
+ // Start the listen operation on the port
+ //
+ Status = pTcp4Protocol->Accept ( pTcp4Protocol,
+ &pTcp4->ListenToken );
+ if ( EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_LISTEN,
+ "ERROR - Failed Tcp4 accept, Status: %r\r\n",
+ Status ));
+ switch ( Status ) {
+ case EFI_ACCESS_DENIED:
+ pSocket->errno = EACCES;
+ break;
+
+ default:
+ case EFI_DEVICE_ERROR:
+ pSocket->errno = EIO;
+ break;
+
+ case EFI_INVALID_PARAMETER:
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case EFI_NOT_STARTED:
+ pSocket->errno = ENETDOWN;
+ break;
+
+ case EFI_OUT_OF_RESOURCES:
+ pSocket->errno = ENOBUFS;
+ break;
+ }
+ break;
+ }
+ DEBUG (( DEBUG_LISTEN,
+ "0x%08x: Listen pending on Port\r\n",
+ pPort ));
+
+ //
+ // Listen is pending on this port
+ //
+ break;
+ }
+
+ //
+ // Get the next port
+ //
+ pNextPort = pPort->pLinkSocket;
+
+ //
+ // Close the port upon error
+ //
+ if ( EFI_ERROR ( Status ))
+ {
+ EslTcpPortCloseStart4 ( pPort, TRUE, DEBUG_LISTEN );
+ }
+
+ //
+ // Set the next port
+ //
+ pPort = pNextPort;
+ }
+
+ //
+ // Determine if any ports are in the listen state
+ //
+ if ( NULL == pSocket->pPortList ) {
+ //
+ // No ports in the listen state
+ //
+ pSocket->MaxFifoDepth = 0;
+
+ //
+ // Return the last error detected
+ //
+ break;
+ }
+
+ //
+ // Mark the socket as configured
+ //
+ pSocket->bConfigured = TRUE;
+
+ //
+ // All done
+ //
+ DEBUG (( DEBUG_LISTEN,
+ "0x%08x: pSocket - Listen pending on socket\r\n",
+ pSocket ));
+ break;
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Process the connection attempt
+
+ A system has initiated a connection attempt with a socket in the
+ listen state. Attempt to complete the connection.
+
+ @param Event The listen completion event
+
+ @param pPort The DT_PORT structure address
+
+**/
+VOID
+EslTcpListenComplete4 (
+ IN EFI_EVENT Event,
+ IN DT_PORT * pPort
+ )
+{
+ EFI_HANDLE ChildHandle;
+ EFI_TCP4_CONFIG_DATA * pConfigData;
+ DT_LAYER * pLayer;
+ DT_PORT * pNewPort;
+ DT_SOCKET * pNewSocket;
+ DT_SOCKET * pSocket;
+ DT_TCP4_CONTEXT * pTcp4;
+ EFI_TCP4_PROTOCOL * pTcp4Protocol;
+ EFI_STATUS Status;
+ EFI_HANDLE TcpPortHandle;
+ EFI_STATUS TempStatus;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume success
+ //
+ Status = EFI_SUCCESS;
+
+ //
+ // Determine if this connection fits into the connection FIFO
+ //
+ pSocket = pPort->pSocket;
+ TcpPortHandle = pPort->Context.Tcp4.ListenToken.NewChildHandle;
+ if (( SOCKET_STATE_LISTENING == pSocket->State )
+ && ( pSocket->MaxFifoDepth > pSocket->FifoDepth )) {
+ //
+ // Allocate a socket for this connection
+ //
+ ChildHandle = NULL;
+ pLayer = &mEslLayer;
+ Status = EslSocketAllocate ( &ChildHandle,
+ DEBUG_CONNECTION,
+ &pNewSocket );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Clone the socket parameters
+ //
+ pNewSocket->Domain = pSocket->Domain;
+ pNewSocket->Protocol = pSocket->Protocol;
+ pNewSocket->Type = pSocket->Type;
+
+ //
+ // Allocate a port for this connection
+ //
+ pTcp4 = &pPort->Context.Tcp4;
+ Status = EslTcpPortAllocate4 ( pNewSocket,
+ pPort->pService,
+ TcpPortHandle,
+ &pTcp4->ConfigData.AccessPoint.StationAddress.Addr[0],
+ 0,
+ DEBUG_CONNECTION,
+ &pNewPort );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Restart the listen operation on the port
+ //
+ pTcp4Protocol = pTcp4->pProtocol;
+ Status = pTcp4Protocol->Accept ( pTcp4Protocol,
+ &pTcp4->ListenToken );
+
+ //
+ // Close the TCP port using SocketClose
+ //
+ TcpPortHandle = NULL;
+ pTcp4 = &pNewPort->Context.Tcp4;
+ pTcp4->bConfigured = TRUE;
+
+ //
+ // Check for an accept call error
+ //
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Get the port configuration
+ //
+ pConfigData = &pTcp4->ConfigData;
+ pConfigData->ControlOption = &pTcp4->Option;
+ pTcp4Protocol = pTcp4->pProtocol;
+ Status = pTcp4Protocol->GetModeData ( pTcp4Protocol,
+ NULL,
+ pConfigData,
+ NULL,
+ NULL,
+ NULL );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Add the new socket to the connection FIFO
+ //
+ if ( NULL == pSocket->pFifoTail ) {
+ //
+ // First connection
+ //
+ pSocket->pFifoHead = pNewSocket;
+ }
+ else {
+ //
+ // Add to end of list.
+ //
+ pSocket->pFifoTail->pNextConnection = pNewSocket;
+ }
+ pSocket->pFifoTail = pNewSocket;
+ pSocket->FifoDepth += 1;
+
+ //
+ // Update the socket state
+ //
+ pNewSocket->State = SOCKET_STATE_IN_FIFO;
+
+ //
+ // Log the connection
+ //
+ DEBUG (( DEBUG_CONNECTION | DEBUG_INFO,
+ "0x%08x: Socket on port %d.%d.%d.%d:%d connected to %d.%d.%d.%d:%d\r\n",
+ pNewSocket,
+ pConfigData->AccessPoint.StationAddress.Addr[0],
+ pConfigData->AccessPoint.StationAddress.Addr[1],
+ pConfigData->AccessPoint.StationAddress.Addr[2],
+ pConfigData->AccessPoint.StationAddress.Addr[3],
+ pConfigData->AccessPoint.StationPort,
+ pConfigData->AccessPoint.RemoteAddress.Addr[0],
+ pConfigData->AccessPoint.RemoteAddress.Addr[1],
+ pConfigData->AccessPoint.RemoteAddress.Addr[2],
+ pConfigData->AccessPoint.RemoteAddress.Addr[3],
+ pConfigData->AccessPoint.RemotePort ));
+ DEBUG (( DEBUG_CONNECTION | DEBUG_INFO,
+ "0x%08x: Listen socket adding socket 0x%08x to FIFO, depth: %d\r\n",
+ pSocket,
+ pNewSocket,
+ pSocket->FifoDepth ));
+
+ //
+ // Start the receive operation
+ //
+ EslTcpRxStart4 ( pNewPort );
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_CONNECTION | DEBUG_INFO,
+ "ERROR - GetModeData failed on port 0x%08x, Status: %r\r\n",
+ pNewPort,
+ Status ));
+ }
+ }
+ else {
+ //
+ // The listen failed on this port
+ //
+ DEBUG (( DEBUG_LISTEN | DEBUG_INFO,
+ "ERROR - Listen failed on port 0x%08x, Status: %r\r\n",
+ pPort,
+ Status ));
+
+ //
+ // Close the listening port
+ //
+ EslTcpPortCloseStart4 ( pPort, TRUE, DEBUG_LISTEN );
+ }
+ }
+
+ //
+ // Done with the socket if necessary
+ //
+ if ( EFI_ERROR ( Status )) {
+ TempStatus = EslSocketCloseStart ( &pNewSocket->SocketProtocol,
+ TRUE,
+ &pSocket->errno );
+ ASSERT ( EFI_SUCCESS == TempStatus );
+ }
+ }
+ }
+ else {
+ DEBUG (( DEBUG_CONNECTION,
+ "0x%08x: Socket FIFO full, connection refused\r\n",
+ pSocket ));
+
+ //
+ // The FIFO is full or the socket is in the wrong state
+ //
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Close the connection if necessary
+ //
+ if (( EFI_ERROR ( Status ))
+ && ( NULL == TcpPortHandle )) {
+ //
+ // TODO: Finish this code path
+ // The new connection does not fit into the connection FIFO
+ //
+ // Process:
+ // Call close
+ // Release the resources
+
+ }
+
+ DBG_EXIT ( );
+}
+
+
+/**
+ Allocate and initialize a DT_PORT structure.
+
+ @param [in] pSocket Address of the socket structure.
+ @param [in] pService Address of the DT_SERVICE structure.
+ @param [in] ChildHandle TCP4 child handle
+ @param [in] pIpAddress Buffer containing IP4 network address of the local host
+ @param [in] PortNumber Tcp4 port number
+ @param [in] DebugFlags Flags for debug messages
+ @param [out] ppPort Buffer to receive new DT_PORT structure address
+
+ @retval EFI_SUCCESS - Socket successfully created
+
+ **/
+EFI_STATUS
+EslTcpPortAllocate4 (
+ IN DT_SOCKET * pSocket,
+ IN DT_SERVICE * pService,
+ IN EFI_HANDLE ChildHandle,
+ IN CONST UINT8 * pIpAddress,
+ IN UINT16 PortNumber,
+ IN UINTN DebugFlags,
+ OUT DT_PORT ** ppPort
+ )
+{
+ UINTN LengthInBytes;
+ EFI_TCP4_ACCESS_POINT * pAccessPoint;
+ DT_LAYER * pLayer;
+ DT_PORT * pPort;
+ DT_TCP4_CONTEXT * pTcp4;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Use for/break instead of goto
+ for ( ; ; ) {
+ //
+ // Allocate a port structure
+ //
+ pLayer = &mEslLayer;
+ LengthInBytes = sizeof ( *pPort );
+ Status = gBS->AllocatePool ( EfiRuntimeServicesData,
+ LengthInBytes,
+ (VOID **)&pPort );
+ if ( EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL | DEBUG_INIT,
+ "ERROR - Failed to allocate the port structure, Status: %r\r\n",
+ Status ));
+ pSocket->errno = ENOMEM;
+ pPort = NULL;
+ break;
+ }
+ DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT,
+ "0x%08x: Allocate pPort, %d bytes\r\n",
+ pPort,
+ LengthInBytes ));
+
+ //
+ // Initialize the port
+ //
+ ZeroMem ( pPort, LengthInBytes );
+ pPort->Signature = PORT_SIGNATURE;
+ pPort->pService = pService;
+ pPort->pSocket = pSocket;
+ pPort->pfnCloseStart = EslTcpPortCloseStart4;
+ pPort->DebugFlags = DebugFlags;
+
+ //
+ // Allocate the receive event
+ //
+ pTcp4 = &pPort->Context.Tcp4;
+ Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
+ TPL_SOCKETS,
+ (EFI_EVENT_NOTIFY)EslTcpRxComplete4,
+ pPort,
+ &pTcp4->RxToken.CompletionToken.Event);
+ if ( EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_ERROR | DebugFlags,
+ "ERROR - Failed to create the receive event, Status: %r\r\n",
+ Status ));
+ pSocket->errno = ENOMEM;
+ break;
+ }
+ DEBUG (( DEBUG_RX | DEBUG_POOL,
+ "0x%08x: Created receive event\r\n",
+ pTcp4->RxToken.CompletionToken.Event ));
+
+ //
+ // Allocate the urgent transmit event
+ //
+ Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
+ TPL_SOCKETS,
+ (EFI_EVENT_NOTIFY)EslTcpTxOobComplete4,
+ pPort,
+ &pTcp4->TxOobToken.CompletionToken.Event);
+ if ( EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_ERROR | DebugFlags,
+ "ERROR - Failed to create the urgent transmit event, Status: %r\r\n",
+ Status ));
+ pSocket->errno = ENOMEM;
+ break;
+ }
+ DEBUG (( DEBUG_CLOSE | DEBUG_POOL,
+ "0x%08x: Created urgent transmit event\r\n",
+ pTcp4->TxOobToken.CompletionToken.Event ));
+
+ //
+ // Allocate the normal transmit event
+ //
+ Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
+ TPL_SOCKETS,
+ (EFI_EVENT_NOTIFY)EslTcpTxComplete4,
+ pPort,
+ &pTcp4->TxToken.CompletionToken.Event);
+ if ( EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_ERROR | DebugFlags,
+ "ERROR - Failed to create the normal transmit event, Status: %r\r\n",
+ Status ));
+ pSocket->errno = ENOMEM;
+ break;
+ }
+ DEBUG (( DEBUG_CLOSE | DEBUG_POOL,
+ "0x%08x: Created normal transmit event\r\n",
+ pTcp4->TxToken.CompletionToken.Event ));
+
+ //
+ // Allocate the close event
+ //
+ Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
+ TPL_SOCKETS,
+ (EFI_EVENT_NOTIFY)EslTcpPortCloseComplete4,
+ pPort,
+ &pTcp4->CloseToken.CompletionToken.Event);
+ if ( EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_ERROR | DebugFlags,
+ "ERROR - Failed to create the close event, Status: %r\r\n",
+ Status ));
+ pSocket->errno = ENOMEM;
+ break;
+ }
+ DEBUG (( DEBUG_CLOSE | DEBUG_POOL,
+ "0x%08x: Created close event\r\n",
+ pTcp4->CloseToken.CompletionToken.Event ));
+
+ //
+ // Allocate the connection event
+ //
+ Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
+ TPL_SOCKETS,
+ (EFI_EVENT_NOTIFY)EslTcpConnectComplete4,
+ pPort,
+ &pTcp4->ConnectToken.CompletionToken.Event);
+ if ( EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_ERROR | DebugFlags,
+ "ERROR - Failed to create the connect event, Status: %r\r\n",
+ Status ));
+ pSocket->errno = ENOMEM;
+ break;
+ }
+ DEBUG (( DEBUG_CLOSE | DEBUG_POOL,
+ "0x%08x: Created connect event\r\n",
+ pTcp4->ConnectToken.CompletionToken.Event ));
+
+ //
+ // Open the port protocol
+ //
+ Status = gBS->OpenProtocol (
+ ChildHandle,
+ &gEfiTcp4ProtocolGuid,
+ (VOID **) &pTcp4->pProtocol,
+ pLayer->ImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );
+ if ( EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_ERROR | DebugFlags,
+ "ERROR - Failed to open gEfiTcp4ProtocolGuid on controller 0x%08x\r\n",
+ pTcp4->Handle ));
+ pSocket->errno = EEXIST;
+ break;
+ }
+ DEBUG (( DebugFlags,
+ "0x%08x: gEfiTcp4ProtocolGuid opened on controller 0x%08x\r\n",
+ pTcp4->pProtocol,
+ ChildHandle ));
+
+ //
+ // Set the port address
+ //
+ pTcp4->Handle = ChildHandle;
+ pAccessPoint = &pPort->Context.Tcp4.ConfigData.AccessPoint;
+ pAccessPoint->StationPort = PortNumber;
+ if (( 0 == pIpAddress[0])
+ && ( 0 == pIpAddress[1])
+ && ( 0 == pIpAddress[2])
+ && ( 0 == pIpAddress[3])) {
+ pAccessPoint->UseDefaultAddress = TRUE;
+ }
+ else {
+ pAccessPoint->StationAddress.Addr[0] = pIpAddress[0];
+ pAccessPoint->StationAddress.Addr[1] = pIpAddress[1];
+ pAccessPoint->StationAddress.Addr[2] = pIpAddress[2];
+ pAccessPoint->StationAddress.Addr[3] = pIpAddress[3];
+ pAccessPoint->SubnetMask.Addr[0] = 0xff;
+ pAccessPoint->SubnetMask.Addr[1] = 0xff;
+ pAccessPoint->SubnetMask.Addr[2] = 0xff;
+ pAccessPoint->SubnetMask.Addr[3] = 0xff;
+ }
+ pAccessPoint->ActiveFlag = FALSE;
+ pTcp4->ConfigData.TimeToLive = 255;
+
+ //
+ // Verify the socket layer synchronization
+ //
+ VERIFY_TPL ( TPL_SOCKETS );
+
+ //
+ // Add this port to the socket
+ //
+ pPort->pLinkSocket = pSocket->pPortList;
+ pSocket->pPortList = pPort;
+ DEBUG (( DebugFlags,
+ "0x%08x: Socket adding port: 0x%08x\r\n",
+ pSocket,
+ pPort ));
+
+ //
+ // Add this port to the service
+ //
+ pPort->pLinkService = pService->pPortList;
+ pService->pPortList = pPort;
+
+ //
+ // Return the port
+ //
+ *ppPort = pPort;
+ break;
+ }
+
+ //
+ // Clean up after the error if necessary
+ //
+ if (( EFI_ERROR ( Status )) && ( NULL != pPort )) {
+ //
+ // Close the port
+ //
+ EslTcpPortClose4 ( pPort );
+ }
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Close a TCP4 port.
+
+ This routine releases the resources allocated by
+ ::TcpPortAllocate4().
+
+ @param [in] pPort Address of the port structure.
+
+ @retval EFI_SUCCESS The port is closed
+ @retval other Port close error
+
+**/
+EFI_STATUS
+EslTcpPortClose4 (
+ IN DT_PORT * pPort
+ )
+{
+ UINTN DebugFlags;
+ DT_LAYER * pLayer;
+ DT_PACKET * pPacket;
+ DT_PORT * pPreviousPort;
+ DT_SERVICE * pService;
+ DT_SOCKET * pSocket;
+ EFI_SERVICE_BINDING_PROTOCOL * pTcp4Service;
+ DT_TCP4_CONTEXT * pTcp4;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Verify the socket layer synchronization
+ //
+ VERIFY_TPL ( TPL_SOCKETS );
+
+ //
+ // Locate the port in the socket list
+ //
+ Status = EFI_SUCCESS;
+ pLayer = &mEslLayer;
+ DebugFlags = pPort->DebugFlags;
+ pSocket = pPort->pSocket;
+ pPreviousPort = pSocket->pPortList;
+ if ( pPreviousPort == pPort ) {
+ //
+ // Remove this port from the head of the socket list
+ //
+ pSocket->pPortList = pPort->pLinkSocket;
+ }
+ else {
+ //
+ // Locate the port in the middle of the socket list
+ //
+ while (( NULL != pPreviousPort )
+ && ( pPreviousPort->pLinkSocket != pPort )) {
+ pPreviousPort = pPreviousPort->pLinkSocket;
+ }
+ if ( NULL != pPreviousPort ) {
+ //
+ // Remove the port from the middle of the socket list
+ //
+ pPreviousPort->pLinkSocket = pPort->pLinkSocket;
+ }
+ }
+
+ //
+ // Locate the port in the service list
+ //
+ pService = pPort->pService;
+ pPreviousPort = pService->pPortList;
+ if ( pPreviousPort == pPort ) {
+ //
+ // Remove this port from the head of the service list
+ //
+ pService->pPortList = pPort->pLinkService;
+ }
+ else {
+ //
+ // Locate the port in the middle of the service list
+ //
+ while (( NULL != pPreviousPort )
+ && ( pPreviousPort->pLinkService != pPort )) {
+ pPreviousPort = pPreviousPort->pLinkService;
+ }
+ if ( NULL != pPreviousPort ) {
+ //
+ // Remove the port from the middle of the service list
+ //
+ pPreviousPort->pLinkService = pPort->pLinkService;
+ }
+ }
+
+ //
+ // Empty the urgent receive queue
+ //
+ pTcp4 = &pPort->Context.Tcp4;
+ while ( NULL != pSocket->pRxOobPacketListHead ) {
+ pPacket = pSocket->pRxOobPacketListHead;
+ pSocket->pRxOobPacketListHead = pPacket->pNext;
+ pSocket->RxOobBytes -= pPacket->Op.Tcp4Rx.ValidBytes;
+ EslSocketPacketFree ( pPacket, DEBUG_RX );
+ }
+ pSocket->pRxOobPacketListTail = NULL;
+ ASSERT ( 0 == pSocket->RxOobBytes );
+
+ //
+ // Empty the receive queue
+ //
+ while ( NULL != pSocket->pRxPacketListHead ) {
+ pPacket = pSocket->pRxPacketListHead;
+ pSocket->pRxPacketListHead = pPacket->pNext;
+ pSocket->RxBytes -= pPacket->Op.Tcp4Rx.ValidBytes;
+ EslSocketPacketFree ( pPacket, DEBUG_RX );
+ }
+ pSocket->pRxPacketListTail = NULL;
+ ASSERT ( 0 == pSocket->RxBytes );
+
+ //
+ // Empty the receive free queue
+ //
+ while ( NULL != pSocket->pRxFree ) {
+ pPacket = pSocket->pRxFree;
+ pSocket->pRxFree = pPacket->pNext;
+ EslSocketPacketFree ( pPacket, DEBUG_RX );
+ }
+
+ //
+ // Done with the connect event
+ //
+ if ( NULL != pTcp4->ConnectToken.CompletionToken.Event ) {
+ Status = gBS->CloseEvent ( pTcp4->ConnectToken.CompletionToken.Event );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DebugFlags | DEBUG_POOL,
+ "0x%08x: Closed connect event\r\n",
+ pTcp4->ConnectToken.CompletionToken.Event ));
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DebugFlags,
+ "ERROR - Failed to close the connect event, Status: %r\r\n",
+ Status ));
+ ASSERT ( EFI_SUCCESS == Status );
+ }
+ }
+
+ //
+ // Done with the close event
+ //
+ if ( NULL != pTcp4->CloseToken.CompletionToken.Event ) {
+ Status = gBS->CloseEvent ( pTcp4->CloseToken.CompletionToken.Event );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DebugFlags | DEBUG_POOL,
+ "0x%08x: Closed close event\r\n",
+ pTcp4->CloseToken.CompletionToken.Event ));
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DebugFlags,
+ "ERROR - Failed to close the close event, Status: %r\r\n",
+ Status ));
+ ASSERT ( EFI_SUCCESS == Status );
+ }
+ }
+
+ //
+ // Done with the listen completion event
+ //
+ if ( NULL != pTcp4->ListenToken.CompletionToken.Event ) {
+ Status = gBS->CloseEvent ( pTcp4->ListenToken.CompletionToken.Event );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DebugFlags | DEBUG_POOL,
+ "0x%08x: Closed listen completion event\r\n",
+ pTcp4->ListenToken.CompletionToken.Event ));
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DebugFlags,
+ "ERROR - Failed to close the listen completion event, Status: %r\r\n",
+ Status ));
+ ASSERT ( EFI_SUCCESS == Status );
+ }
+ }
+
+ //
+ // Done with the receive event
+ //
+ if ( NULL != pTcp4->RxToken.CompletionToken.Event ) {
+ Status = gBS->CloseEvent ( pTcp4->RxToken.CompletionToken.Event );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DebugFlags | DEBUG_POOL,
+ "0x%08x: Closed receive event\r\n",
+ pTcp4->RxToken.CompletionToken.Event ));
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DebugFlags,
+ "ERROR - Failed to close the receive event, Status: %r\r\n",
+ Status ));
+ ASSERT ( EFI_SUCCESS == Status );
+ }
+ }
+
+ //
+ // Done with the normal transmit event
+ //
+ if ( NULL != pTcp4->TxToken.CompletionToken.Event ) {
+ Status = gBS->CloseEvent ( pTcp4->TxToken.CompletionToken.Event );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DebugFlags | DEBUG_POOL,
+ "0x%08x: Closed normal transmit event\r\n",
+ pTcp4->TxToken.CompletionToken.Event ));
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DebugFlags,
+ "ERROR - Failed to close the normal transmit event, Status: %r\r\n",
+ Status ));
+ ASSERT ( EFI_SUCCESS == Status );
+ }
+ }
+
+ //
+ // Done with the urgent transmit event
+ //
+ if ( NULL != pTcp4->TxOobToken.CompletionToken.Event ) {
+ Status = gBS->CloseEvent ( pTcp4->TxOobToken.CompletionToken.Event );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DebugFlags | DEBUG_POOL,
+ "0x%08x: Closed urgent transmit event\r\n",
+ pTcp4->TxOobToken.CompletionToken.Event ));
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DebugFlags,
+ "ERROR - Failed to close the urgent transmit event, Status: %r\r\n",
+ Status ));
+ ASSERT ( EFI_SUCCESS == Status );
+ }
+ }
+
+ //
+ // Done with the TCP protocol
+ //
+ pTcp4Service = pService->pInterface;
+ if ( NULL != pTcp4->pProtocol ) {
+ Status = gBS->CloseProtocol ( pTcp4->Handle,
+ &gEfiTcp4ProtocolGuid,
+ pLayer->ImageHandle,
+ NULL );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DebugFlags,
+ "0x%08x: gEfiTcp4ProtocolGuid closed on controller 0x%08x\r\n",
+ pTcp4->pProtocol,
+ pTcp4->Handle ));
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DebugFlags,
+ "ERROR - Failed to close gEfiTcp4ProtocolGuid opened on controller 0x%08x, Status: %r\r\n",
+ pTcp4->Handle,
+ Status ));
+ ASSERT ( EFI_SUCCESS == Status );
+ }
+ }
+
+ //
+ // Done with the TCP port
+ //
+ if ( NULL != pTcp4->Handle ) {
+ Status = pTcp4Service->DestroyChild ( pTcp4Service,
+ pTcp4->Handle );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DebugFlags | DEBUG_POOL,
+ "0x%08x: Tcp4 port handle destroyed\r\n",
+ pTcp4->Handle ));
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL,
+ "ERROR - Failed to destroy the Tcp4 port handle, Status: %r\r\n",
+ Status ));
+ ASSERT ( EFI_SUCCESS == Status );
+ }
+ }
+
+ //
+ // Release the port structure
+ //
+ Status = gBS->FreePool ( pPort );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DebugFlags | DEBUG_POOL,
+ "0x%08x: Free pPort, %d bytes\r\n",
+ pPort,
+ sizeof ( *pPort )));
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL,
+ "ERROR - Failed to free pPort: 0x%08x, Status: %r\r\n",
+ pPort,
+ Status ));
+ ASSERT ( EFI_SUCCESS == Status );
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Process the port close completion
+
+ @param Event The close completion event
+
+ @param pPort The DT_PORT structure address
+
+**/
+VOID
+EslTcpPortCloseComplete4 (
+ IN EFI_EVENT Event,
+ IN DT_PORT * pPort
+ )
+{
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Update the port state
+ //
+ pPort->State = PORT_STATE_CLOSE_DONE;
+
+ //
+ // Release the resources once the receive operation completes
+ //
+ Status = EslTcpPortCloseRxDone4 ( pPort );
+ DBG_EXIT_STATUS ( Status );
+}
+
+
+/**
+ Start the close operation on a TCP4 port, state 1.
+
+ Closing a port goes through the following states:
+ 1. Port close starting - Mark the port as closing and wait for transmission to complete
+ 2. Port TX close done - Transmissions complete, close the port and abort the receives
+ 3. Port RX close done - Receive operations complete, close the port
+ 4. Port closed - Release the port resources
+
+ @param [in] pPort Address of the port structure.
+ @param [in] bCloseNow Set TRUE to abort active transfers
+ @param [in] DebugFlags Flags for debug messages
+
+ @retval EFI_SUCCESS The port is closed, not normally returned
+ @retval EFI_NOT_READY The port has started the closing process
+ @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
+ most likely the routine was called already.
+
+**/
+EFI_STATUS
+EslTcpPortCloseStart4 (
+ IN DT_PORT * pPort,
+ IN BOOLEAN bCloseNow,
+ IN UINTN DebugFlags
+ )
+{
+ DT_SOCKET * pSocket;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Verify the socket layer synchronization
+ //
+ VERIFY_TPL ( TPL_SOCKETS );
+
+ //
+ // Mark the port as closing
+ //
+ Status = EFI_ALREADY_STARTED;
+ pSocket = pPort->pSocket;
+ pSocket->errno = EALREADY;
+ if ( PORT_STATE_CLOSE_STARTED > pPort->State ) {
+
+ //
+ // Update the port state
+ //
+ pPort->State = PORT_STATE_CLOSE_STARTED;
+ DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
+ "0x%08x: Port Close State: PORT_STATE_CLOSE_STARTED\r\n",
+ pPort ));
+ pPort->bCloseNow = bCloseNow;
+ pPort->DebugFlags = DebugFlags;
+
+ //
+ // Determine if transmits are complete
+ //
+ Status = EslTcpPortCloseTxDone4 ( pPort );
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Port close state 3
+
+ Continue the close operation after the receive is complete.
+
+ @param [in] pPort Address of the port structure.
+
+ @retval EFI_SUCCESS The port is closed
+ @retval EFI_NOT_READY The port is still closing
+ @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
+ most likely the routine was called already.
+
+**/
+EFI_STATUS
+EslTcpPortCloseRxDone4 (
+ IN DT_PORT * pPort
+ )
+{
+ PORT_STATE PortState;
+ DT_TCP4_CONTEXT * pTcp4;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Verify the socket layer synchronization
+ //
+ VERIFY_TPL ( TPL_SOCKETS );
+
+ //
+ // Verify that the port is closing
+ //
+ Status = EFI_ALREADY_STARTED;
+ PortState = pPort->State;
+ if (( PORT_STATE_CLOSE_TX_DONE == PortState )
+ || ( PORT_STATE_CLOSE_DONE == PortState )) {
+ //
+ // Determine if the receive operation is pending
+ //
+ Status = EFI_NOT_READY;
+ pTcp4 = &pPort->Context.Tcp4;
+ if ( NULL == pTcp4->pReceivePending ) {
+ //
+ // The receive operation is complete
+ // Update the port state
+ //
+ pPort->State = PORT_STATE_CLOSE_RX_DONE;
+ DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
+ "0x%08x: Port Close State: PORT_STATE_CLOSE_RX_DONE\r\n",
+ pPort ));
+
+ //
+ // Determine if the close operation has completed
+ //
+ if ( PORT_STATE_CLOSE_DONE == PortState ) {
+ //
+ // The close operation has completed
+ // Release the port resources
+ //
+ Status = EslTcpPortClose4 ( pPort );
+ }
+ else
+ {
+ DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
+ "0x%08x: Port Close: Close operation still pending!\r\n",
+ pPort ));
+ }
+ }
+ else {
+ DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
+ "0x%08x: Port Close: Receive still pending!\r\n",
+ pPort ));
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Port close state 2
+
+ Continue the close operation after the transmission is complete.
+
+ @param [in] pPort Address of the port structure.
+
+ @retval EFI_SUCCESS The port is closed, not normally returned
+ @retval EFI_NOT_READY The port is still closing
+ @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
+ most likely the routine was called already.
+
+**/
+EFI_STATUS
+EslTcpPortCloseTxDone4 (
+ IN DT_PORT * pPort
+ )
+{
+ DT_SOCKET * pSocket;
+ DT_TCP4_CONTEXT * pTcp4;
+ EFI_TCP4_PROTOCOL * pTcp4Protocol;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Verify the socket layer synchronization
+ //
+ VERIFY_TPL ( TPL_SOCKETS );
+
+ //
+ // All transmissions are complete or must be stopped
+ // Mark the port as TX complete
+ //
+ Status = EFI_ALREADY_STARTED;
+ if ( PORT_STATE_CLOSE_STARTED == pPort->State ) {
+ //
+ // Verify that the transmissions are complete
+ //
+ pSocket = pPort->pSocket;
+ if ( pPort->bCloseNow
+ || ( EFI_SUCCESS != pSocket->TxError )
+ || (( 0 == pSocket->TxOobBytes )
+ && ( 0 == pSocket->TxBytes ))) {
+ //
+ // Start the close operation on the port
+ //
+ pTcp4 = &pPort->Context.Tcp4;
+ pTcp4->CloseToken.AbortOnClose = FALSE;
+ pTcp4Protocol = pTcp4->pProtocol;
+ if ( !pTcp4->bConfigured ) {
+ //
+ // Skip the close operation since the port is not
+ // configured
+ //
+ // Update the port state
+ //
+ pPort->State = PORT_STATE_CLOSE_DONE;
+ DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
+ "0x%08x: Port Close State: PORT_STATE_CLOSE_DONE\r\n",
+ pPort ));
+ Status = EFI_SUCCESS;
+ }
+ else {
+ //
+ // Close the configured port
+ //
+ Status = pTcp4Protocol->Close ( pTcp4Protocol,
+ &pTcp4->CloseToken );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,
+ "0x%08x: Port close started\r\n",
+ pPort ));
+
+ //
+ // Update the port state
+ //
+ pPort->State = PORT_STATE_CLOSE_TX_DONE;
+ DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
+ "0x%08x: Port Close State: PORT_STATE_CLOSE_TX_DONE\r\n",
+ pPort ));
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,
+ "ERROR - Close failed on port 0x%08x, Status: %r\r\n",
+ pPort,
+ Status ));
+ ASSERT ( EFI_SUCCESS == Status );
+ }
+ }
+
+ //
+ // Determine if the receive operation is pending
+ //
+ if ( !EFI_ERROR ( Status )) {
+ Status = EslTcpPortCloseRxDone4 ( pPort );
+ }
+ }
+ else {
+ //
+ // Transmissions are still active, exit
+ //
+ DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
+ "0x%08x: Port Close: Transmits are still pending!\r\n",
+ pPort ));
+ Status = EFI_NOT_READY;
+ pSocket->errno = EAGAIN;
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Receive data from a network connection.
+
+
+ @param [in] pSocket Address of a DT_SOCKET structure
+
+ @param [in] Flags Message control flags
+
+ @param [in] BufferLength Length of the the buffer
+
+ @param [in] pBuffer Address of a buffer to receive the data.
+
+ @param [in] pDataLength Number of received data bytes in the buffer.
+
+ @param [out] pAddress Network address to receive the remote system address
+
+ @param [in,out] pAddressLength Length of the remote network address structure
+
+ @retval EFI_SUCCESS - Socket data successfully received
+
+ **/
+EFI_STATUS
+EslTcpReceive4 (
+ IN DT_SOCKET * pSocket,
+ IN INT32 Flags,
+ IN size_t BufferLength,
+ IN UINT8 * pBuffer,
+ OUT size_t * pDataLength,
+ OUT struct sockaddr * pAddress,
+ IN OUT socklen_t * pAddressLength
+ )
+{
+ socklen_t AddressLength;
+ size_t BytesToCopy;
+ in_addr_t IpAddress;
+ size_t LengthInBytes;
+ DT_PACKET * pPacket;
+ DT_PORT * pPort;
+ DT_PACKET ** ppQueueHead;
+ DT_PACKET ** ppQueueTail;
+ struct sockaddr_in * pRemoteAddress;
+ size_t * pRxDataBytes;
+ DT_TCP4_CONTEXT * pTcp4;
+ struct sockaddr_in RemoteAddress;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume failure
+ //
+ Status = EFI_UNSUPPORTED;
+ pSocket->errno = ENOTCONN;
+
+ //
+ // Verify that the socket is connected
+ //
+ if (( SOCKET_STATE_CONNECTED == pSocket->State )
+ || ( PORT_STATE_RX_ERROR == pSocket->State )) {
+ //
+ // Locate the port
+ //
+ pPort = pSocket->pPortList;
+ if ( NULL != pPort ) {
+ //
+ // Determine the queue head
+ //
+ pTcp4 = &pPort->Context.Tcp4;
+ if ( 0 != ( Flags & MSG_OOB )) {
+ ppQueueHead = &pSocket->pRxOobPacketListHead;
+ ppQueueTail = &pSocket->pRxOobPacketListTail;
+ pRxDataBytes = &pSocket->RxOobBytes;
+ }
+ else {
+ ppQueueHead = &pSocket->pRxPacketListHead;
+ ppQueueTail = &pSocket->pRxPacketListTail;
+ pRxDataBytes = &pSocket->RxBytes;
+ }
+
+ //
+ // Determine if there is any data on the queue
+ //
+ pPacket = *ppQueueHead;
+ if ( NULL != pPacket ) {
+ //
+ // Validate the return address parameters
+ //
+ if (( NULL == pAddress ) || ( NULL != pAddressLength )) {
+ //
+ // Return the remote system address if requested
+ //
+ if ( NULL != pAddress ) {
+ //
+ // Build the remote address
+ //
+ ZeroMem ( &RemoteAddress, sizeof ( RemoteAddress ));
+ RemoteAddress.sin_len = sizeof ( RemoteAddress );
+ RemoteAddress.sin_family = AF_INET;
+ IpAddress = pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3];
+ IpAddress <<= 8;
+ IpAddress |= pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2];
+ IpAddress <<= 8;
+ IpAddress |= pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1];
+ IpAddress <<= 8;
+ IpAddress |= pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0];
+ RemoteAddress.sin_addr.s_addr = IpAddress;
+ RemoteAddress.sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.RemotePort );
+
+ //
+ // Copy the address
+ //
+ pRemoteAddress = (struct sockaddr_in *)pAddress;
+ AddressLength = sizeof ( *pRemoteAddress );
+ if ( AddressLength > *pAddressLength ) {
+ AddressLength = *pAddressLength;
+ }
+ CopyMem ( pRemoteAddress,
+ &RemoteAddress,
+ AddressLength );
+
+ //
+ // Update the address length
+ //
+ *pAddressLength = AddressLength;
+ }
+
+ //
+ // Copy the received data
+ //
+ LengthInBytes = 0;
+ do {
+ //
+ // Determine the amount of received data
+ //
+ BytesToCopy = pPacket->Op.Tcp4Rx.ValidBytes;
+ if (( BufferLength - LengthInBytes ) < BytesToCopy ) {
+ BytesToCopy = BufferLength - LengthInBytes;
+ }
+ LengthInBytes += BytesToCopy;
+
+ //
+ // Move the data into the buffer
+ //
+ DEBUG (( DEBUG_RX,
+ "0x%08x: Port copy packet 0x%08x data into 0x%08x, 0x%08x bytes\r\n",
+ pPort,
+ pPacket,
+ pBuffer,
+ BytesToCopy ));
+ CopyMem ( pBuffer, pPacket->Op.Tcp4Rx.pBuffer, BytesToCopy );
+
+ //
+ // Determine if the data is being read
+ //
+ if ( 0 == ( Flags & MSG_PEEK )) {
+ //
+ // Account for the bytes consumed
+ //
+ pPacket->Op.Tcp4Rx.pBuffer += BytesToCopy;
+ pPacket->Op.Tcp4Rx.ValidBytes -= BytesToCopy;
+ *pRxDataBytes -= BytesToCopy;
+ DEBUG (( DEBUG_RX,
+ "0x%08x: Port account for 0x%08x bytes\r\n",
+ pPort,
+ BytesToCopy ));
+
+ //
+ // Determine if the entire packet was consumed
+ //
+ if (( 0 == pPacket->Op.Tcp4Rx.ValidBytes )
+ || ( SOCK_STREAM != pSocket->Type )) {
+ //
+ // All done with this packet
+ // Account for any discarded data
+ //
+ *pRxDataBytes -= pPacket->Op.Tcp4Rx.ValidBytes;
+ if ( 0 != pPacket->Op.Tcp4Rx.ValidBytes ) {
+ DEBUG (( DEBUG_RX,
+ "0x%08x: Port, packet read, skipping over 0x%08x bytes\r\n",
+ pPort,
+ pPacket->Op.Tcp4Rx.ValidBytes ));
+ }
+
+ //
+ // Remove this packet from the queue
+ //
+ *ppQueueHead = pPacket->pNext;
+ if ( NULL == *ppQueueHead ) {
+ *ppQueueTail = NULL;
+ }
+
+ //
+ // Move the packet to the free queue
+ //
+ pPacket->pNext = pSocket->pRxFree;
+ pSocket->pRxFree = pPacket;
+ DEBUG (( DEBUG_RX,
+ "0x%08x: Port freeing packet 0x%08x\r\n",
+ pPort,
+ pPacket ));
+
+ //
+ // Restart this receive operation if necessary
+ //
+ if (( NULL == pTcp4->pReceivePending )
+ && ( MAX_RX_DATA > pSocket->RxBytes )) {
+ EslTcpRxStart4 ( pPort );
+ }
+ }
+ }
+
+ //
+ // Get the next packet
+ //
+ pPacket = *ppQueueHead;
+ } while (( SOCK_STREAM == pSocket->Type )
+ && ( NULL != pPacket )
+ && ( 0 == ( Flags & MSG_PEEK ))
+ && ( BufferLength > LengthInBytes ));
+
+ //
+ // Return the data length
+ //
+ *pDataLength = LengthInBytes;
+
+ //
+ // Successful operation
+ //
+ Status = EFI_SUCCESS;
+ pSocket->errno = 0;
+ }
+ else {
+ //
+ // Bad return address pointer and length
+ //
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EINVAL;
+ }
+ }
+ else {
+ //
+ // The queue is empty
+ // Determine if it is time to return the receive error
+ //
+ if ( EFI_ERROR ( pSocket->RxError )
+ && ( NULL == pSocket->pRxPacketListHead )
+ && ( NULL == pSocket->pRxOobPacketListHead )) {
+ Status = pSocket->RxError;
+ switch ( Status ) {
+ default:
+ pSocket->errno = EIO;
+ break;
+
+ case EFI_CONNECTION_FIN:
+ pSocket->errno = ESHUTDOWN;
+ break;
+
+ case EFI_CONNECTION_REFUSED:
+ pSocket->errno = ECONNREFUSED;
+ break;
+
+ case EFI_CONNECTION_RESET:
+ pSocket->errno = ECONNRESET;
+ break;
+
+ case EFI_HOST_UNREACHABLE:
+ pSocket->errno = EHOSTUNREACH;
+ break;
+
+ case EFI_NETWORK_UNREACHABLE:
+ pSocket->errno = ENETUNREACH;
+ break;
+
+ case EFI_PORT_UNREACHABLE:
+ pSocket->errno = EPROTONOSUPPORT;
+ break;
+
+ case EFI_PROTOCOL_UNREACHABLE:
+ pSocket->errno = ENOPROTOOPT;
+ break;
+ }
+ pSocket->RxError = EFI_SUCCESS;
+ }
+ else {
+ Status = EFI_NOT_READY;
+ pSocket->errno = EAGAIN;
+ }
+ }
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Cancel the receive operations
+
+ @param [in] pSocket Address of a DT_SOCKET structure
+
+ @retval EFI_SUCCESS - The cancel was successful
+
+ **/
+EFI_STATUS
+EslTcpRxCancel4 (
+ IN DT_SOCKET * pSocket
+ )
+{
+ DT_PACKET * pPacket;
+ DT_PORT * pPort;
+ DT_TCP4_CONTEXT * pTcp4;
+ EFI_TCP4_PROTOCOL * pTcp4Protocol;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume failure
+ //
+ Status = EFI_NOT_FOUND;
+
+ //
+ // Locate the port
+ //
+ pPort = pSocket->pPortList;
+ if ( NULL != pPort ) {
+ //
+ // Determine if a receive is pending
+ //
+ pTcp4 = &pPort->Context.Tcp4;
+ pPacket = pTcp4->pReceivePending;
+ if ( NULL != pPacket ) {
+ //
+ // Attempt to cancel the receive operation
+ //
+ pTcp4Protocol = pTcp4->pProtocol;
+ Status = pTcp4Protocol->Cancel ( pTcp4Protocol,
+ &pTcp4->RxToken.CompletionToken );
+ if ( EFI_NOT_FOUND == Status ) {
+ //
+ // The receive is complete
+ //
+ Status = EFI_SUCCESS;
+ }
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Process the receive completion
+
+ Buffer the data that was just received.
+
+ @param Event The receive completion event
+
+ @param pPort The DT_PORT structure address
+
+**/
+VOID
+EslTcpRxComplete4 (
+ IN EFI_EVENT Event,
+ IN DT_PORT * pPort
+ )
+{
+ BOOLEAN bUrgent;
+ size_t LengthInBytes;
+ DT_PACKET * pPacket;
+ DT_PACKET * pPrevious;
+ DT_SOCKET * pSocket;
+ DT_TCP4_CONTEXT * pTcp4;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Mark this receive complete
+ //
+ pTcp4 = &pPort->Context.Tcp4;
+ pPacket = pTcp4->pReceivePending;
+ pTcp4->pReceivePending = NULL;
+
+ //
+ // Determine if this receive was successful
+ //
+ pSocket = pPort->pSocket;
+ Status = pTcp4->RxToken.CompletionToken.Status;
+ if (( !EFI_ERROR ( Status )) && ( !pSocket->bRxDisable )) {
+ //
+ // Set the buffer size and address
+ //
+ pPacket->Op.Tcp4Rx.pBuffer = pPacket->Op.Tcp4Rx.RxData.FragmentTable[0].FragmentBuffer;
+ LengthInBytes = pPacket->Op.Tcp4Rx.RxData.DataLength;
+ pPacket->Op.Tcp4Rx.ValidBytes = LengthInBytes;
+ pPacket->pNext = NULL;
+
+ //
+ // Queue this packet
+ //
+ bUrgent = pPacket->Op.Tcp4Rx.RxData.UrgentFlag;
+ if ( bUrgent ) {
+ //
+ // Add packet to the urgent list
+ //
+ pPrevious = pSocket->pRxOobPacketListTail;
+ if ( NULL == pPrevious ) {
+ pSocket->pRxOobPacketListHead = pPacket;
+ }
+ else {
+ pPrevious->pNext = pPacket;
+ }
+ pSocket->pRxOobPacketListTail = pPacket;
+
+ //
+ // Account for the urgent data
+ //
+ pSocket->RxOobBytes += LengthInBytes;
+ }
+ else {
+ //
+ // Add packet to the normal list
+ //
+ pPrevious = pSocket->pRxPacketListTail;
+ if ( NULL == pPrevious ) {
+ pSocket->pRxPacketListHead = pPacket;
+ }
+ else {
+ pPrevious->pNext = pPacket;
+ }
+ pSocket->pRxPacketListTail = pPacket;
+
+ //
+ // Account for the normal data
+ //
+ pSocket->RxBytes += LengthInBytes;
+ }
+
+ //
+ // Log the received data
+ //
+ DEBUG (( DEBUG_RX | DEBUG_INFO,
+ "0x%08x: Packet queued on port 0x%08x with 0x%08x bytes of %s data\r\n",
+ pPacket,
+ pPort,
+ LengthInBytes,
+ bUrgent ? L"urgent" : L"normal" ));
+
+ //
+ // Attempt to restart this receive operation
+ //
+ if ( pSocket->MaxRxBuf > pSocket->RxBytes ) {
+ EslTcpRxStart4 ( pPort );
+ }
+ else {
+ DEBUG (( DEBUG_RX,
+ "0x%08x: Port RX suspended, 0x%08x bytes queued\r\n",
+ pPort,
+ pSocket->RxBytes ));
+ }
+ }
+ else
+ {
+ DEBUG (( DEBUG_RX | DEBUG_INFO,
+ "ERROR - Receiving packet 0x%08x, on port 0x%08x, Status:%r\r\n",
+ pPacket,
+ pPort,
+ Status ));
+
+ //
+ // Receive error, free the packet save the error
+ //
+ EslSocketPacketFree ( pPacket, DEBUG_RX );
+ if ( !EFI_ERROR ( pSocket->RxError )) {
+ pSocket->RxError = Status;
+ }
+
+ //
+ // Update the port state
+ //
+ if ( PORT_STATE_CLOSE_STARTED <= pPort->State ) {
+ EslTcpPortCloseRxDone4 ( pPort );
+ }
+ else {
+ if ( EFI_ERROR ( Status )) {
+ pPort->State = PORT_STATE_RX_ERROR;
+ }
+ }
+ }
+
+ DBG_EXIT ( );
+}
+
+
+/**
+ Start a receive operation
+
+ @param [in] pPort Address of the DT_PORT structure.
+
+ **/
+VOID
+EslTcpRxStart4 (
+ IN DT_PORT * pPort
+ )
+{
+ size_t LengthInBytes;
+ DT_PACKET * pPacket;
+ DT_SOCKET * pSocket;
+ DT_TCP4_CONTEXT * pTcp4;
+ EFI_TCP4_PROTOCOL * pTcp4Protocol;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Determine if a receive is already pending
+ //
+ Status = EFI_SUCCESS;
+ pPacket = NULL;
+ pSocket = pPort->pSocket;
+ pTcp4 = &pPort->Context.Tcp4;
+ if ( !EFI_ERROR ( pPort->pSocket->RxError )) {
+ if (( NULL == pTcp4->pReceivePending )
+ && ( PORT_STATE_CLOSE_STARTED > pPort->State )) {
+ //
+ // Determine if there are any free packets
+ //
+ pPacket = pSocket->pRxFree;
+ LengthInBytes = sizeof ( pPacket->Op.Tcp4Rx.Buffer );
+ if ( NULL != pPacket ) {
+ //
+ // Remove this packet from the free list
+ //
+ pSocket->pRxFree = pPacket->pNext;
+ DEBUG (( DEBUG_RX,
+ "0x%08x: Port removed packet 0x%08x from free list\r\n",
+ pPort,
+ pPacket ));
+ }
+ else {
+ //
+ // Allocate a packet structure
+ //
+ Status = EslSocketPacketAllocate ( &pPacket,
+ sizeof ( pPacket->Op.Tcp4Rx ),
+ DEBUG_RX );
+ if ( EFI_ERROR ( Status )) {
+ pPacket = NULL;
+ DEBUG (( DEBUG_ERROR | DEBUG_RX,
+ "0x%08x: Port failed to allocate RX packet, Status: %r\r\n",
+ pPort,
+ Status ));
+ }
+ }
+
+ //
+ // Determine if a packet is available
+ //
+ if ( NULL != pPacket ) {
+ //
+ // Initialize the buffer for receive
+ //
+ pTcp4->RxToken.Packet.RxData = &pPacket->Op.Tcp4Rx.RxData;
+ pPacket->Op.Tcp4Rx.RxData.DataLength = (UINT32) LengthInBytes;
+ pPacket->Op.Tcp4Rx.RxData.FragmentCount = 1;
+ pPacket->Op.Tcp4Rx.RxData.FragmentTable [0].FragmentLength = (UINT32) LengthInBytes;
+ pPacket->Op.Tcp4Rx.RxData.FragmentTable [0].FragmentBuffer = &pPacket->Op.Tcp4Rx.Buffer [0];
+ pTcp4->pReceivePending = pPacket;
+
+ //
+ // Start the receive on the packet
+ //
+ pTcp4Protocol = pTcp4->pProtocol;
+ Status = pTcp4Protocol->Receive ( pTcp4Protocol,
+ &pTcp4->RxToken );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_RX | DEBUG_INFO,
+ "0x%08x: Packet receive pending on port 0x%08x\r\n",
+ pPacket,
+ pPort ));
+ }
+ else {
+ DEBUG (( DEBUG_RX | DEBUG_INFO,
+ "ERROR - Failed to post a receive on port 0x%08x, Status: %r\r\n",
+ pPort,
+ Status ));
+ pTcp4->pReceivePending = NULL;
+ if ( !EFI_ERROR ( pSocket->RxError )) {
+ //
+ // Save the error status
+ //
+ pSocket->RxError = Status;
+ }
+ }
+ }
+ }
+ }
+
+ DBG_EXIT ( );
+}
+
+
+/**
+ Shutdown the TCP4 service.
+
+ This routine undoes the work performed by ::TcpInitialize4.
+
+ @param [in] pService DT_SERVICE structure address
+
+**/
+VOID
+EFIAPI
+EslTcpShutdown4 (
+ IN DT_SERVICE * pService
+ )
+{
+ DT_LAYER * pLayer;
+ DT_PORT * pPort;
+ DT_SERVICE * pPreviousService;
+
+ DBG_ENTER ( );
+
+ //
+ // Verify the socket layer synchronization
+ //
+ VERIFY_TPL ( TPL_SOCKETS );
+
+ //
+ // Walk the list of ports
+ //
+ do {
+ pPort = pService->pPortList;
+ if ( NULL != pPort ) {
+ //
+ // Remove the port from the port list
+ //
+ pService->pPortList = pPort->pLinkService;
+
+ //
+ // Close the port
+ // TODO: Fix this
+ //
+// pPort->pfnClosePort ( pPort, DEBUG_LISTEN | DEBUG_CONNECTION );
+ }
+ } while ( NULL != pPort );
+
+ //
+ // Remove the service from the service list
+ //
+ pLayer = &mEslLayer;
+ pPreviousService = pLayer->pTcp4List;
+ if ( pService == pPreviousService ) {
+ //
+ // Remove the service from the beginning of the list
+ //
+ pLayer->pTcp4List = pService->pNext;
+ }
+ else {
+ //
+ // Remove the service from the middle of the list
+ //
+ while ( NULL != pPreviousService ) {
+ if ( pService == pPreviousService->pNext ) {
+ pPreviousService->pNext = pService->pNext;
+ break;
+ }
+ }
+ }
+
+ DBG_EXIT ( );
+}
+
+
+/**
+ Determine if the socket is configured.
+
+
+ @param [in] pSocket Address of a DT_SOCKET structure
+
+ @retval EFI_SUCCESS - The port is connected
+ @retval EFI_NOT_STARTED - The port is not connected
+
+ **/
+ EFI_STATUS
+ EslTcpSocketIsConfigured4 (
+ IN DT_SOCKET * pSocket
+ )
+{
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Determine the socket configuration status
+ //
+ Status = pSocket->bConfigured ? EFI_SUCCESS : EFI_NOT_STARTED;
+
+ //
+ // Return the port connected state.
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Buffer data for transmission over a network connection.
+
+ This routine is called by the socket layer API to buffer
+ data for transmission. When necessary, this routine will
+ start the transmit engine that performs the data transmission
+ on the network connection.
+
+ The transmit engine uses two queues, one for urgent (out-of-band)
+ data and the other for normal data. The urgent data is provided
+ to TCP as soon as it is available, allowing the TCP layer to
+ schedule transmission of the urgent data between packets of normal
+ data.
+
+ Transmission errors are returned during the next transmission or
+ during the close operation. Only buffering errors are returned
+ during the current transmission attempt.
+
+ @param [in] pSocket Address of a DT_SOCKET structure
+
+ @param [in] Flags Message control flags
+
+ @param [in] BufferLength Length of the the buffer
+
+ @param [in] pBuffer Address of a buffer to receive the data.
+
+ @param [in] pDataLength Number of received data bytes in the buffer.
+
+ @retval EFI_SUCCESS - Socket data successfully buffered
+
+ **/
+EFI_STATUS
+EslTcpTxBuffer4 (
+ IN DT_SOCKET * pSocket,
+ IN int Flags,
+ IN size_t BufferLength,
+ IN CONST UINT8 * pBuffer,
+ OUT size_t * pDataLength
+ )
+{
+ BOOLEAN bUrgent;
+ DT_PACKET * pPacket;
+ DT_PACKET * pPreviousPacket;
+ DT_PACKET ** ppPacket;
+ DT_PACKET ** ppQueueHead;
+ DT_PACKET ** ppQueueTail;
+ DT_PORT * pPort;
+ DT_TCP4_CONTEXT * pTcp4;
+ EFI_TCP4_IO_TOKEN * pToken;
+ size_t * pTxBytes;
+ EFI_TCP4_TRANSMIT_DATA * pTxData;
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume failure
+ //
+ Status = EFI_UNSUPPORTED;
+ pSocket->errno = ENOTCONN;
+ * pDataLength = 0;
+
+ //
+ // Verify that the socket is connected
+ //
+ if ( SOCKET_STATE_CONNECTED == pSocket->State ) {
+ //
+ // Locate the port
+ //
+ pPort = pSocket->pPortList;
+ if ( NULL != pPort ) {
+ //
+ // Determine the queue head
+ //
+ pTcp4 = &pPort->Context.Tcp4;
+ bUrgent = (BOOLEAN)( 0 != ( Flags & MSG_OOB ));
+ if ( bUrgent ) {
+ ppQueueHead = &pSocket->pTxOobPacketListHead;
+ ppQueueTail = &pSocket->pTxOobPacketListTail;
+ ppPacket = &pTcp4->pTxOobPacket;
+ pToken = &pTcp4->TxOobToken;
+ pTxBytes = &pSocket->TxOobBytes;
+ }
+ else {
+ ppQueueHead = &pSocket->pTxPacketListHead;
+ ppQueueTail = &pSocket->pTxPacketListTail;
+ ppPacket = &pTcp4->pTxPacket;
+ pToken = &pTcp4->TxToken;
+ pTxBytes = &pSocket->TxBytes;
+ }
+
+ //
+ // Verify that there is enough room to buffer another
+ // transmit operation
+ //
+ if ( pSocket->MaxTxBuf > *pTxBytes ) {
+ //
+ // Attempt to allocate the packet
+ //
+ Status = EslSocketPacketAllocate ( &pPacket,
+ sizeof ( pPacket->Op.Tcp4Tx )
+ - sizeof ( pPacket->Op.Tcp4Tx.Buffer )
+ + BufferLength,
+ DEBUG_TX );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Initialize the transmit operation
+ //
+ pTxData = &pPacket->Op.Tcp4Tx.TxData;
+ pTxData->Push = TRUE;
+ pTxData->Urgent = bUrgent;
+ pTxData->DataLength = (UINT32) BufferLength;
+ pTxData->FragmentCount = 1;
+ pTxData->FragmentTable[0].FragmentLength = (UINT32) BufferLength;
+ pTxData->FragmentTable[0].FragmentBuffer = &pPacket->Op.Tcp4Tx.Buffer[0];
+
+ //
+ // Copy the data into the buffer
+ //
+ CopyMem ( &pPacket->Op.Tcp4Tx.Buffer[0],
+ pBuffer,
+ BufferLength );
+
+ //
+ // Synchronize with the socket layer
+ //
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );
+
+ //
+ // Stop transmission after an error
+ //
+ if ( !EFI_ERROR ( pSocket->TxError )) {
+ //
+ // Display the request
+ //
+ DEBUG (( DEBUG_TX,
+ "Send %d %s bytes from 0x%08x\r\n",
+ BufferLength,
+ bUrgent ? L"urgent" : L"normal",
+ pBuffer ));
+
+ //
+ // Queue the data for transmission
+ //
+ pPacket->pNext = NULL;
+ pPreviousPacket = *ppQueueTail;
+ if ( NULL == pPreviousPacket ) {
+ *ppQueueHead = pPacket;
+ }
+ else {
+ pPreviousPacket->pNext = pPacket;
+ }
+ *ppQueueTail = pPacket;
+ DEBUG (( DEBUG_TX,
+ "0x%08x: Packet on %s transmit list\r\n",
+ pPacket,
+ bUrgent ? L"urgent" : L"normal" ));
+
+ //
+ // Account for the buffered data
+ //
+ *pTxBytes += BufferLength;
+ *pDataLength = BufferLength;
+
+ //
+ // Start the transmit engine if it is idle
+ //
+ if ( NULL == *ppPacket ) {
+ EslTcpTxStart4 ( pSocket->pPortList,
+ pToken,
+ ppQueueHead,
+ ppQueueTail,
+ ppPacket );
+ }
+ }
+ else {
+ //
+ // Previous transmit error
+ // Stop transmission
+ //
+ Status = pSocket->TxError;
+ pSocket->errno = EIO;
+
+ //
+ // Free the packet
+ //
+ EslSocketPacketFree ( pPacket, DEBUG_TX );
+ }
+
+ //
+ // Release the socket layer synchronization
+ //
+ RESTORE_TPL ( TplPrevious );
+ }
+ else {
+ //
+ // Packet allocation failed
+ //
+ pSocket->errno = ENOMEM;
+ }
+ }
+ else {
+ //
+ // Not enough buffer space available
+ //
+ pSocket->errno = EAGAIN;
+ Status = EFI_NOT_READY;
+ }
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Process the normal data transmit completion
+
+ @param Event The normal transmit completion event
+
+ @param pPort The DT_PORT structure address
+
+**/
+VOID
+EslTcpTxComplete4 (
+ IN EFI_EVENT Event,
+ IN DT_PORT * pPort
+ )
+{
+ UINT32 LengthInBytes;
+ DT_PACKET * pCurrentPacket;
+ DT_PACKET * pNextPacket;
+ DT_PACKET * pPacket;
+ DT_SOCKET * pSocket;
+ DT_TCP4_CONTEXT * pTcp4;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Locate the active transmit packet
+ //
+ pSocket = pPort->pSocket;
+ pTcp4 = &pPort->Context.Tcp4;
+ pPacket = pTcp4->pTxPacket;
+
+ //
+ // Mark this packet as complete
+ //
+ pTcp4->pTxPacket = NULL;
+ LengthInBytes = pPacket->Op.Tcp4Tx.TxData.DataLength;
+ pSocket->TxBytes -= LengthInBytes;
+
+ //
+ // Save any transmit error
+ //
+ Status = pTcp4->TxToken.CompletionToken.Status;
+ if ( EFI_ERROR ( Status )) {
+ if ( !EFI_ERROR ( pSocket->TxError )) {
+ pSocket->TxError = Status;
+ }
+ DEBUG (( DEBUG_TX | DEBUG_INFO,
+ "ERROR - Transmit failure for packet 0x%08x, Status: %r\r\n",
+ pPacket,
+ Status ));
+
+ //
+ // Empty the normal transmit list
+ //
+ pCurrentPacket = pPacket;
+ pNextPacket = pSocket->pTxPacketListHead;
+ while ( NULL != pNextPacket ) {
+ pPacket = pNextPacket;
+ pNextPacket = pPacket->pNext;
+ EslSocketPacketFree ( pPacket, DEBUG_TX );
+ }
+ pSocket->pTxPacketListHead = NULL;
+ pSocket->pTxPacketListTail = NULL;
+ pPacket = pCurrentPacket;
+ }
+ else
+ {
+ DEBUG (( DEBUG_TX | DEBUG_INFO,
+ "0x%08x: Packet transmitted %d bytes successfully\r\n",
+ pPacket,
+ LengthInBytes ));
+
+ //
+ // Verify the transmit engine is still running
+ //
+ if ( !pPort->bCloseNow ) {
+ //
+ // Start the next packet transmission
+ //
+ EslTcpTxStart4 ( pPort,
+ &pTcp4->TxToken,
+ &pSocket->pTxPacketListHead,
+ &pSocket->pTxPacketListTail,
+ &pTcp4->pTxPacket );
+ }
+ }
+
+ //
+ // Release this packet
+ //
+ EslSocketPacketFree ( pPacket, DEBUG_TX );
+
+ //
+ // Finish the close operation if necessary
+ //
+ if ( PORT_STATE_CLOSE_STARTED <= pPort->State ) {
+ //
+ // Indicate that the transmit is complete
+ //
+ EslTcpPortCloseTxDone4 ( pPort );
+ }
+ DBG_EXIT ( );
+}
+
+
+/**
+ Process the urgent data transmit completion
+
+ @param Event The urgent transmit completion event
+
+ @param pPort The DT_PORT structure address
+
+**/
+VOID
+EslTcpTxOobComplete4 (
+ IN EFI_EVENT Event,
+ IN DT_PORT * pPort
+ )
+{
+ UINT32 LengthInBytes;
+ DT_PACKET * pCurrentPacket;
+ DT_PACKET * pNextPacket;
+ DT_PACKET * pPacket;
+ DT_SOCKET * pSocket;
+ DT_TCP4_CONTEXT * pTcp4;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Locate the active transmit packet
+ //
+ pSocket = pPort->pSocket;
+ pTcp4 = &pPort->Context.Tcp4;
+ pPacket = pTcp4->pTxOobPacket;
+
+ //
+ // Mark this packet as complete
+ //
+ pTcp4->pTxOobPacket = NULL;
+ LengthInBytes = pPacket->Op.Tcp4Tx.TxData.DataLength;
+ pSocket->TxOobBytes -= LengthInBytes;
+
+ //
+ // Save any transmit error
+ //
+ Status = pTcp4->TxOobToken.CompletionToken.Status;
+ if ( EFI_ERROR ( Status )) {
+ if ( !EFI_ERROR ( Status )) {
+ pSocket->TxError = Status;
+ }
+ DEBUG (( DEBUG_TX | DEBUG_INFO,
+ "ERROR - Transmit failure for urgent packet 0x%08x, Status: %r\r\n",
+ pPacket,
+ Status ));
+
+
+ //
+ // Empty the OOB transmit list
+ //
+ pCurrentPacket = pPacket;
+ pNextPacket = pSocket->pTxOobPacketListHead;
+ while ( NULL != pNextPacket ) {
+ pPacket = pNextPacket;
+ pNextPacket = pPacket->pNext;
+ EslSocketPacketFree ( pPacket, DEBUG_TX );
+ }
+ pSocket->pTxOobPacketListHead = NULL;
+ pSocket->pTxOobPacketListTail = NULL;
+ pPacket = pCurrentPacket;
+ }
+ else
+ {
+ DEBUG (( DEBUG_TX | DEBUG_INFO,
+ "0x%08x: Urgent packet transmitted %d bytes successfully\r\n",
+ pPacket,
+ LengthInBytes ));
+
+ //
+ // Verify the transmit engine is still running
+ //
+ if ( !pPort->bCloseNow ) {
+ //
+ // Start the next packet transmission
+ //
+ EslTcpTxStart4 ( pPort,
+ &pTcp4->TxOobToken,
+ &pSocket->pTxOobPacketListHead,
+ &pSocket->pTxOobPacketListTail,
+ &pTcp4->pTxOobPacket );
+ }
+ }
+
+ //
+ // Release this packet
+ //
+ EslSocketPacketFree ( pPacket, DEBUG_TX );
+
+ //
+ // Finish the close operation if necessary
+ //
+ if ( PORT_STATE_CLOSE_STARTED <= pPort->State ) {
+ //
+ // Indicate that the transmit is complete
+ //
+ EslTcpPortCloseTxDone4 ( pPort );
+ }
+ DBG_EXIT ( );
+}
+
+
+/**
+ Transmit data using a network connection.
+
+
+ @param [in] pPort Address of a DT_PORT structure
+ @param [in] pToken Address of either the OOB or normal transmit token
+ @param [in] ppQueueHead Transmit queue head address
+ @param [in] ppQueueTail Transmit queue tail address
+ @param [in] ppPacket Active transmit packet address
+
+ **/
+VOID
+EslTcpTxStart4 (
+ IN DT_PORT * pPort,
+ IN EFI_TCP4_IO_TOKEN * pToken,
+ IN DT_PACKET ** ppQueueHead,
+ IN DT_PACKET ** ppQueueTail,
+ IN DT_PACKET ** ppPacket
+ )
+{
+ DT_PACKET * pNextPacket;
+ DT_PACKET * pPacket;
+ DT_SOCKET * pSocket;
+ EFI_TCP4_PROTOCOL * pTcp4Protocol;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume success
+ //
+ Status = EFI_SUCCESS;
+
+ //
+ // Get the packet from the queue head
+ //
+ pPacket = *ppQueueHead;
+ if ( NULL != pPacket ) {
+ //
+ // Remove the packet from the queue
+ //
+ pNextPacket = pPacket->pNext;
+ *ppQueueHead = pNextPacket;
+ if ( NULL == pNextPacket ) {
+ *ppQueueTail = NULL;
+ }
+
+ //
+ // Set the packet as active
+ //
+ *ppPacket = pPacket;
+
+ //
+ // Start the transmit operation
+ //
+ pTcp4Protocol = pPort->Context.Tcp4.pProtocol;
+ pToken->Packet.TxData = &pPacket->Op.Tcp4Tx.TxData;
+ Status = pTcp4Protocol->Transmit ( pTcp4Protocol, pToken );
+ if ( EFI_ERROR ( Status )) {
+ pSocket = pPort->pSocket;
+ if ( EFI_SUCCESS == pSocket->TxError ) {
+ pSocket->TxError = Status;
+ }
+ }
+ }
+
+ DBG_EXIT ( );
+}
diff --git a/StdLib/EfiSocketLib/Udp4.c b/StdLib/EfiSocketLib/Udp4.c new file mode 100644 index 0000000000..95fc66517a --- /dev/null +++ b/StdLib/EfiSocketLib/Udp4.c @@ -0,0 +1,2408 @@ +/** @file
+ Implement the UDP4 driver support for the socket layer.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Socket.h"
+
+
+/**
+ Bind a name to a socket.
+
+ The ::UdpBind4 routine connects a name to a UDP4 stack on the local machine.
+
+ The configure call to the UDP4 driver occurs on the first poll, recv, recvfrom,
+ send or sentto call. Until then, all changes are made in the local UDP context
+ structure.
+
+ @param [in] pSocket Address of the socket structure.
+
+ @param [in] pSockAddr Address of a sockaddr structure that contains the
+ connection point on the local machine. An IPv4 address
+ of INADDR_ANY specifies that the connection is made to
+ all of the network stacks on the platform. Specifying a
+ specific IPv4 address restricts the connection to the
+ network stack supporting that address. Specifying zero
+ for the port causes the network layer to assign a port
+ number from the dynamic range. Specifying a specific
+ port number causes the network layer to use that port.
+
+ @param [in] SockAddrLen Specifies the length in bytes of the sockaddr structure.
+
+ @retval EFI_SUCCESS - Socket successfully created
+
+ **/
+EFI_STATUS
+EslUdpBind4 (
+ IN DT_SOCKET * pSocket,
+ IN const struct sockaddr * pSockAddr,
+ IN socklen_t SockAddrLength
+ )
+{
+ EFI_HANDLE ChildHandle;
+ DT_LAYER * pLayer;
+ DT_PORT * pPort;
+ DT_SERVICE * pService;
+ CONST struct sockaddr_in * pIp4Address;
+ EFI_SERVICE_BINDING_PROTOCOL * pUdp4Service;
+ EFI_STATUS Status;
+ EFI_STATUS TempStatus;
+
+ DBG_ENTER ( );
+
+ //
+ // Verify the socket layer synchronization
+ //
+ VERIFY_TPL ( TPL_SOCKETS );
+
+ //
+ // Assume success
+ //
+ pSocket->errno = 0;
+ Status = EFI_SUCCESS;
+
+ //
+ // Validate the address length
+ //
+ pIp4Address = (CONST struct sockaddr_in *) pSockAddr;
+ if ( SockAddrLength >= ( sizeof ( *pIp4Address )
+ - sizeof ( pIp4Address->sin_zero ))) {
+
+ //
+ // Walk the list of services
+ //
+ pLayer = &mEslLayer;
+ pService = pLayer->pUdp4List;
+ while ( NULL != pService ) {
+
+ //
+ // Create the UDP port
+ //
+ pUdp4Service = pService->pInterface;
+ ChildHandle = NULL;
+ Status = pUdp4Service->CreateChild ( pUdp4Service,
+ &ChildHandle );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_BIND | DEBUG_POOL,
+ "0x%08x: Udp4 port handle created\r\n",
+ ChildHandle ));
+
+ //
+ // Open the port
+ //
+ Status = EslUdpPortAllocate4 ( pSocket,
+ pService,
+ ChildHandle,
+ (UINT8 *) &pIp4Address->sin_addr.s_addr,
+ SwapBytes16 ( pIp4Address->sin_port ),
+ DEBUG_BIND,
+ &pPort );
+ }
+ else {
+ DEBUG (( DEBUG_BIND | DEBUG_POOL,
+ "ERROR - Failed to open Udp4 port handle, Status: %r\r\n",
+ Status ));
+ ChildHandle = NULL;
+ }
+
+ //
+ // Close the port if necessary
+ //
+ if (( EFI_ERROR ( Status )) && ( NULL != ChildHandle )) {
+ TempStatus = pUdp4Service->DestroyChild ( pUdp4Service,
+ ChildHandle );
+ if ( !EFI_ERROR ( TempStatus )) {
+ DEBUG (( DEBUG_BIND | DEBUG_POOL,
+ "0x%08x: Udp4 port handle destroyed\r\n",
+ ChildHandle ));
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_BIND | DEBUG_POOL,
+ "ERROR - Failed to destroy the Udp4 port handle 0x%08x, Status: %r\r\n",
+ ChildHandle,
+ TempStatus ));
+ ASSERT ( EFI_SUCCESS == TempStatus );
+ }
+ }
+
+ //
+ // Set the next service
+ //
+ pService = pService->pNext;
+ }
+
+ //
+ // Verify that at least one network connection was found
+ //
+ if ( NULL == pSocket->pPortList ) {
+ DEBUG (( DEBUG_BIND | DEBUG_POOL | DEBUG_INIT,
+ "Socket address %d.%d.%d.%d (0x%08x) is not available!\r\n",
+ ( pIp4Address->sin_addr.s_addr >> 24 ) & 0xff,
+ ( pIp4Address->sin_addr.s_addr >> 16 ) & 0xff,
+ ( pIp4Address->sin_addr.s_addr >> 8 ) & 0xff,
+ pIp4Address->sin_addr.s_addr & 0xff,
+ pIp4Address->sin_addr.s_addr ));
+ pSocket->errno = EADDRNOTAVAIL;
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+ else {
+ DEBUG (( DEBUG_BIND,
+ "ERROR - Invalid Udp4 address length: %d\r\n",
+ SockAddrLength ));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EINVAL;
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Initialize the UDP4 service.
+
+ This routine initializes the UDP4 service after its service binding
+ protocol was located on a controller.
+
+ @param [in] pService DT_SERVICE structure address
+
+ @retval EFI_SUCCESS The service was properly initialized
+ @retval other A failure occurred during the service initialization
+
+**/
+EFI_STATUS
+EFIAPI
+EslUdpInitialize4 (
+ IN DT_SERVICE * pService
+ )
+{
+ DT_LAYER * pLayer;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Identify the service
+ //
+ pService->NetworkType = NETWORK_TYPE_UDP4;
+
+ //
+ // Connect this service to the service list
+ //
+ pLayer = &mEslLayer;
+ pService->pNext = pLayer->pUdp4List;
+ pLayer->pUdp4List = pService;
+
+ //
+ // Assume the list is empty
+ //
+ Status = EFI_SUCCESS;
+
+ //
+ // Return the initialization status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Allocate and initialize a DT_PORT structure.
+
+ @param [in] pSocket Address of the socket structure.
+ @param [in] pService Address of the DT_SERVICE structure.
+ @param [in] ChildHandle Udp4 child handle
+ @param [in] pIpAddress Buffer containing IP4 network address of the local host
+ @param [in] PortNumber Udp4 port number
+ @param [in] DebugFlags Flags for debug messages
+ @param [out] ppPort Buffer to receive new DT_PORT structure address
+
+ @retval EFI_SUCCESS - Socket successfully created
+
+ **/
+EFI_STATUS
+EslUdpPortAllocate4 (
+ IN DT_SOCKET * pSocket,
+ IN DT_SERVICE * pService,
+ IN EFI_HANDLE ChildHandle,
+ IN CONST UINT8 * pIpAddress,
+ IN UINT16 PortNumber,
+ IN UINTN DebugFlags,
+ OUT DT_PORT ** ppPort
+ )
+{
+ UINTN LengthInBytes;
+ EFI_UDP4_CONFIG_DATA * pConfig;
+ DT_LAYER * pLayer;
+ DT_PORT * pPort;
+ DT_UDP4_CONTEXT * pUdp4;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Use for/break instead of goto
+ for ( ; ; ) {
+ //
+ // Allocate a port structure
+ //
+ pLayer = &mEslLayer;
+ LengthInBytes = sizeof ( *pPort );
+ Status = gBS->AllocatePool ( EfiRuntimeServicesData,
+ LengthInBytes,
+ (VOID **)&pPort );
+ if ( EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL | DEBUG_INIT,
+ "ERROR - Failed to allocate the port structure, Status: %r\r\n",
+ Status ));
+ pSocket->errno = ENOMEM;
+ pPort = NULL;
+ break;
+ }
+ DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT,
+ "0x%08x: Allocate pPort, %d bytes\r\n",
+ pPort,
+ LengthInBytes ));
+
+ //
+ // Initialize the port
+ //
+ ZeroMem ( pPort, LengthInBytes );
+ pPort->Signature = PORT_SIGNATURE;
+ pPort->pService = pService;
+ pPort->pSocket = pSocket;
+ pPort->pfnCloseStart = EslUdpPortCloseStart4;
+ pPort->DebugFlags = DebugFlags;
+
+ //
+ // Allocate the receive event
+ //
+ pUdp4 = &pPort->Context.Udp4;
+ Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
+ TPL_SOCKETS,
+ (EFI_EVENT_NOTIFY)EslUdpRxComplete4,
+ pPort,
+ &pUdp4->RxToken.Event);
+ if ( EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_ERROR | DebugFlags,
+ "ERROR - Failed to create the receive event, Status: %r\r\n",
+ Status ));
+ pSocket->errno = ENOMEM;
+ break;
+ }
+ DEBUG (( DEBUG_RX | DEBUG_POOL,
+ "0x%08x: Created receive event\r\n",
+ pUdp4->RxToken.Event ));
+
+ //
+ // Allocate the transmit event
+ //
+ Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
+ TPL_SOCKETS,
+ (EFI_EVENT_NOTIFY)EslUdpTxComplete4,
+ pPort,
+ &pUdp4->TxToken.Event);
+ if ( EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_ERROR | DebugFlags,
+ "ERROR - Failed to create the transmit event, Status: %r\r\n",
+ Status ));
+ pSocket->errno = ENOMEM;
+ break;
+ }
+ DEBUG (( DEBUG_CLOSE | DEBUG_POOL,
+ "0x%08x: Created transmit event\r\n",
+ pUdp4->TxToken.Event ));
+
+ //
+ // Open the port protocol
+ //
+ Status = gBS->OpenProtocol (
+ ChildHandle,
+ &gEfiUdp4ProtocolGuid,
+ (VOID **) &pUdp4->pProtocol,
+ pLayer->ImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );
+ if ( EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_ERROR | DebugFlags,
+ "ERROR - Failed to open gEfiUdp4ProtocolGuid on controller 0x%08x\r\n",
+ pUdp4->Handle ));
+ pSocket->errno = EEXIST;
+ break;
+ }
+ DEBUG (( DebugFlags,
+ "0x%08x: gEfiUdp4ProtocolGuid opened on controller 0x%08x\r\n",
+ pUdp4->pProtocol,
+ ChildHandle ));
+
+ //
+ // Set the port address
+ //
+ pUdp4->Handle = ChildHandle;
+ pConfig = &pPort->Context.Udp4.ConfigData;
+ pConfig->StationPort = PortNumber;
+ if (( 0 == pIpAddress[0])
+ && ( 0 == pIpAddress[1])
+ && ( 0 == pIpAddress[2])
+ && ( 0 == pIpAddress[3])) {
+ pConfig->UseDefaultAddress = TRUE;
+ }
+ else {
+ pConfig->StationAddress.Addr[0] = pIpAddress[0];
+ pConfig->StationAddress.Addr[1] = pIpAddress[1];
+ pConfig->StationAddress.Addr[2] = pIpAddress[2];
+ pConfig->StationAddress.Addr[3] = pIpAddress[3];
+ pConfig->SubnetMask.Addr[0] = 0xff;
+ pConfig->SubnetMask.Addr[1] = 0xff;
+ pConfig->SubnetMask.Addr[2] = 0xff;
+ pConfig->SubnetMask.Addr[3] = 0xff;
+ }
+ pConfig->TimeToLive = 255;
+ pConfig->AcceptAnyPort = FALSE;
+ pConfig->AcceptBroadcast = FALSE;
+ pConfig->AcceptPromiscuous = FALSE;
+ pConfig->AllowDuplicatePort = TRUE;
+ pConfig->DoNotFragment = TRUE;
+
+ //
+ // Verify the socket layer synchronization
+ //
+ VERIFY_TPL ( TPL_SOCKETS );
+
+ //
+ // Add this port to the socket
+ //
+ pPort->pLinkSocket = pSocket->pPortList;
+ pSocket->pPortList = pPort;
+ DEBUG (( DebugFlags,
+ "0x%08x: Socket adding port: 0x%08x\r\n",
+ pSocket,
+ pPort ));
+
+ //
+ // Add this port to the service
+ //
+ pPort->pLinkService = pService->pPortList;
+ pService->pPortList = pPort;
+
+ //
+ // Return the port
+ //
+ *ppPort = pPort;
+ break;
+ }
+
+ //
+ // Clean up after the error if necessary
+ //
+ if (( EFI_ERROR ( Status )) && ( NULL != pPort )) {
+ //
+ // Close the port
+ //
+ EslUdpPortClose4 ( pPort );
+ }
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Close a UDP4 port.
+
+ This routine releases the resources allocated by
+ ::UdpPortAllocate4().
+
+ @param [in] pPort Address of the port structure.
+
+ @retval EFI_SUCCESS The port is closed
+ @retval other Port close error
+
+**/
+EFI_STATUS
+EslUdpPortClose4 (
+ IN DT_PORT * pPort
+ )
+{
+ UINTN DebugFlags;
+ DT_LAYER * pLayer;
+ DT_PACKET * pPacket;
+ DT_PORT * pPreviousPort;
+ DT_SERVICE * pService;
+ DT_SOCKET * pSocket;
+ EFI_SERVICE_BINDING_PROTOCOL * pUdp4Service;
+ DT_UDP4_CONTEXT * pUdp4;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Verify the socket layer synchronization
+ //
+ VERIFY_TPL ( TPL_SOCKETS );
+
+ //
+ // Assume success
+ //
+ Status = EFI_SUCCESS;
+ pSocket = pPort->pSocket;
+ pSocket->errno = 0;
+
+ //
+ // Locate the port in the socket list
+ //
+ pLayer = &mEslLayer;
+ DebugFlags = pPort->DebugFlags;
+ pPreviousPort = pSocket->pPortList;
+ if ( pPreviousPort == pPort ) {
+ //
+ // Remove this port from the head of the socket list
+ //
+ pSocket->pPortList = pPort->pLinkSocket;
+ }
+ else {
+ //
+ // Locate the port in the middle of the socket list
+ //
+ while (( NULL != pPreviousPort )
+ && ( pPreviousPort->pLinkSocket != pPort )) {
+ pPreviousPort = pPreviousPort->pLinkSocket;
+ }
+ if ( NULL != pPreviousPort ) {
+ //
+ // Remove the port from the middle of the socket list
+ //
+ pPreviousPort->pLinkSocket = pPort->pLinkSocket;
+ }
+ }
+
+ //
+ // Locate the port in the service list
+ //
+ pService = pPort->pService;
+ pPreviousPort = pService->pPortList;
+ if ( pPreviousPort == pPort ) {
+ //
+ // Remove this port from the head of the service list
+ //
+ pService->pPortList = pPort->pLinkService;
+ }
+ else {
+ //
+ // Locate the port in the middle of the service list
+ //
+ while (( NULL != pPreviousPort )
+ && ( pPreviousPort->pLinkService != pPort )) {
+ pPreviousPort = pPreviousPort->pLinkService;
+ }
+ if ( NULL != pPreviousPort ) {
+ //
+ // Remove the port from the middle of the service list
+ //
+ pPreviousPort->pLinkService = pPort->pLinkService;
+ }
+ }
+
+ //
+ // Empty the receive queue
+ //
+ ASSERT ( NULL == pSocket->pRxPacketListHead );
+ ASSERT ( NULL == pSocket->pRxPacketListTail );
+ ASSERT ( 0 == pSocket->RxBytes );
+
+ //
+ // Empty the receive free queue
+ //
+ while ( NULL != pSocket->pRxFree ) {
+ pPacket = pSocket->pRxFree;
+ pSocket->pRxFree = pPacket->pNext;
+ EslSocketPacketFree ( pPacket, DEBUG_RX );
+ }
+
+ //
+ // Done with the receive event
+ //
+ pUdp4 = &pPort->Context.Udp4;
+ if ( NULL != pUdp4->RxToken.Event ) {
+ Status = gBS->CloseEvent ( pUdp4->RxToken.Event );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DebugFlags | DEBUG_POOL,
+ "0x%08x: Closed receive event\r\n",
+ pUdp4->RxToken.Event ));
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DebugFlags,
+ "ERROR - Failed to close the receive event, Status: %r\r\n",
+ Status ));
+ ASSERT ( EFI_SUCCESS == Status );
+ }
+ }
+
+ //
+ // Done with the transmit event
+ //
+ if ( NULL != pUdp4->TxToken.Event ) {
+ Status = gBS->CloseEvent ( pUdp4->TxToken.Event );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DebugFlags | DEBUG_POOL,
+ "0x%08x: Closed normal transmit event\r\n",
+ pUdp4->TxToken.Event ));
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DebugFlags,
+ "ERROR - Failed to close the normal transmit event, Status: %r\r\n",
+ Status ));
+ ASSERT ( EFI_SUCCESS == Status );
+ }
+ }
+
+ //
+ // Done with the UDP protocol
+ //
+ pUdp4Service = pService->pInterface;
+ if ( NULL != pUdp4->pProtocol ) {
+ Status = gBS->CloseProtocol ( pUdp4->Handle,
+ &gEfiUdp4ProtocolGuid,
+ pLayer->ImageHandle,
+ NULL );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DebugFlags,
+ "0x%08x: gEfiUdp4ProtocolGuid closed on controller 0x%08x\r\n",
+ pUdp4->pProtocol,
+ pUdp4->Handle ));
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DebugFlags,
+ "ERROR - Failed to close gEfiUdp4ProtocolGuid opened on controller 0x%08x, Status: %r\r\n",
+ pUdp4->Handle,
+ Status ));
+ ASSERT ( EFI_SUCCESS == Status );
+ }
+ }
+
+ //
+ // Done with the UDP port
+ //
+ if ( NULL != pUdp4->Handle ) {
+ Status = pUdp4Service->DestroyChild ( pUdp4Service,
+ pUdp4->Handle );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DebugFlags | DEBUG_POOL,
+ "0x%08x: Udp4 port handle destroyed\r\n",
+ pUdp4->Handle ));
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL,
+ "ERROR - Failed to destroy the Udp4 port handle, Status: %r\r\n",
+ Status ));
+ ASSERT ( EFI_SUCCESS == Status );
+ }
+ }
+
+ //
+ // Release the port structure
+ //
+ Status = gBS->FreePool ( pPort );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DebugFlags | DEBUG_POOL,
+ "0x%08x: Free pPort, %d bytes\r\n",
+ pPort,
+ sizeof ( *pPort )));
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL,
+ "ERROR - Failed to free pPort: 0x%08x, Status: %r\r\n",
+ pPort,
+ Status ));
+ ASSERT ( EFI_SUCCESS == Status );
+ }
+
+ //
+ // Mark the socket as closed if necessary
+ //
+ if ( NULL == pSocket->pPortList ) {
+ pSocket->State = SOCKET_STATE_CLOSED;
+ DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
+ "0x%08x: Socket State: SOCKET_STATE_CLOSED\r\n",
+ pSocket ));
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Start the close operation on a UDP4 port, state 1.
+
+ Closing a port goes through the following states:
+ 1. Port close starting - Mark the port as closing and wait for transmission to complete
+ 2. Port TX close done - Transmissions complete, close the port and abort the receives
+ 3. Port RX close done - Receive operations complete, close the port
+ 4. Port closed - Release the port resources
+
+ @param [in] pPort Address of the port structure.
+ @param [in] bCloseNow Set TRUE to abort active transfers
+ @param [in] DebugFlags Flags for debug messages
+
+ @retval EFI_SUCCESS The port is closed, not normally returned
+ @retval EFI_NOT_READY The port has started the closing process
+ @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
+ most likely the routine was called already.
+
+**/
+EFI_STATUS
+EslUdpPortCloseStart4 (
+ IN DT_PORT * pPort,
+ IN BOOLEAN bCloseNow,
+ IN UINTN DebugFlags
+ )
+{
+ DT_SOCKET * pSocket;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Verify the socket layer synchronization
+ //
+ VERIFY_TPL ( TPL_SOCKETS );
+
+ //
+ // Mark the port as closing
+ //
+ Status = EFI_ALREADY_STARTED;
+ pSocket = pPort->pSocket;
+ pSocket->errno = EALREADY;
+ if ( PORT_STATE_CLOSE_STARTED > pPort->State ) {
+
+ //
+ // Update the port state
+ //
+ pPort->State = PORT_STATE_CLOSE_STARTED;
+ DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
+ "0x%08x: Port Close State: PORT_STATE_CLOSE_STARTED\r\n",
+ pPort ));
+ pPort->bCloseNow = bCloseNow;
+ pPort->DebugFlags = DebugFlags;
+
+ //
+ // Determine if transmits are complete
+ //
+ Status = EslUdpPortCloseTxDone4 ( pPort );
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Port close state 3
+
+ Continue the close operation after the receive is complete.
+
+ @param [in] pPort Address of the port structure.
+
+ @retval EFI_SUCCESS The port is closed
+ @retval EFI_NOT_READY The port is still closing
+ @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
+ most likely the routine was called already.
+
+**/
+EFI_STATUS
+EslUdpPortCloseRxDone4 (
+ IN DT_PORT * pPort
+ )
+{
+ PORT_STATE PortState;
+ DT_SOCKET * pSocket;
+ DT_UDP4_CONTEXT * pUdp4;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Verify the socket layer synchronization
+ //
+ VERIFY_TPL ( TPL_SOCKETS );
+
+ //
+ // Verify that the port is closing
+ //
+ Status = EFI_ALREADY_STARTED;
+ pSocket = pPort->pSocket;
+ pSocket->errno = EALREADY;
+ PortState = pPort->State;
+ if (( PORT_STATE_CLOSE_TX_DONE == PortState )
+ || ( PORT_STATE_CLOSE_DONE == PortState )) {
+ //
+ // Determine if the receive operation is pending
+ //
+ Status = EFI_NOT_READY;
+ pSocket->errno = EAGAIN;
+ pUdp4 = &pPort->Context.Udp4;
+ if ( NULL == pUdp4->pReceivePending ) {
+ //
+ // The receive operation is complete
+ // Update the port state
+ //
+ pPort->State = PORT_STATE_CLOSE_RX_DONE;
+ DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
+ "0x%08x: Port Close State: PORT_STATE_CLOSE_RX_DONE\r\n",
+ pPort ));
+
+ //
+ // The close operation has completed
+ // Release the port resources
+ //
+ Status = EslUdpPortClose4 ( pPort );
+ }
+ else {
+ DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
+ "0x%08x: Port Close: Receive still pending!\r\n",
+ pPort ));
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Port close state 2
+
+ Continue the close operation after the transmission is complete.
+
+ @param [in] pPort Address of the port structure.
+
+ @retval EFI_SUCCESS The port is closed, not normally returned
+ @retval EFI_NOT_READY The port is still closing
+ @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
+ most likely the routine was called already.
+
+**/
+EFI_STATUS
+EslUdpPortCloseTxDone4 (
+ IN DT_PORT * pPort
+ )
+{
+ DT_PACKET * pPacket;
+ DT_SOCKET * pSocket;
+ DT_UDP4_CONTEXT * pUdp4;
+ EFI_UDP4_PROTOCOL * pUdp4Protocol;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Verify the socket layer synchronization
+ //
+ VERIFY_TPL ( TPL_SOCKETS );
+
+ //
+ // All transmissions are complete or must be stopped
+ // Mark the port as TX complete
+ //
+ Status = EFI_ALREADY_STARTED;
+ if ( PORT_STATE_CLOSE_STARTED == pPort->State ) {
+ //
+ // Verify that the transmissions are complete
+ //
+ pSocket = pPort->pSocket;
+ if ( pPort->bCloseNow
+ || ( EFI_SUCCESS != pSocket->TxError )
+ || ( 0 == pSocket->TxBytes )) {
+ //
+ // Start the close operation on the port
+ //
+ pUdp4 = &pPort->Context.Udp4;
+ pUdp4Protocol = pUdp4->pProtocol;
+ if ( !pUdp4->bConfigured ) {
+ //
+ // Skip the close operation since the port is not
+ // configured
+ //
+ // Update the port state
+ //
+ pPort->State = PORT_STATE_CLOSE_DONE;
+ DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
+ "0x%08x: Port Close State: PORT_STATE_CLOSE_DONE\r\n",
+ pPort ));
+ Status = EFI_SUCCESS;
+ }
+ else {
+ //
+ // Update the port state
+ //
+ pPort->State = PORT_STATE_CLOSE_TX_DONE;
+ DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
+ "0x%08x: Port Close State: PORT_STATE_CLOSE_TX_DONE\r\n",
+ pPort ));
+
+ //
+ // Empty the receive queue
+ //
+ while ( NULL != pSocket->pRxPacketListHead ) {
+ pPacket = pSocket->pRxPacketListHead;
+ pSocket->pRxPacketListHead = pPacket->pNext;
+ pSocket->RxBytes -= pPacket->Op.Udp4Rx.pRxData->DataLength;
+
+ //
+ // Return the buffer to the UDP4 driver
+ //
+ gBS->SignalEvent ( pPacket->Op.Udp4Rx.pRxData->RecycleSignal );
+
+ //
+ // Done with this packet
+ //
+ EslSocketPacketFree ( pPacket, DEBUG_RX );
+ }
+ pSocket->pRxPacketListTail = NULL;
+ ASSERT ( 0 == pSocket->RxBytes );
+
+ //
+ // Reset the port, cancel the outstanding receive
+ //
+ Status = pUdp4Protocol->Configure ( pUdp4Protocol,
+ NULL );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,
+ "0x%08x: Port reset\r\n",
+ pPort ));
+
+ //
+ // Free the receive packet
+ //
+ Status = gBS->CheckEvent ( pUdp4->RxToken.Event );
+ if ( EFI_SUCCESS != Status ) {
+ EslSocketPacketFree ( pUdp4->pReceivePending, DEBUG_CLOSE );
+ pUdp4->pReceivePending = NULL;
+ Status = EFI_SUCCESS;
+ }
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,
+ "ERROR - Port 0x%08x reset failed, Status: %r\r\n",
+ pPort,
+ Status ));
+ ASSERT ( EFI_SUCCESS == Status );
+ }
+ }
+
+ //
+ // Determine if the receive operation is pending
+ //
+ if ( !EFI_ERROR ( Status )) {
+ Status = EslUdpPortCloseRxDone4 ( pPort );
+ }
+ }
+ else {
+ //
+ // Transmissions are still active, exit
+ //
+ DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
+ "0x%08x: Port Close: Transmits are still pending!\r\n",
+ pPort ));
+ Status = EFI_NOT_READY;
+ pSocket->errno = EAGAIN;
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Connect to a remote system via the network.
+
+ The ::UdpConnectStart4= routine sets the remote address for the connection.
+
+ @param [in] pSocket Address of the socket structure.
+
+ @param [in] pSockAddr Network address of the remote system.
+
+ @param [in] SockAddrLength Length in bytes of the network address.
+
+ @retval EFI_SUCCESS The connection was successfully established.
+ @retval EFI_NOT_READY The connection is in progress, call this routine again.
+ @retval Others The connection attempt failed.
+
+ **/
+EFI_STATUS
+EslUdpConnect4 (
+ IN DT_SOCKET * pSocket,
+ IN const struct sockaddr * pSockAddr,
+ IN socklen_t SockAddrLength
+ )
+{
+ struct sockaddr_in LocalAddress;
+ DT_PORT * pPort;
+ struct sockaddr_in * pRemoteAddress;
+ DT_UDP4_CONTEXT * pUdp4;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume failure
+ //
+ Status = EFI_NETWORK_UNREACHABLE;
+ pSocket->errno = ENETUNREACH;
+
+ //
+ // Get the address
+ //
+ pRemoteAddress = (struct sockaddr_in *)pSockAddr;
+
+ //
+ // Validate the address length
+ //
+ if ( SockAddrLength >= ( sizeof ( *pRemoteAddress )
+ - sizeof ( pRemoteAddress->sin_zero ))) {
+ //
+ // Determine if BIND was already called
+ //
+ if ( NULL == pSocket->pPortList ) {
+ //
+ // Allow any local port
+ //
+ ZeroMem ( &LocalAddress, sizeof ( LocalAddress ));
+ LocalAddress.sin_len = sizeof ( LocalAddress );
+ LocalAddress.sin_family = AF_INET;
+ Status = EslSocketBind ( &pSocket->SocketProtocol,
+ (struct sockaddr *)&LocalAddress,
+ LocalAddress.sin_len,
+ &pSocket->errno );
+ }
+
+ //
+ // Walk the list of ports
+ //
+ pPort = pSocket->pPortList;
+ while ( NULL != pPort ) {
+ //
+ // Set the remote address
+ //
+ pUdp4 = &pPort->Context.Udp4;
+ pUdp4->ConfigData.RemoteAddress.Addr[0] = (UINT8)( pRemoteAddress->sin_addr.s_addr );
+ pUdp4->ConfigData.RemoteAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 );
+ pUdp4->ConfigData.RemoteAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 );
+ pUdp4->ConfigData.RemoteAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 );
+ pUdp4->ConfigData.RemotePort = SwapBytes16 ( pRemoteAddress->sin_port );
+
+ //
+ // At least one path exists
+ //
+ Status = EFI_SUCCESS;
+ pSocket->errno = 0;
+
+ //
+ // Set the next port
+ //
+ pPort = pPort->pLinkSocket;
+ }
+ }
+ else {
+ DEBUG (( DEBUG_CONNECT,
+ "ERROR - Invalid UDP4 address length: %d\r\n",
+ SockAddrLength ));
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EINVAL;
+ }
+
+ //
+ // Return the connect status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Get the local socket address
+
+ @param [in] pSocket Address of the socket structure.
+
+ @param [out] pAddress Network address to receive the local system address
+
+ @param [in,out] pAddressLength Length of the local network address structure
+
+ @retval EFI_SUCCESS - Address available
+ @retval Other - Failed to get the address
+
+**/
+EFI_STATUS
+EslUdpGetLocalAddress4 (
+ IN DT_SOCKET * pSocket,
+ OUT struct sockaddr * pAddress,
+ IN OUT socklen_t * pAddressLength
+ )
+{
+ socklen_t LengthInBytes;
+ DT_PORT * pPort;
+ struct sockaddr_in * pLocalAddress;
+ DT_UDP4_CONTEXT * pUdp4;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Verify the socket layer synchronization
+ //
+ VERIFY_TPL ( TPL_SOCKETS );
+
+ //
+ // Verify that there is just a single connection
+ //
+ pPort = pSocket->pPortList;
+ if (( NULL != pPort ) && ( NULL == pPort->pLinkSocket )) {
+ //
+ // Verify the address length
+ //
+ LengthInBytes = sizeof ( struct sockaddr_in );
+ if ( LengthInBytes <= * pAddressLength ) {
+ //
+ // Return the local address
+ //
+ pUdp4 = &pPort->Context.Udp4;
+ pLocalAddress = (struct sockaddr_in *)pAddress;
+ ZeroMem ( pLocalAddress, LengthInBytes );
+ pLocalAddress->sin_family = AF_INET;
+ pLocalAddress->sin_len = (uint8_t)LengthInBytes;
+ pLocalAddress->sin_port = SwapBytes16 ( pUdp4->ConfigData.StationPort );
+ CopyMem ( &pLocalAddress->sin_addr,
+ &pUdp4->ConfigData.StationAddress.Addr[0],
+ sizeof ( pLocalAddress->sin_addr ));
+ pSocket->errno = 0;
+ Status = EFI_SUCCESS;
+ }
+ else {
+ pSocket->errno = EINVAL;
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+ else {
+ pSocket->errno = ENOTCONN;
+ Status = EFI_NOT_STARTED;
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Get the remote socket address
+
+ @param [in] pSocket Address of the socket structure.
+
+ @param [out] pAddress Network address to receive the remote system address
+
+ @param [in,out] pAddressLength Length of the remote network address structure
+
+ @retval EFI_SUCCESS - Address available
+ @retval Other - Failed to get the address
+
+**/
+EFI_STATUS
+EslUdpGetRemoteAddress4 (
+ IN DT_SOCKET * pSocket,
+ OUT struct sockaddr * pAddress,
+ IN OUT socklen_t * pAddressLength
+ )
+{
+ socklen_t LengthInBytes;
+ DT_PORT * pPort;
+ struct sockaddr_in * pRemoteAddress;
+ DT_UDP4_CONTEXT * pUdp4;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Verify the socket layer synchronization
+ //
+ VERIFY_TPL ( TPL_SOCKETS );
+
+ //
+ // Verify that there is just a single connection
+ //
+ pPort = pSocket->pPortList;
+ if (( NULL != pPort ) && ( NULL == pPort->pLinkSocket )) {
+ //
+ // Verify the address length
+ //
+ LengthInBytes = sizeof ( struct sockaddr_in );
+ if ( LengthInBytes <= * pAddressLength ) {
+ //
+ // Return the local address
+ //
+ pUdp4 = &pPort->Context.Udp4;
+ pRemoteAddress = (struct sockaddr_in *)pAddress;
+ ZeroMem ( pRemoteAddress, LengthInBytes );
+ pRemoteAddress->sin_family = AF_INET;
+ pRemoteAddress->sin_len = (uint8_t)LengthInBytes;
+ pRemoteAddress->sin_port = SwapBytes16 ( pUdp4->ConfigData.RemotePort );
+ CopyMem ( &pRemoteAddress->sin_addr,
+ &pUdp4->ConfigData.RemoteAddress.Addr[0],
+ sizeof ( pRemoteAddress->sin_addr ));
+ pSocket->errno = 0;
+ Status = EFI_SUCCESS;
+ }
+ else {
+ pSocket->errno = EINVAL;
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+ else {
+ pSocket->errno = ENOTCONN;
+ Status = EFI_NOT_STARTED;
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Receive data from a network connection.
+
+ To minimize the number of buffer copies, the ::UdpRxComplete4
+ routine queues the UDP4 driver's buffer to a list of datagrams
+ waiting to be received. The socket driver holds on to the
+ buffers from the UDP4 driver until the application layer requests
+ the data or the socket is closed.
+
+ The application calls this routine in the socket layer to
+ receive datagrams from one or more remote systems. This routine
+ removes the next available datagram from the list of datagrams
+ and copies the data from the UDP4 driver's buffer into the
+ application's buffer. The UDP4 driver's buffer is then returned.
+
+ @param [in] pSocket Address of a DT_SOCKET structure
+
+ @param [in] Flags Message control flags
+
+ @param [in] BufferLength Length of the the buffer
+
+ @param [in] pBuffer Address of a buffer to receive the data.
+
+ @param [in] pDataLength Number of received data bytes in the buffer.
+
+ @param [out] pAddress Network address to receive the remote system address
+
+ @param [in,out] pAddressLength Length of the remote network address structure
+
+ @retval EFI_SUCCESS - Socket data successfully received
+
+**/
+EFI_STATUS
+EslUdpReceive4 (
+ IN DT_SOCKET * pSocket,
+ IN INT32 Flags,
+ IN size_t BufferLength,
+ IN UINT8 * pBuffer,
+ OUT size_t * pDataLength,
+ OUT struct sockaddr * pAddress,
+ IN OUT socklen_t * pAddressLength
+ )
+{
+ socklen_t AddressLength;
+ size_t BytesToCopy;
+ size_t DataBytes;
+ UINT32 Fragment;
+ in_addr_t IpAddress;
+ size_t LengthInBytes;
+ UINT8 * pData;
+ DT_PACKET * pPacket;
+ DT_PORT * pPort;
+ struct sockaddr_in * pRemoteAddress;
+ EFI_UDP4_RECEIVE_DATA * pRxData;
+ DT_UDP4_CONTEXT * pUdp4;
+ struct sockaddr_in RemoteAddress;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume failure
+ //
+ Status = EFI_UNSUPPORTED;
+ pSocket->errno = ENOTCONN;
+
+ //
+ // Verify that the socket is connected
+ //
+ if (( SOCKET_STATE_CONNECTED == pSocket->State )
+ || ( PORT_STATE_RX_ERROR == pSocket->State )) {
+ //
+ // Locate the port
+ //
+ pPort = pSocket->pPortList;
+ if ( NULL != pPort ) {
+ //
+ // Determine if there is any data on the queue
+ //
+ pUdp4 = &pPort->Context.Udp4;
+ pPacket = pSocket->pRxPacketListHead;
+ if ( NULL != pPacket ) {
+ //
+ // Validate the return address parameters
+ //
+ pRxData = pPacket->Op.Udp4Rx.pRxData;
+ if (( NULL == pAddress ) || ( NULL != pAddressLength )) {
+ //
+ // Return the remote system address if requested
+ //
+ if ( NULL != pAddress ) {
+ //
+ // Build the remote address
+ //
+ DEBUG (( DEBUG_RX,
+ "Getting packet source address: %d.%d.%d.%d:%d\r\n",
+ pRxData->UdpSession.SourceAddress.Addr[0],
+ pRxData->UdpSession.SourceAddress.Addr[1],
+ pRxData->UdpSession.SourceAddress.Addr[2],
+ pRxData->UdpSession.SourceAddress.Addr[3],
+ pRxData->UdpSession.SourcePort ));
+ ZeroMem ( &RemoteAddress, sizeof ( RemoteAddress ));
+ RemoteAddress.sin_len = sizeof ( RemoteAddress );
+ RemoteAddress.sin_family = AF_INET;
+ IpAddress = pRxData->UdpSession.SourceAddress.Addr[3];
+ IpAddress <<= 8;
+ IpAddress |= pRxData->UdpSession.SourceAddress.Addr[2];
+ IpAddress <<= 8;
+ IpAddress |= pRxData->UdpSession.SourceAddress.Addr[1];
+ IpAddress <<= 8;
+ IpAddress |= pRxData->UdpSession.SourceAddress.Addr[0];
+ RemoteAddress.sin_addr.s_addr = IpAddress;
+ RemoteAddress.sin_port = SwapBytes16 ( pRxData->UdpSession.SourcePort );
+
+ //
+ // Copy the address
+ //
+ pRemoteAddress = (struct sockaddr_in *)pAddress;
+ AddressLength = sizeof ( *pRemoteAddress );
+ if ( AddressLength > *pAddressLength ) {
+ AddressLength = *pAddressLength;
+ }
+ CopyMem ( pRemoteAddress,
+ &RemoteAddress,
+ AddressLength );
+
+ //
+ // Update the address length
+ //
+ *pAddressLength = AddressLength;
+ }
+
+ //
+ // Reduce the buffer length if necessary
+ //
+ DataBytes = pRxData->DataLength;
+ if ( DataBytes < BufferLength ) {
+ BufferLength = DataBytes;
+ }
+
+ //
+ // Copy the received data
+ //
+ LengthInBytes = 0;
+ Fragment = 0;
+ do {
+ //
+ // Determine the amount of received data
+ //
+ pData = pRxData->FragmentTable[Fragment].FragmentBuffer;
+ BytesToCopy = pRxData->FragmentTable[Fragment].FragmentLength;
+ if (( BufferLength - LengthInBytes ) < BytesToCopy ) {
+ BytesToCopy = BufferLength - LengthInBytes;
+ }
+ LengthInBytes += BytesToCopy;
+
+ //
+ // Move the data into the buffer
+ //
+ DEBUG (( DEBUG_RX,
+ "0x%08x: Port copy packet 0x%08x data into 0x%08x, 0x%08x bytes\r\n",
+ pPort,
+ pPacket,
+ pBuffer,
+ BytesToCopy ));
+ CopyMem ( pBuffer, pData, BytesToCopy );
+ } while ( BufferLength > LengthInBytes );
+
+ //
+ // Determine if the data is being read
+ //
+ if ( 0 == ( Flags & MSG_PEEK )) {
+ //
+ // Display for the bytes consumed
+ //
+ DEBUG (( DEBUG_RX,
+ "0x%08x: Port account for 0x%08x bytes\r\n",
+ pPort,
+ BufferLength ));
+
+ //
+ // All done with this packet
+ // Account for any discarded data
+ //
+ pSocket->RxBytes -= DataBytes;
+ if ( 0 != ( DataBytes - BufferLength )) {
+ DEBUG (( DEBUG_RX,
+ "0x%08x: Port, packet read, skipping over 0x%08x bytes\r\n",
+ pPort,
+ DataBytes - BufferLength ));
+ }
+
+ //
+ // Remove this packet from the queue
+ //
+ pSocket->pRxPacketListHead = pPacket->pNext;
+ if ( NULL == pSocket->pRxPacketListHead ) {
+ pSocket->pRxPacketListTail = NULL;
+ }
+
+ //
+ // Return this packet to the UDP4 driver
+ //
+ gBS->SignalEvent ( pRxData->RecycleSignal );
+
+ //
+ // Move the packet to the free queue
+ //
+ pPacket->pNext = pSocket->pRxFree;
+ pSocket->pRxFree = pPacket;
+ DEBUG (( DEBUG_RX,
+ "0x%08x: Port freeing packet 0x%08x\r\n",
+ pPort,
+ pPacket ));
+
+ //
+ // Restart this receive operation if necessary
+ //
+ if (( NULL == pUdp4->pReceivePending )
+ && ( MAX_RX_DATA > pSocket->RxBytes )) {
+ EslUdpRxStart4 ( pPort );
+ }
+ }
+
+ //
+ // Return the data length
+ //
+ *pDataLength = LengthInBytes;
+
+ //
+ // Successful operation
+ //
+ Status = EFI_SUCCESS;
+ pSocket->errno = 0;
+ }
+ else {
+ //
+ // Bad return address pointer and length
+ //
+ Status = EFI_INVALID_PARAMETER;
+ pSocket->errno = EINVAL;
+ }
+ }
+ else {
+ //
+ // The queue is empty
+ // Determine if it is time to return the receive error
+ //
+ if ( EFI_ERROR ( pSocket->RxError )) {
+ Status = pSocket->RxError;
+ switch ( Status ) {
+ default:
+ pSocket->errno = EIO;
+ break;
+
+ case EFI_HOST_UNREACHABLE:
+ pSocket->errno = EHOSTUNREACH;
+ break;
+
+ case EFI_NETWORK_UNREACHABLE:
+ pSocket->errno = ENETUNREACH;
+ break;
+
+ case EFI_PORT_UNREACHABLE:
+ pSocket->errno = EPROTONOSUPPORT;
+ break;
+
+ case EFI_PROTOCOL_UNREACHABLE:
+ pSocket->errno = ENOPROTOOPT;
+ break;
+ }
+ pSocket->RxError = EFI_SUCCESS;
+ }
+ else {
+ Status = EFI_NOT_READY;
+ pSocket->errno = EAGAIN;
+ }
+ }
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Cancel the receive operations
+
+ @param [in] pSocket Address of a DT_SOCKET structure
+
+ @retval EFI_SUCCESS - The cancel was successful
+
+ **/
+EFI_STATUS
+EslUdpRxCancel4 (
+ IN DT_SOCKET * pSocket
+ )
+{
+ DT_PACKET * pPacket;
+ DT_PORT * pPort;
+ DT_UDP4_CONTEXT * pUdp4;
+ EFI_UDP4_PROTOCOL * pUdp4Protocol;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume failure
+ //
+ Status = EFI_NOT_FOUND;
+
+ //
+ // Locate the port
+ //
+ pPort = pSocket->pPortList;
+ if ( NULL != pPort ) {
+ //
+ // Determine if a receive is pending
+ //
+ pUdp4 = &pPort->Context.Udp4;
+ pPacket = pUdp4->pReceivePending;
+ if ( NULL != pPacket ) {
+ //
+ // Attempt to cancel the receive operation
+ //
+ pUdp4Protocol = pUdp4->pProtocol;
+ Status = pUdp4Protocol->Cancel ( pUdp4Protocol,
+ &pUdp4->RxToken );
+ if ( EFI_NOT_FOUND == Status ) {
+ //
+ // The receive is complete
+ //
+ Status = EFI_SUCCESS;
+ }
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Process the receive completion
+
+ Keep the UDP4 driver's buffer and append it to the list of
+ datagrams for the application to receive. The UDP4 driver's
+ buffer will be returned by either ::UdpReceive4 or
+ ::UdpPortCloseTxDone4.
+
+ @param Event The receive completion event
+
+ @param pPort The DT_PORT structure address
+
+**/
+VOID
+EslUdpRxComplete4 (
+ IN EFI_EVENT Event,
+ IN DT_PORT * pPort
+ )
+{
+ size_t LengthInBytes;
+ DT_PACKET * pPacket;
+ DT_PACKET * pPrevious;
+ EFI_UDP4_RECEIVE_DATA * pRxData;
+ DT_SOCKET * pSocket;
+ DT_UDP4_CONTEXT * pUdp4;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Mark this receive complete
+ //
+ pUdp4 = &pPort->Context.Udp4;
+ pPacket = pUdp4->pReceivePending;
+ pUdp4->pReceivePending = NULL;
+
+ //
+ // Determine if this receive was successful
+ //
+ pSocket = pPort->pSocket;
+ Status = pUdp4->RxToken.Status;
+ if (( !EFI_ERROR ( Status )) && ( !pSocket->bRxDisable )) {
+ pRxData = pUdp4->RxToken.Packet.RxData;
+ if ( PORT_STATE_CLOSE_STARTED >= pPort->State ) {
+ //
+ // Save the data in the packet
+ //
+ pPacket->Op.Udp4Rx.pRxData = pRxData;
+
+ //
+ // Queue this packet
+ //
+ pPrevious = pSocket->pRxPacketListTail;
+ if ( NULL == pPrevious ) {
+ pSocket->pRxPacketListHead = pPacket;
+ }
+ else {
+ pPrevious->pNext = pPacket;
+ }
+ pSocket->pRxPacketListTail = pPacket;
+
+ //
+ // Account for the normal data
+ //
+ LengthInBytes = pRxData->DataLength;
+ pSocket->RxBytes += LengthInBytes;
+
+ //
+ // Log the received data
+ //
+ DEBUG (( DEBUG_RX | DEBUG_INFO,
+ "Received packet from: %d.%d.%d.%d:%d\r\n",
+ pRxData->UdpSession.SourceAddress.Addr[0],
+ pRxData->UdpSession.SourceAddress.Addr[1],
+ pRxData->UdpSession.SourceAddress.Addr[2],
+ pRxData->UdpSession.SourceAddress.Addr[3],
+ pRxData->UdpSession.SourcePort ));
+ DEBUG (( DEBUG_RX | DEBUG_INFO,
+ "Received packet sent to: %d.%d.%d.%d:%d\r\n",
+ pRxData->UdpSession.DestinationAddress.Addr[0],
+ pRxData->UdpSession.DestinationAddress.Addr[1],
+ pRxData->UdpSession.DestinationAddress.Addr[2],
+ pRxData->UdpSession.DestinationAddress.Addr[3],
+ pRxData->UdpSession.DestinationPort ));
+ DEBUG (( DEBUG_RX | DEBUG_INFO,
+ "0x%08x: Packet queued on port 0x%08x with 0x%08x bytes of data\r\n",
+ pPacket,
+ pPort,
+ LengthInBytes ));
+
+ //
+ // Attempt to restart this receive operation
+ //
+ if ( pSocket->MaxRxBuf > pSocket->RxBytes ) {
+ EslUdpRxStart4 ( pPort );
+ }
+ else {
+ DEBUG (( DEBUG_RX,
+ "0x%08x: Port RX suspended, 0x%08x bytes queued\r\n",
+ pPort,
+ pSocket->RxBytes ));
+ }
+ }
+ else {
+ //
+ // The port is being closed
+ // Return the buffer to the UDP4 driver
+ //
+ gBS->SignalEvent ( pRxData->RecycleSignal );
+
+ //
+ // Free the packet
+ //
+ EslSocketPacketFree ( pPacket, DEBUG_RX );
+ }
+ }
+ else
+ {
+ DEBUG (( DEBUG_RX | DEBUG_INFO,
+ "ERROR - Receiving packet 0x%08x, on port 0x%08x, Status:%r\r\n",
+ pPacket,
+ pPort,
+ Status ));
+
+ //
+ // Receive error, free the packet save the error
+ //
+ EslSocketPacketFree ( pPacket, DEBUG_RX );
+ if ( !EFI_ERROR ( pSocket->RxError )) {
+ pSocket->RxError = Status;
+ }
+
+ //
+ // Update the port state
+ //
+ if ( PORT_STATE_CLOSE_STARTED <= pPort->State ) {
+ EslUdpPortCloseRxDone4 ( pPort );
+ }
+ else {
+ if ( EFI_ERROR ( Status )) {
+ pPort->State = PORT_STATE_RX_ERROR;
+ }
+ }
+ }
+
+ DBG_EXIT ( );
+}
+
+
+/**
+ Start a receive operation
+
+ @param [in] pPort Address of the DT_PORT structure.
+
+ **/
+VOID
+EslUdpRxStart4 (
+ IN DT_PORT * pPort
+ )
+{
+ DT_PACKET * pPacket;
+ DT_SOCKET * pSocket;
+ DT_UDP4_CONTEXT * pUdp4;
+ EFI_UDP4_PROTOCOL * pUdp4Protocol;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Determine if a receive is already pending
+ //
+ Status = EFI_SUCCESS;
+ pPacket = NULL;
+ pSocket = pPort->pSocket;
+ pUdp4 = &pPort->Context.Udp4;
+ if ( !EFI_ERROR ( pPort->pSocket->RxError )) {
+ if (( NULL == pUdp4->pReceivePending )
+ && ( PORT_STATE_CLOSE_STARTED > pPort->State )) {
+ //
+ // Determine if there are any free packets
+ //
+ pPacket = pSocket->pRxFree;
+ if ( NULL != pPacket ) {
+ //
+ // Remove this packet from the free list
+ //
+ pSocket->pRxFree = pPacket->pNext;
+ DEBUG (( DEBUG_RX,
+ "0x%08x: Port removed packet 0x%08x from free list\r\n",
+ pPort,
+ pPacket ));
+ }
+ else {
+ //
+ // Allocate a packet structure
+ //
+ Status = EslSocketPacketAllocate ( &pPacket,
+ sizeof ( pPacket->Op.Udp4Rx ),
+ DEBUG_RX );
+ if ( EFI_ERROR ( Status )) {
+ pPacket = NULL;
+ DEBUG (( DEBUG_ERROR | DEBUG_RX,
+ "0x%08x: Port failed to allocate RX packet, Status: %r\r\n",
+ pPort,
+ Status ));
+ }
+ }
+
+ //
+ // Determine if a packet is available
+ //
+ if ( NULL != pPacket ) {
+ //
+ // Initialize the buffer for receive
+ //
+ pPacket->pNext = NULL;
+ pPacket->Op.Udp4Rx.pRxData = NULL;
+ pUdp4->RxToken.Packet.RxData = NULL;
+ pUdp4->pReceivePending = pPacket;
+
+ //
+ // Start the receive on the packet
+ //
+ pUdp4Protocol = pUdp4->pProtocol;
+ Status = pUdp4Protocol->Receive ( pUdp4Protocol,
+ &pUdp4->RxToken );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_RX | DEBUG_INFO,
+ "0x%08x: Packet receive pending on port 0x%08x\r\n",
+ pPacket,
+ pPort ));
+ }
+ else {
+ DEBUG (( DEBUG_RX | DEBUG_INFO,
+ "ERROR - Failed to post a receive on port 0x%08x, Status: %r\r\n",
+ pPort,
+ Status ));
+ if ( !EFI_ERROR ( pSocket->RxError )) {
+ //
+ // Save the error status
+ //
+ pSocket->RxError = Status;
+ }
+
+ //
+ // Free the packet
+ //
+ pUdp4->pReceivePending = NULL;
+ pPacket->pNext = pSocket->pRxFree;
+ pSocket->pRxFree = pPacket;
+ }
+ }
+ }
+ }
+
+ DBG_EXIT ( );
+}
+
+
+/**
+ Shutdown the UDP4 service.
+
+ This routine undoes the work performed by ::UdpInitialize4.
+
+ @param [in] pService DT_SERVICE structure address
+
+**/
+VOID
+EFIAPI
+EslUdpShutdown4 (
+ IN DT_SERVICE * pService
+ )
+{
+ DT_LAYER * pLayer;
+ DT_PORT * pPort;
+ DT_SERVICE * pPreviousService;
+
+ DBG_ENTER ( );
+
+ //
+ // Verify the socket layer synchronization
+ //
+ VERIFY_TPL ( TPL_SOCKETS );
+
+ //
+ // Walk the list of ports
+ //
+ do {
+ pPort = pService->pPortList;
+ if ( NULL != pPort ) {
+ //
+ // Remove the port from the port list
+ //
+ pService->pPortList = pPort->pLinkService;
+
+ //
+ // Close the port
+ // TODO: Fix this
+ //
+// pPort->pfnClosePort ( pPort, 0 );
+ }
+ } while ( NULL != pPort );
+
+ //
+ // Remove the service from the service list
+ //
+ pLayer = &mEslLayer;
+ pPreviousService = pLayer->pUdp4List;
+ if ( pService == pPreviousService ) {
+ //
+ // Remove the service from the beginning of the list
+ //
+ pLayer->pUdp4List = pService->pNext;
+ }
+ else {
+ //
+ // Remove the service from the middle of the list
+ //
+ while ( NULL != pPreviousService ) {
+ if ( pService == pPreviousService->pNext ) {
+ pPreviousService->pNext = pService->pNext;
+ break;
+ }
+ }
+ }
+
+ DBG_EXIT ( );
+}
+
+
+/**
+ Determine if the sockedt is configured.
+
+
+ @param [in] pSocket Address of a DT_SOCKET structure
+
+ @retval EFI_SUCCESS - The port is connected
+ @retval EFI_NOT_STARTED - The port is not connected
+
+ **/
+ EFI_STATUS
+ EslUdpSocketIsConfigured4 (
+ IN DT_SOCKET * pSocket
+ )
+{
+ DT_PORT * pPort;
+ DT_PORT * pNextPort;
+ DT_UDP4_CONTEXT * pUdp4;
+ EFI_UDP4_PROTOCOL * pUdp4Protocol;
+ EFI_STATUS Status;
+ struct sockaddr_in LocalAddress;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume success
+ //
+ Status = EFI_SUCCESS;
+
+ //
+ // Configure the port if necessary
+ //
+ if ( !pSocket->bConfigured ) {
+ //
+ // Fill in the port list if necessary
+ //
+ if ( NULL == pSocket->pPortList ) {
+ LocalAddress.sin_len = sizeof ( LocalAddress );
+ LocalAddress.sin_family = AF_INET;
+ LocalAddress.sin_addr.s_addr = 0;
+ LocalAddress.sin_port = 0;
+ Status = EslUdpBind4 ( pSocket,
+ (struct sockaddr *)&LocalAddress,
+ LocalAddress.sin_len );
+ }
+
+ //
+ // Walk the port list
+ //
+ pPort = pSocket->pPortList;
+ while ( NULL != pPort ) {
+ //
+ // Attempt to configure the port
+ //
+ pNextPort = pPort->pLinkSocket;
+ pUdp4 = &pPort->Context.Udp4;
+ pUdp4Protocol = pUdp4->pProtocol;
+ Status = pUdp4Protocol->Configure ( pUdp4Protocol,
+ &pUdp4->ConfigData );
+ if ( EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_LISTEN,
+ "ERROR - Failed to configure the Udp4 port, Status: %r\r\n",
+ Status ));
+ switch ( Status ) {
+ case EFI_ACCESS_DENIED:
+ pSocket->errno = EACCES;
+ break;
+
+ default:
+ case EFI_DEVICE_ERROR:
+ pSocket->errno = EIO;
+ break;
+
+ case EFI_INVALID_PARAMETER:
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case EFI_NO_MAPPING:
+ pSocket->errno = EAFNOSUPPORT;
+ break;
+
+ case EFI_OUT_OF_RESOURCES:
+ pSocket->errno = ENOBUFS;
+ break;
+
+ case EFI_UNSUPPORTED:
+ pSocket->errno = EOPNOTSUPP;
+ break;
+ }
+ }
+ else {
+ DEBUG (( DEBUG_LISTEN,
+ "0x%08x: Port configured\r\n",
+ pPort ));
+ pUdp4->bConfigured = TRUE;
+
+ //
+ // Start the first read on the port
+ //
+ EslUdpRxStart4 ( pPort );
+
+ //
+ // The socket is connected
+ //
+ pSocket->State = SOCKET_STATE_CONNECTED;
+ }
+
+ //
+ // Set the next port
+ //
+ pPort = pNextPort;
+ }
+
+ //
+ // Determine the configuration status
+ //
+ if ( NULL != pSocket->pPortList ) {
+ pSocket->bConfigured = TRUE;
+ }
+ }
+
+ //
+ // Determine the socket configuration status
+ //
+ if ( !EFI_ERROR ( Status )) {
+ Status = pSocket->bConfigured ? EFI_SUCCESS : EFI_NOT_STARTED;
+ }
+
+ //
+ // Return the port connected state.
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Buffer data for transmission over a network connection.
+
+ This routine is called by the socket layer API to buffer
+ data for transmission. The data is copied into a local buffer
+ freeing the application buffer for reuse upon return. When
+ necessary, this routine will start the transmit engine that
+ performs the data transmission on the network connection. The
+ transmit engine transmits the data a packet at a time over the
+ network connection.
+
+ Transmission errors are returned during the next transmission or
+ during the close operation. Only buffering errors are returned
+ during the current transmission attempt.
+
+ @param [in] pSocket Address of a DT_SOCKET structure
+
+ @param [in] Flags Message control flags
+
+ @param [in] BufferLength Length of the the buffer
+
+ @param [in] pBuffer Address of a buffer to receive the data.
+
+ @param [in] pDataLength Number of received data bytes in the buffer.
+
+ @param [in] pAddress Network address of the remote system address
+
+ @param [in] AddressLength Length of the remote network address structure
+
+ @retval EFI_SUCCESS - Socket data successfully buffered
+
+**/
+EFI_STATUS
+EslUdpTxBuffer4 (
+ IN DT_SOCKET * pSocket,
+ IN int Flags,
+ IN size_t BufferLength,
+ IN CONST UINT8 * pBuffer,
+ OUT size_t * pDataLength,
+ IN const struct sockaddr * pAddress,
+ IN socklen_t AddressLength
+ )
+{
+ DT_PACKET * pPacket;
+ DT_PACKET * pPreviousPacket;
+ DT_PACKET ** ppPacket;
+ DT_PORT * pPort;
+ const struct sockaddr_in * pRemoteAddress;
+ DT_UDP4_CONTEXT * pUdp4;
+ EFI_UDP4_COMPLETION_TOKEN * pToken;
+ size_t * pTxBytes;
+ DT_UDP4_TX_DATA * pTxData;
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume failure
+ //
+ Status = EFI_UNSUPPORTED;
+ pSocket->errno = ENOTCONN;
+ * pDataLength = 0;
+
+ //
+ // Verify that the socket is connected
+ //
+ if ( SOCKET_STATE_CONNECTED == pSocket->State ) {
+ //
+ // Locate the port
+ //
+ pPort = pSocket->pPortList;
+ if ( NULL != pPort ) {
+ //
+ // Determine the queue head
+ //
+ pUdp4 = &pPort->Context.Udp4;
+ ppPacket = &pUdp4->pTxPacket;
+ pToken = &pUdp4->TxToken;
+ pTxBytes = &pSocket->TxBytes;
+
+ //
+ // Verify that there is enough room to buffer another
+ // transmit operation
+ //
+ if ( pSocket->MaxTxBuf > *pTxBytes ) {
+ //
+ // Attempt to allocate the packet
+ //
+ Status = EslSocketPacketAllocate ( &pPacket,
+ sizeof ( pPacket->Op.Udp4Tx )
+ - sizeof ( pPacket->Op.Udp4Tx.Buffer )
+ + BufferLength,
+ DEBUG_TX );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Initialize the transmit operation
+ //
+ pTxData = &pPacket->Op.Udp4Tx;
+ pTxData->TxData.GatewayAddress = NULL;
+ pTxData->TxData.UdpSessionData = NULL;
+ pTxData->TxData.DataLength = (UINT32) BufferLength;
+ pTxData->TxData.FragmentCount = 1;
+ pTxData->TxData.FragmentTable[0].FragmentLength = (UINT32) BufferLength;
+ pTxData->TxData.FragmentTable[0].FragmentBuffer = &pPacket->Op.Udp4Tx.Buffer[0];
+
+ //
+ // Set the remote system address if necessary
+ //
+ if ( NULL != pAddress ) {
+ pRemoteAddress = (const struct sockaddr_in *)pAddress;
+ pTxData->Session.SourceAddress.Addr[0] = 0;
+ pTxData->Session.SourceAddress.Addr[1] = 0;
+ pTxData->Session.SourceAddress.Addr[2] = 0;
+ pTxData->Session.SourceAddress.Addr[3] = 0;
+ pTxData->Session.SourcePort = 0;
+ pTxData->Session.DestinationAddress.Addr[0] = (UINT8)pRemoteAddress->sin_addr.s_addr;
+ pTxData->Session.DestinationAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 );
+ pTxData->Session.DestinationAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 );
+ pTxData->Session.DestinationAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 );
+ pTxData->Session.DestinationPort = SwapBytes16 ( pRemoteAddress->sin_port );
+
+ //
+ // Use the remote system address when sending this packet
+ //
+ pTxData->TxData.UdpSessionData = &pTxData->Session;
+ }
+
+ //
+ // Copy the data into the buffer
+ //
+ CopyMem ( &pPacket->Op.Udp4Tx.Buffer[0],
+ pBuffer,
+ BufferLength );
+
+ //
+ // Synchronize with the socket layer
+ //
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );
+
+ //
+ // Stop transmission after an error
+ //
+ if ( !EFI_ERROR ( pSocket->TxError )) {
+ //
+ // Display the request
+ //
+ DEBUG (( DEBUG_TX,
+ "Send %d %s bytes from 0x%08x\r\n",
+ BufferLength,
+ pBuffer ));
+
+ //
+ // Queue the data for transmission
+ //
+ pPacket->pNext = NULL;
+ pPreviousPacket = pSocket->pTxPacketListTail;
+ if ( NULL == pPreviousPacket ) {
+ pSocket->pTxPacketListHead = pPacket;
+ }
+ else {
+ pPreviousPacket->pNext = pPacket;
+ }
+ pSocket->pTxPacketListTail = pPacket;
+ DEBUG (( DEBUG_TX,
+ "0x%08x: Packet on transmit list\r\n",
+ pPacket ));
+
+ //
+ // Account for the buffered data
+ //
+ *pTxBytes += BufferLength;
+ *pDataLength = BufferLength;
+
+ //
+ // Start the transmit engine if it is idle
+ //
+ if ( NULL == pUdp4->pTxPacket ) {
+ EslUdpTxStart4 ( pSocket->pPortList );
+ }
+ }
+ else {
+ //
+ // Previous transmit error
+ // Stop transmission
+ //
+ Status = pSocket->TxError;
+ pSocket->errno = EIO;
+
+ //
+ // Free the packet
+ //
+ EslSocketPacketFree ( pPacket, DEBUG_TX );
+ }
+
+ //
+ // Release the socket layer synchronization
+ //
+ RESTORE_TPL ( TplPrevious );
+ }
+ else {
+ //
+ // Packet allocation failed
+ //
+ pSocket->errno = ENOMEM;
+ }
+ }
+ else {
+ //
+ // Not enough buffer space available
+ //
+ pSocket->errno = EAGAIN;
+ Status = EFI_NOT_READY;
+ }
+ }
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Process the transmit completion
+
+ @param Event The normal transmit completion event
+
+ @param pPort The DT_PORT structure address
+
+**/
+VOID
+EslUdpTxComplete4 (
+ IN EFI_EVENT Event,
+ IN DT_PORT * pPort
+ )
+{
+ UINT32 LengthInBytes;
+ DT_PACKET * pCurrentPacket;
+ DT_PACKET * pNextPacket;
+ DT_PACKET * pPacket;
+ DT_SOCKET * pSocket;
+ DT_UDP4_CONTEXT * pUdp4;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Locate the active transmit packet
+ //
+ pSocket = pPort->pSocket;
+ pUdp4 = &pPort->Context.Udp4;
+ pPacket = pUdp4->pTxPacket;
+
+ //
+ // Mark this packet as complete
+ //
+ pUdp4->pTxPacket = NULL;
+ LengthInBytes = pPacket->Op.Udp4Tx.TxData.DataLength;
+ pSocket->TxBytes -= LengthInBytes;
+
+ //
+ // Save any transmit error
+ //
+ Status = pUdp4->TxToken.Status;
+ if ( EFI_ERROR ( Status )) {
+ if ( !EFI_ERROR ( pSocket->TxError )) {
+ pSocket->TxError = Status;
+ }
+ DEBUG (( DEBUG_TX | DEBUG_INFO,
+ "ERROR - Transmit failure for packet 0x%08x, Status: %r\r\n",
+ pPacket,
+ Status ));
+
+ //
+ // Empty the normal transmit list
+ //
+ pCurrentPacket = pPacket;
+ pNextPacket = pSocket->pTxPacketListHead;
+ while ( NULL != pNextPacket ) {
+ pPacket = pNextPacket;
+ pNextPacket = pPacket->pNext;
+ EslSocketPacketFree ( pPacket, DEBUG_TX );
+ }
+ pSocket->pTxPacketListHead = NULL;
+ pSocket->pTxPacketListTail = NULL;
+ pPacket = pCurrentPacket;
+ }
+ else
+ {
+ DEBUG (( DEBUG_TX | DEBUG_INFO,
+ "0x%08x: Packet transmitted %d bytes successfully\r\n",
+ pPacket,
+ LengthInBytes ));
+
+ //
+ // Verify the transmit engine is still running
+ //
+ if ( !pPort->bCloseNow ) {
+ //
+ // Start the next packet transmission
+ //
+ EslUdpTxStart4 ( pPort );
+ }
+ }
+
+ //
+ // Release this packet
+ //
+ EslSocketPacketFree ( pPacket, DEBUG_TX );
+
+ //
+ // Finish the close operation if necessary
+ //
+ if (( PORT_STATE_CLOSE_STARTED <= pPort->State )
+ && ( NULL == pSocket->pTxPacketListHead )
+ && ( NULL == pUdp4->pTxPacket )) {
+ //
+ // Indicate that the transmit is complete
+ //
+ EslUdpPortCloseTxDone4 ( pPort );
+ }
+ DBG_EXIT ( );
+}
+
+
+/**
+ Transmit data using a network connection.
+
+ @param [in] pPort Address of a DT_PORT structure
+
+ **/
+VOID
+EslUdpTxStart4 (
+ IN DT_PORT * pPort
+ )
+{
+ DT_PACKET * pNextPacket;
+ DT_PACKET * pPacket;
+ DT_SOCKET * pSocket;
+ DT_UDP4_CONTEXT * pUdp4;
+ EFI_UDP4_PROTOCOL * pUdp4Protocol;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume success
+ //
+ Status = EFI_SUCCESS;
+
+ //
+ // Get the packet from the queue head
+ //
+ pSocket = pPort->pSocket;
+ pPacket = pSocket->pTxPacketListHead;
+ if ( NULL != pPacket ) {
+ //
+ // Remove the packet from the queue
+ //
+ pNextPacket = pPacket->pNext;
+ pSocket->pTxPacketListHead = pNextPacket;
+ if ( NULL == pNextPacket ) {
+ pSocket->pTxPacketListTail = NULL;
+ }
+
+ //
+ // Set the packet as active
+ //
+ pUdp4 = &pPort->Context.Udp4;
+ pUdp4->pTxPacket = pPacket;
+
+ //
+ // Start the transmit operation
+ //
+ pUdp4Protocol = pUdp4->pProtocol;
+ pUdp4->TxToken.Packet.TxData = &pPacket->Op.Udp4Tx.TxData;
+ Status = pUdp4Protocol->Transmit ( pUdp4Protocol, &pUdp4->TxToken );
+ if ( EFI_ERROR ( Status )) {
+ pSocket = pPort->pSocket;
+ if ( EFI_SUCCESS == pSocket->TxError ) {
+ pSocket->TxError = Status;
+ }
+ }
+ }
+
+ DBG_EXIT ( );
+}
+
diff --git a/StdLib/EfiSocketLib/UseEfiSocketLib.c b/StdLib/EfiSocketLib/UseEfiSocketLib.c new file mode 100644 index 0000000000..b0e8ef671a --- /dev/null +++ b/StdLib/EfiSocketLib/UseEfiSocketLib.c @@ -0,0 +1,242 @@ +/** @file
+ Implement the connection to the EFI socket library
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <socket.h>
+
+
+CONST EFI_GUID mEslRawServiceGuid = {
+ 0xc31bf4a5, 0x2c7, 0x49d2, { 0xa5, 0x58, 0xfe, 0x62, 0x6f, 0x7e, 0xd4, 0x77 }
+};
+
+CONST EFI_GUID mEslTcp4ServiceGuid = {
+ 0xffc659c2, 0x4ef2, 0x4532, { 0xb8, 0x75, 0xcd, 0x9a, 0xa4, 0x27, 0x4c, 0xde }
+};
+
+CONST EFI_GUID mEslUdp4ServiceGuid = {
+ 0x44e03a55, 0x8d97, 0x4511, { 0xbf, 0xef, 0xa, 0x8b, 0xc6, 0x2c, 0x25, 0xae }
+};
+
+
+/**
+ Connect to the EFI socket library
+
+ @param [in] ppSocketProtocol Address to receive the socket protocol address
+
+ @retval 0 Successfully returned the socket protocol
+ @retval other Value for errno
+ **/
+int
+EslServiceGetProtocol (
+ IN EFI_SOCKET_PROTOCOL ** ppSocketProtocol
+ )
+{
+ EFI_HANDLE ChildHandle;
+ DT_SOCKET * pSocket;
+ int RetVal;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume success
+ //
+ RetVal = 0;
+
+ //
+ // Locate the socket protocol
+ //
+ ChildHandle = NULL;
+ Status = EslSocketAllocate ( &ChildHandle,
+ DEBUG_SOCKET,
+ &pSocket );
+ if ( !EFI_ERROR ( Status )) {
+ *ppSocketProtocol = &pSocket->SocketProtocol;
+ }
+ else {
+ //
+ // No resources
+ //
+ RetVal = ENOMEM;
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_DEC ( RetVal );
+ return RetVal;
+}
+
+
+/**
+ Connect to the network layer
+
+ @retval EFI_SUCCESS Successfully connected to the network layer
+
+ **/
+EFI_STATUS
+EslServiceNetworkConnect (
+ VOID
+ )
+{
+ UINTN HandleCount;
+ EFI_HANDLE * pHandles;
+ UINTN Index;
+ CONST DT_SOCKET_BINDING * pSocketBinding;
+ CONST DT_SOCKET_BINDING * pEnd;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Initialize the socket layer
+ //
+ Status = EFI_SUCCESS;
+ EslServiceLoad ( gImageHandle );
+
+ //
+ // Connect the network devices
+ //
+ pSocketBinding = &cEslSocketBinding [0];
+ pEnd = &pSocketBinding [ cEslSocketBindingEntries ];
+ while ( pEnd > pSocketBinding ) {
+ //
+ // Attempt to locate the network adapters
+ //
+ HandleCount = 0;
+ pHandles = NULL;
+ Status = gBS->LocateHandleBuffer ( ByProtocol,
+ pSocketBinding->pNetworkBinding,
+ NULL,
+ &HandleCount,
+ &pHandles );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ if ( NULL != pHandles ) {
+ //
+ // Attempt to connect to this network adapter
+ //
+ for ( Index = 0; HandleCount > Index; Index++ ) {
+ Status = EslServiceConnect ( gImageHandle,
+ pHandles [ Index ]);
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ }
+
+ //
+ // Done with the handles
+ //
+ gBS->FreePool ( pHandles );
+ }
+
+ //
+ // Set the next network protocol
+ //
+ pSocketBinding += 1;
+ }
+
+ //
+ // Return the network connection status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Disconnect from the network layer
+
+ @retval EFI_SUCCESS Successfully disconnected from the network layer
+
+ **/
+EFI_STATUS
+EslServiceNetworkDisconnect (
+ VOID
+ )
+{
+ UINTN HandleCount;
+ EFI_HANDLE * pHandles;
+ UINTN Index;
+ CONST DT_SOCKET_BINDING * pSocketBinding;
+ CONST DT_SOCKET_BINDING * pEnd;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume success
+ //
+ Status = EFI_SUCCESS;
+
+ //
+ // Disconnect the network devices
+ //
+ pSocketBinding = &cEslSocketBinding [0];
+ pEnd = &pSocketBinding [ cEslSocketBindingEntries ];
+ while ( pEnd > pSocketBinding ) {
+ //
+ // Attempt to locate the network adapters
+ //
+ HandleCount = 0;
+ pHandles = NULL;
+ Status = gBS->LocateHandleBuffer ( ByProtocol,
+ pSocketBinding->pNetworkBinding,
+ NULL,
+ &HandleCount,
+ &pHandles );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ if ( NULL != pHandles ) {
+ //
+ // Attempt to disconnect from this network adapter
+ //
+ for ( Index = 0; HandleCount > Index; Index++ ) {
+ Status = EslServiceDisconnect ( gImageHandle,
+ pHandles [ Index ]);
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ }
+
+ //
+ // Done with the handles
+ //
+ gBS->FreePool ( pHandles );
+ }
+
+ //
+ // Set the next network protocol
+ //
+ pSocketBinding += 1;
+ }
+
+ //
+ // Finish the disconnect operation
+ //
+ if ( !EFI_ERROR ( Status )) {
+ EslServiceUnload ( );
+ }
+
+ //
+ // Return the network connection status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+PFN_ESL_xSTRUCTOR mpfnEslConstructor = EslServiceNetworkConnect;
+PFN_ESL_xSTRUCTOR mpfnEslDestructor = EslServiceNetworkDisconnect;
diff --git a/StdLib/Include/Efi/EfiSocketLib.h b/StdLib/Include/Efi/EfiSocketLib.h new file mode 100644 index 0000000000..53ad0d4003 --- /dev/null +++ b/StdLib/Include/Efi/EfiSocketLib.h @@ -0,0 +1,679 @@ +/** @file
+ Definitions for the EFI Socket layer library.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EFI_SOCKET_LIB_H_
+#define _EFI_SOCKET_LIB_H_
+
+#include <Uefi.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include <Protocol/EfiSocket.h>
+#include <Protocol/ServiceBinding.h>
+#include <Protocol/Tcp4.h>
+#include <Protocol/Udp4.h>
+
+#include <sys/time.h>
+
+//------------------------------------------------------------------------------
+// Constants
+//------------------------------------------------------------------------------
+
+#define DEBUG_TPL 0x40000000 ///< Display TPL change messages
+
+#define TPL_SOCKETS TPL_CALLBACK ///< TPL for routine synchronization
+
+//------------------------------------------------------------------------------
+// Macros
+//------------------------------------------------------------------------------
+
+#if defined(_MSC_VER) /* Handle Microsoft VC++ compiler specifics. */
+#define DBG_ENTER() DEBUG (( DEBUG_INFO, "Entering " __FUNCTION__ "\n" )) ///< Display routine entry
+#define DBG_EXIT() DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ "\n" )) ///< Display routine exit
+#define DBG_EXIT_DEC(Status) DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ ", Status: %d\n", Status )) ///< Display routine exit with decimal value
+#define DBG_EXIT_HEX(Status) DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ ", Status: 0x%08x\n", Status )) ///< Display routine exit with hex value
+#define DBG_EXIT_STATUS(Status) DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ ", Status: %r\n", Status )) ///< Display routine exit with status value
+#define DBG_EXIT_TF(Status) DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ ", returning %s\n", (FALSE == Status) ? L"FALSE" : L"TRUE" )) ///< Display routine with TRUE/FALSE value
+#else // _MSC_VER
+#define DBG_ENTER()
+#define DBG_EXIT()
+#define DBG_EXIT_DEC(Status)
+#define DBG_EXIT_HEX(Status)
+#define DBG_EXIT_STATUS(Status)
+#define DBG_EXIT_TF(Status)
+#endif // _MSC_VER
+
+#define DIM(x) ( sizeof ( x ) / sizeof ( x[0] )) ///< Compute the number of entries in an array
+
+/**
+ Verify new TPL value
+
+ This macro which is enabled when debug is enabled verifies that
+ the new TPL value is >= the current TPL value.
+**/
+#ifdef VERIFY_TPL
+#undef VERIFY_TPL
+#endif // VERIFY_TPL
+
+#if !defined(MDEPKG_NDEBUG)
+
+#define VERIFY_TPL(tpl) \
+{ \
+ EFI_TPL PreviousTpl; \
+ \
+ PreviousTpl = gBS->RaiseTPL ( TPL_HIGH_LEVEL ); \
+ gBS->RestoreTPL ( PreviousTpl ); \
+ if ( PreviousTpl > tpl ) { \
+ DEBUG (( DEBUG_ERROR | DEBUG_TPL, \
+ "Current TPL: %d, New TPL: %d\r\n", \
+ PreviousTpl, tpl )); \
+ ASSERT ( PreviousTpl <= tpl ); \
+ } \
+}
+
+#else // MDEPKG_NDEBUG
+
+#define VERIFY_TPL(tpl)
+
+#endif // MDEPKG_NDEBUG
+
+#define RAISE_TPL(PreviousTpl, tpl) \
+ VERIFY_TPL ( tpl ); \
+ PreviousTpl = gBS->RaiseTPL ( tpl ); \
+ DEBUG (( DEBUG_TPL | DEBUG_TPL, \
+ "%d: TPL\r\n", \
+ tpl ))
+
+#define RESTORE_TPL(tpl) \
+ gBS->RestoreTPL ( tpl ); \
+ DEBUG (( DEBUG_TPL | DEBUG_TPL, \
+ "%d: TPL\r\n", \
+ tpl ))
+
+//------------------------------------------------------------------------------
+// Data Types
+//------------------------------------------------------------------------------
+
+typedef struct _DT_SERVICE DT_SERVICE; ///< Forward delcaration
+
+typedef
+EFI_STATUS
+(* PFN_SB_INITIALIZE) (
+ DT_SERVICE * pService
+ );
+
+typedef
+VOID
+(* PFN_SB_SHUTDOWN) (
+ DT_SERVICE * pService
+ );
+
+/**
+ Protocol binding and installation control structure
+
+ The driver uses this structure to simplify the driver binding processing.
+**/
+typedef struct {
+ CHAR16 * pName; ///< Protocol name
+ EFI_GUID * pNetworkBinding; ///< Network service binding protocol for socket support
+ CONST EFI_GUID * pTagGuid; ///< Tag to mark protocol in use
+ PFN_SB_INITIALIZE pfnInitialize;///< Routine to initialize the service
+ PFN_SB_SHUTDOWN pfnShutdown; ///< Routine to shutdown the service
+} DT_SOCKET_BINDING;
+
+//------------------------------------------------------------------------------
+// GUIDs
+//------------------------------------------------------------------------------
+
+extern CONST EFI_GUID mEslRawServiceGuid;
+extern CONST EFI_GUID mEslTcp4ServiceGuid;
+extern CONST EFI_GUID mEslUdp4ServiceGuid;
+
+//------------------------------------------------------------------------------
+// Data
+//------------------------------------------------------------------------------
+
+extern CONST DT_SOCKET_BINDING cEslSocketBinding [];
+extern CONST UINTN cEslSocketBindingEntries;
+
+//------------------------------------------------------------------------------
+// Service Support Routines
+//------------------------------------------------------------------------------
+
+/**
+ Connect to the network service bindings
+
+ Walk the network service protocols on the controller handle and
+ locate any that are not in use. Create service structures to
+ manage the service binding for the socket driver.
+
+ @param [in] BindingHandle Handle for protocol binding.
+ @param [in] Controller Handle of device to work with.
+
+ @retval EFI_SUCCESS This driver is added to Controller.
+ @retval other This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+EslServiceConnect (
+ IN EFI_HANDLE BindingHandle,
+ IN EFI_HANDLE Controller
+ );
+
+/**
+ Shutdown the network connections to this controller by removing
+ NetworkInterfaceIdentifier protocol and closing the DevicePath
+ and PciIo protocols on Controller.
+
+ @param [in] BindingHandle Handle for protocol binding.
+ @param [in] Controller Handle of device to stop driver on.
+
+ @retval EFI_SUCCESS This driver is removed Controller.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+ @retval other This driver was not removed from this device.
+
+**/
+EFI_STATUS
+EFIAPI
+EslServiceDisconnect (
+ IN EFI_HANDLE BindingHandle,
+ IN EFI_HANDLE Controller
+ );
+
+/**
+Install the socket service
+
+@param [in] pImageHandle Address of the image handle
+
+@retval EFI_SUCCESS Service installed successfully
+**/
+EFI_STATUS
+EFIAPI
+EslServiceInstall (
+ IN EFI_HANDLE * pImageHandle
+ );
+
+/**
+Initialize the service layer
+
+@param [in] ImageHandle Handle for the image.
+
+**/
+VOID
+EFIAPI
+EslServiceLoad (
+ IN EFI_HANDLE ImageHandle
+ );
+
+/**
+Uninstall the socket service
+
+@param [in] ImageHandle Handle for the image.
+
+@retval EFI_SUCCESS Service installed successfully
+**/
+EFI_STATUS
+EFIAPI
+EslServiceUninstall (
+ IN EFI_HANDLE ImageHandle
+ );
+
+/**
+ Shutdown the service layer
+
+**/
+VOID
+EFIAPI
+EslServiceUnload (
+ VOID
+ );
+
+//------------------------------------------------------------------------------
+// Socket Service Binding Protocol Routines
+//------------------------------------------------------------------------------
+
+/**
+ Creates a child handle and installs a protocol.
+
+ The CreateChild() function installs a protocol on ChildHandle.
+ If pChildHandle is a pointer to NULL, then a new handle is created and returned in pChildHandle.
+ If pChildHandle is not a pointer to NULL, then the protocol installs on the existing pChildHandle.
+
+ @param [in] pThis Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param [in] pChildHandle Pointer to the handle of the child to create. If it is NULL,
+ then a new handle is created. If it is a pointer to an existing UEFI handle,
+ then the protocol is added to the existing UEFI handle.
+
+ @retval EFI_SUCCES The protocol was added to ChildHandle.
+ @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
+ the child
+ @retval other The child handle was not created
+
+**/
+EFI_STATUS
+EFIAPI
+EslSocketCreateChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL * pThis,
+ IN OUT EFI_HANDLE * pChildHandle
+ );
+
+/**
+ Destroys a child handle with a protocol installed on it.
+
+ The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
+ that was installed by CreateChild() from ChildHandle. If the removed protocol is the
+ last protocol on ChildHandle, then ChildHandle is destroyed.
+
+ @param [in] pThis Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param [in] ChildHandle Handle of the child to destroy
+
+ @retval EFI_SUCCES The protocol was removed from ChildHandle.
+ @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
+ @retval EFI_INVALID_PARAMETER Child handle is not a valid UEFI Handle.
+ @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
+ because its services are being used.
+ @retval other The child handle was not destroyed
+
+**/
+EFI_STATUS
+EFIAPI
+EslSocketDestroyChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL * pThis,
+ IN EFI_HANDLE ChildHandle
+ );
+
+//------------------------------------------------------------------------------
+// Socket Protocol Routines
+//------------------------------------------------------------------------------
+
+/**
+ Bind a name to a socket.
+
+ The ::SocketBind routine connects a name to a socket on the local machine. The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html">POSIX</a>
+ documentation for the bind routine is available online for reference.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [in] pSockAddr Address of a sockaddr structure that contains the
+ connection point on the local machine. An IPv4 address
+ of INADDR_ANY specifies that the connection is made to
+ all of the network stacks on the platform. Specifying a
+ specific IPv4 address restricts the connection to the
+ network stack supporting that address. Specifying zero
+ for the port causes the network layer to assign a port
+ number from the dynamic range. Specifying a specific
+ port number causes the network layer to use that port.
+
+ @param [in] SockAddrLen Specifies the length in bytes of the sockaddr structure.
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket successfully created
+
+ **/
+EFI_STATUS
+EslSocketBind (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN const struct sockaddr * pSockAddr,
+ IN socklen_t SockAddrLength,
+ OUT int * pErrno
+ );
+
+/**
+ Determine if the socket is closed
+
+ Reverses the operations of the ::SocketAllocate() routine.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS Socket successfully closed
+ @retval EFI_NOT_READY Close still in progress
+ @retval EFI_ALREADY Close operation already in progress
+ @retval Other Failed to close the socket
+
+**/
+EFI_STATUS
+EslSocketClosePoll (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN int * pErrno
+ );
+
+/**
+ Start the close operation on the socket
+
+ Start closing the socket by closing all of the ports. Upon
+ completion, the ::SocketPoll() routine finishes closing the
+ socket.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+ @param [in] bCloseNow Boolean to control close behavior
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS Socket successfully closed
+ @retval EFI_NOT_READY Close still in progress
+ @retval EFI_ALREADY Close operation already in progress
+ @retval Other Failed to close the socket
+
+**/
+EFI_STATUS
+EslSocketCloseStart (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN BOOLEAN bCloseNow,
+ IN int * pErrno
+ );
+
+/**
+ Connect to a remote system via the network.
+
+ The ::SocketConnect routine attempts to establish a connection to a
+ socket on the local or remote system using the specified address.
+ The POSIX
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html">connect</a>
+ documentation is available online.
+
+ There are three states associated with a connection:
+ <ul>
+ <li>Not connected</li>
+ <li>Connection in progress</li>
+ <li>Connected</li>
+ </ul>
+ In the "Not connected" state, calls to ::connect start the connection
+ processing and update the state to "Connection in progress". During
+ the "Connection in progress" state, connect polls for connection completion
+ and moves the state to "Connected" after the connection is established.
+ Note that these states are only visible when the file descriptor is marked
+ with O_NONBLOCK. Also, the POLL_WRITE bit is set when the connection
+ completes and may be used by poll or select as an indicator to call
+ connect again.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [in] pSockAddr Network address of the remote system.
+
+ @param [in] SockAddrLength Length in bytes of the network address.
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS The connection was successfully established.
+ @retval EFI_NOT_READY The connection is in progress, call this routine again.
+ @retval Others The connection attempt failed.
+
+ **/
+EFI_STATUS
+EslSocketConnect (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN const struct sockaddr * pSockAddr,
+ IN socklen_t SockAddrLength,
+ IN int * pErrno
+ );
+
+/**
+ Get the local address.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [out] pAddress Network address to receive the local system address
+
+ @param [in,out] pAddressLength Length of the local network address structure
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Local address successfully returned
+
+ **/
+EFI_STATUS
+EslSocketGetLocalAddress (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ OUT struct sockaddr * pAddress,
+ IN OUT socklen_t * pAddressLength,
+ IN int * pErrno
+ );
+
+/**
+ Get the peer address.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [out] pAddress Network address to receive the remote system address
+
+ @param [in,out] pAddressLength Length of the remote network address structure
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Remote address successfully returned
+
+ **/
+EFI_STATUS
+EslSocketGetPeerAddress (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ OUT struct sockaddr * pAddress,
+ IN OUT socklen_t * pAddressLength,
+ IN int * pErrno
+ );
+
+/**
+ Establish the known port to listen for network connections.
+
+ The ::SocketListen routine places the port into a state that enables connection
+ attempts. Connections are placed into FIFO order in a queue to be serviced
+ by the application. The application calls the ::SocketAccept routine to remove
+ the next connection from the queue and get the associated socket. The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html">POSIX</a>
+ documentation for the bind routine is available online for reference.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [in] Backlog Backlog specifies the maximum FIFO depth for
+ the connections waiting for the application
+ to call accept. Connection attempts received
+ while the queue is full are refused.
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket successfully created
+ @retval Other - Failed to enable the socket for listen
+
+**/
+EFI_STATUS
+EslSocketListen (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN INT32 Backlog,
+ OUT int * pErrno
+ );
+
+/**
+ Get the socket options
+
+ Retrieve the socket options one at a time by name. The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html">POSIX</a>
+ documentation is available online.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+ @param [in] level Option protocol level
+ @param [in] option_name Name of the option
+ @param [out] option_value Buffer to receive the option value
+ @param [in,out] option_len Length of the buffer in bytes,
+ upon return length of the option value in bytes
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket data successfully received
+
+ **/
+EFI_STATUS
+EslSocketOptionGet (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN int level,
+ IN int option_name,
+ OUT void * __restrict option_value,
+ IN OUT socklen_t * __restrict option_len,
+ IN int * pErrno
+ );
+
+/**
+ Set the socket options
+
+ Adjust the socket options one at a time by name. The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html">POSIX</a>
+ documentation is available online.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+ @param [in] level Option protocol level
+ @param [in] option_name Name of the option
+ @param [in] option_value Buffer containing the option value
+ @param [in] option_len Length of the buffer in bytes
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket data successfully received
+
+ **/
+EFI_STATUS
+EslSocketOptionSet (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN int level,
+ IN int option_name,
+ IN CONST void * option_value,
+ IN socklen_t option_len,
+ IN int * pErrno
+ );
+
+/**
+ Poll a socket for pending activity.
+
+ The SocketPoll routine checks a socket for pending activity associated
+ with the event mask. Activity is returned in the detected event buffer.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [in] Events Events of interest for this socket
+
+ @param [in] pEvents Address to receive the detected events
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket successfully polled
+ @retval EFI_INVALID_PARAMETER - When pEvents is NULL
+
+ **/
+EFI_STATUS
+EslSocketPoll (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN short Events,
+ IN short * pEvents,
+ IN int * pErrno
+ );
+
+/**
+ Receive data from a network connection.
+
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [in] Flags Message control flags
+
+ @param [in] BufferLength Length of the the buffer
+
+ @param [in] pBuffer Address of a buffer to receive the data.
+
+ @param [in] pDataLength Number of received data bytes in the buffer.
+
+ @param [out] pAddress Network address to receive the remote system address
+
+ @param [in,out] pAddressLength Length of the remote network address structure
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket data successfully received
+
+ **/
+EFI_STATUS
+EslSocketReceive (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN INT32 Flags,
+ IN size_t BufferLength,
+ IN UINT8 * pBuffer,
+ OUT size_t * pDataLength,
+ OUT struct sockaddr * pAddress,
+ IN OUT socklen_t * pAddressLength,
+ IN int * pErrno
+ );
+
+/**
+ Shutdown the socket receive and transmit operations
+
+ The SocketShutdown routine stops the socket receive and transmit
+ operations.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [in] How Which operations to stop
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket operations successfully shutdown
+
+ **/
+EFI_STATUS
+EslSocketShutdown (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN int How,
+ IN int * pErrno
+ );
+
+/**
+ Send data using a network connection.
+
+ The SocketTransmit routine queues the data for transmission to the
+ remote network connection.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [in] Flags Message control flags
+
+ @param [in] BufferLength Length of the the buffer
+
+ @param [in] pBuffer Address of a buffer containing the data to send
+
+ @param [in] pDataLength Address to receive the number of data bytes sent
+
+ @param [in] pAddress Network address of the remote system address
+
+ @param [in] AddressLength Length of the remote network address structure
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket data successfully received
+
+ **/
+EFI_STATUS
+EslSocketTransmit (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN int Flags,
+ IN size_t BufferLength,
+ IN CONST UINT8 * pBuffer,
+ OUT size_t * pDataLength,
+ IN const struct sockaddr * pAddress,
+ IN socklen_t AddressLength,
+ IN int * pErrno
+ );
+
+//------------------------------------------------------------------------------
+
+#endif // _EFI_SOCKET_LIB_H_
diff --git a/StdLib/Include/Ia32/machine/limits.h b/StdLib/Include/Ia32/machine/limits.h index 62fbe40b42..0b3cfbe4c5 100644 --- a/StdLib/Include/Ia32/machine/limits.h +++ b/StdLib/Include/Ia32/machine/limits.h @@ -1,3 +1,14 @@ #include <x86/limits.h>
#define __POINTER_BIT 32
+#define __LONG_BIT 32
+
+/** minimum value for an object of type long int **/
+#define __LONG_MIN (-2147483647L - 1L) // -(2^31 - 1)
+
+/** maximum value for an object of type long int **/
+#define __LONG_MAX +2147483647L // 2^31 - 1
+
+/** maximum value for an object of type unsigned long int **/
+#define __ULONG_MAX 0xffffffff // 2^32 - 1
+
diff --git a/StdLib/Include/Protocol/EfiSocket.h b/StdLib/Include/Protocol/EfiSocket.h new file mode 100644 index 0000000000..5e044fac9e --- /dev/null +++ b/StdLib/Include/Protocol/EfiSocket.h @@ -0,0 +1,606 @@ +/** @file
+ Definitions for the EFI Socket protocol.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EFI_SOCKET_H_
+#define _EFI_SOCKET_H_
+
+#include <errno.h>
+#include <Uefi.h>
+
+#include <netinet/in.h>
+
+#include <sys/poll.h>
+#include <sys/socket.h>
+
+//------------------------------------------------------------------------------
+// Data Types
+//------------------------------------------------------------------------------
+
+typedef struct _EFI_SOCKET_PROTOCOL EFI_SOCKET_PROTOCOL;
+
+/**
+ Constructor/Destructor
+
+ @retval EFI_SUCCESS The operation was successful
+
+ **/
+typedef
+EFI_STATUS
+(* PFN_ESL_xSTRUCTOR) (
+ VOID
+ );
+
+//------------------------------------------------------------------------------
+// Data
+//------------------------------------------------------------------------------
+
+extern PFN_ESL_xSTRUCTOR mpfnEslConstructor;
+extern PFN_ESL_xSTRUCTOR mpfnEslDestructor;
+
+extern EFI_GUID gEfiSocketProtocolGuid;
+extern EFI_GUID gEfiSocketServiceBindingProtocolGuid;
+
+//------------------------------------------------------------------------------
+// Socket API
+//------------------------------------------------------------------------------
+
+/**
+ Accept a network connection.
+
+ The SocketAccept routine waits for a network connection to the socket.
+ It is able to return the remote network address to the caller if
+ requested.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [in] pSockAddr Address of a buffer to receive the remote
+ network address.
+
+ @param [in, out] pSockAddrLength Length in bytes of the address buffer.
+ On output specifies the length of the
+ remote network address.
+
+ @param [out] ppSocketProtocol Address of a buffer to receive the socket protocol
+ instance associated with the new socket.
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS New connection successfully created
+ @retval EFI_NOT_READY No connection is available
+
+ **/
+typedef
+EFI_STATUS
+(* PFN_ACCEPT) (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN struct sockaddr * pSockAddr,
+ IN OUT socklen_t * pSockAddrLength,
+ IN EFI_SOCKET_PROTOCOL ** ppSocketProtocol,
+ IN int * pErrno
+ );
+
+/**
+ Bind a name to a socket.
+
+ The ::SocketBind routine connects a name to a socket on the local machine. The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html">POSIX</a>
+ documentation for the bind routine is available online for reference.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [in] pSockAddr Address of a sockaddr structure that contains the
+ connection point on the local machine. An IPv4 address
+ of INADDR_ANY specifies that the connection is made to
+ all of the network stacks on the platform. Specifying a
+ specific IPv4 address restricts the connection to the
+ network stack supporting that address. Specifying zero
+ for the port causes the network layer to assign a port
+ number from the dynamic range. Specifying a specific
+ port number causes the network layer to use that port.
+
+ @param [in] SockAddrLen Specifies the length in bytes of the sockaddr structure.
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket successfully created
+
+ **/
+typedef
+EFI_STATUS
+(* PFN_BIND) (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN const struct sockaddr * pSockAddr,
+ IN socklen_t SockAddrLength,
+ OUT int * pErrno
+ );
+
+/**
+ Determine if the socket is closed
+
+ Reverses the operations of the ::SocketAllocate() routine.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS Socket successfully closed
+ @retval EFI_NOT_READY Close still in progress
+ @retval EFI_ALREADY Close operation already in progress
+ @retval Other Failed to close the socket
+
+**/
+typedef
+EFI_STATUS
+(* PFN_CLOSE_POLL) (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN int * pErrno
+ );
+
+/**
+ Start the close operation on the socket
+
+ Start closing the socket by closing all of the ports. Upon
+ completion, the ::pfnClosePoll() routine finishes closing the
+ socket.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+ @param [in] bCloseNow Boolean to control close behavior
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS Socket successfully closed
+ @retval EFI_NOT_READY Close still in progress
+ @retval EFI_ALREADY Close operation already in progress
+ @retval Other Failed to close the socket
+
+**/
+typedef
+EFI_STATUS
+(* PFN_CLOSE_START) (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN BOOLEAN bCloseNow,
+ IN int * pErrno
+ );
+
+/**
+ Connect to a remote system via the network.
+
+ The ::Connect routine attempts to establish a connection to a
+ socket on the local or remote system using the specified address.
+ The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html">POSIX</a>
+ documentation is available online.
+
+ There are three states associated with a connection:
+ <ul>
+ <li>Not connected</li>
+ <li>Connection in progress</li>
+ <li>Connected</li>
+ </ul>
+ In the "Not connected" state, calls to ::connect start the connection
+ processing and update the state to "Connection in progress". During
+ the "Connection in progress" state, connect polls for connection completion
+ and moves the state to "Connected" after the connection is established.
+ Note that these states are only visible when the file descriptor is marked
+ with O_NONBLOCK. Also, the POLL_WRITE bit is set when the connection
+ completes and may be used by poll or select as an indicator to call
+ connect again.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [in] pSockAddr Network address of the remote system.
+
+ @param [in] SockAddrLength Length in bytes of the network address.
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS The connection was successfully established.
+ @retval EFI_NOT_READY The connection is in progress, call this routine again.
+ @retval Others The connection attempt failed.
+
+ **/
+typedef
+EFI_STATUS
+(* PFN_CONNECT) (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN const struct sockaddr * pSockAddr,
+ IN socklen_t SockAddrLength,
+ IN int * pErrno
+ );
+
+/**
+ Get the local address.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [out] pAddress Network address to receive the local system address
+
+ @param [in,out] pAddressLength Length of the local network address structure
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Local address successfully returned
+
+ **/
+typedef
+EFI_STATUS
+(* PFN_GET_LOCAL) (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ OUT struct sockaddr * pAddress,
+ IN OUT socklen_t * pAddressLength,
+ IN int * pErrno
+ );
+
+/**
+ Get the peer address.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [out] pAddress Network address to receive the remote system address
+
+ @param [in,out] pAddressLength Length of the remote network address structure
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Remote address successfully returned
+
+ **/
+typedef
+EFI_STATUS
+(* PFN_GET_PEER) (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ OUT struct sockaddr * pAddress,
+ IN OUT socklen_t * pAddressLength,
+ IN int * pErrno
+ );
+
+/**
+ Establish the known port to listen for network connections.
+
+ The ::SocketAisten routine places the port into a state that enables connection
+ attempts. Connections are placed into FIFO order in a queue to be serviced
+ by the application. The application calls the ::SocketAccept routine to remove
+ the next connection from the queue and get the associated socket. The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html">POSIX</a>
+ documentation for the bind routine is available online for reference.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [in] Backlog Backlog specifies the maximum FIFO depth for
+ the connections waiting for the application
+ to call accept. Connection attempts received
+ while the queue is full are refused.
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket successfully created
+ @retval Other - Failed to enable the socket for listen
+
+**/
+typedef
+EFI_STATUS
+(* PFN_LISTEN) (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN INT32 Backlog,
+ OUT int * pErrno
+ );
+
+/**
+ Get the socket options
+
+ Retrieve the socket options one at a time by name. The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html">POSIX</a>
+ documentation is available online.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+ @param [in] level Option protocol level
+ @param [in] OptionName Name of the option
+ @param [out] pOptionValue Buffer to receive the option value
+ @param [in,out] pOptionLength Length of the buffer in bytes,
+ upon return length of the option value in bytes
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket data successfully received
+
+ **/
+typedef
+EFI_STATUS
+(* PFN_OPTION_GET) (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN int level,
+ IN int OptionName,
+ OUT void * __restrict pOptionValue,
+ IN OUT socklen_t * __restrict pOptionLength,
+ IN int * pErrno
+ );
+
+/**
+ Set the socket options
+
+ Adjust the socket options one at a time by name. The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html">POSIX</a>
+ documentation is available online.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+ @param [in] level Option protocol level
+ @param [in] OptionName Name of the option
+ @param [in] pOptionValue Buffer containing the option value
+ @param [in] OptionLength Length of the buffer in bytes
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket data successfully received
+
+ **/
+typedef
+EFI_STATUS
+(* PFN_OPTION_SET) (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN int level,
+ IN int OptionName,
+ IN CONST void * pOptionValue,
+ IN socklen_t OptionLength,
+ IN int * pErrno
+ );
+
+/**
+ Poll a socket for pending activity.
+
+ The SocketPoll routine checks a socket for pending activity associated
+ with the event mask. Activity is returned in the detected event buffer.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [in] Events Events of interest for this socket
+
+ @param [in] pEvents Address to receive the detected events
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket successfully polled
+ @retval EFI_INVALID_PARAMETER - When pEvents is NULL
+
+ **/
+typedef
+EFI_STATUS
+(* PFN_POLL) (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN short Events,
+ IN short * pEvents,
+ IN int * pErrno
+ );
+
+/**
+ Receive data from a network connection.
+
+ The ::recv routine waits for receive data from a remote network
+ connection. The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html">POSIX</a>
+ documentation is available online.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [in] Flags Message control flags
+
+ @param [in] BufferLength Length of the the buffer
+
+ @param [in] pBuffer Address of a buffer to receive the data.
+
+ @param [in] pDataLength Number of received data bytes in the buffer.
+
+ @param [out] pAddress Network address to receive the remote system address
+
+ @param [in,out] pAddressLength Length of the remote network address structure
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket data successfully received
+
+ **/
+typedef
+EFI_STATUS
+(* PFN_RECEIVE) (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN int Flags,
+ IN size_t BufferLength,
+ IN UINT8 * pBuffer,
+ OUT size_t * pDataLength,
+ OUT struct sockaddr * pAddress,
+ IN OUT socklen_t * pAddressLength,
+ IN int * pErrno
+ );
+
+/**
+ Send data using a network connection.
+
+ The SocketTransmit routine queues the data for transmission to the
+ remote network connection.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [in] Flags Message control flags
+
+ @param [in] BufferLength Length of the the buffer
+
+ @param [in] pBuffer Address of a buffer containing the data to send
+
+ @param [in] pDataLength Address to receive the number of data bytes sent
+
+ @param [in] pAddress Network address of the remote system address
+
+ @param [in] AddressLength Length of the remote network address structure
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket data successfully queued for transmission
+
+ **/
+typedef
+EFI_STATUS
+(* PFN_SEND) (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN int Flags,
+ IN size_t BufferLength,
+ IN CONST UINT8 * pBuffer,
+ OUT size_t * pDataLength,
+ IN const struct sockaddr * pAddress,
+ IN socklen_t AddressLength,
+ IN int * pErrno
+ );
+
+/**
+ Shutdown the socket receive and transmit operations
+
+ The SocketShutdown routine stops the socket receive and transmit
+ operations.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [in] How Which operations to stop
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket operations successfully shutdown
+
+ **/
+typedef
+EFI_STATUS
+(* PFN_SHUTDOWN) (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN int How,
+ IN int * pErrno
+ );
+
+/**
+ Initialize an endpoint for network communication.
+
+ The ::Socket routine initializes the communication endpoint by providing
+ the support for the socket library function ::socket. The
+ <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html">POSIX</a>
+ documentation for the socket routine is available online for reference.
+
+ @param [in] pSocketProtocol Address of the socket protocol structure.
+
+ @param [in] domain Select the family of protocols for the client or server
+ application.
+
+ @param [in] type Specifies how to make the network connection. The following values
+ are supported:
+ <ul>
+ <li>
+ SOCK_STREAM - Connect to TCP, provides a byte stream
+ that is manipluated by read, recv, send and write.
+ </li>
+ <li>
+ SOCK_SEQPACKET - Connect to TCP, provides sequenced packet stream
+ that is manipulated by read, recv, send and write.
+ </li>
+ <li>
+ SOCK_DGRAM - Connect to UDP, provides a datagram service that is
+ manipulated by recvfrom and sendto.
+ </li>
+ </ul>
+
+ @param [in] protocol Specifies the lower layer protocol to use. The following
+ values are supported:
+ <ul>
+ <li>IPPROTO_TCP</li> - This value must be combined with SOCK_STREAM.</li>
+ <li>IPPROTO_UDP</li> - This value must be combined with SOCK_DGRAM.</li>
+ </ul>
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS - Socket successfully created
+ @retval EFI_INVALID_PARAMETER - Invalid domain value, errno = EAFNOSUPPORT
+ @retval EFI_INVALID_PARAMETER - Invalid type value, errno = EINVAL
+ @retval EFI_INVALID_PARAMETER - Invalid protocol value, errno = EINVAL
+
+ **/
+typedef
+EFI_STATUS
+(*PFN_SOCKET) (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN int domain,
+ IN int type,
+ IN int protocol,
+ IN int * pErrno
+ );
+
+//------------------------------------------------------------------------------
+// Socket Protocol
+//------------------------------------------------------------------------------
+
+/**
+ Socket protocol declaration
+**/
+typedef struct _EFI_SOCKET_PROTOCOL {
+ EFI_HANDLE SocketHandle; ///< Handle for the socket
+ PFN_ACCEPT pfnAccept; ///< Accept a network connection
+ PFN_BIND pfnBind; ///< Bind a local address to the socket
+ PFN_CLOSE_POLL pfnClosePoll; ///< Determine if the socket is closed
+ PFN_CLOSE_START pfnCloseStart; ///< Start the close operation
+ PFN_CONNECT pfnConnect; ///< Connect to a remote system
+ PFN_GET_LOCAL pfnGetLocal; ///< Get local address
+ PFN_GET_PEER pfnGetPeer; ///< Get peer address
+ PFN_LISTEN pfnListen; ///< Enable connection attempts on known port
+ PFN_POLL pfnPoll; ///< Poll for socket activity
+ PFN_OPTION_GET pfnOptionGet; ///< Get socket options
+ PFN_OPTION_SET pfnOptionSet; ///< Set socket options
+ PFN_RECEIVE pfnReceive; ///< Receive data from a socket
+ PFN_SEND pfnSend; ///< Transmit data using the socket
+ PFN_SHUTDOWN pfnShutdown; ///< Shutdown receive and transmit operations
+ PFN_SOCKET pfnSocket; ///< Initialize the socket
+} GCC_EFI_SOCKET_PROTOCOL;
+
+//------------------------------------------------------------------------------
+// Non-blocking routines
+//------------------------------------------------------------------------------
+
+/**
+ Non blocking version of accept.
+
+ See ::accept
+
+ @param [in] s Socket file descriptor returned from ::socket.
+
+ @param [in] address Address of a buffer to receive the remote network address.
+
+ @param [in, out] address_len Address of a buffer containing the Length in bytes
+ of the remote network address buffer. Upon return,
+ contains the length of the remote network address.
+
+ @returns This routine returns zero if successful and -1 when an error occurs.
+ In the case of an error, errno contains more details.
+
+ **/
+int
+AcceptNB (
+ int s,
+ struct sockaddr * address,
+ socklen_t * address_len
+ );
+
+/**
+ Connect to the socket driver
+
+ @param [in] ppSocketProtocol Address to receive the socket protocol address
+
+ @retval 0 Successfully returned the socket protocol
+ @retval other Value for errno
+ **/
+int
+EslServiceGetProtocol (
+ IN EFI_SOCKET_PROTOCOL ** ppSocketProtocol
+ );
+
+//------------------------------------------------------------------------------
+
+#endif // _EFI_SOCKET_H_
diff --git a/StdLib/Include/X64/machine/limits.h b/StdLib/Include/X64/machine/limits.h index 663b2e3290..d046c64dab 100644 --- a/StdLib/Include/X64/machine/limits.h +++ b/StdLib/Include/X64/machine/limits.h @@ -1,3 +1,25 @@ #include <x86/limits.h>
#define __POINTER_BIT 64
+
+#if defined(__GNUC__)
+#define __LONG_BIT 64
+/** minimum value for an object of type long int **/
+#define __LONG_MIN (-9223372036854775807L - 1L) // -(2^63 - 1)
+
+/** maximum value for an object of type long int **/
+#define __LONG_MAX +9223372036854775807L // 2^63 - 1
+
+/** maximum value for an object of type unsigned long int **/
+#define __ULONG_MAX 0xFFFFFFFFFFFFFFFFUL // 2^64 - 1
+#else
+#define __LONG_BIT 32
+/** minimum value for an object of type long int **/
+#define __LONG_MIN (-2147483647L - 1L) // -(2^31 - 1)
+
+/** maximum value for an object of type long int **/
+#define __LONG_MAX +2147483647L // 2^31 - 1
+
+/** maximum value for an object of type unsigned long int **/
+#define __ULONG_MAX 0xffffffff // 2^32 - 1
+#endif
diff --git a/StdLib/Include/arpa/ftp.h b/StdLib/Include/arpa/ftp.h new file mode 100644 index 0000000000..3cb509daea --- /dev/null +++ b/StdLib/Include/arpa/ftp.h @@ -0,0 +1,109 @@ +/*
+ * Copyright (c) 1983, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ftp.h 8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _ARPA_FTP_H_
+#define _ARPA_FTP_H_
+
+/* Definitions for FTP; see RFC-765. */
+
+/*
+ * Reply codes.
+ */
+#define PRELIM 1 /* positive preliminary */
+#define COMPLETE 2 /* positive completion */
+#define CONTINUE 3 /* positive intermediate */
+#define TRANSIENT 4 /* transient negative completion */
+#define ERROR 5 /* permanent negative completion */
+
+/*
+ * Type codes
+ */
+#define TYPE_A 1 /* ASCII */
+#define TYPE_E 2 /* EBCDIC */
+#define TYPE_I 3 /* image */
+#define TYPE_L 4 /* local byte size */
+
+#ifdef FTP_NAMES
+char *typenames[] = {"0", "ASCII", "EBCDIC", "Image", "Local" };
+#endif
+
+/*
+ * Form codes
+ */
+#define FORM_N 1 /* non-print */
+#define FORM_T 2 /* telnet format effectors */
+#define FORM_C 3 /* carriage control (ASA) */
+#ifdef FTP_NAMES
+char *formnames[] = {"0", "Nonprint", "Telnet", "Carriage-control" };
+#endif
+
+/*
+ * Structure codes
+ */
+#define STRU_F 1 /* file (no record structure) */
+#define STRU_R 2 /* record structure */
+#define STRU_P 3 /* page structure */
+#ifdef FTP_NAMES
+char *strunames[] = {"0", "File", "Record", "Page" };
+#endif
+
+/*
+ * Mode types
+ */
+#define MODE_S 1 /* stream */
+#define MODE_B 2 /* block */
+#define MODE_C 3 /* compressed */
+#ifdef FTP_NAMES
+char *modenames[] = {"0", "Stream", "Block", "Compressed" };
+#endif
+
+/*
+ * Record Tokens
+ */
+#define REC_ESC '\377' /* Record-mode Escape */
+#define REC_EOR '\001' /* Record-mode End-of-Record */
+#define REC_EOF '\002' /* Record-mode End-of-File */
+
+/*
+ * Block Header
+ */
+#define BLK_EOR 0x80 /* Block is End-of-Record */
+#define BLK_EOF 0x40 /* Block is End-of-File */
+#define BLK_ERRORS 0x20 /* Block is suspected of containing errors */
+#define BLK_RESTART 0x10 /* Block is Restart Marker */
+
+#define BLK_BYTECOUNT 2 /* Bytes in this block */
+
+#endif /* !_FTP_H_ */
diff --git a/StdLib/Include/arpa/nameser.h b/StdLib/Include/arpa/nameser.h index c4db9efc86..8f8a840f5b 100644 --- a/StdLib/Include/arpa/nameser.h +++ b/StdLib/Include/arpa/nameser.h @@ -126,6 +126,10 @@ struct _ns_flagdata { int mask, shift; }; extern struct _ns_flagdata _ns_flagdata[];
/* Accessor macros - this is part of the public interface. */
+#define ns_msg_getflag(handle, flag) ( \
+ ((handle)._flags & _ns_flagdata[flag].mask) \
+ >> _ns_flagdata[flag].shift \
+ )
#define ns_msg_id(handle) ((handle)._id + 0)
#define ns_msg_base(handle) ((handle)._msg + 0)
@@ -217,6 +221,28 @@ typedef enum __ns_update_operation { ns_uop_max = 2
} ns_update_operation;
+/*
+ * This RR-like structure is particular to UPDATE.
+ */
+struct _ns_updrec {
+ struct _ns_updrec *r_prev; /* prev record */
+ struct _ns_updrec *r_next; /* next record */
+ u_int8_t r_section; /* ZONE/PREREQUISITE/UPDATE */
+ char * r_dname; /* owner of the RR */
+ u_int16_t r_class; /* class number */
+ u_int16_t r_type; /* type number */
+ u_int32_t r_ttl; /* time to live */
+ u_char * r_data; /* rdata fields as text string */
+ u_int16_t r_size; /* size of r_data field */
+ int r_opcode; /* type of operation */
+ /* following fields for private use by the resolver/server routines */
+ struct _ns_updrec *r_grpnext; /* next record when grouped */
+ struct databuf *r_dp; /* databuf to process */
+ struct databuf *r_deldp; /* databuf's deleted/overwritten */
+ u_int16_t r_zone; /* zone number on server */
+};
+typedef struct _ns_updrec ns_updrec;
+
/*%
* This structure is used for TSIG authenticated messages
*/
@@ -456,25 +482,24 @@ typedef enum __ns_cert_types { #define NS_PUT16(s, cp) do { \
uint32_t t_s = (uint32_t)(s); \
u_char *t_cp = (u_char *)(cp); \
- *t_cp++ = t_s >> 8; \
- *t_cp = t_s; \
+ *t_cp++ = (u_char)( t_s >> 8 ); \
+ *t_cp = (u_char)( t_s ); \
(cp) += NS_INT16SZ; \
} while (/*CONSTCOND*/0)
#define NS_PUT32(l, cp) do { \
uint32_t t_l = (uint32_t)(l); \
u_char *t_cp = (u_char *)(cp); \
- *t_cp++ = t_l >> 24; \
- *t_cp++ = t_l >> 16; \
- *t_cp++ = t_l >> 8; \
- *t_cp = t_l; \
+ *t_cp++ = (u_char)( t_l >> 24 ); \
+ *t_cp++ = (u_char)( t_l >> 16 ); \
+ *t_cp++ = (u_char)( t_l >> 8 ); \
+ *t_cp = (u_char)( t_l ); \
(cp) += NS_INT32SZ; \
} while (/*CONSTCOND*/0)
/*%
* ANSI C identifier hiding for bind's lib/nameser.
*/
-#define ns_msg_getflag __ns_msg_getflag
#define ns_get16 __ns_get16
#define ns_get32 __ns_get32
#define ns_put16 __ns_put16
@@ -511,7 +536,6 @@ typedef enum __ns_cert_types { #define ns_samename __ns_samename
__BEGIN_DECLS
-int ns_msg_getflag(ns_msg, int);
uint16_t ns_get16(const u_char *);
uint32_t ns_get32(const u_char *);
void ns_put16(uint16_t, u_char *);
diff --git a/StdLib/Include/arpa/telnet.h b/StdLib/Include/arpa/telnet.h new file mode 100644 index 0000000000..d7c8ecbd57 --- /dev/null +++ b/StdLib/Include/arpa/telnet.h @@ -0,0 +1,340 @@ +/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)telnet.h 8.2 (Berkeley) 12/15/93
+ */
+
+#ifndef _ARPA_TELNET_H_
+#define _ARPA_TELNET_H_
+
+/*
+ * Definitions for the TELNET protocol.
+ */
+#define IAC 255 /* interpret as command: */
+#define DONT 254 /* you are not to use option */
+#define DO 253 /* please, you use option */
+#define WONT 252 /* I won't use option */
+#define WILL 251 /* I will use option */
+#define SB 250 /* interpret as subnegotiation */
+#define GA 249 /* you may reverse the line */
+#define EL 248 /* erase the current line */
+#define EC 247 /* erase the current character */
+#define AYT 246 /* are you there */
+#define AO 245 /* abort output--but let prog finish */
+#define IP 244 /* interrupt process--permanently */
+#define BREAK 243 /* break */
+#define DM 242 /* data mark--for connect. cleaning */
+#define NOP 241 /* nop */
+#define SE 240 /* end sub negotiation */
+#define EOR 239 /* end of record (transparent mode) */
+#define ABORT 238 /* Abort process */
+#define SUSP 237 /* Suspend process */
+#define xEOF 236 /* End of file: EOF is already used... */
+
+#define SYNCH 242 /* for telfunc calls */
+
+#ifdef TELCMDS
+char *telcmds[] = {
+ "EOF", "SUSP", "ABORT", "EOR",
+ "SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC",
+ "EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC",
+ 0
+};
+#else
+extern char *telcmds[];
+#endif
+
+#define TELCMD_FIRST xEOF
+#define TELCMD_LAST IAC
+#define TELCMD_OK(x) ((unsigned int)(x) <= TELCMD_LAST && \
+ (unsigned int)(x) >= TELCMD_FIRST)
+#define TELCMD(x) telcmds[(x)-TELCMD_FIRST]
+
+/* telnet options */
+#define TELOPT_BINARY 0 /* 8-bit data path */
+#define TELOPT_ECHO 1 /* echo */
+#define TELOPT_RCP 2 /* prepare to reconnect */
+#define TELOPT_SGA 3 /* suppress go ahead */
+#define TELOPT_NAMS 4 /* approximate message size */
+#define TELOPT_STATUS 5 /* give status */
+#define TELOPT_TM 6 /* timing mark */
+#define TELOPT_RCTE 7 /* remote controlled transmission and echo */
+#define TELOPT_NAOL 8 /* negotiate about output line width */
+#define TELOPT_NAOP 9 /* negotiate about output page size */
+#define TELOPT_NAOCRD 10 /* negotiate about CR disposition */
+#define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */
+#define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */
+#define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */
+#define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */
+#define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */
+#define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */
+#define TELOPT_XASCII 17 /* extended ascic character set */
+#define TELOPT_LOGOUT 18 /* force logout */
+#define TELOPT_BM 19 /* byte macro */
+#define TELOPT_DET 20 /* data entry terminal */
+#define TELOPT_SUPDUP 21 /* supdup protocol */
+#define TELOPT_SUPDUPOUTPUT 22 /* supdup output */
+#define TELOPT_SNDLOC 23 /* send location */
+#define TELOPT_TTYPE 24 /* terminal type */
+#define TELOPT_EOR 25 /* end or record */
+#define TELOPT_TUID 26 /* TACACS user identification */
+#define TELOPT_OUTMRK 27 /* output marking */
+#define TELOPT_TTYLOC 28 /* terminal location number */
+#define TELOPT_3270REGIME 29 /* 3270 regime */
+#define TELOPT_X3PAD 30 /* X.3 PAD */
+#define TELOPT_NAWS 31 /* window size */
+#define TELOPT_TSPEED 32 /* terminal speed */
+#define TELOPT_LFLOW 33 /* remote flow control */
+#define TELOPT_LINEMODE 34 /* Linemode option */
+#define TELOPT_XDISPLOC 35 /* X Display Location */
+#define TELOPT_OLD_ENVIRON 36 /* Old - Environment variables */
+#define TELOPT_AUTHENTICATION 37/* Authenticate */
+#define TELOPT_ENCRYPT 38 /* Encryption option */
+#define TELOPT_NEW_ENVIRON 39 /* New - Environment variables */
+#define TELOPT_EXOPL 255 /* extended-options-list */
+
+
+#define NTELOPTS (1+TELOPT_NEW_ENVIRON)
+#ifdef TELOPTS
+char *telopts[NTELOPTS+1] = {
+ "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME",
+ "STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP",
+ "NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS",
+ "NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO",
+ "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT",
+ "SEND LOCATION", "TERMINAL TYPE", "END OF RECORD",
+ "TACACS UID", "OUTPUT MARKING", "TTYLOC",
+ "3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW",
+ "LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION",
+ "ENCRYPT", "NEW-ENVIRON",
+ 0
+};
+#define TELOPT_FIRST TELOPT_BINARY
+#define TELOPT_LAST TELOPT_NEW_ENVIRON
+#define TELOPT_OK(x) ((unsigned int)(x) <= TELOPT_LAST)
+#define TELOPT(x) telopts[(x)-TELOPT_FIRST]
+#endif
+
+/* sub-option qualifiers */
+#define TELQUAL_IS 0 /* option is... */
+#define TELQUAL_SEND 1 /* send option */
+#define TELQUAL_INFO 2 /* ENVIRON: informational version of IS */
+#define TELQUAL_REPLY 2 /* AUTHENTICATION: client version of IS */
+#define TELQUAL_NAME 3 /* AUTHENTICATION: client version of IS */
+
+#define LFLOW_OFF 0 /* Disable remote flow control */
+#define LFLOW_ON 1 /* Enable remote flow control */
+#define LFLOW_RESTART_ANY 2 /* Restart output on any char */
+#define LFLOW_RESTART_XON 3 /* Restart output only on XON */
+
+/*
+ * LINEMODE suboptions
+ */
+
+#define LM_MODE 1
+#define LM_FORWARDMASK 2
+#define LM_SLC 3
+
+#define MODE_EDIT 0x01
+#define MODE_TRAPSIG 0x02
+#define MODE_ACK 0x04
+#define MODE_SOFT_TAB 0x08
+#define MODE_LIT_ECHO 0x10
+
+#define MODE_MASK 0x1f
+
+/* Not part of protocol, but needed to simplify things... */
+#define MODE_FLOW 0x0100
+#define MODE_ECHO 0x0200
+#define MODE_INBIN 0x0400
+#define MODE_OUTBIN 0x0800
+#define MODE_FORCE 0x1000
+
+#define SLC_SYNCH 1
+#define SLC_BRK 2
+#define SLC_IP 3
+#define SLC_AO 4
+#define SLC_AYT 5
+#define SLC_EOR 6
+#define SLC_ABORT 7
+#define SLC_EOF 8
+#define SLC_SUSP 9
+#define SLC_EC 10
+#define SLC_EL 11
+#define SLC_EW 12
+#define SLC_RP 13
+#define SLC_LNEXT 14
+#define SLC_XON 15
+#define SLC_XOFF 16
+#define SLC_FORW1 17
+#define SLC_FORW2 18
+#define SLC_MCL 19
+#define SLC_MCR 20
+#define SLC_MCWL 21
+#define SLC_MCWR 22
+#define SLC_MCBOL 23
+#define SLC_MCEOL 24
+#define SLC_INSRT 25
+#define SLC_OVER 26
+#define SLC_ECR 27
+#define SLC_EWR 28
+#define SLC_EBOL 29
+#define SLC_EEOL 30
+
+#define NSLC 30
+
+/*
+ * For backwards compatability, we define SLC_NAMES to be the
+ * list of names if SLC_NAMES is not defined.
+ */
+#define SLC_NAMELIST "0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \
+ "ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \
+ "LNEXT", "XON", "XOFF", "FORW1", "FORW2", \
+ "MCL", "MCR", "MCWL", "MCWR", "MCBOL", \
+ "MCEOL", "INSRT", "OVER", "ECR", "EWR", \
+ "EBOL", "EEOL", \
+ 0
+
+#ifdef SLC_NAMES
+char *slc_names[] = {
+ SLC_NAMELIST
+};
+#else
+extern char *slc_names[];
+#define SLC_NAMES SLC_NAMELIST
+#endif
+
+#define SLC_NAME_OK(x) ((unsigned int)(x) <= NSLC)
+#define SLC_NAME(x) slc_names[x]
+
+#define SLC_NOSUPPORT 0
+#define SLC_CANTCHANGE 1
+#define SLC_VARIABLE 2
+#define SLC_DEFAULT 3
+#define SLC_LEVELBITS 0x03
+
+#define SLC_FUNC 0
+#define SLC_FLAGS 1
+#define SLC_VALUE 2
+
+#define SLC_ACK 0x80
+#define SLC_FLUSHIN 0x40
+#define SLC_FLUSHOUT 0x20
+
+#define OLD_ENV_VAR 1
+#define OLD_ENV_VALUE 0
+#define NEW_ENV_VAR 0
+#define NEW_ENV_VALUE 1
+#define ENV_ESC 2
+#define ENV_USERVAR 3
+
+/*
+ * AUTHENTICATION suboptions
+ */
+
+/*
+ * Who is authenticating who ...
+ */
+#define AUTH_WHO_CLIENT 0 /* Client authenticating server */
+#define AUTH_WHO_SERVER 1 /* Server authenticating client */
+#define AUTH_WHO_MASK 1
+
+/*
+ * amount of authentication done
+ */
+#define AUTH_HOW_ONE_WAY 0
+#define AUTH_HOW_MUTUAL 2
+#define AUTH_HOW_MASK 2
+
+#define AUTHTYPE_NULL 0
+#define AUTHTYPE_KERBEROS_V4 1
+#define AUTHTYPE_KERBEROS_V5 2
+#define AUTHTYPE_SPX 3
+#define AUTHTYPE_MINK 4
+#define AUTHTYPE_CNT 5
+
+#define AUTHTYPE_TEST 99
+
+#ifdef AUTH_NAMES
+char *authtype_names[] = {
+ "NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK",
+ 0
+};
+#else
+extern char *authtype_names[];
+#endif
+
+#define AUTHTYPE_NAME_OK(x) ((unsigned int)(x) < AUTHTYPE_CNT)
+#define AUTHTYPE_NAME(x) authtype_names[x]
+
+/*
+ * ENCRYPTion suboptions
+ */
+#define ENCRYPT_IS 0 /* I pick encryption type ... */
+#define ENCRYPT_SUPPORT 1 /* I support encryption types ... */
+#define ENCRYPT_REPLY 2 /* Initial setup response */
+#define ENCRYPT_START 3 /* Am starting to send encrypted */
+#define ENCRYPT_END 4 /* Am ending encrypted */
+#define ENCRYPT_REQSTART 5 /* Request you start encrypting */
+#define ENCRYPT_REQEND 6 /* Request you end encrypting */
+#define ENCRYPT_ENC_KEYID 7
+#define ENCRYPT_DEC_KEYID 8
+#define ENCRYPT_CNT 9
+
+#define ENCTYPE_ANY 0
+#define ENCTYPE_DES_CFB64 1
+#define ENCTYPE_DES_OFB64 2
+#define ENCTYPE_CNT 3
+
+#ifdef ENCRYPT_NAMES
+char *encrypt_names[] = {
+ "IS", "SUPPORT", "REPLY", "START", "END",
+ "REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID",
+ 0
+};
+char *enctype_names[] = {
+ "ANY", "DES_CFB64", "DES_OFB64",
+ 0
+};
+#else
+extern char *encrypt_names[];
+extern char *enctype_names[];
+#endif
+
+
+#define ENCRYPT_NAME_OK(x) ((unsigned int)(x) < ENCRYPT_CNT)
+#define ENCRYPT_NAME(x) encrypt_names[x]
+
+#define ENCTYPE_NAME_OK(x) ((unsigned int)(x) < ENCTYPE_CNT)
+#define ENCTYPE_NAME(x) enctype_names[x]
+
+#endif /* !_TELNET_H_ */
diff --git a/StdLib/Include/err.h b/StdLib/Include/err.h new file mode 100644 index 0000000000..6207d18039 --- /dev/null +++ b/StdLib/Include/err.h @@ -0,0 +1,25 @@ +/** @file error and warning output messages
+
+ Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#ifndef _ERR_H_
+#define _ERR_H_
+
+//
+// Error and Warning outputs
+//
+
+void errx (int eval, const char *fmt, ...);
+void err (int eval, const char *fmt, ...);
+void warnx(const char *fmt, ...);
+void warn (const char *fmt, ...);
+
+#endif
\ No newline at end of file diff --git a/StdLib/Include/errno.h b/StdLib/Include/errno.h index f6d97bb9e5..9c6e071a2a 100644 --- a/StdLib/Include/errno.h +++ b/StdLib/Include/errno.h @@ -34,6 +34,8 @@ extern RETURN_STATUS EFIerrno; // Define error number in terms of the ENUM in <sys/errno.h>
+#define ERESTART -1 /* restart syscall */
+
#define EMINERRORVAL __EMINERRORVAL /* The lowest valid error value */
#define EPERM __EPERM /* 1 Operation not permitted */
diff --git a/StdLib/Include/glob.h b/StdLib/Include/glob.h new file mode 100644 index 0000000000..5842130447 --- /dev/null +++ b/StdLib/Include/glob.h @@ -0,0 +1,109 @@ +/* $NetBSD: glob.h,v 1.24 2008/09/13 17:05:07 christos Exp $ */
+
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)glob.h 8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _GLOB_H_
+#define _GLOB_H_
+
+#include <sys/cdefs.h>
+#include <sys/featuretest.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifndef __gl_size_t
+#define __gl_size_t size_t
+#endif
+#ifndef __gl_stat_t
+#define __gl_stat_t struct stat
+#endif
+
+typedef struct {
+ __gl_size_t gl_pathc; /* Count of total paths so far. */
+ __gl_size_t gl_matchc; /* Count of paths matching pattern. */
+ __gl_size_t gl_offs; /* Reserved at beginning of gl_pathv. */
+ int gl_flags; /* Copy of flags parameter to glob. */
+ char **gl_pathv; /* List of paths matching pattern. */
+ /* Copy of errfunc parameter to glob. */
+ int (*gl_errfunc)(const char *, int);
+
+ /*
+ * Alternate filesystem access methods for glob; replacement
+ * versions of closedir(3), readdir(3), opendir(3), stat(2)
+ * and lstat(2).
+ */
+ void (*gl_closedir)(void *);
+ struct dirent *(*gl_readdir)(void *);
+ void *(*gl_opendir)(const char *);
+ int (*gl_lstat)(const char *, __gl_stat_t *);
+ int (*gl_stat)(const char *, __gl_stat_t *);
+} glob_t;
+
+#define GLOB_APPEND 0x0001 /* Append to output from previous call. */
+#define GLOB_DOOFFS 0x0002 /* Use gl_offs. */
+#define GLOB_ERR 0x0004 /* Return on error. */
+#define GLOB_MARK 0x0008 /* Append / to matching directories. */
+#define GLOB_NOCHECK 0x0010 /* Return pattern itself if nothing matches. */
+#define GLOB_NOSORT 0x0020 /* Don't sort. */
+#define GLOB_NOESCAPE 0x1000 /* Disable backslash escaping. */
+
+#define GLOB_NOSPACE (-1) /* Malloc call failed. */
+#define GLOB_ABORTED (-2) /* Unignored error. */
+#define GLOB_NOMATCH (-3) /* No match, and GLOB_NOCHECK was not set. */
+#define GLOB_NOSYS (-4) /* Implementation does not support function. */
+
+#if defined(_NETBSD_SOURCE) || defined(HAVE_NBTOOL_CONFIG_H)
+#define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */
+#define GLOB_BRACE 0x0080 /* Expand braces ala csh. */
+#define GLOB_MAGCHAR 0x0100 /* Pattern had globbing characters. */
+#define GLOB_NOMAGIC 0x0200 /* GLOB_NOCHECK without magic chars (csh). */
+#define GLOB_LIMIT 0x0400 /* Limit memory used by matches to ARG_MAX */
+#define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */
+/* GLOB_NOESCAPE 0x1000 above */
+#define GLOB_PERIOD 0x2000 /* Allow metachars to match leading periods. */
+#define GLOB_NO_DOTDIRS 0x4000 /* Make . and .. vanish from wildcards. */
+#define GLOB_QUOTE 0 /* source compatibility */
+
+#define GLOB_ABEND GLOB_ABORTED /* source compatibility */
+#endif
+
+__BEGIN_DECLS
+#ifndef __LIBC12_SOURCE__
+int glob(const char * __restrict, int,
+ int (*)(const char *, int), glob_t * __restrict) __RENAME(__glob30);
+void globfree(glob_t *) __RENAME(__globfree30);
+#endif
+__END_DECLS
+
+#endif /* !_GLOB_H_ */
diff --git a/StdLib/Include/libgen.h b/StdLib/Include/libgen.h new file mode 100644 index 0000000000..3ee673832d --- /dev/null +++ b/StdLib/Include/libgen.h @@ -0,0 +1,14 @@ +/** @file
+
+Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+char *dirname(char *path);
diff --git a/StdLib/Include/net/if.h b/StdLib/Include/net/if.h new file mode 100644 index 0000000000..0b8afa0965 --- /dev/null +++ b/StdLib/Include/net/if.h @@ -0,0 +1,227 @@ +/*
+ * Copyright (c) 1982, 1986, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)if.h 8.1 (Berkeley) 6/10/93
+ * $Id: if.h,v 1.1.1.1 2006/05/30 06:12:41 hhzhou Exp $
+ */
+
+#ifndef _NET_IF_H_
+#define _NET_IF_H_
+
+/*
+ * <net/if.h> does not depend on <sys/time.h> on most other systems. This
+ * helps userland compatability. (struct timeval ifi_lastchange)
+ */
+#ifndef KERNEL
+#include <sys/time.h>
+#endif
+
+/*
+ * Structure describing information about an interface
+ * which may be of interest to management entities.
+ */
+struct if_data {
+ /* generic interface information */
+ u_char ifi_type; /* ethernet, tokenring, etc */
+ u_char ifi_physical; /* e.g., AUI, Thinnet, 10base-T, etc */
+ u_char ifi_addrlen; /* media address length */
+ u_char ifi_hdrlen; /* media header length */
+ u_char ifi_recvquota; /* polling quota for receive intrs */
+ u_char ifi_xmitquota; /* polling quota for xmit intrs */
+ u_long ifi_mtu; /* maximum transmission unit */
+ u_long ifi_metric; /* routing metric (external only) */
+ u_long ifi_baudrate; /* linespeed */
+ /* volatile statistics */
+ u_long ifi_ipackets; /* packets received on interface */
+ u_long ifi_ierrors; /* input errors on interface */
+ u_long ifi_opackets; /* packets sent on interface */
+ u_long ifi_oerrors; /* output errors on interface */
+ u_long ifi_collisions; /* collisions on csma interfaces */
+ u_long ifi_ibytes; /* total number of octets received */
+ u_long ifi_obytes; /* total number of octets sent */
+ u_long ifi_imcasts; /* packets received via multicast */
+ u_long ifi_omcasts; /* packets sent via multicast */
+ u_long ifi_iqdrops; /* dropped on input, this interface */
+ u_long ifi_noproto; /* destined for unsupported protocol */
+ u_long ifi_recvtiming; /* usec spent receiving when timing */
+ u_long ifi_xmittiming; /* usec spent xmitting when timing */
+ struct timeval ifi_lastchange; /* time of last administrative change */
+};
+
+#define IFF_UP 0x1 /* interface is up */
+#define IFF_BROADCAST 0x2 /* broadcast address valid */
+#define IFF_DEBUG 0x4 /* turn on debugging */
+#define IFF_LOOPBACK 0x8 /* is a loopback net */
+#define IFF_POINTOPOINT 0x10 /* interface is point-to-point link */
+/*#define IFF_NOTRAILERS 0x20 * obsolete: avoid use of trailers */
+#define IFF_RUNNING 0x40 /* resources allocated */
+#define IFF_NOARP 0x80 /* no address resolution protocol */
+#define IFF_PROMISC 0x100 /* receive all packets */
+#define IFF_ALLMULTI 0x200 /* receive all multicast packets */
+#define IFF_OACTIVE 0x400 /* transmission in progress */
+#define IFF_SIMPLEX 0x800 /* can't hear own transmissions */
+#define IFF_LINK0 0x1000 /* per link layer defined bit */
+#define IFF_LINK1 0x2000 /* per link layer defined bit */
+#define IFF_LINK2 0x4000 /* per link layer defined bit */
+#define IFF_ALTPHYS IFF_LINK2 /* use alternate physical connection */
+#define IFF_MULTICAST 0x8000 /* supports multicast */
+
+/* flags set internally only: */
+#define IFF_CANTCHANGE \
+ (IFF_BROADCAST|IFF_POINTOPOINT|IFF_RUNNING|IFF_OACTIVE|\
+ IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI)
+
+#define IFQ_MAXLEN 50
+#define IFNET_SLOWHZ 1 /* granularity is 1 second */
+
+/*
+ * Message format for use in obtaining information about interfaces
+ * from getkerninfo and the routing socket
+ */
+struct if_msghdr {
+ u_short ifm_msglen; /* to skip over non-understood messages */
+ u_char ifm_version; /* future binary compatability */
+ u_char ifm_type; /* message type */
+ int ifm_addrs; /* like rtm_addrs */
+ int ifm_flags; /* value of if_flags */
+ u_short ifm_index; /* index for associated ifp */
+ struct if_data ifm_data;/* statistics and other data about if */
+};
+
+/*
+ * Message format for use in obtaining information about interface addresses
+ * from getkerninfo and the routing socket
+ */
+struct ifa_msghdr {
+ u_short ifam_msglen; /* to skip over non-understood messages */
+ u_char ifam_version; /* future binary compatability */
+ u_char ifam_type; /* message type */
+ int ifam_addrs; /* like rtm_addrs */
+ int ifam_flags; /* value of ifa_flags */
+ u_short ifam_index; /* index for associated ifp */
+ int ifam_metric; /* value of ifa_metric */
+};
+
+/*
+ * Message format for use in obtaining information about multicast addresses
+ * from the routing socket
+ */
+struct ifma_msghdr {
+ u_short ifmam_msglen; /* to skip over non-understood messages */
+ u_char ifmam_version; /* future binary compatability */
+ u_char ifmam_type; /* message type */
+ int ifmam_addrs; /* like rtm_addrs */
+ int ifmam_flags; /* value of ifa_flags */
+ u_short ifmam_index; /* index for associated ifp */
+};
+
+/*
+ * Interface request structure used for socket
+ * ioctl's. All interface ioctl's must have parameter
+ * definitions which begin with ifr_name. The
+ * remainder may be interface specific.
+ */
+struct ifreq {
+#define IFNAMSIZ 16
+ char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */
+ union {
+ struct sockaddr ifru_addr;
+ struct sockaddr ifru_dstaddr;
+ struct sockaddr ifru_broadaddr;
+ short ifru_flags;
+ int ifru_metric;
+ int ifru_mtu;
+ int ifru_phys;
+ int ifru_media;
+ caddr_t ifru_data;
+ } ifr_ifru;
+#define ifr_addr ifr_ifru.ifru_addr /* address */
+#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p link */
+#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
+#define ifr_flags ifr_ifru.ifru_flags /* flags */
+#define ifr_metric ifr_ifru.ifru_metric /* metric */
+#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
+#define ifr_phys ifr_ifru.ifru_phys /* physical wire */
+#define ifr_media ifr_ifru.ifru_media /* physical media */
+#define ifr_data ifr_ifru.ifru_data /* for use by interface */
+};
+
+#define _SIZEOF_ADDR_IFREQ(ifr) \
+ ((ifr).ifr_addr.sa_len > sizeof(struct sockaddr) ? \
+ (sizeof(struct ifreq) - sizeof(struct sockaddr) + \
+ (ifr).ifr_addr.sa_len) : sizeof(struct ifreq))
+
+struct ifaliasreq {
+ char ifra_name[IFNAMSIZ]; /* if name, e.g. "en0" */
+ struct sockaddr ifra_addr;
+ struct sockaddr ifra_broadaddr;
+ struct sockaddr ifra_mask;
+};
+
+struct ifmediareq {
+ char ifm_name[IFNAMSIZ]; /* if name, e.g. "en0" */
+ int ifm_current; /* current media options */
+ int ifm_mask; /* don't care mask */
+ int ifm_status; /* media status */
+ int ifm_active; /* active options */
+ int ifm_count; /* # entries in ifm_ulist array */
+ int *ifm_ulist; /* media words */
+};
+/*
+ * Structure used in SIOCGIFCONF request.
+ * Used to retrieve interface configuration
+ * for machine (useful for programs which
+ * must know all networks accessible).
+ */
+struct ifconf {
+ int ifc_len; /* size of associated buffer */
+ union {
+ caddr_t ifcu_buf;
+ struct ifreq *ifcu_req;
+ } ifc_ifcu;
+#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */
+#define ifc_req ifc_ifcu.ifcu_req /* array of structures returned */
+};
+
+#ifdef KERNEL
+#ifdef MALLOC_DECLARE
+MALLOC_DECLARE(M_IFADDR);
+MALLOC_DECLARE(M_IFMADDR);
+#endif
+#endif
+
+/* XXX - this should go away soon */
+#ifdef KERNEL
+#include <net/if_var.h>
+#endif
+
+#endif /* !_NET_IF_H_ */
diff --git a/StdLib/Include/net/if_dl.h b/StdLib/Include/net/if_dl.h new file mode 100644 index 0000000000..3935551097 --- /dev/null +++ b/StdLib/Include/net/if_dl.h @@ -0,0 +1,86 @@ +/*
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)if_dl.h 8.1 (Berkeley) 6/10/93
+ * $Id: if_dl.h,v 1.1.1.1 2006/05/30 06:12:42 hhzhou Exp $
+ */
+
+#ifndef _NET_IF_DL_H_
+#define _NET_IF_DL_H_
+
+/*
+ * A Link-Level Sockaddr may specify the interface in one of two
+ * ways: either by means of a system-provided index number (computed
+ * anew and possibly differently on every reboot), or by a human-readable
+ * string such as "il0" (for managerial convenience).
+ *
+ * Census taking actions, such as something akin to SIOCGCONF would return
+ * both the index and the human name.
+ *
+ * High volume transactions (such as giving a link-level ``from'' address
+ * in a recvfrom or recvmsg call) may be likely only to provide the indexed
+ * form, (which requires fewer copy operations and less space).
+ *
+ * The form and interpretation of the link-level address is purely a matter
+ * of convention between the device driver and its consumers; however, it is
+ * expected that all drivers for an interface of a given if_type will agree.
+ */
+
+/*
+ * Structure of a Link-Level sockaddr:
+ */
+struct sockaddr_dl {
+ u_char sdl_len; /* Total length of sockaddr */
+ u_char sdl_family; /* AF_DLI */
+ u_short sdl_index; /* if != 0, system given index for interface */
+ u_char sdl_type; /* interface type */
+ u_char sdl_nlen; /* interface name length, no trailing 0 reqd. */
+ u_char sdl_alen; /* link level address length */
+ u_char sdl_slen; /* link layer selector length */
+ char sdl_data[12]; /* minimum work area, can be larger;
+ contains both if name and ll address */
+};
+
+#define LLADDR(s) ((caddr_t)((s)->sdl_data + (s)->sdl_nlen))
+
+#ifndef KERNEL
+
+#include <sys/EfiCdefs.h>
+
+__BEGIN_DECLS
+void link_addr __P((const char *, struct sockaddr_dl *));
+char *link_ntoa __P((const struct sockaddr_dl *));
+__END_DECLS
+
+#endif /* !KERNEL */
+
+#endif
diff --git a/StdLib/Include/net/radix.h b/StdLib/Include/net/radix.h new file mode 100644 index 0000000000..20ad34b6e8 --- /dev/null +++ b/StdLib/Include/net/radix.h @@ -0,0 +1,170 @@ +/*
+ * Copyright (c) 1988, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)radix.h 8.2 (Berkeley) 10/31/94
+ * $Id: radix.h,v 1.1.1.1 2006/05/30 06:12:46 hhzhou Exp $
+ */
+
+#ifndef _RADIX_H_
+#define _RADIX_H_
+
+#ifdef MALLOC_DECLARE
+MALLOC_DECLARE(M_RTABLE);
+#endif
+
+/*
+ * Radix search tree node layout.
+ */
+
+struct radix_node {
+ struct radix_mask *rn_mklist; /* list of masks contained in subtree */
+ struct radix_node *rn_p; /* parent */
+ short rn_b; /* bit offset; -1-index(netmask) */
+ char rn_bmask; /* node: mask for bit test*/
+ u_char rn_flags; /* enumerated next */
+#define RNF_NORMAL 1 /* leaf contains normal route */
+#define RNF_ROOT 2 /* leaf is root leaf for tree */
+#define RNF_ACTIVE 4 /* This node is alive (for rtfree) */
+ union {
+ struct { /* leaf only data: */
+ caddr_t rn_Key; /* object of search */
+ caddr_t rn_Mask; /* netmask, if present */
+ struct radix_node *rn_Dupedkey;
+ } rn_leaf;
+ struct { /* node only data: */
+ int rn_Off; /* where to start compare */
+ struct radix_node *rn_L;/* progeny */
+ struct radix_node *rn_R;/* progeny */
+ } rn_node;
+ } rn_u;
+#ifdef RN_DEBUG
+ int rn_info;
+ struct radix_node *rn_twin;
+ struct radix_node *rn_ybro;
+#endif
+};
+
+#define rn_dupedkey rn_u.rn_leaf.rn_Dupedkey
+#define rn_key rn_u.rn_leaf.rn_Key
+#define rn_mask rn_u.rn_leaf.rn_Mask
+#define rn_off rn_u.rn_node.rn_Off
+#define rn_l rn_u.rn_node.rn_L
+#define rn_r rn_u.rn_node.rn_R
+
+/*
+ * Annotations to tree concerning potential routes applying to subtrees.
+ */
+
+struct radix_mask {
+ short rm_b; /* bit offset; -1-index(netmask) */
+ char rm_unused; /* cf. rn_bmask */
+ u_char rm_flags; /* cf. rn_flags */
+ struct radix_mask *rm_mklist; /* more masks to try */
+ union {
+ caddr_t rmu_mask; /* the mask */
+ struct radix_node *rmu_leaf; /* for normal routes */
+ } rm_rmu;
+ int rm_refs; /* # of references to this struct */
+};
+
+#define rm_mask rm_rmu.rmu_mask
+#define rm_leaf rm_rmu.rmu_leaf /* extra field would make 32 bytes */
+
+#define MKGet(m) {\
+ if (rn_mkfreelist) {\
+ m = rn_mkfreelist; \
+ rn_mkfreelist = (m)->rm_mklist; \
+ } else \
+ R_Malloc(m, struct radix_mask *, sizeof (*(m))); }\
+
+#define MKFree(m) { (m)->rm_mklist = rn_mkfreelist; rn_mkfreelist = (m);}
+
+typedef int walktree_f_t __P((struct radix_node *, void *));
+
+struct radix_node_head {
+ struct radix_node *rnh_treetop;
+ int rnh_addrsize; /* permit, but not require fixed keys */
+ int rnh_pktsize; /* permit, but not require fixed keys */
+ struct radix_node *(*rnh_addaddr) /* add based on sockaddr */
+ __P((void *v, void *mask,
+ struct radix_node_head *head, struct radix_node nodes[]));
+ struct radix_node *(*rnh_addpkt) /* add based on packet hdr */
+ __P((void *v, void *mask,
+ struct radix_node_head *head, struct radix_node nodes[]));
+ struct radix_node *(*rnh_deladdr) /* remove based on sockaddr */
+ __P((void *v, void *mask, struct radix_node_head *head));
+ struct radix_node *(*rnh_delpkt) /* remove based on packet hdr */
+ __P((void *v, void *mask, struct radix_node_head *head));
+ struct radix_node *(*rnh_matchaddr) /* locate based on sockaddr */
+ __P((void *v, struct radix_node_head *head));
+ struct radix_node *(*rnh_lookup) /* locate based on sockaddr */
+ __P((void *v, void *mask, struct radix_node_head *head));
+ struct radix_node *(*rnh_matchpkt) /* locate based on packet hdr */
+ __P((void *v, struct radix_node_head *head));
+ int (*rnh_walktree) /* traverse tree */
+ __P((struct radix_node_head *head, walktree_f_t *f, void *w));
+ int (*rnh_walktree_from) /* traverse tree below a */
+ __P((struct radix_node_head *head, void *a, void *m,
+ walktree_f_t *f, void *w));
+ void (*rnh_close) /* do something when the last ref drops */
+ __P((struct radix_node *rn, struct radix_node_head *head));
+ struct radix_node rnh_nodes[3]; /* empty tree for common case */
+};
+
+#ifndef KERNEL
+#define Bcmp(a, b, n) bcmp(((char *)(a)), ((char *)(b)), (n))
+#define Bcopy(a, b, n) bcopy(((char *)(a)), ((char *)(b)), (unsigned)(n))
+#define Bzero(p, n) bzero((char *)(p), (int)(n));
+#define R_Malloc(p, t, n) (p = (t) malloc((unsigned int)(n)))
+#define Free(p) free((char *)p);
+#else
+#define Bcmp(a, b, n) bcmp(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n))
+#define Bcopy(a, b, n) bcopy(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n))
+#define Bzero(p, n) bzero((caddr_t)(p), (unsigned)(n));
+#define R_Malloc(p, t, n) (p = (t) malloc((unsigned long)(n), M_RTABLE, M_DONTWAIT))
+#define Free(p) free((caddr_t)p, M_RTABLE);
+#endif /*KERNEL*/
+
+void rn_init __P((void));
+int rn_inithead __P((void **, int));
+int rn_refines __P((void *, void *));
+struct radix_node
+ *rn_addmask __P((void *, int, int)),
+ *rn_addroute __P((void *, void *, struct radix_node_head *,
+ struct radix_node [2])),
+ *rn_delete __P((void *, void *, struct radix_node_head *)),
+ *rn_lookup __P((void *v_arg, void *m_arg,
+ struct radix_node_head *head)),
+ *rn_match __P((void *, struct radix_node_head *));
+
+
+#endif /* _RADIX_H_ */
diff --git a/StdLib/Include/net/route.h b/StdLib/Include/net/route.h new file mode 100644 index 0000000000..ec5d9eba7e --- /dev/null +++ b/StdLib/Include/net/route.h @@ -0,0 +1,292 @@ +/*
+ * Copyright (c) 1980, 1986, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)route.h 8.3 (Berkeley) 4/19/94
+ * $Id: route.h,v 1.1.1.1 2006/05/30 06:12:46 hhzhou Exp $
+ */
+
+#ifndef _NET_ROUTE_H_
+#define _NET_ROUTE_H_
+
+#define __P(protos) protos /* full-blown ANSI C */
+
+
+/*
+ * Kernel resident routing tables.
+ *
+ * The routing tables are initialized when interface addresses
+ * are set by making entries for all directly connected interfaces.
+ */
+
+/*
+ * A route consists of a destination address and a reference
+ * to a routing entry. These are often held by protocols
+ * in their control blocks, e.g. inpcb.
+ */
+struct route {
+ struct rtentry *ro_rt;
+ struct sockaddr ro_dst;
+};
+
+/*
+ * These numbers are used by reliable protocols for determining
+ * retransmission behavior and are included in the routing structure.
+ */
+struct rt_metrics {
+ u_long rmx_locks; /* Kernel must leave these values alone */
+ u_long rmx_mtu; /* MTU for this path */
+ u_long rmx_hopcount; /* max hops expected */
+ u_long rmx_expire; /* lifetime for route, e.g. redirect */
+ u_long rmx_recvpipe; /* inbound delay-bandwidth product */
+ u_long rmx_sendpipe; /* outbound delay-bandwidth product */
+ u_long rmx_ssthresh; /* outbound gateway buffer limit */
+ u_long rmx_rtt; /* estimated round trip time */
+ u_long rmx_rttvar; /* estimated rtt variance */
+ u_long rmx_pksent; /* packets sent using this route */
+ u_long rmx_filler[4]; /* will be used for T/TCP later */
+};
+
+/*
+ * rmx_rtt and rmx_rttvar are stored as microseconds;
+ * RTTTOPRHZ(rtt) converts to a value suitable for use
+ * by a protocol slowtimo counter.
+ */
+#define RTM_RTTUNIT 1000000 /* units for rtt, rttvar, as units per sec */
+#define RTTTOPRHZ(r) ((r) / (RTM_RTTUNIT / PR_SLOWHZ))
+
+/*
+ * XXX kernel function pointer `rt_output' is visible to applications.
+ */
+struct mbuf;
+
+/*
+ * We distinguish between routes to hosts and routes to networks,
+ * preferring the former if available. For each route we infer
+ * the interface to use from the gateway address supplied when
+ * the route was entered. Routes that forward packets through
+ * gateways are marked so that the output routines know to address the
+ * gateway rather than the ultimate destination.
+ */
+#ifndef RNF_NORMAL
+#include <net/radix.h>
+#endif
+struct rtentry {
+ struct radix_node rt_nodes[2]; /* tree glue, and other values */
+#define rt_key(r) ((struct sockaddr *)((r)->rt_nodes->rn_key))
+#define rt_mask(r) ((struct sockaddr *)((r)->rt_nodes->rn_mask))
+ struct sockaddr *rt_gateway; /* value */
+ short rt_filler; /* was short flags field */
+ short rt_refcnt; /* # held references */
+ u_long rt_flags; /* up/down?, host/net */
+ struct ifnet *rt_ifp; /* the answer: interface to use */
+ struct ifaddr *rt_ifa; /* the answer: interface to use */
+ struct sockaddr *rt_genmask; /* for generation of cloned routes */
+ caddr_t rt_llinfo; /* pointer to link level info cache */
+ struct rt_metrics rt_rmx; /* metrics used by rx'ing protocols */
+ struct rtentry *rt_gwroute; /* implied entry for gatewayed routes */
+ int (*rt_output) __P((struct ifnet *, struct mbuf *,
+ struct sockaddr *, struct rtentry *));
+ /* output routine for this (rt,if) */
+ struct rtentry *rt_parent; /* cloning parent of this route */
+ void *rt_filler2; /* more filler */
+};
+
+/*
+ * Following structure necessary for 4.3 compatibility;
+ * We should eventually move it to a compat file.
+ */
+struct ortentry {
+ u_long rt_hash; /* to speed lookups */
+ struct sockaddr rt_dst; /* key */
+ struct sockaddr rt_gateway; /* value */
+ short rt_flags; /* up/down?, host/net */
+ short rt_refcnt; /* # held references */
+ u_long rt_use; /* raw # packets forwarded */
+ struct ifnet *rt_ifp; /* the answer: interface to use */
+};
+
+#define rt_use rt_rmx.rmx_pksent
+
+#define RTF_UP 0x1 /* route usable */
+#define RTF_GATEWAY 0x2 /* destination is a gateway */
+#define RTF_HOST 0x4 /* host entry (net otherwise) */
+#define RTF_REJECT 0x8 /* host or net unreachable */
+#define RTF_DYNAMIC 0x10 /* created dynamically (by redirect) */
+#define RTF_MODIFIED 0x20 /* modified dynamically (by redirect) */
+#define RTF_DONE 0x40 /* message confirmed */
+/* 0x80 unused */
+#define RTF_CLONING 0x100 /* generate new routes on use */
+#define RTF_XRESOLVE 0x200 /* external daemon resolves name */
+#define RTF_LLINFO 0x400 /* generated by link layer (e.g. ARP) */
+#define RTF_STATIC 0x800 /* manually added */
+#define RTF_BLACKHOLE 0x1000 /* just discard pkts (during updates) */
+#define RTF_PROTO2 0x4000 /* protocol specific routing flag */
+#define RTF_PROTO1 0x8000 /* protocol specific routing flag */
+
+#define RTF_PRCLONING 0x10000 /* protocol requires cloning */
+#define RTF_WASCLONED 0x20000 /* route generated through cloning */
+#define RTF_PROTO3 0x40000 /* protocol specific routing flag */
+/* 0x80000 unused */
+#define RTF_PINNED 0x100000 /* future use */
+#define RTF_LOCAL 0x200000 /* route represents a local address */
+#define RTF_BROADCAST 0x400000 /* route represents a bcast address */
+#define RTF_MULTICAST 0x800000 /* route represents a mcast address */
+ /* 0x1000000 and up unassigned */
+
+/*
+ * Routing statistics.
+ */
+struct rtstat {
+ short rts_badredirect; /* bogus redirect calls */
+ short rts_dynamic; /* routes created by redirects */
+ short rts_newgateway; /* routes modified by redirects */
+ short rts_unreach; /* lookups which failed */
+ short rts_wildcard; /* lookups satisfied by a wildcard */
+};
+/*
+ * Structures for routing messages.
+ */
+struct rt_msghdr {
+ u_short rtm_msglen; /* to skip over non-understood messages */
+ u_char rtm_version; /* future binary compatibility */
+ u_char rtm_type; /* message type */
+ u_short rtm_index; /* index for associated ifp */
+ int rtm_flags; /* flags, incl. kern & message, e.g. DONE */
+ int rtm_addrs; /* bitmask identifying sockaddrs in msg */
+ pid_t rtm_pid; /* identify sender */
+ int rtm_seq; /* for sender to identify action */
+ int rtm_errno; /* why failed */
+ int rtm_use; /* from rtentry */
+ u_long rtm_inits; /* which metrics we are initializing */
+ struct rt_metrics rtm_rmx; /* metrics themselves */
+};
+
+#define RTM_VERSION 5 /* Up the ante and ignore older versions */
+
+#define RTM_ADD 0x1 /* Add Route */
+#define RTM_DELETE 0x2 /* Delete Route */
+#define RTM_CHANGE 0x3 /* Change Metrics or flags */
+#define RTM_GET 0x4 /* Report Metrics */
+#define RTM_LOSING 0x5 /* Kernel Suspects Partitioning */
+#define RTM_REDIRECT 0x6 /* Told to use different route */
+#define RTM_MISS 0x7 /* Lookup failed on this address */
+#define RTM_LOCK 0x8 /* fix specified metrics */
+#define RTM_OLDADD 0x9 /* caused by SIOCADDRT */
+#define RTM_OLDDEL 0xa /* caused by SIOCDELRT */
+#define RTM_RESOLVE 0xb /* req to resolve dst to LL addr */
+#define RTM_NEWADDR 0xc /* address being added to iface */
+#define RTM_DELADDR 0xd /* address being removed from iface */
+#define RTM_IFINFO 0xe /* iface going up/down etc. */
+#define RTM_NEWMADDR 0xf /* mcast group membership being added to if */
+#define RTM_DELMADDR 0x10 /* mcast group membership being deleted */
+
+#define RTV_MTU 0x1 /* init or lock _mtu */
+#define RTV_HOPCOUNT 0x2 /* init or lock _hopcount */
+#define RTV_EXPIRE 0x4 /* init or lock _hopcount */
+#define RTV_RPIPE 0x8 /* init or lock _recvpipe */
+#define RTV_SPIPE 0x10 /* init or lock _sendpipe */
+#define RTV_SSTHRESH 0x20 /* init or lock _ssthresh */
+#define RTV_RTT 0x40 /* init or lock _rtt */
+#define RTV_RTTVAR 0x80 /* init or lock _rttvar */
+
+/*
+ * Bitmask values for rtm_addr.
+ */
+#define RTA_DST 0x1 /* destination sockaddr present */
+#define RTA_GATEWAY 0x2 /* gateway sockaddr present */
+#define RTA_NETMASK 0x4 /* netmask sockaddr present */
+#define RTA_GENMASK 0x8 /* cloning mask sockaddr present */
+#define RTA_IFP 0x10 /* interface name sockaddr present */
+#define RTA_IFA 0x20 /* interface addr sockaddr present */
+#define RTA_AUTHOR 0x40 /* sockaddr for author of redirect */
+#define RTA_BRD 0x80 /* for NEWADDR, broadcast or p-p dest addr */
+
+/*
+ * Index offsets for sockaddr array for alternate internal encoding.
+ */
+#define RTAX_DST 0 /* destination sockaddr present */
+#define RTAX_GATEWAY 1 /* gateway sockaddr present */
+#define RTAX_NETMASK 2 /* netmask sockaddr present */
+#define RTAX_GENMASK 3 /* cloning mask sockaddr present */
+#define RTAX_IFP 4 /* interface name sockaddr present */
+#define RTAX_IFA 5 /* interface addr sockaddr present */
+#define RTAX_AUTHOR 6 /* sockaddr for author of redirect */
+#define RTAX_BRD 7 /* for NEWADDR, broadcast or p-p dest addr */
+#define RTAX_MAX 8 /* size of array to allocate */
+
+struct rt_addrinfo {
+ int rti_addrs;
+ struct sockaddr *rti_info[RTAX_MAX];
+};
+
+struct route_cb {
+ int ip_count;
+ int ipx_count;
+ int ns_count;
+ int iso_count;
+ int any_count;
+};
+
+#ifdef KERNEL
+#define RTFREE(rt) \
+ if ((rt)->rt_refcnt <= 1) \
+ rtfree(rt); \
+ else \
+ (rt)->rt_refcnt--;
+
+extern struct route_cb route_cb;
+extern struct radix_node_head *rt_tables[AF_MAX+1];
+
+struct ifmultiaddr;
+struct proc;
+
+void route_init __P((void));
+void rt_ifmsg __P((struct ifnet *));
+void rt_missmsg __P((int, struct rt_addrinfo *, int, int));
+void rt_newaddrmsg __P((int, struct ifaddr *, int, struct rtentry *));
+void rt_newmaddrmsg __P((int, struct ifmultiaddr *));
+int rt_setgate __P((struct rtentry *,
+ struct sockaddr *, struct sockaddr *));
+void rtalloc __P((struct route *));
+void rtalloc_ign __P((struct route *, unsigned long));
+struct rtentry *
+ rtalloc1 __P((struct sockaddr *, int, unsigned long));
+void rtfree __P((struct rtentry *));
+int rtinit __P((struct ifaddr *, int, int));
+int rtioctl __P((int, caddr_t, struct proc *));
+void rtredirect __P((struct sockaddr *, struct sockaddr *,
+ struct sockaddr *, int, struct sockaddr *, struct rtentry **));
+int rtrequest __P((int, struct sockaddr *,
+ struct sockaddr *, struct sockaddr *, int, struct rtentry **));
+#endif
+
+#endif
diff --git a/StdLib/Include/netatalk/at.h b/StdLib/Include/netatalk/at.h new file mode 100644 index 0000000000..6c2b4f45c8 --- /dev/null +++ b/StdLib/Include/netatalk/at.h @@ -0,0 +1,92 @@ +/*
+ * Copyright (c) 1990,1991 Regents of The University of Michigan.
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation, and that the name of The University
+ * of Michigan not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. This software is supplied as is without expressed or
+ * implied warranties of any kind.
+ *
+ * Research Systems Unix Group
+ * The University of Michigan
+ * c/o Mike Clark
+ * 535 W. William Street
+ * Ann Arbor, Michigan
+ * +1-313-763-0525
+ * netatalk@itd.umich.edu
+ */
+
+#ifndef __AT_HEADER__
+#define __AT_HEADER__
+/*
+ * Supported protocols
+ */
+#define ATPROTO_DDP 0
+#define ATPROTO_AARP 254
+
+/*
+ * Ethernet types, for DIX.
+ * These should really be in some global header file, but we can't
+ * count on them being there, and it's annoying to patch system files.
+ */
+#define ETHERTYPE_AT 0x809B /* AppleTalk protocol */
+#define ETHERTYPE_AARP 0x80F3 /* AppleTalk ARP */
+
+#define DDP_MAXSZ 587
+
+/*
+ * If ATPORT_FIRST <= Port < ATPORT_RESERVED,
+ * Port was created by a privileged process.
+ * If ATPORT_RESERVED <= Port < ATPORT_LAST,
+ * Port was not necessarily created by a
+ * privileged process.
+ */
+#define ATPORT_FIRST 1
+#define ATPORT_RESERVED 128
+#define ATPORT_LAST 255
+
+/*
+ * AppleTalk address.
+ */
+struct at_addr {
+ u_short s_net;
+ u_char s_node;
+};
+
+#define ATADDR_ANYNET (u_short)0x0000
+#define ATADDR_ANYNODE (u_char)0x00
+#define ATADDR_ANYPORT (u_char)0x00
+#define ATADDR_BCAST (u_char)0xff /* There is no BCAST for NET */
+
+struct netrange {
+ u_char nr_phase;
+ u_short nr_firstnet;
+ u_short nr_lastnet;
+};
+
+/*
+ * Socket address, AppleTalk style. We keep magic information in the
+ * zero bytes. There are three types, NONE, CONFIG which has the phase
+ * and a net range, and IFACE which has the network address of an
+ * interface. IFACE may be filled in by the client, and is filled in
+ * by the kernel.
+ */
+struct sockaddr_at {
+ u_char sat_len;
+ u_char sat_family;
+ u_char sat_port;
+ struct at_addr sat_addr;
+ union {
+ struct netrange r_netrange;
+ char r_zero[ 8 ]; /* Hide a struct netrange in here */
+ } sat_range;
+};
+
+#define sat_zero sat_range.r_zero
+
+#endif /* !__AT_HEADER__ */
diff --git a/StdLib/Include/netdb.h b/StdLib/Include/netdb.h index e645f77bd3..e0d1a82082 100644 --- a/StdLib/Include/netdb.h +++ b/StdLib/Include/netdb.h @@ -94,6 +94,7 @@ #include <sys/cdefs.h>
#include <sys/featuretest.h>
#include <inttypes.h>
+#include <paths.h>
/*
* Data types
*/
@@ -108,27 +109,6 @@ typedef __socklen_t socklen_t; #undef _BSD_SIZE_T_
#endif
-////#if defined(_NETBSD_SOURCE)
-////#ifndef _PATH_HEQUIV
-////#define _PATH_HEQUIV "/etc/hosts.equiv"
-////#endif
-#ifndef _PATH_HOSTS
-#define _PATH_HOSTS "/etc/hosts"
-#endif
-#ifndef _PATH_NETWORKS
-#define _PATH_NETWORKS "/etc/networks"
-#endif
-#ifndef _PATH_PROTOCOLS
-#define _PATH_PROTOCOLS "/etc/protocols"
-#endif
-#ifndef _PATH_SERVICES
-#define _PATH_SERVICES "/etc/services"
-#endif
-////#ifndef _PATH_SERVICES_DB
-////#define _PATH_SERVICES_DB "/var/db/services.db"
-////#endif
-////#endif
-
__BEGIN_DECLS
extern int h_errno;
__END_DECLS
@@ -219,14 +199,11 @@ struct addrinfo { #define NETDB_INTERNAL -1 /*%< see errno */
#define NETDB_SUCCESS 0 /*%< no problem */
#endif
-////#define NO_ADDRESS NO_DATA /* no address, look for MX record */
+#define NO_ADDRESS NO_DATA /* no address, look for MX record */
#define HOST_NOT_FOUND 1 /*%< Authoritative Answer Host not found */
#define TRY_AGAIN 2 /*%< Non-Authoritive Host not found, or SERVERFAIL */
#define NO_RECOVERY 3 /*%< Non recoverable errors, FORMERR, REFUSED, NOTIMP */
-////#define NO_DATA 4 /*%< Valid name, no data record of requested type */
-////#if defined(_NETBSD_SOURCE)
-////#define NO_ADDRESS NO_DATA /*%< no address, look for MX record */
-////#endif
+#define NO_DATA 4 /*%< Valid name, no data record of requested type */
/*
* Error return codes from getaddrinfo()
diff --git a/StdLib/Include/netinet/in_systm.h b/StdLib/Include/netinet/in_systm.h new file mode 100644 index 0000000000..f86bf65fbc --- /dev/null +++ b/StdLib/Include/netinet/in_systm.h @@ -0,0 +1,62 @@ +/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)in_systm.h 8.1 (Berkeley) 6/10/93
+ * $Id: in_systm.h,v 1.1.1.1 2006/05/30 06:12:48 hhzhou Exp $
+ */
+
+#ifndef _NETINET_IN_SYSTM_H_
+#define _NETINET_IN_SYSTM_H_
+
+/*
+ * Miscellaneous internetwork
+ * definitions for kernel.
+ */
+
+/*
+ * Network types.
+ *
+ * Internally the system keeps counters in the headers with the bytes
+ * swapped so that VAX instructions will work on them. It reverses
+ * the bytes before transmission at each protocol level. The n_ types
+ * represent the types with the bytes in ``high-ender'' order.
+ */
+typedef u_int16_t n_short; /* short as received from the net */
+typedef u_int32_t n_long; /* long as received from the net */
+
+typedef u_int32_t n_time; /* ms since 00:00 GMT, byte rev */
+
+#ifdef KERNEL
+n_time iptime __P((void));
+#endif
+
+#endif
diff --git a/StdLib/Include/netinet/ip.h b/StdLib/Include/netinet/ip.h new file mode 100644 index 0000000000..b2de1b9779 --- /dev/null +++ b/StdLib/Include/netinet/ip.h @@ -0,0 +1,197 @@ +/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by the University of
+ * California, Berkeley, Intel Corporation, and its contributors.
+ *
+ * 4. Neither the name of University, Intel Corporation, or their respective
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS,
+ * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @(#)ip.h 8.2 (Berkeley) 6/1/94
+ * $Id: ip.h,v 1.1.1.1 2006/05/30 06:12:48 hhzhou Exp $
+ */
+
+#ifndef _NETINET_IP_H_
+#define _NETINET_IP_H_
+
+#ifndef _ORG_FREEBSD_
+#define _IP_VHL
+#endif
+
+/*
+ * Definitions for internet protocol version 4.
+ * Per RFC 791, September 1981.
+ */
+#define IPVERSION 4
+
+/*
+ * Structure of an internet header, naked of options.
+ */
+struct ip {
+#ifdef _IP_VHL
+ u_char ip_vhl; /* version << 4 | header length >> 2 */
+#else
+#if BYTE_ORDER == LITTLE_ENDIAN
+ u_int ip_hl:4, /* header length */
+ ip_v:4; /* version */
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+ u_int ip_v:4, /* version */
+ ip_hl:4; /* header length */
+#endif
+#endif /* not _IP_VHL */
+ u_char ip_tos; /* type of service */
+ u_short ip_len; /* total length */
+ u_short ip_id; /* identification */
+ u_short ip_off; /* fragment offset field */
+#define IP_RF 0x8000 /* reserved fragment flag */
+#define IP_DF 0x4000 /* dont fragment flag */
+#define IP_MF 0x2000 /* more fragments flag */
+#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
+ u_char ip_ttl; /* time to live */
+ u_char ip_p; /* protocol */
+ u_short ip_sum; /* checksum */
+ struct in_addr ip_src,ip_dst; /* source and dest address */
+};
+
+#ifdef _IP_VHL
+#define IP_MAKE_VHL(v, hl) ((v) << 4 | (hl))
+#define IP_VHL_HL(vhl) ((vhl) & 0x0f)
+#define IP_VHL_V(vhl) ((vhl) >> 4)
+#define IP_VHL_BORING 0x45
+#endif
+
+#define IP_MAXPACKET 65535 /* maximum packet size */
+
+/*
+ * Definitions for IP type of service (ip_tos)
+ */
+#define IPTOS_LOWDELAY 0x10
+#define IPTOS_THROUGHPUT 0x08
+#define IPTOS_RELIABILITY 0x04
+#define IPTOS_MINCOST 0x02
+
+/*
+ * Definitions for IP precedence (also in ip_tos) (hopefully unused)
+ */
+#define IPTOS_PREC_NETCONTROL 0xe0
+#define IPTOS_PREC_INTERNETCONTROL 0xc0
+#define IPTOS_PREC_CRITIC_ECP 0xa0
+#define IPTOS_PREC_FLASHOVERRIDE 0x80
+#define IPTOS_PREC_FLASH 0x60
+#define IPTOS_PREC_IMMEDIATE 0x40
+#define IPTOS_PREC_PRIORITY 0x20
+#define IPTOS_PREC_ROUTINE 0x00
+
+/*
+ * Definitions for options.
+ */
+#define IPOPT_COPIED(o) ((o)&0x80)
+#define IPOPT_CLASS(o) ((o)&0x60)
+#define IPOPT_NUMBER(o) ((o)&0x1f)
+
+#define IPOPT_CONTROL 0x00
+#define IPOPT_RESERVED1 0x20
+#define IPOPT_DEBMEAS 0x40
+#define IPOPT_RESERVED2 0x60
+
+#define IPOPT_EOL 0 /* end of option list */
+#define IPOPT_NOP 1 /* no operation */
+
+#define IPOPT_RR 7 /* record packet route */
+#define IPOPT_TS 68 /* timestamp */
+#define IPOPT_SECURITY 130 /* provide s,c,h,tcc */
+#define IPOPT_LSRR 131 /* loose source route */
+#define IPOPT_SATID 136 /* satnet id */
+#define IPOPT_SSRR 137 /* strict source route */
+#define IPOPT_RA 148 /* router alert */
+
+/*
+ * Offsets to fields in options other than EOL and NOP.
+ */
+#define IPOPT_OPTVAL 0 /* option ID */
+#define IPOPT_OLEN 1 /* option length */
+#define IPOPT_OFFSET 2 /* offset within option */
+#define IPOPT_MINOFF 4 /* min value of above */
+
+/*
+ * Time stamp option structure.
+ */
+struct ip_timestamp {
+ u_char ipt_code; /* IPOPT_TS */
+ u_char ipt_len; /* size of structure (variable) */
+ u_char ipt_ptr; /* index of current entry */
+#if BYTE_ORDER == LITTLE_ENDIAN
+ u_int ipt_flg:4, /* flags, see below */
+ ipt_oflw:4; /* overflow counter */
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+ u_int ipt_oflw:4, /* overflow counter */
+ ipt_flg:4; /* flags, see below */
+#endif
+ union ipt_timestamp {
+ n_long ipt_time[1];
+ struct ipt_ta {
+ struct in_addr ipt_addr;
+ n_long ipt_time;
+ } ipt_ta[1];
+ } ipt_timestamp;
+};
+
+/* flag bits for ipt_flg */
+#define IPOPT_TS_TSONLY 0 /* timestamps only */
+#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
+#define IPOPT_TS_PRESPEC 3 /* specified modules only */
+
+/* bits for security (not byte swapped) */
+#define IPOPT_SECUR_UNCLASS 0x0000
+#define IPOPT_SECUR_CONFID 0xf135
+#define IPOPT_SECUR_EFTO 0x789a
+#define IPOPT_SECUR_MMMM 0xbc4d
+#define IPOPT_SECUR_RESTR 0xaf13
+#define IPOPT_SECUR_SECRET 0xd788
+#define IPOPT_SECUR_TOPSECRET 0x6bc5
+
+/*
+ * Internet implementation parameters.
+ */
+#define MAXTTL 255 /* maximum time to live (seconds) */
+#define IPDEFTTL 64 /* default ttl, from RFC 1340 */
+#define IPFRAGTTL 60 /* time to live for frags, slowhz */
+#define IPTTLDEC 1 /* subtracted when forwarding */
+
+#define IP_MSS 576 /* default maximum segment size */
+
+#endif
diff --git a/StdLib/Include/netns/ns.h b/StdLib/Include/netns/ns.h new file mode 100644 index 0000000000..58bac08301 --- /dev/null +++ b/StdLib/Include/netns/ns.h @@ -0,0 +1,157 @@ +/*
+ * Copyright (c) 1984, 1985, 1986, 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ns.h 8.1 (Berkeley) 6/10/93
+ * $Id: ns.h,v 1.1.1.1 2003/11/19 01:48:56 kyu3 Exp $
+ */
+
+#ifndef _NETNS_NS_H_
+#define _NETNS_NS_H_
+
+/*
+ * Constants and Structures defined by the Xerox Network Software
+ * per "Internet Transport Protocols", XSIS 028112, December 1981
+ */
+
+/*
+ * Protocols
+ */
+#define NSPROTO_RI 1 /* Routing Information */
+#define NSPROTO_ECHO 2 /* Echo Protocol */
+#define NSPROTO_ERROR 3 /* Error Protocol */
+#define NSPROTO_PE 4 /* Packet Exchange */
+#define NSPROTO_SPP 5 /* Sequenced Packet */
+#define NSPROTO_RAW 255 /* Placemarker*/
+#define NSPROTO_MAX 256 /* Placemarker*/
+
+
+/*
+ * Port/Socket numbers: network standard functions
+ */
+
+#define NSPORT_RI 1 /* Routing Information */
+#define NSPORT_ECHO 2 /* Echo */
+#define NSPORT_RE 3 /* Router Error */
+
+/*
+ * Ports < NSPORT_RESERVED are reserved for priveleged
+ * processes (e.g. root).
+ */
+#define NSPORT_RESERVED 3000
+
+/* flags passed to ns_output as last parameter */
+
+#define NS_FORWARDING 0x1 /* most of idp header exists */
+#define NS_ROUTETOIF 0x10 /* same as SO_DONTROUTE */
+#define NS_ALLOWBROADCAST SO_BROADCAST /* can send broadcast packets */
+
+#define NS_MAXHOPS 15
+
+/* flags passed to get/set socket option */
+#define SO_HEADERS_ON_INPUT 1
+#define SO_HEADERS_ON_OUTPUT 2
+#define SO_DEFAULT_HEADERS 3
+#define SO_LAST_HEADER 4
+#define SO_NSIP_ROUTE 5
+#define SO_SEQNO 6
+#define SO_ALL_PACKETS 7
+#define SO_MTU 8
+
+
+/*
+ * NS addressing
+ */
+union ns_host {
+ u_char c_host[6];
+ u_short s_host[3];
+};
+
+union ns_net {
+ u_char c_net[4];
+ u_short s_net[2];
+};
+
+union ns_net_u {
+ union ns_net net_e;
+ u_long long_e;
+};
+
+struct ns_addr {
+ union ns_net x_net;
+ union ns_host x_host;
+ u_short x_port;
+};
+
+/*
+ * Socket address, Xerox style
+ */
+struct sockaddr_ns {
+ u_char sns_len;
+ u_char sns_family;
+ struct ns_addr sns_addr;
+ char sns_zero[2];
+};
+#define sns_port sns_addr.x_port
+
+#ifdef vax
+#define ns_netof(a) (*(long *) & ((a).x_net)) /* XXX - not needed */
+#endif
+#define ns_neteqnn(a,b) (((a).s_net[0]==(b).s_net[0]) && \
+ ((a).s_net[1]==(b).s_net[1]))
+#define ns_neteq(a,b) ns_neteqnn((a).x_net, (b).x_net)
+#define satons_addr(sa) (((struct sockaddr_ns *)&(sa))->sns_addr)
+#define ns_hosteqnh(s,t) ((s).s_host[0] == (t).s_host[0] && \
+ (s).s_host[1] == (t).s_host[1] && (s).s_host[2] == (t).s_host[2])
+#define ns_hosteq(s,t) (ns_hosteqnh((s).x_host,(t).x_host))
+#define ns_nullhost(x) (((x).x_host.s_host[0]==0) && \
+ ((x).x_host.s_host[1]==0) && ((x).x_host.s_host[2]==0))
+
+#ifdef KERNEL
+extern struct domain nsdomain;
+union ns_host ns_thishost;
+union ns_host ns_zerohost;
+union ns_host ns_broadhost;
+union ns_net ns_zeronet;
+union ns_net ns_broadnet;
+u_short ns_cksum();
+#else
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+extern struct ns_addr ns_addr (const char *);
+extern char *ns_ntoa (struct ns_addr);
+__END_DECLS
+
+#endif
+
+#endif
diff --git a/StdLib/Include/paths.h b/StdLib/Include/paths.h index 389272f0d9..d70e8dd885 100644 --- a/StdLib/Include/paths.h +++ b/StdLib/Include/paths.h @@ -45,6 +45,19 @@ //#define _PATH_DEFPATH "/usr/bin:/bin:/usr/pkg/bin:/usr/local/bin"
//#endif
+/*
+ * Provide trailing slash, since mostly used for building pathnames.
+ * see the __CONCAT() macro from <sys/EfiCdefs.h> for cpp examples.
+ */
+#define _PATH_DEV "/dev/"
+#define _PATH_ETC "/Efi/etc/"
+#define _PATH_TMP "/Efi/Temp/"
+//#define _PATH_DEV_PTS "/dev/pts/"
+//#define _PATH_EMUL_AOUT "/emul/aout/"
+//#define _PATH_VARDB "/var/db/"
+//#define _PATH_VARRUN "/var/run/"
+//#define _PATH_VARTMP "/var/tmp/"
+
///*
// * All standard utilities path.
// * set by init(8) for system programs & scripts (e.g. /etc/rc)
@@ -97,33 +110,34 @@ #define _PATH_SOCKET "socket:"
// *nix style device paths
-#define _PATH_DEVTTY "/dev/tty"
-#define _PATH_DEVNULL "/dev/null"
-#define _PATH_DEVCONSOLE "/dev/console"
-#define _PATH_DEVCONSTTY "/dev/constty"
-#define _PATH_DEVSTDIN "/dev/stdin"
-#define _PATH_DEVSTDOUT "/dev/stdout"
-#define _PATH_DEVSTDERR "/dev/stderr"
-#define _PATH_DEVSOCKET "/dev/socket"
+#define _PATH_DEVTTY _PATH_DEV "tty"
+#define _PATH_DEVNULL _PATH_DEV "null"
+#define _PATH_DEVCONSOLE _PATH_DEV "console"
+#define _PATH_DEVCONSTTY _PATH_DEV "constty"
+#define _PATH_DEVSTDIN _PATH_DEV "stdin"
+#define _PATH_DEVSTDOUT _PATH_DEV "stdout"
+#define _PATH_DEVSTDERR _PATH_DEV "stderr"
+#define _PATH_DEVSOCKET _PATH_DEV "socket"
// Special files and locations
-#define _PATH_HOSTS "/Efi/etc/hosts"
-#define _PATH_SERVICES "/Efi/etc/services"
-#define _PATH_HOSTNAME "/Efi/etc/hostname"
-#define _PATH_LOCALE "/Efi/etc/Locale"
-#define _PATH_FSTAB "/Efi/etc/fstab"
+#define _PATH_FSTAB _PATH_ETC "fstab"
+////#define _PATH_HEQUIV _PATH_ETC "hosts.equiv"
+#define _PATH_HOSTNAME _PATH_ETC "hostname"
+#define _PATH_HOSTS _PATH_ETC "hosts"
+#define _PATH_HOSTCONF _PATH_ETC "host.conf"
+#define _PATH_LOCALE _PATH_ETC "Locale"
+#define _PATH_NETCONF _PATH_ETC "host.conf"
+#define _PATH_NETWORKS _PATH_ETC "networks"
+#define _PATH_PROTOCOLS _PATH_ETC "protocols"
/*
- * Provide trailing slash, since mostly used for building pathnames.
- * see the __CONCAT() macro from <sys/EfiCdefs.h> for cpp examples.
+ * Resolver configuration file.
+ * Normally not present, but may contain the address of the
+ * inital name server(s) to query and the domain search list.
*/
-#define _PATH_DEV "/dev/"
-#define _PATH_TMP "/Efi/Temp/"
-//#define _PATH_DEV_PTS "/dev/pts/"
-//#define _PATH_EMUL_AOUT "/emul/aout/"
-//#define _PATH_VARDB "/var/db/"
-//#define _PATH_VARRUN "/var/run/"
-//#define _PATH_VARTMP "/var/tmp/"
+#define _PATH_RESCONF _PATH_ETC "resolv.conf"
+#define _PATH_SERVICES _PATH_ETC "services"
+////#define _PATH_SERVICES_DB "/Efi/var/db/services.db"
//#define _PATH_BSHELL RESCUEDIR "/sh"
//#define _PATH_CSHELL RESCUEDIR "/csh"
diff --git a/StdLib/Include/pwd.h b/StdLib/Include/pwd.h new file mode 100644 index 0000000000..afbae1589e --- /dev/null +++ b/StdLib/Include/pwd.h @@ -0,0 +1,145 @@ +/* $NetBSD: pwd.h,v 1.39 2005/05/24 17:36:29 kleink Exp $ */
+
+/*-
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)pwd.h 8.2 (Berkeley) 1/21/94
+ */
+
+/*-
+ * Portions Copyright(C) 1995, Jason Downs. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _PWD_H_
+#define _PWD_H_
+
+#include <sys/EfiCdefs.h>
+#include <sys/featuretest.h>
+#include <sys/types.h>
+
+#define _PATH_PASSWD "/etc/passwd"
+#define _PATH_MASTERPASSWD "/etc/master.passwd"
+#define _PATH_MASTERPASSWD_LOCK "/etc/ptmp"
+
+#define _PATH_PASSWD_CONF "/etc/passwd.conf"
+#define _PATH_PASSWDCONF _PATH_PASSWD_CONF /* XXX: compat */
+#define _PATH_USERMGMT_CONF "/etc/usermgmt.conf"
+
+#define _PATH_MP_DB "/etc/pwd.db"
+#define _PATH_SMP_DB "/etc/spwd.db"
+
+#define _PATH_PWD_MKDB "/usr/sbin/pwd_mkdb"
+
+#define _PW_KEYBYNAME '1' /* stored by name */
+#define _PW_KEYBYNUM '2' /* stored by entry in the "file" */
+#define _PW_KEYBYUID '3' /* stored by uid */
+
+#define _PASSWORD_EFMT1 '_' /* extended DES encryption format */
+#define _PASSWORD_NONDES '$' /* non-DES encryption formats */
+
+#define _PASSWORD_LEN 128 /* max length, not counting NUL */
+
+#define _PASSWORD_NOUID 0x01 /* flag for no specified uid. */
+#define _PASSWORD_NOGID 0x02 /* flag for no specified gid. */
+#define _PASSWORD_NOCHG 0x04 /* flag for no specified change. */
+#define _PASSWORD_NOEXP 0x08 /* flag for no specified expire. */
+
+#define _PASSWORD_OLDFMT 0x10 /* flag to expect an old style entry */
+#define _PASSWORD_NOWARN 0x20 /* no warnings for bad entries */
+
+#define _PASSWORD_WARNDAYS 14 /* days to warn about expiry */
+#define _PASSWORD_CHGNOW -1 /* special day to force password
+ * change at next login */
+
+struct passwd {
+ __aconst char *pw_name; /* user name */
+ __aconst char *pw_passwd; /* encrypted password */
+ uid_t pw_uid; /* user uid */
+ gid_t pw_gid; /* user gid */
+ time_t pw_change; /* password change time */
+ __aconst char *pw_class; /* user login class */
+ __aconst char *pw_gecos; /* general information */
+ __aconst char *pw_dir; /* home directory */
+ __aconst char *pw_shell; /* default shell */
+ time_t pw_expire; /* account expiration */
+};
+
+__BEGIN_DECLS
+ struct passwd *getpwuid(uid_t);
+ struct passwd *getpwnam(const char *);
+
+#if 0 /* Normally declared here but not implemented for UEFI. */
+
+ int getpwnam_r( const char *, struct passwd *, char *, size_t,
+ struct passwd **);
+ int getpwuid_r( uid_t, struct passwd *, char *, size_t,
+ struct passwd **);
+
+ struct passwd *getpwent(void);
+ void setpwent(void);
+ void endpwent(void);
+
+ int pw_gensalt(char *, size_t, const char *, const char *);
+ int pw_scan(char *, struct passwd *, int *);
+ int setpassent(int);
+ int getpwent_r(struct passwd *, char *, size_t, struct passwd **);
+ const char *user_from_uid(uid_t, int);
+ int uid_from_user(const char *, uid_t *);
+ int pwcache_userdb( int (*)(int), void (*)(void),
+ struct passwd * (*)(const char *),
+ struct passwd * (*)(uid_t));
+#endif
+__END_DECLS
+
+#endif /* !_PWD_H_ */
diff --git a/StdLib/Include/resolv.h b/StdLib/Include/resolv.h new file mode 100644 index 0000000000..818a0ea07f --- /dev/null +++ b/StdLib/Include/resolv.h @@ -0,0 +1,293 @@ +/*-
+ * Copyright (c) 1983, 1987, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * @(#)resolv.h 8.1 (Berkeley) 6/2/93
+ * From Id: resolv.h,v 8.12 1998/04/28 19:36:46 halley Exp $
+ * $Id: resolv.h,v 1.1.1.1 2003/11/19 01:48:35 kyu3 Exp $
+ */
+
+#ifndef _RESOLV_H_
+#define _RESOLV_H_
+
+#include <arpa/nameser.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/cdefs.h>
+#include <stdio.h>
+#include <paths.h>
+
+#ifndef __P
+#define __P(x) x
+#endif // __P
+
+/*
+ * Revision information. This is the release date in YYYYMMDD format.
+ * It can change every day so the right thing to do with it is use it
+ * in preprocessor commands such as "#if (__RES > 19931104)". Do not
+ * compare for equality; rather, use it to determine whether your resolver
+ * is new enough to contain a certain feature.
+ */
+
+#define __RES 19960801
+
+/*
+ * Global defines and variables for resolver stub.
+ */
+#define MAXNS 3 /* max # name servers we'll track */
+#define MAXDFLSRCH 3 /* # default domain levels to try */
+#define MAXDNSRCH 6 /* max # domains in search path */
+#define LOCALDOMAINPARTS 2 /* min levels in name that is "local" */
+
+#define RES_TIMEOUT 5 /* min. seconds between retries */
+#define MAXRESOLVSORT 10 /* number of net to sort on */
+#define RES_MAXNDOTS 15 /* should reflect bit field size */
+
+struct __res_state {
+ int retrans; /* retransmition time interval */
+ int retry; /* number of times to retransmit */
+ u_long options; /* option flags - see below. */
+ int nscount; /* number of name servers */
+ struct sockaddr_in
+ nsaddr_list[MAXNS]; /* address of name server */
+#define nsaddr nsaddr_list[0] /* for backward compatibility */
+ u_short id; /* current message id */
+ char *dnsrch[MAXDNSRCH+1]; /* components of domain to search */
+ char defdname[256]; /* default domain (deprecated) */
+ u_long pfcode; /* RES_PRF_ flags - see below. */
+ unsigned ndots:4; /* threshold for initial abs. query */
+ unsigned nsort:4; /* number of elements in sort_list[] */
+ char unused[3];
+ struct {
+ struct in_addr addr;
+ u_int32_t mask;
+ } sort_list[MAXRESOLVSORT];
+ char pad[72]; /* on an i386 this means 512b total */
+};
+
+/*
+ * Resolver options (keep these in synch with res_debug.c, please)
+ */
+#define RES_INIT 0x00000001 /* address initialized */
+#define RES_DEBUG 0x00000002 /* print debug messages */
+#define RES_AAONLY 0x00000004 /* authoritative answers only (!IMPL)*/
+#define RES_USEVC 0x00000008 /* use virtual circuit */
+#define RES_PRIMARY 0x00000010 /* query primary server only (!IMPL) */
+#define RES_IGNTC 0x00000020 /* ignore truncation errors */
+#define RES_RECURSE 0x00000040 /* recursion desired */
+#define RES_DEFNAMES 0x00000080 /* use default domain name */
+#define RES_STAYOPEN 0x00000100 /* Keep TCP socket open */
+#define RES_DNSRCH 0x00000200 /* search up local domain tree */
+#define RES_INSECURE1 0x00000400 /* type 1 security disabled */
+#define RES_INSECURE2 0x00000800 /* type 2 security disabled */
+#define RES_NOALIASES 0x00001000 /* shuts off HOSTALIASES feature */
+#define RES_USE_INET6 0x00002000 /* use/map IPv6 in gethostbyname() */
+#define RES_NOTLDQUERY 0x00004000 /* Don't query TLD names */
+
+#define RES_DEFAULT (RES_RECURSE | RES_DEFNAMES | RES_DNSRCH)
+
+/*
+ * Resolver "pfcode" values. Used by dig.
+ */
+#define RES_PRF_STATS 0x00000001
+#define RES_PRF_UPDATE 0x00000002
+#define RES_PRF_CLASS 0x00000004
+#define RES_PRF_CMD 0x00000008
+#define RES_PRF_QUES 0x00000010
+#define RES_PRF_ANS 0x00000020
+#define RES_PRF_AUTH 0x00000040
+#define RES_PRF_ADD 0x00000080
+#define RES_PRF_HEAD1 0x00000100
+#define RES_PRF_HEAD2 0x00000200
+#define RES_PRF_TTLID 0x00000400
+#define RES_PRF_HEADX 0x00000800
+#define RES_PRF_QUERY 0x00001000
+#define RES_PRF_REPLY 0x00002000
+#define RES_PRF_INIT 0x00004000
+/* 0x00008000 */
+
+typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error }
+ res_sendhookact;
+
+typedef res_sendhookact (*res_send_qhook)__P((struct sockaddr_in * const *ns,
+ const u_char **query,
+ int *querylen,
+ u_char *ans,
+ int anssiz,
+ int *resplen));
+
+typedef res_sendhookact (*res_send_rhook)__P((const struct sockaddr_in *ns,
+ const u_char *query,
+ int querylen,
+ u_char *ans,
+ int anssiz,
+ int *resplen));
+
+struct res_sym {
+ int number; /* Identifying number, like T_MX */
+ char * name; /* Its symbolic name, like "MX" */
+ char * humanname; /* Its fun name, like "mail exchanger" */
+};
+
+extern struct __res_state _res;
+extern const struct res_sym __p_class_syms[];
+extern const struct res_sym __p_type_syms[];
+
+/* Private routines shared between libc/net, named, nslookup and others. */
+#define res_hnok __res_hnok
+#define res_ownok __res_ownok
+#define res_mailok __res_mailok
+#define res_dnok __res_dnok
+#define sym_ston __sym_ston
+#define sym_ntos __sym_ntos
+#define sym_ntop __sym_ntop
+#define b64_ntop __b64_ntop
+#define b64_pton __b64_pton
+#define loc_ntoa __loc_ntoa
+#define loc_aton __loc_aton
+#define fp_resstat __fp_resstat
+#define p_query __p_query
+#define dn_skipname __dn_skipname
+#define fp_resstat __fp_resstat
+#define fp_query __fp_query
+#define fp_nquery __fp_nquery
+#define hostalias __hostalias
+#define putlong __putlong
+#define putshort __putshort
+#define p_class __p_class
+#define p_time __p_time
+#define p_type __p_type
+#define p_query __p_query
+#define p_cdnname __p_cdnname
+#define p_section __p_section
+#define p_cdname __p_cdname
+#define p_fqnname __p_fqnname
+#define p_fqname __p_fqname
+#define p_option __p_option
+#define p_secstodate __p_secstodate
+#define dn_count_labels __dn_count_labels
+#define dn_comp __dn_comp
+#define dn_expand __dn_expand
+#define res_init __res_init
+#define res_randomid __res_randomid
+#define res_query __res_query
+#define res_search __res_search
+#define res_querydomain __res_querydomain
+#define res_mkquery __res_mkquery
+#define res_send __res_send
+#define res_isourserver __res_isourserver
+#define res_nameinquery __res_nameinquery
+#define res_queriesmatch __res_queriesmatch
+#define res_close __res_close
+#define res_mkupdate __res_mkupdate
+#define res_mkupdrec __res_mkupdrec
+#define res_freeupdrec __res_freeupdrec
+
+__BEGIN_DECLS
+int res_hnok __P((const char *));
+int res_ownok __P((const char *));
+int res_mailok __P((const char *));
+int res_dnok __P((const char *));
+int sym_ston __P((const struct res_sym *, const char *, int *));
+const char * sym_ntos __P((const struct res_sym *, int, int *));
+const char * sym_ntop __P((const struct res_sym *, int, int *));
+int b64_ntop __P((u_char const *, size_t, char *, size_t));
+int b64_pton __P((char const *, u_char *, size_t));
+int loc_aton __P((const char *, u_char *));
+const char * loc_ntoa __P((const u_char *, char *));
+int dn_skipname __P((const u_char *, const u_char *));
+void fp_resstat __P((struct __res_state *, FILE *));
+void fp_query __P((const u_char *, FILE *));
+void fp_nquery __P((const u_char *, int, FILE *));
+const char * hostalias __P((const char *));
+void putlong __P((u_int32_t, u_char *));
+void putshort __P((u_int16_t, u_char *));
+const char * p_class __P((int));
+const char * p_time __P((u_int32_t));
+const char * p_type __P((int));
+void p_query __P((const u_char *));
+const u_char * p_cdnname __P((const u_char *, const u_char *, int, FILE *));
+const u_char * p_cdname __P((const u_char *, const u_char *, FILE *));
+const u_char * p_fqnname __P((const u_char *, const u_char *,
+ int, char *, int));
+const u_char * p_fqname __P((const u_char *, const u_char *, FILE *));
+const char * p_option __P((u_long));
+char * p_secstodate __P((u_long));
+int dn_count_labels __P((const char *));
+int dn_comp __P((const char *, u_char *, int,
+ u_char **, u_char **));
+int dn_expand __P((const u_char *, const u_char *, const u_char *,
+ char *, int));
+int res_init __P((void));
+u_int res_randomid __P((void));
+int res_query __P((const char *, int, int, u_char *, int));
+int res_search __P((const char *, int, int, u_char *, int));
+int res_querydomain __P((const char *, const char *, int, int,
+ u_char *, int));
+int res_mkquery __P((int, const char *, int, int, const u_char *,
+ int, const u_char *, u_char *, int));
+int res_send __P((const u_char *, int, u_char *, int));
+int res_isourserver __P((const struct sockaddr_in *));
+int res_nameinquery __P((const char *, int, int,
+ const u_char *, const u_char *));
+int res_queriesmatch __P((const u_char *, const u_char *,
+ const u_char *, const u_char *));
+void res_close __P((void));
+const char * p_section __P((int, int));
+/* XXX The following depend on the ns_updrec typedef in arpa/nameser.h */
+#ifdef _ARPA_NAMESER_H_
+int res_update __P((ns_updrec *));
+int res_mkupdate __P((ns_updrec *, u_char *, int));
+ns_updrec * res_mkupdrec __P((int, const char *, u_int, u_int, u_long));
+void res_freeupdrec __P((ns_updrec *));
+#endif
+__END_DECLS
+
+#endif /* !_RESOLV_H_ */
diff --git a/StdLib/Include/signal.h b/StdLib/Include/signal.h index a84369f310..6c1ff1b4e4 100644 --- a/StdLib/Include/signal.h +++ b/StdLib/Include/signal.h @@ -14,7 +14,7 @@ their semantics, and their default handling is implementation-defined; all
signal numbers shall be positive.
-Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
@@ -57,6 +57,14 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #define SIGSEGV __SigSegv ///< an invalid access to storage
#define SIGTERM __SigTerm ///< a termination request sent to the program
#define SIGBREAK __SigBreak ///< added for Python
+#define SIGALRM __SigAlrm ///< Added for Posix timer functions
+#define SIGVTALRM __SigVtAlrm ///< Added for Posix timer functions
+#define SIGPROF __SigProf ///< Added for Posix timer functions
+#define SIGUSR1 __SigUsr1 ///< Added for Posix timer functions
+#define SIGUSR2 __SigUsr2 ///< Added for Posix timer functions
+#define SIGWINCH __SigWinch ///< Added for Posix timer functions
+#define SIGPIPE __SigPipe ///< Added for Posix timer functions
+#define SIGQUIT __SigQuit ///< Added for Posix timer functions
#define SIG_LAST __Sig_Last ///< One more than the largest signal number
__BEGIN_DECLS
diff --git a/StdLib/Include/stdarg.h b/StdLib/Include/stdarg.h index 226e315695..b966a5ce2b 100644 --- a/StdLib/Include/stdarg.h +++ b/StdLib/Include/stdarg.h @@ -41,10 +41,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. /** The type va_list is a type suitable for holding information needed by the
macros va_start, va_arg, and va_end.
-
- This implementation aliases va_list to VA_LIST, declared in MdePkg/Base.h.
**/
+#if defined(__GNUC__)
+typedef __builtin_va_list va_list;
+#else
#define va_list VA_LIST
+#endif
/** The va_start macro shall be invoked before any access to the unnamed arguments.
The va_start macro initializes ap for subsequent use by va_arg and va_end.
@@ -63,11 +65,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. is not compatible with the type that results after
application of the default argument promotions, the
behavior is undefined.
-
- This implementation aliases va_start to VA_START, declared in MdePkg/Base.h.
**/
-//#define va_start(ap, ParamN) VA_START(ap, ParamN)
+#if defined(__GNUC__)
+#define va_start __builtin_va_start
+#else
#define va_start VA_START
+#endif
/** The va_arg macro expands to an expression that has the type and value of
the next argument in the call. The parameter ap shall be the same as the
@@ -90,11 +93,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. va_start macro returns the value of the argument after that
specified by paramN. Successive invocations return the values
of the remaining arguments in succession.
-
- This implementation aliases va_arg to VA_ARG, declared in MdePkg/Base.h.
**/
-//#define va_arg(ap, type) VA_ARG(ap, type)
+#if defined(__GNUC__)
+#define va_arg __builtin_va_arg
+#else
#define va_arg VA_ARG
+#endif
/** The va_end macro facillitates a normal return from the function whose
variable argument list was referred to by the expansion of va_start that
@@ -109,13 +113,18 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. @param ap An object of type va_list, initialized by a prior
invocation of va_start, that will no longer be referenced.
-
- This implementation aliases va_end to VA_END, declared in MdePkg/Base.h.
**/
-//#define va_end(ap) VA_END(ap)
+#if defined(__GNUC__)
+#define va_end __builtin_va_end
+#else
#define va_end VA_END
+#endif
/** For BSD compatibility. **/
+#if defined(__GNUC__)
+#define va_copy __builtin_va_copy
+#else
#define va_copy(s,d) (s) = (d)
+#endif
#endif /* _STDARG_H */
diff --git a/StdLib/Include/stdio.h b/StdLib/Include/stdio.h index 7a60a290ac..7c3586c9ab 100644 --- a/StdLib/Include/stdio.h +++ b/StdLib/Include/stdio.h @@ -36,7 +36,7 @@ #ifndef _STDIO_H_
#define _STDIO_H_
-#include <sys/EfiCdefs.h>
+#include <stdarg.h>
#include <limits.h>
#include <sys/ansi.h>
#include <machine/ansi.h>
@@ -475,14 +475,14 @@ int setvbuf (FILE * __restrict, char * __restrict, int, size_t); int sscanf (const char * __restrict, const char * __restrict, ...);
FILE *tmpfile (void);
int ungetc (int, FILE *);
-int vfprintf(FILE * __restrict, const char * __restrict, _BSD_VA_LIST_);
-int vprintf (const char * __restrict, _BSD_VA_LIST_);
+int vfprintf(FILE * __restrict, const char * __restrict, va_list);
+int vprintf (const char * __restrict, va_list);
#ifndef __AUDIT__
char *gets (char *);
int sprintf (char * __restrict, const char * __restrict, ...);
char *tmpnam (char *);
-int vsprintf(char * __restrict, const char * __restrict, _BSD_VA_LIST_);
+int vsprintf(char * __restrict, const char * __restrict, va_list);
#endif
#if defined(_POSIX_C_SOURCE) || defined(_XOPEN_SOURCE)
@@ -531,46 +531,33 @@ __END_DECLS /*
* Functions defined in POSIX 1003.2 and XPG2 or later.
*/
-#if (_POSIX_C_SOURCE - 0) >= 2 || (_XOPEN_SOURCE - 0) >= 2 || \
- defined(_NETBSD_SOURCE)
- __BEGIN_DECLS
+__BEGIN_DECLS
int pclose (FILE *);
FILE *popen (const char *, const char *);
- __END_DECLS
-#endif
+__END_DECLS
/*
* Functions defined in ISO XPG4.2, ISO C99, POSIX 1003.1-2001 or later.
*/
-#if ((__STDC_VERSION__ - 0) >= 199901L) || \
- ((_POSIX_C_SOURCE - 0) >= 200112L) || \
- (defined(_XOPEN_SOURCE) && defined(_XOPEN_SOURCE_EXTENDED)) || \
- ((_XOPEN_SOURCE - 0) >= 500) || \
- defined(_ISOC99_SOURCE) || defined(_NETBSD_SOURCE)
- __BEGIN_DECLS
+__BEGIN_DECLS
int snprintf (char * __restrict, size_t, const char * __restrict, ...)
__attribute__((__format__(__printf__, 3, 4)));
- int vsnprintf(char * __restrict, size_t, const char * __restrict, _BSD_VA_LIST_)
+ int vsnprintf(char * __restrict, size_t, const char * __restrict, va_list)
__attribute__((__format__(__printf__, 3, 0)));
- __END_DECLS
-#endif
+__END_DECLS
/*
* Functions defined in XPG4.2.
*/
-#if defined(_XOPEN_SOURCE) || defined(_NETBSD_SOURCE)
- __BEGIN_DECLS
+__BEGIN_DECLS
int getw(FILE *);
int putw(int, FILE *);
char *mkdtemp(char *);
int mkstemp(char *);
char *mktemp(char *);
- #ifndef __AUDIT__
char *tempnam(const char *, const char *);
- #endif
- __END_DECLS
-#endif
+__END_DECLS
/*
* X/Open CAE Specification Issue 5 Version 2
@@ -588,15 +575,13 @@ __END_DECLS /*
* Routines that are purely local.
*/
-#if defined(_NETBSD_SOURCE)
-
- #define FPARSELN_UNESCESC 0x01
- #define FPARSELN_UNESCCONT 0x02
- #define FPARSELN_UNESCCOMM 0x04
- #define FPARSELN_UNESCREST 0x08
- #define FPARSELN_UNESCALL 0x0f
+#define FPARSELN_UNESCESC 0x01
+#define FPARSELN_UNESCCONT 0x02
+#define FPARSELN_UNESCCOMM 0x04
+#define FPARSELN_UNESCREST 0x08
+#define FPARSELN_UNESCALL 0x0f
- __BEGIN_DECLS
+__BEGIN_DECLS
//int asprintf(char ** __restrict, const char * __restrict, ...)
// __attribute__((__format__(__printf__, 2, 3)));
char *fgetln(FILE * __restrict, size_t * __restrict);
@@ -605,33 +590,32 @@ __END_DECLS void setbuffer(FILE *, char *, int);
int setlinebuf(FILE *);
int vasprintf(char ** __restrict, const char * __restrict,
- _BSD_VA_LIST_)
+ va_list)
__attribute__((__format__(__printf__, 2, 0)));
- int vscanf(const char * __restrict, _BSD_VA_LIST_)
+ int vscanf(const char * __restrict, va_list)
__attribute__((__format__(__scanf__, 1, 0)));
int vfscanf(FILE * __restrict, const char * __restrict,
- _BSD_VA_LIST_)
+ va_list)
__attribute__((__format__(__scanf__, 2, 0)));
int vsscanf(const char * __restrict, const char * __restrict,
- _BSD_VA_LIST_)
+ va_list)
__attribute__((__format__(__scanf__, 2, 0)));
const char *fmtcheck(const char *, const char *)
__attribute__((__format_arg__(2)));
- __END_DECLS
+__END_DECLS
/*
* Stdio function-access interface.
*/
- __BEGIN_DECLS
+__BEGIN_DECLS
FILE *funopen(const void *,
int (*)(void *, char *, int),
int (*)(void *, const char *, int),
fpos_t (*)(void *, fpos_t, int),
int (*)(void *));
- __END_DECLS
+__END_DECLS
//#define fropen(cookie, fn) funopen(cookie, fn, 0, 0, 0)
//#define fwopen(cookie, fn) funopen(cookie, 0, fn, 0, 0)
-#endif /* _NETBSD_SOURCE */
/*
* Functions internal to the implementation.
@@ -646,6 +630,7 @@ __END_DECLS * define function versions in the C library.
*/
#define __sgetc(p) (--(p)->_r < 0 ? __srget(p) : (int)(*(p)->_p++))
+
#if defined(__GNUC__) && defined(__STDC__)
static __inline int __sputc(int _c, FILE *_p) {
if (--_p->_w >= 0 || (_p->_w >= _p->_lbfsize && (char)_c != '\n'))
@@ -673,33 +658,23 @@ __END_DECLS #define __sfileno(p) ((p)->_file)
#ifndef __lint__
- #if !defined(_REENTRANT) && !defined(_PTHREADS)
#define feof(p) __sfeof(p)
#define ferror(p) __sferror(p)
#define clearerr(p) __sclearerr(p)
#define getc(fp) __sgetc(fp)
#define putc(x, fp) __sputc(x, fp)
- #endif /* !_REENTRANT && !_PTHREADS */
#endif /* __lint__ */
#define getchar() getc(stdin)
#define putchar(x) putc(x, stdout)
-#if defined(_POSIX_C_SOURCE) || defined(_XOPEN_SOURCE) || \
- defined(_NETBSD_SOURCE)
- #if !defined(_REENTRANT) && !defined(_PTHREADS)
- #define fileno(p) __sfileno(p)
- #endif /* !_REENTRANT && !_PTHREADS */
-#endif /* !_ANSI_SOURCE */
+#define fileno(p) __sfileno(p)
-#if (_POSIX_C_SOURCE - 0) >= 199506L || (_XOPEN_SOURCE - 0) >= 500 || \
- defined(_REENTRANT) || defined(_NETBSD_SOURCE)
- #define getc_unlocked(fp) __sgetc(fp)
- #define putc_unlocked(x, fp) __sputc(x, fp)
+#define getc_unlocked(fp) __sgetc(fp)
+#define putc_unlocked(x, fp) __sputc(x, fp)
- #define getchar_unlocked() getc_unlocked(stdin)
- #define putchar_unlocked(x) putc_unlocked(x, stdout)
-#endif /* _POSIX_C_SOURCE >= 199506 || _XOPEN_SOURCE >= 500 || _REENTRANT... */
+#define getchar_unlocked() getc_unlocked(stdin)
+#define putchar_unlocked(x) putc_unlocked(x, stdout)
#endif /* _STDIO_H_ */
diff --git a/StdLib/Include/stdlib.h b/StdLib/Include/stdlib.h index 2cfc9fe1ff..d51d4bffd2 100644 --- a/StdLib/Include/stdlib.h +++ b/StdLib/Include/stdlib.h @@ -91,7 +91,7 @@ __BEGIN_DECLS @sa signal.h
**/
-void abort(void);
+void abort(void) __noreturn;
/** The atexit function registers the function pointed to by func, to be
called without arguments at normal program termination.
@@ -122,6 +122,10 @@ int atexit(void (*)(void)); status is zero, or EXIT_SUCCESS, status is returned unchanged. If the value
of status is EXIT_FAILURE, EAPPLICATION is returned.
Otherwise, status is returned unchanged.
+
+ While this function does not return, it can NOT be marked as "__noreturn"
+ without causing a warning to be emitted because the compilers can not
+ determine that the function truly does not return.
**/
void exit(int status) __noreturn;
@@ -140,7 +144,7 @@ void exit(int status) __noreturn; The status returned to the host environment is determined in the same way
as for the exit function.
**/
-void _Exit(int status);
+void _Exit(int status) __noreturn;
/** The getenv function searches an environment list, provided by the host
environment, for a string that matches the string pointed to by name. The
@@ -641,6 +645,42 @@ size_t mbstowcs(wchar_t * __restrict dest, const char * __restrict src, size_t **/
size_t wcstombs(char * __restrict dest, const wchar_t * __restrict src, size_t limit);
+/**
+ The realpath() function shall derive, from the pathname pointed to by
+ file_name, an absolute pathname that names the same file, whose resolution
+ does not involve '.', '..', or symbolic links. The generated pathname shall
+ be stored as a null-terminated string, up to a maximum of {PATH_MAX} bytes,
+ in the buffer pointed to by resolved_name.
+
+ If resolved_name is a null pointer, the behavior of realpath() is
+ implementation-defined.
+
+ @param[in] file_name The filename to convert.
+ @param[in,out] resolved_name The resultant name.
+
+ @retval NULL An error occured.
+ @return resolved_name.
+**/
+char * realpath(char *file_name, char *resolved_name);
+
+/**
+ The getprogname() function returns the name of the program. If the name
+ has not been set yet, it will return NULL.
+
+ @retval The name of the program.
+ @retval NULL The name has not been set.
+**/
+const char * getprogname(void);
+
+/**
+ The setprogname() function sets the name of the program.
+
+ @param[in] The name of the program. This memory must be retained
+ by the caller until no calls to "getprogname" will be
+ called.
+**/
+void setprogname(const char *progname);
+
__END_DECLS
#endif /* _STDLIB_H */
diff --git a/StdLib/Include/string.h b/StdLib/Include/string.h index 992ca0ba18..517b9e6e98 100644 --- a/StdLib/Include/string.h +++ b/StdLib/Include/string.h @@ -324,15 +324,31 @@ int strerror_r(int, char *, size_t); int strcasecmp(const char *s1, const char *s2);
void *memccpy (void *, const void *, int, size_t);
int strncasecmp(const char *s1, const char *s2, size_t n);
+size_t strlcpy(char *destination, const char *source, size_t size);
+size_t strlcat(char *destination, const char *source, size_t size);
-// bcopy is same as memcpy but it is a void function, being used in socket lib
-#define bcopy(a,b,c) ( memcpy((void *)a, (void *)b, (size_t)c))
+// bcopy is is a void function with the src/dest arguments reversed, being used in socket lib
+#define bcopy(a,b,c) ( memcpy((void *)b, (const void *)a, (size_t)c))
// bcmp is same as memcmp, returns 0 for successful compare, non-zero otherwise
#define bcmp(a,b,c) ( memcmp((void *)a, (void *)b, (size_t)c))
-//strsep is the same as strtok, the only difference is for strsep the 1st parameter is a char**
-#define strsep(a,b) (strtok(*a,b))
+/*
+ * Get next token from string *stringp, where tokens are possibly-empty
+ * strings separated by characters from delim.
+ *
+ * Writes NULs into the string at *stringp to end tokens.
+ * delim need not remain constant from call to call.
+ * On return, *stringp points past the last NUL written (if there might
+ * be further tokens), or is NULL (if there are definitely no more tokens).
+ *
+ * If *stringp is NULL, strsep returns NULL.
+ */
+char *
+strsep(
+ register char **stringp,
+ register const char *delim
+ );
__END_DECLS
diff --git a/StdLib/Include/stringlist.h b/StdLib/Include/stringlist.h new file mode 100644 index 0000000000..d0d9239355 --- /dev/null +++ b/StdLib/Include/stringlist.h @@ -0,0 +1,65 @@ +/** @file contains all the stringlist types and functions.
+
+Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+
+ * Copyright (c) 1994 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ $NetBSD: stringlist.h,v 1.7 2008/04/28 20:22:54 martin Exp $
+**/
+
+#ifndef _STRINGLIST_H
+#define _STRINGLIST_H
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+/*
+ * Simple string list
+ */
+typedef struct _stringlist {
+ char **sl_str;
+ size_t sl_max;
+ size_t sl_cur;
+} StringList;
+
+__BEGIN_DECLS
+StringList *sl_init(void);
+int sl_add(StringList *, char *);
+void sl_free(StringList *, int);
+char *sl_find(StringList *, const char *);
+int sl_delete(StringList *, const char *, int);
+__END_DECLS
+
+#endif /* _STRINGLIST_H */
diff --git a/StdLib/Include/sys/EfiCdefs.h b/StdLib/Include/sys/EfiCdefs.h index 46aaf6e744..c3a2772bfc 100644 --- a/StdLib/Include/sys/EfiCdefs.h +++ b/StdLib/Include/sys/EfiCdefs.h @@ -17,16 +17,16 @@ that the library can be easily tuned for different compilers.
__inline Defined to the appropriate keyword or not defined.
__func__ Defined to __FUNC__, __FUNCTION__, or NULL as appropriate.
- __restrict Defined to nothing for VC++ or to restrict for C99 compliant compilers.
+ __restrict Defined to nothing for VC++ or to restrict for GCC and C99 compliant compilers.
This file and its contents are inspired by the <sys/cdefs.h> files in Berkeley
Unix. They have been re-implemented to be specific to the EFI environment.
- Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php.
+ http://opensource.org/licenses/bsd-license.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
@@ -261,22 +261,7 @@ #endif
#endif /* !(__STDC_VERSION__ >= 199901L) */
-// <DVM 12/21/2010> Experiment to disable RENAME for GCC
-#if 0
-#ifdef __GNUC__
- #define __RENAME(x) ___RENAME(x)
-#else
- #ifdef __lint__
- #define __RENAME(x) __symbolrename(x)
- #else
- /*DVM To see where this might be used... */
- //#error "No function renaming possible"
- #define __RENAME(x)
- #endif /* __lint__ */
-#endif /* __GNUC__ */
-#else /* if 0 */
- #define __RENAME(x)
-#endif /* if 0 */
+#define __RENAME(x)
/*
* A barrier to stop the optimizer from moving code or assume live
@@ -362,6 +347,4 @@ typedef UINT32 ULONG32; typedef INT64 LONG64;
typedef UINT64 ULONG64;
-//extern int EFIAPI main();
-
#endif /* _EFI_CDEFS_H */
diff --git a/StdLib/Include/sys/EfiSysCall.h b/StdLib/Include/sys/EfiSysCall.h index 7b299108e6..a49eeda1fc 100644 --- a/StdLib/Include/sys/EfiSysCall.h +++ b/StdLib/Include/sys/EfiSysCall.h @@ -75,7 +75,7 @@ int isatty (int); int fstat (int, struct stat *);
int lstat (const char *, struct stat *);
int stat (const char *, void *);
-// int chmod (const char *, mode_t);
+ int chmod (const char *, mode_t);
#endif // __STAT_SYSCALLS_DECLARED
// These are also declared in sys/types.h
@@ -110,10 +110,11 @@ int FindFreeFD (int MinFd); */
BOOLEAN ValidateFD (int fd, int IsOpen);
+char *getcwd (char *, size_t);
+int chdir (const char *);
+
/* These system calls don't YET have EFI implementations. */
int access (const char *path, int amode);
-int chdir (const char *);
-char *getcwd (char *, size_t);
int reboot (int, char *);
__END_DECLS
diff --git a/StdLib/Include/sys/_posix.h b/StdLib/Include/sys/_posix.h new file mode 100644 index 0000000000..706cf7edb4 --- /dev/null +++ b/StdLib/Include/sys/_posix.h @@ -0,0 +1,97 @@ +#ifndef _SYS__POSIX_H_
+#define _SYS__POSIX_H_
+
+/*-
+ * Copyright (c) 1998 HD Associates, Inc.
+ * All rights reserved.
+ * contact: dufault@hda.com
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: _posix.h,v 1.1.1.1 2006/05/30 06:13:04 hhzhou Exp $
+ */
+
+/*
+ * This is a stand alone header file to set up for feature specification
+ * defined to take place before the inclusion of any standard header.
+ * It should only handle pre-processor defines.
+ *
+ * See section B.2.7 of 1003.1b-1993
+ *
+ */
+
+#ifdef KERNEL
+
+#if !defined(ACTUALLY_LKM_NOT_KERNEL) && !defined(KLD_MODULE)
+#include "opt_posix.h"
+#endif
+
+/* Only kern_mib.c uses _POSIX_VERSION. Introduce a kernel
+ * one to avoid other pieces of the kernel getting dependant
+ * on that.
+ * XXX Complain if you think this dumb.
+ */
+
+/* Make P1003 structures visible for the kernel if
+ * the P1003_1B option is in effect.
+ */
+#ifdef P1003_1B
+#define _P1003_1B_VISIBLE
+#ifndef _KPOSIX_VERSION
+#define _KPOSIX_VERSION 199309L
+#endif
+#endif
+
+#ifndef _KPOSIX_VERSION
+#define _KPOSIX_VERSION 199009L
+#endif
+
+#define _P1003_1B_VISIBLE_HISTORICALLY
+
+#else
+
+/* Default to existing user space version.
+ */
+#ifndef _POSIX_VERSION
+#define _POSIX_VERSION 199009L
+#endif
+
+/* Test for visibility of P1003.1B features:
+ * If _POSIX_SOURCE and POSIX_C_SOURCE are completely undefined
+ * they show up.
+ *
+ * If they specify a version including P1003.1B then they show up.
+ *
+ * (Two macros are added to permit hiding new extensions while
+ * keeping historic BSD features - that is not done now)
+ *
+ */
+
+#if (!defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE)) || \
+ (_POSIX_VERSION >= 199309L && defined(_POSIX_C_SOURCE) && \
+ _POSIX_C_SOURCE >= 199309L)
+#define _P1003_1B_VISIBLE
+#define _P1003_1B_VISIBLE_HISTORICALLY
+#endif
+
+#endif /* not KERNEL */
+#endif /* _SYS__POSIX_H_ */
diff --git a/StdLib/Include/sys/cdefs_aout.h b/StdLib/Include/sys/cdefs_aout.h index c7920a02b1..0ce4fd9d2d 100644 --- a/StdLib/Include/sys/cdefs_aout.h +++ b/StdLib/Include/sys/cdefs_aout.h @@ -11,12 +11,7 @@ #define _C_LABEL(x) __CONCAT(_,x)
#define _C_LABEL_STRING(x) "_"x
-#if __STDC__
-#define ___RENAME(x) __asm(___STRING(_C_LABEL(x)))
-#else
-#define ___RENAME(x) ____RENAME(_/**/x)
-#define ____RENAME(x) __asm(___STRING(x))
-#endif
+#define ___RENAME(x)
#define __indr_reference(sym,alias) /* nada, since we do weak refs */
diff --git a/StdLib/Include/sys/file.h b/StdLib/Include/sys/file.h new file mode 100644 index 0000000000..cce35f1637 --- /dev/null +++ b/StdLib/Include/sys/file.h @@ -0,0 +1,102 @@ +/*
+ * Copyright (c) 1982, 1986, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)file.h 8.3 (Berkeley) 1/9/95
+ * $Id: file.h,v 1.1.1.1 2006/05/30 06:12:53 hhzhou Exp $
+ */
+
+#ifndef _SYS_FILE_H_
+#define _SYS_FILE_H_
+
+#ifndef KERNEL
+#include <sys/fcntl.h>
+#include <sys/unistd.h>
+#endif
+
+#ifdef KERNEL
+#include <sys/queue.h>
+
+struct proc;
+struct uio;
+
+/*
+ * Kernel descriptor table.
+ * One entry for each open kernel vnode and socket.
+ */
+struct file {
+ LIST_ENTRY(file) f_list;/* list of active files */
+ short f_flag; /* see fcntl.h */
+#define DTYPE_VNODE 1 /* file */
+#define DTYPE_SOCKET 2 /* communications endpoint */
+#define DTYPE_PIPE 3 /* pipe */
+#define DTYPE_FIFO 4 /* fifo (named pipe) */
+ short f_type; /* descriptor type */
+ short f_count; /* reference count */
+ short f_msgcount; /* references from message queue */
+ struct ucred *f_cred; /* credentials associated with descriptor */
+ struct fileops {
+ int (*fo_read) __P((struct file *fp, struct uio *uio,
+ struct ucred *cred, int flags));
+ int (*fo_write) __P((struct file *fp, struct uio *uio,
+ struct ucred *cred, int flags));
+#define FOF_OFFSET 1
+ int (*fo_ioctl) __P((struct file *fp, u_long com,
+ caddr_t data, struct proc *p));
+ int (*fo_poll) __P((struct file *fp, int events,
+ struct ucred *cred, struct proc *p));
+ int (*fo_close) __P((struct file *fp, struct proc *p));
+ } *f_ops;
+ int f_seqcount; /*
+ * count of sequential accesses -- cleared
+ * by most seek operations.
+ */
+ off_t f_nextread; /*
+ * offset of next expected read
+ */
+ off_t f_offset;
+ caddr_t f_data; /* vnode or socket */
+};
+
+#ifdef MALLOC_DECLARE
+MALLOC_DECLARE(M_FILE);
+#endif
+
+LIST_HEAD(filelist, file);
+extern struct filelist filehead; /* head of list of open files */
+extern struct fileops vnops;
+extern int maxfiles; /* kernel limit on number of open files */
+extern int maxfilesperproc; /* per process limit on number of open files */
+extern int nfiles; /* actual number of open files */
+
+#endif /* KERNEL */
+
+#endif /* !SYS_FILE_H */
diff --git a/StdLib/Include/sys/select.h b/StdLib/Include/sys/select.h index e1e5de1d5f..5166a0552f 100644 --- a/StdLib/Include/sys/select.h +++ b/StdLib/Include/sys/select.h @@ -38,6 +38,7 @@ #include <sys/fd_set.h>
#include <sys/sigtypes.h>
+#include <sys/time.h>
#include <time.h>
__BEGIN_DECLS
diff --git a/StdLib/Include/sys/signal.h b/StdLib/Include/sys/signal.h index e945a62bfe..6f21fcd0a2 100644 --- a/StdLib/Include/sys/signal.h +++ b/StdLib/Include/sys/signal.h @@ -1,5 +1,5 @@ /**
-Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
@@ -22,6 +22,14 @@ enum { __SigSegv,
__SigTerm,
__SigBreak,
+ __SigAlrm,
+ __SigVtAlrm,
+ __SigProf,
+ __SigUsr1,
+ __SigUsr2,
+ __SigWinch,
+ __SigPipe,
+ __SigQuit,
__Sig_Last
};
diff --git a/StdLib/Include/sys/sockio.h b/StdLib/Include/sys/sockio.h new file mode 100644 index 0000000000..5711ed2014 --- /dev/null +++ b/StdLib/Include/sys/sockio.h @@ -0,0 +1,100 @@ +/*-
+ * Copyright (c) 1982, 1986, 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by the University of
+ * California, Berkeley, Intel Corporation, and its contributors.
+ *
+ * 4. Neither the name of University, Intel Corporation, or their respective
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS,
+ * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @(#)sockio.h 8.1 (Berkeley) 3/28/94
+ * $Id: sockio.h,v 1.1.1.1 2006/05/30 06:12:59 hhzhou Exp $
+ */
+
+#ifndef _SYS_SOCKIO_H_
+#define _SYS_SOCKIO_H_
+
+#include <sys/ioccom.h>
+
+/* Socket ioctl's. */
+#define SIOCSHIWAT _IOW('s', 0, int) /* set high watermark */
+#define SIOCGHIWAT _IOR('s', 1, int) /* get high watermark */
+#define SIOCSLOWAT _IOW('s', 2, int) /* set low watermark */
+#define SIOCGLOWAT _IOR('s', 3, int) /* get low watermark */
+#define SIOCATMARK _IOR('s', 7, int) /* at oob mark? */
+#define SIOCSPGRP _IOW('s', 8, int) /* set process group */
+#define SIOCGPGRP _IOR('s', 9, int) /* get process group */
+#ifndef _ORG_FREEBSD_
+#define SIOCUPCALL _IOW('s', 10, struct upcall_req)/* register upcall req */
+#endif
+
+#define SIOCADDRT _IOW('r', 10, struct ortentry) /* add route */
+#define SIOCDELRT _IOW('r', 11, struct ortentry) /* delete route */
+#define SIOCGETVIFCNT _IOWR('r', 15, struct sioc_vif_req)/* get vif pkt cnt */
+#define SIOCGETSGCNT _IOWR('r', 16, struct sioc_sg_req) /* get s,g pkt cnt */
+
+#define SIOCSIFADDR _IOW('i', 12, struct ifreq) /* set ifnet address */
+#define OSIOCGIFADDR _IOWR('i', 13, struct ifreq) /* get ifnet address */
+#define SIOCGIFADDR _IOWR('i', 33, struct ifreq) /* get ifnet address */
+#define SIOCSIFDSTADDR _IOW('i', 14, struct ifreq) /* set p-p address */
+#define OSIOCGIFDSTADDR _IOWR('i', 15, struct ifreq) /* get p-p address */
+#define SIOCGIFDSTADDR _IOWR('i', 34, struct ifreq) /* get p-p address */
+#define SIOCSIFFLAGS _IOW('i', 16, struct ifreq) /* set ifnet flags */
+#define SIOCGIFFLAGS _IOWR('i', 17, struct ifreq) /* get ifnet flags */
+#define OSIOCGIFBRDADDR _IOWR('i', 18, struct ifreq) /* get broadcast addr */
+#define SIOCGIFBRDADDR _IOWR('i', 35, struct ifreq) /* get broadcast addr */
+#define SIOCSIFBRDADDR _IOW('i', 19, struct ifreq) /* set broadcast addr */
+#define OSIOCGIFCONF _IOWR('i', 20, struct ifconf) /* get ifnet list */
+#define SIOCGIFCONF _IOWR('i', 36, struct ifconf) /* get ifnet list */
+#define OSIOCGIFNETMASK _IOWR('i', 21, struct ifreq) /* get net addr mask */
+#define SIOCGIFNETMASK _IOWR('i', 37, struct ifreq) /* get net addr mask */
+#define SIOCSIFNETMASK _IOW('i', 22, struct ifreq) /* set net addr mask */
+#define SIOCGIFMETRIC _IOWR('i', 23, struct ifreq) /* get IF metric */
+#define SIOCSIFMETRIC _IOW('i', 24, struct ifreq) /* set IF metric */
+#define SIOCDIFADDR _IOW('i', 25, struct ifreq) /* delete IF addr */
+#define SIOCAIFADDR _IOW('i', 26, struct ifaliasreq)/* add/chg IF alias */
+
+#define SIOCADDMULTI _IOW('i', 49, struct ifreq) /* add m'cast addr */
+#define SIOCDELMULTI _IOW('i', 50, struct ifreq) /* del m'cast addr */
+#define SIOCGIFMTU _IOWR('i', 51, struct ifreq) /* get IF mtu */
+#define SIOCSIFMTU _IOW('i', 52, struct ifreq) /* set IF mtu */
+#define SIOCGIFPHYS _IOWR('i', 53, struct ifreq) /* get IF wire */
+#define SIOCSIFPHYS _IOW('i', 54, struct ifreq) /* set IF wire */
+#define SIOCSIFMEDIA _IOWR('i', 55, struct ifreq) /* set net media */
+#define SIOCGIFMEDIA _IOWR('i', 56, struct ifmediareq) /* get net media */
+#define SIOCSIFGENERIC _IOW('i', 57, struct ifreq) /* generic IF set op */
+#define SIOCGIFGENERIC _IOWR('i', 58, struct ifreq) /* generic IF get op */
+
+#endif /* !_SYS_SOCKIO_H_ */
diff --git a/StdLib/Include/sys/stat.h b/StdLib/Include/sys/stat.h index 47e993b8be..b87f3f12e6 100644 --- a/StdLib/Include/sys/stat.h +++ b/StdLib/Include/sys/stat.h @@ -210,7 +210,7 @@ __BEGIN_DECLS extern int fstat (int, struct stat *);
extern int lstat (const char *, struct stat *);
extern int stat (const char *, void *);
-// extern int chmod (const char *, mode_t);
+ extern int chmod (const char *, mode_t);
#endif // __STAT_SYSCALLS_DECLARED
__END_DECLS
diff --git a/StdLib/Include/sys/sysctl.h b/StdLib/Include/sys/sysctl.h new file mode 100644 index 0000000000..2382900bae --- /dev/null +++ b/StdLib/Include/sys/sysctl.h @@ -0,0 +1,505 @@ +/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Karels at Berkeley Software Design, Inc.
+ *
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by the University of
+ * California, Berkeley, Intel Corporation, and its contributors.
+ *
+ * 4. Neither the name of University, Intel Corporation, or their respective
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS,
+ * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @(#)sysctl.h 8.1 (Berkeley) 6/2/93
+ * $Id: sysctl.h,v 1.1.1.1 2006/05/30 06:13:00 hhzhou Exp $
+ */
+
+#ifndef _SYS_SYSCTL_H_
+#define _SYS_SYSCTL_H_
+
+#include <sys/_posix.h>
+
+/*
+ * Definitions for sysctl call. The sysctl call uses a hierarchical name
+ * for objects that can be examined or modified. The name is expressed as
+ * a sequence of integers. Like a file path name, the meaning of each
+ * component depends on its place in the hierarchy. The top-level and kern
+ * identifiers are defined here, and other identifiers are defined in the
+ * respective subsystem header files.
+ */
+
+#define CTL_MAXNAME 12 /* largest number of components supported */
+
+/*
+ * Each subsystem defined by sysctl defines a list of variables
+ * for that subsystem. Each name is either a node with further
+ * levels defined below it, or it is a leaf of some particular
+ * type given below. Each sysctl level defines a set of name/type
+ * pairs to be used by sysctl(1) in manipulating the subsystem.
+ */
+struct ctlname {
+ char *ctl_name; /* subsystem name */
+ int ctl_type; /* type of name */
+};
+
+#define CTLTYPE 0xf /* Mask for the type */
+#define CTLTYPE_NODE 1 /* name is a node */
+#define CTLTYPE_INT 2 /* name describes an integer */
+#define CTLTYPE_STRING 3 /* name describes a string */
+#define CTLTYPE_QUAD 4 /* name describes a 64-bit number */
+#define CTLTYPE_OPAQUE 5 /* name describes a structure */
+#define CTLTYPE_STRUCT CTLTYPE_OPAQUE /* name describes a structure */
+
+#define CTLFLAG_RD 0x80000000 /* Allow reads of variable */
+#define CTLFLAG_WR 0x40000000 /* Allow writes to the variable */
+#define CTLFLAG_RW (CTLFLAG_RD|CTLFLAG_WR)
+#define CTLFLAG_NOLOCK 0x20000000 /* XXX Don't Lock */
+#define CTLFLAG_ANYBODY 0x10000000 /* All users can set this var */
+#define CTLFLAG_SECURE 0x08000000 /* Permit set only if securelevel<=0 */
+
+/*
+ * USE THIS instead of a hardwired number from the categories below
+ * to get dynamically assigned sysctl entries using the linker-set
+ * technology. This is the way nearly all new sysctl variables should
+ * be implemented.
+ * e.g. SYSCTL_INT(_parent, OID_AUTO, name, CTLFLAG_RW, &variable, 0, "");
+ */
+#define OID_AUTO (-1)
+
+#ifdef KERNEL
+#define SYSCTL_HANDLER_ARGS (struct sysctl_oid *oidp, void *arg1, int arg2, \
+ struct sysctl_req *req)
+
+/*
+ * This describes the access space for a sysctl request. This is needed
+ * so that we can use the interface from the kernel or from user-space.
+ */
+struct sysctl_req {
+ struct proc *p;
+ int lock;
+ void *oldptr;
+ size_t oldlen;
+ size_t oldidx;
+ int (*oldfunc)(struct sysctl_req *, const void *, size_t);
+ void *newptr;
+ size_t newlen;
+ size_t newidx;
+ int (*newfunc)(struct sysctl_req *, void *, size_t);
+};
+
+#ifndef _ORG_FREEBSD_
+#include <sys/ioccom.h>
+/*
+ * Pseudo sysctl call through ioctl(2) interface
+ */
+#define IOCSYSCTL _IOWR('X', 0, struct sysctl_req)
+
+struct pseudo_sysctl {
+ int *name;
+ u_int namelen;
+ struct sysctl_req req;
+};
+
+#endif
+
+/*
+ * This describes one "oid" in the MIB tree. Potentially more nodes can
+ * be hidden behind it, expanded by the handler.
+ */
+struct sysctl_oid {
+ int oid_number;
+ int oid_kind;
+ void *oid_arg1;
+ int oid_arg2;
+ const char *oid_name;
+ int (*oid_handler) SYSCTL_HANDLER_ARGS;
+ const char *oid_fmt;
+};
+
+#define SYSCTL_IN(r, p, l) (r->newfunc)(r, p, l)
+#define SYSCTL_OUT(r, p, l) (r->oldfunc)(r, p, l)
+
+int sysctl_handle_int SYSCTL_HANDLER_ARGS;
+int sysctl_handle_long SYSCTL_HANDLER_ARGS;
+int sysctl_handle_intptr SYSCTL_HANDLER_ARGS;
+int sysctl_handle_string SYSCTL_HANDLER_ARGS;
+int sysctl_handle_opaque SYSCTL_HANDLER_ARGS;
+
+#ifdef _ORG_FREEBSD_
+/* This constructs a "raw" MIB oid. */
+#define SYSCTL_OID(parent, nbr, name, kind, a1, a2, handler, fmt, descr) \
+ static struct sysctl_oid sysctl__##parent##_##name = { \
+ nbr, kind, a1, a2, #name, handler, fmt }; \
+ DATA_SET(sysctl_##parent, sysctl__##parent##_##name)
+
+/* This constructs a node from which other oids can hang. */
+#define SYSCTL_NODE(parent, nbr, name, access, handler, descr) \
+ extern struct linker_set sysctl_##parent##_##name; \
+ SYSCTL_OID(parent, nbr, name, CTLTYPE_NODE|access, \
+ (void*)&sysctl_##parent##_##name, 0, handler, "N", descr); \
+ DATA_SET(sysctl_##parent##_##name, sysctl__##parent##_##name)
+#else
+#define SYSCTL_OID(parent, nbr, name, kind, a1, a2, handler, fmt, descr)
+#define SYSCTL_NODE(parent, nbr, name, access, handler, descr)
+#endif
+
+/* Oid for a string. len can be 0 to indicate '\0' termination. */
+#define SYSCTL_STRING(parent, nbr, name, access, arg, len, descr) \
+ SYSCTL_OID(parent, nbr, name, CTLTYPE_STRING|access, \
+ arg, len, sysctl_handle_string, "A", descr)
+
+/* Oid for an int. If ptr is NULL, val is returned. */
+#define SYSCTL_INT(parent, nbr, name, access, ptr, val, descr) \
+ SYSCTL_OID(parent, nbr, name, CTLTYPE_INT|access, \
+ ptr, val, sysctl_handle_int, "I", descr)
+
+/* Oid for a long. The pointer must be non NULL. */
+#define SYSCTL_LONG(parent, nbr, name, access, ptr, descr) \
+ SYSCTL_OID(parent, nbr, name, CTLTYPE_INT|access, \
+ ptr, 0, sysctl_handle_long, "L", descr)
+
+/* Oid for an opaque object. Specified by a pointer and a length. */
+#define SYSCTL_OPAQUE(parent, nbr, name, access, ptr, len, fmt, descr) \
+ SYSCTL_OID(parent, nbr, name, CTLTYPE_OPAQUE|access, \
+ ptr, len, sysctl_handle_opaque, fmt, descr)
+
+/* Oid for a struct. Specified by a pointer and a type. */
+#define SYSCTL_STRUCT(parent, nbr, name, access, ptr, type, descr) \
+ SYSCTL_OID(parent, nbr, name, CTLTYPE_OPAQUE|access, \
+ ptr, sizeof(struct type), sysctl_handle_opaque, \
+ "S," #type, descr)
+
+/* Oid for a procedure. Specified by a pointer and an arg. */
+#define SYSCTL_PROC(parent, nbr, name, access, ptr, arg, handler, fmt, descr) \
+ SYSCTL_OID(parent, nbr, name, access, \
+ ptr, arg, handler, fmt, descr)
+#endif /* KERNEL */
+
+/*
+ * Top-level identifiers
+ */
+#define CTL_UNSPEC 0 /* unused */
+#define CTL_KERN 1 /* "high kernel": proc, limits */
+#define CTL_VM 2 /* virtual memory */
+#define CTL_VFS 3 /* file system, mount type is next */
+#define CTL_NET 4 /* network, see socket.h */
+#define CTL_DEBUG 5 /* debugging parameters */
+#define CTL_HW 6 /* generic cpu/io */
+#define CTL_MACHDEP 7 /* machine dependent */
+#define CTL_USER 8 /* user-level */
+#define CTL_P1003_1B 9 /* POSIX 1003.1B */
+#define CTL_MAXID 10 /* number of valid top-level ids */
+
+#define CTL_NAMES { \
+ { 0, 0 }, \
+ { "kern", CTLTYPE_NODE }, \
+ { "vm", CTLTYPE_NODE }, \
+ { "vfs", CTLTYPE_NODE }, \
+ { "net", CTLTYPE_NODE }, \
+ { "debug", CTLTYPE_NODE }, \
+ { "hw", CTLTYPE_NODE }, \
+ { "machdep", CTLTYPE_NODE }, \
+ { "user", CTLTYPE_NODE }, \
+ { "p1003_1b", CTLTYPE_NODE }, \
+}
+
+/*
+ * CTL_KERN identifiers
+ */
+#define KERN_OSTYPE 1 /* string: system version */
+#define KERN_OSRELEASE 2 /* string: system release */
+#define KERN_OSREV 3 /* int: system revision */
+#define KERN_VERSION 4 /* string: compile time info */
+#define KERN_MAXVNODES 5 /* int: max vnodes */
+#define KERN_MAXPROC 6 /* int: max processes */
+#define KERN_MAXFILES 7 /* int: max open files */
+#define KERN_ARGMAX 8 /* int: max arguments to exec */
+#define KERN_SECURELVL 9 /* int: system security level */
+#define KERN_HOSTNAME 10 /* string: hostname */
+#define KERN_HOSTID 11 /* int: host identifier */
+#define KERN_CLOCKRATE 12 /* struct: struct clockrate */
+#define KERN_VNODE 13 /* struct: vnode structures */
+#define KERN_PROC 14 /* struct: process entries */
+#define KERN_FILE 15 /* struct: file entries */
+#define KERN_PROF 16 /* node: kernel profiling info */
+#define KERN_POSIX1 17 /* int: POSIX.1 version */
+#define KERN_NGROUPS 18 /* int: # of supplemental group ids */
+#define KERN_JOB_CONTROL 19 /* int: is job control available */
+#define KERN_SAVED_IDS 20 /* int: saved set-user/group-ID */
+#define KERN_BOOTTIME 21 /* struct: time kernel was booted */
+#define KERN_NISDOMAINNAME 22 /* string: YP domain name */
+#define KERN_UPDATEINTERVAL 23 /* int: update process sleep time */
+#define KERN_OSRELDATE 24 /* int: OS release date */
+#define KERN_NTP_PLL 25 /* node: NTP PLL control */
+#define KERN_BOOTFILE 26 /* string: name of booted kernel */
+#define KERN_MAXFILESPERPROC 27 /* int: max open files per proc */
+#define KERN_MAXPROCPERUID 28 /* int: max processes per uid */
+#define KERN_DUMPDEV 29 /* dev_t: device to dump on */
+#define KERN_IPC 30 /* node: anything related to IPC */
+#define KERN_DUMMY 31 /* unused */
+#define KERN_PS_STRINGS 32 /* int: address of PS_STRINGS */
+#define KERN_USRSTACK 33 /* int: address of USRSTACK */
+#define KERN_LOGSIGEXIT 34 /* int: do we log sigexit procs? */
+#define KERN_MAXID 35 /* number of valid kern ids */
+
+#define CTL_KERN_NAMES { \
+ { 0, 0 }, \
+ { "ostype", CTLTYPE_STRING }, \
+ { "osrelease", CTLTYPE_STRING }, \
+ { "osrevision", CTLTYPE_INT }, \
+ { "version", CTLTYPE_STRING }, \
+ { "maxvnodes", CTLTYPE_INT }, \
+ { "maxproc", CTLTYPE_INT }, \
+ { "maxfiles", CTLTYPE_INT }, \
+ { "argmax", CTLTYPE_INT }, \
+ { "securelevel", CTLTYPE_INT }, \
+ { "hostname", CTLTYPE_STRING }, \
+ { "hostid", CTLTYPE_INT }, \
+ { "clockrate", CTLTYPE_STRUCT }, \
+ { "vnode", CTLTYPE_STRUCT }, \
+ { "proc", CTLTYPE_STRUCT }, \
+ { "file", CTLTYPE_STRUCT }, \
+ { "profiling", CTLTYPE_NODE }, \
+ { "posix1version", CTLTYPE_INT }, \
+ { "ngroups", CTLTYPE_INT }, \
+ { "job_control", CTLTYPE_INT }, \
+ { "saved_ids", CTLTYPE_INT }, \
+ { "boottime", CTLTYPE_STRUCT }, \
+ { "nisdomainname", CTLTYPE_STRING }, \
+ { "update", CTLTYPE_INT }, \
+ { "osreldate", CTLTYPE_INT }, \
+ { "ntp_pll", CTLTYPE_NODE }, \
+ { "bootfile", CTLTYPE_STRING }, \
+ { "maxfilesperproc", CTLTYPE_INT }, \
+ { "maxprocperuid", CTLTYPE_INT }, \
+ { "dumpdev", CTLTYPE_STRUCT }, /* we lie; don't print as int */ \
+ { "ipc", CTLTYPE_NODE }, \
+ { "dummy", CTLTYPE_INT }, \
+ { "ps_strings", CTLTYPE_INT }, \
+ { "usrstack", CTLTYPE_INT }, \
+ { "logsigexit", CTLTYPE_INT }, \
+}
+
+/*
+ * CTL_VFS identifiers
+ */
+#define CTL_VFS_NAMES { \
+ { "vfsconf", CTLTYPE_STRUCT }, \
+}
+
+/*
+ * KERN_PROC subtypes
+ */
+#define KERN_PROC_ALL 0 /* everything */
+#define KERN_PROC_PID 1 /* by process id */
+#define KERN_PROC_PGRP 2 /* by process group id */
+#define KERN_PROC_SESSION 3 /* by session of pid */
+#define KERN_PROC_TTY 4 /* by controlling tty */
+#define KERN_PROC_UID 5 /* by effective uid */
+#define KERN_PROC_RUID 6 /* by real uid */
+
+/*
+ * KERN_IPC identifiers
+ */
+#define KIPC_MAXSOCKBUF 1 /* int: max size of a socket buffer */
+#define KIPC_SOCKBUF_WASTE 2 /* int: wastage factor in sockbuf */
+#define KIPC_SOMAXCONN 3 /* int: max length of connection q */
+#define KIPC_MAX_LINKHDR 4 /* int: max length of link header */
+#define KIPC_MAX_PROTOHDR 5 /* int: max length of network header */
+#define KIPC_MAX_HDR 6 /* int: max total length of headers */
+#define KIPC_MAX_DATALEN 7 /* int: max length of data? */
+#define KIPC_MBSTAT 8 /* struct: mbuf usage statistics */
+#define KIPC_NMBCLUSTERS 9 /* int: maximum mbuf clusters */
+
+/*
+ * CTL_HW identifiers
+ */
+#define HW_MACHINE 1 /* string: machine class */
+#define HW_MODEL 2 /* string: specific machine model */
+#define HW_NCPU 3 /* int: number of cpus */
+#define HW_BYTEORDER 4 /* int: machine byte order */
+#define HW_PHYSMEM 5 /* int: total memory */
+#define HW_USERMEM 6 /* int: non-kernel memory */
+#define HW_PAGESIZE 7 /* int: software page size */
+#define HW_DISKNAMES 8 /* strings: disk drive names */
+#define HW_DISKSTATS 9 /* struct: diskstats[] */
+#define HW_FLOATINGPT 10 /* int: has HW floating point? */
+#define HW_MACHINE_ARCH 11 /* string: machine architecture */
+#define HW_MAXID 12 /* number of valid hw ids */
+
+#define CTL_HW_NAMES { \
+ { 0, 0 }, \
+ { "machine", CTLTYPE_STRING }, \
+ { "model", CTLTYPE_STRING }, \
+ { "ncpu", CTLTYPE_INT }, \
+ { "byteorder", CTLTYPE_INT }, \
+ { "physmem", CTLTYPE_INT }, \
+ { "usermem", CTLTYPE_INT }, \
+ { "pagesize", CTLTYPE_INT }, \
+ { "disknames", CTLTYPE_STRUCT }, \
+ { "diskstats", CTLTYPE_STRUCT }, \
+ { "floatingpoint", CTLTYPE_INT }, \
+}
+
+/*
+ * CTL_USER definitions
+ */
+#define USER_CS_PATH 1 /* string: _CS_PATH */
+#define USER_BC_BASE_MAX 2 /* int: BC_BASE_MAX */
+#define USER_BC_DIM_MAX 3 /* int: BC_DIM_MAX */
+#define USER_BC_SCALE_MAX 4 /* int: BC_SCALE_MAX */
+#define USER_BC_STRING_MAX 5 /* int: BC_STRING_MAX */
+#define USER_COLL_WEIGHTS_MAX 6 /* int: COLL_WEIGHTS_MAX */
+#define USER_EXPR_NEST_MAX 7 /* int: EXPR_NEST_MAX */
+#define USER_LINE_MAX 8 /* int: LINE_MAX */
+#define USER_RE_DUP_MAX 9 /* int: RE_DUP_MAX */
+#define USER_POSIX2_VERSION 10 /* int: POSIX2_VERSION */
+#define USER_POSIX2_C_BIND 11 /* int: POSIX2_C_BIND */
+#define USER_POSIX2_C_DEV 12 /* int: POSIX2_C_DEV */
+#define USER_POSIX2_CHAR_TERM 13 /* int: POSIX2_CHAR_TERM */
+#define USER_POSIX2_FORT_DEV 14 /* int: POSIX2_FORT_DEV */
+#define USER_POSIX2_FORT_RUN 15 /* int: POSIX2_FORT_RUN */
+#define USER_POSIX2_LOCALEDEF 16 /* int: POSIX2_LOCALEDEF */
+#define USER_POSIX2_SW_DEV 17 /* int: POSIX2_SW_DEV */
+#define USER_POSIX2_UPE 18 /* int: POSIX2_UPE */
+#define USER_STREAM_MAX 19 /* int: POSIX2_STREAM_MAX */
+#define USER_TZNAME_MAX 20 /* int: POSIX2_TZNAME_MAX */
+#define USER_MAXID 21 /* number of valid user ids */
+
+#define CTL_USER_NAMES { \
+ { 0, 0 }, \
+ { "cs_path", CTLTYPE_STRING }, \
+ { "bc_base_max", CTLTYPE_INT }, \
+ { "bc_dim_max", CTLTYPE_INT }, \
+ { "bc_scale_max", CTLTYPE_INT }, \
+ { "bc_string_max", CTLTYPE_INT }, \
+ { "coll_weights_max", CTLTYPE_INT }, \
+ { "expr_nest_max", CTLTYPE_INT }, \
+ { "line_max", CTLTYPE_INT }, \
+ { "re_dup_max", CTLTYPE_INT }, \
+ { "posix2_version", CTLTYPE_INT }, \
+ { "posix2_c_bind", CTLTYPE_INT }, \
+ { "posix2_c_dev", CTLTYPE_INT }, \
+ { "posix2_char_term", CTLTYPE_INT }, \
+ { "posix2_fort_dev", CTLTYPE_INT }, \
+ { "posix2_fort_run", CTLTYPE_INT }, \
+ { "posix2_localedef", CTLTYPE_INT }, \
+ { "posix2_sw_dev", CTLTYPE_INT }, \
+ { "posix2_upe", CTLTYPE_INT }, \
+ { "stream_max", CTLTYPE_INT }, \
+ { "tzname_max", CTLTYPE_INT }, \
+}
+
+#define CTL_P1003_1B_ASYNCHRONOUS_IO 1 /* boolean */
+#define CTL_P1003_1B_MAPPED_FILES 2 /* boolean */
+#define CTL_P1003_1B_MEMLOCK 3 /* boolean */
+#define CTL_P1003_1B_MEMLOCK_RANGE 4 /* boolean */
+#define CTL_P1003_1B_MEMORY_PROTECTION 5 /* boolean */
+#define CTL_P1003_1B_MESSAGE_PASSING 6 /* boolean */
+#define CTL_P1003_1B_PRIORITIZED_IO 7 /* boolean */
+#define CTL_P1003_1B_PRIORITY_SCHEDULING 8 /* boolean */
+#define CTL_P1003_1B_REALTIME_SIGNALS 9 /* boolean */
+#define CTL_P1003_1B_SEMAPHORES 10 /* boolean */
+#define CTL_P1003_1B_FSYNC 11 /* boolean */
+#define CTL_P1003_1B_SHARED_MEMORY_OBJECTS 12 /* boolean */
+#define CTL_P1003_1B_SYNCHRONIZED_IO 13 /* boolean */
+#define CTL_P1003_1B_TIMERS 14 /* boolean */
+#define CTL_P1003_1B_AIO_LISTIO_MAX 15 /* int */
+#define CTL_P1003_1B_AIO_MAX 16 /* int */
+#define CTL_P1003_1B_AIO_PRIO_DELTA_MAX 17 /* int */
+#define CTL_P1003_1B_DELAYTIMER_MAX 18 /* int */
+#define CTL_P1003_1B_MQ_OPEN_MAX 19 /* int */
+#define CTL_P1003_1B_PAGESIZE 20 /* int */
+#define CTL_P1003_1B_RTSIG_MAX 21 /* int */
+#define CTL_P1003_1B_SEM_NSEMS_MAX 22 /* int */
+#define CTL_P1003_1B_SEM_VALUE_MAX 23 /* int */
+#define CTL_P1003_1B_SIGQUEUE_MAX 24 /* int */
+#define CTL_P1003_1B_TIMER_MAX 25 /* int */
+
+#define CTL_P1003_1B_MAXID 26
+
+#define CTL_P1003_1B_NAMES { \
+ { 0, 0 }, \
+ { "asynchronous_io", CTLTYPE_INT }, \
+ { "mapped_files", CTLTYPE_INT }, \
+ { "memlock", CTLTYPE_INT }, \
+ { "memlock_range", CTLTYPE_INT }, \
+ { "memory_protection", CTLTYPE_INT }, \
+ { "message_passing", CTLTYPE_INT }, \
+ { "prioritized_io", CTLTYPE_INT }, \
+ { "priority_scheduling", CTLTYPE_INT }, \
+ { "realtime_signals", CTLTYPE_INT }, \
+ { "semaphores", CTLTYPE_INT }, \
+ { "fsync", CTLTYPE_INT }, \
+ { "shared_memory_objects", CTLTYPE_INT }, \
+ { "synchronized_io", CTLTYPE_INT }, \
+ { "timers", CTLTYPE_INT }, \
+ { "aio_listio_max", CTLTYPE_INT }, \
+ { "aio_max", CTLTYPE_INT }, \
+ { "aio_prio_delta_max", CTLTYPE_INT }, \
+ { "delaytimer_max", CTLTYPE_INT }, \
+ { "mq_open_max", CTLTYPE_INT }, \
+ { "pagesize", CTLTYPE_INT }, \
+ { "rtsig_max", CTLTYPE_INT }, \
+ { "nsems_max", CTLTYPE_INT }, \
+ { "sem_value_max", CTLTYPE_INT }, \
+ { "sigqueue_max", CTLTYPE_INT }, \
+ { "timer_max", CTLTYPE_INT }, \
+}
+
+#ifdef KERNEL
+
+extern char machine[];
+extern char osrelease[];
+extern char ostype[];
+
+int kernel_sysctl(struct proc *p, int *name, u_int namelen, void *old,
+ size_t *oldlenp, void *new, size_t newlen,
+ size_t *retval);
+void sysctl_order_all(void);
+int userland_sysctl(struct proc *p, int *name, u_int namelen, void *old,
+ size_t *oldlenp, int inkernel, void *new, size_t newlen,
+ size_t *retval);
+
+#else /* !KERNEL */
+#include <sys/EfiCdefs.h>
+
+__BEGIN_DECLS
+int sysctl __P((int *, u_int, void *, size_t *, void *, size_t));
+int sysctlbyname __P((const char *, void *, size_t *, void *, size_t));
+__END_DECLS
+#endif /* KERNEL */
+
+#endif /* !_SYS_SYSCTL_H_ */
diff --git a/StdLib/Include/sys/syslimits.h b/StdLib/Include/sys/syslimits.h index 80b18c3917..d308387f2a 100644 --- a/StdLib/Include/sys/syslimits.h +++ b/StdLib/Include/sys/syslimits.h @@ -37,7 +37,7 @@ #include <sys/featuretest.h>
#define ARG_MAX (2 * 1024) /* max bytes for an exec function */
-#define ARGC_MAX (ARG_MAX / 2) /* Maximum value for argc */
+#define ARGC_MAX (64) /* Maximum value for argc */
#ifndef CHILD_MAX
#define CHILD_MAX 128 /* max simultaneous processes */
diff --git a/StdLib/Include/sys/time.h b/StdLib/Include/sys/time.h index 4b17317200..b8957f4c41 100644 --- a/StdLib/Include/sys/time.h +++ b/StdLib/Include/sys/time.h @@ -71,6 +71,7 @@ struct timespec { (ts)->tv_sec = (tv)->tv_sec; \
(ts)->tv_nsec = (tv)->tv_usec * 1000; \
} while (/*CONSTCOND*/0)
+
#define TIMESPEC_TO_TIMEVAL(tv, ts) do { \
(tv)->tv_sec = (ts)->tv_sec; \
(tv)->tv_usec = (ts)->tv_nsec / 1000; \
@@ -79,10 +80,12 @@ struct timespec { /* Operations on timevals. */
#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0
#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
+
#define timercmp(tvp, uvp, cmp) \
(((tvp)->tv_sec == (uvp)->tv_sec) ? \
((tvp)->tv_usec cmp (uvp)->tv_usec) : \
((tvp)->tv_sec cmp (uvp)->tv_sec))
+
#define timeradd(tvp, uvp, vvp) \
do { \
(vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \
@@ -92,6 +95,7 @@ struct timespec { (vvp)->tv_usec -= 1000000; \
} \
} while (/* CONSTCOND */ 0)
+
#define timersub(tvp, uvp, vvp) \
do { \
(vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
@@ -105,10 +109,12 @@ struct timespec { /* Operations on timespecs. */
#define timespecclear(tsp) (tsp)->tv_sec = (tsp)->tv_nsec = 0
#define timespecisset(tsp) ((tsp)->tv_sec || (tsp)->tv_nsec)
+
#define timespeccmp(tsp, usp, cmp) \
(((tsp)->tv_sec == (usp)->tv_sec) ? \
((tsp)->tv_nsec cmp (usp)->tv_nsec) : \
((tsp)->tv_sec cmp (usp)->tv_sec))
+
#define timespecadd(tsp, usp, vsp) \
do { \
(vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec; \
@@ -118,6 +124,7 @@ struct timespec { (vsp)->tv_nsec -= 1000000000L; \
} \
} while (/* CONSTCOND */ 0)
+
#define timespecsub(tsp, usp, vsp) \
do { \
(vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \
@@ -182,5 +189,8 @@ __END_DECLS /* BSD compatibility functions */
int gettimeofday (struct timeval *tp, void *ignore);
+/* POSIX compatibility functions */
+int getitimer (int which, struct itimerval *value);
+int setitimer (int which, const struct itimerval *value, struct itimerval *ovalue);
#endif /* !_SYS_TIME_H_ */
diff --git a/StdLib/Include/sys/unistd.h b/StdLib/Include/sys/unistd.h index 0e7158c7c8..a63d88df55 100644 --- a/StdLib/Include/sys/unistd.h +++ b/StdLib/Include/sys/unistd.h @@ -37,7 +37,7 @@ #include <sys/featuretest.h>
/* compile-time symbolic constants */
-#define _POSIX_JOB_CONTROL /* implementation supports job control */
+//#define _POSIX_JOB_CONTROL /* implementation supports job control */
/*
* According to POSIX 1003.1:
@@ -62,43 +62,42 @@ /* execution-time symbolic constants */
/* chown requires appropriate privileges */
-#define _POSIX_CHOWN_RESTRICTED 1
- /* clock selection */
-#define _POSIX_CLOCK_SELECTION -1
- /* too-long path components generate errors */
-#define _POSIX_NO_TRUNC 1
- /* may disable terminal special characters */
-#define _POSIX_VDISABLE ((unsigned char)'\377')
- /* file synchronization is available */
-#define _POSIX_FSYNC 1
- /* synchronized I/O is available */
-#define _POSIX_SYNCHRONIZED_IO 1
- /* memory mapped files */
-#define _POSIX_MAPPED_FILES 1
- /* memory locking of whole address space */
-#define _POSIX_MEMLOCK 1
- /* memory locking address ranges */
-#define _POSIX_MEMLOCK_RANGE 1
- /* memory access protections */
-#define _POSIX_MEMORY_PROTECTION 1
- /* monotonic clock */
-#define _POSIX_MONOTONIC_CLOCK 200112L
- /* threads */
-#define _POSIX_THREADS 200112L
- /* semaphores */
-#define _POSIX_SEMAPHORES 0
- /* barriers */
-#define _POSIX_BARRIERS 200112L
+//#define _POSIX_CHOWN_RESTRICTED 1
+// /* clock selection */
+//#define _POSIX_CLOCK_SELECTION -1
+// /* too-long path components generate errors */
+//#define _POSIX_NO_TRUNC 1
+// /* may disable terminal special characters */
+//#define _POSIX_VDISABLE ((unsigned char)'\377')
+// /* file synchronization is available */
+//#define _POSIX_FSYNC 1
+// /* synchronized I/O is available */
+//#define _POSIX_SYNCHRONIZED_IO 1
+// /* memory mapped files */
+//#define _POSIX_MAPPED_FILES 1
+// /* memory locking of whole address space */
+//#define _POSIX_MEMLOCK 1
+// /* memory locking address ranges */
+//#define _POSIX_MEMLOCK_RANGE 1
+// /* memory access protections */
+//#define _POSIX_MEMORY_PROTECTION 1
+// /* monotonic clock */
+//#define _POSIX_MONOTONIC_CLOCK 200112L
+// /* threads */
+//#define _POSIX_THREADS 200112L
+// /* semaphores */
+//#define _POSIX_SEMAPHORES 0
+// /* barriers */
+//#define _POSIX_BARRIERS 200112L
/* timers */
#define _POSIX_TIMERS 200112L
/* spin locks */
-#define _POSIX_SPIN_LOCKS 200112L
- /* read/write locks */
-#define _POSIX_READER_WRITER_LOCKS 200112L
- /* XPG4.2 shared memory */
-#define _XOPEN_SHM 0
+//#define _POSIX_SPIN_LOCKS 200112L
+// /* read/write locks */
+//#define _POSIX_READER_WRITER_LOCKS 200112L
+// /* XPG4.2 shared memory */
+//#define _XOPEN_SHM 0
-#if defined(_NETBSD_SOURCE)
/* whence values for lseek(2); renamed by POSIX 1003.1 */
#define L_SET SEEK_SET
#define L_INCR SEEK_CUR
@@ -115,7 +114,6 @@ #define FDATASYNC 0x0010 /* sync data and minimal metadata */
#define FFILESYNC 0x0020 /* sync data and metadata */
#define FDISKSYNC 0x0040 /* flush disk caches after sync */
-#endif
/* configurable pathname variables; use as argument to pathconf(3) */
#define _PC_LINK_MAX 1
diff --git a/StdLib/Include/sys/wait.h b/StdLib/Include/sys/wait.h new file mode 100644 index 0000000000..64200aa999 --- /dev/null +++ b/StdLib/Include/sys/wait.h @@ -0,0 +1,170 @@ +/* $NetBSD: wait.h,v 1.24 2005/12/11 12:25:21 christos Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986, 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)wait.h 8.2 (Berkeley) 7/10/94
+ */
+#ifndef _SYS_WAIT_H_
+#define _SYS_WAIT_H_
+
+#include <sys/featuretest.h>
+#include <sys/types.h>
+
+/*
+ * This file holds definitions relevent to the wait4 system call
+ * and the alternate interfaces that use it (wait, wait3, waitpid).
+ */
+
+/*
+ * Macros to test the exit status returned by wait
+ * and extract the relevant values.
+ */
+#define _W_INT(w) (*(int *)(void *)&(w)) /* convert union wait to int */
+
+#define _WSTATUS(x) (_W_INT(x) & 0177)
+#define _WSTOPPED 0177 /* _WSTATUS if process is stopped */
+#define WIFSTOPPED(x) (_WSTATUS(x) == _WSTOPPED)
+#define WSTOPSIG(x) ((int)(((unsigned int)_W_INT(x)) >> 8) & 0xff)
+#define WIFSIGNALED(x) (_WSTATUS(x) != _WSTOPPED && _WSTATUS(x) != 0)
+#define WTERMSIG(x) (_WSTATUS(x))
+#define WIFEXITED(x) (_WSTATUS(x) == 0)
+#define WEXITSTATUS(x) ((int)(((unsigned int)_W_INT(x)) >> 8) & 0xff)
+#define WCOREFLAG 0200
+#define WCOREDUMP(x) (_W_INT(x) & WCOREFLAG)
+
+#define W_EXITCODE(ret, sig) ((ret) << 8 | (sig))
+#define W_STOPCODE(sig) ((sig) << 8 | _WSTOPPED)
+
+/*
+ * Option bits for the third argument of wait4. WNOHANG causes the
+ * wait to not hang if there are no stopped or terminated processes, rather
+ * returning an error indication in this case (pid==0). WUNTRACED
+ * indicates that the caller should receive status about untraced children
+ * which stop due to signals. If children are stopped and a wait without
+ * this option is done, it is as though they were still running... nothing
+ * about them is returned.
+ */
+#define WNOHANG 0x00000001 /* don't hang in wait */
+#define WUNTRACED 0x00000002 /* tell about stopped,
+ untraced children */
+#if defined(_XOPEN_SOURCE) || defined(_NETBSD_SOURCE)
+#define WALTSIG 0x00000004 /* wait for processes that exit
+ with an alternate signal (i.e.
+ not SIGCHLD) */
+#define WALLSIG 0x00000008 /* wait for processes that exit
+ with any signal, i.e. SIGCHLD
+ and alternates */
+
+/*
+ * These are the Linux names of some of the above flags, for compatibility
+ * with Linux's clone(2) API.
+ */
+#define __WCLONE WALTSIG
+#define __WALL WALLSIG
+
+/*
+ * These bits are used in order to support SVR4 (etc) functionality
+ * without replicating sys_wait4 5 times.
+ */
+#define WNOWAIT 0x00010000 /* Don't mark child 'P_WAITED' */
+#define WNOZOMBIE 0x00020000 /* Ignore zombies */
+#endif /* _XOPEN_SOURCE || _NETBSD_SOURCE */
+
+/* POSIX extensions and 4.2/4.3 compatibility: */
+
+/*
+ * Tokens for special values of the "pid" parameter to wait4.
+ */
+#define WAIT_ANY (-1) /* any process */
+#define WAIT_MYPGRP 0 /* any process in my process group */
+
+/*
+ * Deprecated:
+ * Structure of the information in the status word returned by wait4.
+ * If w_stopval==WSTOPPED, then the second structure describes
+ * the information returned, else the first.
+ */
+union wait {
+ int w_status; /* used in syscall */
+ /*
+ * Terminated process status.
+ */
+ struct {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ unsigned int w_Termsig:7, /* termination signal */
+ w_Coredump:1, /* core dump indicator */
+ w_Retcode:8, /* exit code if w_termsig==0 */
+ w_Filler:16; /* upper bits filler */
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+ unsigned int w_Filler:16, /* upper bits filler */
+ w_Retcode:8, /* exit code if w_termsig==0 */
+ w_Coredump:1, /* core dump indicator */
+ w_Termsig:7; /* termination signal */
+#endif
+ } w_T;
+ /*
+ * Stopped process status. Returned
+ * only for traced children unless requested
+ * with the WUNTRACED option bit.
+ */
+ struct {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ unsigned int w_Stopval:8, /* == W_STOPPED if stopped */
+ w_Stopsig:8, /* signal that stopped us */
+ w_Filler:16; /* upper bits filler */
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+ unsigned int w_Filler:16, /* upper bits filler */
+ w_Stopsig:8, /* signal that stopped us */
+ w_Stopval:8; /* == W_STOPPED if stopped */
+#endif
+ } w_S;
+};
+#define w_termsig w_T.w_Termsig
+#define w_coredump w_T.w_Coredump
+#define w_retcode w_T.w_Retcode
+#define w_stopval w_S.w_Stopval
+#define w_stopsig w_S.w_Stopsig
+
+#define WSTOPPED _WSTOPPED
+
+__BEGIN_DECLS
+pid_t wait(int *);
+
+#if 0 /* Normally declared here but not implemented for UEFI. */
+struct rusage; /* forward declaration */
+
+pid_t waitpid(pid_t, int *, int);
+pid_t wait3(int *, int, struct rusage *);
+pid_t wait4(pid_t, int *, int, struct rusage *);
+#endif
+__END_DECLS
+
+#endif /* !_SYS_WAIT_H_ */
diff --git a/StdLib/Include/sysexits.h b/StdLib/Include/sysexits.h new file mode 100644 index 0000000000..e18348d39a --- /dev/null +++ b/StdLib/Include/sysexits.h @@ -0,0 +1,122 @@ +/** @file contains exit code definitions for exiting systems applications.
+
+ These exit codes are an extension beyond the two values specified by
+ ISO/IEC 9899:199409 and defined in <stdlib.h>.
+
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)sysexits.h 8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _SYSEXITS_H_
+#define _SYSEXITS_H_
+
+/*
+ * SYSEXITS.H -- Exit status codes for system programs.
+ *
+ * This include file attempts to categorize possible error
+ * exit statuses for system programs, notably delivermail
+ * and the Berkeley network.
+ *
+ * Error numbers begin at EX__BASE to reduce the possibility of
+ * clashing with other exit statuses that random programs may
+ * already return. The meaning of the codes is approximately
+ * as follows:
+ *
+ * EX_USAGE -- The command was used incorrectly, e.g., with
+ * the wrong number of arguments, a bad flag, a bad
+ * syntax in a parameter, or whatever.
+ * EX_DATAERR -- The input data was incorrect in some way.
+ * This should only be used for user's data & not
+ * system files.
+ * EX_NOINPUT -- An input file (not a system file) did not
+ * exist or was not readable. This could also include
+ * errors like "No message" to a mailer (if it cared
+ * to catch it).
+ * EX_NOUSER -- The user specified did not exist. This might
+ * be used for mail addresses or remote logins.
+ * EX_NOHOST -- The host specified did not exist. This is used
+ * in mail addresses or network requests.
+ * EX_UNAVAILABLE -- A service is unavailable. This can occur
+ * if a support program or file does not exist. This
+ * can also be used as a catchall message when something
+ * you wanted to do doesn't work, but you don't know
+ * why.
+ * EX_SOFTWARE -- An internal software error has been detected.
+ * This should be limited to non-operating system related
+ * errors as possible.
+ * EX_OSERR -- An operating system error has been detected.
+ * This is intended to be used for such things as "cannot
+ * fork", "cannot create pipe", or the like. It includes
+ * things like getuid returning a user that does not
+ * exist in the passwd file.
+ * EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp,
+ * etc.) does not exist, cannot be opened, or has some
+ * sort of error (e.g., syntax error).
+ * EX_CANTCREAT -- A (user specified) output file cannot be
+ * created.
+ * EX_IOERR -- An error occurred while doing I/O on some file.
+ * EX_TEMPFAIL -- temporary failure, indicating something that
+ * is not really an error. In sendmail, this means
+ * that a mailer (e.g.) could not create a connection,
+ * and the request should be reattempted later.
+ * EX_PROTOCOL -- the remote system returned something that
+ * was "not possible" during a protocol exchange.
+ * EX_NOPERM -- You did not have sufficient permission to
+ * perform the operation. This is not intended for
+ * file system problems, which should use NOINPUT or
+ * CANTCREAT, but rather for higher level permissions.
+ */
+
+#define EX_OK 0 /* successful termination */
+
+#define EX__BASE 64 /* base value for error messages */
+
+#define EX_USAGE 64 /* command line usage error */
+#define EX_DATAERR 65 /* data format error */
+#define EX_NOINPUT 66 /* cannot open input */
+#define EX_NOUSER 67 /* addressee unknown */
+#define EX_NOHOST 68 /* host name unknown */
+#define EX_UNAVAILABLE 69 /* service unavailable */
+#define EX_SOFTWARE 70 /* internal software error */
+#define EX_OSERR 71 /* system error (e.g., can't fork) */
+#define EX_OSFILE 72 /* critical OS file missing */
+#define EX_CANTCREAT 73 /* can't create (user) output file */
+#define EX_IOERR 74 /* input/output error */
+#define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
+#define EX_PROTOCOL 76 /* remote error in protocol */
+#define EX_NOPERM 77 /* permission denied */
+#define EX_CONFIG 78 /* configuration error */
+
+#define EX__MAX 78 /* maximum listed value */
+
+#endif /* !_SYSEXITS_H_ */
diff --git a/StdLib/Include/time.h b/StdLib/Include/time.h index 8c7b8e1422..a0ebbb9881 100644 --- a/StdLib/Include/time.h +++ b/StdLib/Include/time.h @@ -108,13 +108,13 @@ **/
struct tm {
int tm_year; // years since 1900
- int tm_mon; // months since January — [0, 11]
- int tm_mday; // day of the month — [1, 31]
- int tm_hour; // hours since midnight — [0, 23]
- int tm_min; // minutes after the hour — [0, 59]
- int tm_sec; // seconds after the minute — [0, 60]
- int tm_wday; // days since Sunday — [0, 6]
- int tm_yday; // days since January 1 — [0, 365]
+ int tm_mon; // months since January [0, 11]
+ int tm_mday; // day of the month [1, 31]
+ int tm_hour; // hours since midnight [0, 23]
+ int tm_min; // minutes after the hour [0, 59]
+ int tm_sec; // seconds after the minute [0, 60]
+ int tm_wday; // days since Sunday [0, 6]
+ int tm_yday; // days since January 1 [0, 365]
int tm_isdst; // Daylight Saving Time flag
int tm_zoneoff; // EFI TimeZone offset, -1440 to 1440 or 2047
int tm_daylight; // EFI Daylight flags
@@ -125,7 +125,7 @@ struct tm { /** The clock function determines the processor time used.
- @return The clock function returns the implementation’s best
+ @return The clock function returns the implementation's best
approximation to the processor time used by the program since the
beginning of an implementation-defined era related only to the
program invocation. To determine the time in seconds, the value
@@ -137,11 +137,11 @@ struct tm { On IA32 or X64 platforms, the value returned is the number of
CPU TimeStamp Counter ticks since the appliation started.
**/
-clock_t EFIAPI clock(void);
+clock_t clock(void);
/**
**/
-double EFIAPI difftime(time_t time1, time_t time0);
+double difftime(time_t time1, time_t time0);
/** The mktime function converts the broken-down time, expressed as local time,
in the structure pointed to by timeptr into a calendar time value with the
@@ -159,19 +159,19 @@ double EFIAPI difftime(time_t time1, time_t time0); as a value of type time_t. If the calendar time cannot be
represented, the function returns the value (time_t)(-1).
**/
-time_t EFIAPI mktime(struct tm *timeptr);
+time_t mktime(struct tm *timeptr);
/** The time function determines the current calendar time.
The encoding of the value is unspecified.
- @return The time function returns the implementation’s best approximation
+ @return The time function returns the implementation's best approximation
of the current calendar time. The value (time_t)(-1) is returned
if the calendar time is not available. If timer is not a null
pointer, the return value is also assigned to the object it
points to.
**/
-time_t EFIAPI time(time_t *timer);
+time_t time(time_t *timer);
/* ################# Time Conversion Functions ########################## */
@@ -181,7 +181,7 @@ time_t EFIAPI time(time_t *timer); @return The asctime function returns a pointer to the string.
**/
-char * EFIAPI asctime(const struct tm *timeptr);
+char * asctime(const struct tm *timeptr);
/** The ctime function converts the calendar time pointed to by timer to local
time in the form of a string. It is equivalent to asctime(localtime(timer))
@@ -189,7 +189,7 @@ char * EFIAPI asctime(const struct tm *timeptr); @return The ctime function returns the pointer returned by the asctime
function with that broken-down time as argument.
**/
-char * EFIAPI ctime(const time_t *timer);
+char * ctime(const time_t *timer);
/** The gmtime function converts the calendar time pointed to by timer into a
brokendown time, expressed as UTC.
@@ -197,7 +197,13 @@ char * EFIAPI ctime(const time_t *timer); @return The gmtime function returns a pointer to the broken-down time,
or a null pointer if the specified time cannot be converted to UTC.
**/
-struct tm * EFIAPI gmtime(const time_t *timer);
+struct tm * gmtime(const time_t *timer);
+
+/** The timegm function is the opposite of gmtime.
+
+ @return The calendar time expressed as UTC.
+**/
+time_t timegm(struct tm*);
/** The localtime function converts the calendar time pointed to by timer into
a broken-down time, expressed as local time.
@@ -206,7 +212,7 @@ struct tm * EFIAPI gmtime(const time_t *timer); or a null pointer if the specified time cannot be converted to
local time.
**/
-struct tm * EFIAPI localtime(const time_t *timer);
+struct tm * localtime(const time_t *timer);
/** The strftime function places characters into the array pointed to by s as
controlled by the string pointed to by format. The format shall be a
@@ -228,11 +234,11 @@ struct tm * EFIAPI localtime(const time_t *timer); in the description. If any of the specified values is outside the normal
range, the characters stored are unspecified.
- %a is replaced by the locale’s abbreviated weekday name. [tm_wday]
- %A is replaced by the locale’s full weekday name. [tm_wday]
- %b is replaced by the locale’s abbreviated month name. [tm_mon]
- %B is replaced by the locale’s full month name. [tm_mon]
- %c is replaced by the locale’s appropriate date and time representation.
+ %a is replaced by the locale's abbreviated weekday name. [tm_wday]
+ %A is replaced by the locale's full weekday name. [tm_wday]
+ %b is replaced by the locale's abbreviated month name. [tm_mon]
+ %B is replaced by the locale's full month name. [tm_mon]
+ %c is replaced by the locale's appropriate date and time representation.
%C is replaced by the year divided by 100 and truncated to an integer,
as a decimal number (00-99). [tm_year]
%d is replaced by the day of the month as a decimal number (01-31). [tm_mday]
@@ -252,9 +258,9 @@ struct tm * EFIAPI localtime(const time_t *timer); %m is replaced by the month as a decimal number (01-12). [tm_mon]
%M is replaced by the minute as a decimal number (00-59). [tm_min]
%n is replaced by a new-line character.
- %p is replaced by the locale’s equivalent of the AM/PM designations
+ %p is replaced by the locale's equivalent of the AM/PM designations
associated with a 12-hour clock. [tm_hour]
- %r is replaced by the locale’s 12-hour clock time. [tm_hour, tm_min, tm_sec]
+ %r is replaced by the locale's 12-hour clock time. [tm_hour, tm_min, tm_sec]
%R is equivalent to "%H:%M". [tm_hour, tm_min]
%S is replaced by the second as a decimal number (00-60). [tm_sec]
%t is replaced by a horizontal-tab character.
@@ -270,8 +276,8 @@ struct tm * EFIAPI localtime(const time_t *timer); [tm_wday]
%W is replaced by the week number of the year (the first Monday as the
first day of week 1) as a decimal number (00-53). [tm_year, tm_wday, tm_yday]
- %x is replaced by the locale’s appropriate date representation.
- %X is replaced by the locale’s appropriate time representation.
+ %x is replaced by the locale's appropriate date representation.
+ %X is replaced by the locale's appropriate time representation.
%y is replaced by the last 2 digits of the year as a decimal
number (00-99). [tm_year]
%Y is replaced by the year as a decimal number (e.g., 1997). [tm_year]
@@ -285,38 +291,38 @@ struct tm * EFIAPI localtime(const time_t *timer); Some conversion specifiers can be modified by the inclusion of an E or O
modifier character to indicate an alternative format or specification.
If the alternative format or specification does not exist for the current
- locale, the modifier is ignored. %Ec is replaced by the locale’s
+ locale, the modifier is ignored. %Ec is replaced by the locale's
alternative date and time representation.
- %EC is replaced by the name of the base year (period) in the locale’s
+ %EC is replaced by the name of the base year (period) in the locale's
alternative representation.
- %Ex is replaced by the locale’s alternative date representation.
- %EX is replaced by the locale’s alternative time representation.
- %Ey is replaced by the offset from %EC (year only) in the locale’s
+ %Ex is replaced by the locale's alternative date representation.
+ %EX is replaced by the locale's alternative time representation.
+ %Ey is replaced by the offset from %EC (year only) in the locale's
alternative representation.
- %EY is replaced by the locale’s full alternative year representation.
- %Od is replaced by the day of the month, using the locale’s alternative
+ %EY is replaced by the locale's full alternative year representation.
+ %Od is replaced by the day of the month, using the locale's alternative
numeric symbols (filled as needed with leading zeros, or with leading
spaces if there is no alternative symbol for zero).
- %Oe is replaced by the day of the month, using the locale’s alternative
+ %Oe is replaced by the day of the month, using the locale's alternative
numeric symbols (filled as needed with leading spaces).
- %OH is replaced by the hour (24-hour clock), using the locale’s
+ %OH is replaced by the hour (24-hour clock), using the locale's
alternative numeric symbols.
- %OI is replaced by the hour (12-hour clock), using the locale’s
+ %OI is replaced by the hour (12-hour clock), using the locale's
alternative numeric symbols.
- %Om is replaced by the month, using the locale’s alternative numeric symbols.
- %OM is replaced by the minutes, using the locale’s alternative numeric symbols.
- %OS is replaced by the seconds, using the locale’s alternative numeric symbols.
- %Ou is replaced by the ISO 8601 weekday as a number in the locale’s
+ %Om is replaced by the month, using the locale's alternative numeric symbols.
+ %OM is replaced by the minutes, using the locale's alternative numeric symbols.
+ %OS is replaced by the seconds, using the locale's alternative numeric symbols.
+ %Ou is replaced by the ISO 8601 weekday as a number in the locale's
alternative representation, where Monday is 1.
- %OU is replaced by the week number, using the locale’s alternative numeric symbols.
- %OV is replaced by the ISO 8601 week number, using the locale’s alternative
+ %OU is replaced by the week number, using the locale's alternative numeric symbols.
+ %OV is replaced by the ISO 8601 week number, using the locale's alternative
numeric symbols.
- %Ow is replaced by the weekday as a number, using the locale’s alternative
+ %Ow is replaced by the weekday as a number, using the locale's alternative
numeric symbols.
- %OW is replaced by the week number of the year, using the locale’s
+ %OW is replaced by the week number of the year, using the locale's
alternative numeric symbols.
- %Oy is replaced by the last 2 digits of the year, using the locale’s
+ %Oy is replaced by the last 2 digits of the year, using the locale's
alternative numeric symbols.
%g, %G, and %V give values according to the ISO 8601 week-based year. In
@@ -358,7 +364,7 @@ struct tm * EFIAPI localtime(const time_t *timer); character. Otherwise, zero is returned and the contents of the
array are indeterminate.
**/
-size_t EFIAPI strftime( char * __restrict s, size_t maxsize,
+size_t strftime( char * __restrict s, size_t maxsize,
const char * __restrict format,
const struct tm * __restrict timeptr);
@@ -367,6 +373,6 @@ char *strptime(const char *, const char * format, struct tm*); /* ################# Implementation Functions ########################### */
-clock_t EFIAPI __getCPS(void);
+clock_t __getCPS(void);
#endif /* _TIME_H */
diff --git a/StdLib/Include/unistd.h b/StdLib/Include/unistd.h index fc8d7381b7..df78690525 100644 --- a/StdLib/Include/unistd.h +++ b/StdLib/Include/unistd.h @@ -27,8 +27,17 @@ __BEGIN_DECLS
+int dup(int);
int rename(const char *, const char *);
+/* Functions implemented for compatibility. */
+int getopt(int, char * const [], const char *);
+extern char *optarg; /* getopt(3) external variables */
+extern int optind;
+pid_t getpgrp(void);
+pid_t tcgetpgrp(int);
+char *getpass(const char *);
+
// Networking
long gethostid(void);
int gethostname(char *, size_t);
@@ -37,15 +46,20 @@ int setdomainname(const char *, size_t); int sethostid(long);
int sethostname(const char *, size_t);
+/* Stub functions implemented for porting ease.
+ These functions always fail or return NULL.
+*/
+__aconst char *getlogin(void);
+pid_t fork(void);
+uid_t getuid(void);
+
// For Future implementation
-__dead void _exit(int) __attribute__((__noreturn__));
ssize_t pread(int, void *, size_t, off_t);
ssize_t pwrite(int, const void *, size_t, off_t);
int syscall(int, ...);
-int dup(int);
-pid_t fork(void);
-// The following *nix functions are not implemented
+#if 0 // The following functions are not implemented
+__dead void _exit(int) __attribute__((__noreturn__));
unsigned int alarm(unsigned int);
int chown(const char *, uid_t, gid_t);
size_t confstr(int, char *, size_t);
@@ -60,11 +74,8 @@ gid_t getegid(void); uid_t geteuid(void);
gid_t getgid(void);
int getgroups(int, gid_t []);
-__aconst char *getlogin(void);
-pid_t getpgrp(void);
pid_t getpid(void);
pid_t getppid(void);
-uid_t getuid(void);
int link(const char *, const char *);
long pathconf(const char *, int);
int pause(void);
@@ -75,18 +86,14 @@ pid_t setsid(void); int setuid(uid_t);
unsigned int sleep(unsigned int);
long sysconf(int);
-pid_t tcgetpgrp(int);
+
int tcsetpgrp(int, pid_t);
__aconst char *ttyname(int);
-int getopt(int, char * const [], const char *);
-
-extern char *optarg; /* getopt(3) external variables */
extern int opterr;
-extern int optind;
extern int optopt;
-extern int optreset; /* getopt(3) external variable */
-extern char *suboptarg; /* getsubopt(3) external variable */
+extern int optreset;
+extern char *suboptarg;
int setegid(gid_t);
int seteuid(uid_t);
@@ -97,7 +104,6 @@ int chroot(const char *); int nice(int);
__aconst char *crypt(const char *, const char *);
int encrypt(char *, int);
-char *getpass(const char *);
pid_t getsid(pid_t);
#ifndef intptr_t
@@ -164,6 +170,7 @@ int undelete(const char *); int rcmd_af(char **, int, const char *, const char *, const char *, int *, int);
int rresvport_af(int *, int);
int iruserok_sa(const void *, int, int, const char *, const char *);
+#endif /* Unimplemented functions. */
__END_DECLS
diff --git a/StdLib/Include/x86/limits.h b/StdLib/Include/x86/limits.h index 19d7963e2a..08222fa2d6 100644 --- a/StdLib/Include/x86/limits.h +++ b/StdLib/Include/x86/limits.h @@ -46,15 +46,6 @@ /** maximum value for an object of type unsigned int **/
#define __UINT_MAX 0xffffffff // 2^32 - 1
-/** minimum value for an object of type long int **/
-#define __LONG_MIN (-2147483647L - 1L) // -(2^31 - 1)
-
-/** maximum value for an object of type long int **/
-#define __LONG_MAX +2147483647L // 2^31 - 1
-
-/** maximum value for an object of type unsigned long int **/
-#define __ULONG_MAX 0xffffffff // 2^32 - 1
-
/** minimum value for an object of type long long int **/
//#define __LLONG_MIN -9223372036854775808LL // -(2^63 - 1)
//#define __LLONG_MIN ((-9223372036854775807LL)-1) // -(2^63 - 1)
@@ -71,7 +62,6 @@ #define __SHORT_BIT 16
#define __WCHAR_BIT 16
#define __INT_BIT 32
-#define __LONG_BIT 32 /* Compiler dependent */
#define __LONG_LONG_BIT 64
#endif /* _MACHINE_LIMITS_H */
diff --git a/StdLib/LibC/Locale/Locale.inf b/StdLib/LibC/Locale/Locale.inf index 5fee723f85..c891e3bfaf 100644 --- a/StdLib/LibC/Locale/Locale.inf +++ b/StdLib/LibC/Locale/Locale.inf @@ -63,12 +63,3 @@ [LibraryClasses]
LibC
LibCType
-
-################################################################
-#
-# The Build Options, below, are only used when building the C library.
-# DO NOT use them when building your application!
-# Nasty things could happen if you do.
-#
-[BuildOptions]
- GCC:*_*_*_CC_FLAGS = -fno-builtin
diff --git a/StdLib/LibC/Locale/_wcstoul.h b/StdLib/LibC/Locale/_wcstoul.h index ebfc330fe9..2131d4b5c1 100644 --- a/StdLib/LibC/Locale/_wcstoul.h +++ b/StdLib/LibC/Locale/_wcstoul.h @@ -42,6 +42,8 @@ NetBSD: _wcstoul.h,v 1.3 2005/11/29 03:11:59 christos Exp
*/
+#include <Library/BaseLib.h>
+
/*
* function template for wcstoul, wcstoull and wcstoumax.
*
@@ -102,8 +104,8 @@ _FUNCNAME( /*
* See strtoul for comments as to the logic used.
*/
- cutoff = __wUINT_MAX / (__wUINT)base;
- cutlim = (int)(__wUINT_MAX % (__wUINT)base);
+ cutoff = (__wUINT)DivU64x32 ((UINT64) __wUINT_MAX, (UINT32) base);
+ cutlim = (int) ModU64x32 ((UINT64) __wUINT_MAX, (UINT32) base);
for (acc = 0, any = 0;; wc = (wint_t) *s++) {
i = __wctoint((wchar_t)wc);
if (i == -1) {
diff --git a/StdLib/LibC/Locale/multibyte_sb.c b/StdLib/LibC/Locale/multibyte_sb.c index 6d57cd6c09..0a73898e61 100644 --- a/StdLib/LibC/Locale/multibyte_sb.c +++ b/StdLib/LibC/Locale/multibyte_sb.c @@ -137,7 +137,7 @@ wcrtomb( /* ps appears to be unused */
if (s == NULL)
- return 0;
+ return 1; /* Spec. says this should be 1. */
*s = (char) wchar;
return 1;
@@ -150,7 +150,12 @@ wctomb( )
{
- /* s may be NULL */
+ /*
+ If s is NULL just return if MB Characters have state
+ dependent encodings.
+ */
+ if (s == NULL)
+ return 0;
return (int)wcrtomb(s, wchar, NULL);
}
@@ -176,8 +181,10 @@ mbsrtowcs( if (n != 0) {
if (pwcs != NULL) {
do {
- if ((*pwcs++ = (wchar_t) *(*s)++) == 0)
+ if ((*pwcs++ = (wchar_t) *(*s)++) == 0) {
+ *s = NULL;
break;
+ }
count++;
} while (--n != 0);
} else {
@@ -232,8 +239,10 @@ wcsrtombs( if (n != 0) {
do {
- if ((*s++ = (char) *(*pwcs)++) == 0)
+ if ((*s++ = (char) *(*pwcs)++) == 0) {
+ *pwcs = NULL;
break;
+ }
count++;
} while (--n != 0);
}
@@ -266,7 +275,13 @@ btowc(int c) int
wctob(wint_t c)
{
- if (c == WEOF || c & ~0xFF)
+ /* wctob needs to be consistent with wcrtomb.
+ if wcrtomb says that a character is representable in 1 byte,
+ which this implementation always says, then wctob needs to
+ also represent the character as 1 byte.
+ */
+ if (c == WEOF) {
return EOF;
- return (int)c;
+ }
+ return (int)(c & 0xFF);
}
diff --git a/StdLib/LibC/Main/Main.c b/StdLib/LibC/Main/Main.c index 47103ce388..3a5cca5b24 100644 --- a/StdLib/LibC/Main/Main.c +++ b/StdLib/LibC/Main/Main.c @@ -8,13 +8,14 @@ This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php.
+ http://opensource.org/licenses/bsd-license.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Uefi.h>
#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
#include <Library/ShellCEntryLib.h>
#include <Library/MemoryAllocationLib.h>
@@ -40,23 +41,30 @@ void __main() ;
}
-static
+/** Clean up data as required by the exit() function.
+
+**/
void
-FinalCleanup( void )
+exitCleanup(INTN ExitVal)
{
+ void (*CleanUp)(void); // Pointer to Cleanup Function
int i;
- /* Close any open files */
- for(i = OPEN_MAX - 1; i >= 0; --i) {
- (void)close(i); // Close properly handles closing a closed file.
+ if(gMD != NULL) {
+ gMD->ExitValue = (int)ExitVal;
+ CleanUp = gMD->cleanup; // Preserve the pointer to the Cleanup Function
+
+ // Call all registered atexit functions in reverse order
+ i = gMD->num_atexit;
+ if( i > 0) {
+ do {
+ (gMD->atexit_handler[--i])();
+ } while( i > 0);
}
- /* Free the global MainData structure */
- if(gMD != NULL) {
- if(gMD->NCmdLine != NULL) {
- FreePool( gMD->NCmdLine );
+ if (CleanUp != NULL) {
+ CleanUp();
}
- FreePool( gMD );
}
}
@@ -71,6 +79,13 @@ ArgvConvert(UINTN Argc, CHAR16 **Argv) char *string;
INTN nArgvSize; /* Cumulative size of narrow Argv[i] */
+DEBUG_CODE_BEGIN();
+ Print(L"ArgvConvert called with %d arguments.\n", Argc);
+ for(count = 0; count < ((Argc > 5)? 5: Argc); ++count) {
+ Print(L"Argument[%d] = \"%s\".\n", count, Argv[count]);
+ }
+DEBUG_CODE_END();
+
nArgvSize = Argc;
/* Determine space needed for narrow Argv strings. */
for(count = 0; count < Argc; ++count) {
@@ -98,6 +113,7 @@ ArgvConvert(UINTN Argc, CHAR16 **Argv) nArgv[count] = string;
AVsz = wcstombs(string, Argv[count], nArgvSize);
string[AVsz] = 0; /* NULL terminate the argument */
+ DEBUG((DEBUG_INFO, "Cvt[%d] %d \"%s\" --> \"%a\"\n", (INT32)count, (INT32)AVsz, Argv[count], nArgv[count]));
string += AVsz + 1;
nArgvSize -= AVsz + 1;
if(nArgvSize < 0) {
@@ -119,7 +135,7 @@ ShellAppMain ( struct __filedes *mfd;
char **nArgv;
INTN ExitVal;
- INTN i;
+ int i;
ExitVal = (INTN)RETURN_SUCCESS;
gMD = AllocateZeroPool(sizeof(struct __MainData));
@@ -132,7 +148,6 @@ ShellAppMain ( _fltused = 1;
errno = 0;
EFIerrno = 0;
- gMD->FinalCleanup = &FinalCleanup;
#ifdef NT32dvm
gMD->ClocksPerSecond = 1; // For NT32 only
@@ -166,10 +181,33 @@ ShellAppMain ( ExitVal = (INTN)RETURN_INVALID_PARAMETER;
}
else {
- ExitVal = (INTN)main( (int)Argc, nArgv);
+ if( setjmp(gMD->MainExit) == 0) {
+ ExitVal = (INTN)main( (int)Argc, gMD->NArgV);
+ exitCleanup(ExitVal);
+ }
+ /* You reach here if:
+ * normal return from main()
+ * call to _Exit(), either directly or through exit().
+ */
+ ExitVal = (INTN)gMD->ExitValue;
+ }
+
+ if( ExitVal == EXIT_FAILURE) {
+ ExitVal = RETURN_ABORTED;
+ }
+
+ /* Close any open files */
+ for(i = OPEN_MAX - 1; i >= 0; --i) {
+ (void)close(i); // Close properly handles closing a closed file.
+ }
+
+ /* Free the global MainData structure */
+ if(gMD != NULL) {
+ if(gMD->NCmdLine != NULL) {
+ FreePool( gMD->NCmdLine );
+ }
+ FreePool( gMD );
}
}
- exit((int)ExitVal);
- /* Not Reached */
return ExitVal;
}
diff --git a/StdLib/LibC/Main/assert.c b/StdLib/LibC/Main/assert.c index 6bb53d6abd..a20a656ef0 100644 --- a/StdLib/LibC/Main/assert.c +++ b/StdLib/LibC/Main/assert.c @@ -18,7 +18,6 @@ #include <stdlib.h>
void
-EFIAPI
__assert(const char *func, const char *file, int line, const char *failedexpr)
{
if (func == NULL)
diff --git a/StdLib/LibC/Main/x86flt_rounds.c b/StdLib/LibC/Main/x86flt_rounds.c index d0478e2c1b..86b4846098 100644 --- a/StdLib/LibC/Main/x86flt_rounds.c +++ b/StdLib/LibC/Main/x86flt_rounds.c @@ -16,7 +16,6 @@ extern int internal_FPU_rmode( void ); static INT8 rmode[] = { 1, 3, 2, 0 };
int
-EFIAPI
__flt_rounds ( void )
{
return rmode[ internal_FPU_rmode() ];
diff --git a/StdLib/LibC/NetUtil/NetUtil.inf b/StdLib/LibC/NetUtil/NetUtil.inf index 537fe9cd42..9fc6b9b7be 100644 --- a/StdLib/LibC/NetUtil/NetUtil.inf +++ b/StdLib/LibC/NetUtil/NetUtil.inf @@ -48,12 +48,3 @@ LibStdLib
LibStdio
LibString
-
-################################################################
-#
-# The Build Options, below, are only used when building the Socket library.
-# DO NOT use them when building your application!
-# Nasty things could happen if you do.
-#
-#[BuildOptions]
-# MSFT:*_*_IA32_CC_FLAGS = /GL-
diff --git a/StdLib/LibC/StdLib/Environs.c b/StdLib/LibC/StdLib/Environs.c index 8472d0ef4c..40807279c9 100644 --- a/StdLib/LibC/StdLib/Environs.c +++ b/StdLib/LibC/StdLib/Environs.c @@ -29,6 +29,10 @@ #include <stdlib.h>
#include <MainData.h>
+/** Internal worker function used by exit().
+**/
+void exitCleanup(INTN ExitVal);
+
/* ################# Public Functions ################################### */
/** The abort function causes abnormal program termination to occur, unless
@@ -92,24 +96,7 @@ atexit(void (*handler)(void)) void
exit(int status)
{
- void (*CleanUp)(void); // Pointer to Cleanup Function
- int i;
-
- if(gMD != NULL) {
- CleanUp = gMD->cleanup; // Preserve the pointer to the Cleanup Function
-
- // Call all registered atexit functions in reverse order
- i = gMD->num_atexit;
- if( i > 0) {
- do {
- (gMD->atexit_handler[--i])();
- } while( i > 0);
- }
-
- if (CleanUp != NULL) {
- CleanUp();
- }
- }
+ exitCleanup((INTN) status);
_Exit(status);
}
@@ -129,17 +116,12 @@ exit(int status) void
_Exit(int status)
{
- RETURN_STATUS ExitVal = (RETURN_STATUS)status;
-
- if( ExitVal == EXIT_FAILURE) {
- ExitVal = RETURN_ABORTED;
- }
-
- if(gMD->FinalCleanup != NULL) {
- gMD->FinalCleanup(); // gMD does not exist when this returns.
- }
+ gMD->ExitValue = status; // Save our exit status. Allows a status of 0.
+ longjmp(gMD->MainExit, 0x55); // Get out of here. longjmp can't return 0. Use 0x55 for a non-zero value.
- gBS->Exit(gImageHandle, ExitVal, 0, NULL); /* abort() */
+#ifdef __GNUC__
+ __builtin__Exit(status); /* Keep GCC happy - never reached */
+#endif
}
/** If string is a null pointer, the system function determines whether the
diff --git a/StdLib/LibC/StdLib/NumericInt.c b/StdLib/LibC/StdLib/NumericInt.c index 058ad04959..97e52eb1bd 100644 --- a/StdLib/LibC/StdLib/NumericInt.c +++ b/StdLib/LibC/StdLib/NumericInt.c @@ -8,7 +8,7 @@ - atol: strtol(nptr, (char **)NULL, 10)
- atoll: strtoll(nptr, (char **)NULL, 10)
- Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
@@ -120,7 +120,7 @@ atoll(const char *nptr) static int
Digit2Val( int c)
{
- if(__isHexLetter(c)) { /* If c is one of [A-Fa-f]... */
+ if(isalpha(c)) { /* If c is one of [A-Za-z]... */
c = toupper(c) - 7; // Adjust so 'A' is ('9' + 1)
}
return c - '0'; // Value returned is between 0 and 35, inclusive.
@@ -183,13 +183,18 @@ Digit2Val( int c) long
strtol(const char * __restrict nptr, char ** __restrict endptr, int base)
{
+ const char *pEnd;
long Result = 0;
long Previous;
int temp;
BOOLEAN Negative = FALSE;
+ pEnd = nptr;
+
if((base < 0) || (base == 1) || (base > 36)) {
+ if(endptr != NULL) {
*endptr = NULL;
+ }
return 0;
}
// Skip leading spaces.
@@ -204,9 +209,29 @@ strtol(const char * __restrict nptr, char ** __restrict endptr, int base) Negative = TRUE;
++nptr;
}
- if( (base == 16) && (*nptr == '0') && (toupper(nptr[1]) == 'X')) {
- nptr += 2;
+
+ if(*nptr == '0') { /* Might be Octal or Hex */
+ if(toupper(nptr[1]) == 'X') { /* Looks like Hex */
+ if((base == 0) || (base == 16)) {
+ nptr += 2; /* Skip the "0X" */
+ base = 16; /* In case base was 0 */
+ }
+ }
+ else { /* Looks like Octal */
+ if((base == 0) || (base == 8)) {
+ ++nptr; /* Skip the leading "0" */
+ base = 8; /* In case base was 0 */
+ }
+ }
+ }
+ if(base == 0) { /* If still zero then must be decimal */
+ base = 10;
+ }
+ if(*nptr == '0') {
+ for( ; *nptr == '0'; ++nptr); /* Skip any remaining leading zeros */
+ pEnd = nptr;
}
+
while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
Previous = Result;
Result = (Result * base) + (long int)temp;
@@ -221,15 +246,15 @@ strtol(const char * __restrict nptr, char ** __restrict endptr, int base) errno = ERANGE;
break;
}
- ++nptr;
+ pEnd = ++nptr;
}
if(Negative) {
Result = -Result;
}
// Save pointer to final sequence
- if( endptr != NULL) {
- *endptr = (char *)nptr;
+ if(endptr != NULL) {
+ *endptr = (char *)pEnd;
}
return Result;
}
@@ -247,12 +272,17 @@ strtol(const char * __restrict nptr, char ** __restrict endptr, int base) unsigned long
strtoul(const char * __restrict nptr, char ** __restrict endptr, int base)
{
+ const char *pEnd;
unsigned long Result = 0;
unsigned long Previous;
int temp;
+ pEnd = nptr;
+
if((base < 0) || (base == 1) || (base > 36)) {
+ if(endptr != NULL) {
*endptr = NULL;
+ }
return 0;
}
// Skip leading spaces.
@@ -262,9 +292,29 @@ strtoul(const char * __restrict nptr, char ** __restrict endptr, int base) if(*nptr == '+') {
++nptr;
}
- if( (base == 16) && (*nptr == '0') && (toupper(nptr[1]) == 'X')) {
- nptr += 2;
+
+ if(*nptr == '0') { /* Might be Octal or Hex */
+ if(toupper(nptr[1]) == 'X') { /* Looks like Hex */
+ if((base == 0) || (base == 16)) {
+ nptr += 2; /* Skip the "0X" */
+ base = 16; /* In case base was 0 */
+ }
+ }
+ else { /* Looks like Octal */
+ if((base == 0) || (base == 8)) {
+ ++nptr; /* Skip the leading "0" */
+ base = 8; /* In case base was 0 */
+ }
+ }
+ }
+ if(base == 0) { /* If still zero then must be decimal */
+ base = 10;
+ }
+ if(*nptr == '0') {
+ for( ; *nptr == '0'; ++nptr); /* Skip any remaining leading zeros */
+ pEnd = nptr;
}
+
while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
Previous = Result;
Result = (Result * base) + (unsigned long)temp;
@@ -273,12 +323,12 @@ strtoul(const char * __restrict nptr, char ** __restrict endptr, int base) errno = ERANGE;
break;
}
- ++nptr;
+ pEnd = ++nptr;
}
// Save pointer to final sequence
- if( endptr != NULL) {
- *endptr = (char *)nptr;
+ if(endptr != NULL) {
+ *endptr = (char *)pEnd;
}
return Result;
}
@@ -297,13 +347,18 @@ strtoul(const char * __restrict nptr, char ** __restrict endptr, int base) long long
strtoll(const char * __restrict nptr, char ** __restrict endptr, int base)
{
+ const char *pEnd;
long long Result = 0;
long long Previous;
int temp;
BOOLEAN Negative = FALSE;
+ pEnd = nptr;
+
if((base < 0) || (base == 1) || (base > 36)) {
+ if(endptr != NULL) {
*endptr = NULL;
+ }
return 0;
}
// Skip leading spaces.
@@ -318,9 +373,29 @@ strtoll(const char * __restrict nptr, char ** __restrict endptr, int base) Negative = TRUE;
++nptr;
}
- if( (base == 16) && (*nptr == '0') && (toupper(nptr[1]) == 'X')) {
- nptr += 2;
+
+ if(*nptr == '0') { /* Might be Octal or Hex */
+ if(toupper(nptr[1]) == 'X') { /* Looks like Hex */
+ if((base == 0) || (base == 16)) {
+ nptr += 2; /* Skip the "0X" */
+ base = 16; /* In case base was 0 */
+ }
+ }
+ else { /* Looks like Octal */
+ if((base == 0) || (base == 8)) {
+ ++nptr; /* Skip the leading "0" */
+ base = 8; /* In case base was 0 */
+ }
+ }
+ }
+ if(base == 0) { /* If still zero then must be decimal */
+ base = 10;
+ }
+ if(*nptr == '0') {
+ for( ; *nptr == '0'; ++nptr); /* Skip any remaining leading zeros */
+ pEnd = nptr;
}
+
while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
Previous = Result;
Result = (Result * base) + (long long int)temp;
@@ -335,15 +410,15 @@ strtoll(const char * __restrict nptr, char ** __restrict endptr, int base) errno = ERANGE;
break;
}
- ++nptr;
+ pEnd = ++nptr;
}
if(Negative) {
Result = -Result;
}
// Save pointer to final sequence
- if( endptr != NULL) {
- *endptr = (char *)nptr;
+ if(endptr != NULL) {
+ *endptr = (char *)pEnd;
}
return Result;
}
@@ -361,12 +436,17 @@ strtoll(const char * __restrict nptr, char ** __restrict endptr, int base) unsigned long long
strtoull(const char * __restrict nptr, char ** __restrict endptr, int base)
{
+ const char *pEnd;
unsigned long long Result = 0;
unsigned long long Previous;
int temp;
+ pEnd = nptr;
+
if((base < 0) || (base == 1) || (base > 36)) {
+ if(endptr != NULL) {
*endptr = NULL;
+ }
return 0;
}
// Skip leading spaces.
@@ -376,9 +456,29 @@ strtoull(const char * __restrict nptr, char ** __restrict endptr, int base) if(*nptr == '+') {
++nptr;
}
- if( (base == 16) && (*nptr == '0') && (toupper(nptr[1]) == 'X')) {
- nptr += 2;
+
+ if(*nptr == '0') { /* Might be Octal or Hex */
+ if(toupper(nptr[1]) == 'X') { /* Looks like Hex */
+ if((base == 0) || (base == 16)) {
+ nptr += 2; /* Skip the "0X" */
+ base = 16; /* In case base was 0 */
+ }
+ }
+ else { /* Looks like Octal */
+ if((base == 0) || (base == 8)) {
+ ++nptr; /* Skip the leading "0" */
+ base = 8; /* In case base was 0 */
+ }
+ }
+ }
+ if(base == 0) { /* If still zero then must be decimal */
+ base = 10;
+ }
+ if(*nptr == '0') {
+ for( ; *nptr == '0'; ++nptr); /* Skip any remaining leading zeros */
+ pEnd = nptr;
}
+
while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
Previous = Result;
Result = (Result * base) + (unsigned long long)temp;
@@ -387,12 +487,12 @@ strtoull(const char * __restrict nptr, char ** __restrict endptr, int base) errno = ERANGE;
break;
}
- ++nptr;
+ pEnd = ++nptr;
}
// Save pointer to final sequence
- if( endptr != NULL) {
- *endptr = (char *)nptr;
+ if(endptr != NULL) {
+ *endptr = (char *)pEnd;
}
return Result;
}
diff --git a/StdLib/LibC/StdLib/StdLib.inf b/StdLib/LibC/StdLib/StdLib.inf index 21d1c1f4aa..ce1c3052cb 100644 --- a/StdLib/LibC/StdLib/StdLib.inf +++ b/StdLib/LibC/StdLib/StdLib.inf @@ -1,7 +1,7 @@ ## @file
# Standard C library: StdLib implementations.
#
-# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
@@ -36,6 +36,8 @@ strtoumax.c
Xabs.c
Xdiv.c
+ realpath.c
+ setprogname.c
[Packages]
StdLib/StdLib.dec
@@ -53,6 +55,7 @@ LibC
LibCType
LibSignal
+ PathLib
################################################################
#
diff --git a/StdLib/LibC/StdLib/realpath.c b/StdLib/LibC/StdLib/realpath.c new file mode 100644 index 0000000000..b9f674dbce --- /dev/null +++ b/StdLib/LibC/StdLib/realpath.c @@ -0,0 +1,57 @@ +/** @file
+ Implement the realpath function.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <LibConfig.h>
+#include <Library/BaseLib.h>
+#include <Library/PathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <errno.h>
+
+/**
+ The realpath() function shall derive, from the pathname pointed to by
+ file_name, an absolute pathname that names the same file, whose resolution
+ does not involve '.', '..', or symbolic links. The generated pathname shall
+ be stored as a null-terminated string, up to a maximum of {PATH_MAX} bytes,
+ in the buffer pointed to by resolved_name.
+
+ If resolved_name is a null pointer, the behavior of realpath() is
+ implementation-defined.
+
+ @param[in] file_name The filename to convert.
+ @param[in,out] resolved_name The resultant name.
+
+ @retval NULL An error occured.
+ @return resolved_name.
+**/
+char *
+realpath(
+ char *file_name,
+ char *resolved_name
+ )
+{
+ CHAR16 *Temp;
+ if (file_name == NULL || resolved_name == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ Temp = AllocateZeroPool((1+AsciiStrLen(file_name))*sizeof(CHAR16));
+ if (Temp == NULL) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ AsciiStrToUnicodeStr(file_name, Temp);
+ PathCleanUpDirectories(Temp);
+ UnicodeStrToAsciiStr(Temp, resolved_name);
+ return (resolved_name);
+}
\ No newline at end of file diff --git a/StdLib/LibC/StdLib/setprogname.c b/StdLib/LibC/StdLib/setprogname.c new file mode 100644 index 0000000000..3f2bc53cd5 --- /dev/null +++ b/StdLib/LibC/StdLib/setprogname.c @@ -0,0 +1,64 @@ +/** @file setprogname and getprogname
+
+ $NetBSD: setprogname.c,v 1.5 2008/04/28 20:24:12 martin Exp $
+
+ Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Todd Vierling.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <LibConfig.h>
+
+#ifndef HAVE_SETPROGNAME
+#include <string.h>
+
+static const char *__progname = NULL;
+
+void
+setprogname(const char *progname)
+{
+ __progname = strrchr(progname, '/');
+ if (__progname == NULL)
+ __progname = progname;
+ else
+ __progname++;
+}
+
+const char *
+getprogname(void)
+{
+ return __progname;
+}
+
+#endif
diff --git a/StdLib/LibC/StdLib/strtoumax.c b/StdLib/LibC/StdLib/strtoumax.c index 5bf64383d4..15658002a9 100644 --- a/StdLib/LibC/StdLib/strtoumax.c +++ b/StdLib/LibC/StdLib/strtoumax.c @@ -48,6 +48,8 @@ __RCSID("$NetBSD: strtoumax.c,v 1.1 2006/04/22 15:33:33 thorpej Exp $"); #include <inttypes.h>
#include <stddef.h>
+#include <Library/BaseLib.h>
+
#ifdef __weak_alias
__weak_alias(strtoumax, _strtoumax)
#endif
@@ -98,8 +100,8 @@ strtoumax(const char *nptr, char **endptr, int base) if (base == 0)
base = c == '0' ? 8 : 10;
- cutoff = UINTMAX_MAX / (uintmax_t)base;
- cutlim = (int)(UINTMAX_MAX % (uintmax_t)base);
+ cutoff = DivU64x32 ((UINT64) UINTMAX_MAX, (UINT32) base);
+ cutlim = (int) ModU64x32 ((UINT64) UINTMAX_MAX, (UINT32) base);
for (acc = 0, any = 0;; c = (unsigned char) *s++) {
if (isdigit(c))
c -= '0';
diff --git a/StdLib/LibC/Stdio/Stdio.inf b/StdLib/LibC/Stdio/Stdio.inf index 9d2adef1f6..6edc8867e8 100644 --- a/StdLib/LibC/Stdio/Stdio.inf +++ b/StdLib/LibC/Stdio/Stdio.inf @@ -72,6 +72,7 @@ snprintf.c
vsnprintf.c
+ fparseln.c
# Wide character functions
fgetwc.c #
diff --git a/StdLib/LibC/Stdio/freopen.c b/StdLib/LibC/Stdio/freopen.c index 4d34497317..75a086b84b 100644 --- a/StdLib/LibC/Stdio/freopen.c +++ b/StdLib/LibC/Stdio/freopen.c @@ -104,7 +104,7 @@ freopen(const char *file, const char *mode, FILE *fp) (void) __sflush(fp);
/* if close is NULL, closing is a no-op, hence pointless */
isopen = fp->_close != NULL;
- if ((wantfd = fp->_file) < 0 && isopen) {
+ if (((wantfd = fp->_file) >= 0) && isopen) {
(void) (*fp->_close)(fp->_cookie);
isopen = 0;
}
@@ -127,7 +127,7 @@ freopen(const char *file, const char *mode, FILE *fp) * keep fp->_base: it may be the wrong size. This loses the effect
* of any setbuffer calls, but stdio has always done this before.
*/
- if (isopen && f != wantfd)
+ if (isopen && (f != wantfd))
(void) (*fp->_close)(fp->_cookie);
if (fp->_flags & __SMBF)
free((char *)fp->_bf._base);
diff --git a/StdLib/LibC/Stdio/fseeko.c b/StdLib/LibC/Stdio/fseeko.c index 7fc7e42661..662d25f91a 100644 --- a/StdLib/LibC/Stdio/fseeko.c +++ b/StdLib/LibC/Stdio/fseeko.c @@ -238,6 +238,7 @@ fseeko(FILE *fp, off_t offset, int whence) fp->_r = (int)(n - o);
if (HASUB(fp))
FREEUB(fp);
+ WCIO_FREE(fp); /* Should this really be unconditional??? */
fp->_flags &= ~__SEOF;
FUNLOCKFILE(fp);
return (0);
@@ -261,6 +262,7 @@ fseeko(FILE *fp, off_t offset, int whence) fp->_p = fp->_bf._base;
if (HASUB(fp))
FREEUB(fp);
+ WCIO_FREE(fp); /* Should this really be unconditional??? */
fp->_flags &= ~__SEOF;
n = (int)(target - curoff);
if (n) {
@@ -290,9 +292,10 @@ dumb: /* success: clear EOF indicator and discard ungetc() data */
if (HASUB(fp))
FREEUB(fp);
+ WCIO_FREE(fp); /* Should this really be unconditional??? */
fp->_p = fp->_bf._base;
fp->_r = 0;
- /* fp->_w = 0; */ /* unnecessary (I think...) */
+ fp->_w = 0;
fp->_flags &= ~__SEOF;
FUNLOCKFILE(fp);
//Print(L"%a: %d\n", __func__, __LINE__);
diff --git a/StdLib/LibC/Stdio/gettemp.c b/StdLib/LibC/Stdio/gettemp.c index 1bd7dd3924..7b1c564c9a 100644 --- a/StdLib/LibC/Stdio/gettemp.c +++ b/StdLib/LibC/Stdio/gettemp.c @@ -45,7 +45,7 @@ #include "nbtool_config.h"
#endif
-#if !HAVE_NBTOOL_CONFIG_H || !HAVE_MKSTEMP || !HAVE_MKDTEMP
+#if !defined(HAVE_NBTOOL_CONFIG_H) || !defined(HAVE_MKSTEMP) || !defined(HAVE_MKDTEMP)
#include <sys/EfiCdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
diff --git a/StdLib/LibC/Stdio/local.h b/StdLib/LibC/Stdio/local.h index f9eaba9989..262deb3611 100644 --- a/StdLib/LibC/Stdio/local.h +++ b/StdLib/LibC/Stdio/local.h @@ -64,11 +64,11 @@ extern int _fwalk(int (*)(FILE *)); extern char *_mktemp(char *);
extern int __swsetup(FILE *);
extern int __sflags(const char *, int *);
-extern int __svfscanf(FILE * __restrict, const char * __restrict, _BSD_VA_LIST_)
+extern int __svfscanf(FILE * __restrict, const char * __restrict, va_list)
__attribute__((__format__(__scanf__, 2, 0)));
-extern int __svfscanf_unlocked(FILE * __restrict, const char * __restrict, _BSD_VA_LIST_)
+extern int __svfscanf_unlocked(FILE * __restrict, const char * __restrict, va_list)
__attribute__((__format__(__scanf__, 2, 0)));
-extern int __vfprintf_unlocked(FILE * __restrict, const char * __restrict, _BSD_VA_LIST_);
+extern int __vfprintf_unlocked(FILE * __restrict, const char * __restrict, va_list);
extern int __sdidinit;
@@ -80,8 +80,8 @@ extern wint_t __fputwc_unlock(wchar_t, FILE *); extern char *__fgetstr(FILE * __restrict, size_t * __restrict, int);
extern int __slbexpand(FILE *, size_t);
-extern int __vfwprintf_unlocked(FILE *, const wchar_t *, _BSD_VA_LIST_);
-extern int __vfwscanf_unlocked(FILE * __restrict, const wchar_t * __restrict, _BSD_VA_LIST_);
+extern int __vfwprintf_unlocked(FILE *, const wchar_t *, va_list);
+extern int __vfwscanf_unlocked(FILE * __restrict, const wchar_t * __restrict, va_list);
/*
* Return true iff the given FILE cannot be written now.
diff --git a/StdLib/LibC/Stdio/mkstemp.c b/StdLib/LibC/Stdio/mkstemp.c index 7ea578ce4a..d2962214dd 100644 --- a/StdLib/LibC/Stdio/mkstemp.c +++ b/StdLib/LibC/Stdio/mkstemp.c @@ -34,7 +34,7 @@ #include "nbtool_config.h"
#endif
-#if !HAVE_NBTOOL_CONFIG_H || !HAVE_MKSTEMP
+#if !defined(HAVE_NBTOOL_CONFIG_H) || !defined(HAVE_MKSTEMP)
#include <sys/EfiCdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
diff --git a/StdLib/LibC/Stdio/setbuffer.c b/StdLib/LibC/Stdio/setbuffer.c index 9527a4b3f6..761f67f88c 100644 --- a/StdLib/LibC/Stdio/setbuffer.c +++ b/StdLib/LibC/Stdio/setbuffer.c @@ -1,6 +1,13 @@ -/* $NetBSD: setbuffer.c,v 1.10 2003/08/07 16:43:31 agc Exp $ */
+/*
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License that accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -30,16 +37,12 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- */
+
+ NetBSD: setbuffer.c,v 1.10 2003/08/07 16:43:31 agc Exp
+ setbuffer.c 8.1 (Berkeley) 6/4/93
+*/
#include <LibConfig.h>
#include <sys/EfiCdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)setbuffer.c 8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: setbuffer.c,v 1.10 2003/08/07 16:43:31 agc Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
#include <assert.h>
#include <errno.h>
diff --git a/StdLib/LibC/Stdio/vfwprintf.c b/StdLib/LibC/Stdio/vfwprintf.c index 3c5332ac4a..0554edb645 100644 --- a/StdLib/LibC/Stdio/vfwprintf.c +++ b/StdLib/LibC/Stdio/vfwprintf.c @@ -1056,8 +1056,6 @@ reswitch: switch (ch) { xdigs = xdigs_upper;
expchar = 'P';
}
- if (prec >= 0)
- prec++;
if (flags & LONGDBL) {
fparg.ldbl = GETARG(long double);
dtoaresult =
@@ -1092,10 +1090,8 @@ reswitch: switch (ch) { case 'e':
case 'E':
expchar = ch;
- if (prec < 0) /* account for digit before decpt */
- prec = DEFPREC + 1;
- else
- prec++;
+ if (prec < 0)
+ prec = DEFPREC;
goto fp_begin;
case 'f':
case 'F':
@@ -1165,10 +1161,8 @@ fp_common: case 'e':
case 'E':
expchar = ch;
- if (prec < 0) /* account for digit before decpt */
- prec = DEFPREC /* + 1*/ ;
- else
- prec++;
+ if (prec < 0)
+ prec = DEFPREC;
goto fp_begin;
case 'f':
case 'F':
@@ -1242,16 +1236,21 @@ fp_begin: /*
* Make %[gG] smell like %[eE], but
* trim trailing zeroes if no # flag.
+ *
+ * Note: The precision field used with [gG] is the number significant
+ * digits to print. When converting to [eE] the digit before the
+ * decimal must not be included in the precision value.
*/
if (!(flags & ALT))
- prec = ndig;
+ prec = ndig - 1;
}
}
if (expchar) {
+ dprec = prec; /* In some cases dprec will not be set. Make sure it is set now */
expsize = exponent(expstr, expt - 1, expchar);
- size = expsize + prec;
- if (prec > 1 || flags & ALT)
- ++size;
+ size = expsize + prec + 1; /* Leading digit + exponent string + precision */
+ if (prec >= 1 || flags & ALT)
+ ++size; /* Decimal point is added to character count */
} else {
/* space for digits before decimal point */
if (expt > 0)
@@ -1322,7 +1321,7 @@ fp_begin: * defined manner.''
* -- ANSI X3J11
*/
- ujval = (uintmax_t)GETARG(void *);
+ ujval = (uintmax_t) (UINTN) GETARG(void *);
base = 16;
xdigs = xdigs_lower;
flags = flags | INTMAXT;
@@ -1332,7 +1331,7 @@ fp_begin: flags |= LONGINT;
/*FALLTHROUGH*/
case 's':
- if ((flags & LONGINT) != MULTI) {
+ if (((flags & LONGINT) ? 1:0) != MULTI) {
if ((result = GETARG(CHAR_T *)) == NULL)
result = STRCONST("(null)");
} else {
@@ -1538,7 +1537,7 @@ number: if ((dprec = prec) >= 0) PRINTANDPAD(result, convbuf + ndig, prec,
zeroes);
} else { /* %[eE] or sufficiently long %[gG] */
- if (prec > 1 || flags & ALT) {
+ if (prec >= 1 || flags & ALT) {
buf[0] = *result++;
buf[1] = *decimal_point;
PRINT(buf, 2);
@@ -2003,8 +2002,6 @@ cvt(double value, int ndigits, int flags, char *sign, int *decpt, int ch, *decpt = -ndigits + 1;
bp += *decpt;
}
- if (value == 0) /* kludge for __dtoa irregularity */
- rve = bp;
while (rve < bp)
*rve++ = '0';
}
diff --git a/StdLib/LibC/Stdio/vfwscanf.c b/StdLib/LibC/Stdio/vfwscanf.c index 3d7404171b..7bf3f66690 100644 --- a/StdLib/LibC/Stdio/vfwscanf.c +++ b/StdLib/LibC/Stdio/vfwscanf.c @@ -198,7 +198,7 @@ literal: goto input_failure;
if (wi != c) {
ungetwc(wi, fp);
- goto input_failure;
+ goto match_failure;
}
nread++;
continue;
@@ -721,20 +721,19 @@ literal: if ((width = parsefloat(fp, buf, buf + width)) == 0)
goto match_failure;
if ((flags & SUPPRESS) == 0) {
-#ifdef notyet
+#ifdef REAL_LONG_DOUBLE_SUPPORT
if (flags & LONGDBL) {
long double res = wcstold(buf, &p);
*va_arg(ap, long double *) = res;
} else
#endif
- if (flags & LONG) {
+ if (flags & (LONG | LONGDBL)) {
double res = wcstod(buf, &p);
*va_arg(ap, double *) = res;
-#ifdef notyet
- } else {
+ }
+ else {
float res = wcstof(buf, &p);
*va_arg(ap, float *) = res;
-#endif
}
#ifdef DEBUG
if (p - buf != width)
diff --git a/StdLib/LibC/Stdio/vprintf.c b/StdLib/LibC/Stdio/vprintf.c index 96d43ee7a0..46ebf32970 100644 --- a/StdLib/LibC/Stdio/vprintf.c +++ b/StdLib/LibC/Stdio/vprintf.c @@ -50,7 +50,7 @@ #include <stdio.h>
int
-vprintf(char const *fmt, _BSD_VA_LIST_ ap)
+vprintf(char const *fmt, va_list ap)
{
_DIAGASSERT(fmt != NULL);
diff --git a/StdLib/LibC/Stdio/vsnprintf.c b/StdLib/LibC/Stdio/vsnprintf.c index 23385ba0d8..16e06667bc 100644 --- a/StdLib/LibC/Stdio/vsnprintf.c +++ b/StdLib/LibC/Stdio/vsnprintf.c @@ -54,7 +54,7 @@ __weak_alias(vsnprintf,_vsnprintf) #endif
int
-vsnprintf(char *str, size_t n, const char *fmt, _BSD_VA_LIST_ ap)
+vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
{
int ret;
FILE f;
diff --git a/StdLib/LibC/Stdio/vsnprintf_ss.c b/StdLib/LibC/Stdio/vsnprintf_ss.c index 77a2887ea6..a71dd6d3e5 100644 --- a/StdLib/LibC/Stdio/vsnprintf_ss.c +++ b/StdLib/LibC/Stdio/vsnprintf_ss.c @@ -117,7 +117,7 @@ __weak_alias(vsnprintf_ss,_vsnprintf_ss) } while (/*CONSTCOND*/0)
int
-vsnprintf_ss(char *sbuf, size_t slen, const char *fmt0, _BSD_VA_LIST_ ap)
+vsnprintf_ss(char *sbuf, size_t slen, const char *fmt0, va_list ap)
{
const char *fmt; /* format string */
int ch; /* character from fmt */
diff --git a/StdLib/LibC/Stdio/vsprintf.c b/StdLib/LibC/Stdio/vsprintf.c index 4fb8d28155..9534d95e1b 100644 --- a/StdLib/LibC/Stdio/vsprintf.c +++ b/StdLib/LibC/Stdio/vsprintf.c @@ -53,7 +53,7 @@ #include "local.h"
int
-vsprintf(char *str, const char *fmt, _BSD_VA_LIST_ ap)
+vsprintf(char *str, const char *fmt, va_list ap)
{
int ret;
FILE f;
diff --git a/StdLib/LibC/String/Comparison.c b/StdLib/LibC/String/Comparison.c index e656fe73f5..b4980c7c1e 100644 --- a/StdLib/LibC/String/Comparison.c +++ b/StdLib/LibC/String/Comparison.c @@ -109,10 +109,15 @@ strcasecmp(const char *s1, const char *s2) {
const unsigned char *us1 = (const unsigned char *)s1,
*us2 = (const unsigned char *)s2;
+ int Difference;
- while (tolower(*us1) == tolower(*us2++))
- if (*us1++ == '\0')
+ while ( 0 == ( Difference = tolower(*us1) - tolower(*us2))) {
+ if (*us1 == 0) {
return (0);
- return (tolower(*us1) - tolower(*--us2));
+ }
+ us1 += 1;
+ us2 += 1;
+ }
+ return Difference;
}
diff --git a/StdLib/LibC/String/String.inf b/StdLib/LibC/String/String.inf index b6ab660051..62db60e6a5 100644 --- a/StdLib/LibC/String/String.inf +++ b/StdLib/LibC/String/String.inf @@ -33,6 +33,9 @@ Searching.c
ErrorList.c
strncasecmp.c
+ strlcpy.c
+ strlcat.c
+ strsep.c
[Packages]
StdLib/StdLib.dec
diff --git a/StdLib/LibC/String/strlcat.c b/StdLib/LibC/String/strlcat.c new file mode 100644 index 0000000000..fc9aba7b12 --- /dev/null +++ b/StdLib/LibC/String/strlcat.c @@ -0,0 +1,86 @@ +/* $NetBSD: strlcat.c,v 1.3 2007/06/04 18:19:27 christos Exp $ */
+/* $OpenBSD: strlcat.c,v 1.10 2003/04/12 21:56:39 millert Exp $ */
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <LibConfig.h>
+
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: strlcat.c,v 1.3 2007/06/04 18:19:27 christos Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef _LIBC
+#include "namespace.h"
+#endif
+#include <sys/types.h>
+#include <assert.h>
+#include <string.h>
+
+#ifdef _LIBC
+# ifdef __weak_alias
+__weak_alias(strlcat, _strlcat)
+# endif
+#endif
+
+#else
+#include <lib/libkern/libkern.h>
+#endif /* !_KERNEL && !_STANDALONE */
+
+#ifndef HAVE_STRLCAT
+/*
+ * Appends src to string dst of size siz (unlike strncat, siz is the
+ * full size of dst, not space left). At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
+ * Returns strlen(src) + MIN(siz, strlen(initial dst)).
+ * If retval >= siz, truncation occurred.
+ */
+size_t
+strlcat(char *dst, const char *src, size_t siz)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = siz;
+ size_t dlen;
+
+ _DIAGASSERT(dst != NULL);
+ _DIAGASSERT(src != NULL);
+
+ /* Find the end of dst and adjust bytes left but don't go past end */
+ while (n-- != 0 && *d != '\0')
+ d++;
+ dlen = d - dst;
+ n = siz - dlen;
+
+ if (n == 0)
+ return(dlen + strlen(s));
+ while (*s != '\0') {
+ if (n != 1) {
+ *d++ = *s;
+ n--;
+ }
+ s++;
+ }
+ *d = '\0';
+
+ return(dlen + (s - src)); /* count does not include NUL */
+}
+#endif
diff --git a/StdLib/LibC/String/strlcpy.c b/StdLib/LibC/String/strlcpy.c new file mode 100644 index 0000000000..5631e255d5 --- /dev/null +++ b/StdLib/LibC/String/strlcpy.c @@ -0,0 +1,82 @@ +/* $NetBSD: strlcpy.c,v 1.3 2007/06/04 18:19:27 christos Exp $ */
+/* $OpenBSD: strlcpy.c,v 1.7 2003/04/12 21:56:39 millert Exp $ */
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <LibConfig.h>
+
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: strlcpy.c,v 1.3 2007/06/04 18:19:27 christos Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef _LIBC
+#include "namespace.h"
+#endif
+#include <sys/types.h>
+#include <assert.h>
+#include <string.h>
+
+#ifdef _LIBC
+# ifdef __weak_alias
+__weak_alias(strlcpy, _strlcpy)
+# endif
+#endif
+#else
+#include <lib/libkern/libkern.h>
+#endif /* !_KERNEL && !_STANDALONE */
+
+
+#if !HAVE_STRLCPY
+/*
+ * Copy src to string dst of size siz. At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+size_t
+strlcpy(char *dst, const char *src, size_t siz)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = siz;
+
+ _DIAGASSERT(dst != NULL);
+ _DIAGASSERT(src != NULL);
+
+ /* Copy as many bytes as will fit */
+ if (n != 0 && --n != 0) {
+ do {
+ if ((*d++ = *s++) == 0)
+ break;
+ } while (--n != 0);
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src */
+ if (n == 0) {
+ if (siz != 0)
+ *d = '\0'; /* NUL-terminate dst */
+ while (*s++)
+ ;
+ }
+
+ return(s - src - 1); /* count does not include NUL */
+}
+#endif
diff --git a/StdLib/LibC/String/strncasecmp.c b/StdLib/LibC/String/strncasecmp.c index 2519df94e4..b3f6d05965 100644 --- a/StdLib/LibC/String/strncasecmp.c +++ b/StdLib/LibC/String/strncasecmp.c @@ -40,7 +40,6 @@ $NetBSD: strncasecmp.c,v 1.2 2007/06/04 18:19:27 christos Exp $
strcasecmp.c 8.1 (Berkeley) 6/4/93
**/
-
#include <LibConfig.h>
#include <sys/cdefs.h>
diff --git a/StdLib/LibC/String/strsep.c b/StdLib/LibC/String/strsep.c new file mode 100644 index 0000000000..234b0cabd6 --- /dev/null +++ b/StdLib/LibC/String/strsep.c @@ -0,0 +1,82 @@ +/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <LibConfig.h>
+
+#include <sys/cdefs.h>
+#include <string.h>
+#include <stdio.h>
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strsep.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Get next token from string *stringp, where tokens are possibly-empty
+ * strings separated by characters from delim.
+ *
+ * Writes NULs into the string at *stringp to end tokens.
+ * delim need not remain constant from call to call.
+ * On return, *stringp points past the last NUL written (if there might
+ * be further tokens), or is NULL (if there are definitely no more tokens).
+ *
+ * If *stringp is NULL, strsep returns NULL.
+ */
+char *
+strsep(
+ register char **stringp,
+ register const char *delim
+ )
+{
+ register char *s;
+ register const char *spanp;
+ register int c, sc;
+ char *tok;
+
+ if ((s = *stringp) == NULL)
+ return (NULL);
+ for (tok = s;;) {
+ c = *s++;
+ spanp = delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+ else
+ s[-1] = 0;
+ *stringp = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
+}
diff --git a/StdLib/LibC/Time/Time.c b/StdLib/LibC/Time/Time.c index 5cb9347752..e3eccb593b 100644 --- a/StdLib/LibC/Time/Time.c +++ b/StdLib/LibC/Time/Time.c @@ -82,7 +82,6 @@ static void localsub(const time_t * const timep, const long offset, struct tm * const tmp);
clock_t
-EFIAPI
__getCPS(void)
{
return gMD->ClocksPerSecond;
@@ -183,7 +182,7 @@ timesub( /** The clock function determines the processor time used.
- @return The clock function returns the implementation’s best
+ @return The clock function returns the implementation's best
approximation to the processor time used by the program since the
beginning of an implementation-defined era related only to the
program invocation. To determine the time in seconds, the value
@@ -196,7 +195,6 @@ timesub( CPU TimeStamp Counter ticks since the appliation started.
**/
clock_t
-EFIAPI
clock(void)
{
#ifndef NT32dvm
@@ -213,7 +211,6 @@ clock(void) /**
**/
double
-EFIAPI
difftime(time_t time1, time_t time0)
{
return (double)(time1 - time0);
@@ -429,7 +426,7 @@ time2sub( return t;
}
-static time_t
+time_t
time2(struct tm * const tmp, void (* const funcp)(const time_t*, long, struct tm*),
const long offset, int * const okayp)
{
@@ -542,7 +539,6 @@ time1( represented, the function returns the value (time_t)(-1).
**/
time_t
-EFIAPI
mktime(struct tm *timeptr)
{
/* From NetBSD */
@@ -558,14 +554,13 @@ mktime(struct tm *timeptr) /** The time function determines the current calendar time. The encoding of
the value is unspecified.
- @return The time function returns the implementation’s best approximation
+ @return The time function returns the implementation's best approximation
to the current calendar time. The value (time_t)(-1) is returned
if the calendar time is not available. If timer is not a null
pointer, the return value is also assigned to the object it
points to.
**/
time_t
-EFIAPI
time(time_t *timer)
{
time_t CalTime;
@@ -633,7 +628,6 @@ time(time_t *timer) @return The asctime function returns a pointer to the string.
**/
char *
-EFIAPI
asctime(const struct tm *timeptr)
{
register const char * wn;
@@ -663,7 +657,6 @@ asctime(const struct tm *timeptr) /**
**/
char *
-EFIAPI
ctime(const time_t *timer)
{
return asctime(localtime(timer));
@@ -672,7 +665,7 @@ ctime(const time_t *timer) /*
** gmtsub is to gmtime as localsub is to localtime.
*/
-static void
+void
gmtsub(
const time_t * const timep,
const long offset,
@@ -718,7 +711,6 @@ gmtsub( /**
**/
struct tm *
-EFIAPI
gmtime(const time_t *timer)
{
gmtsub(timer, 0L, &gMD->BDTime);
@@ -771,7 +763,6 @@ localsub(const time_t * const timep, const long offset, struct tm * const tmp) /**
**/
struct tm *
-EFIAPI
localtime(const time_t *timer)
{
tzset();
diff --git a/StdLib/LibC/Time/Time.inf b/StdLib/LibC/Time/Time.inf index 6de494f8d4..3ad226951d 100644 --- a/StdLib/LibC/Time/Time.inf +++ b/StdLib/LibC/Time/Time.inf @@ -32,6 +32,8 @@ strptime.c
TimeEfi.c
gettimeofday.c
+ timegm.c
+ itimer.c
[Packages]
StdLib/StdLib.dec
diff --git a/StdLib/LibC/Time/TimeEfi.c b/StdLib/LibC/Time/TimeEfi.c index 7b062c917b..8c033fd7d9 100644 --- a/StdLib/LibC/Time/TimeEfi.c +++ b/StdLib/LibC/Time/TimeEfi.c @@ -21,7 +21,6 @@ /* Convert an EFI_TIME structure into a C Standard tm structure. */
void
-EFIAPI
Efi2Tm( EFI_TIME *ET, struct tm *BT)
{
// Convert EFI time to broken-down time.
@@ -39,7 +38,6 @@ Efi2Tm( EFI_TIME *ET, struct tm *BT) /* Convert an EFI_TIME structure into a time_t value. */
time_t
-EFIAPI
Efi2Time( EFI_TIME *EfiBDtime)
{
Efi2Tm( EfiBDtime, &gMD->BDTime);
diff --git a/StdLib/LibC/Time/TimeVals.h b/StdLib/LibC/Time/TimeVals.h index 72827f9a91..f84f4f612a 100644 --- a/StdLib/LibC/Time/TimeVals.h +++ b/StdLib/LibC/Time/TimeVals.h @@ -110,8 +110,8 @@ struct rule { #define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
__BEGIN_DECLS
-extern void EFIAPI gmtload(struct state * const sp);
-extern void EFIAPI tzset(void);
+extern void gmtload(struct state * const sp);
+extern void tzset(void);
__END_DECLS
#endif /* _TIMEVAL_H */
diff --git a/StdLib/LibC/Time/ZoneProc.c b/StdLib/LibC/Time/ZoneProc.c index e33b99ed68..a7b589b7df 100644 --- a/StdLib/LibC/Time/ZoneProc.c +++ b/StdLib/LibC/Time/ZoneProc.c @@ -761,7 +761,6 @@ tzparse( }
void
-EFIAPI
gmtload(struct state * const sp)
{
if (tzload(gmt, sp) != 0)
@@ -788,7 +787,6 @@ tzsetwall(void) }
void
-EFIAPI
tzset(void)
{
register const char * name;
diff --git a/StdLib/LibC/Time/gettimeofday.c b/StdLib/LibC/Time/gettimeofday.c index 1c379a6b97..b26d157684 100644 --- a/StdLib/LibC/Time/gettimeofday.c +++ b/StdLib/LibC/Time/gettimeofday.c @@ -44,7 +44,6 @@ Heimdal: gettimeofday.c 14773 2005-04-12 11:29:18Z lha $
NetBSD: gettimeofday.c,v 1.2 2008/03/22 08:37:21 mlelstv Exp $
**/
-
#include <LibConfig.h>
#include <sys/EfiCdefs.h>
#include <sys/time.h>
diff --git a/StdLib/LibC/Time/itimer.c b/StdLib/LibC/Time/itimer.c new file mode 100644 index 0000000000..d6f6ab44c0 --- /dev/null +++ b/StdLib/LibC/Time/itimer.c @@ -0,0 +1,277 @@ +/** @file
+ setitimer and getitimer functions.
+
+ Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials are licensed and made available under
+ the terms and conditions of the BSD License that accompanies this distribution.
+ The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#include <LibConfig.h>
+#include <sys/EfiSysCall.h>
+#include <sys/time.h>
+#include <time.h>
+#include <errno.h>
+#include <sys/signal.h>
+#include <signal.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiLib.h>
+
+STATIC EFI_EVENT RealTimer = NULL;
+STATIC EFI_EVENT VirtualTimer = NULL;
+STATIC EFI_EVENT ProfTimer = NULL;
+
+STATIC struct itimerval RealTimerInfo = {{0,0},{0,0}};
+STATIC struct itimerval VirtualTimerInfo = {{0,0},{0,0}};
+STATIC struct itimerval ProfTimerInfo = {{0,0},{0,0}};
+
+/**
+ Function to queue the next iteration of the timer.
+
+ This will copy the interval part of the struct into the value and (if
+ non-zero), then queue the next timer event.
+
+ @param[in] TimerInfo The timer info structure.
+ @param[in] Event The EFI timer event.
+**/
+VOID
+EFIAPI
+SetNext (
+ IN struct itimerval *TimerInfo,
+ IN EFI_EVENT Event
+ )
+{
+ EFI_STATUS Status;
+
+ CopyMem(&(TimerInfo->it_value), &(TimerInfo->it_interval), sizeof(struct timeval));
+
+ //
+ // If now zero then close and be done.
+ //
+ if (TimerInfo->it_value.tv_sec+TimerInfo->it_value.tv_usec == 0) {
+ if (Event != NULL) {
+ gBS->CloseEvent(Event);
+ Event = NULL;
+ }
+ return;
+ }
+
+ //
+ // Set up for the next loop.
+ //
+ Status = gBS->SetTimer (
+ Event,
+ TimerRelative,
+ TimerInfo->it_value.tv_sec*10000000+TimerInfo->it_value.tv_usec*1000);
+
+ if (EFI_ERROR(Status)) {
+ gBS->CloseEvent(Event);
+ Event = NULL;
+ }
+}
+
+/**
+ Notification function for real timer.
+
+ @param[in] Event The event.
+ @param[in] Context Ignored.
+**/
+VOID
+EFIAPI
+iTimerRealNotifyFunction (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ raise(SIGALRM);
+ SetNext(&RealTimerInfo, RealTimer);
+}
+
+/**
+ Notification function for virtual timer.
+
+ @param[in] Event The event.
+ @param[in] Context Ignored.
+**/
+VOID
+EFIAPI
+iTimerVirtualNotifyFunction (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ raise(SIGVTALRM);
+ SetNext(&VirtualTimerInfo, VirtualTimer);
+}
+
+/**
+ Notification function for prof timer.
+
+ @param[in] Event The event.
+ @param[in] Context Ignored.
+**/
+VOID
+EFIAPI
+iTimerProfNotifyFunction (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ raise(SIGPROF);
+ SetNext(&ProfTimerInfo, ProfTimer);
+}
+
+/**
+ The setitimer() function sets the timer specified by which to the value
+ specified in the structure pointed to by value, and if ovalue is not a null
+ pointer, stores the previous value of the timer in the structure pointed to
+ by ovalue.
+
+ A timer value is defined by the itimerval structure. If it_value is non-zero,
+ it indicates the time to the next timer expiration. If it_interval is
+ non-zero, it specifies a value to be used in reloading it_value when the
+ timer expires. Setting it_value to 0 disables a timer, regardless of the
+ value of it_interval. Setting it_interval to 0 disables a timer after its
+ next expiration (assuming it_value is non-zero).
+
+ ITIMER_REAL
+ Decrements in real time. A SIGALRM signal is delivered when this timer
+ expires.
+
+ ITIMER_VIRTUAL
+ Decrements in process virtual time. It runs only when the process is
+ executing. A SIGVTALRM signal is delivered when it expires.
+
+ ITIMER_PROF
+ Decrements both in process virtual time and when the system is running on
+ behalf of the process. It is designed to be used by interpreters in
+ statistically profiling the execution of interpreted programs. Each time
+ the ITIMER_PROF timer expires, the SIGPROF signal is delivered.
+
+ @param[in] which Which timer to set. Possible values are described above.
+ @param[in] value The new value for this timer.
+ @param[out] ovalue The old value for this timer.
+
+ @retval 0 The operation was successful.
+ @retval -1 The operation failed. see errno for more details.
+**/
+
+int setitimer(
+ int which,
+ const struct itimerval *value,
+ struct itimerval *ovalue
+ )
+{
+ EFI_EVENT *EventPointer;
+ EFI_EVENT_NOTIFY NotifyFunction;
+ EFI_STATUS Status;
+
+ if (value == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (which == ITIMER_REAL) {
+ EventPointer = &RealTimer;
+ NotifyFunction = iTimerRealNotifyFunction;
+ if (ovalue != NULL) {
+ CopyMem(ovalue, &RealTimerInfo, sizeof(struct itimerval));
+ }
+ CopyMem(&RealTimerInfo, value, sizeof(struct itimerval));
+ } else if (which == ITIMER_VIRTUAL) {
+ EventPointer = &VirtualTimer;
+ NotifyFunction = iTimerVirtualNotifyFunction;
+ if (ovalue != NULL) {
+ CopyMem(ovalue, &VirtualTimerInfo, sizeof(struct itimerval));
+ }
+ CopyMem(&VirtualTimerInfo, value, sizeof(struct itimerval));
+ } else if (which == ITIMER_PROF) {
+ EventPointer = &ProfTimer;
+ NotifyFunction = iTimerProfNotifyFunction;
+ if (ovalue != NULL) {
+ CopyMem(ovalue, &ProfTimerInfo, sizeof(struct itimerval));
+ }
+ CopyMem(&ProfTimerInfo, value, sizeof(struct itimerval));
+ } else {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (*EventPointer != NULL) {
+ gBS->CloseEvent(*EventPointer);
+ *EventPointer = NULL;
+ }
+
+ //
+ // This was a 'please cancel me' request.
+ //
+ if (value->it_value.tv_sec+value->it_value.tv_usec == 0) {
+ return 0;
+ }
+
+ Status = gBS->CreateEvent (
+ EVT_TIMER|EVT_NOTIFY_SIGNAL,
+ EfiGetCurrentTpl(),
+ NotifyFunction,
+ NULL, // no context
+ EventPointer);
+
+ if (EFI_ERROR(Status)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ Status = gBS->SetTimer (
+ *EventPointer,
+ TimerRelative,
+ value->it_value.tv_sec*10000000+value->it_value.tv_usec*1000);
+
+ if (EFI_ERROR(Status)) {
+ gBS->CloseEvent(*EventPointer);
+ *EventPointer = NULL;
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return 0;
+}
+
+/**
+ Function to get the current state of a timer.
+
+ @param[in] which The identifier of the timer to get. See setitimer for
+ details.
+ @param[in] value The pointer to populate. must be pre-allocated to size.
+
+ @return 0 The operation was successful.
+ @return -1 The operation failed.
+ This means that value or which had an invalid value.
+**/
+int getitimer(
+ int which,
+ struct itimerval *value
+ )
+{
+
+ if (value == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (which == ITIMER_REAL) {
+ CopyMem(value, &RealTimerInfo, sizeof(struct itimerval));
+ } else if (which == ITIMER_VIRTUAL) {
+ CopyMem(value, &VirtualTimerInfo, sizeof(struct itimerval));
+ } else if (which == ITIMER_PROF) {
+ CopyMem(value, &ProfTimerInfo, sizeof(struct itimerval));
+ } else {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return 0;
+}
\ No newline at end of file diff --git a/StdLib/LibC/Time/strftime.c b/StdLib/LibC/Time/strftime.c index 6a5e2a34af..11757b6129 100644 --- a/StdLib/LibC/Time/strftime.c +++ b/StdLib/LibC/Time/strftime.c @@ -72,9 +72,9 @@ #define Locale _CurrentTimeLocale
-static char * EFIAPI _add(const char *, char *, const char * const);
-static char * EFIAPI _conv(const int, const char * const, char * const, const char * const);
-static char * EFIAPI _fmt(const char *, const struct tm * const, char *, const char * const, int *);
+static char * _add(const char *, char *, const char * const);
+static char * _conv(const int, const char * const, char * const, const char * const);
+static char * _fmt(const char *, const struct tm * const, char *, const char * const, int *);
#define NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
@@ -89,7 +89,6 @@ static char * EFIAPI _fmt(const char *, const struct tm * const, char *, const c #define IN_ALL 3
size_t
-EFIAPI
strftime(
char * __restrict s,
size_t maxsize,
@@ -128,7 +127,6 @@ strftime( }
static char *
-EFIAPI
_fmt(
const char * format,
const struct tm * const t,
@@ -574,7 +572,6 @@ label: }
static char *
-EFIAPI
_conv(
const int n,
const char * const format,
@@ -589,7 +586,6 @@ _conv( }
static char *
-EFIAPI
_add(
const char * str,
char * pt,
diff --git a/StdLib/LibC/Time/timegm.c b/StdLib/LibC/Time/timegm.c new file mode 100644 index 0000000000..a672dc8da1 --- /dev/null +++ b/StdLib/LibC/Time/timegm.c @@ -0,0 +1,113 @@ +/** @file
+ timegm implementation
+
+ Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials are licensed and made available under
+ the terms and conditions of the BSD License that accompanies this distribution.
+ The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ * Copyright (c) 1987, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Arthur David Olson of the National Cancer Institute.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+
+static char *sccsid = "from: @(#)ctime.c 5.26 (Berkeley) 2/23/91";
+
+
+ * This implementation of mktime is lifted straight from the NetBSD (BSD 4.4)
+ * version. I modified it slightly to divorce it from the internals of the
+ * ctime library. Thus this version can't use details of the internal
+ * timezone state file to figure out strange unnormalized struct tm values,
+ * as might result from someone doing date math on the tm struct then passing
+ * it to mktime.
+ *
+ * It just does as well as it can at normalizing the tm input, then does a
+ * binary search of the time space using the system's localtime() function.
+ *
+ * The original binary search was defective in that it didn't consider the
+ * setting of tm_isdst when comparing tm values, causing the search to be
+ * flubbed for times near the dst/standard time changeover. The original
+ * code seems to make up for this by grubbing through the timezone info
+ * whenever the binary search barfed. Since I don't have that luxury in
+ * portable code, I have to take care of tm_isdst in the comparison routine.
+ * This requires knowing how many minutes offset dst is from standard time.
+ *
+ * So, if you live somewhere in the world where dst is not 60 minutes offset,
+ * and your vendor doesn't supply mktime(), you'll have to edit this variable
+ * by hand. Sorry about that.
+
+ $NetBSD: mktime.c,v 1.4 2006/06/11 19:34:10 kardel Exp $
+**/
+
+#include <LibConfig.h>
+#include <time.h>
+
+/*
+ This funciton is in Time.c, which has a different license than timegm.
+*/
+time_t
+time2(struct tm * const tmp, void (* const funcp)(const time_t*, long, struct tm*),
+ const long offset, int * const okayp);
+
+/*
+ This funciton is in Time.c, which has a different license than timegm.
+*/
+void
+gmtsub(
+ const time_t * const timep,
+ const long offset,
+ struct tm * const tmp
+ );
+
+#ifndef WRONG
+#define WRONG (-1)
+#endif /* !defined WRONG */
+
+/*
+ Convert a tm structure to a GMT based time_t.
+*/
+time_t timegm( struct tm * tmp )
+{
+ register time_t t;
+ int okay;
+
+ tmp->tm_isdst = 0;
+ t = time2(tmp, gmtsub, 0, &okay);
+ if (okay || tmp->tm_isdst < 0)
+ return t;
+
+ return WRONG;
+}
\ No newline at end of file diff --git a/StdLib/LibC/Uefi/Devices/Console/daConsole.c b/StdLib/LibC/Uefi/Devices/Console/daConsole.c index c579959081..5dfc18acb4 100644 --- a/StdLib/LibC/Uefi/Devices/Console/daConsole.c +++ b/StdLib/LibC/Uefi/Devices/Console/daConsole.c @@ -45,6 +45,12 @@ static const int stdioFlags[NUM_SPECIAL] = { static DeviceNode *ConNode[NUM_SPECIAL];
static ConInstance *ConInstanceList;
+static wchar_t *ConReadBuf;
+
+/* Flags settable by Ioctl */
+static BOOLEAN TtyCooked;
+static BOOLEAN TtyEcho;
+
ssize_t
WideTtyCvt( CHAR16 *dest, const char *buf, size_t n)
{
@@ -127,74 +133,6 @@ da_ConSeek( }
}
-static
-ssize_t
-EFIAPI
-da_ConRead(
- IN OUT struct __filedes *filp,
- IN OUT off_t *offset, // Console ignores this
- IN size_t BufferSize,
- OUT VOID *Buffer
-)
-{
- EFI_SIMPLE_TEXT_INPUT_PROTOCOL *Proto;
- ConInstance *Stream;
- CHAR16 *OutPtr;
- EFI_INPUT_KEY Key;
- UINTN NumChar;
- UINTN Edex;
- EFI_STATUS Status = RETURN_SUCCESS;
- UINTN i;
-
- Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
- // Quick check to see if Stream looks reasonable
- if(Stream->Cookie != CON_COOKIE) { // Cookie == 'IoAb'
- EFIerrno = RETURN_INVALID_PARAMETER;
- return -1; // Looks like a bad This pointer
- }
- if(Stream->InstanceNum != STDIN_FILENO) {
- // Read only valid for stdin
- EFIerrno = RETURN_UNSUPPORTED;
- return -1;
- }
- // It looks like things are OK for trying to read
- // We will accumulate *BufferSize characters or until we encounter
- // an "activation" character. Currently any control character.
- Proto = (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)Stream->Dev;
- OutPtr = Buffer;
- NumChar = (BufferSize - 1) / sizeof(CHAR16);
- i = 0;
- do {
- if((Stream->UnGetKey.UnicodeChar == CHAR_NULL) && (Stream->UnGetKey.ScanCode == SCAN_NULL)) {
- Status = gBS->WaitForEvent( 1, &Proto->WaitForKey, &Edex);
- if(Status != RETURN_SUCCESS) {
- break;
- }
- Status = Proto->ReadKeyStroke(Proto, &Key);
- if(Status != RETURN_SUCCESS) {
- break;
- }
- }
- else {
- Key.ScanCode = Stream->UnGetKey.ScanCode;
- Key.UnicodeChar = Stream->UnGetKey.UnicodeChar;
- Stream->UnGetKey.ScanCode = SCAN_NULL;
- Stream->UnGetKey.UnicodeChar = CHAR_NULL;
- }
- if(Key.ScanCode == SCAN_NULL) {
- *OutPtr++ = Key.UnicodeChar;
- ++i;
- }
- if(iswcntrl(Key.UnicodeChar)) { // If a control character, or a scan code
- break;
- }
- } while(i < NumChar);
-
- *OutPtr = L'\0'; // Terminate the input buffer
- EFIerrno = Status;
- return (ssize_t)(i * sizeof(CHAR16)); // Will be 0 if we didn't get a key
-}
-
/* Write a NULL terminated WCS to the EFI console.
@param[in,out] BufferSize Number of bytes in Buffer. Set to zero if
@@ -265,6 +203,109 @@ da_ConWrite( return BufferSize;
}
+/** Read characters from the console input device.
+
+ @param[in,out] filp Pointer to file descriptor for this file.
+ @param[in,out] offset Ignored.
+ @param[in] BufferSize Buffer size, in bytes.
+ @param[out] Buffer Buffer in which to place the read characters.
+
+ @return Number of bytes actually placed into Buffer.
+
+ @todo Handle encodings other than ASCII-7 and UEFI.
+**/
+static
+ssize_t
+EFIAPI
+da_ConRead(
+ IN OUT struct __filedes *filp,
+ IN OUT off_t *offset, // Console ignores this
+ IN size_t BufferSize,
+ OUT VOID *Buffer
+)
+{
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL *Proto;
+ ConInstance *Stream;
+ wchar_t *OutPtr;
+ EFI_INPUT_KEY Key;
+ UINTN NumChar;
+ UINTN Edex;
+ EFI_STATUS Status = RETURN_SUCCESS;
+ UINTN i;
+ char EchoBuff[MB_CUR_MAX + 1];
+ int NumEcho;
+
+ Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
+ // Quick check to see if Stream looks reasonable
+ if(Stream->Cookie != CON_COOKIE) { // Cookie == 'IoAb'
+ EFIerrno = RETURN_INVALID_PARAMETER;
+ return -1; // Looks like a bad This pointer
+ }
+ if(Stream->InstanceNum != STDIN_FILENO) {
+ // Read only valid for stdin
+ EFIerrno = RETURN_UNSUPPORTED;
+ return -1;
+ }
+ // It looks like things are OK for trying to read
+ // We will accumulate *BufferSize characters or until we encounter
+ // an "activation" character. Currently any control character.
+ Proto = (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)Stream->Dev;
+ OutPtr = ConReadBuf;
+ NumChar = (BufferSize > MAX_INPUT)? MAX_INPUT : BufferSize;
+ i = 0;
+ do {
+ if((Stream->UnGetKey.UnicodeChar == CHAR_NULL) && (Stream->UnGetKey.ScanCode == SCAN_NULL)) {
+ Status = gBS->WaitForEvent( 1, &Proto->WaitForKey, &Edex);
+ if(Status != RETURN_SUCCESS) {
+ break;
+ }
+ Status = Proto->ReadKeyStroke(Proto, &Key);
+ if(Status != RETURN_SUCCESS) {
+ break;
+ }
+ }
+ else {
+ Key.ScanCode = Stream->UnGetKey.ScanCode;
+ Key.UnicodeChar = Stream->UnGetKey.UnicodeChar;
+ Stream->UnGetKey.ScanCode = SCAN_NULL;
+ Stream->UnGetKey.UnicodeChar = CHAR_NULL;
+ }
+ if(Key.ScanCode == SCAN_NULL) {
+ NumEcho = 0;
+ if(TtyCooked && (Key.UnicodeChar == CHAR_CARRIAGE_RETURN)) {
+ *OutPtr++ = CHAR_LINEFEED;
+ NumEcho = wctomb(EchoBuff, CHAR_LINEFEED);
+ }
+ else {
+ *OutPtr++ = Key.UnicodeChar;
+ NumEcho = wctomb(EchoBuff, Key.UnicodeChar);
+ }
+ ++i;
+ EchoBuff[NumEcho] = 0; /* Terminate the Echo buffer */
+ if(TtyEcho) {
+ /* Echo the character just input */
+ da_ConWrite(&gMD->fdarray[STDOUT_FILENO], NULL, 2, EchoBuff);
+ }
+ }
+ if(iswcntrl(Key.UnicodeChar)) { // If a control character, or a scan code
+ break;
+ }
+ } while(i < NumChar);
+
+ *OutPtr = L'\0'; // Terminate the input buffer
+
+ /* Convert the input buffer and place in Buffer.
+ If the fully converted input buffer won't fit, write what will and
+ leave the rest in ConReadBuf with ConReadLeft indicating how many
+ unconverted characters remain in ConReadBuf.
+ */
+ NumEcho = (int)wcstombs(Buffer, ConReadBuf, BufferSize); /* Re-use NumEcho to hold number of bytes in Buffer */
+ /* More work needs to be done before locales other than C can be supported. */
+
+ EFIerrno = Status;
+ return (ssize_t)NumEcho; // Will be 0 if we didn't get a key
+}
+
/** Console-specific helper function for the fstat() function.
st_size Set to number of characters read for stdin and number written for stdout and stderr.
@@ -347,27 +388,28 @@ da_ConIoctl( int
EFIAPI
da_ConOpen(
+ DeviceNode *DevNode,
struct __filedes *filp,
- void *DevInstance,
+ int DevInstance, // Not used for console devices
wchar_t *Path, // Not used for console devices
- wchar_t *Flags // Not used for console devices
+ wchar_t *MPath // Not used for console devices
)
{
ConInstance *Stream;
if((filp == NULL) ||
- (DevInstance == NULL))
+ (DevNode == NULL))
{
EFIerrno = RETURN_INVALID_PARAMETER;
return -1;
}
- Stream = (ConInstance *)DevInstance;
+ Stream = (ConInstance *)DevNode->InstanceList;
// Quick check to see if Stream looks reasonable
if(Stream->Cookie != CON_COOKIE) { // Cookie == 'IoAb'
EFIerrno = RETURN_INVALID_PARAMETER;
return -1; // Looks like a bad This pointer
}
- gMD->StdIo[Stream->InstanceNum] = (ConInstance *)DevInstance;
+ gMD->StdIo[Stream->InstanceNum] = Stream;
filp->f_iflags |= (S_IFREG | _S_IFCHR | _S_ICONSOLE);
filp->f_offset = 0;
filp->f_ops = &Stream->Abstraction;
@@ -448,7 +490,8 @@ __Cons_construct( int i;
ConInstanceList = (ConInstance *)AllocateZeroPool(NUM_SPECIAL * sizeof(ConInstance));
- if(ConInstanceList == NULL) {
+ ConReadBuf = (wchar_t *)AllocateZeroPool((MAX_INPUT + 1) * sizeof(wchar_t));
+ if((ConInstanceList == NULL) || (ConReadBuf == NULL)) {
return RETURN_OUT_OF_RESOURCES;
}
@@ -507,6 +550,10 @@ __Cons_construct( }
Stream->Parent = ConNode[i];
}
+ /* Initialize Ioctl flags until Ioctl is really implemented. */
+ TtyCooked = TRUE;
+ TtyEcho = TRUE;
+
return Status;
}
@@ -527,6 +574,9 @@ __Cons_deconstruct( if(ConInstanceList != NULL) {
FreePool(ConInstanceList);
}
+ if(ConReadBuf != NULL) {
+ FreePool(ConReadBuf);
+ }
return RETURN_SUCCESS;
}
diff --git a/StdLib/LibC/Uefi/Devices/UefiShell/daShell.c b/StdLib/LibC/Uefi/Devices/UefiShell/daShell.c index 37870e8384..d56db49159 100644 --- a/StdLib/LibC/Uefi/Devices/UefiShell/daShell.c +++ b/StdLib/LibC/Uefi/Devices/UefiShell/daShell.c @@ -29,6 +29,7 @@ #include <wctype.h>
#include <wchar.h>
#include <sys/fcntl.h>
+#include <sys/syslimits.h>
#include <kfile.h>
#include <Device/Device.h>
#include <MainData.h>
@@ -321,7 +322,7 @@ da_ShellIoctl( void *argp ///< May be a pointer or a value
)
{
- return 0;
+ return -EPERM;
}
/** Open an abstract Shell File.
@@ -329,10 +330,11 @@ da_ShellIoctl( int
EFIAPI
da_ShellOpen(
+ DeviceNode *DevNode,
struct __filedes *filp,
- void *DevInstance,
+ int DevInstance, /* Not used by Shell */
wchar_t *Path,
- wchar_t *Flags
+ wchar_t *MPath
)
{
UINT64 OpenMode;
@@ -340,8 +342,10 @@ da_ShellOpen( SHELL_FILE_HANDLE FileHandle;
GenericInstance *Gip;
char *NPath;
+ wchar_t *WPath;
RETURN_STATUS Status;
int oflags;
+ int retval;
EFIerrno = RETURN_SUCCESS;
@@ -356,6 +360,23 @@ da_ShellOpen( return -1;
}
+ /* Re-create the full mapped path for the shell. */
+ if(MPath != NULL) {
+ WPath = AllocateZeroPool(PATH_MAX * sizeof(wchar_t) + 1);
+ if(WPath == NULL) {
+ errno = ENOMEM;
+ EFIerrno = RETURN_OUT_OF_RESOURCES;
+ return -1;
+ }
+ wcsncpy(WPath, MPath, NAME_MAX); /* Get the Map Name */
+ wcsncat(WPath, Path, (PATH_MAX - NAME_MAX)); /* Append the path */
+ }
+ else {
+ WPath = Path;
+ }
+
+ retval = -1; /* Initially assume failure. */
+
/* Do we care if the file already exists?
If O_TRUNC, then delete the file. It will be created anew subsequently.
If O_EXCL, then error if the file exists and O_CREAT is set.
@@ -363,23 +384,24 @@ da_ShellOpen( !!!!!!!!! Change this to use ShellSetFileInfo() to actually truncate the file
!!!!!!!!! instead of deleting and re-creating it.
*/
+ do { /* Do fake exception handling */
if((oflags & O_TRUNC) || ((oflags & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT))) {
- Status = ShellIsFile( Path );
+ Status = ShellIsFile( WPath );
if(Status == RETURN_SUCCESS) {
// The file exists
if(oflags & O_TRUNC) {
- NPath = AllocateZeroPool(1024);
+ NPath = AllocateZeroPool(PATH_MAX);
if(NPath == NULL) {
errno = ENOMEM;
EFIerrno = RETURN_OUT_OF_RESOURCES;
- return -1;
+ break;
}
- wcstombs(NPath, Path, 1024);
+ wcstombs(NPath, WPath, PATH_MAX);
// We do a truncate by deleting the existing file and creating a new one.
if(unlink(NPath) != 0) {
filp->f_iflags = 0; // Release our reservation on this FD
FreePool(NPath);
- return -1; // errno and EFIerrno are already set.
+ break;
}
FreePool(NPath);
}
@@ -387,32 +409,40 @@ da_ShellOpen( errno = EEXIST;
EFIerrno = RETURN_ACCESS_DENIED;
filp->f_iflags = 0; // Release our reservation on this FD
- return -1;
+ break;
}
}
}
// Call the EFI Shell's Open function
- Status = ShellOpenFileByName( Path, &FileHandle, OpenMode, Attributes);
+ Status = ShellOpenFileByName( WPath, &FileHandle, OpenMode, Attributes);
if(RETURN_ERROR(Status)) {
filp->f_iflags = 0; // Release our reservation on this FD
// Set errno based upon Status
errno = EFI2errno(Status);
EFIerrno = Status;
- return -1;
+ break;
}
+ retval = 0;
// Successfully got a regular File
filp->f_iflags |= S_IFREG;
// Update the info in the fd
filp->devdata = (void *)FileHandle;
- Gip = (GenericInstance *)DevInstance;
+ Gip = (GenericInstance *)DevNode->InstanceList;
filp->f_offset = 0;
filp->f_ops = &Gip->Abstraction;
-// filp->devdata = FileHandle;
+ // filp->devdata = FileHandle;
+ } while(FALSE);
- return 0;
+ /* If we get this far, WPath is not NULL.
+ If MPath is not NULL, then WPath was allocated so we need to free it.
+ */
+ if(MPath != NULL) {
+ FreePool(WPath);
+ }
+ return retval;
}
#include <sys/poll.h>
@@ -468,9 +498,10 @@ da_ShellRename( RETURN_STATUS Status;
EFI_FILE_INFO *NewFileInfo;
EFI_FILE_INFO *OldFileInfo;
- char *NewFn;
+ wchar_t *NewFn;
int OldFd;
SHELL_FILE_HANDLE FileHandle;
+ wchar_t *NormalizedPath;
// Open old file
OldFd = open(from, O_RDWR, 0);
@@ -482,22 +513,20 @@ da_ShellRename( OldFileInfo = ShellGetFileInfo( FileHandle);
if(OldFileInfo != NULL) {
// Copy the Old file info into our new buffer, and free the old.
- memcpy(OldFileInfo, NewFileInfo, sizeof(EFI_FILE_INFO));
+ memcpy(NewFileInfo, OldFileInfo, sizeof(EFI_FILE_INFO));
FreePool(OldFileInfo);
+ // Normalize path and convert to WCS.
+ NormalizedPath = NormalizePath(to);
+ if (NormalizedPath != NULL) {
// Strip off all but the file name portion of new
- NewFn = strrchr(to, '/');
- if(NewFn == NULL) {
- NewFn = strrchr(to, '\\');
- if(NewFn == NULL) {
- NewFn = (char *)to;
- }
- }
- // Convert new name from MBCS to WCS
- (void)AsciiStrToUnicodeStr( NewFn, gMD->UString);
+ NewFn = GetFileNameFromPath(NormalizedPath);
// Copy the new file name into our new file info buffer
- wcsncpy(NewFileInfo->FileName, gMD->UString, wcslen(gMD->UString)+1);
+ wcsncpy(NewFileInfo->FileName, NewFn, wcslen(NewFn) + 1);
+ // Update the size of the structure.
+ NewFileInfo->Size = sizeof(EFI_FILE_INFO) + StrSize(NewFn);
// Apply the new file name
Status = ShellSetFileInfo(FileHandle, NewFileInfo);
+ free(NormalizedPath);
free(NewFileInfo);
if(Status == EFI_SUCCESS) {
// File has been successfully renamed. We are DONE!
@@ -507,6 +536,12 @@ da_ShellRename( EFIerrno = Status;
}
else {
+ free(NewFileInfo);
+ errno = ENOMEM;
+ }
+ }
+ else {
+ free(NewFileInfo);
errno = EIO;
}
}
@@ -619,7 +654,7 @@ __ctor_DevShell( Stream->Abstraction.fo_poll = &da_ShellPoll;
Stream->Abstraction.fo_flush = &fnullop_flush;
Stream->Abstraction.fo_stat = &da_ShellStat;
- Stream->Abstraction.fo_ioctl = &fbadop_ioctl;
+ Stream->Abstraction.fo_ioctl = &da_ShellIoctl;
Stream->Abstraction.fo_delete = &da_ShellDelete;
Stream->Abstraction.fo_rmdir = &da_ShellRmdir;
Stream->Abstraction.fo_mkdir = &da_ShellMkdir;
diff --git a/StdLib/LibC/Uefi/Devices/Utility/DevGenisis.c b/StdLib/LibC/Uefi/Devices/Utility/DevGenisis.c index 2bdb33ac53..6510ce7747 100644 --- a/StdLib/LibC/Uefi/Devices/Utility/DevGenisis.c +++ b/StdLib/LibC/Uefi/Devices/Utility/DevGenisis.c @@ -31,33 +31,33 @@ DeviceNode *daCurrentDevice = NULL; ///< Device currently being accessed fnullop_* Does nothing and returns success.
fbadop_* Does nothing and returns EPERM
*/
-int fnullop_fcntl (struct __filedes *filp, UINT32 Cmd, void *p3, void *p4)
+int EFIAPI fnullop_fcntl (struct __filedes *filp, UINT32 Cmd, void *p3, void *p4)
{ return 0; }
-short fnullop_poll (struct __filedes *filp, short Events)
+short EFIAPI fnullop_poll (struct __filedes *filp, short Events)
{
return ((POLLIN | POLLRDNORM | POLLOUT) & Events);
}
-int fnullop_flush (struct __filedes *filp)
+int EFIAPI fnullop_flush (struct __filedes *filp)
{ return 0; }
-int fbadop_stat (struct __filedes *filp, struct stat *StatBuf, void *Buf)
+int EFIAPI fbadop_stat (struct __filedes *filp, struct stat *StatBuf, void *Buf)
{ return -EPERM; }
-int fbadop_ioctl (struct __filedes *filp, ULONGN Cmd, void *argp)
+int EFIAPI fbadop_ioctl (struct __filedes *filp, ULONGN Cmd, void *argp)
{ return -EPERM; }
-int fbadop_delete (struct __filedes *filp)
+int EFIAPI fbadop_delete (struct __filedes *filp)
{ return -EPERM; }
-int fbadop_mkdir (const char *path, __mode_t perms)
+int EFIAPI fbadop_mkdir (const char *path, __mode_t perms)
{ return -EPERM; }
-int fbadop_rename (const char *from, const char *to)
+int EFIAPI fbadop_rename (const char *from, const char *to)
{ return -EPERM; }
-int fbadop_rmdir (struct __filedes *filp)
+int EFIAPI fbadop_rmdir (struct __filedes *filp)
{ return -EPERM; }
/** Add a new device to the device list.
diff --git a/StdLib/LibC/Uefi/Devices/Utility/Path.c b/StdLib/LibC/Uefi/Devices/Utility/Path.c index 92bb1a20b7..96392e018d 100644 --- a/StdLib/LibC/Uefi/Devices/Utility/Path.c +++ b/StdLib/LibC/Uefi/Devices/Utility/Path.c @@ -248,10 +248,16 @@ PathAlias( /** Parse a path producing the target device, device instance, and file path.
+ It is the caller's responsibility to free() FullPath and MapPath when they
+ are no longer needed.
+
@param[in] path
@param[out] FullPath
@param[out] DevNode
@param[out] Which
+ @param[out] MapPath OPTIONAL. If not NULL, it points to the place to save a pointer
+ to the extracted map name. If the path didn't have a map name,
+ then *MapPath is set to NULL.
@retval RETURN_SUCCESS The path was parsed successfully.
@retval RETURN_NOT_FOUND The path does not map to a valid device.
@@ -266,7 +272,8 @@ ParsePath( IN const char *path,
OUT wchar_t **FullPath,
OUT DeviceNode **DevNode,
- OUT int *Which
+ OUT int *Which,
+ OUT wchar_t **MapPath
)
{
int MapLen;
@@ -301,7 +308,7 @@ reclassify: // Get the Map Name, including the trailing ':'. */
MPath = calloc(MapLen+2, sizeof(wchar_t));
if(MPath != NULL) {
- wmemcpy(MPath, WPath, MapLen+2);
+ wmemcpy(MPath, WPath, MapLen+1);
}
else {
errno = ENOMEM;
@@ -346,6 +353,12 @@ reclassify: if(!RETURN_ERROR(Status)) {
*FullPath = WPath;
*Which = Instance;
+ if(MapPath != NULL) {
+ *MapPath = MPath;
+ }
+ else if(MPath != NULL) {
+ free(MPath); /* Caller doesn't want it so let MPath go free */
+ }
/* At this point, WPath is an absolute path,
MPath is either NULL or points to the Map Name,
@@ -359,6 +372,9 @@ reclassify: if(Node != NULL) {
Status = RETURN_SUCCESS;
}
+ else {
+ Status = RETURN_NOT_FOUND;
+ }
}
else {
/* This is a mapped path. */
@@ -375,8 +391,41 @@ reclassify: *DevNode = Node;
}
}
- if(MPath != NULL) {
- free(MPath); // We don't need this any more.
- }
return Status;
}
+
+/**
+ Parses a normalized wide character path and returns a pointer to the entry
+ following the last \. If a \ is not found in the path the return value will
+ be the same as the input value. All error conditions return NULL.
+
+ The behavior when passing in a path that has not been normalized is undefined.
+
+ @param Path - A pointer to a wide character string containing a path to a
+ directory or a file.
+
+ @return Pointer to the file name or terminal directory. NULL if an error is
+ detected.
+**/
+wchar_t *
+EFIAPI
+GetFileNameFromPath (
+ const wchar_t *Path
+ )
+{
+ wchar_t *Tail;
+
+ if (Path == NULL) {
+ return NULL;
+ }
+
+ Tail = wcsrchr(Path, L'\\');
+ if(Tail == NULL) {
+ Tail = (wchar_t *) Path;
+ } else {
+ // Move to the next character after the '\\' to get the file name.
+ Tail++;
+ }
+
+ return Tail;
+}
diff --git a/StdLib/LibC/Uefi/Devices/daConsole.inf b/StdLib/LibC/Uefi/Devices/daConsole.inf index 17865e4fec..802c6eb13c 100644 --- a/StdLib/LibC/Uefi/Devices/daConsole.inf +++ b/StdLib/LibC/Uefi/Devices/daConsole.inf @@ -16,7 +16,7 @@ [Defines]
INF_VERSION = 0x00010005
BASE_NAME = DevConsole
- FILE_GUID = 42c078ef-14a8-4e30-9329-6f12d796e54a
+ FILE_GUID = f6937495-1f44-4a8a-8a1b-5a669f9396f6
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
LIBRARY_CLASS = DevConsole
@@ -49,15 +49,3 @@ [Protocols]
gEfiSimpleTextInProtocolGuid
gEfiSimpleTextOutProtocolGuid
-
-################################################################
-#
-# The Build Options, below, are only used when building the C library.
-# DO NOT use them when building your application!
-# Nasty things could happen if you do.
-#
-# /Oi is required for Microsoft VC++ to allow "intrinsic" functions to be
-# defined in this library.
-#
-#[BuildOptions]
-# MSFT:*_*_*_CC_FLAGS = /Oi-
diff --git a/StdLib/LibC/Uefi/Devices/daShell.inf b/StdLib/LibC/Uefi/Devices/daShell.inf index 7b56f37363..56710259b6 100644 --- a/StdLib/LibC/Uefi/Devices/daShell.inf +++ b/StdLib/LibC/Uefi/Devices/daShell.inf @@ -19,7 +19,7 @@ [Defines]
INF_VERSION = 0x00010005
BASE_NAME = DevShell
- FILE_GUID = 42c078ef-14a8-4e30-9329-6f12d796e54a
+ FILE_GUID = 0a1d4fd8-4704-4501-85eb-93399492cbed
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
LIBRARY_CLASS = DevShell
@@ -49,15 +49,3 @@ LibWchar
LibUefi
DevUtility
-
-################################################################
-#
-# The Build Options, below, are only used when building the C library.
-# DO NOT use them when building your application!
-# Nasty things could happen if you do.
-#
-# /Oi is required for Microsoft VC++ to allow "intrinsic" functions to be
-# defined in this library.
-#
-#[BuildOptions]
-# MSFT:*_*_*_CC_FLAGS = /Oi-
diff --git a/StdLib/LibC/Uefi/Devices/daUtility.inf b/StdLib/LibC/Uefi/Devices/daUtility.inf index 53daad28ac..6bdc1eead9 100644 --- a/StdLib/LibC/Uefi/Devices/daUtility.inf +++ b/StdLib/LibC/Uefi/Devices/daUtility.inf @@ -15,7 +15,7 @@ [Defines]
INF_VERSION = 0x00010005
BASE_NAME = DevUtility
- FILE_GUID = 42c078ef-14a8-4e30-9329-6f12d796e54a
+ FILE_GUID = d6a9928c-3397-4dd1-818f-c664ba6dcaaf
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
LIBRARY_CLASS = DevUtility
@@ -42,15 +42,3 @@ LibC
LibWchar
LibUefi
-
-################################################################
-#
-# The Build Options, below, are only used when building the C library.
-# DO NOT use them when building your application!
-# Nasty things could happen if you do.
-#
-# /Oi- is required for Microsoft VC++ to allow "intrinsic" functions to be
-# defined in this library.
-#
-#[BuildOptions]
-# MSFT:*_*_*_CC_FLAGS = /Oi-
diff --git a/StdLib/LibC/Uefi/GetPass.c b/StdLib/LibC/Uefi/GetPass.c new file mode 100644 index 0000000000..9c0c1f4116 --- /dev/null +++ b/StdLib/LibC/Uefi/GetPass.c @@ -0,0 +1,57 @@ +/** @file Implement the getpass function.
+
+ Copyright (c) 2011, Intel Corporation <BR>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/ShellLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+
+static CHAR8 *ReturnStringAscii = NULL;
+
+char *getpass(const char *Prompt)
+{
+ BOOLEAN Ascii;
+ CHAR16 *ReturnString;
+
+ Ascii = FALSE;
+
+ Print(L"%a", Prompt);
+
+ ReturnString = ShellFileHandleReturnLine (gEfiShellParametersProtocol->StdIn, &Ascii);
+ if (ReturnString == NULL) {
+ return (NULL);
+ }
+
+ ReturnStringAscii = AllocateZeroPool((StrLen(ReturnString)+1)*sizeof(CHAR8));
+ if (ReturnStringAscii == NULL) {
+ return (NULL);
+ }
+
+ UnicodeStrToAsciiStr(ReturnString, ReturnStringAscii);
+
+ FreePool(ReturnString);
+
+ return (ReturnStringAscii);
+}
+
+EFI_STATUS
+EFIAPI
+DestructMePlease (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ SHELL_FREE_NON_NULL(ReturnStringAscii);
+
+ return EFI_SUCCESS;
+}
\ No newline at end of file diff --git a/StdLib/LibC/Uefi/StubFunctions.c b/StdLib/LibC/Uefi/StubFunctions.c new file mode 100644 index 0000000000..da2eaf9148 --- /dev/null +++ b/StdLib/LibC/Uefi/StubFunctions.c @@ -0,0 +1,79 @@ +/** @file
+ Implement the invalid functions to return failures.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <sys/EfiCdefs.h>
+#include <sys/featuretest.h>
+#include <namespace.h>
+#include <stdio.h>
+#include <pwd.h>
+#include <errno.h>
+
+struct passwd *
+getpwuid (uid_t uid)
+{
+ uid;
+ errno = EPERM;
+ return NULL;
+}
+
+char *getlogin (void)
+{
+ errno = EPERM;
+ return NULL;
+}
+
+struct passwd *
+getpwnam (const char *name)
+{
+ name;
+ errno = EPERM;
+ return NULL;
+}
+
+uid_t getuid (void)
+{
+ return 0;
+}
+
+pid_t fork (void)
+{
+ errno = EPERM;
+ return (-1);
+}
+
+int chmod (const char *c, mode_t m)
+{
+ errno = EPERM;
+ return (-1);
+}
+
+pid_t wait(int *stat_loc) {
+ return 0;
+}
+
+FILE *popen (const char *cmd, const char *type)
+{
+ errno = EPERM;
+ return NULL;
+}
+
+int pclose (FILE *stream)
+{
+ errno = EPERM;
+ return -1;
+}
+
+int access (const char *path, int amode)
+{
+ return 0;
+}
diff --git a/StdLib/LibC/Uefi/SysCalls.c b/StdLib/LibC/Uefi/SysCalls.c index b3ca5b89b4..d2fb0c6af6 100644 --- a/StdLib/LibC/Uefi/SysCalls.c +++ b/StdLib/LibC/Uefi/SysCalls.c @@ -524,7 +524,7 @@ mkdir (const char *path, __mode_t perms) int Instance = 0;
int retval = 0;
- Status = ParsePath(path, &NewPath, &Node, &Instance);
+ Status = ParsePath(path, &NewPath, &Node, &Instance, NULL);
if(Status == RETURN_SUCCESS) {
GenI = Node->InstanceList;
if(GenI == NULL) {
@@ -532,7 +532,7 @@ mkdir (const char *path, __mode_t perms) retval = -1;
}
else {
- GenI += (Instance * Node->InstanceSize);
+ //GenI += (Instance * Node->InstanceSize);
retval = ((GenericInstance *)GenI)->Abstraction.fo_mkdir( path, perms);
}
free(NewPath);
@@ -567,11 +567,15 @@ mkdir (const char *path, __mode_t perms) O_EXCL -- if O_CREAT is also set, open will fail if the file already exists.
**/
int
-open (const char *path, int oflags, int mode)
+open(
+ const char *path,
+ int oflags,
+ int mode
+ )
{
wchar_t *NewPath;
+ wchar_t *MPath;
DeviceNode *Node;
- char *GenI = NULL;
struct __filedes *filp;
int Instance = 0;
RETURN_STATUS Status;
@@ -579,10 +583,10 @@ open (const char *path, int oflags, int mode) int fd = -1;
int doresult;
- Status = ParsePath(path, &NewPath, &Node, &Instance);
+ Status = ParsePath(path, &NewPath, &Node, &Instance, &MPath);
if(Status == RETURN_SUCCESS) {
- if((Node != NULL) &&
- ((GenI = Node->InstanceList) == NULL)) {
+ if((Node == NULL) ||
+ (Node->InstanceList == NULL)) {
errno = EPERM;
}
else {
@@ -595,15 +599,14 @@ open (const char *path, int oflags, int mode) if( fd < 0 ) {
// All available FDs are in use
errno = EMFILE;
- return -1;
}
+ else {
filp = &gMD->fdarray[fd];
// Save the flags and mode in the File Descriptor
filp->Oflags = oflags;
filp->Omode = mode;
- GenI += (Instance * Node->InstanceSize);
- doresult = Node->OpenFunc(filp, GenI, NewPath, NULL);
+ doresult = Node->OpenFunc(Node, filp, Instance, NewPath, MPath);
if(doresult < 0) {
filp->f_iflags = 0; // Release this FD
fd = -1; // Indicate an error
@@ -618,8 +621,14 @@ open (const char *path, int oflags, int mode) FILE_SET_MATURE(filp);
}
}
+ }
+ if(NewPath != NULL) {
free(NewPath);
}
+ }
+ if(MPath != NULL) {
+ free(MPath); // We don't need this any more.
+ }
// return the fd of our now open file
return fd;
}
@@ -748,6 +757,7 @@ poll ( }
} while (( 0 == SelectedFDs )
&& ( EFI_SUCCESS == Status ));
+
//
// Stop the timer
//
@@ -776,7 +786,6 @@ poll ( }
-
/** The rename() function changes the name of a file.
The old argument points to the pathname of the file to be renamed. The new
argument points to the new pathname of the file.
@@ -807,7 +816,6 @@ poll ( shall be changed or created.
**/
int
-EFIAPI
rename(
const char *from,
const char *to
@@ -820,7 +828,7 @@ rename( RETURN_STATUS Status;
int retval = -1;
- Status = ParsePath(from, &FromPath, &FromNode, &Instance);
+ Status = ParsePath(from, &FromPath, &FromNode, &Instance, NULL);
if(Status == RETURN_SUCCESS) {
GenI = FromNode->InstanceList;
if(GenI == NULL) {
@@ -828,7 +836,7 @@ rename( retval = -1;
}
else {
- GenI += (Instance * FromNode->InstanceSize);
+ //GenI += (Instance * FromNode->InstanceSize);
retval = ((GenericInstance *)GenI)->Abstraction.fo_rename( from, to);
}
free(FromPath);
@@ -839,7 +847,6 @@ rename( /**
**/
int
-EFIAPI
rmdir(
const char *path
)
@@ -1006,13 +1013,13 @@ ioctl( from a file associated with a terminal may return one typed line of data.
If fildes does not refer to a directory, the function reads the requested
- number of bytes from the file at the file’s current position and returns
+ number of bytes from the file at the file's current position and returns
them in buf. If the read goes beyond the end of the file, the read
- length is truncated to the end of the file. The file’s current position is
+ length is truncated to the end of the file. The file's current position is
increased by the number of bytes returned.
If fildes refers to a directory, the function reads the directory entry at
- the file’s current position and returns the entry in buf. If buf
+ the file's current position and returns the entry in buf. If buf
is not large enough to hold the current directory entry, then
errno is set to EBUFSIZE, EFIerrno is set to EFI_BUFFER_TOO_SMALL, and the
current file position is not updated. The size of the buffer needed to read
@@ -1129,3 +1136,56 @@ char return (UnicodeStrToAsciiStr(Cwd, buf));
}
+
+/** Change the current working directory.
+
+ The chdir() function shall cause the directory named by the pathname
+ pointed to by the path argument to become the current working directory;
+ that is, the starting point for path searches for pathnames not beginning
+ with '/'.
+
+ @param[in] path The new path to set.
+
+ @todo Add non-shell CWD changing.
+**/
+int
+chdir (const char *path)
+{
+ CONST CHAR16 *Cwd;
+ EFI_STATUS Status;
+ CHAR16 *UnicodePath;
+
+ Cwd = ShellGetCurrentDir(NULL);
+ if (Cwd != NULL) {
+ /* We have shell support */
+ UnicodePath = AllocatePool(((AsciiStrLen (path) + 1) * sizeof (CHAR16)));
+ if (UnicodePath == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ AsciiStrToUnicodeStr(path, UnicodePath);
+ Status = gEfiShellProtocol->SetCurDir(NULL, UnicodePath);
+ FreePool(UnicodePath);
+ if (EFI_ERROR(Status)) {
+ errno = EACCES;
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+
+ /* Add here for non-shell */
+ errno = EACCES;
+ return -1;
+}
+
+pid_t tcgetpgrp (int x)
+{
+ return ((pid_t)(UINTN)(gImageHandle));
+}
+
+pid_t getpgrp(void)
+{
+ return ((pid_t)(UINTN)(gImageHandle));
+}
+
diff --git a/StdLib/LibC/Uefi/Uefi.inf b/StdLib/LibC/Uefi/Uefi.inf index 084d6c4fc3..30b619b409 100644 --- a/StdLib/LibC/Uefi/Uefi.inf +++ b/StdLib/LibC/Uefi/Uefi.inf @@ -16,18 +16,24 @@ [Defines]
INF_VERSION = 0x00010005
BASE_NAME = LibUefi
- FILE_GUID = 39356e02-26bf-4cfb-9564-378ce25e702f
+ FILE_GUID = 1dcff17c-aa53-4b78-b234-864027555035
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
LIBRARY_CLASS = LibUefi
+ LIBRARY_CONSTRUCTOR = DestructMePlease
#
# VALID_ARCHITECTURES = IA32 X64 IPF
#
[Sources]
+ select.c
SysCalls.c
+ writev.c
Xform.c
+ compat.c
+ GetPass.c
+ StubFunctions.c
[Packages]
StdLib/StdLib.dec
diff --git a/StdLib/LibC/Uefi/compat.c b/StdLib/LibC/Uefi/compat.c new file mode 100644 index 0000000000..7f250d15ff --- /dev/null +++ b/StdLib/LibC/Uefi/compat.c @@ -0,0 +1,847 @@ +/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: compat.c,v 1.1.1.1 2008/08/24 05:33:08 gmcgarry Exp $
+
+ * Copyright (c) 1997, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Klaus Klein and Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $NetBSD: compat.c,v 1.1.1.1 2008/08/24 05:33:08 gmcgarry Exp $
+
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $NetBSD: compat.c,v 1.1.1.1 2008/08/24 05:33:08 gmcgarry Exp $
+ */
+#include <LibConfig.h>
+#include <string.h>
+#include <fcntl.h>
+
+#ifndef HAVE_GETOPT
+char *optarg;
+int optind = 1;
+int
+getopt(int argc, char **argv, char *args)
+{
+ size_t n;
+ size_t nlen = strlen(args);
+ char cmd;
+ char rv;
+
+ if (argv[optind] && *argv[optind] == '-') {
+ cmd = *(argv[optind] + 1);
+
+ for (n = 0; n < nlen; n++) {
+ if (args[n] == ':')
+ continue;
+ if (args[n] == cmd) {
+ rv = *(argv[optind] + 1);
+ if (args[n+1] == ':') {
+ if (*(argv[optind] + 2) != '\0') {
+ optarg = argv[optind] + 2;
+ optind += 1;
+ } else {
+ optarg = argv[optind + 1];
+ optind += 2;
+ }
+ if (!optarg)
+ optarg="";
+ return rv;
+ } else {
+ optarg = NULL;
+ optind += 1;
+ return rv;
+ }
+ }
+ }
+ }
+
+ return -1;
+}
+#endif
+
+#ifdef WIN32
+#define ISPATHSEPARATOR(x) ((x == '/') || (x == '\\'))
+#else
+#define ISPATHSEPARATOR(x) (x == '/')
+#endif
+
+#ifndef HAVE_BASENAME
+#ifndef PATH_MAX
+#define PATH_MAX 5000
+#endif
+
+char *
+basename(char *path)
+{
+ static char singledot[] = ".";
+ static char result[PATH_MAX];
+ char *p, *lastp;
+ size_t len;
+
+ /*
+ * If `path' is a null pointer or points to an empty string,
+ * return a pointer to the string ".".
+ */
+ if ((path == NULL) || (*path == '\0'))
+ return (singledot);
+
+ /* Strip trailing slashes, if any. */
+ lastp = path + strlen(path) - 1;
+ while (lastp != path && ISPATHSEPARATOR(*lastp))
+ lastp--;
+
+ /* Now find the beginning of this (final) component. */
+ p = lastp;
+ while (p != path && !ISPATHSEPARATOR(*(p - 1)))
+ p--;
+
+ /* ...and copy the result into the result buffer. */
+ len = (lastp - p) + 1 /* last char */;
+ if (len > (PATH_MAX - 1))
+ len = PATH_MAX - 1;
+
+ memcpy(result, p, len);
+ result[len] = '\0';
+
+ return (result);
+}
+#endif
+
+#if !defined(HAVE_MKSTEMP) && !defined(WIN32)
+int
+mkstemp(char *path)
+{
+ char *start, *trv;
+ unsigned int pid;
+
+ /* To guarantee multiple calls generate unique names even if
+ the file is not created. 676 different possibilities with 7
+ or more X's, 26 with 6 or less. */
+ static char xtra[2] = "aa";
+ int xcnt = 0;
+
+ pid = getpid();
+
+ /* Move to end of path and count trailing X's. */
+ for (trv = path; *trv; ++trv)
+ if (*trv == 'X')
+ xcnt++;
+ else
+ xcnt = 0;
+
+ /* Use at least one from xtra. Use 2 if more than 6 X's. */
+ if (*(trv - 1) == 'X')
+ *--trv = xtra[0];
+ if (xcnt > 6 && *(trv - 1) == 'X')
+ *--trv = xtra[1];
+
+ /* Set remaining X's to pid digits with 0's to the left. */
+ while (*--trv == 'X') {
+ *trv = (pid % 10) + '0';
+ pid /= 10;
+ }
+
+ /* update xtra for next call. */
+ if (xtra[0] != 'z')
+ xtra[0]++;
+ else {
+ xtra[0] = 'a';
+ if (xtra[1] != 'z')
+ xtra[1]++;
+ else
+ xtra[1] = 'a';
+ }
+
+ return open(path, O_CREAT | O_EXCL | O_RDWR, 0600);
+}
+#endif
+
+#ifndef HAVE_FFS
+int
+ffs(int x)
+{
+ int r = 1;
+ if (!x) return 0;
+ if (!(x & 0xffff)) { x >>= 16; r += 16; }
+ if (!(x & 0xff)) { x >>= 8; r += 8; }
+ if (!(x & 0xf)) { x >>= 4; r += 4; }
+ if (!(x & 3)) { x >>= 2; r += 2; }
+ if (!(x & 1)) { x >>= 1; r += 1; }
+
+ return r;
+}
+#endif
+
+/*
+ * Copyright Patrick Powell 1995
+ * This code is based on code written by Patrick Powell (papowell@astart.com)
+ * It may be used for any purpose as long as this notice remains intact
+ * on all source code distributions
+ */
+
+#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
+
+static void
+dopr(char *buffer, size_t maxlen, const char *format, va_list args);
+
+static void
+fmtstr(char *buffer, size_t *currlen, size_t maxlen, char *value, int flags,
+ int min, int max);
+
+static void
+fmtint(char *buffer, size_t *currlen, size_t maxlen, long value, int base,
+ int min, int max, int flags);
+
+static void
+fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue,
+ int min, int max, int flags);
+
+static void
+dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
+
+/*
+ * dopr(): poor man's version of doprintf
+ */
+
+/* format read states */
+#define DP_S_DEFAULT 0
+#define DP_S_FLAGS 1
+#define DP_S_MIN 2
+#define DP_S_DOT 3
+#define DP_S_MAX 4
+#define DP_S_MOD 5
+#define DP_S_CONV 6
+#define DP_S_DONE 7
+
+/* format flags - Bits */
+#define DP_F_MINUS (1 << 0)
+#define DP_F_PLUS (1 << 1)
+#define DP_F_SPACE (1 << 2)
+#define DP_F_NUM (1 << 3)
+#define DP_F_ZERO (1 << 4)
+#define DP_F_UP (1 << 5)
+#define DP_F_UNSIGNED (1 << 6)
+
+/* Conversion Flags */
+#define DP_C_SHORT 1
+#define DP_C_LONG 2
+#define DP_C_LDOUBLE 3
+#define DP_C_LONG_LONG 4
+
+#define char_to_int(p) (p - '0')
+#define abs_val(p) (p < 0 ? -p : p)
+
+
+static void
+dopr(char *buffer, size_t maxlen, const char *format, va_list args)
+{
+ char *strvalue, ch;
+ long value;
+ long double fvalue;
+ int min = 0, max = -1, state = DP_S_DEFAULT, flags = 0, cflags = 0;
+ size_t currlen = 0;
+
+ ch = *format++;
+
+ while (state != DP_S_DONE) {
+ if ((ch == '\0') || (currlen >= maxlen))
+ state = DP_S_DONE;
+
+ switch(state) {
+ case DP_S_DEFAULT:
+ if (ch == '%')
+ state = DP_S_FLAGS;
+ else
+ dopr_outch(buffer, &currlen, maxlen, ch);
+ ch = *format++;
+ break;
+ case DP_S_FLAGS:
+ switch (ch) {
+ case '-':
+ flags |= DP_F_MINUS;
+ ch = *format++;
+ break;
+ case '+':
+ flags |= DP_F_PLUS;
+ ch = *format++;
+ break;
+ case ' ':
+ flags |= DP_F_SPACE;
+ ch = *format++;
+ break;
+ case '#':
+ flags |= DP_F_NUM;
+ ch = *format++;
+ break;
+ case '0':
+ flags |= DP_F_ZERO;
+ ch = *format++;
+ break;
+ default:
+ state = DP_S_MIN;
+ break;
+ }
+ break;
+ case DP_S_MIN:
+ if (isdigit((unsigned char)ch)) {
+ min = 10 * min + char_to_int (ch);
+ ch = *format++;
+ } else if (ch == '*') {
+ min = va_arg (args, int);
+ ch = *format++;
+ state = DP_S_DOT;
+ } else
+ state = DP_S_DOT;
+ break;
+ case DP_S_DOT:
+ if (ch == '.') {
+ state = DP_S_MAX;
+ ch = *format++;
+ } else
+ state = DP_S_MOD;
+ break;
+ case DP_S_MAX:
+ if (isdigit((unsigned char)ch)) {
+ if (max < 0)
+ max = 0;
+ max = 10 * max + char_to_int(ch);
+ ch = *format++;
+ } else if (ch == '*') {
+ max = va_arg (args, int);
+ ch = *format++;
+ state = DP_S_MOD;
+ } else
+ state = DP_S_MOD;
+ break;
+ case DP_S_MOD:
+ switch (ch) {
+ case 'h':
+ cflags = DP_C_SHORT;
+ ch = *format++;
+ break;
+ case 'l':
+ cflags = DP_C_LONG;
+ ch = *format++;
+ if (ch == 'l') {
+ cflags = DP_C_LONG_LONG;
+ ch = *format++;
+ }
+ break;
+ case 'q':
+ cflags = DP_C_LONG_LONG;
+ ch = *format++;
+ break;
+ case 'L':
+ cflags = DP_C_LDOUBLE;
+ ch = *format++;
+ break;
+ default:
+ break;
+ }
+ state = DP_S_CONV;
+ break;
+ case DP_S_CONV:
+ switch (ch) {
+ case 'd':
+ case 'i':
+ if (cflags == DP_C_SHORT)
+ value = va_arg(args, int);
+ else if (cflags == DP_C_LONG)
+ value = va_arg(args, long int);
+ else if (cflags == DP_C_LONG_LONG)
+ value = va_arg (args, long long);
+ else
+ value = va_arg (args, int);
+ fmtint(buffer, &currlen, maxlen, value, 10, min, max, flags);
+ break;
+ case 'o':
+ flags |= DP_F_UNSIGNED;
+ if (cflags == DP_C_SHORT)
+ value = va_arg(args, unsigned int);
+ else if (cflags == DP_C_LONG)
+ value = va_arg(args, unsigned long int);
+ else if (cflags == DP_C_LONG_LONG)
+ value = va_arg(args, unsigned long long);
+ else
+ value = va_arg(args, unsigned int);
+ fmtint(buffer, &currlen, maxlen, value, 8, min, max, flags);
+ break;
+ case 'u':
+ flags |= DP_F_UNSIGNED;
+ if (cflags == DP_C_SHORT)
+ value = va_arg(args, unsigned int);
+ else if (cflags == DP_C_LONG)
+ value = va_arg(args, unsigned long int);
+ else if (cflags == DP_C_LONG_LONG)
+ value = va_arg(args, unsigned long long);
+ else
+ value = va_arg(args, unsigned int);
+ fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
+ break;
+ case 'X':
+ flags |= DP_F_UP;
+ case 'x':
+ flags |= DP_F_UNSIGNED;
+ if (cflags == DP_C_SHORT)
+ value = va_arg(args, unsigned int);
+ else if (cflags == DP_C_LONG)
+ value = va_arg(args, unsigned long int);
+ else if (cflags == DP_C_LONG_LONG)
+ value = va_arg(args, unsigned long long);
+ else
+ value = va_arg(args, unsigned int);
+ fmtint(buffer, &currlen, maxlen, value, 16, min, max, flags);
+ break;
+ case 'f':
+ if (cflags == DP_C_LDOUBLE)
+ fvalue = va_arg(args, long double);
+ else
+ fvalue = va_arg(args, double);
+ /* um, floating point? */
+ fmtfp(buffer, &currlen, maxlen, fvalue, min, max, flags);
+ break;
+ case 'E':
+ flags |= DP_F_UP;
+ case 'e':
+ if (cflags == DP_C_LDOUBLE)
+ fvalue = va_arg(args, long double);
+ else
+ fvalue = va_arg(args, double);
+ break;
+ case 'G':
+ flags |= DP_F_UP;
+ case 'g':
+ if (cflags == DP_C_LDOUBLE)
+ fvalue = va_arg(args, long double);
+ else
+ fvalue = va_arg(args, double);
+ break;
+ case 'c':
+ dopr_outch(buffer, &currlen, maxlen, va_arg(args, int));
+ break;
+ case 's':
+ strvalue = va_arg(args, char *);
+ if (max < 0)
+ max = maxlen; /* ie, no max */
+ fmtstr(buffer, &currlen, maxlen, strvalue, flags, min, max);
+ break;
+ case 'p':
+ strvalue = va_arg(args, void *);
+ fmtint(buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);
+ break;
+ case 'n':
+ if (cflags == DP_C_SHORT) {
+ short int *num;
+ num = va_arg(args, short int *);
+ *num = currlen;
+ } else if (cflags == DP_C_LONG) {
+ long int *num;
+ num = va_arg(args, long int *);
+ *num = currlen;
+ } else if (cflags == DP_C_LONG_LONG) {
+ long long *num;
+ num = va_arg(args, long long *);
+ *num = currlen;
+ } else {
+ int *num;
+ num = va_arg(args, int *);
+ *num = currlen;
+ }
+ break;
+ case '%':
+ dopr_outch(buffer, &currlen, maxlen, ch);
+ break;
+ case 'w': /* not supported yet, treat as next char */
+ ch = *format++;
+ break;
+ default: /* Unknown, skip */
+ break;
+ }
+ ch = *format++;
+ state = DP_S_DEFAULT;
+ flags = cflags = min = 0;
+ max = -1;
+ break;
+ case DP_S_DONE:
+ break;
+ default: /* hmm? */
+ break; /* some picky compilers need this */
+ }
+ }
+ if (currlen < maxlen - 1)
+ buffer[currlen] = '\0';
+ else
+ buffer[maxlen - 1] = '\0';
+}
+
+static void
+fmtstr(char *buffer, size_t *currlen, size_t maxlen,
+ char *value, int flags, int min, int max)
+{
+ int cnt = 0, padlen, strln; /* amount to pad */
+
+ if (value == 0)
+ value = "<NULL>";
+
+ for (strln = 0; value[strln]; ++strln); /* strlen */
+ padlen = min - strln;
+ if (padlen < 0)
+ padlen = 0;
+ if (flags & DP_F_MINUS)
+ padlen = -padlen; /* Left Justify */
+
+ while ((padlen > 0) && (cnt < max)) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ --padlen;
+ ++cnt;
+ }
+ while (*value && (cnt < max)) {
+ dopr_outch(buffer, currlen, maxlen, *value++);
+ ++cnt;
+ }
+ while ((padlen < 0) && (cnt < max)) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ ++padlen;
+ ++cnt;
+ }
+}
+
+/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
+
+static void
+fmtint(char *buffer, size_t *currlen, size_t maxlen,
+ long value, int base, int min, int max, int flags)
+{
+ unsigned long uvalue;
+ char convert[20];
+ int signvalue = 0, place = 0, caps = 0;
+ int spadlen = 0; /* amount to space pad */
+ int zpadlen = 0; /* amount to zero pad */
+
+#define PADMAX(x,y) ((x) > (y) ? (x) : (y))
+
+ if (max < 0)
+ max = 0;
+
+ uvalue = value;
+
+ if (!(flags & DP_F_UNSIGNED)) {
+ if (value < 0) {
+ signvalue = '-';
+ uvalue = -value;
+ } else if (flags & DP_F_PLUS) /* Do a sign (+/i) */
+ signvalue = '+';
+ else if (flags & DP_F_SPACE)
+ signvalue = ' ';
+ }
+
+ if (flags & DP_F_UP)
+ caps = 1; /* Should characters be upper case? */
+ do {
+ convert[place++] =
+ (caps ? "0123456789ABCDEF" : "0123456789abcdef")
+ [uvalue % (unsigned)base];
+ uvalue = (uvalue / (unsigned)base );
+ } while (uvalue && (place < 20));
+ if (place == 20)
+ place--;
+ convert[place] = 0;
+
+ zpadlen = max - place;
+ spadlen = min - PADMAX(max, place) - (signvalue ? 1 : 0);
+ if (zpadlen < 0)
+ zpadlen = 0;
+ if (spadlen < 0)
+ spadlen = 0;
+ if (flags & DP_F_ZERO) {
+ zpadlen = PADMAX(zpadlen, spadlen);
+ spadlen = 0;
+ }
+ if (flags & DP_F_MINUS)
+ spadlen = -spadlen; /* Left Justifty */
+
+ /* Spaces */
+ while (spadlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ --spadlen;
+ }
+
+ /* Sign */
+ if (signvalue)
+ dopr_outch(buffer, currlen, maxlen, signvalue);
+
+ /* Zeros */
+ if (zpadlen > 0) {
+ while (zpadlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, '0');
+ --zpadlen;
+ }
+ }
+
+ /* Digits */
+ while (place > 0)
+ dopr_outch(buffer, currlen, maxlen, convert[--place]);
+
+ /* Left Justified spaces */
+ while (spadlen < 0) {
+ dopr_outch (buffer, currlen, maxlen, ' ');
+ ++spadlen;
+ }
+}
+
+static long double
+pow10(int exp)
+{
+ long double result = 1;
+
+ while (exp) {
+ result *= 10;
+ exp--;
+ }
+
+ return result;
+}
+
+static long
+round(long double value)
+{
+ long intpart = value;
+
+ value -= intpart;
+ if (value >= 0.5)
+ intpart++;
+
+ return intpart;
+}
+
+static void
+fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue,
+ int min, int max, int flags)
+{
+ char iconvert[20], fconvert[20];
+ int signvalue = 0, iplace = 0, fplace = 0;
+ int padlen = 0; /* amount to pad */
+ int zpadlen = 0, caps = 0;
+ long intpart, fracpart;
+ long double ufvalue;
+
+ /*
+ * AIX manpage says the default is 0, but Solaris says the default
+ * is 6, and sprintf on AIX defaults to 6
+ */
+ if (max < 0)
+ max = 6;
+
+ ufvalue = abs_val(fvalue);
+
+ if (fvalue < 0)
+ signvalue = '-';
+ else if (flags & DP_F_PLUS) /* Do a sign (+/i) */
+ signvalue = '+';
+ else if (flags & DP_F_SPACE)
+ signvalue = ' ';
+
+ intpart = ufvalue;
+
+ /*
+ * Sorry, we only support 9 digits past the decimal because of our
+ * conversion method
+ */
+ if (max > 9)
+ max = 9;
+
+ /* We "cheat" by converting the fractional part to integer by
+ * multiplying by a factor of 10
+ */
+ fracpart = round((pow10 (max)) * (ufvalue - intpart));
+
+ if (fracpart >= pow10 (max)) {
+ intpart++;
+ fracpart -= pow10 (max);
+ }
+
+ /* Convert integer part */
+ do {
+ iconvert[iplace++] =
+ (caps ? "0123456789ABCDEF" : "0123456789abcdef")
+ [intpart % 10];
+ intpart = (intpart / 10);
+ } while(intpart && (iplace < 20));
+ if (iplace == 20)
+ iplace--;
+ iconvert[iplace] = 0;
+
+ /* Convert fractional part */
+ do {
+ fconvert[fplace++] =
+ (caps ? "0123456789ABCDEF" : "0123456789abcdef")
+ [fracpart % 10];
+ fracpart = (fracpart / 10);
+ } while(fracpart && (fplace < 20));
+ if (fplace == 20)
+ fplace--;
+ fconvert[fplace] = 0;
+
+ /* -1 for decimal point, another -1 if we are printing a sign */
+ padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
+ zpadlen = max - fplace;
+ if (zpadlen < 0)
+ zpadlen = 0;
+ if (padlen < 0)
+ padlen = 0;
+ if (flags & DP_F_MINUS)
+ padlen = -padlen; /* Left Justifty */
+
+ if ((flags & DP_F_ZERO) && (padlen > 0)) {
+ if (signvalue) {
+ dopr_outch(buffer, currlen, maxlen, signvalue);
+ --padlen;
+ signvalue = 0;
+ }
+ while (padlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, '0');
+ --padlen;
+ }
+ }
+ while (padlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ --padlen;
+ }
+ if (signvalue)
+ dopr_outch(buffer, currlen, maxlen, signvalue);
+
+ while (iplace > 0)
+ dopr_outch(buffer, currlen, maxlen, iconvert[--iplace]);
+
+ /*
+ * Decimal point. This should probably use locale to find the
+ * correct char to print out.
+ */
+ dopr_outch(buffer, currlen, maxlen, '.');
+
+ while (fplace > 0)
+ dopr_outch(buffer, currlen, maxlen, fconvert[--fplace]);
+
+ while (zpadlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, '0');
+ --zpadlen;
+ }
+
+ while (padlen < 0) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ ++padlen;
+ }
+}
+
+static void
+dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
+{
+ if (*currlen < maxlen)
+ buffer[(*currlen)++] = c;
+}
+#endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */
+
+#ifndef HAVE_VSNPRINTF
+int
+vsnprintf(char *str, size_t count, const char *fmt, va_list args)
+{
+ str[0] = 0;
+ dopr(str, count, fmt, args);
+
+ return(strlen(str));
+}
+#endif /* !HAVE_VSNPRINTF */
+
+#ifndef HAVE_SNPRINTF
+int
+snprintf(char *str,size_t count,const char *fmt,...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ (void) vsnprintf(str, count, fmt, ap);
+ va_end(ap);
+
+ return(strlen(str));
+}
+
+#endif /* !HAVE_SNPRINTF */
diff --git a/StdLib/LibC/Uefi/select.c b/StdLib/LibC/Uefi/select.c new file mode 100644 index 0000000000..8da03e65d0 --- /dev/null +++ b/StdLib/LibC/Uefi/select.c @@ -0,0 +1,256 @@ +/*
+ * Copyright (c) 1982, 1986, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by the University of
+ * California, Berkeley, Intel Corporation, and its contributors.
+ *
+ * 4. Neither the name of University, Intel Corporation, or their respective
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS,
+ * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @(#)sys_generic.c 8.5 (Berkeley) 1/21/94
+ * $Id: select.c,v 1.1.1.1 2003/11/19 01:50:30 kyu3 Exp $
+ */
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <LibConfig.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/poll.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <extern.h> /* For ffs() */
+#ifndef KERNEL
+#define KERNEL
+#include <errno.h>
+#undef KERNEL
+#else
+#include <errno.h>
+#endif
+
+#ifdef EFI_NT_EMULATOR
+#define _SELECT_DELAY_ 10000
+#else
+#define _SELECT_DELAY_ 1000
+#endif
+
+#define MAX_SLEEP_DELAY 0xfffffffe
+
+//
+// Name:
+// usleep
+//
+// Description:
+// Implement usleep(3) function.
+//
+// Arguments:
+// Microseconds to sleep.
+//
+// Returns:
+// 0
+//
+int
+usleep( useconds_t Microseconds )
+{
+ while ( MAX_SLEEP_DELAY < Microseconds ) {
+ gBS->Stall ( MAX_SLEEP_DELAY );
+ Microseconds -= MAX_SLEEP_DELAY;
+ }
+ gBS->Stall((UINTN)Microseconds );
+ return (0);
+}
+
+static int
+selscan(
+ fd_mask **ibits,
+ fd_mask **obits,
+ int nfd,
+ int *nselected
+ )
+{
+ int msk;
+ int i;
+ int j;
+ int fd;
+ int n;
+ struct pollfd pfd;
+ int FdCount;
+ fd_mask bits;
+ /* Note: backend also returns POLLHUP/POLLERR if appropriate. */
+ static int16_t flag[3] = { POLLRDNORM, POLLWRNORM, POLLRDBAND };
+
+ for (msk = 0, n = 0; msk < 3; msk++) {
+ if (ibits[msk] == NULL)
+ continue;
+ for (i = 0; i < nfd; i += NFDBITS) {
+ bits = ibits[ msk ][ i / NFDBITS ];
+ while (( 0 != (j = ffs(bits))) && ((fd = i + --j) < nfd)) {
+ bits &= ~(1 << j);
+
+ pfd.fd = fd;
+ pfd.events = flag[msk];
+ pfd.revents = 0;
+ FdCount = poll ( &pfd, 1, 0 );
+ if ( -1 == FdCount ) {
+ return errno;
+ }
+ if ( 0 != FdCount ) {
+ obits[msk][(fd)/NFDBITS] |=
+ (1 << ((fd) % NFDBITS));
+ n++;
+ break;
+ }
+ }
+ }
+ }
+ *nselected = n;
+ return (0);
+}
+
+int
+select(
+ int nd,
+ fd_set *in,
+ fd_set *ou,
+ fd_set *ex,
+ struct timeval *tv
+ )
+{
+ fd_mask *ibits[3], *obits[3], *selbits, *sbp;
+ int error, forever, nselected;
+ u_int nbufbytes, ncpbytes, nfdbits;
+ int64_t timo;
+
+ if (nd < 0)
+ return (EINVAL);
+
+ /*
+ * Allocate just enough bits for the non-null fd_sets. Use the
+ * preallocated auto buffer if possible.
+ */
+ nfdbits = roundup(nd, NFDBITS);
+ ncpbytes = nfdbits / NBBY;
+ nbufbytes = 0;
+ if (in != NULL)
+ nbufbytes += 2 * ncpbytes;
+ if (ou != NULL)
+ nbufbytes += 2 * ncpbytes;
+ if (ex != NULL)
+ nbufbytes += 2 * ncpbytes;
+ selbits = malloc(nbufbytes);
+
+ /*
+ * Assign pointers into the bit buffers and fetch the input bits.
+ * Put the output buffers together so that they can be bzeroed
+ * together.
+ */
+ sbp = selbits;
+#define getbits(name, x) \
+ do { \
+ if (name == NULL) \
+ ibits[x] = NULL; \
+ else { \
+ ibits[x] = sbp + nbufbytes / 2 / sizeof *sbp; \
+ obits[x] = sbp; \
+ sbp += ncpbytes / sizeof *sbp; \
+ bcopy(name, ibits[x], ncpbytes); \
+ } \
+ } while (0)
+ getbits(in, 0);
+ getbits(ou, 1);
+ getbits(ex, 2);
+#undef getbits
+ if (nbufbytes != 0)
+ memset(selbits, 0, nbufbytes / 2);
+
+ if (tv) {
+ timo = tv->tv_usec + (tv->tv_sec * 1000000);
+ forever = 0;
+ } else {
+ timo = 0;
+ forever = 1;
+ }
+
+ /*
+ * Poll for I/O events
+ */
+ nselected = 0;
+ do {
+ /*
+ * Scan for pending I/O
+ */
+ error = selscan(ibits, obits, nd, &nselected);
+ if (error || nselected)
+ break;
+
+ /*
+ * Adjust timeout is needed
+ */
+ if (timo) {
+ /*
+ * Give it a rest
+ */
+ usleep( _SELECT_DELAY_ );
+ timo -= _SELECT_DELAY_;
+ }
+
+ } while (timo > 0 || forever);
+
+ /* select is not restarted after signals... */
+ if (error == ERESTART)
+ error = EINTR;
+ else if (error == EWOULDBLOCK)
+ error = 0;
+
+#define putbits(name, x) if (name) bcopy(obits[x], name, ncpbytes)
+ if (error == 0) {
+ putbits(in, 0);
+ putbits(ou, 1);
+ putbits(ex, 2);
+#undef putbits
+ } else {
+ errno = error;
+ nselected = -1;
+ }
+
+ free( selbits );
+ return ( nselected );
+}
diff --git a/StdLib/LibC/Uefi/writev.c b/StdLib/LibC/Uefi/writev.c new file mode 100644 index 0000000000..9cff086c6a --- /dev/null +++ b/StdLib/LibC/Uefi/writev.c @@ -0,0 +1,143 @@ +/*
+ * Copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software must
+ * display the following acknowledgement:
+ *
+ * This product includes software developed by Intel Corporation and its
+ * contributors.
+ *
+ * 4. Neither the name of Intel Corporation or its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*++
+
+Module Name:
+
+ writev.c
+
+Abstract:
+
+ Functions implementing the standard "writev" system call interface
+
+
+Revision History
+
+--*/
+#include <LibConfig.h>
+
+#ifdef foo
+#include <efi_interface.h>
+#include <unistd.h>
+#include <fcntl.h>
+#define KERNEL
+#include <errno.h>
+#undef KERNEL
+#include "./filedesc.h"
+
+#include <libc_debug.h>
+#include <assert.h>
+#endif
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/uio.h>
+#include <string.h>
+#ifndef KERNEL
+#define KERNEL
+#include <errno.h>
+#undef KERNEL
+#else
+#include <errno.h>
+#endif
+
+//
+// Name:
+// writev
+//
+// Description:
+// BSD writev interface for libc
+//
+// Arguments:
+// File Descriptor (index into file descriptor table)
+// iovec pointer
+// size of iovec array
+//
+// Returns:
+// number of bytes written
+//
+
+ssize_t
+writev(
+ int fd,
+ const struct iovec *iov,
+ int iovcnt
+ )
+{
+ const struct iovec *pVecTmp;
+ char *pBuf, *pBufTmp;
+ size_t TotalBytes, i, ret;
+
+ //
+ // See how much memory we'll need
+ //
+
+ for (i = 0, TotalBytes = 0, pVecTmp = iov; i < (size_t)iovcnt; i++, pVecTmp++) {
+ TotalBytes += pVecTmp->iov_len;
+ }
+
+ //
+ // Allocate a contiguous buffer
+ //
+
+ pBuf = (char*)malloc (TotalBytes);
+ if (pBuf == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ //
+ // Copy vectors to the buffer
+ //
+
+ for (pBufTmp = pBuf; iovcnt; iovcnt--) {
+ bcopy(iov->iov_base, pBuf, iov->iov_len);
+ pBuf += iov->iov_len;
+ iov++;
+ }
+
+ //
+ // Use standard write(2) then free buffer
+ //
+
+ ret = write (fd, pBuf, TotalBytes);
+ free (pBuf);
+
+ return (ret);
+}
diff --git a/StdLib/PosixLib/Err/LibErr.inf b/StdLib/PosixLib/Err/LibErr.inf new file mode 100644 index 0000000000..fe1b5d4e60 --- /dev/null +++ b/StdLib/PosixLib/Err/LibErr.inf @@ -0,0 +1,42 @@ +## @file
+# Library used for supplying some POSIX routines.
+#
+# Copyright (c) 2011, Intel Corporation. All rights reserved. <BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = LibErr
+ FILE_GUID = FC1D4706-88FB-42b0-98B0-A4B2E607EBAA
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = LibErr|UEFI_APPLICATION UEFI_DRIVER
+
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ warn_err.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ StdLib/StdLib.dec
+ StdLibPrivateInternalFiles/DoNotUse.dec
+
+[Libraries]
+ LibC
+ LibStdio
+ LibStdLib
+ LibString
diff --git a/StdLib/PosixLib/Err/warn_err.c b/StdLib/PosixLib/Err/warn_err.c new file mode 100644 index 0000000000..b69a41753f --- /dev/null +++ b/StdLib/PosixLib/Err/warn_err.c @@ -0,0 +1,99 @@ +/** @file
+ Implement the warning and error output messages.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ * Copyright (c) 1994 Michael L. Hitch
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Michael L. Hitch.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **/
+#include <LibConfig.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+static void
+_Vdomessage(int doerrno, const char *fmt, va_list args)
+{
+ fprintf(stderr, "%s: ", getprogname());
+ if (fmt) {
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, ": ");
+ }
+ if (doerrno && errno < EMAXERRORVAL) {
+ fprintf(stderr, "%s", strerror(errno));
+ }
+ fprintf(stderr, "\n");
+}
+
+void
+err(int eval, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ _Vdomessage(1, fmt, ap);
+ va_end(ap);
+ exit(eval);
+}
+
+void
+errx(int eval, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ _Vdomessage(0, fmt, ap);
+ va_end(ap);
+ exit(eval);
+}
+
+void
+warn(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ _Vdomessage(1, fmt, ap);
+ va_end(ap);
+}
+
+void
+warnx(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ _Vdomessage(0, fmt, ap);
+ va_end(ap);
+}
diff --git a/StdLib/PosixLib/Gen/LibGen.inf b/StdLib/PosixLib/Gen/LibGen.inf new file mode 100644 index 0000000000..276b2ee427 --- /dev/null +++ b/StdLib/PosixLib/Gen/LibGen.inf @@ -0,0 +1,41 @@ +## @file
+# Library used for supplying glob POSIX routines.
+#
+# Copyright (c) 2011, Intel Corporation. All rights reserved. <BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = LibGen
+ FILE_GUID = CA599759-90A7-4fe4-BC8B-4B71C350DCAC
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = LibGen|UEFI_APPLICATION UEFI_DRIVER
+
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ dirname.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ StdLib/StdLib.dec
+ StdLibPrivateInternalFiles/DoNotUse.dec
+
+[Libraries]
+ LibString
+ LibStdLib
+
+[Pcd]
diff --git a/StdLib/PosixLib/Gen/dirname.c b/StdLib/PosixLib/Gen/dirname.c new file mode 100644 index 0000000000..7fb4d39a0f --- /dev/null +++ b/StdLib/PosixLib/Gen/dirname.c @@ -0,0 +1,88 @@ +/** @file
+
+ * Copyright (c) 1997, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Klaus Klein and Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+
+ NetBSD: dirname.c,v 1.10 2008/05/10 22:39:40 christos Exp
+ */
+#include <LibConfig.h>
+
+#include <sys/cdefs.h>
+
+//#include "namespace.h"
+//#include <libgen.h>
+#include <limits.h>
+#include <string.h>
+
+#ifdef __weak_alias
+__weak_alias(dirname,_dirname)
+#endif
+
+#if !HAVE_DIRNAME
+char *
+dirname(char *path)
+{
+ static char singledot[] = ".";
+ static char result[PATH_MAX];
+ const char *lastp;
+ size_t len;
+
+ /*
+ * If `path' is a null pointer or points to an empty string,
+ * return a pointer to the string ".".
+ */
+ if ((path == NULL) || (*path == '\0'))
+ return (singledot);
+
+ /* Strip trailing slashes, if any. */
+ lastp = path + strlen(path) - 1;
+ while (lastp != path && *lastp == '/')
+ lastp--;
+
+ /* Terminate path at the last occurence of '/'. */
+ do {
+ if (*lastp == '/') {
+ /* Strip trailing slashes, if any. */
+ while (lastp != path && *lastp == '/')
+ lastp--;
+
+ /* ...and copy the result into the result buffer. */
+ len = (lastp - path) + 1 /* last char */;
+ if (len > (PATH_MAX - 1))
+ len = PATH_MAX - 1;
+
+ memcpy(result, path, len);
+ result[len] = '\0';
+
+ return (result);
+ }
+ } while (--lastp >= path);
+
+ /* No /'s found, return a pointer to the string ".". */
+ return (singledot);
+}
+#endif
diff --git a/StdLib/PosixLib/Glob/DirFunctions.c b/StdLib/PosixLib/Glob/DirFunctions.c new file mode 100644 index 0000000000..db495e36d2 --- /dev/null +++ b/StdLib/PosixLib/Glob/DirFunctions.c @@ -0,0 +1,135 @@ +/** @file
+ Implement the opendir, closedir, and readdir functions.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "internal.h"
+#include <Library/ShellLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseLib.h>
+
+typedef struct {
+ UINT32 Signature;
+ SHELL_FILE_HANDLE DirHandle;
+ EFI_FILE_INFO *FileInfo;
+ struct dirent *DirentStructure;
+} DIR_STRUCTURE;
+
+DIR * opendir(const char * AsciiFileName)
+{
+ EFI_STATUS Status;
+ DIR_STRUCTURE *DirStruct;
+ CHAR16 *FileName;
+
+ DirStruct = (DIR_STRUCTURE*)AllocateZeroPool(sizeof(DIR_STRUCTURE));
+ if (DirStruct == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ FileName = (CHAR16*)AllocateZeroPool((1+AsciiStrLen(AsciiFileName))*sizeof(CHAR16));
+ if (FileName == NULL) {
+ FreePool(DirStruct);
+ errno = ENOMEM;
+ return NULL;
+ }
+ AsciiStrToUnicodeStr(AsciiFileName, FileName);
+
+ Status = ShellOpenFileByName(FileName, &DirStruct->DirHandle, EFI_FILE_MODE_READ, 0);
+ FreePool(FileName);
+ if (EFI_ERROR(Status)) {
+ errno = ENOENT;
+ FreePool(DirStruct);
+ return NULL;
+ }
+ DirStruct->Signature = 0x08675309;
+ return ((DIR*)DirStruct);
+}
+
+int closedir(DIR * DirPointer)
+{
+ DIR_STRUCTURE *DirStruct;
+
+ if (DirPointer == NULL) {
+ return 0;
+ }
+
+ DirStruct = (DIR_STRUCTURE*)DirPointer;
+ if (DirStruct->Signature != 0x08675309) {
+ return 0;
+ }
+
+ ShellCloseFile(DirStruct->DirHandle);
+ SHELL_FREE_NON_NULL(DirStruct->FileInfo);
+ SHELL_FREE_NON_NULL(DirStruct->DirentStructure);
+ SHELL_FREE_NON_NULL(DirStruct);
+
+ return 0;
+}
+
+struct dirent * readdir(DIR * DirPointer)
+{
+ DIR_STRUCTURE *DirStruct;
+ EFI_STATUS Status;
+ BOOLEAN NoFile;
+
+ NoFile = FALSE;
+
+ if (DirPointer == NULL) {
+ errno = EBADF;
+ return NULL;
+ }
+
+ DirStruct = (DIR_STRUCTURE*)DirPointer;
+ if (DirStruct->Signature != 0x08675309) {
+ errno = EBADF;
+ return NULL;
+ }
+
+ if (DirStruct->FileInfo == NULL) {
+ Status = ShellFindFirstFile(DirStruct->DirHandle, &(DirStruct->FileInfo));
+ } else {
+ Status = ShellFindNextFile(DirStruct->DirHandle, DirStruct->FileInfo, &NoFile);
+ }
+
+ if (EFI_ERROR(Status)) {
+ errno = ENOENT;
+ return NULL;
+ }
+
+ if (NoFile) {
+ return (NULL);
+ }
+
+ SHELL_FREE_NON_NULL(DirStruct->DirentStructure);
+
+ DirStruct->DirentStructure = AllocateZeroPool(sizeof(DIR_STRUCTURE)+(StrSize(DirStruct->FileInfo->FileName)));
+ if (DirStruct->DirentStructure == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ StrCpy(DirStruct->FileInfo->FileName, DirStruct->DirentStructure->FileName);
+
+ DirStruct->DirentStructure->FileSize = DirStruct->FileInfo->FileSize;
+ DirStruct->DirentStructure->PhysicalSize = DirStruct->FileInfo->PhysicalSize;
+ DirStruct->DirentStructure->Attribute = DirStruct->FileInfo->Attribute;
+ DirStruct->DirentStructure->CreateTime.tv_sec = Efi2Time(&DirStruct->FileInfo->CreateTime);
+ DirStruct->DirentStructure->CreateTime.tv_nsec = DirStruct->FileInfo->CreateTime.Nanosecond;
+ DirStruct->DirentStructure->LastAccessTime.tv_nsec = Efi2Time(&DirStruct->FileInfo->LastAccessTime);
+ DirStruct->DirentStructure->LastAccessTime.tv_sec = DirStruct->FileInfo->LastAccessTime.Nanosecond;
+ DirStruct->DirentStructure->ModificationTime.tv_sec = Efi2Time(&DirStruct->FileInfo->ModificationTime);
+ DirStruct->DirentStructure->ModificationTime.tv_nsec = DirStruct->FileInfo->ModificationTime.Nanosecond;
+ DirStruct->DirentStructure->Size = StrSize(DirStruct->DirentStructure->FileName) + sizeof(DIR_STRUCTURE);
+
+ return (DirStruct->DirentStructure);
+}
diff --git a/StdLib/PosixLib/Glob/LibGlob.inf b/StdLib/PosixLib/Glob/LibGlob.inf new file mode 100644 index 0000000000..fab4730bb8 --- /dev/null +++ b/StdLib/PosixLib/Glob/LibGlob.inf @@ -0,0 +1,47 @@ +## @file
+# Library used for supplying glob POSIX routines.
+#
+# Copyright (c) 2011, Intel Corporation. All rights reserved. <BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = LibGlob
+ FILE_GUID = 1D57B5D5-BAB4-4d2b-B7EB-0EB41D7B189C
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = LibGlob|UEFI_APPLICATION UEFI_DRIVER
+
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ DirFunctions.c
+ glob.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ StdLib/StdLib.dec
+ StdLibPrivateInternalFiles/DoNotUse.dec
+
+[Libraries]
+ MemoryAllocationLib
+ ShellLib
+ BaseLib
+ LibStdio
+ LibStdLib
+ LibString
+
+[Pcd]
diff --git a/StdLib/PosixLib/Glob/glob.c b/StdLib/PosixLib/Glob/glob.c new file mode 100644 index 0000000000..dec78d89d6 --- /dev/null +++ b/StdLib/PosixLib/Glob/glob.c @@ -0,0 +1,1033 @@ +/** @file
+ * glob(3) -- a superset of the one defined in POSIX 1003.2.
+ *
+ * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
+ *
+ * Optional extra services, controlled by flags not defined by POSIX:
+ *
+ * GLOB_MAGCHAR:
+ * Set in gl_flags if pattern contained a globbing character.
+ * GLOB_NOMAGIC:
+ * Same as GLOB_NOCHECK, but it will only append pattern if it did
+ * not contain any magic characters. [Used in csh style globbing]
+ * GLOB_ALTDIRFUNC:
+ * Use alternately specified directory access functions.
+ * GLOB_TILDE:
+ * expand ~user/foo to the /home/dir/of/user/foo
+ * GLOB_BRACE:
+ * expand {1,2}{a,b} to 1a 1b 2a 2b
+ * GLOB_PERIOD:
+ * allow metacharacters to match leading dots in filenames.
+ * GLOB_NO_DOTDIRS:
+ * . and .. are hidden from wildcards, even if GLOB_PERIOD is set.
+ * gl_matchc:
+ * Number of matches in the current invocation of glob.
+ *
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+
+ glob.c 8.3 (Berkeley) 10/13/93
+ NetBSD: glob.c,v 1.23.4.1 2010/07/19 18:14:08 riz Exp
+ */
+#pragma warning ( disable : 4244 )
+#pragma warning ( disable : 4018 )
+
+#include <LibConfig.h>
+
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <glob.h>
+//#include <pwd.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/fcntl.h>
+#include "internal.h"
+
+#ifdef HAVE_NBTOOL_CONFIG_H
+#define NO_GETPW_R
+#endif
+
+#define GLOB_LIMIT_MALLOC 65536
+#define GLOB_LIMIT_STAT 128
+#define GLOB_LIMIT_READDIR 16384
+
+#define GLOB_INDEX_MALLOC 0
+#define GLOB_INDEX_STAT 1
+#define GLOB_INDEX_READDIR 2
+
+/*
+ * XXX: For NetBSD 1.4.x compatibility. (kill me l8r)
+ */
+#ifndef _DIAGASSERT
+#define _DIAGASSERT(a)
+#endif
+
+#define DOLLAR '$'
+#define DOT '.'
+#define EOS '\0'
+#define LBRACKET '['
+#define NOT '!'
+#define QUESTION '?'
+#define QUOTE '\\'
+#define RANGE '-'
+#define RBRACKET ']'
+#define SEP '/'
+#define STAR '*'
+#define TILDE '~'
+#define UNDERSCORE '_'
+#define LBRACE '{'
+#define RBRACE '}'
+#define SLASH '/'
+#define COMMA ','
+
+#ifndef USE_8BIT_CHARS
+
+#define M_QUOTE 0x8000
+#define M_PROTECT 0x4000
+#define M_MASK 0xffff
+#define M_ASCII 0x00ff
+
+typedef u_short Char;
+
+#else
+
+#define M_QUOTE (Char)0x80
+#define M_PROTECT (Char)0x40
+#define M_MASK (Char)0xff
+#define M_ASCII (Char)0x7f
+
+typedef char Char;
+
+#endif
+
+
+#define CHAR(c) ((Char)((c)&M_ASCII))
+#define META(c) ((Char)((c)|M_QUOTE))
+#define M_ALL META('*')
+#define M_END META(']')
+#define M_NOT META('!')
+#define M_ONE META('?')
+#define M_RNG META('-')
+#define M_SET META('[')
+#define ismeta(c) (((c)&M_QUOTE) != 0)
+
+static int compare(const void *, const void *);
+static int g_Ctoc(const Char *, char *, size_t);
+static int g_lstat(Char *, __gl_stat_t *, glob_t *);
+static DIR *g_opendir(Char *, glob_t *);
+static Char *g_strchr(const Char *, int);
+static int g_stat(Char *, __gl_stat_t *, glob_t *);
+static int glob0(const Char *, glob_t *, size_t *);
+static int glob1(Char *, glob_t *, size_t *);
+static int glob2(Char *, Char *, Char *, Char *, glob_t *, size_t *);
+static int glob3(Char *, Char *, Char *, Char *, Char *, glob_t *, size_t *);
+static int globextend(const Char *, glob_t *, size_t *);
+static const Char *globtilde(const Char *, Char *, size_t, glob_t *);
+static int globexp1(const Char *, glob_t *, size_t *);
+static int globexp2(const Char *, const Char *, glob_t *, int *, size_t *);
+static int match(Char *, Char *, Char *);
+#ifdef DEBUG
+static void qprintf(const char *, Char *);
+#endif
+
+int
+glob(
+ const char *pattern,
+ int flags,
+ int (*errfunc)(const char *, int),
+ glob_t *pglob
+)
+{
+ const u_char *patnext;
+ int c;
+ Char *bufnext, *bufend, patbuf[MAXPATHLEN+1];
+ /* 0 = malloc(), 1 = stat(), 2 = readdir() */
+ size_t limit[] = { 0, 0, 0 };
+
+ _DIAGASSERT(pattern != NULL);
+
+ patnext = (const u_char *) pattern;
+ if (!(flags & GLOB_APPEND)) {
+ pglob->gl_pathc = 0;
+ pglob->gl_pathv = NULL;
+ if (!(flags & GLOB_DOOFFS))
+ pglob->gl_offs = 0;
+ }
+ pglob->gl_flags = flags & ~GLOB_MAGCHAR;
+ pglob->gl_errfunc = errfunc;
+ pglob->gl_matchc = 0;
+
+ bufnext = patbuf;
+ bufend = bufnext + MAXPATHLEN;
+ if (flags & GLOB_NOESCAPE) {
+ while (bufnext < bufend && (c = *patnext++) != EOS)
+ *bufnext++ = c;
+ } else {
+ /* Protect the quoted characters. */
+ while (bufnext < bufend && (c = *patnext++) != EOS)
+ if (c == QUOTE) {
+ if ((c = *patnext++) == EOS) {
+ c = QUOTE;
+ --patnext;
+ }
+ *bufnext++ = c | M_PROTECT;
+ }
+ else
+ *bufnext++ = c;
+ }
+ *bufnext = EOS;
+
+ if (flags & GLOB_BRACE)
+ return globexp1(patbuf, pglob, limit);
+ else
+ return glob0(patbuf, pglob, limit);
+}
+
+/*
+ * Expand recursively a glob {} pattern. When there is no more expansion
+ * invoke the standard globbing routine to glob the rest of the magic
+ * characters
+ */
+static int
+globexp1(const Char *pattern, glob_t *pglob, size_t *limit)
+{
+ const Char* ptr = pattern;
+ int rv;
+
+ _DIAGASSERT(pattern != NULL);
+ _DIAGASSERT(pglob != NULL);
+
+ /* Protect a single {}, for find(1), like csh */
+ if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
+ return glob0(pattern, pglob, limit);
+
+ while ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL)
+ if (!globexp2(ptr, pattern, pglob, &rv, limit))
+ return rv;
+
+ return glob0(pattern, pglob, limit);
+}
+
+
+/*
+ * Recursive brace globbing helper. Tries to expand a single brace.
+ * If it succeeds then it invokes globexp1 with the new pattern.
+ * If it fails then it tries to glob the rest of the pattern and returns.
+ */
+static int
+globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv,
+ size_t *limit)
+{
+ int i;
+ Char *lm, *ls;
+ const Char *pe, *pm, *pl;
+ Char patbuf[MAXPATHLEN + 1];
+
+ _DIAGASSERT(ptr != NULL);
+ _DIAGASSERT(pattern != NULL);
+ _DIAGASSERT(pglob != NULL);
+ _DIAGASSERT(rv != NULL);
+
+ /* copy part up to the brace */
+ for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
+ continue;
+ ls = lm;
+
+ /* Find the balanced brace */
+ for (i = 0, pe = ++ptr; *pe; pe++)
+ if (*pe == LBRACKET) {
+ /* Ignore everything between [] */
+ for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
+ continue;
+ if (*pe == EOS) {
+ /*
+ * We could not find a matching RBRACKET.
+ * Ignore and just look for RBRACE
+ */
+ pe = pm;
+ }
+ }
+ else if (*pe == LBRACE)
+ i++;
+ else if (*pe == RBRACE) {
+ if (i == 0)
+ break;
+ i--;
+ }
+
+ /* Non matching braces; just glob the pattern */
+ if (i != 0 || *pe == EOS) {
+ /*
+ * we use `pattern', not `patbuf' here so that that
+ * unbalanced braces are passed to the match
+ */
+ *rv = glob0(pattern, pglob, limit);
+ return 0;
+ }
+
+ for (i = 0, pl = pm = ptr; pm <= pe; pm++) {
+ switch (*pm) {
+ case LBRACKET:
+ /* Ignore everything between [] */
+ for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++)
+ continue;
+ if (*pm == EOS) {
+ /*
+ * We could not find a matching RBRACKET.
+ * Ignore and just look for RBRACE
+ */
+ pm = pl;
+ }
+ break;
+
+ case LBRACE:
+ i++;
+ break;
+
+ case RBRACE:
+ if (i) {
+ i--;
+ break;
+ }
+ /* FALLTHROUGH */
+ case COMMA:
+ if (i && *pm == COMMA)
+ break;
+ else {
+ /* Append the current string */
+ for (lm = ls; (pl < pm); *lm++ = *pl++)
+ continue;
+ /*
+ * Append the rest of the pattern after the
+ * closing brace
+ */
+ for (pl = pe + 1; (*lm++ = *pl++) != EOS;)
+ continue;
+
+ /* Expand the current pattern */
+#ifdef DEBUG
+ qprintf("globexp2:", patbuf);
+#endif
+ *rv = globexp1(patbuf, pglob, limit);
+
+ /* move after the comma, to the next string */
+ pl = pm + 1;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ *rv = 0;
+ return 0;
+}
+
+
+
+/*
+ * expand tilde from the passwd file.
+ */
+static const Char *
+globtilde(const Char *pattern, Char *patbuf, size_t patsize, glob_t *pglob)
+{
+ const char *h;
+ const Char *p;
+ Char *b;
+ char *d;
+ Char *pend = &patbuf[patsize / sizeof(Char)];
+
+ pend--;
+
+ _DIAGASSERT(pattern != NULL);
+ _DIAGASSERT(patbuf != NULL);
+ _DIAGASSERT(pglob != NULL);
+
+ if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
+ return pattern;
+
+ /* Copy up to the end of the string or / */
+ for (p = pattern + 1, d = (char *)(void *)patbuf;
+ d < (char *)(void *)pend && *p && *p != SLASH;
+ *d++ = *p++)
+ continue;
+
+ if (d == (char *)(void *)pend)
+ return NULL;
+
+ *d = EOS;
+ d = (char *)(void *)patbuf;
+
+ if (*d == EOS) {
+ /*
+ * handle a plain ~ or ~/ by expanding $HOME
+ * first and then trying the password file
+ */
+ if ((h = getenv("HOME")) == NULL) {
+ return pattern;
+ }
+ }
+ else {
+ /*
+ * Expand a ~user
+ */
+ return pattern;
+ }
+
+ /* Copy the home directory */
+ for (b = patbuf; b < pend && *h; *b++ = *h++)
+ continue;
+
+ if (b == pend)
+ return NULL;
+
+ /* Append the rest of the pattern */
+ while (b < pend && (*b++ = *p++) != EOS)
+ continue;
+
+ if (b == pend)
+ return NULL;
+
+ return patbuf;
+}
+
+
+/*
+ * The main glob() routine: compiles the pattern (optionally processing
+ * quotes), calls glob1() to do the real pattern matching, and finally
+ * sorts the list (unless unsorted operation is requested). Returns 0
+ * if things went well, nonzero if errors occurred. It is not an error
+ * to find no matches.
+ */
+static int
+glob0(const Char *pattern, glob_t *pglob, size_t *limit)
+{
+ const Char *qpatnext;
+ int c, error;
+ __gl_size_t oldpathc;
+ Char *bufnext, patbuf[MAXPATHLEN+1];
+
+ _DIAGASSERT(pattern != NULL);
+ _DIAGASSERT(pglob != NULL);
+
+ if ((qpatnext = globtilde(pattern, patbuf, sizeof(patbuf),
+ pglob)) == NULL)
+ return GLOB_ABEND;
+ oldpathc = pglob->gl_pathc;
+ bufnext = patbuf;
+
+ /* We don't need to check for buffer overflow any more. */
+ while ((c = *qpatnext++) != EOS) {
+ switch (c) {
+ case LBRACKET:
+ c = *qpatnext;
+ if (c == NOT)
+ ++qpatnext;
+ if (*qpatnext == EOS ||
+ g_strchr(qpatnext+1, RBRACKET) == NULL) {
+ *bufnext++ = LBRACKET;
+ if (c == NOT)
+ --qpatnext;
+ break;
+ }
+ *bufnext++ = M_SET;
+ if (c == NOT)
+ *bufnext++ = M_NOT;
+ c = *qpatnext++;
+ do {
+ *bufnext++ = CHAR(c);
+ if (*qpatnext == RANGE &&
+ (c = qpatnext[1]) != RBRACKET) {
+ *bufnext++ = M_RNG;
+ *bufnext++ = CHAR(c);
+ qpatnext += 2;
+ }
+ } while ((c = *qpatnext++) != RBRACKET);
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ *bufnext++ = M_END;
+ break;
+ case QUESTION:
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ *bufnext++ = M_ONE;
+ break;
+ case STAR:
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ /* collapse adjacent stars to one,
+ * to avoid exponential behavior
+ */
+ if (bufnext == patbuf || bufnext[-1] != M_ALL)
+ *bufnext++ = M_ALL;
+ break;
+ default:
+ *bufnext++ = CHAR(c);
+ break;
+ }
+ }
+ *bufnext = EOS;
+#ifdef DEBUG
+ qprintf("glob0:", patbuf);
+#endif
+
+ if ((error = glob1(patbuf, pglob, limit)) != 0)
+ return error;
+
+ if (pglob->gl_pathc == oldpathc) {
+ /*
+ * If there was no match we are going to append the pattern
+ * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was
+ * specified and the pattern did not contain any magic
+ * characters GLOB_NOMAGIC is there just for compatibility
+ * with csh.
+ */
+ if ((pglob->gl_flags & GLOB_NOCHECK) ||
+ ((pglob->gl_flags & (GLOB_NOMAGIC|GLOB_MAGCHAR))
+ == GLOB_NOMAGIC)) {
+ return globextend(pattern, pglob, limit);
+ } else {
+ return GLOB_NOMATCH;
+ }
+ } else if (!(pglob->gl_flags & GLOB_NOSORT)) {
+ qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
+ (size_t)pglob->gl_pathc - oldpathc, sizeof(char *),
+ compare);
+ }
+
+ return 0;
+}
+
+static int
+compare(const void *p, const void *q)
+{
+
+ _DIAGASSERT(p != NULL);
+ _DIAGASSERT(q != NULL);
+
+ return strcoll(*(const char * const *)p, *(const char * const *)q);
+}
+
+static int
+glob1(Char *pattern, glob_t *pglob, size_t *limit)
+{
+ Char pathbuf[MAXPATHLEN+1];
+
+ _DIAGASSERT(pattern != NULL);
+ _DIAGASSERT(pglob != NULL);
+
+ /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
+ if (*pattern == EOS)
+ return 0;
+ /*
+ * we save one character so that we can use ptr >= limit,
+ * in the general case when we are appending non nul chars only.
+ */
+ return glob2(pathbuf, pathbuf,
+ pathbuf + (sizeof(pathbuf) / sizeof(*pathbuf)) - 1, pattern,
+ pglob, limit);
+}
+
+/*
+ * The functions glob2 and glob3 are mutually recursive; there is one level
+ * of recursion for each segment in the pattern that contains one or more
+ * meta characters.
+ */
+static int
+glob2(Char *pathbuf, Char *pathend, Char *pathlim, Char *pattern, glob_t *pglob,
+ size_t *limit)
+{
+ __gl_stat_t sb;
+ Char *p, *q;
+ int anymeta;
+ Char *pend;
+ ptrdiff_t diff;
+
+ _DIAGASSERT(pathbuf != NULL);
+ _DIAGASSERT(pathend != NULL);
+ _DIAGASSERT(pattern != NULL);
+ _DIAGASSERT(pglob != NULL);
+
+ /*
+ * Loop over pattern segments until end of pattern or until
+ * segment with meta character found.
+ */
+ for (anymeta = 0;;) {
+ if (*pattern == EOS) { /* End of pattern? */
+ *pathend = EOS;
+ if (g_lstat(pathbuf, &sb, pglob))
+ return 0;
+
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limit[GLOB_INDEX_STAT]++ >= GLOB_LIMIT_STAT) {
+ errno = 0;
+ *pathend++ = SEP;
+ *pathend = EOS;
+ return GLOB_NOSPACE;
+ }
+ if (((pglob->gl_flags & GLOB_MARK) &&
+ pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) ||
+// (S_ISLNK(sb.st_mode) &&
+ (0 &&
+ (g_stat(pathbuf, &sb, pglob) == 0) &&
+ S_ISDIR(sb.st_mode)))) {
+ if (pathend >= pathlim)
+ return GLOB_ABORTED;
+ *pathend++ = SEP;
+ *pathend = EOS;
+ }
+ ++pglob->gl_matchc;
+ return globextend(pathbuf, pglob, limit);
+ }
+
+ /* Find end of next segment, copy tentatively to pathend. */
+ q = pathend;
+ p = pattern;
+ while (*p != EOS && *p != SEP) {
+ if (ismeta(*p))
+ anymeta = 1;
+ if (q >= pathlim)
+ return GLOB_ABORTED;
+ *q++ = *p++;
+ }
+
+ /*
+ * No expansion, or path ends in slash-dot shash-dot-dot,
+ * do next segment.
+ */
+ if (pglob->gl_flags & GLOB_PERIOD) {
+ for (pend = pathend; pend > pathbuf && pend[-1] == '/';
+ pend--)
+ continue;
+ diff = pend - pathbuf;
+ } else {
+ /* XXX: GCC */
+ diff = 0;
+ pend = pathend;
+ }
+
+ if ((!anymeta) ||
+ ((pglob->gl_flags & GLOB_PERIOD) &&
+ (diff >= 1 && pend[-1] == DOT) &&
+ (diff >= 2 && (pend[-2] == SLASH || pend[-2] == DOT)) &&
+ (diff < 3 || pend[-3] == SLASH))) {
+ pathend = q;
+ pattern = p;
+ while (*pattern == SEP) {
+ if (pathend >= pathlim)
+ return GLOB_ABORTED;
+ *pathend++ = *pattern++;
+ }
+ } else /* Need expansion, recurse. */
+ return glob3(pathbuf, pathend, pathlim, pattern, p,
+ pglob, limit);
+ }
+ /* NOTREACHED */
+}
+
+static int
+glob3(Char *pathbuf, Char *pathend, Char *pathlim, Char *pattern,
+ Char *restpattern, glob_t *pglob, size_t *limit)
+{
+ struct dirent *dp;
+ DIR *dirp;
+ int error;
+ char buf[MAXPATHLEN];
+
+ /*
+ * The readdirfunc declaration can't be prototyped, because it is
+ * assigned, below, to two functions which are prototyped in glob.h
+ * and dirent.h as taking pointers to differently typed opaque
+ * structures.
+ */
+ struct dirent *(*readdirfunc)(void *);
+
+ _DIAGASSERT(pathbuf != NULL);
+ _DIAGASSERT(pathend != NULL);
+ _DIAGASSERT(pattern != NULL);
+ _DIAGASSERT(restpattern != NULL);
+ _DIAGASSERT(pglob != NULL);
+
+ *pathend = EOS;
+ errno = 0;
+
+ if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
+ if (pglob->gl_errfunc) {
+ if (g_Ctoc(pathbuf, buf, sizeof(buf)))
+ return GLOB_ABORTED;
+ if (pglob->gl_errfunc(buf, errno) ||
+ pglob->gl_flags & GLOB_ERR)
+ return GLOB_ABORTED;
+ }
+ /*
+ * Posix/XOpen: glob should return when it encounters a
+ * directory that it cannot open or read
+ * XXX: Should we ignore ENOTDIR and ENOENT though?
+ * I think that Posix had in mind EPERM...
+ */
+ if (pglob->gl_flags & GLOB_ERR)
+ return GLOB_ABORTED;
+
+ return 0;
+ }
+
+ error = 0;
+
+ /* Search directory for matching names. */
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ readdirfunc = pglob->gl_readdir;
+ else
+ readdirfunc = (struct dirent *(*)(void *)) readdir;
+ while ((dp = (*readdirfunc)(dirp)) != NULL) {
+ u_char *sc;
+ Char *dc;
+
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limit[GLOB_INDEX_READDIR]++ >= GLOB_LIMIT_READDIR) {
+ errno = 0;
+ *pathend++ = SEP;
+ *pathend = EOS;
+ return GLOB_NOSPACE;
+ }
+
+ /*
+ * Initial DOT must be matched literally, unless we have
+ * GLOB_PERIOD set.
+ */
+ if ((pglob->gl_flags & GLOB_PERIOD) == 0)
+ if (dp->FileName[0] == DOT && *pattern != DOT)
+ continue;
+ /*
+ * If GLOB_NO_DOTDIRS is set, . and .. vanish.
+ */
+ if ((pglob->gl_flags & GLOB_NO_DOTDIRS) &&
+ (dp->FileName[0] == DOT) &&
+ ((dp->FileName[1] == EOS) ||
+ ((dp->FileName[1] == DOT) && (dp->FileName[2] == EOS))))
+ continue;
+ /*
+ * The resulting string contains EOS, so we can
+ * use the pathlim character, if it is the nul
+ */
+ for (sc = (u_char *) dp->FileName, dc = pathend;
+ dc <= pathlim && (*dc++ = *sc++) != EOS;)
+ continue;
+
+ /*
+ * Have we filled the buffer without seeing EOS?
+ */
+ if (dc > pathlim && *pathlim != EOS) {
+ /*
+ * Abort when requested by caller, otherwise
+ * reset pathend back to last SEP and continue
+ * with next dir entry.
+ */
+ if (pglob->gl_flags & GLOB_ERR) {
+ error = GLOB_ABORTED;
+ break;
+ }
+ else {
+ *pathend = EOS;
+ continue;
+ }
+ }
+
+ if (!match(pathend, pattern, restpattern)) {
+ *pathend = EOS;
+ continue;
+ }
+ error = glob2(pathbuf, --dc, pathlim, restpattern, pglob,
+ limit);
+ if (error)
+ break;
+ }
+
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ (*pglob->gl_closedir)(dirp);
+ else
+ closedir(dirp);
+
+ /*
+ * Again Posix X/Open issue with regards to error handling.
+ */
+ if ((error || errno) && (pglob->gl_flags & GLOB_ERR))
+ return GLOB_ABORTED;
+
+ return error;
+}
+
+
+/*
+ * Extend the gl_pathv member of a glob_t structure to accommodate a new item,
+ * add the new item, and update gl_pathc.
+ *
+ * This assumes the BSD realloc, which only copies the block when its size
+ * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
+ * behavior.
+ *
+ * Return 0 if new item added, error code if memory couldn't be allocated.
+ *
+ * Invariant of the glob_t structure:
+ * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
+ * gl_pathv points to (gl_offs + gl_pathc + 1) items.
+ */
+static int
+globextend(const Char *path, glob_t *pglob, size_t *limit)
+{
+ char **pathv;
+ size_t i, newsize, len;
+ char *copy;
+ const Char *p;
+
+ _DIAGASSERT(path != NULL);
+ _DIAGASSERT(pglob != NULL);
+
+ newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
+ pathv = pglob->gl_pathv ? realloc(pglob->gl_pathv, newsize) :
+ malloc(newsize);
+ if (pathv == NULL)
+ return GLOB_NOSPACE;
+
+ if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
+ /* first time around -- clear initial gl_offs items */
+ pathv += pglob->gl_offs;
+ for (i = pglob->gl_offs + 1; --i > 0; )
+ *--pathv = NULL;
+ }
+ pglob->gl_pathv = pathv;
+
+ for (p = path; *p++;)
+ continue;
+ len = (size_t)(p - path);
+ limit[GLOB_INDEX_MALLOC] += len;
+ if ((copy = malloc(len)) != NULL) {
+ if (g_Ctoc(path, copy, len)) {
+ free(copy);
+ return GLOB_ABORTED;
+ }
+ pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
+ }
+ pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ (newsize + limit[GLOB_INDEX_MALLOC]) >= GLOB_LIMIT_MALLOC) {
+ errno = 0;
+ return GLOB_NOSPACE;
+ }
+
+ return copy == NULL ? GLOB_NOSPACE : 0;
+}
+
+
+/*
+ * pattern matching function for filenames. Each occurrence of the *
+ * pattern causes a recursion level.
+ */
+static int
+match(Char *name, Char *pat, Char *patend)
+{
+ int ok, negate_range;
+ Char c, k;
+
+ _DIAGASSERT(name != NULL);
+ _DIAGASSERT(pat != NULL);
+ _DIAGASSERT(patend != NULL);
+
+ while (pat < patend) {
+ c = *pat++;
+ switch (c & M_MASK) {
+ case M_ALL:
+ if (pat == patend)
+ return 1;
+ do
+ if (match(name, pat, patend))
+ return 1;
+ while (*name++ != EOS);
+ return 0;
+ case M_ONE:
+ if (*name++ == EOS)
+ return 0;
+ break;
+ case M_SET:
+ ok = 0;
+ if ((k = *name++) == EOS)
+ return 0;
+ if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
+ ++pat;
+ while (((c = *pat++) & M_MASK) != M_END)
+ if ((*pat & M_MASK) == M_RNG) {
+ if (c <= k && k <= pat[1])
+ ok = 1;
+ pat += 2;
+ } else if (c == k)
+ ok = 1;
+ if (ok == negate_range)
+ return 0;
+ break;
+ default:
+ if (*name++ != c)
+ return 0;
+ break;
+ }
+ }
+ return *name == EOS;
+}
+
+/* Free allocated data belonging to a glob_t structure. */
+void
+globfree(glob_t *pglob)
+{
+ size_t i;
+ char **pp;
+
+ _DIAGASSERT(pglob != NULL);
+
+ if (pglob->gl_pathv != NULL) {
+ pp = pglob->gl_pathv + pglob->gl_offs;
+ for (i = pglob->gl_pathc; i--; ++pp)
+ if (*pp)
+ free(*pp);
+ free(pglob->gl_pathv);
+ pglob->gl_pathv = NULL;
+ pglob->gl_pathc = 0;
+ }
+}
+
+static DIR *
+g_opendir(Char *str, glob_t *pglob)
+{
+ char buf[MAXPATHLEN];
+
+ _DIAGASSERT(str != NULL);
+ _DIAGASSERT(pglob != NULL);
+
+ if (!*str)
+ (void)strlcpy(buf, ".", sizeof(buf));
+ else {
+ if (g_Ctoc(str, buf, sizeof(buf)))
+ return NULL;
+ }
+
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ return (*pglob->gl_opendir)(buf);
+
+ return opendir(buf);
+}
+
+static int
+g_lstat(Char *fn, __gl_stat_t *sb, glob_t *pglob)
+{
+ char buf[MAXPATHLEN];
+
+ _DIAGASSERT(fn != NULL);
+ _DIAGASSERT(sb != NULL);
+ _DIAGASSERT(pglob != NULL);
+
+ if (g_Ctoc(fn, buf, sizeof(buf)))
+ return -1;
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ return (*pglob->gl_lstat)(buf, sb);
+ return lstat(buf, sb);
+}
+
+static int
+g_stat(Char *fn, __gl_stat_t *sb, glob_t *pglob)
+{
+ char buf[MAXPATHLEN];
+
+ _DIAGASSERT(fn != NULL);
+ _DIAGASSERT(sb != NULL);
+ _DIAGASSERT(pglob != NULL);
+
+ if (g_Ctoc(fn, buf, sizeof(buf)))
+ return -1;
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ return (*pglob->gl_stat)(buf, sb);
+ return stat(buf, sb);
+}
+
+static Char *
+g_strchr(const Char *str, int ch)
+{
+
+ _DIAGASSERT(str != NULL);
+
+ do {
+ if (*str == ch)
+ return __UNCONST(str);
+ } while (*str++);
+ return NULL;
+}
+
+static int
+g_Ctoc(const Char *str, char *buf, size_t len)
+{
+ char *dc;
+
+ _DIAGASSERT(str != NULL);
+ _DIAGASSERT(buf != NULL);
+
+ if (len == 0)
+ return 1;
+
+ for (dc = buf; len && (*dc++ = *str++) != EOS; len--)
+ continue;
+
+ return len == 0;
+}
+
+#ifdef DEBUG
+static void
+qprintf(const char *str, Char *s)
+{
+ Char *p;
+
+ _DIAGASSERT(str != NULL);
+ _DIAGASSERT(s != NULL);
+
+ (void)printf("%s:\n", str);
+ for (p = s; *p; p++)
+ (void)printf("%c", CHAR(*p));
+ (void)printf("\n");
+ for (p = s; *p; p++)
+ (void)printf("%c", *p & M_PROTECT ? '"' : ' ');
+ (void)printf("\n");
+ for (p = s; *p; p++)
+ (void)printf("%c", ismeta(*p) ? '_' : ' ');
+ (void)printf("\n");
+}
+#endif
diff --git a/StdLib/PosixLib/Glob/internal.h b/StdLib/PosixLib/Glob/internal.h new file mode 100644 index 0000000000..c65a7ca075 --- /dev/null +++ b/StdLib/PosixLib/Glob/internal.h @@ -0,0 +1,23 @@ +/** @file
+ Implement the invalid functions to return failures.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <errno.h>
+#include <dirent.h>
+#include <sysexits.h>
+
+typedef VOID* DIR;
+
+struct dirent * readdir(DIR *);
+int closedir(DIR *);
+DIR * opendir(const char *);
diff --git a/StdLib/PosixLib/Stringlist/LibStringlist.inf b/StdLib/PosixLib/Stringlist/LibStringlist.inf new file mode 100644 index 0000000000..c441765386 --- /dev/null +++ b/StdLib/PosixLib/Stringlist/LibStringlist.inf @@ -0,0 +1,41 @@ +## @file
+# Library used for supplying glob POSIX routines.
+#
+# Copyright (c) 2011, Intel Corporation. All rights reserved. <BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = LibStringlist
+ FILE_GUID = 19D17940-BA8D-4fa7-A704-F33D9FAFAB9D
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = LibStringlist|UEFI_APPLICATION UEFI_DRIVER
+
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ stringlist.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ StdLib/StdLib.dec
+ StdLibPrivateInternalFiles/DoNotUse.dec
+
+[Libraries]
+ LibC
+ LibStdio
+ LibStdLib
+ LibString
diff --git a/StdLib/PosixLib/Stringlist/stringlist.c b/StdLib/PosixLib/Stringlist/stringlist.c new file mode 100644 index 0000000000..47e3bee748 --- /dev/null +++ b/StdLib/PosixLib/Stringlist/stringlist.c @@ -0,0 +1,154 @@ +/* $NetBSD: stringlist.c,v 1.13 2008/04/28 20:22:59 martin Exp $
+
+ * Copyright (c) 1994, 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma warning ( disable : 4018 )
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: stringlist.c,v 1.13 2008/04/28 20:22:59 martin Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stringlist.h>
+
+#ifdef __weak_alias
+__weak_alias(sl_add,_sl_add)
+__weak_alias(sl_find,_sl_find)
+__weak_alias(sl_free,_sl_free)
+__weak_alias(sl_init,_sl_init)
+__weak_alias(sl_delete,_sl_delete)
+#endif
+
+#define _SL_CHUNKSIZE 20
+
+/*
+ * sl_init(): Initialize a string list
+ */
+StringList *
+sl_init(void)
+{
+ StringList *sl;
+
+ sl = malloc(sizeof(StringList));
+ if (sl == NULL)
+ return NULL;
+
+ sl->sl_cur = 0;
+ sl->sl_max = _SL_CHUNKSIZE;
+ sl->sl_str = malloc(sl->sl_max * sizeof(char *));
+ if (sl->sl_str == NULL) {
+ free(sl);
+ sl = NULL;
+ }
+ return sl;
+}
+
+
+/*
+ * sl_add(): Add an item to the string list
+ */
+int
+sl_add(StringList *sl, char *name)
+{
+
+ _DIAGASSERT(sl != NULL);
+
+ if (sl->sl_cur == sl->sl_max - 1) {
+ char **new;
+
+ new = realloc(sl->sl_str,
+ (sl->sl_max + _SL_CHUNKSIZE) * sizeof(char *));
+ if (new == NULL)
+ return -1;
+ sl->sl_max += _SL_CHUNKSIZE;
+ sl->sl_str = new;
+ }
+ sl->sl_str[sl->sl_cur++] = name;
+ return 0;
+}
+
+
+/*
+ * sl_free(): Free a stringlist
+ */
+void
+sl_free(StringList *sl, int all)
+{
+ size_t i;
+
+ if (sl == NULL)
+ return;
+ if (sl->sl_str) {
+ if (all)
+ for (i = 0; i < sl->sl_cur; i++)
+ free(sl->sl_str[i]);
+ free(sl->sl_str);
+ }
+ free(sl);
+}
+
+
+/*
+ * sl_find(): Find a name in the string list
+ */
+char *
+sl_find(StringList *sl, const char *name)
+{
+ size_t i;
+
+ _DIAGASSERT(sl != NULL);
+
+ for (i = 0; i < sl->sl_cur; i++)
+ if (strcmp(sl->sl_str[i], name) == 0)
+ return sl->sl_str[i];
+
+ return NULL;
+}
+
+int
+sl_delete(StringList *sl, const char *name, int all)
+{
+ size_t i, j;
+
+ for (i = 0; i < sl->sl_cur; i++)
+ if (strcmp(sl->sl_str[i], name) == 0) {
+ if (all)
+ free(sl->sl_str[i]);
+ for (j = i + 1; j < sl->sl_cur; j++)
+ sl->sl_str[j - 1] = sl->sl_str[j];
+ sl->sl_str[--sl->sl_cur] = NULL;
+ return 0;
+ }
+ return -1;
+}
+
diff --git a/StdLib/SocketDxe/ComponentName.c b/StdLib/SocketDxe/ComponentName.c new file mode 100644 index 0000000000..7fe9c711ee --- /dev/null +++ b/StdLib/SocketDxe/ComponentName.c @@ -0,0 +1,182 @@ +/** @file
+ UEFI Component Name(2) protocol implementation.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Socket.h"
+
+/**
+ EFI Component Name Protocol declaration
+**/
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gComponentName = {
+ GetDriverName,
+ GetControllerName,
+ "eng"
+};
+
+/**
+ EFI Component Name 2 Protocol declaration
+**/
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) GetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) GetControllerName,
+ "en"
+};
+
+
+/**
+ Driver name table declaration
+**/
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
+mDriverNameTable[] = {
+ {"eng;en", L"Socket Layer Driver"},
+ {NULL, NULL}
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param [in] pThis A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param [in] pLanguage A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 3066 or ISO 639-2 language code format.
+ @param [out] ppDriverName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+GetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL * pThis,
+ IN CHAR8 * pLanguage,
+ OUT CHAR16 ** ppDriverName
+ )
+{
+ EFI_STATUS Status;
+
+ Status = LookupUnicodeString2 (
+ pLanguage,
+ pThis->SupportedLanguages,
+ mDriverNameTable,
+ ppDriverName,
+ (BOOLEAN)(pThis == &gComponentName)
+ );
+ return Status;
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param [in] pThis A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param [in] ControllerHandle The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+ @param [in] ChildHandle The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+ @param [in] pLanguage A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 3066 or ISO 639-2 language code format.
+ @param [out] ppControllerName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+GetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL * pThis,
+ IN EFI_HANDLE ControllerHandle,
+ IN OPTIONAL EFI_HANDLE ChildHandle,
+ IN CHAR8 * pLanguage,
+ OUT CHAR16 ** ppControllerName
+ )
+{
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Set the controller name
+ //
+ *ppControllerName = L"Socket Layer";
+ Status = EFI_SUCCESS;
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_HEX ( Status );
+ return Status;
+}
diff --git a/StdLib/SocketDxe/DriverBinding.c b/StdLib/SocketDxe/DriverBinding.c new file mode 100644 index 0000000000..7de7f62a35 --- /dev/null +++ b/StdLib/SocketDxe/DriverBinding.c @@ -0,0 +1,198 @@ +/** @file
+ Implement the driver binding protocol for the socket layer.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Socket.h"
+
+/**
+ Verify the controller type
+
+ Determine if any of the network service binding protocols exist on
+ the controller handle. If so, verify that these protocols are not
+ already in use. Call ::DriverStart for any network service binding
+ protocol that is not in use.
+
+ @param [in] pThis Protocol instance pointer.
+ @param [in] Controller Handle of device to test.
+ @param [in] pRemainingDevicePath Not used.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval other This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+DriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL * pThis,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL * pRemainingDevicePath
+ )
+{
+ CONST DT_SOCKET_BINDING * pEnd;
+ VOID * pInterface;
+ CONST DT_SOCKET_BINDING * pSocketBinding;
+ EFI_STATUS Status;
+
+ //
+ // Assume the list is empty
+ //
+ Status = EFI_UNSUPPORTED;
+
+ //
+ // Walk the list of network connection points
+ //
+ pSocketBinding = &cEslSocketBinding[0];
+ pEnd = &pSocketBinding[ cEslSocketBindingEntries ];
+ while ( pEnd > pSocketBinding ) {
+ //
+ // Determine if the controller supports the network protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ pSocketBinding->pNetworkBinding,
+ &pInterface,
+ pThis->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Determine if the driver is already connected
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ (EFI_GUID *)pSocketBinding->pTagGuid,
+ &pInterface,
+ pThis->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if ( !EFI_ERROR ( Status )) {
+ Status = EFI_ALREADY_STARTED;
+ }
+ else {
+ if ( EFI_UNSUPPORTED == Status ) {
+ //
+ // Connect the driver since the tag is not present
+ //
+ Status = EFI_SUCCESS;
+ }
+ }
+ }
+
+ //
+ // Set the next network protocol
+ //
+ pSocketBinding += 1;
+ }
+
+ //
+ // Return the device supported status
+ //
+ return Status;
+}
+
+
+/**
+ Connect to the network service bindings
+
+ Walk the network service protocols on the controller handle and
+ locate any that are not in use. Create service structures to
+ manage the service binding for the socket driver.
+
+ @param [in] pThis Protocol instance pointer.
+ @param [in] Controller Handle of device to work with.
+ @param [in] pRemainingDevicePath Not used, always produce all possible children.
+
+ @retval EFI_SUCCESS This driver is added to Controller.
+ @retval other This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+DriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL * pThis,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL * pRemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Connect to this network adapter
+ //
+ Status = EslServiceConnect ( pThis->DriverBindingHandle,
+ Controller );
+
+ //
+ // Display the driver start status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and
+ closing the DevicePath and PciIo protocols on Controller.
+
+ @param [in] pThis Protocol instance pointer.
+ @param [in] Controller Handle of device to stop driver on.
+ @param [in] NumberOfChildren How many children need to be stopped.
+ @param [in] pChildHandleBuffer Not used.
+
+ @retval EFI_SUCCESS This driver is removed Controller.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+ @retval other This driver was not removed from this device.
+
+**/
+EFI_STATUS
+EFIAPI
+DriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL * pThis,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE * pChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Disconnect the network adapters
+ //
+ Status = EslServiceDisconnect ( pThis->DriverBindingHandle,
+ Controller );
+
+ //
+ // Display the driver start status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Driver binding protocol definition
+**/
+EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
+ DriverSupported,
+ DriverStart,
+ DriverStop,
+ 0xa,
+ NULL,
+ NULL
+};
diff --git a/StdLib/SocketDxe/EntryUnload.c b/StdLib/SocketDxe/EntryUnload.c new file mode 100644 index 0000000000..6afd8e6b48 --- /dev/null +++ b/StdLib/SocketDxe/EntryUnload.c @@ -0,0 +1,296 @@ +/** @file
+ Implement the entry and unload for the socket driver.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Socket.h"
+
+
+CONST EFI_GUID mEslRawServiceGuid = {
+ 0xf9f5d280, 0x8a4b, 0x48e2, { 0x96, 0x28, 0xda, 0xfa, 0xa7, 0x70, 0x54, 0x5d }
+};
+
+CONST EFI_GUID mEslTcp4ServiceGuid = {
+ 0x4dcaab0a, 0x1990, 0x4352, { 0x8d, 0x2f, 0x2d, 0x8f, 0x13, 0x55, 0x98, 0xa5 }
+};
+
+CONST EFI_GUID mEslUdp4ServiceGuid = {
+ 0x43a110ce, 0x9ccd, 0x402b, { 0x8c, 0x29, 0x4a, 0x6d, 0x8a, 0xf7, 0x79, 0x90 }
+};
+
+
+/**
+ Socket driver unload routine.
+
+ @param [in] ImageHandle Handle for the image.
+
+ @retval EFI_SUCCESS Image may be unloaded
+
+**/
+EFI_STATUS
+EFIAPI
+DriverUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ UINTN BufferSize;
+ UINTN Index;
+ UINTN Max;
+ EFI_HANDLE * pHandle;
+ EFI_STATUS Status;
+
+ //
+ // Determine which devices are using this driver
+ //
+ BufferSize = 0;
+ pHandle = NULL;
+ Status = gBS->LocateHandle (
+ ByProtocol,
+ &gEfiCallerIdGuid,
+ NULL,
+ &BufferSize,
+ NULL );
+ if ( EFI_BUFFER_TOO_SMALL == Status ) {
+ for ( ; ; ) {
+ //
+ // One or more block IO devices are present
+ //
+ Status = gBS->AllocatePool (
+ EfiRuntimeServicesData,
+ BufferSize,
+ (VOID **) &pHandle
+ );
+ if ( EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
+ "Insufficient memory, failed handle buffer allocation\r\n" ));
+ break;
+ }
+
+ //
+ // Locate the block IO devices
+ //
+ Status = gBS->LocateHandle (
+ ByProtocol,
+ &gEfiCallerIdGuid,
+ NULL,
+ &BufferSize,
+ pHandle );
+ if ( EFI_ERROR ( Status )) {
+ //
+ // Error getting handles
+ //
+ DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_INFO,
+ "Failure getting Telnet handles\r\n" ));
+ break;
+ }
+
+ //
+ // Remove any use of the driver
+ //
+ Max = BufferSize / sizeof ( pHandle[ 0 ]);
+ for ( Index = 0; Max > Index; Index++ ) {
+ Status = DriverStop ( &gDriverBinding,
+ pHandle[ Index ],
+ 0,
+ NULL );
+ if ( EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_WARN | DEBUG_INIT | DEBUG_INFO,
+ "WARNING - Failed to shutdown the driver on handle %08x\r\n", pHandle[ Index ]));
+ break;
+ }
+ }
+ break;
+ }
+ }
+ else {
+ if ( EFI_NOT_FOUND == Status ) {
+ //
+ // No devices were found
+ //
+ Status = EFI_SUCCESS;
+ }
+ }
+
+ //
+ // Free the handle array
+ //
+ if ( NULL != pHandle ) {
+ gBS->FreePool ( pHandle );
+ }
+
+ //
+ // Done with the socket layer
+ //
+ if ( !EFI_ERROR ( Status )) {
+ Status = EslServiceUninstall ( ImageHandle );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Remove the protocols installed by the EntryPoint routine.
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ ImageHandle,
+ &gEfiDriverBindingProtocolGuid,
+ &gDriverBinding,
+ &gEfiComponentNameProtocolGuid,
+ &gComponentName,
+ &gEfiComponentName2ProtocolGuid,
+ &gComponentName2,
+ NULL
+ );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
+ "Removed: gEfiComponentName2ProtocolGuid from 0x%08x\r\n",
+ ImageHandle ));
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
+ "Removed: gEfiComponentNameProtocolGuid from 0x%08x\r\n",
+ ImageHandle ));
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
+ "Removed: gEfiDriverBindingProtocolGuid from 0x%08x\r\n",
+ ImageHandle ));
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,
+ "ERROR - Failed to remove gEfiDriverBindingProtocolGuid from 0x%08x, Status: %r\r\n",
+ ImageHandle,
+ Status ));
+ }
+ }
+ }
+
+ //
+ // Disconnect the network services
+ //
+ if ( !EFI_ERROR ( Status )) {
+ EslServiceUnload ( );
+ }
+
+ //
+ // Return the unload status
+ //
+ return Status;
+}
+
+
+/**
+Socket driver entry point.
+
+@param [in] ImageHandle Handle for the image.
+@param [in] pSystemTable Address of the system table.
+
+@retval EFI_SUCCESS Image successfully loaded.
+
+**/
+EFI_STATUS
+EFIAPI
+EntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE * pSystemTable
+ )
+{
+ EFI_LOADED_IMAGE_PROTOCOL * pLoadedImage;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Display the image handle
+ //
+ DEBUG (( DEBUG_INFO,
+ "ImageHandle: 0x%08x\r\n",
+ ImageHandle ));
+
+ //
+ // Enable unload support
+ //
+ Status = gBS->HandleProtocol (
+ gImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **)&pLoadedImage
+ );
+ if (!EFI_ERROR (Status)) {
+ pLoadedImage->Unload = DriverUnload;
+
+ //
+ // Add the driver to the list of drivers
+ //
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ pSystemTable,
+ &gDriverBinding,
+ ImageHandle,
+ &gComponentName,
+ &gComponentName2
+ );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
+ "Installed: gEfiDriverBindingProtocolGuid on 0x%08x\r\n",
+ ImageHandle ));
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
+ "Installed: gEfiComponentNameProtocolGuid on 0x%08x\r\n",
+ ImageHandle ));
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
+ "Installed: gEfiComponentName2ProtocolGuid on 0x%08x\r\n",
+ ImageHandle ));
+
+ //
+ // Initialize the service layer
+ //
+ EslServiceLoad ( ImageHandle );
+
+ //
+ // Make the socket serivces available to other drivers
+ // and applications
+ //
+ Status = EslServiceInstall ( &ImageHandle );
+ if ( EFI_ERROR ( Status )) {
+ //
+ // Disconnect from the network
+ //
+ EslServiceUnload ( );
+
+ //
+ // Remove the driver bindings
+ //
+ gBS->UninstallMultipleProtocolInterfaces (
+ ImageHandle,
+ &gEfiDriverBindingProtocolGuid,
+ &gDriverBinding,
+ &gEfiComponentNameProtocolGuid,
+ &gComponentName,
+ &gEfiComponentName2ProtocolGuid,
+ &gComponentName2,
+ NULL
+ );
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
+ "Removed: gEfiComponentName2ProtocolGuid from 0x%08x\r\n",
+ ImageHandle ));
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
+ "Removed: gEfiComponentNameProtocolGuid from 0x%08x\r\n",
+ ImageHandle ));
+ DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
+ "Removed: gEfiDriverBindingProtocolGuid from 0x%08x\r\n",
+ ImageHandle ));
+ }
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,
+ "ERROR - EfiLibInstallDriverBindingComponentName2 failed, Status: %r\r\n",
+ Status ));
+ }
+ }
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+PFN_ESL_xSTRUCTOR mpfnEslConstructor = NULL;
+PFN_ESL_xSTRUCTOR mpfnEslDestructor = NULL;
diff --git a/StdLib/SocketDxe/Socket.h b/StdLib/SocketDxe/Socket.h new file mode 100644 index 0000000000..dfa4dad51b --- /dev/null +++ b/StdLib/SocketDxe/Socket.h @@ -0,0 +1,175 @@ +/** @file
+ Definitions for the Socket layer driver.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef _SOCKET_H_
+#define _SOCKET_H_
+
+#include <Library/UefiDriverEntryPoint.h>
+#include <Efi/EfiSocketLib.h>
+
+#include <Protocol/LoadedImage.h>
+
+//------------------------------------------------------------------------------
+// Protocol Declarations
+//------------------------------------------------------------------------------
+
+extern EFI_COMPONENT_NAME_PROTOCOL gComponentName; ///< Component name protocol declaration
+extern EFI_COMPONENT_NAME2_PROTOCOL gComponentName2; ///< Component name 2 protocol declaration
+extern EFI_DRIVER_BINDING_PROTOCOL gDriverBinding; ///< Driver binding protocol declaration
+extern EFI_SERVICE_BINDING_PROTOCOL mServiceBinding; ///< Service binding protocol delcaration
+
+//------------------------------------------------------------------------------
+// Driver Binding Protocol Support
+//------------------------------------------------------------------------------
+
+/**
+ Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and
+ closing the DevicePath and PciIo protocols on Controller.
+
+ @param [in] pThis Protocol instance pointer.
+ @param [in] Controller Handle of device to stop driver on.
+ @param [in] NumberOfChildren How many children need to be stopped.
+ @param [in] pChildHandleBuffer Not used.
+
+ @retval EFI_SUCCESS This driver is removed Controller.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+ @retval other This driver was not removed from this device.
+
+**/
+EFI_STATUS
+EFIAPI
+DriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL * pThis,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE * pChildHandleBuffer
+ );
+
+//------------------------------------------------------------------------------
+// EFI Component Name Protocol Support
+//------------------------------------------------------------------------------
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param [in] pThis A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param [in] pLanguage A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 3066 or ISO 639-2 language code format.
+ @param [out] ppDriverName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+GetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL * pThis,
+ IN CHAR8 * pLanguage,
+ OUT CHAR16 ** ppDriverName
+ );
+
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param [in] pThis A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param [in] ControllerHandle The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+ @param [in] ChildHandle The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+ @param [in] pLanguage A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 3066 or ISO 639-2 language code format.
+ @param [out] ppControllerName A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+GetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL * pThis,
+ IN EFI_HANDLE ControllerHandle,
+ IN OPTIONAL EFI_HANDLE ChildHandle,
+ IN CHAR8 * pLanguage,
+ OUT CHAR16 ** ppControllerName
+ );
+
+//------------------------------------------------------------------------------
+
+#endif // _SOCKET_H_
diff --git a/StdLib/SocketDxe/SocketDxe.inf b/StdLib/SocketDxe/SocketDxe.inf new file mode 100644 index 0000000000..1b459bafc8 --- /dev/null +++ b/StdLib/SocketDxe/SocketDxe.inf @@ -0,0 +1,62 @@ +#/** @file
+# Component description file for the socket layer driver.
+#
+# This module implements the socket layer.
+# Copyright (c) 2011, Intel Corporation
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SocketDxe
+ FILE_GUID = 2A43BA5F-AC29-4fdc-8A3B-0328D0256F8C
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = EntryPoint
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ Socket.h
+ ComponentName.c
+ DriverBinding.c
+ EntryUnload.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ StdLib/StdLib.dec
+
+[LibraryClasses]
+ EfiSocketLib
+ UefiLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ UefiRuntimeLib
+ UefiDriverEntryPoint
+
+[Protocols]
+ gEfiTcp4ProtocolGuid
+ gEfiTcp4ServiceBindingProtocolGuid
+ gEfiUdp4ProtocolGuid
+ gEfiUdp4ServiceBindingProtocolGuid
+ gEfiSocketProtocolGuid
+ gEfiSocketServiceBindingProtocolGuid
+
+[Depex]
+ gEfiBdsArchProtocolGuid AND
+ gEfiCpuArchProtocolGuid AND
+ gEfiTcp4ServiceBindingProtocolGuid AND
+ gEfiTimerArchProtocolGuid AND
+ gEfiUdp4ServiceBindingProtocolGuid
diff --git a/StdLib/StdLib.dec b/StdLib/StdLib.dec index 6c5b11aba4..b31469c4a1 100644 --- a/StdLib/StdLib.dec +++ b/StdLib/StdLib.dec @@ -34,3 +34,18 @@ [Includes.ARM]
Include/Arm
+
+
+[Guids]
+ gStdLibTokenSpaceGuid = { 0x447559f0, 0xd02e, 0x4cf1, { 0x99, 0xbc, 0xca, 0x11, 0x65, 0x40, 0x54, 0xc2 }}
+
+
+[PcdsFixedAtBuild]
+ gStdLibTokenSpaceGuid.DataSource_Port|1234|UINT16|0
+ gStdLibTokenSpaceGuid.WebServer_HttpPort|80|UINT16|1
+
+
+[Protocols]
+ gEfiSocketProtocolGuid = { 0x58e6ed63, 0x1694, 0x440b, { 0x93, 0x88, 0xe9, 0x8f, 0xed, 0x6b, 0x65, 0xaf } }
+ gEfiSocketServiceBindingProtocolGuid = { 0x8aaedb2a, 0xa6bb, 0x47c6, { 0x94, 0xce, 0x1b, 0x80, 0x96, 0x42, 0x3f, 0x2a } }
+
diff --git a/StdLib/StdLib.dsc b/StdLib/StdLib.dsc index 3f71d41e30..454f31040e 100644 --- a/StdLib/StdLib.dsc +++ b/StdLib/StdLib.dsc @@ -43,6 +43,7 @@ #
UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
+ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
#
# Common Libraries
#
@@ -69,41 +70,7 @@ ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
FileHandleLib|ShellPkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
SortLib|ShellPkg/Library/UefiSortLib/UefiSortLib.inf
-
- #
- # C Standard Libraries
- #
- LibC|StdLib/LibC/LibC.inf
- LibStdLib|StdLib/LibC/StdLib/StdLib.inf
- LibString|StdLib/LibC/String/String.inf
- LibWchar|StdLib/LibC/Wchar/Wchar.inf
- LibCType|StdLib/LibC/Ctype/Ctype.inf
- LibTime|StdLib/LibC/Time/Time.inf
- LibStdio|StdLib/LibC/Stdio/Stdio.inf
- LibGdtoa|StdLib/LibC/gdtoa/gdtoa.inf
- LibLocale|StdLib/LibC/Locale/Locale.inf
- LibUefi|StdLib/LibC/Uefi/Uefi.inf
- LibMath|StdLib/LibC/Math/Math.inf
- LibSignal|StdLib/LibC/Signal/Signal.inf
- LibNetUtil|StdLib/LibC/NetUtil/NetUtil.inf
-
- # Libraries for device abstractions within the Standard C Library
- # Applications should not directly access any functions defined in these libraries.
- DevUtility|StdLib/LibC/Uefi/Devices/daUtility.inf
- DevConsole|StdLib/LibC/Uefi/Devices/daConsole.inf
- DevShell|StdLib/LibC/Uefi/Devices/daShell.inf
-
-[LibraryClasses.IA32]
- TimerLib|PerformancePkg/Library/DxeTscTimerLib/DxeTscTimerLib.inf
- ## Comment out the above line and un-comment the line below for running under Nt32 emulation.
-# TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
-
-[LibraryClasses.X64]
- TimerLib|PerformancePkg/Library/DxeTscTimerLib/DxeTscTimerLib.inf
-
-[LibraryClasses.IPF]
- PalLib|MdePkg/Library/UefiPalLib/UefiPalLib.inf
- TimerLib|MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf
+ PathLib|ShellPkg/Library/BasePathLib/BasePathLib.inf
###################################################################################################
#
@@ -125,20 +92,6 @@ ###################################################################################################
[Components]
-# BaseLib and BaseMemoryLib need to be built with the /GL- switch when using the Microsoft
-# tool chain. This is required so that the library functions can be resolved during
-# the second pass of the linker during Link-time-code-generation.
-###
-# MdePkg/Library/BaseLib/BaseLib.inf {
-# <BuildOptions>
-# MSFT:*_*_*_CC_FLAGS = /X /Zc:wchar_t /GL-
-# }
-#
-# MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf {
-# <BuildOptions>
-# MSFT:*_*_*_CC_FLAGS = /X /Zc:wchar_t /GL-
-# }
-
# Standard C Libraries.
StdLib/LibC/LibC.inf
StdLib/LibC/StdLib/StdLib.inf
@@ -147,7 +100,6 @@ StdLib/LibC/Ctype/Ctype.inf
StdLib/LibC/Time/Time.inf
StdLib/LibC/Stdio/Stdio.inf
- StdLib/LibC/gdtoa/gdtoa.inf
StdLib/LibC/Locale/Locale.inf
StdLib/LibC/Uefi/Uefi.inf
StdLib/LibC/Math/Math.inf
@@ -156,26 +108,25 @@ # Device Abstractions within the Standard C Library
# Applications should not directly access any functions defined in these libraries.
+ StdLib/LibC/gdtoa/gdtoa.inf
StdLib/LibC/Uefi/Devices/daUtility.inf
StdLib/LibC/Uefi/Devices/daConsole.inf
StdLib/LibC/Uefi/Devices/daShell.inf
-################################################################
-#
-# See the additional comments below if you plan to run applications under the
-# Nt32 emulation environment.
-#
-
-[BuildOptions]
- INTEL:*_*_*_CC_FLAGS = /Qfreestanding
- MSFT:*_*_*_CC_FLAGS = /X /Zc:wchar_t
- GCC:*_*_*_CC_FLAGS = -ffreestanding -nostdinc -nostdlib
+# Additional libraries for POSIX functionality.
+ StdLib/PosixLib/Err/LibErr.inf
+ StdLib/PosixLib/Gen/LibGen.inf
+ StdLib/PosixLib/Glob/LibGlob.inf
+ StdLib/PosixLib/Stringlist/LibStringlist.inf
-# The Build Options, below, are only used when building the C library
-# to be run under the NT32 emulation. They disable the clock() system call
-# which is currently incompatible with the NT32 environment.
-# Just uncomment the lines below and select the correct TimerLib instance, above.
+# Socket Applications - LibC based
+ StdLib/BsdSocketLib/BsdSocketLib.inf
+ StdLib/EfiSocketLib/EfiSocketLib.inf
+ StdLib/UseSocketDxe/UseSocketDxe.inf
- # INTEL:*_*_IA32_CC_FLAGS = /D NT32dvm
- # MSFT:*_*_IA32_CC_FLAGS = /D NT32dvm
- # GCC:*_*_IA32_CC_FLAGS = -DNT32dvm
+###################################################################################################
+#
+# Include Boilerplate text required for building with the Standard Libraries.
+#
+###################################################################################################
+!include StdLib/StdLib.inc
diff --git a/StdLib/StdLib.inc b/StdLib/StdLib.inc new file mode 100644 index 0000000000..e6d1b459ae --- /dev/null +++ b/StdLib/StdLib.inc @@ -0,0 +1,115 @@ +################################################################
+# Boilerplate text to be included by any DSC file using the
+# Standard Libraries.
+#
+# The including DSC file must DEFINE the EMULATE macro if
+# the application is to be run in an emulation environment.
+################################################################
+
+##########
+# Socket Support Libraries
+##########
+
+[LibraryClasses.common]
+ BsdSocketLib|StdLib/BsdSocketLib/BsdSocketLib.inf
+ EfiSocketLib|StdLib/EfiSocketLib/EfiSocketLib.inf
+ UseSocketDxe|StdLib/UseSocketDxe/UseSocketDxe.inf
+
+[LibraryClasses.Common.UEFI_APPLICATION]
+ #
+ # C Standard Libraries
+ #
+ LibC|StdLib/LibC/LibC.inf
+ LibCType|StdLib/LibC/Ctype/Ctype.inf
+ LibLocale|StdLib/LibC/Locale/Locale.inf
+ LibMath|StdLib/LibC/Math/Math.inf
+ LibSignal|StdLib/LibC/Signal/Signal.inf
+ LibStdio|StdLib/LibC/Stdio/Stdio.inf
+ LibStdLib|StdLib/LibC/StdLib/StdLib.inf
+ LibString|StdLib/LibC/String/String.inf
+ LibTime|StdLib/LibC/Time/Time.inf
+ LibUefi|StdLib/LibC/Uefi/Uefi.inf
+ LibWchar|StdLib/LibC/Wchar/Wchar.inf
+
+# Common Utilities for Networking Libraries
+ LibNetUtil|StdLib/LibC/NetUtil/NetUtil.inf
+
+# Additional libraries for POSIX functionality.
+ LibErr|StdLib/PosixLib/Err/LibErr.inf
+ LibGen|StdLib/PosixLib/Gen/LibGen.inf
+ LibGlob|StdLib/PosixLib/Glob/LibGlob.inf
+ LibStringlist|StdLib/PosixLib/Stringlist/LibStringlist.inf
+
+# Libraries for device abstractions within the Standard C Library
+# Applications should not directly access any functions defined in these libraries.
+ LibGdtoa|StdLib/LibC/gdtoa/gdtoa.inf
+ DevConsole|StdLib/LibC/Uefi/Devices/daConsole.inf
+ DevShell|StdLib/LibC/Uefi/Devices/daShell.inf
+ DevUtility|StdLib/LibC/Uefi/Devices/daUtility.inf
+
+###
+# Select the correct TimerLib instance depending upon whether running under
+# an emulation environment, or not.
+!ifndef $(EMULATE)
+ # Not running in an Emulation Environment
+[LibraryClasses.IA32.UEFI_APPLICATION]
+ TimerLib|PerformancePkg/Library/DxeTscTimerLib/DxeTscTimerLib.inf
+
+[LibraryClasses.X64.UEFI_APPLICATION]
+ TimerLib|PerformancePkg/Library/DxeTscTimerLib/DxeTscTimerLib.inf
+
+[LibraryClasses.IPF.UEFI_APPLICATION]
+ PalLib|MdePkg/Library/UefiPalLib/UefiPalLib.inf
+ TimerLib|MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf
+
+!else
+ # Running in an Emulation Environment.
+ # Adds this to the end of the current [LibraryClasses.Common.UEFI_APPLICATION] section.
+[LibraryClasses.Common.UEFI_APPLICATION]
+ TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
+!endif
+
+[Components]
+# BaseLib and BaseMemoryLib need to be built with the /GL- switch when using the Microsoft
+# tool chain. This is required so that the library functions can be resolved during
+# the second pass of the linker during Link-time-code-generation.
+###
+ MdePkg/Library/BaseLib/BaseLib.inf {
+ <BuildOptions>
+ MSFT:*_*_*_CC_FLAGS = /X /Zc:wchar_t /GL-
+ }
+
+ MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf {
+ <BuildOptions>
+ MSFT:*_*_*_CC_FLAGS = /X /Zc:wchar_t /GL-
+ }
+
+##########
+# Socket Layer
+##########
+ StdLib/SocketDxe/SocketDxe.inf
+
+
+##############################################################################
+#
+# See the additional comments below if you plan to run applications under an
+# emulation environment.
+#
+
+[BuildOptions]
+!ifndef $(EMULATE)
+ # These Build Options are used when building the Standard Libraries to be run
+ # on real hardware.
+ INTEL:*_*_*_CC_FLAGS = /Qfreestanding
+ MSFT:*_*_*_CC_FLAGS = /X /Zc:wchar_t
+ GCC:*_*_*_CC_FLAGS = -nostdinc -nostdlib
+
+!else
+ # The Build Options, below, are only used when building the Standard Libraries
+ # to be run under an emulation environment. They disable the clock() system call
+ # which is currently incompatible with the most emulation environments.
+ # Select the correct TimerLib instance, above.
+ INTEL:*_*_IA32_CC_FLAGS = /Od /D NT32dvm
+ MSFT:*_*_IA32_CC_FLAGS = /Od /D NT32dvm
+ GCC:*_*_IA32_CC_FLAGS = -O0 -DNT32dvm
+!endif
diff --git a/StdLib/UseSocketDxe/UseSocketDxe.c b/StdLib/UseSocketDxe/UseSocketDxe.c new file mode 100644 index 0000000000..0b7194c234 --- /dev/null +++ b/StdLib/UseSocketDxe/UseSocketDxe.c @@ -0,0 +1,160 @@ +/** @file
+ Implement the connection to the socket driver
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include <Protocol/EfiSocket.h>
+#include <Protocol/ServiceBinding.h>
+
+
+/**
+ Connect to the socket driver
+
+ @param [in] ppSocketProtocol Address to receive the socket protocol address
+
+ @retval 0 Successfully returned the socket protocol
+ @retval other Value for errno
+ **/
+int
+EslServiceGetProtocol (
+ IN EFI_SOCKET_PROTOCOL ** ppSocketProtocol
+ )
+{
+ EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding;
+ int RetVal;
+ EFI_HANDLE SocketHandle;
+ EFI_STATUS Status;
+
+ //
+ // Locate the socket protocol
+ //
+ Status = gBS->LocateProtocol ( &gEfiSocketServiceBindingProtocolGuid,
+ NULL,
+ (VOID **)&pServiceBinding );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Create a new socket
+ //
+ SocketHandle = NULL;
+ Status = pServiceBinding->CreateChild ( pServiceBinding,
+ &SocketHandle );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Get the socket protocol
+ //
+ Status = gBS->OpenProtocol ( SocketHandle,
+ &gEfiSocketProtocolGuid,
+ (VOID **)ppSocketProtocol,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Success!
+ //
+ RetVal = 0;
+ }
+ else {
+ DEBUG (( DEBUG_ERROR,
+ "ERROR - No socket protocol on 0x%08x, Status: %r\r\n",
+ SocketHandle,
+ Status ));
+ RetVal = ENODEV;
+ }
+ }
+ else {
+ //
+ // Translate the error
+ //
+ DEBUG (( DEBUG_ERROR,
+ "ERROR - CreateChild failed, Status: %r\r\n",
+ Status ));
+ switch ( Status ) {
+ case EFI_SUCCESS:
+ RetVal = 0;
+ break;
+
+ case EFI_ACCESS_DENIED:
+ case EFI_WRITE_PROTECTED:
+ RetVal = EACCES;
+ break;
+
+ case EFI_NO_RESPONSE:
+ RetVal = EHOSTUNREACH;
+ break;
+
+ case EFI_BAD_BUFFER_SIZE:
+ case EFI_BUFFER_TOO_SMALL:
+ case EFI_INVALID_PARAMETER:
+ RetVal = EINVAL;
+ break;
+
+ case EFI_DEVICE_ERROR:
+ case EFI_MEDIA_CHANGED:
+ case EFI_NO_MEDIA:
+ case EFI_VOLUME_CORRUPTED:
+ RetVal = EIO;
+ break;
+
+ case EFI_NOT_FOUND:
+ RetVal = ENOENT;
+ break;
+
+ default:
+ case EFI_OUT_OF_RESOURCES:
+ RetVal = ENOMEM;
+ break;
+
+ case EFI_VOLUME_FULL:
+ RetVal = ENOSPC;
+ break;
+
+ case EFI_UNSUPPORTED:
+ RetVal = ENOSYS;
+ break;
+
+ case EFI_NO_MAPPING:
+ RetVal = ENXIO;
+ break;
+
+ case EFI_LOAD_ERROR:
+ RetVal = ESRCH;
+ break;
+
+ case EFI_TIMEOUT:
+ RetVal = ETIMEDOUT;
+ break;
+
+ case EFI_NOT_READY:
+ RetVal = EWOULDBLOCK;
+ break;
+ }
+ }
+ }
+ else {
+ DEBUG (( DEBUG_ERROR,
+ "ERROR - No socket service binding protocol, Status: %r\r\n",
+ Status ));
+ RetVal = ENODEV;
+ }
+
+ //
+ // Return the operation status
+ //
+ return RetVal;
+}
diff --git a/StdLib/UseSocketDxe/UseSocketDxe.inf b/StdLib/UseSocketDxe/UseSocketDxe.inf new file mode 100644 index 0000000000..45fb70f292 --- /dev/null +++ b/StdLib/UseSocketDxe/UseSocketDxe.inf @@ -0,0 +1,45 @@ +#/** @file
+# Component description file for the EFI socket library.
+#
+# This module implements the socket layer.
+# Copyright (c) 2011, Intel Corporation
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = UseSocketDxe
+ FILE_GUID = 1A6853C8-F362-4f68-A77E-0B304A194C05
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = UseSocketDxe
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ UseSocketDxe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ StdLib/StdLib.dec
+# SocketPkg/SocketPkg.dec
+
+[LibraryClasses]
+ UefiLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ DebugLib
+
+[Protocols]
+ gEfiSocketProtocolGuid
+ gEfiSocketServiceBindingProtocolGuid
|