diff --git a/include/arpa/ftp.h b/include/arpa/ftp.h new file mode 100644 index 00000000..88206558 --- /dev/null +++ b/include/arpa/ftp.h @@ -0,0 +1,118 @@ +/* + * 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 + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* 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 */ + +#ifdef __cplusplus +} +#endif + +#endif /* !_ARPA_FTP_H */ diff --git a/include/arpa/inet.h b/include/arpa/inet.h new file mode 100644 index 00000000..8555b2dd --- /dev/null +++ b/include/arpa/inet.h @@ -0,0 +1,82 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _ARPA_INET_H +#define _ARPA_INET_H + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Fundamental Internet types */ +#ifndef __libsocket_in_port_t +typedef unsigned short in_port_t; +#define __libsocket_in_port_t +#endif /* __libsocket_in_port_t */ + +#ifndef __libsocket_in_addr_t +typedef unsigned long in_addr_t; +#define __libsocket_in_addr_t +#endif /* __libsocket_in_addr_t */ + +/* Internet address. */ +#ifndef __libsocket_in_addr +#define __libsocket_in_addr +struct in_addr { + in_addr_t s_addr; +}; +#endif /* __libsocket_in_addr */ + +/* Function declarations */ +extern in_addr_t inet_addr (const char *); +extern in_addr_t inet_lnaof (struct in_addr); +extern struct in_addr inet_makeaddr (in_addr_t, in_addr_t); +extern in_addr_t inet_netof (struct in_addr); +extern in_addr_t inet_network (const char *); +extern char *inet_ntoa (struct in_addr); +extern int inet_aton (const char *, struct in_addr *); + +/* New inet functions for handling IPv6 (and other) <-> text conversions. */ +extern const char *inet_ntop (int , const void *, char *, size_t); +extern int inet_pton (int, const char *, void *); + +/* NSAP address functions (que?) */ +extern char *inet_nsap_ntoa (int, + register const unsigned char *, + register char *); + +extern unsigned int inet_nsap_addr (const char * /* ascii */, + unsigned char * /*binary */, + int /* maxlen */); + +#ifdef __cplusplus +} +#endif + +#endif /* _ARPA_INET_H */ diff --git a/include/arpa/nameser.h b/include/arpa/nameser.h new file mode 100644 index 00000000..563666bb --- /dev/null +++ b/include/arpa/nameser.h @@ -0,0 +1,284 @@ +/* + * ++Copyright++ 1983, 1989, 1993 + * - + * 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. + * - + * 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. + * --Copyright-- + */ + +/* + * @(#)nameser.h 8.1 (Berkeley) 6/2/93 + * $Id: nameser.h,v 1.2 2000/11/16 21:27:21 rich Exp $ + */ + +/* + This is part of libsocket. It has been heavily modified by Richard Dawe + in order to incorporate it into libsocket. +*/ + +#ifndef _NAMESER_H_ +#define _NAMESER_H_ + +#include /* RD: Typedefs needed! */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Define constants based on rfc883 + */ +#define PACKETSZ 512 /* maximum packet size */ +#define MAXDNAME 1025 /* maximum domain name */ +#define MAXCDNAME 255 /* maximum compressed domain name */ +#define MAXLABEL 63 /* maximum length of domain label */ +#define HFIXEDSZ 12 /* #/bytes of fixed data in header */ +#define QFIXEDSZ 4 /* #/bytes of fixed data in query */ +#define RRFIXEDSZ 10 /* #/bytes of fixed data in r record */ +#define INT32SZ 4 /* for systems without 32-bit ints */ +#define INT16SZ 2 /* for systems without 16-bit ints */ +#define INADDRSZ 4 /* IPv4 T_A */ +#define IN6ADDRSZ 16 /* IPv6 T_AAAA */ + +/* + * Internet nameserver port number + */ +#define NAMESERVER_PORT 53 + +/* + * Currently defined opcodes + */ +#define QUERY 0x0 /* standard query */ +#define IQUERY 0x1 /* inverse query */ +#define STATUS 0x2 /* nameserver status query */ +/*#define xxx 0x3 *//* 0x3 reserved */ +#define NS_NOTIFY_OP 0x4 /* notify secondary of SOA change */ +#ifdef ALLOW_UPDATES + /* non standard - supports ALLOW_UPDATES stuff from Mike Schwartz */ +# define UPDATEA 0x9 /* add resource record */ +# define UPDATED 0xa /* delete a specific resource record */ +# define UPDATEDA 0xb /* delete all named resource record */ +# define UPDATEM 0xc /* modify a specific resource record */ +# define UPDATEMA 0xd /* modify all named resource record */ +# define ZONEINIT 0xe /* initial zone transfer */ +# define ZONEREF 0xf /* incremental zone referesh */ +#endif + +/* + * Currently defined response codes + */ +#define NOERROR 0 /* no error */ +#define FORMERR 1 /* format error */ +#define SERVFAIL 2 /* server failure */ +#define NXDOMAIN 3 /* non existent domain */ +#define NOTIMP 4 /* not implemented */ +#define REFUSED 5 /* query refused */ +#ifdef ALLOW_UPDATES + /* non standard */ +# define NOCHANGE 0xf /* update failed to change db */ +#endif + +/* + * Type values for resources and queries + */ +#define T_A 1 /* host address */ +#define T_NS 2 /* authoritative server */ +#define T_MD 3 /* mail destination */ +#define T_MF 4 /* mail forwarder */ +#define T_CNAME 5 /* canonical name */ +#define T_SOA 6 /* start of authority zone */ +#define T_MB 7 /* mailbox domain name */ +#define T_MG 8 /* mail group member */ +#define T_MR 9 /* mail rename name */ +#define T_NULL 10 /* null resource record */ +#define T_WKS 11 /* well known service */ +#define T_PTR 12 /* domain name pointer */ +#define T_HINFO 13 /* host information */ +#define T_MINFO 14 /* mailbox information */ +#define T_MX 15 /* mail routing information */ +#define T_TXT 16 /* text strings */ +#define T_RP 17 /* responsible person */ +#define T_AFSDB 18 /* AFS cell database */ +#define T_X25 19 /* X_25 calling address */ +#define T_ISDN 20 /* ISDN calling address */ +#define T_RT 21 /* router */ +#define T_NSAP 22 /* NSAP address */ +#define T_NSAP_PTR 23 /* reverse NSAP lookup (deprecated) */ +#define T_SIG 24 /* security signature */ +#define T_KEY 25 /* security key */ +#define T_PX 26 /* X.400 mail mapping */ +#define T_GPOS 27 /* geographical position (withdrawn) */ +#define T_AAAA 28 /* IP6 Address */ +#define T_LOC 29 /* Location Information */ + /* non standard */ +#define T_UINFO 100 /* user (finger) information */ +#define T_UID 101 /* user ID */ +#define T_GID 102 /* group ID */ +#define T_UNSPEC 103 /* Unspecified format (binary data) */ + /* Query type values which do not appear in resource records */ +#define T_AXFR 252 /* transfer zone of authority */ +#define T_MAILB 253 /* transfer mailbox records */ +#define T_MAILA 254 /* transfer mail agent records */ +#define T_ANY 255 /* wildcard match */ + +/* + * Values for class field + */ + +#define C_IN 1 /* the arpa internet */ +#define C_CHAOS 3 /* for chaos net (MIT) */ +#define C_HS 4 /* for Hesiod name server (MIT) (XXX) */ + /* Query class values which do not appear in resource records */ +#define C_ANY 255 /* wildcard match */ + +/* + * Structure for query header. The order of the fields is machine- and + * compiler-dependent, depending on the byte/bit order and the layout + * of bit fields. We use bit fields only in int variables, as this + * is all ANSI requires. This requires a somewhat confusing rearrangement. + */ + +typedef struct { + unsigned id :16; /* query identification number */ + /* fields in third byte */ + unsigned rd: 1; /* recursion desired */ + unsigned tc: 1; /* truncated message */ + unsigned aa: 1; /* authoritive answer */ + unsigned opcode: 4; /* purpose of message */ + unsigned qr: 1; /* response flag */ + /* fields in fourth byte */ + unsigned rcode :4; /* response code */ + unsigned unused :2; /* unused bits (MBZ as of 4.9.3a3) */ + unsigned pr: 1; /* primary server req'd (!standard) */ + unsigned ra: 1; /* recursion available */ + /* remaining bytes */ + unsigned qdcount :16; /* number of question entries */ + unsigned ancount :16; /* number of answer entries */ + unsigned nscount :16; /* number of authority entries */ + unsigned arcount :16; /* number of resource entries */ +} HEADER; + +/* + * Defines for handling compressed domain names + */ +#define INDIR_MASK 0xc0 + +extern u_int16_t _getshort (const u_char *); +extern u_int32_t _getlong (const u_char *); + +/* + * Inline versions of get/put short/long. Pointer is advanced. + * + * These macros demonstrate the property of C whereby it can be + * portable or it can be elegant but rarely both. + */ +#define GETSHORT(s, cp) { \ + const u_char *t_cp = (const u_char *)(cp); \ + (s) = ((u_int16_t)t_cp[0] << 8) \ + | ((u_int16_t)t_cp[1]) \ + ; \ + (cp) += INT16SZ; \ +} + +#define GETLONG(l, cp) { \ + const u_char *t_cp = (const u_char *)(cp); \ + (l) = ((u_int32_t)t_cp[0] << 24) \ + | ((u_int32_t)t_cp[1] << 16) \ + | ((u_int32_t)t_cp[2] << 8) \ + | ((u_int32_t)t_cp[3]) \ + ; \ + (cp) += INT32SZ; \ +} + +#define PUTSHORT(s, cp) { \ + register u_int16_t t_s = (u_int16_t)(s); \ + register u_char *t_cp = (u_char *)(cp); \ + *t_cp++ = t_s >> 8; \ + *t_cp = t_s; \ + (cp) += INT16SZ; \ +} + +#define PUTLONG(l, cp) { \ + register u_int32_t t_l = (u_int32_t)(l); \ + register 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; \ + (cp) += INT32SZ; \ +} + +#ifdef __cplusplus +} +#endif + +#endif /* !_NAMESER_H_ */ diff --git a/include/arpa/telnet.h b/include/arpa/telnet.h new file mode 100644 index 00000000..d4d402f9 --- /dev/null +++ b/include/arpa/telnet.h @@ -0,0 +1,329 @@ +/* + * 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 + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* + * 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 NSLC 18 + +/* + * 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", 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 send 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] + +#ifdef __cplusplus +} +#endif + +#endif /* _ARPA_TELNET_H */ diff --git a/include/arpa/tftp.h b/include/arpa/tftp.h new file mode 100644 index 00000000..6a7eee34 --- /dev/null +++ b/include/arpa/tftp.h @@ -0,0 +1,89 @@ +/* + * 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. + * + * @(#)tftp.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _ARPA_TFTP_H +#define _ARPA_TFTP_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* + * Trivial File Transfer Protocol (IEN-133) + */ +#define SEGSIZE 512 /* data segment size */ + +/* + * Packet types. + */ +#define RRQ 01 /* read request */ +#define WRQ 02 /* write request */ +#define DATA 03 /* data packet */ +#define ACK 04 /* acknowledgement */ +#define ERROR 05 /* error code */ + +struct tftphdr { + short th_opcode; /* packet type */ + union { + unsigned short tu_block; /* block # */ + short tu_code; /* error code */ + char tu_stuff[1]; /* request packet stuff */ + } th_u; + char th_data[1]; /* data or error string */ +}; + +#define th_block th_u.tu_block +#define th_code th_u.tu_code +#define th_stuff th_u.tu_stuff +#define th_msg th_data + +/* + * Error codes. + */ +#define EUNDEF 0 /* not defined */ +#define ENOTFOUND 1 /* file not found */ +#define EACCESS 2 /* access violation */ +#define ENOSPACE 3 /* disk full or allocation exceeded */ +#define EBADOP 4 /* illegal TFTP operation */ +#define EBADID 5 /* unknown transfer ID */ +#define EEXISTS 6 /* file already exists */ +#define ENOUSER 7 /* no such user */ + +#ifdef __cplusplus +} +#endif + +#endif /* _ARPA_TFTP_H */ diff --git a/include/dj64/thunks_p.inc b/include/dj64/thunks_p.inc index 3a77d18c..361aad16 100644 --- a/include/dj64/thunks_p.inc +++ b/include/dj64/thunks_p.inc @@ -58,6 +58,7 @@ #define __CNV_PTR_CPVOID(t, d, f, l, t0) t d = PTR_DATA(f) #define __CNV_PTR_VOID(t, d, f, l, t0) t d = dj64_obj_init(f, l) #define __CNV_PTR_CVOID(t, d, f, l, t0) t d = dj64_obj_init(f, l) +#define __CNV_PTR_OVOID(t, d, f, l, t0) t d = dj64_obj_oinit(f, l) #define __CNV_SIMPLE(t, d, f, l, t0) t d = (f) #define _CNV(c, t, at, l, n) c(at, _a##n, a##n, l, t) @@ -76,6 +77,7 @@ #define U__CNV_PTR_CPVOID(f, d, l) #define U__CNV_PTR_VOID(f, d, l) dj64_obj_done(f, d, l) #define U__CNV_PTR_CVOID(f, d, l) dj64_rm_dosobj(f, d) +#define U__CNV_PTR_OVOID(f, d, l) dj64_obj_done(f, d, l) #define U__CNV_SIMPLE(f, d, l) #define _UCNV(c, l, n) U##c(a##n, _a##n, l) diff --git a/include/ioctls.h b/include/ioctls.h new file mode 100644 index 00000000..37aa2a10 --- /dev/null +++ b/include/ioctls.h @@ -0,0 +1,56 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __libsocket_ioctls_h__ +#define __libsocket_ioctls_h__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* These are from Linux and are implemented internally by libsocket. */ + +/* These constants *aren't* the same numerically as Linux, but the Linux + #define's didn't work. I think this is the way they should be defined, + and it seems to work. */ +#define SIOCGIFNAME _IOR('s', 0x10, char *) +#define SIOCGIFFLAGS _IOR('s', 0x13, struct ifreq *) /* Faked */ +#define SIOCGIFADDR _IOR('s', 0x15, struct ifreq *) +#define SIOCGIFDSTADDR _IOR('s', 0x17, struct ifreq *) +#define SIOCGIFBRDADDR _IOR('s', 0x19, struct ifreq *) /* Faked */ +#define SIOCGIFNETMASK _IOR('s', 0x1B, struct ifreq *) +#define SIOCGIFMETRIC _IOR('s', 0x1D, struct ifreq *) /* Faked */ +#define SIOCGIFMEM _IOR('s', 0x1F, struct ifreq *) /* Faked */ +#define SIOCGIFMTU _IOR('s', 0x21, struct ifreq *) /* Faked */ +#define SIOCGHWADDR _IOR('s', 0x27, struct ifreq *) /* Faked */ + +#ifdef __cplusplus +} +#endif + +#endif /* __libsocket_ioctls_h__ */ diff --git a/include/libc/asmobj.h b/include/libc/asmobj.h index 75c77010..05143feb 100644 --- a/include/libc/asmobj.h +++ b/include/libc/asmobj.h @@ -140,3 +140,5 @@ t *__##x(void) \ #endif #define __out +#define _V_FW(n) +#define _V_BW(n) diff --git a/include/lsck/bsdtypes.h b/include/lsck/bsdtypes.h new file mode 100644 index 00000000..84500a71 --- /dev/null +++ b/include/lsck/bsdtypes.h @@ -0,0 +1,52 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + bsdtypes.h - BSD types used by some of libsocket's code. +*/ + +#ifndef __libsocket_bsdtypes_h__ +#define __libsocket_bsdtypes_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned long int u_int32_t; +typedef unsigned short u_int16_t; + +typedef unsigned long u_long; +typedef unsigned int u_int; +typedef unsigned short u_short; +typedef unsigned char u_char; + +typedef char * __caddr_t; +typedef __caddr_t caddr_t; + +#ifdef __cplusplus +} +#endif + +#endif /* __libsocket_bsdtypes_h__ */ diff --git a/include/lsck/copyrite.h b/include/lsck/copyrite.h new file mode 100644 index 00000000..f8a129e0 --- /dev/null +++ b/include/lsck/copyrite.h @@ -0,0 +1,53 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* copyrite.h - Copyright information for libsocket + * This name really sucks, but how else can you get it into 8+3? */ + +#ifndef __libsocket_copyrite_h__ +#define __libsocket_copyrite_h__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern char *__lsck_get_version (void); +extern char *__lsck_get_copyright (void); + +#define LSCK_VERSION_MAJOR 0 +#define LSCK_VERSION_MINOR 8 +#define LSCK_VERSION_SUBMINOR 0 +#define LSCK_VERSION_ALPHA 0 +#define LSCK_VERSION_BETA 0 +#define LSCK_VERSION_PRE 0 +#define LSCK_VERSION_DATE "2000-11-16" +#define LSCK_VERSION_RELEASED 1 + +#ifdef __cplusplus +} +#endif + +#endif /* __libsocket_copyrite_h__ */ diff --git a/include/lsck/csock.h b/include/lsck/csock.h new file mode 100644 index 00000000..91d43d01 --- /dev/null +++ b/include/lsck/csock.h @@ -0,0 +1,24 @@ +#ifndef CSOCK_H +#define CSOCK_H + +#include +#include + +LONG32 ___csock_get_version(__out ULONG32 *ver); +LONG32 ___csock_open(ULONG32 proto, __out ULONG32 *fd); +LONG32 ___csock_close(ULONG32 fd); +LONG32 ___csock_bind(ULONG32 fd, ULONG32 addr, unsigned short port); +LONG32 ___csock_sendto(ULONG32 fd, ULONG32 addr, unsigned short port, const void _V_FW(1) *buf, ULONG32 len, __out ULONG32 *sent); +LONG32 ___csock_send(ULONG32 fd, const void _V_FW(1) *buf, ULONG32 len, __out ULONG32 *sent); +LONG32 ___csock_recvfrom(ULONG32 fd, __out void _V_FW(1) *buf, ULONG32 len, __out ULONG32 *rcvd, __out ULONG32 *addr, __out unsigned short *port); +LONG32 ___csock_recv(ULONG32 fd, __out void _V_FW(1) *buf, ULONG32 len, __out ULONG32 *rcvd); +LONG32 ___csock_listen(ULONG32 fd, ULONG32 backlog); +LONG32 ___csock_accept(ULONG32 fd, __out ULONG32 *afd, __out ULONG32 *addr, __out unsigned short *port); +LONG32 ___csock_select(ULONG32 *rfds, ULONG32 *wfds, ULONG32 *efds, ULONG32 *timeout); +LONG32 ___csock_connect(ULONG32 fd, ULONG32 addr, unsigned short port); +LONG32 ___csock_getsockname(ULONG32 fd, __out ULONG32 *addr, __out unsigned short *port); +LONG32 ___csock_getpeername(ULONG32 fd, __out ULONG32 *addr, __out unsigned short *port); +LONG32 ___csock_getnblkio(ULONG32 fd, __out ULONG32 *nb); +LONG32 ___csock_setnblkio(ULONG32 fd, __out ULONG32 nb); + +#endif diff --git a/include/lsck/domname.h b/include/lsck/domname.h new file mode 100644 index 00000000..73dfb278 --- /dev/null +++ b/include/lsck/domname.h @@ -0,0 +1,56 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __libsocket_domname_h__ +#define __libsocket_domname_h__ + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Define this constant for later use */ +#define MAXGETDOMAINNAME MAXGETHOSTNAME + +extern int getdomainname (char * /* name */, size_t /* len */); +extern int setdomainname (const char * /* name */, size_t /* len */); + +/* Define lsck_* versions to be the same */ +#ifndef __lsck_getdomainname +#define __lsck_getdomainname getdomainname +#endif + +#ifndef __lsck_setdomainname +#define __lsck_setdomainname setdomainname +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __libsocket_domname_h__ */ diff --git a/include/lsck/errno.h b/include/lsck/errno.h new file mode 100644 index 00000000..881370c0 --- /dev/null +++ b/include/lsck/errno.h @@ -0,0 +1,82 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __libsocket_errno_h__ +#define __libsocket_errno_h__ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* RD: DJGPP 2.04 will have symlink support, so ELOOP will be defined. + * If it's not, then use DJGPP 2.04's constant. */ +#ifndef ELOOP +#define ELOOP 39 +#endif /* ELOOP */ + +#define EWOULDBLOCK EAGAIN + +#define EREMOTE 66 /* Object is remote */ +#define EPROTOTYPE 71 /* Protocol error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection (reset) */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint + * shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EDQUOT 122 /* Quota exceeded */ + +#ifdef __cplusplus +} +#endif + +#endif /* __libsocket_errno_h__ */ diff --git a/include/lsck/hostname.h b/include/lsck/hostname.h new file mode 100644 index 00000000..407bd228 --- /dev/null +++ b/include/lsck/hostname.h @@ -0,0 +1,53 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + hostname.h - Functions for obtaining the computer's name. +*/ + +#ifndef __libsocket_hostname_h__ +#define __libsocket_hostname_h__ + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* For backwards compatibility */ +#define __lsck_gethostname gethostname +#define __lsck_sethostname sethostname + +/* gethostname() is defined in unistd.h */ +/*extern int gethostname (char *buf, int size);*/ +extern int sethostname (char * /* buf */ , int /* size */); + +#ifdef __cplusplus +} +#endif + +#endif /* __libsocket_hostname_h__ */ diff --git a/include/lsck/if.h b/include/lsck/if.h new file mode 100644 index 00000000..67c4bbd6 --- /dev/null +++ b/include/lsck/if.h @@ -0,0 +1,307 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + if.h + Interface include file +*/ + +#ifndef __libsocket_if_h__ +#define __libsocket_if_h__ + +#include +#include + +#include +#include +#include + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* --- Defines --- */ + +/* Interfaces */ +#define LSCK_IF_LOOPBACK 0 /* Loopback device */ +#define LSCK_IF_WSOCK 1 /* Via WSOCK.VXD */ +/* As yet unimplemented */ +#define LSCK_IF_WSOCK2 2 /* Via WSOCK2.VXD */ +#define LSCK_IF_PKTDRV 3 /* Via packet driver */ +#define LSCK_IF_TCPABI 4 /* Via TCP Applications Binary Int. */ +/* End unimplemented */ +#define LSCK_IF_CSOCK 5 /* Via SOCK.VXD from Coda project */ +#define LSCK_IF_UNIX 6 /* Unix domain sockets via mailslots */ +#define LSCK_IF_WATT32 7 /* Watt-32 ported to libsocket */ + +#define LSCK_MIN_IF LSCK_IF_LOOPBACK +#define LSCK_MAX_IF LSCK_IF_WATT32 + +/* Flag constants for LSCK_SOCKET struct */ +#define LSCK_FLAG_BLOCKING 1 + +/* Socket address constants */ +#define __SOCKADDR_COMMON_SIZE sizeof(struct sockaddr) +#define __SOCKADDR_MAX_SIZE sizeof(struct sockaddr_un) +#define __SOCKADDR_PAD_SIZE (__SOCKADDR_MAX_SIZE - __SOCKADDR_COMMON_SIZE) + +/* --- Structures --- */ + +/* - Socket descriptor */ +typedef struct _LSCK_SOCKET { + /* Basic information */ + int fd; /* File descriptor */ + int family; /* Address family / domain */ + int type; /* SOCK_* type */ + int protocol; /* Protocol to use */ + + int _errno; /* Error status, to support SO_ERROR. */ + + /* Address information */ + /* NB: These need to be padded because the pad should be adjacent to + * the sockaddr structure for Unix domain sockets. */ + + /* Socket local name */ + struct sockaddr sockname; + char pad1[__SOCKADDR_PAD_SIZE]; + size_t socknamelen; + + /* Socket peer name */ + struct sockaddr peername; + char pad2[__SOCKADDR_PAD_SIZE]; + size_t peernamelen; + + /* Status information */ + unsigned char bound:1; /* Socket has been bound */ + unsigned char accepted:1; /* Socket has been accepted */ + unsigned char connected:1; /* Socket has been connected */ + unsigned char connecting:1; /* Non-blocking connect()? */ + unsigned char blocking:1; /* Socket does blocking I/O */ + unsigned char outbound:1; /* Socket outbound allowed */ + unsigned char inbound:1; /* Socket inbound allowed */ + unsigned char listening:1; /* Socket is listening */ + int backlog; /* listen() backlog */ + int send_timeout; /* send() timeout */ + int recv_timeout; /* recv() timeout */ + int urgent_pid; /* Send SIGURG to this pid */ + + /* Interface information */ + struct _LSCK_IF *interface; /* Interface info table */ + void *idata; /* Interface data */ +} LSCK_SOCKET; + +/* Interface address list constants */ +#define LSCK_IF_ADDR_INET_DNS_MAX 4 /* 4 is probably enough */ +#define LSCK_IF_ADDR_INET_HW_ADDRLEN_MAX 16 + +/* Interface descriptor */ +typedef struct _LSCK_IF_ADDR_INET { + struct in_addr addr; + struct in_addr netmask; + int gw_present; + struct in_addr gw; + struct in_addr dns[LSCK_IF_ADDR_INET_DNS_MAX]; + unsigned char fixed:1; + unsigned char hw_type:4; + unsigned char pad:3; + unsigned char hw_addr[LSCK_IF_ADDR_INET_HW_ADDRLEN_MAX]; + int hw_addrlen; + char hostname[MAXGETHOSTNAME]; + char domainname[MAXGETDOMAINNAME]; +} LSCK_IF_ADDR_INET; + +/* Hardware types */ +#define LSCK_IF_HW_TYPE_NONE 0 /* Loopback, virtual devices */ +#define LSCK_IF_HW_TYPE_VIRTUAL LSCK_IF_HW_TYPE_NONE +#define LSCK_IF_HW_TYPE_ETHERNET 1 /* Ethernet */ +#define LSCK_IF_HW_TYPE_DIALUP 2 /* PPP, etc. */ + +/* Hardware address lengths */ +#define LSCK_IF_HW_ADDRLEN_ETHERNET 6 + +/* Actual table includes space for NULL */ +#define LSCK_IF_ADDR_TABLE_MAX 16 + +typedef struct _LSCK_IF_ADDR { + int family; /* One of the AF_* constants */ + + union { + LSCK_IF_ADDR_INET *inet[LSCK_IF_ADDR_TABLE_MAX + 1]; + } table; +} LSCK_IF_ADDR_TABLE; + +typedef struct _LSCK_IF_ROUTE_INET { + struct in_addr netaddr; + struct in_addr netmask; + struct in_addr gw; + struct in_addr addr; + int metric; +} LSCK_IF_ROUTE_INET; + +/* Actual table includes space for NULL */ +#define LSCK_IF_ROUTE_TABLE_MAX 64 + +typedef struct _LSCK_IF_ROUTE { + union { + LSCK_IF_ROUTE_INET *inet[LSCK_IF_ROUTE_TABLE_MAX + 1]; + } table; +} LSCK_IF_ROUTE_TABLE; + +/* Interface flags */ +#define IF_FLAG_HAS_NONBLOCKING 0x0001 /* Can perform non-blocking ops */ +#define IF_FLAG_HAS_MSG_PEEK 0x0002 /* Can recv() with MSG_PEEK */ +#define IF_FLAG_HAS_MSG_WAITALL 0x0004 /* Can recv() with MSG_WAITALL */ + +typedef struct _LSCK_IF { + /* Interface information */ + char *name; /* Interface name */ + int flags; /* Capabilities */ + LSCK_IF_ADDR_TABLE *addr; /* Address information */ + LSCK_IF_ROUTE_TABLE *route; /* Routing information */ + + /* Interface management functions */ + int (*preinit) (void); + struct _LSCK_IF * (*init) (void); + int (*preuninit) (void); + int (*uninit) (void); + + /* General functions */ + int (*socket) (LSCK_SOCKET * /* lsd */); + int (*socketpair) (LSCK_SOCKET * /* lsd */ [2]); + int (*close) (LSCK_SOCKET * /* lsd */); + + int (*proto_check) (int /* domain */, + int /* type */, + int /* protocol */); + + int (*addrlen_check) (LSCK_SOCKET * /* lsd */, size_t /* addrlen */); + /* TODO: route_check */ + + int (*bind) (LSCK_SOCKET * /* lsd */, + struct sockaddr * /* addr */, + size_t /* addrlen */); + + int (*listen) (LSCK_SOCKET * /* lsd */, int /* backlog */); + + int (*accept) (LSCK_SOCKET * /* lsd */, + LSCK_SOCKET * /* nsd */, + struct sockaddr * /* addr */, + size_t * /* addrlen */); + + int (*connect) (LSCK_SOCKET * /* lsd */, + struct sockaddr * /* addr */, + size_t /* addrlen */); + + ssize_t (*recv) (LSCK_SOCKET * /* lsd */, + void * /* buf */, + size_t /* len */, + unsigned int /* flags */); + + ssize_t (*recvfrom) (LSCK_SOCKET * /* lsd */, + void * /* buf */, + size_t /* len */, + unsigned int /* flags */, + struct sockaddr * /* from */, + size_t * /* fromlen */); + + ssize_t (*send) (LSCK_SOCKET * /* lsd */, + const void * /* buf */, + size_t /* len */, + unsigned int /* flags */); + + ssize_t (*sendto) (LSCK_SOCKET * /* lsd */, + const void * /* buf */, + size_t /* len */, + unsigned int /* flags */, + struct sockaddr * /* to */, + size_t /* tolen */); + + int (*getsockname) (LSCK_SOCKET * /* lsd */, + struct sockaddr * /* name */, + size_t * /* namelen */); + + int (*getpeername) (LSCK_SOCKET * /* lsd */, + struct sockaddr * /* name */, + size_t * /* namelen */); + + int (*getsockopt) (LSCK_SOCKET * /* lsd */, + int * /* rv */, + int /* level */, + int /* optname */, + void * /* optval */, + size_t * /* optlen */); + + int (*setsockopt) (LSCK_SOCKET * /* lsd */, + int * /* rv */, + int /* level */, + int /* optname */, + const void * /* optval */, + size_t /* optlen */); + + int (*shutdown) (LSCK_SOCKET * /* lsd */, int /* how */); + + /* I/O control functions */ + int (*fcntl) (LSCK_SOCKET * /* lsd */, + int * /* rv */, + int /* command */, + int /* request */); + + int (*ioctl) (LSCK_SOCKET * /* lsd */, + int * /* rv */, + int /* request */, + int * /* param */); + + int (*select) (LSCK_SOCKET * /* lsd */, int /* event */); + int (*nonblocking_check) (LSCK_SOCKET * /* lsd */); + int (*sockatmark) (LSCK_SOCKET * /* lsd */); +} LSCK_IF; + +/* --- Functions --- */ + +extern LSCK_SOCKET *__fd_to_lsd (int /* fd */); + +extern LSCK_IF_ADDR_INET *__lsck_if_addr_inet_loopback (void); +extern LSCK_IF_ADDR_INET *__lsck_if_addr_inet_getconfig (const char * /* section */); + +/* --- Global variables --- */ + +/* Socket descriptors */ +#ifndef __LSCK_NUM_SOCKET +#define __LSCK_NUM_SOCKET 256 +#endif + +/* Interface information */ +extern LSCK_IF __wsock_interface; +extern LSCK_IF __csock_interface; +extern LSCK_IF __unix_interface; + +#ifdef __cplusplus +} +#endif + +#endif /* __libsocket_if_h__ */ diff --git a/include/lsck/ini.h b/include/lsck/ini.h new file mode 100644 index 00000000..52d76ec5 --- /dev/null +++ b/include/lsck/ini.h @@ -0,0 +1,50 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + ini.h - Windows .INI file functions + Written by Richard Dawe +*/ + +#ifndef __libsocket_ini_h__ +#define __libsocket_ini_h__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern int GetPrivateProfileString (const char * /* appname */, + const char * /* keyname */, + const char * /* deflt */, + char * /* dest */, + size_t /* destsize */, + char * /* filename */); + +#ifdef __cplusplus +} +#endif + +#endif /* __libsocket_ini_h__ */ diff --git a/include/lsck/lsck.h b/include/lsck/lsck.h new file mode 100644 index 00000000..9e510cfe --- /dev/null +++ b/include/lsck/lsck.h @@ -0,0 +1,89 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + lsck.h + General include file for libsocket +*/ + +#ifndef __libsocket_lsck_h__ +#define __libsocket_lsck_h__ + +/* --- Stuff from the old "basket" file, ws.h --- */ + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* --- Functions --- */ + +/* Start-up & shutdown */ +extern int __lsck_init (void); +extern void __lsck_uninit (void); + +/* Configuration */ +extern char *__lsck_config_getdir (void); +extern char *__lsck_config_setdir (char * /* newdir */); +extern char *__lsck_config_getfile (void); +extern char *__lsck_config_setfile (char * /* newfile */); + +/* DNS address(es) */ +extern char * __lsck_getdnsaddr (void); +extern char ** __lsck_getdnsaddrs (void); + +/* Error fudging */ +/* These are now obsolete. */ +/*extern void lsck_perror (char *s); +extern char *lsck_strerror (int errnum);*/ + +/* Just define macros instead. */ +#define lsck_perror perror +#define lsck_strerror strerror + +/* File descriptor tests */ +extern int __fd_is_socket (int /* fd */); +extern int __fd_is_valid (int /* fd */); + +/* Debugging */ +#define LSCK_DEBUG_OFF 0 +#define LSCK_DEBUG_ON LSCK_DEBUG_NORMAL +#define LSCK_DEBUG_NORMAL 1 +#define LSCK_DEBUG_VERBOSE 2 + +extern void __lsck_debug_setlevel (int /* level */); +extern int __lsck_debug_getlevel (void); +extern void __lsck_debug_enable (void); +extern void __lsck_debug_disable (void); +extern int __lsck_debug_enabled (void); + +#ifdef __cplusplus +} +#endif + +#endif /* __libsocket_lsck_h__ */ diff --git a/include/lsck/registry.h b/include/lsck/registry.h new file mode 100644 index 00000000..4db584af --- /dev/null +++ b/include/lsck/registry.h @@ -0,0 +1,140 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + registry.h + Created by Richard Dawe for libsocket. + + RegDos Group's registry access functions. +*/ + +#ifndef __REGDOS_H +#define __REGDOS_H + +#ifndef __libsocket_registry_h__ +#define __libsocket_registry_h__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* --- Types --- */ +#define CONST const + +typedef long DWORD; +typedef long * LPDWORD; +typedef long * LPLONG; + +typedef char BYTE; +typedef char * LPBYTE; +typedef char * LPSTR; +typedef const char * LPCSTR; + +typedef long HKEY; +typedef HKEY * PHKEY; + +/* --- Defines --- */ + +#ifndef ERROR_SUCCESS +#define ERROR_SUCCESS 0L +#endif + +#ifndef ERROR_MORE_DATA +#define ERROR_MORE_DATA 234L +#endif + +#ifndef ERROR_NO_MORE_ITEMS +#define ERROR_NO_MORE_ITEMS 259L +#endif + +#ifndef ERROR_CANTREAD +#define ERROR_CANTREAD 1012L +#endif + +#define __HKEY_CLASSES_ROOT ((HKEY)0x80000000) +#define __HKEY_CURRENT_USER ((HKEY)0x80000001) +#define __HKEY_LOCAL_MACHINE ((HKEY)0x80000002) +#define __HKEY_USERS ((HKEY)0x80000003) +#define __HKEY_PERFORMANCE_DATA ((HKEY)0x80000004) +#define __HKEY_CURRENT_CONFIG ((HKEY)0x80000005) + +#define HKEY_CLASSES_ROOT __HKEY_CLASSES_ROOT +#define HKEY_CURRENT_USER __HKEY_CURRENT_USER +#define HKEY_LOCAL_MACHINE __HKEY_LOCAL_MACHINE +#define HKEY_USERS __HKEY_USERS +#define HKEY_PERFORMANCE_DATA __HKEY_PERFORMANCE_DATA +#define HKEY_CURRENT_CONFIG __HKEY_CURRENT_CONFIG + +/* Reg types */ +#define REG_NONE (0) +#define REG_SZ (1) /* Unicode */ +#define REG_EXPAND_SZ (2) /* " " but with environment + variable expansion */ +#define REG_BINARY (3) /* Binary */ +#define REG_DWORD (4) /* 32 bit number */ +#define REG_DWORD_LITTLE_ENDIAN (4) +#define REG_DWORD_BIG_ENDIAN (5) /* 32-bit number, big end */ + +extern long __RegOpenKey (HKEY, LPCSTR, HKEY *); + +extern long __RegCreateKey (HKEY, LPCSTR, HKEY *); + +extern long __RegCloseKey (HKEY); + +extern long __RegDeleteKey (HKEY, LPCSTR); + +extern long __RegDeleteValue (HKEY, LPCSTR); + +extern long __RegQueryValue (HKEY, LPCSTR, LPSTR, LPLONG); + +extern long __RegQueryValueEx (HKEY, LPCSTR, LPDWORD, LPDWORD, LPBYTE, + LPDWORD); + +extern long __RegEnumKey(HKEY, DWORD, LPSTR, DWORD); + +extern long __RegEnumValue(HKEY, DWORD, LPSTR, LPDWORD, LPDWORD, LPDWORD, + LPBYTE, LPDWORD); + +extern long __RegSetValueEx(HKEY, LPCSTR, DWORD, DWORD, LPBYTE, DWORD); + +#define RegOpenKey __RegOpenKey +#define RegCreateKey __RegCreateKey +#define RegCloseKey __RegCloseKey +#define RegDeleteKey __RegDeleteKey +#define RegDeleteValue __RegDeleteValue +#define RegQueryValue __RegQueryValue +#define RegQueryValueEx __RegQueryValueEx +#define RegEnumKey __RegEnumKey +#define RegEnumValue __RegEnumValue +#define RegSetValueEx __RegSetValueEx + +#ifdef __cplusplus +} +#endif + +#endif /* __libsocket_registry_h__ */ + +#endif /* __REGDOS_H */ diff --git a/include/lsck/vxd.h b/include/lsck/vxd.h new file mode 100644 index 00000000..ceb27015 --- /dev/null +++ b/include/lsck/vxd.h @@ -0,0 +1,47 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __libsocket_vxd_h__ +#define __libsocket_vxd_h__ + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* RD: Moved from vxdldr.h */ +extern int VxdLdrLoadDevice (char * /* Device */); +extern int VxdLdrUnLoadDevice (char * /* Device */); + +LONG32 VxdGetEntry(ULONG32 id); + +#ifdef __cplusplus +} +#endif + +#endif /* __libsocket_vxd_h__ */ diff --git a/include/lsck/win3x.h b/include/lsck/win3x.h new file mode 100644 index 00000000..869c3cc1 --- /dev/null +++ b/include/lsck/win3x.h @@ -0,0 +1,69 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + win3x.h - Windows 3.x functions + Written by Richard Dawe +*/ + +#ifndef __libsocket_win3x_h__ +#define __libsocket_win3x_h__ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern LSCK_IF_ADDR_TABLE * __win3x_getaddrtable (void); + +extern char * __win3x_systemini_gethostname (void); +extern char * __win3x_systemini_getdomainname (void); +extern char ** __win3x_systemini_getdnsaddrs (void); +extern char ** __win3x_systemini_getinterfaces (void); + +extern int __win3x_systemini_getinterfaceaddr (char * /* interface */, + char * /* keyname */, + struct in_addr * /* addr */); + +extern int __win3x_systemini_getipaddr (char * /* interface */, + struct in_addr * /* addr */); + +extern int __win3x_systemini_getnetmask (char * /* interface */, + struct in_addr * /* addr */); + +extern int __win3x_systemini_getgwaddr (char * /* interface */, + struct in_addr * /* addr */); + +extern int __win3x_systemini_getdnsaddr (char * /* interface */, + int /* n */, + struct in_addr * /* addr */); + +#ifdef __cplusplus +} +#endif + +#endif /* __libsocket_win3x_h__ */ diff --git a/include/lsck/win9x.h b/include/lsck/win9x.h new file mode 100644 index 00000000..22d54bc0 --- /dev/null +++ b/include/lsck/win9x.h @@ -0,0 +1,116 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright (C) 1997, 1998 by Indrek Mandre + * Copyright (C) 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __libsocket_win9x_h__ +#define __libsocket_win9x_h__ + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* --- Main --- */ + +extern LSCK_IF_ADDR_TABLE *__win9x_getaddrtable (void); + +/* --- DHCP --- */ + +/* - Defines - */ + +/* DHCP vendor extensions - see RFC 2132. */ +#define DHCP_OPT_PAD 0x00 +#define DHCP_OPT_SUBNET 0x01 +#define DHCP_OPT_ROUTER 0x03 +#define DHCP_OPT_NAME_SERVER 0x05 /* IEN name server */ +#define DHCP_OPT_DNS 0x06 /* Domain name server */ +#define DHCP_OPT_HOST_NAME 0x0C +#define DHCP_OPT_DOMAIN_NAME 0x0F +#define DHCP_OPT_BROADCAST_ADDRESS 0x1C +#define DHCP_OPT_END 0xFF +/* - Functions - */ +extern char * __win9x_dhcp_getkeyvalue (int /* n */, + char * /* valuename */, + int * /* valuesize */); + +extern int __win9x_dhcp_getkeyaddr (int /* n */, + char * /* valuename */, + struct in_addr * /* addr */); + +extern int __win9x_dhcp_getoptaddrs (int /* opt */, + int /* n */, + struct in_addr * /* ip */, + int /* ip_max */); + +extern int __win9x_dhcp_getipaddr (int /* n */, struct in_addr * /* addr */); + +extern int __win9x_dhcp_getnetmask (int /* n */, struct in_addr * /* addr */); + +extern int __win9x_dhcp_getgwaddr (int /* n */, struct in_addr * /* addr */); + +extern int __win9x_dhcp_getdnsaddrs (int /* n */, + struct in_addr * /* dns */, + int /* dns_max */); + +extern int __win9x_dhcp_gethwaddr (int /* n */, + char * /* hw_addr */, + int * /* hw_addrlen */); + +extern int __win9x_dhcp_gethostname (int /* n */, + char * /* buffer */, + int * /* bufferlen */); + +extern int __win9x_dhcp_getdomainname (int /* n */, + char * /* buffer */, + int * /* bufferlen */); + +/* --- MSTCP --- */ +extern int __win9x_mstcp_dnsenabled (void); +extern char ** __win9x_mstcp_getdnsaddrs (void); +extern char * __win9x_mstcp_gethostname (void); +extern char * __win9x_mstcp_getdomainname (void); + +/* --- RAS = Remote Access Service --- */ + +typedef struct _RAS_DATA { + int ip_fixed; /* Local IP addr. fixed? 1 = yep, 0 = nope */ + struct in_addr ip_machine; /* Machine's IP address */ + int ip_dns_specified; /* DNS IP addr. spec'd? 1 = yep, 0 = nope */ + int ip_dns_count; /* No. DNS IP addr. spec'd */ + struct in_addr ip_dns[2]; /* DNS IP addresses */ +} RAS_DATA; + +extern int __win9x_ras_active (void); +extern char *__win9x_ras_getdefaultphonebook (void); +extern int __win9x_ras_getdata (RAS_DATA * /* ras_data */); +extern char **__win9x_ras_getdnsaddrs (void); + +#ifdef __cplusplus +} +#endif + +#endif /* __libsocket_win9x_h__ */ diff --git a/include/lsck/windows.h b/include/lsck/windows.h new file mode 100644 index 00000000..2efcd5de --- /dev/null +++ b/include/lsck/windows.h @@ -0,0 +1,53 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __libsocket_windows_h__ +#define __libsocket_windows_h__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* - Defines - */ + +/* Windows version information */ +enum { + WIN_NONE = 0, + WIN_311 = 1, + WIN_95 = 2, + WIN_98 = 3, + WIN_NT = 4 +}; + +/* - Functions - */ + +extern int __get_windows_version (void); + +#ifdef __cplusplus +} +#endif + +#endif /* __libsocket_windows_h__ */ diff --git a/include/net/if.h b/include/net/if.h new file mode 100644 index 00000000..b4fbc579 --- /dev/null +++ b/include/net/if.h @@ -0,0 +1,197 @@ +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* + This file is part of libsocket, and was taken from an installation of + RedHat Linux 5.1 GPL. Modifications have been made by Richard Dawe + for incorporation into libsocket. These are indicated by comments beginning + 'RD:'. +*/ + +#ifndef _NET_IF_H + +#define _NET_IF_H 1 +/*#include */ /* RD: Don't need this. */ + +#include +#include + +#include /* RD: Typedefs needed! */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Standard interface flags. */ +enum + { + IFF_UP = 0x1, /* Interface is up. */ +#define IFF_UP IFF_UP + IFF_BROADCAST = 0x2, /* Broadcast address valid. */ +#define IFF_BROADCAST IFF_BROADCAST + IFF_DEBUG = 0x4, /* Turn on debugging. */ +#define IFF_DEBUG IFF_DEBUG + IFF_LOOPBACK = 0x8, /* Is a loopback net. */ +#define IFF_LOOPBACK IFF_LOOPBACK + IFF_POINTOPOINT = 0x10, /* Interface is point-to-point link. */ +#define IFF_POINTOPOINT IFF_POINTOPOINT + IFF_NOTRAILERS = 0x20, /* Avoid use of trailers. */ +#define IFF_NOTRAILERS IFF_NOTRAILERS + IFF_RUNNING = 0x40, /* Resources allocated. */ +#define IFF_RUNNING IFF_RUNNING + IFF_NOARP = 0x80, /* No address resolution protocol. */ +#define IFF_NOARP IFF_NOARP + IFF_PROMISC = 0x100, /* Receive all packets. */ +#define IFF_PROMISC IFF_PROMISC + + /* Not supported */ + IFF_ALLMULTI = 0x200, /* Receive all multicast packets. */ +#define IFF_ALLMULTI IFF_ALLMULTI + + IFF_MASTER = 0x400, /* Master of a load balancer. */ +#define IFF_MASTER IFF_MASTER + IFF_SLAVE = 0x800, /* Slave of a load balancer. */ +#define IFF_SLAVE IFF_SLAVE + + IFF_MULTICAST = 0x1000, /* Supports multicast. */ +#define IFF_MULTICAST IFF_MULTICAST + + IFF_PORTSEL = 0x2000, /* Can set media type. */ +#define IFF_PORTSEL IFF_PORTSEL + IFF_AUTOMEDIA = 0x4000 /* Auto media select active. */ +#define IFF_AUTOMEDIA IFF_AUTOMEDIA + }; + +/* The ifaddr structure contains information about one address of an + interface. They are maintained by the different address families, + are allocated and attached when an address is set, and are linked + together so all addresses for an interface can be located. */ + +struct ifaddr + { + struct sockaddr ifa_addr; /* Address of interface. */ + union + { + struct sockaddr ifu_broadaddr; + struct sockaddr ifu_dstaddr; + } ifa_ifu; + struct iface *ifa_ifp; /* Back-pointer to interface. */ + struct ifaddr *ifa_next; /* Next address for interface. */ + }; + +#define ifa_broadaddr ifa_ifu.ifu_broadaddr /* broadcast address */ +#define ifa_dstaddr ifa_ifu.ifu_dstaddr /* other end of link */ + +/* Device mapping structure. I'd just gone off and designed a + beautiful scheme using only loadable modules with arguments for + driver options and along come the PCMCIA people 8) + + Ah well. The get() side of this is good for WDSETUP, and it'll be + handy for debugging things. The set side is fine for now and being + very small might be worth keeping for clean configuration. */ + +struct ifmap + { + unsigned long int mem_start; + unsigned long int mem_end; + unsigned short int base_addr; + unsigned char irq; + unsigned char dma; + unsigned char port; + /* 3 bytes spare */ + }; + +/* 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 IFHWADDRLEN 6 +#define IFNAMSIZ 16 +/* RD: Add this for compatibility */ +#define IFNAMESIZE IFNAMSIZ + union + { + char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "en0". */ + } ifr_ifrn; + + union + { + struct sockaddr ifru_addr; + struct sockaddr ifru_dstaddr; + struct sockaddr ifru_broadaddr; + struct sockaddr ifru_netmask; + struct sockaddr ifru_hwaddr; + short int ifru_flags; + int ifru_ivalue; + int ifru_mtu; + struct ifmap ifru_map; + char ifru_slave[IFNAMSIZ]; /* Just fits the size */ + __caddr_t ifru_data; + } ifr_ifru; + }; + +#define ifr_name ifr_ifrn.ifrn_name /* interface name */ +#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ +#define ifr_addr ifr_ifru.ifru_addr /* address */ +#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */ +#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ +#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */ +#define ifr_flags ifr_ifru.ifru_flags /* flags */ +#define ifr_metric ifr_ifru.ifru_ivalue /* metric */ +#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ +#define ifr_map ifr_ifru.ifru_map /* device map */ +#define ifr_slave ifr_ifru.ifru_slave /* slave device */ +#define ifr_data ifr_ifru.ifru_data /* for use by interface */ +#define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */ + + +/* 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 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. */ + +/* Unix98 declarations */ +struct if_nameindex { + unsigned int if_index; + char *if_name; +}; + +extern unsigned int if_nametoindex (const char *); +extern char *if_indextoname (unsigned int, char *); +extern struct if_nameindex *if_nameindex (void); +extern void if_freenameindex (struct if_nameindex *); + +#ifdef __cplusplus +} +#endif + +#endif /* net/if.h */ diff --git a/include/netdb.h b/include/netdb.h new file mode 100644 index 00000000..119aad2c --- /dev/null +++ b/include/netdb.h @@ -0,0 +1,193 @@ +/*- + * Copyright (c) 1980, 1983, 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. + * + * @(#)netdb.h 8.1 (Berkeley) 6/2/93 + * netdb.h,v 1.1.1.1 1995/02/18 05:34:07 hjl Exp + * - + * 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-- + */ + +/* + Richard Dawe (for libsocket): Temporarily commented out RPC functions as + they are not currently implemented. Also added inet_nsap_*() functions, + not that I know the function of them. Also made functions externs. +*/ + +#ifndef _NETDB_H_ +#define _NETDB_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* RD: Unix98 says we should define these. */ +/* Fundamental Internet types */ +#ifndef __libsocket_in_port_t +typedef unsigned short in_port_t; +#define __libsocket_in_port_t +#endif /* __libsocket_in_port_t */ + +#ifndef __libsocket_in_addr_t +typedef unsigned long in_addr_t; +#define __libsocket_in_addr_t +#endif /* __libsocket_in_addr_t */ + +/* + * Structures returned by network data base library. All addresses are + * supplied in host order, and returned in network order (suitable for + * use in system calls). + */ + + /* Different from the linux versions - note the shorts.. */ +struct hostent { + const char *h_name; /* official name of host */ + char **h_aliases; /* alias list */ + short h_addrtype; /* host address type */ + short h_length; /* length of address */ + char **h_addr_list; /* list of addresses from name server */ +#define h_addr h_addr_list[0] /* address, for backward compatiblity */ +}; + +/* + * Assumption here is that a network number + * fits in an unsigned long -- probably a poor one. + */ + +struct netent { + char *n_name; /* official name of net */ + char **n_aliases; /* alias list */ + short n_addrtype; /* net address type */ + unsigned long n_net; /* network # */ +}; + +struct servent { + char *s_name; /* official service name */ + char **s_aliases; /* alias list */ + short s_port; /* port # */ + char *s_proto; /* protocol to use */ +}; + +struct protoent +{ + char *p_name; /* official protocol name */ + char **p_aliases; /* alias list */ + short p_proto; /* protocol # */ +}; + +struct addrinfo { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + socklen_t ai_addrlen; + struct sockaddr *ai_addr; + char *ai_canonname; + struct addrinfo *ai_next; +}; + +/*struct rpcent { + char *r_name; *//* name of server for this rpc program */ +/* char **r_aliases; *//* alias list */ +/* int r_number; *//* rpc program number */ +/*};*/ + +/* + * Error return codes from gethostbyname() and gethostbyaddr() + * (left in extern int h_errno). + */ + +extern int h_errno; + +#define NETDB_INTERNAL -1 /* see errno */ +#define NETDB_SUCCESS 0 /* no problem */ +#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 */ +#define NO_ADDRESS NO_DATA /* no address, look for MX record */ + +extern void endhostent (void); +extern void endnetent (void); +extern void endprotoent (void); +extern void endservent (void); +/*extern void endrpcent (void);*/ +extern int getaddrinfo(const char *restrict host, const char *restrict serv, + const struct addrinfo *restrict hint, struct addrinfo **restrict res); +extern void freeaddrinfo(struct addrinfo *res); +extern struct hostent *gethostbyaddr (const char *, int, int); +extern struct hostent *gethostbyname (const char *); +extern struct hostent *gethostent (void); +extern struct netent *getnetbyaddr (u_long, int); /* u_long? */ +extern struct netent *getnetbyname (const char *); +extern struct netent *getnetent (void); +extern struct protoent *getprotobyname (const char *); +extern struct protoent *getprotobynumber (int); +extern struct protoent *getprotoent (void); +extern struct servent *getservbyname (const char *, const char *); +extern struct servent *getservbyport (int, const char *); +extern struct servent *getservent (void); +/*struct rpcent extern *getrpcent (void); +extern struct rpcent *getrpcbyname (const char *); +extern struct rpcent *getrpcbynumber (int);*/ +extern void herror (char *); +extern void sethostent (int); +extern void setnetent (int); +extern void setprotoent (int); +extern void setservent (int); +/*extern void setrpcent (int);*/ + +#ifdef __cplusplus +} +#endif + +#endif /* !_NETDB_H_ */ diff --git a/include/netinet/in.h b/include/netinet/in.h index 943ff201..4e9c6dcf 100644 --- a/include/netinet/in.h +++ b/include/netinet/in.h @@ -1,56 +1,296 @@ -/* Copyright (C) 2012 DJ Delorie, see COPYING.DJ for details */ -/* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */ -/* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */ -/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ -#ifndef __dj_include_netinet_in_h_ -#define __dj_include_netinet_in_h_ + +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * RD: Constructed by comparison with netinet/in.h from Cygwin beta 20.1. + * Made all functions externs. + */ + +#ifndef _NETINET_IN_H +#define _NETINET_IN_H + +#ifndef __libsocket_netinet_in_h__ +#define __libsocket_netinet_in_h__ + +#include #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -#ifndef __dj_ENFORCE_ANSI_FREESTANDING +enum { + IPPROTO_IP = 0, /* Dummy protocol for TCP */ + IPPROTO_ICMP = 1, /* Internet Control Message Protocol */ + IPPROTO_IGMP = 2, /* Internet Gateway Management Protocol */ + IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94) */ + IPPROTO_TCP = 6, /* Transmission Control Protocol */ + IPPROTO_EGP = 8, /* Exterior Gateway Protocol */ + IPPROTO_PUP = 12, /* PUP protocol */ + IPPROTO_UDP = 17, /* User Datagram Protocol */ + IPPROTO_IDP = 22, /* XNS IDP protocol */ + + IPPROTO_RAW = 255, /* Raw IP packets */ + IPPROTO_MAX +}; + +/* Standard well-known ports. */ +enum + { + IPPORT_ECHO = 7, /* Echo service. */ + IPPORT_DISCARD = 9, /* Discard transmissions service. */ + IPPORT_SYSTAT = 11, /* System status service. */ + IPPORT_DAYTIME = 13, /* Time of day service. */ + IPPORT_NETSTAT = 15, /* Network status service. */ + IPPORT_FTP = 21, /* File Transfer Protocol. */ + IPPORT_TELNET = 23, /* Telnet protocol. */ + IPPORT_SMTP = 25, /* Simple Mail Transfer Protocol. */ + IPPORT_TIMESERVER = 37, /* Timeserver service. */ + IPPORT_NAMESERVER = 42, /* Domain Name Service. */ + IPPORT_WHOIS = 43, /* Internet Whois service. */ + IPPORT_MTP = 57, + + IPPORT_TFTP = 69, /* Trivial File Transfer Protocol. */ + IPPORT_RJE = 77, + IPPORT_FINGER = 79, /* Finger service. */ + IPPORT_TTYLINK = 87, + IPPORT_SUPDUP = 95, /* SUPDUP protocol. */ + + + IPPORT_EXECSERVER = 512, /* execd service. */ + IPPORT_LOGINSERVER = 513, /* rlogind service. */ + IPPORT_CMDSERVER = 514, + IPPORT_EFSSERVER = 520, + + /* UDP ports. */ + IPPORT_BIFFUDP = 512, + IPPORT_WHOSERVER = 513, + IPPORT_ROUTESERVER = 520, + + /* Ports less than this value are reserved for privileged processes. */ + IPPORT_RESERVED = 1024, + + /* Ports greater this value are reserved for (non-privileged) servers. */ + IPPORT_USERRESERVED = 5000 + }; + +/* Fundamental Internet types */ +#ifndef __libsocket_in_port_t +typedef unsigned short in_port_t; +#define __libsocket_in_port_t +#endif /* __libsocket_in_port_t */ + +#ifndef __libsocket_in_addr_t +typedef unsigned long in_addr_t; +#define __libsocket_in_addr_t +#endif /* __libsocket_in_addr_t */ + +#ifndef __libsocket_sa_family_t +typedef unsigned short sa_family_t; +#define __libsocket_sa_family_t +#endif /* __libsocket_sa_family_t */ + +/* Internet address. */ +#ifndef __libsocket_in_addr +#define __libsocket_in_addr +struct in_addr { + in_addr_t s_addr; +}; +#endif /* __libsocket_in_addr */ + +/* Structure describing an Internet (IP) socket address. */ +#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */ +struct sockaddr_in { + sa_family_t sin_family; /* Address family */ + in_port_t sin_port; /* Port number */ + struct in_addr sin_addr; /* Internet addr. */ + + /* Pad to size of `struct sockaddr'. */ + unsigned char __pad[__SOCK_SIZE__ + - sizeof(sa_family_t) - + sizeof(in_port_t) + - sizeof(struct in_addr)]; +}; /* RD: Pack it for transmission/usage! */ +#define sin_zero __pad /* for BSD UNIX comp. -FvK */ -#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) \ - || !defined(__STRICT_ANSI__) || defined(__cplusplus) +/* + * Definitions of the bits in an Internet address integer. + * On subnets, host and network parts are found according + * to the subnet mask, not these masks. + */ +#define IN_CLASSA(a) ((((long int) (a)) & 0x80000000) == 0) +#define IN_CLASSA_NET 0xff000000 +#define IN_CLASSA_NSHIFT 24 +#define IN_CLASSA_HOST (0xffffffff & ~IN_CLASSA_NET) +#define IN_CLASSA_MAX 128 -#endif /* (__STDC_VERSION__ >= 199901L) || !__STRICT_ANSI__ */ +#define IN_CLASSB(a) ((((long int) (a)) & 0xc0000000) == 0x80000000) +#define IN_CLASSB_NET 0xffff0000 +#define IN_CLASSB_NSHIFT 16 +#define IN_CLASSB_HOST (0xffffffff & ~IN_CLASSB_NET) +#define IN_CLASSB_MAX 65536 -#ifndef __STRICT_ANSI__ +#define IN_CLASSC(a) ((((long int) (a)) & 0xe0000000) == 0xc0000000) +#define IN_CLASSC_NET 0xffffff00 +#define IN_CLASSC_NSHIFT 8 +#define IN_CLASSC_HOST (0xffffffff & ~IN_CLASSC_NET) -#ifndef _POSIX_SOURCE +#define IN_CLASSD(a) ((((long int) (a)) & 0xf0000000) == 0xe0000000) +#define IN_MULTICAST(a) IN_CLASSD(a) +#define IN_MULTICAST_NET 0xF0000000 -uint32_t htonl(uint32_t _val); -uint32_t ntohl(uint32_t _val); -unsigned short htons(unsigned short _val); -unsigned short ntohs(unsigned short _val); +#define IN_EXPERIMENTAL(a) ((((long int) (a)) & 0xe0000000) == 0xe0000000) +#define IN_BADCLASS(a) ((((long int) (a)) & 0xf0000000) == 0xf0000000) -#endif /* !_POSIX_SOURCE */ -#endif /* !__STRICT_ANSI__ */ -#endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ +/* Address to accept any incoming messages. */ +#define INADDR_ANY ((unsigned long int) 0x00000000) -#ifndef __dj_ENFORCE_FUNCTION_CALLS -#include +/* Address to send to all hosts. */ +#define INADDR_BROADCAST ((unsigned long int) 0xffffffff) -_EXTERN_INLINE uint32_t +/* Address indicating an error return. */ +#define INADDR_NONE 0xffffffff + +/* Network number for local host loopback. */ +#define IN_LOOPBACKNET 127 + +/* Address to loopback in software to local host. */ +#define INADDR_LOOPBACK 0x7f000001 /* 127.0.0.1 */ +#define IN_LOOPBACK(a) ((((long int) (a)) & 0xff000000) == 0x7f000000) + +/* Defines for Multicast INADDR */ +#define INADDR_UNSPEC_GROUP 0xe0000000 /* 224.0.0.0 */ +#define INADDR_ALLHOSTS_GROUP 0xe0000001 /* 224.0.0.1 */ +#define INADDR_MAX_LOCAL_GROUP 0xe00000ff /* 224.0.0.255 */ + +/* + * Structure used to describe IP options. + * Used to store options internally, to pass them to a process, + * or to restore options retrieved earlier. + * The ip_dst is used for the first-hop gateway when using a source route + * (this gets put into the header proper). + */ + +/* Ugly hack for g++ 2.95.x */ + +#if defined(__cplusplus) && defined(__GNUC__) && defined(__GNUC_MINOR__) +#if (__GNUC__ == 2) && (__GNUC_MINOR__ == 95) +#define __libsocket_netinet_in_ugly_hack__ +#endif /* (__GNUC__ == 2) && (__GNUC_MINOR__ == 95) */ +#endif /* __cplusplus && __GNUC__ && __GNUC_MINOR__ */ + +#ifndef __libsocket_netinet_in_ugly_hack__ +struct ip_opts { + struct in_addr ip_dst; /* first hop, 0 w/o src rt */ + char ip_opts[40]; /* actually variable in size */ + }; +#else /* !__libsocket_netinet_in_ugly_hack__ */ +#warning struct ip_opts not defined as work-around for g++ 2.95.x bug +#endif /* __libsocket_netinet_in_ugly_hack__ */ + +#undef __libsocket_netinet_in_ugly_hack__ + +/* + * Options for use with [gs]etsockopt at the IP level. + * First word of comment is data type; bool is stored in int. + */ +#define IP_OPTIONS 1 /* buf/ip_opts; set/get IP options */ +#define IP_HDRINCL 2 /* int; header is included with data */ +#define IP_TOS 3 /* int; IP type of service and preced. */ +#define IP_TTL 4 /* int; IP time to live */ +#define IP_RECVOPTS 5 /* bool; receive all IP opts w/dgram */ +#define IP_RECVRETOPTS 6 /* bool; receive IP opts for response */ +#define IP_RECVDSTADDR 7 /* bool; receive IP dst addr w/dgram */ +#define IP_RETOPTS 8 /* ip_opts; set/get IP options */ +#define IP_MULTICAST_IF 9 /* u_char; set/get IP multicast i/f */ +#define IP_MULTICAST_TTL 10 /* u_char; set/get IP multicast ttl */ +#define IP_MULTICAST_LOOP 11 /* u_char; set/get IP multicast loopback */ +#define IP_ADD_MEMBERSHIP 12 /* ip_mreq; add an IP group membership */ +#define IP_DROP_MEMBERSHIP 13 /* ip_mreq; drop an IP group membership */ +#define IP_MULTICAST_VIF 14 /* set/get IP mcast virt. iface */ +#define IP_RSVP_ON 15 /* enable RSVP in kernel */ +#define IP_RSVP_OFF 16 /* disable RSVP in kernel */ +#define IP_RSVP_VIF_ON 17 /* set RSVP per-vif socket */ +#define IP_RSVP_VIF_OFF 18 /* unset RSVP per-vif socket */ +#define IP_PORTRANGE 19 /* int; range to choose for unspec port */ +#define IP_RECVIF 20 /* bool; receive reception if w/dgram */ + +#define IP_FW_ADD 50 /* add a firewall rule to chain */ +#define IP_FW_DEL 51 /* delete a firewall rule from chain */ +#define IP_FW_FLUSH 52 /* flush firewall rule chain */ +#define IP_FW_ZERO 53 /* clear single/all firewall counter(s) */ +#define IP_FW_GET 54 /* get entire firewall rule chain */ +#define IP_NAT 55 /* set/get NAT opts */ + +/* + * Defaults and limits for options + */ +#define IP_DEFAULT_MULTICAST_TTL 1 /* normally limit m'casts to 1 hop */ +#define IP_DEFAULT_MULTICAST_LOOP 1 /* normally hear sends if a member */ +#define IP_MAX_MEMBERSHIPS 20 /* per socket */ + +/* + * Argument structure for IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP. + */ +struct ip_mreq { + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_interface; /* local IP address of interface */ +}; + +/* + * Argument for IP_PORTRANGE: + * - which range to search when port is unspecified at bind() or connect() + */ +#define IP_PORTRANGE_DEFAULT 0 /* default range */ +#define IP_PORTRANGE_HIGH 1 /* "high" - request firewall bypass */ +#define IP_PORTRANGE_LOW 2 /* "low" - vouchsafe security */ + +/* Constants to help with inet_pton(), inet_ntop(). */ +#define INET_ADDRSTRLEN 16 +#define INET6_ADDRSTRLEN 46 + +/* Bind a socket to a privileged IP port */ +extern int bindresvport (int __sockfd, struct sockaddr_in *sin); + +/* Byte-order conversions */ +#include + +static inline uint32_t htonl(uint32_t _val) { return (_val << 24) | ((_val&0xff00) << 8) | ((_val&0xff0000) >> 8) | (_val >> 24); } #define ntohl(x) htonl(x) -_EXTERN_INLINE unsigned short -htons(unsigned short _val) +static inline uint16_t +htons(uint16_t _val) { return (_val << 8) | (_val >> 8); } #define ntohs(x) htons(x) -#endif /* !__dj_ENFORCE_FUNCTION_CALLS */ - #ifdef __cplusplus } #endif -#endif /* !__dj_include_netinet_in_h_ */ +#endif /* __libsocket_netinet_in_h__ */ + +#endif /* _NETINET_IN_H */ diff --git a/include/resolv.h b/include/resolv.h new file mode 100644 index 00000000..988763ac --- /dev/null +++ b/include/resolv.h @@ -0,0 +1,137 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + resolv.h - resolv include file. + + Created by Richard Dawe, based on the format of the RedHat Linux 5.1 + resolv.h file. Made resolver functions externs. +*/ + +#ifndef __libsocket_resolv_h__ +#define __libsocket_resolv_h__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * 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 trucation 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_DEFAULT (RES_RECURSE | RES_DEFNAMES | RES_DNSRCH) + +/* + * Resolver "pfcode" values. Used by dig. + */ +#define RES_PRF_STATS 0x00000001 +/* 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 */ + +/* hooks are still experimental as of 4.9.2 */ +typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error } + res_sendhookact; + +/* + * 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 */ + +#define MAXHOSTNAMELEN 64 /* max length of hostname */ + +struct __res_state { + int retrans; /* retransmition time interval */ + int retry; /* number of times to retransmit */ + unsigned 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 */ + unsigned short id; /* current packet id */ + char *dnsrch[MAXDNSRCH+1]; /* components of domain to search */ + char defdname[MAXDNAME]; /* default domain */ + unsigned 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; + unsigned long int mask; + } sort_list[MAXRESOLVSORT]; +}; + +extern struct __res_state _res; + +extern int h_errno; + +extern int res_query ( const char *, int, int, unsigned char *, int ); +extern int res_search ( const char *, int, int, unsigned char *, int ); +extern int res_mkquery ( int, const char *, int, int, const unsigned char *, int, const unsigned char *, unsigned char *, int); +extern int res_send ( const unsigned char *, int, unsigned char *, int ); +extern int res_init ( void ); +extern int dn_comp ( const char *, unsigned char *, int, unsigned char **, unsigned char **); +extern int dn_expand ( const unsigned char *, const unsigned char *, const unsigned char *, char *, int ); + +#ifdef __cplusplus +} +#endif + +#endif /* __libsocket_resolv_h__ */ diff --git a/include/sys/fsext.h b/include/sys/fsext.h index 96adecda..f5ba30ee 100644 --- a/include/sys/fsext.h +++ b/include/sys/fsext.h @@ -50,6 +50,9 @@ typedef enum { __FSEXT_fchmod } __FSEXT_Fnumber; +extern int __lsck_socket_fsext (__FSEXT_Fnumber func_number, + int *rv, va_list args); + /* _ready gets passed a fd and should return a mask of these, as if we were emulating "int ready(int fd)" */ #define __FSEXT_ready_read 1 diff --git a/include/sys/socket.h b/include/sys/socket.h new file mode 100644 index 00000000..9a4de883 --- /dev/null +++ b/include/sys/socket.h @@ -0,0 +1,402 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _SYS_SOCKET_H +#define _SYS_SOCKET_H + +#ifndef __libsocket_socket_h__ +#define __libsocket_socket_h__ + +#include + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* --- Constants --- */ + +#define SOCK_STREAM 1 /* stream (connection) socket */ +#define SOCK_DGRAM 2 /* datagram (conn.less) socket */ +#define SOCK_RAW 3 /* raw socket */ +#define SOCK_RDM 4 /* reliably-delivered message */ +#define SOCK_SEQPACKET 5 + +/* Flags we can use with send/ and recv. */ +#define MSG_OOB 0x0001 /* Out-of-band data */ +#define MSG_PEEK 0x0002 /* Leave received data in queue */ +#define MSG_DONTROUTE 0x0004 /* Send without using routing tables */ +#define MSG_CTRUNC 0x0008 /* Support this for BSD/Unix98 oddments */ +/* RD: Where did this come from? */ +#define MSG_PROXY 0x0010 /* Supply or ask second address */ +#define MSG_EOR 0x0020 /* Terminate a record (if proto supports) */ +#define MSG_TRUNC 0x0040 /* Normal data truncated */ +#define MSG_WAITALL 0x0080 /* Wait for complete buffer */ +#define MSG_DONTWAIT 0x0100 /* Perform next operation without blocking */ + +/* + * Maximum queue length specifiable by listen. + */ +#define SOMAXCONN 5 + +#define MSG_MAXIOVLEN 16 +#define MSG_PARTIAL 0x8000 /* partial send or recv for message xport */ + +/* Setsockoptions(2) level. Thanks to BSD these must match IPPROTO_xxx */ +#define SOL_IP 0 +#define SOL_IPX 256 +#define SOL_AX25 257 +#define SOL_ATALK 258 +#define SOL_NETROM 259 +#define SOL_TCP 6 +#define SOL_UDP 17 + +/* Link numbers. */ +#define IMPLINK_IP 155 +#define IMPLINK_LOWEXPER 156 +#define IMPLINK_HIGHEXPER 158 + +/* + * Address families. + */ +#define AF_UNSPEC 0 /* unspecified */ +#define AF_UNIX 1 /* local to host (pipes, portals) */ +#define AF_INET 2 /* internetwork: UDP, TCP, etc. */ +#define AF_IMPLINK 3 /* arpanet imp addresses */ +#define AF_PUP 4 /* pup protocols: e.g. BSP */ +#define AF_CHAOS 5 /* mit CHAOS protocols */ +#define AF_IPX 6 /* IPX and SPX */ +#define AF_NS 6 /* XEROX NS protocols */ +#define AF_ISO 7 /* ISO protocols */ +#define AF_OSI AF_ISO /* OSI is ISO */ +#define AF_ECMA 8 /* european computer manufacturers */ +#define AF_DATAKIT 9 /* datakit protocols */ +#define AF_CCITT 10 /* CCITT protocols, X.25 etc */ +#define AF_SNA 11 /* IBM SNA */ +#define AF_DECnet 12 /* DECnet */ +#define AF_DLI 13 /* Direct data link interface */ +#define AF_LAT 14 /* LAT */ +#define AF_HYLINK 15 /* NSC Hyperchannel */ +#define AF_APPLETALK 16 /* AppleTalk */ +#define AF_NETBIOS 17 /* NetBios-style addresses */ +#define AF_VOICEVIEW 18 /* VoiceView */ +#define AF_FIREFOX 19 /* FireFox */ +#define AF_UNKNOWN1 20 /* Somebody is using this! */ +#define AF_BAN 21 /* Banyan */ + +/* RD: From Winsock 2 headers, we have: */ + +/*#define AF_MAX 22*/ + +#define AF_ATM 22 /* Native ATM Services */ +#define AF_INET6 23 /* Internetwork Ver. 6 (RD: IPv6?) */ + +#define AF_MAX 24 + +/* End RD */ + +/* + * Protocol families, same as address families for now. + */ +#define PF_UNSPEC AF_UNSPEC +#define PF_UNIX AF_UNIX +#define PF_INET AF_INET +#define PF_IMPLINK AF_IMPLINK +#define PF_PUP AF_PUP +#define PF_CHAOS AF_CHAOS +#define PF_NS AF_NS +#define PF_IPX AF_IPX +#define PF_ISO AF_ISO +#define PF_OSI AF_OSI +#define PF_ECMA AF_ECMA +#define PF_DATAKIT AF_DATAKIT +#define PF_CCITT AF_CCITT +#define PF_SNA AF_SNA +#define PF_DECnet AF_DECnet +#define PF_DLI AF_DLI +#define PF_LAT AF_LAT +#define PF_HYLINK AF_HYLINK +#define PF_APPLETALK AF_APPLETALK +#define PF_VOICEVIEW AF_VOICEVIEW +#define PF_FIREFOX AF_FIREFOX +#define PF_UNKNOWN1 AF_UNKNOWN1 +#define PF_BAN AF_BAN + +/* RD: Winsock 2 new ones (see AF_* above) */ + +#define PF_ATM AF_ATM +#define PF_INET6 AF_INET6 + +/* End RD */ + +#define PF_MAX AF_MAX + +/* + * Option flags per-socket. + */ +#define SO_DEBUG 0x0001 /* turn on debugging info recording */ +#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ +#define SO_REUSEADDR 0x0004 /* allow local address reuse */ +#define SO_KEEPALIVE 0x0008 /* keep connections alive */ +#define SO_DONTROUTE 0x0010 /* just use interface addresses */ +#define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */ +#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */ +#define SO_LINGER 0x0080 /* linger on close if data present */ +#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */ + +#define SO_DONTLINGER (u_int)(~SO_LINGER) + +/* + * Additional options. + */ +#define SO_SNDBUF 0x1001 /* send buffer size */ +#define SO_RCVBUF 0x1002 /* receive buffer size */ +#define SO_SNDLOWAT 0x1003 /* send low-water mark */ +#define SO_RCVLOWAT 0x1004 /* receive low-water mark */ +#define SO_SNDTIMEO 0x1005 /* send timeout */ +#define SO_RCVTIMEO 0x1006 /* receive timeout */ +#define SO_ERROR 0x1007 /* get error status and clear */ +#define SO_TYPE 0x1008 /* get socket type */ + +/* + * Options for connect and disconnect data and options. Used only by + * non-TCP/IP transports such as DECNet, OSI TP4, etc. + */ +#define SO_CONNDATA 0x7000 +#define SO_CONNOPT 0x7001 +#define SO_DISCDATA 0x7002 +#define SO_DISCOPT 0x7003 +#define SO_CONNDATALEN 0x7004 +#define SO_CONNOPTLEN 0x7005 +#define SO_DISCDATALEN 0x7006 +#define SO_DISCOPTLEN 0x7007 + +/* + * Option for opening sockets for synchronous access. + */ +#define SO_OPENTYPE 0x7008 + +#define SO_SYNCHRONOUS_ALERT 0x10 +#define SO_SYNCHRONOUS_NONALERT 0x20 + +/* + * Other NT-specific options. + */ +#define SO_MAXDG 0x7009 +#define SO_MAXPATHDG 0x700A +#define SO_UPDATE_ACCEPT_CONTEXT 0x700B +#define SO_CONNECT_TIME 0x700C + +/* + * TCP options. + */ +/*#define TCP_NODELAY 0x0001*/ +#define TCP_BSDURGENT 0x7000 + +#define SOL_SOCKET 0xffff /* options for socket level */ + +/* + * Define constant based on rfc883, used by gethostbyxxxx() calls. + */ +#define MAXGETHOSTSTRUCT 1024 + +/* ioctl() and fcntl() defines. Currently #include doesn't + define the required constants because of an #ifdef. So, define them here. + This may lead to problems later :( */ + +#ifndef O_NDELAY +#define O_NDELAY O_NONBLOCK +#endif + +#ifndef FNDELAY +#define FNDELAY O_NONBLOCK +#endif + +#ifndef _IO + +#define IOCPARM_MASK 0x7f /* parameters must be < 128 bytes */ +#define IOC_VOID 0x20000000 /* no parameters */ +#define IOC_OUT 0x40000000 /* copy out parameters */ +#define IOC_IN 0x80000000 /* copy in parameters */ +#define IOC_INOUT (IOC_IN|IOC_OUT) + /* 0x20000000 distinguishes new & + old ioctl's */ + +#define _IO(x,y) (IOC_VOID|((x)<<8)|(y)) +#define _IOR(x,y,t) (IOC_OUT|((sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) +#define _IOW(x,y,t) (IOC_IN|((sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) + +#endif /* _IO */ + +#ifndef FIONREAD +#define FIONREAD _IOR('f', 127, int) /* get # bytes to read */ +#endif + +#ifndef FIONBIO +#define FIONBIO _IOW('f', 126, int) /* set/clear non-blocking i/o */ +#endif + +#ifndef FIOASYNC +#define FIOASYNC _IOW('f', 125, int) /* set/clear async i/o */ +#endif + +/* Socket I/O Controls */ +#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 flags to be used with the WSAAsyncSelect() call. + */ +/* RD: To use some of these requires Dan Hedlund's callback code IMHO. */ +#define FD_READ 0x01 +#define FD_WRITE 0x02 +#define FD_OOB 0x04 +#define FD_ACCEPT 0x08 +#define FD_CONNECT 0x10 +#define FD_CLOSE 0x20 + +/* how parameter of shutdown */ +#define SHUT_RD 0 +#define SHUT_WR 1 +#define SHUT_RDWR 2 + +/* --- Types --- */ + +#ifndef __libsocket_socklen_t +typedef unsigned long socklen_t; +#define __libsocket_socklen_t +#endif /* __libsocket_socklen_t */ + +#ifndef __libsocket_sa_family_t +typedef unsigned short sa_family_t; +#define __libsocket_sa_family_t +#endif /* __libsocket_sa_family_t */ + +/* - Structures - */ + +struct sockaddr +{ + sa_family_t sa_family; /* address family */ + char sa_data[14]; /* protocol address */ +}; + +struct linger { + unsigned short l_onoff; /* Linger active */ + unsigned short l_linger; /* Linger interval */ +}; + +/* Support for readmsg(), sendmsg(). */ +struct msghdr { + void *msg_name; /* Optional address */ + socklen_t msg_namelen; /* Size of address */ + struct iovec *msg_iov; /* Scatter/gather array */ + int msg_iovlen; /* # of members in msg_iov */ + void *msg_control; /* Ancillary data */ + socklen_t msg_controllen; /* Ancillary data buffer length */ + int flags; /* Flags on received message */ +}; + +/* Ancillary data type */ +struct cmsghdr { + socklen_t cmsg_len; /* Data byte count, including the cmsghdr */ + int cmsg_level; /* Originating protocol */ + int cmsg_type; /* Protocol-specific type */ +}; + +/* TODO: Implement the following: + + . SCM_RIGHTS + . CMSG_DATA + . CMSG_NXTHDR + . CMSG_FIRSTHDR +*/ + +/* --- Functions --- */ + +extern int socket (int, int, int); +extern int socketpair (int, int, int, int [2]); +extern int bind (int, struct sockaddr *, size_t); +extern int listen (int, int); +extern int connect (int, struct sockaddr *, size_t); +extern int accept (int, struct sockaddr *, size_t *); + +extern ssize_t recv (int, void *, size_t, unsigned int); +extern ssize_t recvfrom (int, void *, size_t, unsigned int, + struct sockaddr *, size_t *); +extern ssize_t recvmsg (int, struct msghdr *, int); + +extern ssize_t send (int, const void *, size_t, unsigned int); +extern ssize_t sendto (int, const void *, size_t, unsigned int, + struct sockaddr *, size_t); +extern ssize_t sendmsg (int, const struct msghdr *, int); + +extern int getsockname (int, struct sockaddr *, size_t *); +extern int getpeername (int, struct sockaddr *, size_t *); +extern int getsockopt (int, int, int, void *, size_t *); +extern int setsockopt (int, int, int, const void *, size_t); + +extern int shutdown (int, int); + +extern int rcmd (char **, unsigned short, const char *, + const char *, const char *, int *); +extern int rresvport (int *); +extern int ruserok (const char *, int, const char *, const char *); +extern int rexec (char **, int, const char *, const char *, const char *, + int *); + +extern int sockatmark (int); + +/* Non-standard socket calls */ +extern int closesocket (int); +extern int ioctlsocket (int, int, int *); +extern int fcntlsocket (int, int, int); +extern int selectsocket (int, int); + +/* --- Out-of-place defines, functions, etc. --- */ + +/* - sys/stat.h - */ +extern int isfdtype (int, int); + +#ifndef S_IFSOCK +#define S_IFSOCK 0xC000 +#endif + +#ifndef S_ISSOCK +#define S_ISSOCK(mode) ((mode & 0xF000) == S_IFSOCK) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __libsocket_socket_h__ */ + +#endif /* _SYS_SOCKET_H */ diff --git a/include/sys/un.h b/include/sys/un.h new file mode 100644 index 00000000..772b9094 --- /dev/null +++ b/include/sys/un.h @@ -0,0 +1,45 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _SYS_UN_H +#define _SYS_UN_H + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifndef __libsocket_sa_family_t +typedef unsigned short sa_family_t; +#define __libsocket_sa_family_t +#endif /* __libsocket_sa_family_t */ + +struct sockaddr_un { + sa_family_t sun_family; + u_char sun_path[108]; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_UN_H */ diff --git a/src/libc/pc_hw/endian/htonl.S b/src/libc/pc_hw/endian/htonl.S deleted file mode 100644 index 7860aea9..00000000 --- a/src/libc/pc_hw/endian/htonl.S +++ /dev/null @@ -1,10 +0,0 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ -#include - - FUNC(_htonl) - - movl 4(%esp), %eax - xchgb %ah, %al - rorl $16, %eax - xchgb %ah, %al - RET_I diff --git a/src/libc/pc_hw/endian/htons.S b/src/libc/pc_hw/endian/htons.S deleted file mode 100644 index 376398c7..00000000 --- a/src/libc/pc_hw/endian/htons.S +++ /dev/null @@ -1,8 +0,0 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ -#include - - FUNC(_htons) - - movl 4(%esp), %eax - xchgb %ah, %al - RET_I diff --git a/src/libc/pc_hw/endian/makefile b/src/libc/pc_hw/endian/makefile deleted file mode 100644 index 363b8134..00000000 --- a/src/libc/pc_hw/endian/makefile +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details -TOP=../.. - -AS_SRC += htonl.S -AS_SRC += htons.S -AS_SRC += ntohl.S -AS_SRC += ntohs.S - -include $(TOP)/../makefile.inc diff --git a/src/libc/pc_hw/endian/ntohl.S b/src/libc/pc_hw/endian/ntohl.S deleted file mode 100644 index ed4e0eff..00000000 --- a/src/libc/pc_hw/endian/ntohl.S +++ /dev/null @@ -1,10 +0,0 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ -#include - - FUNC(_ntohl) - - movl 4(%esp), %eax - xchgb %ah, %al - rorl $16, %eax - xchgb %ah, %al - RET_I diff --git a/src/libc/pc_hw/endian/ntohs.S b/src/libc/pc_hw/endian/ntohs.S deleted file mode 100644 index cf663249..00000000 --- a/src/libc/pc_hw/endian/ntohs.S +++ /dev/null @@ -1,8 +0,0 @@ -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ -#include - - FUNC(_ntohs) - - movl 4(%esp), %eax - xchgb %ah, %al - RET_I diff --git a/src/libc/posix/socket/accept.c b/src/libc/posix/socket/accept.c new file mode 100644 index 00000000..e6c42601 --- /dev/null +++ b/src/libc/posix/socket/accept.c @@ -0,0 +1,184 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public Lice2nse as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* This was written by Indrek Mandre, extensively rewritten by Richard Dawe + * (RD). There are suggestions by Alain Magloire (AM), implemented by RD. */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +extern int __lsck_socket_fsext (__FSEXT_Fnumber func_number, + int *rv, va_list args); + +extern LSCK_SOCKET *__lsck_socket[__LSCK_NUM_SOCKET]; + +/* ---------- + * - accept - + * ---------- */ + +int accept (int s, struct sockaddr *addr, size_t *addrlen) +{ + LSCK_SOCKET *lsd; /* Current socket descriptor */ + LSCK_SOCKET *nsd; /* New socket descriptor */ + int newfd; /* New file descriptor */ + int ret; /* Return value */ + int i; /* Loop variable */ + int freelsd; /* Free socket descriptor */ + + /* Find the socket descriptor */ + lsd = __fd_to_lsd (s); + + if (lsd == NULL) { + isfdtype(s, S_IFSOCK); + return (-1); + } + + /* Check for completion of outstanding non-blocking I/O */ + if (lsd->interface->nonblocking_check != NULL) + lsd->interface->nonblocking_check (lsd); + + /* Unsupported socket type */ + if ( (lsd->type != SOCK_STREAM) + || (lsd->interface->accept == NULL)) { + errno = EOPNOTSUPP; + return (-1); + } + + /* Can't accept on sockets that were created via accept(), non-bound + * or non-listening sockets! */ + if (lsd->accepted || !lsd->bound || !lsd->listening) { + errno = EINVAL; + return (-1); + } + + /* Check address parameters */ + if ( (addr == NULL) + || ( (addr != NULL) && (addrlen == NULL) ) ) { + errno = EFAULT; + return(-1); + } + + /* Create a descriptor */ + newfd = __FSEXT_alloc_fd (__lsck_socket_fsext); + + if (newfd < 0) { + errno = ENFILE; + return (-1); + } + setmode (newfd, O_BINARY); + + /* -- Allocate a libsocket socket for the accept'd descriptor -- */ + + /* Find the first free descriptor */ + for (i = 0; + (__lsck_socket[i] != NULL) && (i < __LSCK_NUM_SOCKET); + i++) { + ; + } + + freelsd = -1; + + if ((i == (__LSCK_NUM_SOCKET - 1)) && (__lsck_socket[i] == NULL)) { + /* The last desciptor can be used, but needs special + * checking. */ + freelsd = i; + } else if (i < __LSCK_NUM_SOCKET) { + /* Rest are OK */ + freelsd = i; + } + + /* None free! Free the file descriptor, and return error. */ + if (freelsd < 0) { + __FSEXT_set_function (newfd, NULL); + _close (newfd); + /* Alain Magloire: POSIX says ENFILE instead of EMFILE */ + errno = ENFILE; + return (-1); + } + + nsd = __lsck_socket[freelsd] = malloc (sizeof (LSCK_SOCKET)); + + if (nsd == NULL) { + __FSEXT_set_function (newfd, NULL); + _close (newfd); + errno = ENOBUFS; + return (-1); + } + + /* Set the file descriptor's data to be the socket descriptor. */ + __FSEXT_set_data(newfd, (void *) nsd); + + /* Create a socket with *almost* the same properties */ + memcpy (nsd, lsd, sizeof (LSCK_SOCKET)); + nsd->fd = newfd; + nsd->listening = 0; + + /* Accept on the appropriate interface. */ + nsd->peernamelen = __SOCKADDR_MAX_SIZE; + ret = lsd->interface->accept (lsd, nsd, + &nsd->peername, &nsd->peernamelen); + + if (ret == 0) { + /* Call successful */ + + /* Store peer details, if desired */ + if (addr != NULL) { + /* Unix98 spec says: truncate if addrlen not large + * enough */ + if (*addrlen > nsd->peernamelen) + *addrlen = nsd->peernamelen; + memcpy(addr, &nsd->peername, *addrlen); + } + + /* Now we've accepted, stop any accept calls on the new + * descriptor. */ + /* We've accepted, so we're also connected. */ + nsd->accepted = 1; + nsd->connected = 1; + } else { + /* Call unsuccessful - tidy up */ + __FSEXT_set_data(newfd, NULL); + __FSEXT_set_function (newfd, NULL); + _close (newfd); + free(nsd->idata); + nsd->idata = NULL; + free (nsd); + __lsck_socket[freelsd] = NULL; + } + + return ((ret == -1) ? -1 : nsd->fd); +} diff --git a/src/libc/posix/socket/addr.c b/src/libc/posix/socket/addr.c new file mode 100644 index 00000000..3cce6c20 --- /dev/null +++ b/src/libc/posix/socket/addr.c @@ -0,0 +1,151 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* addr.c - Common interface functions */ + +#include +#include +#include +#include + +#include + +#include +#include +#include + +/* -------------------------------- + * - __lsck_if_addr_inet_loopback - + * -------------------------------- */ + +/* This builds and returns an interface Internet address data structure for + * the loopback device. This is used in win3x/w3x_addr.c and win9x/w9x_addr.c, + * but could be used by any interface. */ + +LSCK_IF_ADDR_INET *__lsck_if_addr_inet_loopback (void) +{ + LSCK_IF_ADDR_INET *lo = NULL; + + lo = (LSCK_IF_ADDR_INET *) malloc (sizeof (LSCK_IF_ADDR_INET)); + if (lo == NULL) + return (NULL); + + bzero (lo, sizeof (LSCK_IF_ADDR_INET)); + lo->addr.s_addr = htonl (INADDR_LOOPBACK); + lo->netmask.s_addr = htonl (IN_CLASSA_NET); + lo->gw_present = 0; + lo->fixed = 1; + lo->hw_type = LSCK_IF_HW_TYPE_VIRTUAL; + + return (lo); +} + +/* --------------------------------- + * - __lsck_if_addr_inet_getconfig - + * --------------------------------- */ + +LSCK_IF_ADDR_INET *__lsck_if_addr_inet_getconfig (const char *section) +{ + LSCK_IF_ADDR_INET *inet = NULL; + char *cfg = NULL; + char addrbuf[16]; /* Dotted-quad with nul */ + char dnskey[16]; + char hostname[MAXGETHOSTNAME]; + char *p = NULL; + int i, ret; + + /* Initialise */ + inet = (LSCK_IF_ADDR_INET *) malloc (sizeof (LSCK_IF_ADDR_INET)); + if (inet == NULL) return (NULL); + bzero (inet, sizeof (LSCK_IF_ADDR_INET)); + + cfg = __lsck_config_getfile(); + if (cfg == NULL) return (NULL); + +#define BAD_IP "0.0.0.0" + + /* IP address */ + GetPrivateProfileString (section, "IPAddress", BAD_IP, + addrbuf, sizeof (addrbuf), cfg); + ret = (strcmp (addrbuf, BAD_IP) == 0); + + if (!ret) + ret = (inet_aton (addrbuf, &inet->addr) == 0); + + if (ret) { + free (inet); + return (NULL); + } + /* Network mask */ + GetPrivateProfileString (section, "IPMask", BAD_IP, + addrbuf, sizeof (addrbuf), cfg); + ret = (strcmp (addrbuf, BAD_IP) == 0); + + if (!ret) + ret = (inet_aton (addrbuf, &inet->netmask) == 0); + + if (ret) { + free (inet); + return (NULL); + } + /* Gateway */ + GetPrivateProfileString (section, "Gateway", BAD_IP, + addrbuf, sizeof (addrbuf), cfg); + if ((strcmp (addrbuf, BAD_IP) != 0) + && (inet_aton (addrbuf, &inet->gw) != 0)) { + inet->gw_present = 1; + } + /* DNS */ + for (i = 0; i < LSCK_IF_ADDR_INET_DNS_MAX; i++) { + sprintf (dnskey, "DNS%iAddress", i + 1); + GetPrivateProfileString (section, dnskey, BAD_IP, + addrbuf, sizeof (addrbuf), cfg); + + if (strcmp (addrbuf, BAD_IP) == 0) + break; + if (inet_aton (addrbuf, &inet->dns[i]) == 0) + break; + } + + /* Hardware */ + inet->hw_type = LSCK_IF_HW_TYPE_ETHERNET; + inet->hw_addrlen = LSCK_IF_HW_ADDRLEN_ETHERNET; + + /* Host and domain name */ + GetPrivateProfileString ("main", "hostname", NULL, + hostname, sizeof (hostname), cfg); + + if (*hostname != '\0') { + p = strchr (hostname, '.'); + if (p != NULL) { + *p = '\0'; + p++; + } + strcpy (inet->hostname, hostname); + strcpy (inet->domainname, p); + } + /* Done */ + return (inet); +} diff --git a/src/libc/posix/socket/bind.c b/src/libc/posix/socket/bind.c new file mode 100644 index 00000000..c2f34d07 --- /dev/null +++ b/src/libc/posix/socket/bind.c @@ -0,0 +1,115 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +#include + +#include +#include + +/* -------- + * - bind - + * -------- */ + +int bind (int s, struct sockaddr *my_addr, size_t addrlen) +{ + /* Cope with long addresses. */ + char buf[__SOCKADDR_MAX_SIZE]; + struct sockaddr *bound_addr = (struct sockaddr *) buf; + size_t bound_addrlen = sizeof(buf); + + LSCK_SOCKET *lsd; + int ret; + + /* Find the socket descriptor */ + lsd = __fd_to_lsd (s); + + if (lsd == NULL) { + isfdtype(s, S_IFSOCK); + return (-1); + } + + /* Check for completion of outstanding non-blocking I/O */ + if (lsd->interface->nonblocking_check != NULL) + lsd->interface->nonblocking_check (lsd); + + /* Already bound? */ + if (lsd->bound) { + errno = EINVAL; + return (-1); + } + + /* No address given? */ + if (my_addr == NULL) { + errno = EFAULT; + return(-1); + } + + /* Trying to bind to a different address family? */ + if (lsd->family != my_addr->sa_family) { + errno = EAFNOSUPPORT; + return(-1); + } + + /* TODO: According to Unix98, this error indicates that the socket is + * listening and cannot be connected. Do something about this! Some + * other error will have to be found, because all socket functions + * return this error if the interface doesn't provide a function. */ + + /* NOTE: We may have to add some routing here if more than two + * interfaces are present. */ + if (lsd->interface->bind == NULL) { + errno = EOPNOTSUPP; + return (-1); + } + /* Bind */ + ret = lsd->interface->bind (lsd, my_addr, addrlen); + + /* Copy the details into socket descriptor, if successful, else + * nuke. */ + if (ret == 0) { + /* Get the local address. */ + + /* TODO: This probably shouldn't ignore the return code. + * However, how can we unbind the socket on error? So for the + * moment, possibly return a bogus address. */ + getsockname(lsd->fd, bound_addr, &bound_addrlen); + + memcpy (&lsd->sockname, (void *) bound_addr, bound_addrlen); + lsd->socknamelen = bound_addrlen; + lsd->bound = 1; + } else { + bzero (&lsd->sockname, sizeof (struct sockaddr)); + + lsd->socknamelen = 0; + lsd->bound = 0; + } + + return (ret); +} diff --git a/src/libc/posix/socket/close.c b/src/libc/posix/socket/close.c new file mode 100644 index 00000000..4827ad70 --- /dev/null +++ b/src/libc/posix/socket/close.c @@ -0,0 +1,83 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Originally by Indrek Mandre (IM), modifications by Richard Dawe (RD) */ + +#include +#include + +#include + +#include +#include + +extern LSCK_SOCKET *__lsck_socket[__LSCK_NUM_SOCKET]; + +/* --------------- + * - closesocket - + * --------------- */ + +int closesocket (int s) +{ + LSCK_SOCKET *lsd; + int ret; + int i; + + /* Find the socket descriptor */ + lsd = __fd_to_lsd (s); + + if (lsd == NULL) { + isfdtype(s, S_IFSOCK); + return (-1); + } + + /* Check for completion of outstanding non-blocking I/O */ + if (lsd->interface->nonblocking_check != NULL) + lsd->interface->nonblocking_check (lsd); + + /* Close */ + if (lsd->interface->close == NULL) { + errno = EOPNOTSUPP; + return (-1); + } + ret = lsd->interface->close (lsd); + + /* Free memory if successful */ + if (ret == 0) { + /* Free the interface data. */ + free(lsd->idata); + lsd->idata = NULL; + + for (i = 0; i < __LSCK_NUM_SOCKET; i++) { + if (lsd == __lsck_socket[i]) { + __lsck_socket[i] = NULL; + free (lsd); + break; + } + } + } + + return (ret); +} diff --git a/src/libc/posix/socket/config.c b/src/libc/posix/socket/config.c new file mode 100644 index 00000000..3d44ddb6 --- /dev/null +++ b/src/libc/posix/socket/config.c @@ -0,0 +1,140 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * config.c - libsocket configuration functions + */ + +#include +#include +#include +#include + +#include + +static char *configdir = NULL; /* Where the configuration files are */ +static int configdirset = 0; /* 1 => configdir has been set, 0 => not */ + +static char *configfile = NULL; +static int configfileset = 0; + +#define LSCK_CONFIG_FILE "lsck.cfg" + +/* ------------------------ + * - __lsck_config_getdir - + * ------------------------ */ + +/* This returns the directory name that libsocket will look in for its config. + * files. */ + +char *__lsck_config_getdir (void) +{ + char *p = NULL; + + /* Have we set configdir already? */ + if (!configdirset) { + /* Try the libsocket environment variable, then the Windows dir, else + * leave NULL */ + configdir = getenv ("LSCK"); + if (configdir == NULL) configdir = getenv ("LIBSOCKET"); + if (configdir == NULL) return(NULL); + + /* Maybe this isn't such a good idea. */ + /*if (configdir == NULL) configdir = getenv("windir"); */ + + /* Done this now */ + configdirset = 1; + } + /* Forward-slashify the directory name */ + for (p = configdir; *p != '\0'; p++) { + if (*p == '\\') + *p = '/'; + } + + return (configdir); +} + +/* ------------------------ + * - __lsck_config_setdir - + * ------------------------ */ + +/* This sets the directory that libsocket looks for configuration files. I + * guess this isn't particularly useful, but it's here for symmetry (spot the + * physicist :) ). The old directory is returned. */ + +char *__lsck_config_setdir (char *newdir) +{ + char *p = NULL, *q = NULL; + + p = configdir; + configdir = strdup (newdir); + for (q = configdir; *q != '\0'; q++) { + if (*q == '\\') + *q = '/'; + } + configdirset = 1; + return (p); /* Return the saved old directory */ +} + +/* ------------------------- + * - __lsck_config_getfile - + * ------------------------- */ + +/* This returns the filename that libsocket should use. If none has been set, + * then the default is used. */ + +char *__lsck_config_getfile (void) +{ + if (!configfileset) { + configfile = malloc (PATH_MAX); + if (configfile == NULL) return (NULL); + + /* Default configuration file */ + if (__lsck_config_getdir() == NULL) return(NULL); + sprintf(configfile, "%s/%s", __lsck_config_getdir(), LSCK_CONFIG_FILE); + configfileset = 1; + } + return (configfile); +} + +/* ------------------------- + * - __lsck_config_setfile - + * ------------------------- */ + +/* This sets the filename that libsocket should use for its configuration + * file. */ + +char *__lsck_config_setfile (char *newfile) +{ + char *p = NULL; + + /* Copy the configuration filename */ + p = configfile; + configfile = newfile; + configfileset = 1; + + /* Return the old pointer */ + return (p); +} diff --git a/src/libc/posix/socket/connct.c b/src/libc/posix/socket/connct.c new file mode 100644 index 00000000..15b05607 --- /dev/null +++ b/src/libc/posix/socket/connct.c @@ -0,0 +1,191 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include + +#include +#include + +#include +#include + +/* ----------- + * - connect - + * ----------- */ + +int connect (int s, struct sockaddr *serv_addr, size_t addrlen) +{ + LSCK_SOCKET *lsd; + int ret; + size_t sock_addrlen; + + /* Find the socket descriptor */ + lsd = __fd_to_lsd (s); + + if (lsd == NULL) { + isfdtype(s, S_IFSOCK); + return (-1); + } + + /* Check for completion of outstanding non-blocking I/O */ + if (lsd->interface->nonblocking_check != NULL) + lsd->interface->nonblocking_check (lsd); + + /* Non-blocking socket connecting? */ + if (!lsd->blocking && lsd->connecting) { + errno = EALREADY; + return (-1); + } + + /* Socket already connected? Datagram sockets can call this + * multiply. */ + /* TODO: What should the behaviour be for other sockets? */ + if (lsd->connected && (lsd->type == SOCK_STREAM)) { + errno = EISCONN; + return (-1); + } + + /* Is the socket listening? */ + if (lsd->listening) { + errno = EOPNOTSUPP; + return(-1); + } + + /* Check the address length is valid. */ + if ((lsd->type == SOCK_STREAM) + || ((lsd->type == SOCK_DGRAM) && (serv_addr != NULL))) { + if ((lsd->interface->addrlen_check == NULL) + || !lsd->interface->addrlen_check(lsd, addrlen)) { + /* Bad address length! */ + errno = EINVAL; + return(-1); + } + } + + /* For datagrams, just store/clear the address and return. */ + if (lsd->type == SOCK_DGRAM) { + if (serv_addr != NULL) { + /* We must be connecting to the same socket address + * family! However, since the socket may not have + * been bound, we must check against the socket's + * family. */ + if (serv_addr->sa_family != lsd->family) { + errno = EAFNOSUPPORT; + return (-1); + } + + memcpy(&lsd->peername, serv_addr, addrlen); + lsd->peernamelen = addrlen; + } else { + bzero(&lsd->peername, __SOCKADDR_MAX_SIZE); + lsd->peernamelen = 0; + } + return(0); + } + + /* - Now strictly handling stream sockets! - */ + + /* Address parameter OK? */ + if (serv_addr == NULL) { + errno = EFAULT; + return(-1); + } + + /* We must be connecting to the same socket address family! However, + * since the socket may not have been bound, we must check against the + * socket's family. */ + if (serv_addr->sa_family != lsd->family) { + errno = EAFNOSUPPORT; + return (-1); + } + + /* TODO: Need to check the interface's routing table for a route. */ + + /* TODO: RD: What was I talking about here? */ + /* NOTE: May have to modify routing code to identify the interface + * here. Currently there are only two, so it doesn't matter. */ + + /* Use the appropriate interface */ + if (lsd->interface->connect == NULL) { + errno = EOPNOTSUPP; + return (-1); + } + ret = lsd->interface->connect (lsd, serv_addr, addrlen); + + /* Store the details on success, else clear the socket descriptor. */ + if ((ret == 0) + || ((ret == -1) && !lsd->blocking && (errno == EWOULDBLOCK))) { + /* Store the peer name */ + memcpy (&lsd->peername, serv_addr, addrlen); + lsd->peernamelen = addrlen; + + /* Now find the socket name. This is performed after the peer + * address has been stored, so that the interface code can use + * the peer address to obtain the socket name (if + * necessary). */ + if ((ret == 0) && (lsd->interface->getsockname != NULL)) { + sock_addrlen = __SOCKADDR_MAX_SIZE; + ret = lsd->interface->getsockname + (lsd, + (struct sockaddr *) &lsd->sockname, + &sock_addrlen); + lsd->socknamelen = sock_addrlen; + + if (ret == -1) { + bzero (&lsd->sockname, + sizeof (struct sockaddr_in)); + /* TODO: Fix this? Let the connect() call + * succeed. */ + ret = 0; + } + } + + if ((ret == -1) && !lsd->blocking && (errno == EWOULDBLOCK)) { + /* Non-blocking connects are OK */ + lsd->connecting = 1; + lsd->connected = 0; + } else { + lsd->connecting = 0; + lsd->connected = 1; + } + } else { + /* Call unsuccessful, so clear details for safety. */ + bzero (&lsd->sockname, sizeof (struct sockaddr)); + bzero (&lsd->peername, sizeof (struct sockaddr)); + + lsd->socknamelen = 0; + lsd->peernamelen = 0; + lsd->connected = 0; + } + + /* Return the correct error if non-blocking connect & still waiting */ + if ((ret == -1) && !lsd->blocking && (errno == EWOULDBLOCK)) { + errno = EINPROGRESS; + return (-1); + } + return (ret); +} diff --git a/src/libc/posix/socket/csock/c_accept.c b/src/libc/posix/socket/csock/c_accept.c new file mode 100644 index 00000000..fb6d6359 --- /dev/null +++ b/src/libc/posix/socket/csock/c_accept.c @@ -0,0 +1,114 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* GNU indent seems to have trouble with this file :( */ +/* *INDENT-OFF* */ + +#include + +#include + +#include +#include +#include "csock.h" + +/* ------------------ + - __csock_accept - + ------------------ */ + +int +__csock_accept (LSCK_SOCKET *lsd, LSCK_SOCKET *nsd, + struct sockaddr *addr, size_t *addrlen) +{ + LSCK_SOCKET_CSOCK *csock = (LSCK_SOCKET_CSOCK *) lsd->idata; + LSCK_SOCKET_CSOCK *ncsock = NULL; + int ret = -1; + unsigned short dest_port = 0; + unsigned int dest_addr = 0; + struct sockaddr_in *addr_sa = (struct sockaddr_in *) addr; + int blocking = lsd->blocking; + int flag = lsd->blocking; + unsigned int i; + int rv; + + /* Check there's enough storage space */ + if (*addrlen < sizeof(struct sockaddr_in)) { + errno = EINVAL; + return(-1); + } + + /* Allocate a buffer for the interface data. */ + ncsock = (LSCK_SOCKET_CSOCK *) malloc(sizeof(*ncsock)); + nsd->idata = (void *) ncsock; + + if (csock == NULL) { + errno = ENOMEM; + return(-1); + } + + /* If the socket is in blocking mode, flip into non-blocking mode. + * to allow interruption with Ctrl+C. lsd->blocking is saved in blocking, + * because the ioctl alters lsd->blocking. */ + if (blocking) { + flag = blocking; + __csock_ioctl(lsd, &rv, FIONBIO, &flag); + } + +tryitagain: + ret = ___csock_accept(csock->fd, &i, &dest_addr, &dest_port); + /* No connection this time, so try again. */ + if (blocking && (ret == -CSOCK_ERR_WOULD_BLOCK)) { + /* Let someone else do something */ + __dpmi_yield(); + goto tryitagain; + } + + /* Got one! */ + if (ret == 0) { + ncsock->fd = i; + } + + /* Switch back to blocking mode, if it was in it originally. */ + if (blocking) { + flag = !blocking; + __csock_ioctl(lsd, &rv, FIONBIO, &flag); + } + + if (ret != 0) { + errno = __csock_errno(ret); + return(-1); + } + + /* Copy the peer address */ + addr_sa->sin_family = AF_INET; + addr_sa->sin_addr.s_addr = dest_addr; + addr_sa->sin_port = dest_port; + *addrlen = sizeof(struct sockaddr_in); + + /* Mark the fd as used */ +// __csock_fd_set_used(ncsock->fd); + + return(0); +} diff --git a/src/libc/posix/socket/csock/c_bind.c b/src/libc/posix/socket/csock/c_bind.c new file mode 100644 index 00000000..de2232df --- /dev/null +++ b/src/libc/posix/socket/csock/c_bind.c @@ -0,0 +1,46 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include "csock.h" + +/* ---------------- + * - __csock_bind - + * ---------------- */ + +int __csock_bind (LSCK_SOCKET * lsd, struct sockaddr *my_addr, size_t addrlen) +{ + LSCK_SOCKET_CSOCK *csock = (LSCK_SOCKET_CSOCK *) lsd->idata; + struct sockaddr_in *my_sa = (struct sockaddr_in *) my_addr; + int ret = 0; + + ret = ___csock_bind(csock->fd, my_sa->sin_addr.s_addr, my_sa->sin_port); + if (ret != 0) { + errno = __csock_errno (ret); + ret = -1; + } + return (ret); +} diff --git a/src/libc/posix/socket/csock/c_close.c b/src/libc/posix/socket/csock/c_close.c new file mode 100644 index 00000000..929c0e46 --- /dev/null +++ b/src/libc/posix/socket/csock/c_close.c @@ -0,0 +1,50 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include +#include +#include "csock.h" + +/* ----------------- + * - __csock_close - + * ----------------- */ + +int __csock_close (LSCK_SOCKET * lsd) +{ + LSCK_SOCKET_CSOCK *csock = (LSCK_SOCKET_CSOCK *) lsd->idata; + int ret = 0; + + ret = ___csock_close(csock->fd); + if (ret != 0) { + errno = __csock_errno (ret); + ret = -1; + } else { +// __csock_fd_set_clear(csock->fd); /* fd unused now */ + } + + return (ret); +} diff --git a/src/libc/posix/socket/csock/c_connct.c b/src/libc/posix/socket/csock/c_connct.c new file mode 100644 index 00000000..2526ca84 --- /dev/null +++ b/src/libc/posix/socket/csock/c_connct.c @@ -0,0 +1,63 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include +#include +#include "csock.h" + +/* ------------------- + * - __csock_connect - + * ------------------- */ + +int __csock_connect (LSCK_SOCKET *lsd, + struct sockaddr *serv_addr, size_t addrlen) +{ + LSCK_SOCKET_CSOCK *csock = (LSCK_SOCKET_CSOCK *) lsd->idata; + struct sockaddr_in *sai = (struct sockaddr_in *) serv_addr; + int ret; + + /* Non-blocking connects aren't supported by SOCK.VXD. Fail, so the + * callee doesn't loop infinitely. */ + if (!lsd->blocking) { + errno = EOPNOTSUPP; + return(-1); + } + + /* TODO: Modify this so that Ctrl+C interrupts it. If SOCK.VXD + * supported non-blocking connects, it could be done. In the meantime, + * this always blocks. */ + ret = ___csock_connect(csock->fd, sai->sin_addr.s_addr, sai->sin_port); + if (ret != 0) { + errno = __csock_errno (ret); + return (-1); + } + + /*if (lsd->blocking) + * if (__csock_selectsocket_wait(lsd, FD_WRITE ) == -1) return -1; */ + + return (ret); +} diff --git a/src/libc/posix/socket/csock/c_errors.c b/src/libc/posix/socket/csock/c_errors.c new file mode 100644 index 00000000..ffc07665 --- /dev/null +++ b/src/libc/posix/socket/csock/c_errors.c @@ -0,0 +1,120 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include "csock.h" + +/* Cheers Microsoft */ +#include "tdistat.h" + +/* ----------------- + * - __csock_errno - + * ----------------- */ + +int __csock_errno (int i_errno) +{ + switch (i_errno) { + /* SOCK.VXD errors */ + case -CSOCK_ERR_INVALID_PARAM: + return (EINVAL); + case -CSOCK_ERR_NO_MEMORY: + return (ENOBUFS); + case -CSOCK_ERR_INVALID_SOCKET: + return (ENOTSOCK); + case -CSOCK_ERR_ALREADY_BOUND: + return (EINVAL); + case -CSOCK_ERR_NOT_BOUND: + /* RD: What was I thinking here? */ + /*return (EDESTADDRREQ);*/ + /* This a bit generic, but it's probably the most sensible error + * return here. */ + return(EINVAL); + case -CSOCK_ERR_ACCESS: + return (EACCES); + case -CSOCK_ERR_INTERNAL: + return (EAGAIN); /* TODO: Hmmm */ + case -CSOCK_ERR_FD_INUSE: + return (EBUSY); /* TODO: Hmmm */ + case -CSOCK_ERR_INFINITE_WAIT: + return (EBUSY); /* TODO: Hmmm */ + case -CSOCK_ERR_NOT_CONNECTED: + return (ENOTCONN); + case -CSOCK_ERR_WOULD_BLOCK: + return (EWOULDBLOCK); + + /* Errors SOCK.VXD has passed through from TDI */ + case TDI_SUCCESS: + return (0); /* No error! */ + case TDI_NO_RESOURCES: + return (ENOBUFS); + case TDI_ADDR_IN_USE: + return (EADDRINUSE); + /* TDI_NO_FREE_ADDR */ + /* TDI_ADDR_INVALID */ + /* TDI_ADDR_DELETED */ + /* TDI_BUFFER_OVERFLOW */ + /* TDI_BAD_EVENT_TYPE */ + /* TDI_BAD_OPTION */ + case TDI_CONN_REFUSED: + return (ECONNREFUSED); + case TDI_INVALID_CONNECTION: + return (ENOTCONN); + /* TDI_ALREADY_ASSOCIATED */ + /* TDI_NOT_ASSOCIATED */ + case TDI_CONNECTION_ACTIVE: + return (EISCONN); + case TDI_CONNECTION_ABORTED: + return (ECONNREFUSED); + case TDI_CONNECTION_RESET: + return (ECONNRESET); + case TDI_TIMED_OUT: + return (ETIMEDOUT); + case TDI_GRACEFUL_DISC: + return (ECONNRESET); + /* TDI_NOT_ACCEPTED */ + /* TDI_MORE_PROCESSING */ + /* TDI_INVALID_STATE */ + /* TDI_INVALID_PARAMETER */ + case TDI_DEST_NET_UNREACH: + return (ENETUNREACH); + case TDI_DEST_HOST_UNREACH: + case TDI_DEST_PORT_UNREACH: /* TODO: Hmm */ + return (EHOSTUNREACH); + /* TDI_DEST_PROT_UNREACH */ + /* TDI_INVALID_QUERY */ + /* TDI_BUFFER_TOO_SMALL */ + /* TDI_CANCELLED */ + /* TDI_BUFFER_TOO_BIG */ + /* TDI_INVALID_REQUEST */ + /* TDI_PENDING */ + + /*default: return(EINVAL); */ + /* Return the current errno by default */ + default: + return (errno); + } +} diff --git a/src/libc/posix/socket/csock/c_fcntl.c b/src/libc/posix/socket/csock/c_fcntl.c new file mode 100644 index 00000000..e5006ebf --- /dev/null +++ b/src/libc/posix/socket/csock/c_fcntl.c @@ -0,0 +1,64 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include +#include "csock.h" + +/* ----------------- + * - __csock_fcntl - + * ----------------- */ + +int __csock_fcntl (LSCK_SOCKET *lsd, int *rv, int command, int request) +{ + int x = 1; + int fakeflags = 0; + int handled = 0; /* Set if we've handled fcntl. */ + + switch (command) { + case F_SETFL: + /* Enable/disable non-blocking I/O */ + x = (request & O_NONBLOCK) == O_NONBLOCK; + + /* Set/clear non-blocking mode. */ + handled = __csock_ioctl (lsd, rv, FIONBIO, &x); + break; + + case F_GETFL: + /* TODO: This should be handled by fcntl emulation. */ + if (lsd->blocking) fakeflags |= O_NONBLOCK; + *rv = fakeflags; + handled = 1; + break; + + default: + handled = 0; + break; + } + + return(handled); +} diff --git a/src/libc/posix/socket/csock/c_gprnm.c b/src/libc/posix/socket/csock/c_gprnm.c new file mode 100644 index 00000000..f90926f0 --- /dev/null +++ b/src/libc/posix/socket/csock/c_gprnm.c @@ -0,0 +1,63 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include +#include +#include "csock.h" + +/* ----------------------- + * - __csock_getpeername - + * ----------------------- */ + +int __csock_getpeername (LSCK_SOCKET * lsd, + struct sockaddr *name, size_t *namelen) +{ + LSCK_SOCKET_CSOCK *csock = (LSCK_SOCKET_CSOCK *) lsd->idata; + struct sockaddr_in *peer_sa = (struct sockaddr_in *) name; + unsigned int peer_addr; + unsigned short peer_port; + int ret = 0; + + if (*namelen < sizeof (struct sockaddr_in)) { + errno = ENOBUFS; + return (-1); + } + + ret = ___csock_getpeername(csock->fd, &peer_addr, &peer_port); + if (ret != 0) { + errno = __csock_errno (ret); + return (-1); + } + + *namelen = sizeof (struct sockaddr_in); + + peer_sa->sin_family = AF_INET; + peer_sa->sin_addr.s_addr = peer_addr; + peer_sa->sin_port = peer_port; + + return (0); +} diff --git a/src/libc/posix/socket/csock/c_gscknm.c b/src/libc/posix/socket/csock/c_gscknm.c new file mode 100644 index 00000000..1b23ad89 --- /dev/null +++ b/src/libc/posix/socket/csock/c_gscknm.c @@ -0,0 +1,100 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include +#include +#include +#include "csock.h" + +/* TODO: This function in SOCK.VXD seems broken - it succeeds, but no address + * is returned. Contact SOCK.VXD's author. */ + +/* ----------------------- + * - __csock_getsockname - + * ----------------------- */ + +int __csock_getsockname (LSCK_SOCKET *lsd, + struct sockaddr *name, size_t *namelen) +{ + LSCK_SOCKET_CSOCK *csock = (LSCK_SOCKET_CSOCK *) lsd->idata; + struct sockaddr_in *sock_sa = (struct sockaddr_in *) name; + struct sockaddr_in *peer_sa = (struct sockaddr_in *) &lsd->peername; + LSCK_IF_ADDR_INET **inet = NULL; + ULONG32 sock_addr = 0; + unsigned short sock_port = 0; + int ret = 0; + int i; + + if (*namelen < sizeof (struct sockaddr_in)) { + errno = ENOBUFS; + return (-1); + } + + ret = ___csock_getsockname(csock->fd, &sock_addr, &sock_port); + if (ret != 0) { + errno = __csock_errno (ret); + return (-1); + } + *namelen = sizeof (struct sockaddr_in); + + sock_sa->sin_family = AF_INET; + sock_sa->sin_addr.s_addr = sock_addr; + sock_sa->sin_port = sock_port; + + /* Just in the case the bug gets fixed. */ + if ((sock_addr != 0) && __lsck_debug_enabled ()) + fputs ("__csock_getsockname() now works!\n", stderr); + + /* TODO: Eliminate this nasty hack. It exists because of the problem + * mentioned above. */ + + /* Because the getsockname() call above doesn't fill in sock_addr, it + * has to be faked using the data we have about the interface. The + * following code scans the interface address table for the peer's + * network and then returns our interface address on that network. */ + inet = lsd->interface->addr->table.inet; + + for (i = 0, sock_addr = 0; inet[i] != NULL; i++) { + /* Is this on our network? */ + if ((peer_sa->sin_addr.s_addr & inet[i]->netmask.s_addr) + == (inet[i]->addr.s_addr & inet[i]->netmask.s_addr)) { + sock_addr = inet[i]->addr.s_addr; + break; + } + + /* If this network has a gateway, speculatively use this + * address. If no other networks match, then this will be + used. */ + if (inet[i]->gw_present) + sock_addr = inet[i]->addr.s_addr; + } + + sock_sa->sin_addr.s_addr = sock_addr; + + return (0); +} diff --git a/src/libc/posix/socket/csock/c_initnt.c b/src/libc/posix/socket/csock/c_initnt.c new file mode 100644 index 00000000..10f48eab --- /dev/null +++ b/src/libc/posix/socket/csock/c_initnt.c @@ -0,0 +1,271 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include + +#include + +#include +#include +#include /* For IFNAMSIZ def */ + +#include +#include +#include +#include "csock.h" + +#include +#include +#include +#include + +#include + +/* --- Global variables --- */ + +char CSOCK_IF_NAME[IFNAMSIZ] = "Coda SOCK.VXD"; + +LSCK_IF __csock_interface = +{ + /* Interface information */ + CSOCK_IF_NAME, + IF_FLAG_HAS_NONBLOCKING, + (LSCK_IF_ADDR_TABLE *) NULL, + (LSCK_IF_ROUTE_TABLE *) NULL, + + /* Interface management functions */ + NULL, __csock_init, NULL, __csock_uninit, + + /* General functions */ + __csock_socket, __csock_socketpair, __csock_close, + __csock_proto_check, __csock_addrlen_check, + __csock_bind, __csock_listen, __csock_accept, + __csock_connect, + __csock_recv, __csock_recvfrom, + __csock_send, __csock_sendto, + __csock_getsockname, __csock_getpeername, + __csock_getsockopt, NULL, + __csock_shutdown, + + /* I/O control functions */ + __csock_fcntl, __csock_ioctl, __csock_select, + __csock_nonblocking_check, + NULL /* sockatmark */ +}; + +static int CSOCK_VXD_ID = 0x1235; +//static char CSOCK_VXD_NAME[] = "SOCK.VXD"; +//int csock_entry[2]; +unsigned int __csock_version = 0; + +static int csock_inited = 0; + +/* IP information */ +#define DHCP_IP "0.0.0.0" + +/* ---------------- + * - __csock_init - + * ---------------- */ + +LSCK_IF *__csock_init (void) +{ + LSCK_IF_ADDR_INET *inet = NULL; + char *cfg = NULL; + char enabled_buf[6]; /* 5 letters/digits + nul = 5 bytes */ + int win_version, ret; + + if (csock_inited) + return (&__csock_interface); + + /* Check that this interface is enabled. If the "Enabled" entry is + * present in the configuration file, presume that it's enabled unless + * one of the values false, no or 0 is used. */ + cfg = __lsck_config_getfile(); + + if (cfg != NULL) + GetPrivateProfileString ("csock", "Enabled", "true", + enabled_buf, sizeof (enabled_buf), + cfg); + else + strcpy(enabled_buf, "true"); + + if ((stricmp (enabled_buf, "false") == 0) + || (stricmp (enabled_buf, "no") == 0) + || (strcmp (enabled_buf, "0") == 0)) { + if (__lsck_debug_enabled ()) + printf ("csock: Interface disabled\n"); + return (NULL); + } + + win_version = __get_windows_version(); + + if (__lsck_debug_enabled ()) { + switch (win_version) { + case WIN_311: + /* TODO: Does SOCK.VXD work with Windows 3.x? */ + printf("csock: Windows 3.x detected\n"); + break; + + case WIN_95: + printf("csock: Windows '95 (& later) detected\n"); + break; + + case WIN_98: + printf("csock: Windows '98 detected\n"); + break; + + case WIN_NT: + printf("csock: Windows NT detected\n"); + break; + + case WIN_NONE: + default: + printf("csock: Windows not detected\n"); + break; + } + } + + /* No Windows => no Winsock => fail! */ + switch(win_version) { + /* Unsupported */ + case WIN_NONE: + case WIN_NT: + return (NULL); + break; + + default: + break; + } + + /* Load the VxD and get its entry point */ +// if (VxdLdrLoadDevice (CSOCK_VXD_NAME) != 0) +// return (NULL); + +// csock_entry[0] = csock_entry[1] = 0; + ret = VxdGetEntry (/*csock_entry, */CSOCK_VXD_ID); + if (ret < 0) { + errno = ENODEV; + return (NULL); + } + + /* Get the VxD version - This is a little tricky as the original + * versions of SOCK.VXD do not support this function call (EAX = 0). + * They will try to find the socket descriptor specified by EDI, so + * pass a bogus one to ensure failure. */ + ret = ___csock_get_version(&__csock_version); + if (ret < 0) + return NULL; + + /* - Get the IP details - */ + + /* Config override? */ + inet = __lsck_if_addr_inet_getconfig ("csock"); + + if (inet != NULL) { + /* If malloc fails, fall back on auto */ + __csock_interface.addr = + (LSCK_IF_ADDR_TABLE *) + malloc (sizeof (LSCK_IF_ADDR_TABLE)); + + if (__csock_interface.addr != NULL) { + __csock_interface.addr->family = AF_INET; + __csock_interface.addr->table.inet[0] = + __lsck_if_addr_inet_loopback (); + __csock_interface.addr->table.inet[1] = inet; + __csock_interface.addr->table.inet[2] = NULL; + } + } + + /* No config override, so try to configure automatically */ +// if (__csock_interface.addr == NULL) +// __csock_interface.addr = __win9x_getaddrtable (); + + if (__csock_interface.addr == NULL) { + csock_inited = 1; + __csock_uninit (); + return (NULL); + } + + /* Done */ + csock_inited = 1; + return (&__csock_interface); +} + +/* ------------------ + * - __csock_uninit - + * ------------------ */ + +int __csock_uninit (void) +{ + if (!csock_inited) return (1); + + /* Unloading the VxD may cause protection faults in Windows's Virtual + * Memory Manager (VMM). Maybe SOCK.VXD doesn't clean up properly when + * it's unloaded or a socket is closed (i.e. TDI still thinks it's + * using the memory, tries to access it -> PF). */ + + /*VxdLdrUnLoadDevice ("SOCK.VXD");*/ + + csock_inited = 0; + return (1); +} + +/* ----------------------- + * - __csock_proto_check - + * ----------------------- */ + +/* sock.vxd supported protocols. This was found by looking at sock.vxd's + * source. */ + +int __csock_proto_check (int domain, int type, int protocol) +{ + /* sock.vxd support inited? */ + if (!csock_inited) return (0); + + /* Only Internet sockets */ + if (domain != AF_INET) return (0); + + /* Only TCP streams, UDP datagrams */ + if (((type == SOCK_STREAM) && (protocol == IPPROTO_TCP)) + || ((type == SOCK_DGRAM) && (protocol == IPPROTO_UDP))) + return (1); + + /* Fail all others */ + return (0); +} + +/* ------------------------- + * - __csock_addrlen_check - + * ------------------------- */ + +int __csock_addrlen_check (LSCK_SOCKET *lsd, size_t addrlen) +{ + if (lsd->family != AF_INET) return(0); + if ((lsd->type != SOCK_STREAM) && (lsd->type != SOCK_DGRAM)) return(0); + if (addrlen < sizeof(struct sockaddr_in)) return(0); + return(1); +} diff --git a/src/libc/posix/socket/csock/c_ioctl.c b/src/libc/posix/socket/csock/c_ioctl.c new file mode 100644 index 00000000..dfdf995d --- /dev/null +++ b/src/libc/posix/socket/csock/c_ioctl.c @@ -0,0 +1,86 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include + +#include +#include +#include "csock.h" + +/* ----------------- + * - __csock_ioctl - + * ----------------- */ + +int __csock_ioctl (LSCK_SOCKET *lsd, int *rv, int request, int *param) +{ + LSCK_SOCKET_CSOCK *csock = (LSCK_SOCKET_CSOCK *) lsd->idata; + int ret; /* Temporary return value */ + int handled = 0; /* Have we handled the ioctl? */ + int nonblocking = 0; + + switch (request) { + /* Non-blocking operations */ + case FIONBIO: + nonblocking = (*param == 1) ? 1 : 0; + + ret = ___csock_setnblkio(csock->fd, nonblocking); + if (ret != 0) { + errno = __csock_errno (ret); + *rv = -1; + } else { + lsd->blocking = (nonblocking == 1) ? 0 : 1; + *rv = 0; + } + handled = 1; + break; + + /* Amount of data that can be read atomically from the socket. */ + case FIONREAD: + /* TODO: Is this correct or should it return the amount of + * queued data for a stream? The Win32 API docs seem vague on + * this issue. */ + /* TODO: This should actually return the amount of data + * waiting to be read. */ + if (lsd->type == SOCK_STREAM) { + *param = CSOCK_RECV_BUFSIZE; + *rv = 0; + handled = 1; + break; + } + + ret = -1; + errno = EINVAL; + handled = 1; + break; + + default: + handled = 0; + break; + } + + return(handled); +} diff --git a/src/libc/posix/socket/csock/c_listen.c b/src/libc/posix/socket/csock/c_listen.c new file mode 100644 index 00000000..ac8aede7 --- /dev/null +++ b/src/libc/posix/socket/csock/c_listen.c @@ -0,0 +1,45 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include "csock.h" + +/* ------------------ + * - __csock_listen - + * ------------------ */ + +int __csock_listen (LSCK_SOCKET *lsd, int backlog) +{ + LSCK_SOCKET_CSOCK *csock = (LSCK_SOCKET_CSOCK *) lsd->idata; + int ret = 0; + + ret = ___csock_listen(csock->fd, backlog); + if (ret != 0) { + errno = __csock_errno (ret); + ret = -1; + } + return (ret); +} diff --git a/src/libc/posix/socket/csock/c_nblkio.c b/src/libc/posix/socket/csock/c_nblkio.c new file mode 100644 index 00000000..84b31b98 --- /dev/null +++ b/src/libc/posix/socket/csock/c_nblkio.c @@ -0,0 +1,49 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * c_nblkio.c - Non-blocking I/O completion checking + */ + +#include +#include "csock.h" + +/* ----------------------------- + * - __csock_nonblocking_check - + * ----------------------------- */ + +int __csock_nonblocking_check (LSCK_SOCKET * lsd) +{ + /* Check for a successful connection */ + if (lsd->connecting && !lsd->connected) { + /* Write-ready? */ + if (__csock_select (lsd, FD_WRITE) > 0) { + lsd->connecting = 0; + lsd->connected = 1; + } + } + /* OK */ + return (0); +} diff --git a/src/libc/posix/socket/csock/c_recv.c b/src/libc/posix/socket/csock/c_recv.c new file mode 100644 index 00000000..b9ae4414 --- /dev/null +++ b/src/libc/posix/socket/csock/c_recv.c @@ -0,0 +1,125 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include "csock.h" + +/* ---------------- + * - __csock_recv - + * ---------------- */ + +ssize_t __csock_recv (LSCK_SOCKET *lsd, + void *buf, size_t len, unsigned int flags) +{ + LSCK_SOCKET_CSOCK *csock = (LSCK_SOCKET_CSOCK *) lsd->idata; + ssize_t ret; + ULONG32 recvlen; + + /* Check flags */ + if (flags != 0) { + /* Unsupported flag used */ + errno = EINVAL; + return(-1); + } + + ret = ___csock_recv(csock->fd, buf, len, &recvlen); + if (ret < 0) { + errno = __csock_errno (ret); + return -1; + } + return recvlen; +} + +/* -------------------- + * - __csock_recvfrom - + * -------------------- */ + +ssize_t __csock_recvfrom (LSCK_SOCKET *lsd, + void *buf, size_t len, unsigned int flags, + struct sockaddr *from, size_t *fromlen) +{ + LSCK_SOCKET_CSOCK *csock = (LSCK_SOCKET_CSOCK *) lsd->idata; + ssize_t ret; + ULONG32 recvlen; + struct sockaddr_in from_sin; + int flag; + int rv; + + /* Check the size fo the socket address passed. */ + if ((from != NULL) && (*fromlen < sizeof (from_sin))) { + errno = EINVAL; + return (-1); + } + + /* Check flags */ + if ( (flags != 0) && ((flags & ~MSG_PEEK) != 0) ) { + /* Unsupported flag used */ + errno = EINVAL; + return(-1); + } + + /* NOTE: SOCK.VXD has a bug in its recvfrom() code. If a socket is set + * to non-blocking mode, then recvfrom() will block, and vice-versa. + * So, before performing the call, invert the mode. Reset the mode + * after the call. */ + + /* RD: Later: Version 1 of SOCK.VXD has this bug fixed. */ + if (__csock_version < 1) { + flag = lsd->blocking; + __csock_ioctl (lsd, &rv, FIONBIO, &flag); + } + + ret = ___csock_recvfrom(csock->fd, buf, len, + &recvlen, (ULONG32 *)&from_sin.sin_addr.s_addr, + &from_sin.sin_port); + + from_sin.sin_family = AF_INET; + + if (__csock_version < 1) { + flag = !flag; + __csock_ioctl (lsd, &rv, FIONBIO, &flag); + } + + /* Copy the peer's name, if there is one. */ + if (from != NULL) { + /* Unix98 spec says: truncate if addrlen not large enough */ + if (*fromlen > sizeof(from_sin)) *fromlen = sizeof(from_sin); + memcpy (from, &from_sin, *fromlen); + } + + if (ret < 0) { + errno = __csock_errno (ret); + return -1; + } + return recvlen; +} diff --git a/src/libc/posix/socket/csock/c_sckopt.c b/src/libc/posix/socket/csock/c_sckopt.c new file mode 100644 index 00000000..ce21735f --- /dev/null +++ b/src/libc/posix/socket/csock/c_sckopt.c @@ -0,0 +1,143 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include +#include "csock.h" + +/* ---------------------- + * - __csock_getsockopt - + * ---------------------- */ + +int __csock_getsockopt (LSCK_SOCKET *lsd, int *rv, + int level, int optname, + void *optval, size_t *optlen) +{ + int handled = 0; /* Set if we've handled the option here. */ + int *i_optval = (int *) optval; + struct timeval *tv = (struct timeval *) optval; + + /* TODO: Should this let the emulation do its biz? */ + /* Only socket level supported */ + if (level != SOL_SOCKET) { + errno = EINVAL; + *rv = -1; + return(1); + } + + /* Buffer size checking */ + switch(optname) { + /* Integer/boolean options */ + case SO_REUSEADDR: + case SO_RCVBUF: + case SO_RCVLOWAT: + case SO_SNDBUF: + case SO_SNDLOWAT: + if (*optlen < sizeof(int)) { + errno = ENOBUFS; + *rv = -1; + return(1); + } + break; + + /* struct timeval options */ + case SO_RCVTIMEO: + case SO_SNDTIMEO: + if (*optlen < sizeof(struct timeval)) { + errno = ENOBUFS; + *rv = -1; + return(1); + } + break; + } + + switch(optname) { + /* SOCK.VXD always allows address use for bind() calls - see the call + * to TdiOpenAddressEntry() in do_bind() in the SOCK.VXD sources. */ + case SO_REUSEADDR: + *i_optval = 1; + *optlen = sizeof(int); + *rv = 0; + handled = 1; + break; + + /* Receive buffer size - see sys_socket() in SOCK.VXD sources. */ + case SO_RCVBUF: + *i_optval = CSOCK_RECV_BUFSIZE; + *optlen = sizeof(int); + *rv = 0; + handled = 1; + break; + + /* Receive low water mark - see sys_recv() and sys_recvfrom() in + * SOCK.VXD sources. Any data received is always returned, so the + * low water mark is 1 byte. */ + case SO_RCVLOWAT: + *i_optval = 1; + *optlen = sizeof(int); + *rv = 0; + handled = 1; + break; + + /* SOCK.VXD always completes non-blocking receives. */ + case SO_RCVTIMEO: + tv->tv_sec = tv->tv_usec = 0; + *rv = 0; + handled = 1; + break; + + /* Lie about the send buffer size. Since SOCK.VXD uses a linked-list + * of data to send, this doesn't really make any difference. It seems + * reasonable to pretend it's the same size as the receive buffer. */ + case SO_SNDBUF: + *i_optval = CSOCK_RECV_BUFSIZE; + *optlen = sizeof(int); + *rv = 0; + handled = 1; + break; + + /* Send low water mark - see sys_socket() in SOCK.VXD sources. */ + case SO_SNDLOWAT: + *i_optval = CSOCK_SEND_LOWWATER; + *optlen = sizeof(int); + *rv = 0; + handled = 1; + break; + + /* SOCK.VXD always completes non-blocking sends. */ + case SO_SNDTIMEO: + tv->tv_sec = tv->tv_usec = 0; + *rv = 0; + handled = 1; + break; + + /* Unknown option */ + default: + handled = 0; + } + + return(handled); +} diff --git a/src/libc/posix/socket/csock/c_select.c b/src/libc/posix/socket/csock/c_select.c new file mode 100644 index 00000000..310b7b1a --- /dev/null +++ b/src/libc/posix/socket/csock/c_select.c @@ -0,0 +1,106 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * NOTE: SOCK.VXD uses a socket fd mask here, so one can check for multiple + * sockets in one call. So, one cannot simply pass a file descriptor here. + */ + +#include +#include +#include + +#include + +#include +#include +#include "csock.h" + +/* TODO: How to specify event? */ + +/* ------------------ + * - __csock_select - + * ------------------ */ + +int __csock_select (LSCK_SOCKET * lsd, int event) +{ + LSCK_SOCKET_CSOCK *csock = (LSCK_SOCKET_CSOCK *) lsd->idata; + ULONG32 read_fd = 0; + ULONG32 write_fd = 0; + ULONG32 except_fd = 0; + ULONG32 bit = 1UL << csock->fd; + unsigned to = 0; + int ret = 0; + + switch (event) { + case FD_READ: + read_fd = bit; + break; + + case FD_WRITE: + write_fd = bit; + break; + + /* TODO: Is this correct? Is this how FD_ACCEPT, etc. should be + * handled? This solution seems better than previous one of + * select'ing on all 3 here. I think only one event is passed + * at a time. */ + default: + except_fd = bit; + break; + } + + ret = ___csock_select(&read_fd, &write_fd, &except_fd, &to); + if (ret != 0) { + errno = __csock_errno (ret); + ret = -1; + } else { + /* Success */ + if (((read_fd & bit) == bit) + || ((write_fd & bit) == bit) + || ((except_fd & bit) == bit)) + ret = 1; + else + ret = 0; + } + + return (ret); /* TODO: Return the elapsed time? */ +} + +/* ----------------------- + * - __csock_select_wait - + * ----------------------- */ + +int __csock_select_wait (LSCK_SOCKET * lsd, int event) +{ + int ret = 0; + + while (ret == 0) { + ret = __csock_select (lsd, event); + __dpmi_yield (); + } + + return (ret); +} diff --git a/src/libc/posix/socket/csock/c_send.c b/src/libc/posix/socket/csock/c_send.c new file mode 100644 index 00000000..ac8a64d5 --- /dev/null +++ b/src/libc/posix/socket/csock/c_send.c @@ -0,0 +1,159 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include "csock.h" + +/* ---------------- + * - __csock_send - + * ---------------- */ + +ssize_t __csock_send (LSCK_SOCKET *lsd, + const void *msg, size_t len, unsigned int flags) +{ + LSCK_SOCKET_CSOCK *csock = (LSCK_SOCKET_CSOCK *) lsd->idata; + ssize_t ret; + ULONG32 sentlen; + + /* No flags are supported */ + if (flags != 0) { + errno = EINVAL; + return(-1); + } + + ret = ___csock_send(csock->fd, msg, len, &sentlen); + /* NOTE: Carry is always set, because SOCK.VXD's sys_send() function + * always returns a value - length, error, whatever - so SOCK.VXD + * errors must be distinguished from TDI ones! */ + if (ret < 0) { + if (-ret < CSOCK_ERR_MIN) ret = -ret; /* TDI error code */ + errno = __csock_errno (ret); + ret = -1; + } + + /* NOTE: SOCK.VXD returns the sent length in EAX & ECX. ECX, however, + * is bitwise OR'd with some kind of status byte, so it's value may + * differ from the actual sent length. So, use EAX here. */ + + /*else { + ret = sentlen; + }*/ + + return (ret); +} + +/* ------------------ + * - __csock_sendto - + * ------------------ */ + +ssize_t __csock_sendto (LSCK_SOCKET *lsd, + const void *msg, size_t len, unsigned int flags, + struct sockaddr *to, size_t tolen) +{ + LSCK_SOCKET_CSOCK *csock = (LSCK_SOCKET_CSOCK *) lsd->idata; + ssize_t ret; + ULONG32 sentlen; + struct sockaddr_in bind_sin; + size_t bind_sin_len; + struct sockaddr_in *to_sa = (struct sockaddr_in *) to; + + /* If this is a datagram socket, bind to a local address, if + * necessary. */ + if ( (lsd->type == SOCK_DGRAM) && !lsd->bound) { + /* TODO: Is this correct? Should it not bind only to the IP + * address that will be used to send the data? If so, how do + * you unbind it? Do you just bind to another address? Would a + * sendto() with an address followed by another sendto() + * without an address lead to this situation: bind() with + * address, bind() with wildcard address? */ + + /* Bind it to _any_ local address. */ + bzero(&bind_sin, sizeof(bind_sin)); + bind_sin.sin_family = AF_INET; + bind_sin.sin_port = 0; + bind_sin.sin_addr.s_addr = INADDR_ANY; + + ret = __csock_bind(lsd, + (struct sockaddr *) &bind_sin, + sizeof(bind_sin)); + + /* Copy the details into socket descriptor, if successful, + * else nuke. Since we've called __csock_bind() here, we have + * to handle what bind() would normally do for us. */ + if (ret == 0) { + /* Get the local address. */ + + /* TODO: This probably shouldn't ignore the return + * address. However, how can we unbind the socket on + * error? So for the moment, possibly return a bogus + * address. */ + bind_sin_len = sizeof(bind_sin); + __csock_getsockname(lsd, + (struct sockaddr *) &bind_sin, + &bind_sin_len); + + memcpy(&lsd->sockname, + (void *) &bind_sin, bind_sin_len); + lsd->socknamelen = bind_sin_len; + lsd->bound = 1; + } else { + bzero (&lsd->sockname, sizeof (struct sockaddr)); + + lsd->socknamelen = 0; + lsd->bound = 0; + } + + /* TODO: This should probably translate some of the errors. */ + if (ret == -1) return(-1); + } + + /* No flags are supported */ + if (flags != 0) { + errno = EINVAL; + return(-1); + } + + ret = ___csock_sendto(csock->fd, to_sa->sin_addr.s_addr, + to_sa->sin_port, msg, len, &sentlen); + /* NOTE: Carry is always set, because SOCK.VXD's sys_sendto() function + * always returns a value - length, error, whatever - so SOCK.VXD + * errors must be distinguished from TDI ones! */ + if (ret < 0) { + if (-ret < CSOCK_ERR_MIN) ret = -ret; /* TDI error code */ + errno = __csock_errno (ret); + return -1; + } + return sentlen; +} diff --git a/src/libc/posix/socket/csock/c_shtdwn.c b/src/libc/posix/socket/csock/c_shtdwn.c new file mode 100644 index 00000000..22693f1b --- /dev/null +++ b/src/libc/posix/socket/csock/c_shtdwn.c @@ -0,0 +1,39 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include "csock.h" + +/* -------------------- + * - __csock_shutdown - + * -------------------- */ + +/* Nothing special required here - "fake" success, since SOCK.VXD doesn't + * provide an appropriate function. */ + +int __csock_shutdown (LSCK_SOCKET * lsd, int how) +{ + return 0; +} diff --git a/src/libc/posix/socket/csock/c_socket.c b/src/libc/posix/socket/csock/c_socket.c new file mode 100644 index 00000000..3aef9930 --- /dev/null +++ b/src/libc/posix/socket/csock/c_socket.c @@ -0,0 +1,77 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include + +#include +#include +#include "csock.h" + +/* ------------------ + * - __csock_socket - + * ------------------ */ + +int __csock_socket (LSCK_SOCKET *lsd) +{ + LSCK_SOCKET_CSOCK *csock = NULL; + int flag = 0; + int ret = -1; + int rv; + unsigned int i; + + /* Allocate a buffer for the interface data. */ + csock = (LSCK_SOCKET_CSOCK *) malloc(sizeof(*csock)); + lsd->idata = (void *) csock; + + if (csock == NULL) { + errno = ENOMEM; + return(-1); + } + + ret = ___csock_open(lsd->protocol, &i); + /* Got one! */ + if (ret == 0) { + csock->fd = i; + } + + if (csock->fd == -1) { + /* No free descriptors! */ + /* TODO: Does SOCK.VXD allocate per process or per system? If + * it's per system, then this needs to be changed to ENFILE. */ + errno = EMFILE; + return (-1); + } + + if (ret != 0) { + errno = __csock_errno (ret); + return (-1); + } + + __csock_ioctl (lsd, &rv, FIONBIO, &flag); /* Blocking I/O */ + + return (0); +} diff --git a/src/libc/posix/socket/csock/c_sockpr.c b/src/libc/posix/socket/csock/c_sockpr.c new file mode 100644 index 00000000..3b1a35fe --- /dev/null +++ b/src/libc/posix/socket/csock/c_sockpr.c @@ -0,0 +1,43 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include +#include "csock.h" + +/* ---------------------- + * - __csock_socketpair - + * ---------------------- */ + +/* Until sock.vxd's address reusual can be controlled, this is way too + * dangerous a function to implement. You could just trample over any currently + * bound sockets when creating a pair! */ + +int __csock_socketpair (LSCK_SOCKET *lsd[2]) +{ + errno = EAFNOSUPPORT; + return(-1); +} diff --git a/src/libc/posix/socket/csock/csock.h b/src/libc/posix/socket/csock/csock.h new file mode 100644 index 00000000..f71df515 --- /dev/null +++ b/src/libc/posix/socket/csock/csock.h @@ -0,0 +1,178 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __libsocket_csock_h__ +#define __libsocket_csock_h__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include + +#include + +/* --- Defines --- */ + +/* Error codes, taken from sock.h from Coda's sock.vxd source */ +#define CSOCK_ERR_INVALID_PARAM 0x00000100 +#define CSOCK_ERR_NO_MEMORY 0x00000200 +#define CSOCK_ERR_INVALID_SOCKET 0x00000300 +#define CSOCK_ERR_ALREADY_BOUND 0x00000400 +#define CSOCK_ERR_NOT_BOUND 0x00000500 +#define CSOCK_ERR_ACCESS 0x00000600 +#define CSOCK_ERR_INTERNAL 0x00000700 +#define CSOCK_ERR_FD_INUSE 0x00000800 +#define CSOCK_ERR_INFINITE_WAIT 0x00000900 +#define CSOCK_ERR_NOT_CONNECTED 0x00000a00 +#define CSOCK_ERR_WOULD_BLOCK 0x00000b00 +#define CSOCK_ERR_NOT_LISTENING 0x00000c00 + +/* Minimum error code - used to distinguish sock.vxd errors from TDI ones. */ +#define CSOCK_ERR_MIN CSOCK_ERR_INVALID_PARAM + +/* From the SOCK.VXD sources, the following sizes are defined: */ +#define CSOCK_RECV_BUFSIZE 32768 /* Receive buffer size */ +#define CSOCK_SEND_LOWWATER 1024 +#define CSOCK_SEND_MAXSIZE 5000 + +/* --- Structures --- */ + +/* SOCK.VXD socket information */ +typedef struct _LSCK_SOCKET_CSOCK { + int fd; /* SOCK.VXD's unique file desc. */ +} LSCK_SOCKET_CSOCK; + +/* --- Functions --- */ +extern LSCK_IF *__csock_init (void); + +extern int __csock_uninit (void); + +extern int __csock_errno (int /* i_errno */); + +extern int __csock_proto_check (int /* domain */, + int /* type */, + int /* protocol */); + +extern int __csock_addrlen_check (LSCK_SOCKET * /* lsd */, + size_t /* addrlen */); + +extern int __csock_socket (LSCK_SOCKET * /* lsd */); + +extern int __csock_socketpair (LSCK_SOCKET * /* lsd */ [2]); + +extern int __csock_close (LSCK_SOCKET * /* lsd */); + +extern int __csock_bind (LSCK_SOCKET * /* lsd */, + struct sockaddr * /* my_addr */, + size_t /* addrlen */); + +extern int __csock_accept (LSCK_SOCKET * /* lsd */, + LSCK_SOCKET * /* nsd */, + struct sockaddr * /* sockaddr */, + size_t * /* addrlen */); + +extern int __csock_listen (LSCK_SOCKET * /* lsd */, int /* backlog */); + +extern int __csock_connect (LSCK_SOCKET * /* lsd */, + struct sockaddr * /* serv_addr */, + size_t /* addrlen */); + +extern ssize_t __csock_recv (LSCK_SOCKET * /* lsd */, + void * /* buf */, + size_t /* len */, + unsigned int /* flags */); + +extern ssize_t __csock_recvfrom (LSCK_SOCKET * /* lsd */, + void * /* buf */, + size_t /* len */, + unsigned int /* flags */, + struct sockaddr * /* from */, + size_t * /* fromlen */); + +extern ssize_t __csock_send (LSCK_SOCKET * /* lsd */, + const void * /* msg */, + size_t /* len */, + unsigned int /* flags */); + +extern ssize_t __csock_sendto (LSCK_SOCKET * /* lsd */, + const void * /* msg */, + size_t /* len */, + unsigned int /* flags */, + struct sockaddr * /* to */, + size_t /* tolen */); + +extern int __csock_getpeername (LSCK_SOCKET * /* lsd */, + struct sockaddr * /* name */, + size_t * /* namelen */); + +extern int __csock_getsockname (LSCK_SOCKET * /* lsd */, + struct sockaddr * /* name */, + size_t * /* namelen */); + +extern int __csock_shutdown (LSCK_SOCKET * /* lsd */, int /* how */); + +extern int __csock_select (LSCK_SOCKET * /* lsd */, int /* event */); + +extern int __csock_select_wait (LSCK_SOCKET * /* lsd */, int /* event */); + +extern int __csock_ioctl (LSCK_SOCKET * /* lsd */, + int * /* rv */, + int /* request */, + int * /* param */); + +extern int __csock_fcntl (LSCK_SOCKET * /* lsd */, + int * /* rv */, + int /* command */, + int /* request */); + +extern int __csock_nonblocking_check (LSCK_SOCKET * /* lsd */); + +extern int __csock_getsockopt (LSCK_SOCKET * /* lsd */, + int * /* rv */, + int /* level */, + int /* optname */, + void * /* optval */, + size_t * /* optlen */); + +/* File descriptor tracking */ +extern void __csock_fd_set_usage (int /* fd */, int /* flag */); +extern void __csock_fd_set_used (int /* fd */); +extern void __csock_fd_set_clear (int /* fd */); +extern int __csock_fd_get_usage (int /* fd */); + +/* --- Globals --- */ +//extern int csock_entry[2]; +extern char CSOCK_IF_NAME[]; +extern unsigned int __csock_version; + +#ifdef __cplusplus +}; +#endif + +#endif /* __libsocket_csock_h__ */ + diff --git a/src/libc/posix/socket/csock/makefile b/src/libc/posix/socket/csock/makefile new file mode 100644 index 00000000..59a73c40 --- /dev/null +++ b/src/libc/posix/socket/csock/makefile @@ -0,0 +1,43 @@ +# Copyright (C) 2014 DJ Delorie, see COPYING.DJ for details +# Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details +# Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details +TOP=../../.. + +SRC += c_initnt.c +AS_SRC += s_initnt.S +SRC += c_socket.c +AS_SRC += s_socket.S +SRC += c_close.c +AS_SRC += s_close.S +SRC += c_connct.c +AS_SRC += s_connct.S +SRC += c_send.c +AS_SRC += s_sendto.S +AS_SRC += s_send.S +SRC += c_errors.c +SRC += c_select.c +AS_SRC += s_select.S +SRC += c_recv.c +AS_SRC += s_recvfr.S +AS_SRC += s_recv.S +SRC += c_listen.c +AS_SRC += s_listen.S +SRC += c_bind.c +AS_SRC += s_bind.S +SRC += c_accept.c +AS_SRC += s_accept.S +SRC += c_gprnm.c +AS_SRC += s_gprnm.S +SRC += c_gscknm.c +AS_SRC += s_gscknm.S +SRC += c_ioctl.c +SRC += c_fcntl.c +SRC += c_nblkio.c +AS_SRC += s_gnblk.S +AS_SRC += s_snblk.S +SRC += c_shtdwn.c +SRC += c_sckopt.c +SRC += c_sockpr.c +AS_SRC += vxd.S + +include $(TOP)/../makefile.inc diff --git a/src/libc/posix/socket/csock/s_accept.S b/src/libc/posix/socket/csock/s_accept.S new file mode 100644 index 00000000..84300253 --- /dev/null +++ b/src/libc/posix/socket/csock/s_accept.S @@ -0,0 +1,29 @@ +#include +#define USE_EBX +#define USE_EDX +#define USE_EDI +#define USE_EAX +#define USE_ESI +#define USE_ECX + +.text + +FUNC(____csock_accept) + ENTER + + movl ARG1, %edi + movl $12, %eax + lcall *_csock_entry // Call the entry point for SOCK.VXD + jc 1f // Jump to label 1 if the carry flag is set (error) + movl ARG2, %edi + movl %edx, (%edi) + movl ARG3, %edi + movl %ecx, (%edi) + movl ARG4, %edi + movl %ebx, (%edi) + xorl %eax, %eax // Clear EAX (set it to 0) on success +2: + LEAVE +1: + neg %eax + jmp 2b diff --git a/src/libc/posix/socket/csock/s_bind.S b/src/libc/posix/socket/csock/s_bind.S new file mode 100644 index 00000000..3bedbadb --- /dev/null +++ b/src/libc/posix/socket/csock/s_bind.S @@ -0,0 +1,23 @@ +#include +#define USE_EBX +#define USE_EDX +#define USE_EDI +#define USE_EAX + +.text + +FUNC(____csock_bind) + ENTER + + movl ARG1, %edi + movl ARG2, %ebx + movl ARG3, %edx + movl $3, %eax + lcall *_csock_entry // Call the entry point for SOCK.VXD + jc 1f // Jump to label 1 if the carry flag is set (error) + xorl %eax, %eax // Clear EAX (set it to 0) on success +2: + LEAVE +1: + neg %eax + jmp 2b diff --git a/src/libc/posix/socket/csock/s_close.S b/src/libc/posix/socket/csock/s_close.S new file mode 100644 index 00000000..3f0006be --- /dev/null +++ b/src/libc/posix/socket/csock/s_close.S @@ -0,0 +1,19 @@ +#include +#define USE_EDI +#define USE_EAX + +.text + +FUNC(____csock_close) + ENTER + + movl ARG1, %edi + movl $2, %eax + lcall *_csock_entry // Call the entry point for SOCK.VXD + jc 1f // Jump to label 1 if the carry flag is set (error) + xorl %eax, %eax // Clear EAX (set it to 0) on success +2: + LEAVE +1: + neg %eax + jmp 2b diff --git a/src/libc/posix/socket/csock/s_connct.S b/src/libc/posix/socket/csock/s_connct.S new file mode 100644 index 00000000..857d2989 --- /dev/null +++ b/src/libc/posix/socket/csock/s_connct.S @@ -0,0 +1,25 @@ +#include +#define USE_EBX +#define USE_EDX +#define USE_EDI +#define USE_EAX +#define USE_ESI +#define USE_ECX + +.text + +FUNC(____csock_connect) + ENTER + + movl ARG1, %edi + movl ARG2, %ebx + movl ARG3, %edx + movl $7, %eax + lcall *_csock_entry // Call the entry point for SOCK.VXD + jc 1f // Jump to label 1 if the carry flag is set (error) + xorl %eax, %eax // Clear EAX (set it to 0) on success +2: + LEAVE +1: + neg %eax + jmp 2b diff --git a/src/libc/posix/socket/csock/s_gnblk.S b/src/libc/posix/socket/csock/s_gnblk.S new file mode 100644 index 00000000..835fd4f3 --- /dev/null +++ b/src/libc/posix/socket/csock/s_gnblk.S @@ -0,0 +1,24 @@ +#include +#define USE_EBX +#define USE_EDX +#define USE_EDI +#define USE_EAX + +.text + +FUNC(____csock_getnblkio) + ENTER + + movl ARG1, %edi + movl $0, %ecx + movl $15, %eax + lcall *_csock_entry // Call the entry point for SOCK.VXD + jc 1f // Jump to label 1 if the carry flag is set (error) + movl ARG2, %ebx + movl %edx, (%ebx) + xorl %eax, %eax // Clear EAX (set it to 0) on success +2: + LEAVE +1: + neg %eax + jmp 2b diff --git a/src/libc/posix/socket/csock/s_gprnm.S b/src/libc/posix/socket/csock/s_gprnm.S new file mode 100644 index 00000000..965818f5 --- /dev/null +++ b/src/libc/posix/socket/csock/s_gprnm.S @@ -0,0 +1,25 @@ +#include +#define USE_EBX +#define USE_EDI +#define USE_EAX +#define USE_ECX + +.text + +FUNC(____csock_getpeername) + ENTER + + movl ARG1, %edi + movl $14, %eax + lcall *_csock_entry // Call the entry point for SOCK.VXD + jc 1f // Jump to label 1 if the carry flag is set (error) + movl ARG2, %edi + movl %ecx, (%edi) + movl ARG3, %edi + movl %ebx, (%edi) + xorl %eax, %eax // Clear EAX (set it to 0) on success +2: + LEAVE +1: + neg %eax + jmp 2b diff --git a/src/libc/posix/socket/csock/s_gscknm.S b/src/libc/posix/socket/csock/s_gscknm.S new file mode 100644 index 00000000..fad9c5e8 --- /dev/null +++ b/src/libc/posix/socket/csock/s_gscknm.S @@ -0,0 +1,25 @@ +#include +#define USE_EBX +#define USE_EDI +#define USE_EAX +#define USE_ECX + +.text + +FUNC(____csock_getsockname) + ENTER + + movl ARG1, %edi + movl $13, %eax + lcall *_csock_entry // Call the entry point for SOCK.VXD + jc 1f // Jump to label 1 if the carry flag is set (error) + movl ARG2, %edi + movl %ecx, (%edi) + movl ARG3, %edi + movl %ebx, (%edi) + xorl %eax, %eax // Clear EAX (set it to 0) on success +2: + LEAVE +1: + neg %eax + jmp 2b diff --git a/src/libc/posix/socket/csock/s_initnt.S b/src/libc/posix/socket/csock/s_initnt.S new file mode 100644 index 00000000..03fad7e5 --- /dev/null +++ b/src/libc/posix/socket/csock/s_initnt.S @@ -0,0 +1,22 @@ +#include +#define USE_EBX +#define USE_EDI +#define USE_EAX + +.text + +FUNC(____csock_get_version) + ENTER + + movl $0xFFFF, %edi // Pass a bogus socket descriptor (EDI = 0xFFFF) + movl $0, %eax // Set EAX to 0 for the version call + lcall *_csock_entry // Call the entry point for SOCK.VXD + jc 1f // Jump to label 1 if the carry flag is set (error) + movl ARG1, %ebx + movl %eax, (%ebx) + xorl %eax, %eax // Clear EAX (set it to 0) on success +2: + LEAVE +1: + movl $-1, %eax + jmp 2b diff --git a/src/libc/posix/socket/csock/s_listen.S b/src/libc/posix/socket/csock/s_listen.S new file mode 100644 index 00000000..0aac2afe --- /dev/null +++ b/src/libc/posix/socket/csock/s_listen.S @@ -0,0 +1,21 @@ +#include +#define USE_EDI +#define USE_EAX +#define USE_ECX + +.text + +FUNC(____csock_listen) + ENTER + + movl ARG1, %edi + movl ARG2, %ecx + movl 10, %eax + lcall *_csock_entry // Call the entry point for SOCK.VXD + jc 1f // Jump to label 1 if the carry flag is set (error) + xorl %eax, %eax // Clear EAX (set it to 0) on success +2: + LEAVE +1: + neg %eax + jmp 2b diff --git a/src/libc/posix/socket/csock/s_recv.S b/src/libc/posix/socket/csock/s_recv.S new file mode 100644 index 00000000..04648122 --- /dev/null +++ b/src/libc/posix/socket/csock/s_recv.S @@ -0,0 +1,27 @@ +#include +#define USE_EBX +#define USE_EDX +#define USE_EDI +#define USE_EAX +#define USE_ESI +#define USE_ECX + +.text + +FUNC(____csock_recv) + ENTER + + movl ARG1, %edi + movl ARG2, %esi + movl ARG3, %ecx + movl 9, %eax + lcall *_csock_entry // Call the entry point for SOCK.VXD + jc 1f // Jump to label 1 if the carry flag is set (error) + movl ARG4, %edi + movl %ecx, (%edi) + xorl %eax, %eax // Clear EAX (set it to 0) on success +2: + LEAVE +1: + neg %eax + jmp 2b diff --git a/src/libc/posix/socket/csock/s_recvfr.S b/src/libc/posix/socket/csock/s_recvfr.S new file mode 100644 index 00000000..dbf7da2d --- /dev/null +++ b/src/libc/posix/socket/csock/s_recvfr.S @@ -0,0 +1,31 @@ +#include +#define USE_EBX +#define USE_EDX +#define USE_EDI +#define USE_EAX +#define USE_ESI +#define USE_ECX + +.text + +FUNC(____csock_recvfrom) + ENTER + + movl ARG1, %edi + movl ARG2, %esi + movl ARG3, %ecx + movl $5, %eax + lcall *_csock_entry // Call the entry point for SOCK.VXD + jc 1f // Jump to label 1 if the carry flag is set (error) + movl ARG4, %edi + movl %ecx, (%edi) + movl ARG5, %edi + movl %ebx, (%edi) + movl ARG6, %edi + movl %edx, (%edi) + xorl %eax, %eax // Clear EAX (set it to 0) on success +2: + LEAVE +1: + neg %eax + jmp 2b diff --git a/src/libc/posix/socket/csock/s_select.S b/src/libc/posix/socket/csock/s_select.S new file mode 100644 index 00000000..415a9867 --- /dev/null +++ b/src/libc/posix/socket/csock/s_select.S @@ -0,0 +1,38 @@ +#include +#define USE_EBX +#define USE_EDX +#define USE_EDI +#define USE_EAX +#define USE_ESI +#define USE_ECX + +.text + +FUNC(____csock_select) + ENTER + + movl ARG1, %esi + movl (%esi), %ebx + movl ARG2, %esi + movl (%esi), %ecx + movl ARG3, %esi + movl (%esi), %edx + movl ARG4, %esi + movl (%esi), %edi + movl $6, %eax + lcall *_csock_entry // Call the entry point for SOCK.VXD + jc 1f // Jump to label 1 if the carry flag is set (error) + movl ARG1, %esi + movl %ebx, (%esi) + movl ARG2, %esi + movl %ecx, (%esi) + movl ARG3, %esi + movl %edx, (%esi) + movl ARG4, %esi + movl %edi, (%esi) + xorl %eax, %eax // Clear EAX (set it to 0) on success +2: + LEAVE +1: + neg %eax + jmp 2b diff --git a/src/libc/posix/socket/csock/s_send.S b/src/libc/posix/socket/csock/s_send.S new file mode 100644 index 00000000..7f10da8e --- /dev/null +++ b/src/libc/posix/socket/csock/s_send.S @@ -0,0 +1,26 @@ +#include +#define USE_EBX +#define USE_EDI +#define USE_EAX +#define USE_ESI +#define USE_ECX + +.text + +FUNC(____csock_send) + ENTER + + movl ARG1, %edi + movl ARG2, %esi + movl ARG3, %ecx + movl $8, %eax + lcall *_csock_entry // Call the entry point for SOCK.VXD + jc 1f // Jump to label 1 if the carry flag is set (error) + movl ARG4, %ebx + movl %ecx, (%ebx) + xorl %eax, %eax // Clear EAX (set it to 0) on success +2: + LEAVE +1: + neg %eax + jmp 2b diff --git a/src/libc/posix/socket/csock/s_sendto.S b/src/libc/posix/socket/csock/s_sendto.S new file mode 100644 index 00000000..b5e21f55 --- /dev/null +++ b/src/libc/posix/socket/csock/s_sendto.S @@ -0,0 +1,29 @@ +#include +#define USE_EBX +#define USE_EDX +#define USE_EDI +#define USE_EAX +#define USE_ESI +#define USE_ECX + +.text + +FUNC(____csock_sendto) + ENTER + + movl ARG1, %edi + movl ARG2, %ebx + movl ARG3, %edx + movl ARG4, %esi + movl ARG5, %ecx + movl $4, %eax + lcall *_csock_entry // Call the entry point for SOCK.VXD + jc 1f // Jump to label 1 if the carry flag is set (error) + movl ARG6, %ebx + movl %ecx, (%ebx) + xorl %eax, %eax // Clear EAX (set it to 0) on success +2: + LEAVE +1: + neg %eax + jmp 2b diff --git a/src/libc/posix/socket/csock/s_snblk.S b/src/libc/posix/socket/csock/s_snblk.S new file mode 100644 index 00000000..6f479882 --- /dev/null +++ b/src/libc/posix/socket/csock/s_snblk.S @@ -0,0 +1,23 @@ +#include +#define USE_EBX +#define USE_EDX +#define USE_EDI +#define USE_EAX + +.text + +FUNC(____csock_setnblkio) + ENTER + + movl ARG1, %edi + movl $1, %ecx + movl ARG2, %edx + movl $15, %eax + lcall *_csock_entry // Call the entry point for SOCK.VXD + jc 1f // Jump to label 1 if the carry flag is set (error) + xorl %eax, %eax // Clear EAX (set it to 0) on success +2: + LEAVE +1: + neg %eax + jmp 2b diff --git a/src/libc/posix/socket/csock/s_socket.S b/src/libc/posix/socket/csock/s_socket.S new file mode 100644 index 00000000..3e38ef27 --- /dev/null +++ b/src/libc/posix/socket/csock/s_socket.S @@ -0,0 +1,22 @@ +#include +#define USE_EBX +#define USE_EDI +#define USE_EAX + +.text + +FUNC(____csock_open) + ENTER + + movl ARG1, %ebx + movl $1, %eax + lcall *_csock_entry // Call the entry point for SOCK.VXD + jc 1f // Jump to label 1 if the carry flag is set (error) + movl ARG2, %ebx + movl %edi, (%ebx) + xorl %eax, %eax // Clear EAX (set it to 0) on success +2: + LEAVE +1: + neg %eax + jmp 2b diff --git a/src/libc/posix/socket/csock/tdistat.h b/src/libc/posix/socket/csock/tdistat.h new file mode 100644 index 00000000..7bee1bab --- /dev/null +++ b/src/libc/posix/socket/csock/tdistat.h @@ -0,0 +1,99 @@ +/********************************************************************/ +/** Microsoft LAN Manager **/ +/** Copyright(c) Microsoft Corp., 1990-1993 **/ +/********************************************************************/ + +/* Stop GNU indent now! */ +/* *INDDENT-OFF* */ + +//** TDISTAT.H - TDI status code definitions. +// +// This file contains the TDI status code definitions. + +#ifndef NT + +#define TDI_SUCCESS 0 // Success +#define TDI_NO_RESOURCES 1 // No resources. +#define TDI_ADDR_IN_USE 2 // Address already in use. +#define TDI_BAD_ADDR 3 // Address given is bad. +#define TDI_NO_FREE_ADDR 4 // No addresses available. +#define TDI_ADDR_INVALID 6 // Address object is invalid. +#define TDI_ADDR_DELETED 7 // Address object was deleted. +#define TDI_BUFFER_OVERFLOW 9 // Buffer overflowed. +#define TDI_BAD_EVENT_TYPE 10 // Bad event type. +#define TDI_BAD_OPTION 11 // Bad option or length. +#define TDI_CONN_REFUSED 14 // Connection was refused. +#define TDI_INVALID_CONNECTION 15 // Invalid connection. +#define TDI_ALREADY_ASSOCIATED 16 // Connection already associated. +#define TDI_NOT_ASSOCIATED 17 // Connection not associated. +#define TDI_CONNECTION_ACTIVE 18 // Connection is still active. +#define TDI_CONNECTION_ABORTED 19 // Connection was aborted. +#define TDI_CONNECTION_RESET 20 // Connection was reset. +#define TDI_TIMED_OUT 21 // Connection timed out. +#define TDI_GRACEFUL_DISC 22 // Received a graceful disconnect. +#define TDI_NOT_ACCEPTED 23 // Data not accepted. +#define TDI_MORE_PROCESSING 24 // More processing required. +#define TDI_INVALID_STATE 25 // TCB in an invalid state. +#define TDI_INVALID_PARAMETER 26 // An invalid parameter. +#define TDI_DEST_NET_UNREACH 27 // Destination net is unreachable. +#define TDI_DEST_HOST_UNREACH 28 // Dest. host is unreachable. +#define TDI_DEST_UNREACHABLE TDI_DEST_HOST_UNREACH +#define TDI_DEST_PROT_UNREACH 29 // Destination protocol is + // unreachable. +#define TDI_DEST_PORT_UNREACH 30 // Dest. port is unreachable. +#define TDI_INVALID_QUERY 31 // Invalid query type specified. +#define TDI_REQ_ABORTED 32 // Request was aborted for some + // reason. +#define TDI_BUFFER_TOO_SMALL 33 // Buffer was too small. +#define TDI_CANCELLED 34 // The request was cancelled. +#define TDI_BUFFER_TOO_BIG 35 // Send buffer was too big. +#define TDI_INVALID_REQUEST 0xfe // Invalid request. +#define TDI_PENDING 0xff // Pending + +#else + +// +// Map to NT STATUS codes. +// +#define TDI_SUCCESS STATUS_SUCCESS +#define TDI_NO_RESOURCES STATUS_INSUFFICIENT_RESOURCES +#define TDI_ADDR_IN_USE STATUS_ADDRESS_ALREADY_EXISTS +#define TDI_BAD_ADDR STATUS_INVALID_ADDRESS_COMPONENT +#define TDI_NO_FREE_ADDR STATUS_TOO_MANY_ADDRESSES +#define TDI_ADDR_INVALID STATUS_INVALID_ADDRESS +#define TDI_ADDR_DELETED STATUS_ADDRESS_CLOSED +#define TDI_BUFFER_OVERFLOW STATUS_BUFFER_OVERFLOW +#define TDI_BAD_EVENT_TYPE STATUS_INVALID_PARAMETER +#define TDI_BAD_OPTION STATUS_INVALID_PARAMETER +#define TDI_CONN_REFUSED STATUS_CONNECTION_REFUSED +#define TDI_INVALID_CONNECTION STATUS_CONNECTION_INVALID +#define TDI_ALREADY_ASSOCIATED STATUS_ADDRESS_ALREADY_ASSOCIATED +#define TDI_NOT_ASSOCIATED STATUS_ADDRESS_NOT_ASSOCIATED +#define TDI_CONNECTION_ACTIVE STATUS_CONNECTION_ACTIVE +#define TDI_CONNECTION_ABORTED STATUS_CONNECTION_ABORTED +#define TDI_CONNECTION_RESET STATUS_CONNECTION_RESET +#define TDI_TIMED_OUT STATUS_IO_TIMEOUT +#define TDI_GRACEFUL_DISC STATUS_GRACEFUL_DISCONNECT +#define TDI_NOT_ACCEPTED STATUS_DATA_NOT_ACCEPTED +#define TDI_MORE_PROCESSING STATUS_MORE_PROCESSING_REQUIRED +#define TDI_INVALID_STATE STATUS_INVALID_DEVICE_STATE +#define TDI_INVALID_PARAMETER STATUS_INVALID_PARAMETER +#define TDI_DEST_NET_UNREACH STATUS_NETWORK_UNREACHABLE +#define TDI_DEST_HOST_UNREACH STATUS_HOST_UNREACHABLE +#define TDI_DEST_UNREACHABLE TDI_DEST_HOST_UNREACH +#define TDI_DEST_PROT_UNREACH STATUS_PROTOCOL_UNREACHABLE +#define TDI_DEST_PORT_UNREACH STATUS_PORT_UNREACHABLE +#define TDI_INVALID_QUERY STATUS_INVALID_DEVICE_REQUEST +#define TDI_REQ_ABORTED STATUS_REQUEST_ABORTED +#define TDI_BUFFER_TOO_SMALL STATUS_BUFFER_TOO_SMALL +#define TDI_CANCELLED STATUS_CANCELLED +#define TDI_BUFFER_TOO_BIG STATUS_INVALID_BUFFER_SIZE +#define TDI_INVALID_REQUEST STATUS_INVALID_DEVICE_REQUEST +#define TDI_PENDING STATUS_PENDING + +#endif // NT + +#define TDI_OPTION_EOL 0 + +#define TDI_ADDRESS_OPTION_REUSE 1 +#define TDI_ADDRESS_OPTION_DHCP 2 diff --git a/src/libc/posix/socket/csock/vxd.S b/src/libc/posix/socket/csock/vxd.S new file mode 100644 index 00000000..31cb50c4 --- /dev/null +++ b/src/libc/posix/socket/csock/vxd.S @@ -0,0 +1,37 @@ +#include +#define USE_EBX +#define USE_EAX +#define USE_EDI +#define USE_ESI + +.data + +.global _csock_entry +_csock_entry: +csock_entry_ip: .long 0 +csock_entry_cs: .long 0 + +.text + +FUNC(_VxdGetEntry) + ENTER + + movl ARG1, %ebx + movl $0x1684, %eax + xorl %edi, %edi + push %es + movl %edi, %es + int $0x2f + movl %es, %ebx + pop %es + jc 1f + testl %ebx, %ebx + jz 1f + movl %ebx, csock_entry_cs + movl %edi, csock_entry_ip + xorl %eax, %eax // Clear EAX (set it to 0) on success +2: + LEAVE +1: + movl $-1, %eax + jmp 2b diff --git a/src/libc/posix/socket/dnsaddr.c b/src/libc/posix/socket/dnsaddr.c new file mode 100644 index 00000000..f3c749bf --- /dev/null +++ b/src/libc/posix/socket/dnsaddr.c @@ -0,0 +1,249 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * dnsaddr.c + * + * This code obtains the DNS server's IP address from the interface data + * and resolv.conf. + */ + +/* Include files */ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +/* Globals */ +extern LSCK_IF *__lsck_interface[LSCK_MAX_IF + 1]; + +/* ---------------------------------- + * - __lsck_resolv_conf_getdnsaddrs - + * ---------------------------------- */ + +/* This reads the DNS addresses from resolv.conf and places them in a + * NULL-terminated list. */ + +static char **__lsck_resolv_conf_getdnsaddrs (void) +{ + struct in_addr testaddr; + char buf[256]; + char resolv_conf[PATH_MAX]; + char *cfg = __lsck_config_getfile(); + char **dnsaddrs = NULL; + FILE *fp = NULL; + char *p = NULL; + char *q = NULL; + int count = 0; + int i; + + /* Find resolv.conf */ + if (cfg == NULL) return(NULL); + GetPrivateProfileString("main", "resolv.conf", NULL, + resolv_conf, sizeof(resolv_conf), cfg); + + fp = fopen(resolv_conf, "rt"); + if (fp == NULL) return(NULL); + + /* Allocate memory - max is MAXNS domain names in resolv.conf */ + dnsaddrs = (char **) malloc((MAXNS + 1) * sizeof(char *)); + if (dnsaddrs == NULL) { + /* TODO: Debug message? */ + fclose(fp); + return(NULL); + } + + for (i = 0; i <= MAXNS; i++) { dnsaddrs[i] = NULL; } + + /* Parse the file to find nameserver keys. */ + while (fgets(buf, sizeof(buf), fp) != NULL) { + p = buf; + while (isspace(*p)) { p++; } + if (*p == '#') continue; + + /* nameserver line? Only one IP address is allowed per + * line. */ + if (strncmp(p, "nameserver", strlen("nameserver")) != 0) + continue; + + p += strlen("nameserver"); + if (!isspace(*p)) continue; + + /* Skip all the spaces */ + while (isspace(*p)) { p++; } + + /* Nuke non-numeric or dots characters in the address. */ + q = p; + while (isdigit(*q) || (*q == '.')) { q++; } + *q = '\0'; + + /* Is this a valid address? */ + if (inet_aton(p, &testaddr) == 0) continue; + dnsaddrs[count] = strdup(p); + } + + fclose(fp); + return(dnsaddrs); +} + +/* --------------------- + * - __lsck_getdnsaddr - + * --------------------- */ + +char *__lsck_getdnsaddr (void) +{ + char **dnsaddrs = NULL, *dnsaddr = NULL; + char **p; + + /* Get all addresses, but only return first */ + p = dnsaddrs = __lsck_getdnsaddrs (); + + if (dnsaddrs == NULL) + return (NULL); + + if (*dnsaddrs == NULL) { + free(dnsaddrs); + return(NULL); + } + + /* This is the only one we want */ + dnsaddr = *dnsaddrs; + + /* Free all the unused memory */ + for (p++; *p != NULL; p++) { free (*p); } + free (dnsaddrs); + + /* Return the IP address */ + return (dnsaddr); +} + +/* ------------- + * - strinlist - + * ------------- */ + +/* This function checks to see if the string 'str' is anywhere in 'list', e.g. + * for finding duplicate entries. */ +#if 0 +int strinlist (char **list, char *str) +{ + int i; + + for (i = 0; list[i] != NULL; i++) { + /* Found match */ + if (strcmp (list[i], str) == 0) + return (1); + } + + /* No match */ + return (0); +} +#endif +/* ---------------------- + * - __lsck_getdnsaddrs - + * ---------------------- */ + +/* This goes through the list of interfaces extracting DNS IP data and + * compiles them into a list. The DNS's are stored in order of occurrence. */ + +char **__lsck_getdnsaddrs (void) +{ + LSCK_IF *interface = NULL; + LSCK_IF_ADDR_INET *inet = NULL; + char **resolv_conf_dnsaddrs = NULL; + char **dnsaddrs = NULL; + int i, j, k, count; + + /* Get all the DNS addresses. */ + count = 0; + + resolv_conf_dnsaddrs = __lsck_resolv_conf_getdnsaddrs(); + if (resolv_conf_dnsaddrs != NULL) { + for (i = 0; resolv_conf_dnsaddrs[i] != NULL; count++, i++) { ; } + } + + for (i = 0; (interface = __lsck_interface[i]) != NULL; i++) { + if (interface->addr == NULL) + continue; + if (interface->addr->family != AF_INET) + continue; + + for (j = 0; (inet = interface->addr->table.inet[j]) != NULL; j++) { + for (k = 0; k < LSCK_IF_ADDR_INET_DNS_MAX; k++) { + if (inet->dns[k].s_addr == 0) + break; + count++; + } + } + } + + dnsaddrs = malloc (sizeof (char *) * (count + 1)); + if (dnsaddrs == NULL) + return (NULL); + + for (i = 0; i < count + 1; i++) { dnsaddrs[i] = NULL; } + count = 0; + + if (resolv_conf_dnsaddrs != NULL) { + for (i = 0; resolv_conf_dnsaddrs[i] != NULL; count++, i++) { + dnsaddrs[count] = strdup(resolv_conf_dnsaddrs[i]); + } + } + + for (i = 0; (interface = __lsck_interface[i]) != NULL; i++) { + if (interface->addr == NULL) + continue; + if (interface->addr->family != AF_INET) + continue; + + for (j = 0; (inet = interface->addr->table.inet[j]) != NULL; j++) { + for (k = 0; k < LSCK_IF_ADDR_INET_DNS_MAX; k++) { + if (inet->dns[k].s_addr == 0) + break; + dnsaddrs[count] = strdup(inet_ntoa(inet->dns[k])); + count++; + } + } + } + + /* Free the resolv.conf structures */ + if (resolv_conf_dnsaddrs != NULL) { + for (i = 0; resolv_conf_dnsaddrs[i] != NULL; i++) { + free(resolv_conf_dnsaddrs[i]); + } + } + free(resolv_conf_dnsaddrs); + + /* Done */ + return (dnsaddrs); +} diff --git a/src/libc/posix/socket/fcntl.c b/src/libc/posix/socket/fcntl.c new file mode 100644 index 00000000..a19ad702 --- /dev/null +++ b/src/libc/posix/socket/fcntl.c @@ -0,0 +1,115 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +#include +#include + +int fcntlsocket_emulated (LSCK_SOCKET * lsd, int command, int request); + +/* --------------- + * - fcntlsocket - + * --------------- */ + +int fcntlsocket (int s, int command, int request) +{ + LSCK_SOCKET *lsd; + int handled = 0; /* Set if the interface handled the request. */ + int ret, rv; + + /* Find the socket descriptor */ + lsd = __fd_to_lsd (s); + + if (lsd == NULL) { + isfdtype(s, S_IFSOCK); + return (-1); + } + + /* Check for completion of outstanding non-blocking I/O */ + if (lsd->interface->nonblocking_check != NULL) + lsd->interface->nonblocking_check (lsd); + + /* Process the command appropriately */ + if (lsd->interface->fcntl != NULL) { + /* If the fcntl is not supported by the interface, this should + * return 0, so it can be emulated. */ + handled = lsd->interface->fcntl(lsd, &rv, command, request); + } + + /* Try to emulate it if the call failed */ + if (!handled) + ret = fcntlsocket_emulated (lsd, command, request); + else + ret = rv; + + /* TODO: The flags from F_GETFL should be as used by open(). However, + * the socket is created using socket(), so some "reasonable" flags + * should probably be OR'd into ret here. */ + + return (ret); +} + +/* ------------------------ + * - fcntlsocket_emulated - + * ------------------------ */ + +int fcntlsocket_emulated (LSCK_SOCKET *lsd, int command, int request) +{ + int ret = -1; + + switch (request) { + /* F_GETOWN, F_SETOWN are needed to implement SIGURG support. + * See fcntl(2) for details. */ + + case F_GETOWN: + ret = lsd->urgent_pid; + break; + + case F_SETOWN: + /* DJGPP's libc can only send signals to current process at the + * moment, so F_SETOWN is meaningless unless the pid refers to + * the current process / process group (of 1 process). */ + if ((request != getpid ()) + && (request != -getpid ())) { + /* TODO: Is this the correct error? */ + errno = EPERM; + } else { + lsd->urgent_pid = request; + ret = 0; + } + break; + + default: + errno = EINVAL; + break; + } + + return (ret); +} diff --git a/src/libc/posix/socket/fsext.c b/src/libc/posix/socket/fsext.c new file mode 100644 index 00000000..e8969b30 --- /dev/null +++ b/src/libc/posix/socket/fsext.c @@ -0,0 +1,282 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * fsext.c + * + * File system extensions for treating sockets like ordinary file descriptors. + * Moved here by Rich Dawe from Indrek Mandre's socket.c. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +/* RD: If this returns 1, it informs DJGPP that it emulated the required + * file system function. The actual return value is stored in rv. */ + +/* ----------------------- + * - __lsck_socket_fsext - + * ----------------------- */ + +int __lsck_socket_fsext (__FSEXT_Fnumber func_number, int *rv, va_list args) +{ + int s; + void *data; + int count; + int t = 0, r = 0, selectsocket_err = 0; + int req; + int *ioctl_comm; + int fcntl_comm; + struct stat *st; + + s = va_arg (args, int); + + switch (func_number) { + case __FSEXT_read: + data = va_arg (args, void *); + count = va_arg (args, int); + + /* RD: Non-blocking I/O should return 0 if no bytes were read, + * and set errno to EAGAIN! */ + *rv = recv (s, data, count, 0); + + if ((*rv == -1) && (errno == EWOULDBLOCK)) { + *rv = 0; + errno = EAGAIN; + } + return(1); + + case __FSEXT_write: + data = va_arg (args, void *); + count = va_arg (args, int); + + /* RD: Try and fix write'ing in the same way as read'ing - I + * don't know whether send() via WSOCK.VXD will ever return + * the blocking I/O error, but this should cope with it. */ + *rv = send (s, data, count, 0); + + if ((*rv == -1) && (errno = EWOULDBLOCK)) { + *rv = 0; + errno = EAGAIN; + } + return(1); + + case __FSEXT_ready: + /* + * RD: Removed |FD_ACCEPT from first selectsocket() call. + * + * Also removed 'else if ( t <= 0 ) r |= __FSEXT_ready_error;' + * from the 'if (t > 0)'. The code now detects a failure in + * selectsocket() & returns an error. Previously it would just + * signal that the socket had an error, which is misleading and + * also not often checked by programs using select(). + */ + + /* TODO: Fix this code properly. The problem is that FD_ACCEPT, + * etc. are not well handled by each interface function. This + * could probably be fixed. */ + + t = selectsocket (s, FD_READ); /* Ready for reading? */ + if (t > 0) + r |= __FSEXT_ready_read; + else if (t == -1) + selectsocket_err = 1; + + t = selectsocket (s, FD_WRITE); /* Ready for writing? */ + if (t > 0) + r |= __FSEXT_ready_write; + else if (t == -1) + selectsocket_err = 1; + + /* RD: Error condition on socket? */ + t = selectsocket (s, ~(FD_READ | FD_WRITE)); /* Dodgy? */ + if (t > 0) + r |= __FSEXT_ready_error; + else if (t == -1) + selectsocket_err = 1; + + *rv = selectsocket_err ? -1 : r; + /*return r?r:8; *//* IM: Must I here return the value? */ + /* RD: No, just non-zero, so the FS extensions know we handled + * it. */ + return(1); + + case __FSEXT_close: + *rv = closesocket(s); + if (*rv == 0) { + __FSEXT_set_function(s, NULL); + __FSEXT_set_data(s, NULL); + _close(s); + } + return(1); + + case __FSEXT_ioctl: + req = va_arg (args, int); + ioctl_comm = va_arg(args, int *); + + *rv = ioctlsocket (s, req, ioctl_comm); + return(1); + + case __FSEXT_fcntl: + fcntl_comm = va_arg (args, int); + + switch(fcntl_comm) { + /* Set flags */ + case F_SETFL: + req = va_arg(args, int); + *rv = fcntlsocket(s, fcntl_comm, req); + break; + + /* Get flags */ + case F_GETFL: + *rv = fcntlsocket(s, fcntl_comm, 0); + break; + + /* Set owner - for SIGURG support */ + case F_SETOWN: + req = va_arg(args, int); + *rv = fcntlsocket(s, fcntl_comm, req); + break; + + /* Get owner - for SIGURG support */ + case F_GETOWN: + *rv = fcntlsocket(s, fcntl_comm, 0); + break; + + /* Unsupported command */ + default: + *rv = -1; + break; + } + + return(1); + + /* lseek() is not supported on sockets - where would you move the + * file pointer to? */ + case __FSEXT_lseek: + errno = ESPIPE; + *rv = -1; + return(1); + break; + + /* fstat() support code was written by Alain Magloire and slightly + * modified by Richard Dawe. Cheers Alain! */ + case __FSEXT_fstat: + st = va_arg(args, struct stat *); + /* most of the fields are irrelevent */ + bzero(st, sizeof(struct stat)); + st->st_mode |= S_IFSOCK; + st->st_atime = st->st_ctime = st->st_mtime = time(0); + *rv = 0; + return(1); + break; + + default: + *rv = -1; + return(1); /* That's better now */ + } + + /* This function hasn't handled the call */ + return(0); +} + +/* ------------------ + * - __fd_is_socket - + * ------------------ */ + +/* This checks whether or not the file descriptor refers to a socket. If the + * file desciptor is a socket, then its File System Extensions handler will + * be set to __lsck_socket_fsext() above. Hence, we check for that. */ + +int __fd_is_socket (int fd) +{ + __FSEXT_Function *f = __FSEXT_get_function (fd); + + if (f == NULL) + return(0); + if (f == __lsck_socket_fsext) + return (1); + else + return(0); +} + +/* ----------------- + * - __fd_is_valid - + * ----------------- */ + +/* This function checks whether the file descriptor is valid. First, it checks + * to see if the fd uses the File System Extensions. If not, it tries an + * ioctl() that will succeed if fd is a normal file descriptor. */ + +int __fd_is_valid (int fd) +{ + int devdata; + __FSEXT_Function *f = __FSEXT_get_function (fd); + + /* fd uses the File System Extension => valid. */ + if (f != NULL) + return(1); + + /* fd is a normal file? This should work for all standard file + * descriptors? */ + if (ioctl (fd, DOS_GETDEVDATA, 2, &devdata) != -1) + return(1); + + /* Failed */ + return(0); +} + +/* ------------ + * - isfdtype - + * ------------ */ + +int isfdtype (int fd, int fd_type) +{ + /* Valid file descriptor? */ + if (!__fd_is_valid (fd)) { + errno = EBADF; + return(-1); + } + /* Socket? */ + if (fd_type == S_IFSOCK) { + if (__fd_is_socket (fd)) + return(1); + else + return(0); + } + /* Some other fd query - unsupported */ + errno = EINVAL; + return(-1); +} diff --git a/src/libc/posix/socket/gprnm.c b/src/libc/posix/socket/gprnm.c new file mode 100644 index 00000000..5169316b --- /dev/null +++ b/src/libc/posix/socket/gprnm.c @@ -0,0 +1,75 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include + +#include + +#include +#include + +/* --------------- + * - getpeername - + * --------------- */ + +int getpeername (int s, struct sockaddr *name, size_t *namelen) +{ + LSCK_SOCKET *lsd; + int ret = -1; /* Fail by default */ + + /* Find the socket descriptor */ + lsd = __fd_to_lsd (s); + + if (lsd == NULL) { + isfdtype(s, S_IFSOCK); + return (-1); + } + + /* Check for completion of outstanding non-blocking I/O */ + if (lsd->interface->nonblocking_check != NULL) + lsd->interface->nonblocking_check (lsd); + + /* Not connected? Only checking this for connection oriented sockets. */ + if ((lsd->type == SOCK_STREAM) && !lsd->connected) { + errno = ENOTCONN; + return (-1); + } + + /* Check the address params */ + if ( (name == NULL) || (namelen == NULL) ) { + errno = EFAULT; + return(-1); + } + + /* Use appropriate interface */ + if (lsd->interface->getpeername == NULL) { + errno = EOPNOTSUPP; + return (-1); + } + ret = lsd->interface->getpeername (lsd, name, namelen); + return (ret); +} diff --git a/src/libc/posix/socket/gscknm.c b/src/libc/posix/socket/gscknm.c new file mode 100644 index 00000000..9052720c --- /dev/null +++ b/src/libc/posix/socket/gscknm.c @@ -0,0 +1,70 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include + +#include + +#include +#include + +/* --------------- + * - getsockname - + * --------------- */ + +int getsockname (int s, struct sockaddr *name, size_t *namelen) +{ + LSCK_SOCKET *lsd; + int ret = -1; /* Fail by default */ + + /* Find the socket descriptor */ + lsd = __fd_to_lsd (s); + + if (lsd == NULL) { + isfdtype(s, S_IFSOCK); + return (-1); + } + + /* Check for completion of outstanding non-blocking I/O */ + if (lsd->interface->nonblocking_check != NULL) + lsd->interface->nonblocking_check (lsd); + + /* Check the address params */ + if ( (name == NULL) || (namelen == NULL) ) { + errno = EFAULT; + return(-1); + } + + /* Use the appropriate interface */ + if (lsd->interface->getsockname == NULL) { + errno = EOPNOTSUPP; + return (-1); + } + + ret = lsd->interface->getsockname (lsd, name, namelen); + return (ret); +} diff --git a/src/libc/posix/socket/hstnm.c b/src/libc/posix/socket/hstnm.c new file mode 100644 index 00000000..65c5251f --- /dev/null +++ b/src/libc/posix/socket/hstnm.c @@ -0,0 +1,268 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* hostname.c - Network-aware host, node and domain name functions. */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include /* .ini and .cfg functions */ + +static char hostname[MAXGETHOSTNAME]; +static char nodename[MAXGETHOSTNAME]; +static char domainname[MAXGETHOSTNAME]; +static int gothostname = 0; +static int gotnodename = 0; +static int gotdomainname = 0; + +extern LSCK_IF *__lsck_interface[LSCK_MAX_IF + 1]; + +int __old_djgpp_libc_gethostname (char *buf, int size); + +/* --------------- + * - gethostname - + * --------------- */ +#if 0 +int gethostname (char *buf, int size) +{ + LSCK_IF *interface = NULL; + LSCK_IF_ADDR_INET *inet = NULL; + char *p = NULL, *q = NULL; + int i, j; + int ret; + + /* Check the size is valid */ + if (size <= 0) { + errno = EINVAL; + return (-1); + } + + /* Check that buf is valid */ + if (buf == NULL) { + errno = EINVAL; + return (-1); + } + + /* Try to get the host name. Try to obtain it from the following + * sources: + * + * 1. from the HOSTNAME environment variable, to allow the user to + * override settings; + * + * 2. from the main section of the configuration file; + * + * 3. from the interface data; + * + * 4. from the old DJGPP gethostname() function, which gets 1 or the + * NetBIOS name. + */ + + /* Check if we've already got it */ + if (gothostname) p = strdup(hostname); + if (p == NULL) p = strdup(getenv ("HOSTNAME")); + + if (p == NULL) { + /* Allocate memory */ + p = (char *) malloc (MAXGETHOSTNAME); + if (p == NULL) { + errno = ENOMEM; + return(-1); /* malloc failed */ + } + + /* Get configuration details */ + q = __lsck_config_getfile(); + + if (q != NULL) { + ret = GetPrivateProfileString("main", "hostname", NULL, + p, MAXGETHOSTNAME, q); + + /* Host name not present in configuration file */ + if (ret == 0) { + free (p); + p = NULL; + } + } else { + free(p); + p = NULL; + } + } + + /* Scan interfaces */ + if (p == NULL) { + for (i = 0; (interface = __lsck_interface[i]) != NULL; i++) { + if (p != NULL) break; + if (interface->addr == NULL) continue; + if (interface->addr->family != AF_INET) continue; + + for (j = 0; + (inet = interface->addr->table.inet[j]) != NULL; + j++) { + if (strlen (inet->hostname) == 0) continue; + p = strdup (inet->hostname); + break; + } + } + } + + /* Failed - try DJGPP gethostname */ + if (p == NULL) { + p = (char *) malloc (MAXGETHOSTNAME); + if (p == NULL) { + errno = ENOMEM; + return(-1); /* malloc failed */ + } + __old_djgpp_libc_gethostname (p, MAXGETHOSTNAME); + } + + /* Don't allow spaces in the host name! Terminate the string at the + * first one found. Also, lower case the whole string. */ + q = strchr (p, ' '); + if (q != NULL) *q = '\0'; + strlwr (p); + + /* Copy the host name */ + if (((int)strlen (p) + 1) > size) { + /* Not enough space! */ + errno = EINVAL; + return (-1); + } + strcpy (buf, p); + + /* Save a local copy of the host, node and domain names. */ + strcpy(hostname, p); + gothostname = 1; + + strcpy(nodename, p); + gotnodename = 1; + + q = strchr(nodename, '.'); + if (q != NULL) { + *q = '\0'; + q++; + strcpy(domainname, q); + gotdomainname = 1; + } + + /* Done */ + free (p); + return (0); +} +#endif + +/* --------------- + * - sethostname - + * --------------- */ + +int sethostname (char *buf, int size) +{ + char *q = NULL; + + /* Check the size is valid */ + if ((size <= 0) || (size > MAXGETHOSTNAME)) { + errno = EINVAL; + return (-1); + } + + /* Set the host name */ + strcpy (hostname, buf); + gothostname = 1; + + strcpy(nodename, buf); + gotnodename = 1; + + q = strchr(nodename, '.'); + if (q != NULL) { + *q = '\0'; + q++; + strcpy(domainname, q); + gotdomainname = 1; + } + + /* OK */ + return (0); +} + +/* ----------------- + * - getdomainname - + * ----------------- */ + +int getdomainname (char *name, size_t len) +{ + /* TODO: I don't think the upper bound is right? */ + /* Fail automatically if len <= 0 or len >= MAXGETDOMAINNAME */ + if ((len <= 0) || (len > MAXGETDOMAINNAME)) { + errno = EINVAL; + return (-1); + } + + /* Check the buffer is valid */ + if (name == NULL) { + errno = EFAULT; + return (-1); + } + + /* OK */ + if (gotdomainname) strcpy(name, domainname); else name[0] = '\0'; + return(0); +} + +/* ----------------- + * - setdomainname - + * ----------------- */ + +int setdomainname (const char *name, size_t len) +{ + /* Fail automatically if len <= 0 or len >= MAXGETDOMAINNAME */ + if ((len <= 0) || (len > MAXGETDOMAINNAME)) { + errno = EINVAL; + return (-1); + } + + /* Check the buffer is valid */ + if (name == NULL) { + errno = EFAULT; + return (-1); + } + + /* Store the domain name & rebuild the host name. */ + strcpy(domainname, name); + gotdomainname = 1; + + strcpy(hostname, nodename); + strcat(hostname, "."); + strcat(hostname, domainname); + gothostname = 1; + + /* OK */ + return(0); +} diff --git a/src/libc/posix/socket/if.c b/src/libc/posix/socket/if.c new file mode 100644 index 00000000..c1f30160 --- /dev/null +++ b/src/libc/posix/socket/if.c @@ -0,0 +1,141 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include + +#include +#include + +extern LSCK_IF *__lsck_interface[LSCK_MAX_IF + 1]; +static struct if_nameindex __lsck_if_nameindex[LSCK_MAX_IF + 1]; + +/* ---------------------- + * - build_if_nameindex - + * ---------------------- */ + +static int build_if_nameindex (void) +{ + static int built_if_nameindex = 0; + int i, count; + + /* Already done it */ + if (built_if_nameindex) + return (built_if_nameindex); + + /* Use the existing interface data */ + for (count = i = 0; i <= LSCK_MAX_IF; i++) { + if (__lsck_interface[i] == NULL) + continue; + + __lsck_if_nameindex[count].if_index = count + 1; + __lsck_if_nameindex[count].if_name = __lsck_interface[i]->name; + count++; + } + + __lsck_if_nameindex[count].if_index = 0; + __lsck_if_nameindex[count].if_name = NULL; + + built_if_nameindex = 1; + return (built_if_nameindex); +} + +/* ------------------ + * - if_nametoindex - + * ------------------ */ + +unsigned int if_nametoindex (const char *ifname) +{ + int i; + + /* Valid param? */ + if (ifname == NULL) { + errno = EFAULT; + return(-1); /* TODO: Is this correct */ + } + + /* Build the interface name-index list */ + if (!build_if_nameindex ()) + return (0); + + for (i = 0; __lsck_if_nameindex[i].if_name != NULL; i++) { + if (strcmp (__lsck_if_nameindex[i].if_name, ifname) == 0) + return (__lsck_if_nameindex[i].if_index); + } + + /* Not found */ + return (0); +} + +/* ------------------ + * - if_indextoname - + * ------------------ */ + +char *if_indextoname (unsigned int ifindex, char *ifname) +{ + int i; + + /* Unable to get the interface list */ + if (!build_if_nameindex ()) { + errno = ENXIO; + return (NULL); + } + /* Find the interface */ + for (i = 0; __lsck_if_nameindex[i].if_index != 0; i++) { + if (__lsck_if_nameindex[i].if_index == ifindex) { + strcpy (ifname, __lsck_if_nameindex[i].if_name); + return (ifname); + } + } + + /* No match */ + errno = ENXIO; + return (NULL); +} + +/* ---------------- + * - if_nameindex - + * ---------------- */ + +struct if_nameindex *if_nameindex (void) +{ + if (!build_if_nameindex ()) { + errno = ENOBUFS; + return (NULL); + } + return (__lsck_if_nameindex); +} + +/* -------------------- + * - if_freenameindex - + * -------------------- */ + +/* This doesn't actually do anything. Since no memory was allocated to + * perform the if_nameindex() call, a free isn't needed. */ + +void if_freenameindex (struct if_nameindex *ptr) +{; +} diff --git a/src/libc/posix/socket/inet/bresvpt.c b/src/libc/posix/socket/inet/bresvpt.c new file mode 100644 index 00000000..16c4735c --- /dev/null +++ b/src/libc/posix/socket/inet/bresvpt.c @@ -0,0 +1,81 @@ +/* +static char sccsid[] = "@(#)bindresvport.c 2.2 88/07/29 4.0 RPCSRC 1.8 88/02/08 SMI"; + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * Copyright (c) 1987 by Sun Microsystems, Inc. + */ + +#include +#include +#include +#include + +/* RD: inetprivate.h -> i_priv.h */ +#include "i_priv.h" + +/* + * Bind a socket to a privileged IP port + */ +int bindresvport(sd, sin) + int sd; + struct sockaddr_in *sin; +{ + int res; + static short port; + struct sockaddr_in myaddr; + int i; + +#define STARTPORT 600 +#define ENDPORT (IPPORT_RESERVED - 1) +#define NPORTS (ENDPORT - STARTPORT + 1) + + if (sin == (struct sockaddr_in *)0) { + sin = &myaddr; + bzero(sin, sizeof (*sin)); + sin->sin_family = AF_INET; + } else if (sin->sin_family != AF_INET) { + errno = EPFNOSUPPORT; + return (-1); + } + if (port == 0) { + port = (getpid() % NPORTS) + STARTPORT; + } + res = -1; + errno = EADDRINUSE; + for (i = 0; i < NPORTS && res < 0 && errno == EADDRINUSE; i++) { + sin->sin_port = htons(port++); + if (port > ENDPORT) { + port = STARTPORT; + } + res = bind(sd, (struct sockaddr *) sin, + sizeof(struct sockaddr_in)); + } + return (res); +} diff --git a/src/libc/posix/socket/inet/gaddrinf.c b/src/libc/posix/socket/inet/gaddrinf.c new file mode 100644 index 00000000..8a541391 --- /dev/null +++ b/src/libc/posix/socket/inet/gaddrinf.c @@ -0,0 +1,52 @@ +/* + * dj64 - 64bit djgpp-compatible tool-chain + * Copyright (C) 2021-2025 @stsp + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +#include +#include +#include +#include +#include +#include + +/* minimal getaddrinfo() */ + +int getaddrinfo(const char *restrict host, const char *restrict serv, + const struct addrinfo *restrict hint, struct addrinfo **restrict res) +{ + struct addrinfo *ret = malloc(sizeof(*ret)); + struct sockaddr_in *sin = (struct sockaddr_in *)ret->ai_addr; + struct hostent *h = gethostbyname(host); + + if (!h) + return -1; + ret->ai_flags = 0; + ret->ai_family = AF_INET; + ret->ai_socktype = SOCK_STREAM; + ret->ai_protocol = IPPROTO_TCP; + ret->ai_addrlen = sizeof(struct sockaddr_in); + sin->sin_addr.s_addr = inet_addr(h->h_addr); + ret->ai_canonname = strdup(h->h_name); + ret->ai_next = NULL; + *res = ret; + return 0; +} + +void freeaddrinfo(struct addrinfo *res) +{ + free(res->ai_canonname); + free(res); +} diff --git a/src/libc/posix/socket/inet/ghstnmad.c b/src/libc/posix/socket/inet/ghstnmad.c new file mode 100644 index 00000000..232831c6 --- /dev/null +++ b/src/libc/posix/socket/inet/ghstnmad.c @@ -0,0 +1,1655 @@ +/* + * Copyright (c) 1985, 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University 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 WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* RD: Modifications by Richard Dawe for the libsocket project. Modifications + marked with 'RD' comments like this one. */ + +#include "i_priv.h" /* RD: inetprivate.h -> i_priv.h */ + +#include +#include +#include + +#include +#include +#include + +#include /* RD: For PATH_MAX */ +#include /* RD: Use configuration routines */ +#include /* RD: Use modified registry-based gethostname */ +#include /* RD: .ini and .cfg routines */ + +#if defined(USE_OPTIONS_H) +# include "r_opts.h" /* RD: res_options.h -> r_opts.h */ +#endif + +#define MAXALIASES 35 +#define MAXADDRS 35 +#define MAXTRIMDOMAINS 4 + +/* IM: #define _PATH_HOSTCONF __PATH_ETC_INET"/host.conf" */ + +/* Strict but flexible checking in _PATH_HOSTCONF file. + + * (+) Keywords need not start at the begining of the line. + * (+) Invalid keywords are warned. + * (+) Invalid booleans (other than "on" or "off") are warned. + + * Mitch DSouza - 30th October 1993 + */ +#define STRICT + +#define SERVICE_NONE 0 +#define SERVICE_BIND 1 +#define SERVICE_HOSTS 2 +#define SERVICE_NIS 3 +#define SERVICE_MAX 3 + +#define CMD_ORDER "order" +#define CMD_TRIMDOMAIN "trim" +#define CMD_HMA "multi" +#define CMD_SPOOF "nospoof" +#define CMD_SPOOFALERT "alert" +#define CMD_REORDER "reorder" +#define CMD_ON "on" +#define CMD_OFF "off" +#define CMD_WARN "warn" +#define CMD_NOWARN "warn off" + +#define ORD_BIND "bind" +#define ORD_HOSTS "hosts" +#define ORD_NIS "nis" + +#define ENV_HOSTCONF "RESOLV_HOST_CONF" +#define ENV_SERVORDER "RESOLV_SERV_ORDER" +#define ENV_SPOOF "RESOLV_SPOOF_CHECK" +#define ENV_TRIM_OVERR "RESOLV_OVERRIDE_TRIM_DOMAINS" +#define ENV_TRIM_ADD "RESOLV_ADD_TRIM_DOMAINS" +#define ENV_HMA "RESOLV_MULTI" +#define ENV_REORDER "RESOLV_REORDER" + +#define TOKEN_SEPARATORS " ,;:" + +static int service_order[SERVICE_MAX + 1]; +static int service_done = 0; + +static const char AskedForGot[] = + "gethostby*.getanswer: asked for \"%s\", got \"%s\""; + +static char *h_addr_ptrs[MAXADDRS + 1]; + +static struct hostent host; +static char *host_aliases[MAXALIASES]; +static char hostbuf[BUFSIZ+1]; +static struct in_addr host_addr; +static char HOSTDB[PATH_MAX]; /* RD: Don't need 1K for this! */ +static FILE *hostf = NULL; +static char hostaddr[MAXADDRS]; +static char *host_addrs[2]; +static int stayopen = 0; +static int hosts_multiple_addrs = 0; +static int spoof = 0; +static int spoofalert = 0; +static int reorder = 0; +static char *trimdomain[MAXTRIMDOMAINS]; +static char trimdomainbuf[BUFSIZ]; +static int numtrimdomains = 0; +#ifdef NIS +static struct hostent *_getnishost __P((char *, char*)); +#endif + +#ifdef RESOLVSORT +static void addrsort __P((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 { + long al; + char ac; +} align; + +#if NLS +#include "nl_types.h" +#endif + +extern char *__libc_secure_getenv(const char *); + +extern int yp_match (char *, char *, char *, int, char **, int *); +extern int yp_first (char *, char *, char **, int *, char **, int *); +extern int yp_next (char *, char *, char *, int, char **, + int *, char **, int *); +extern int yp_get_default_domain (char **); + +struct hostent *_gethtbyaddr(const char *, int, int ); +struct hostent *_gethtbyname( const char * ); +struct hostent *_gethtent( void ); +void _endhtent( void ); +void _sethtent( int ); +struct hostent *gethostbyaddr(const char *, int, int ); +struct hostent *gethostbyname(const char *); +struct hostent *gethostent( void ); +static struct hostent *getanswer( const querybuf *, int, + const char *, int, int ); +static void init_services( void ); +static void reorder_addrs( struct hostent * ); +static struct hostent *trim_domains( struct hostent * ); +static void dotrimdomain( char * ); + +static void +dotrimdomain( char *c ) +{ +#if 0 + /* assume c points to the start of a host name; trim off any + domain name matching any of the trimdomains */ + int d,l1,l2; + + for(d=0;dl1 && !strcasecmp(c+l2-l1,trimdomain[d])) + *(c+(strlen(c)-l1))='\0'; + } +#endif +} + +static struct hostent * +trim_domains( struct hostent *h ) +{ +#if 0 + if(numtrimdomains){ + int i; + dotrimdomain((char *) h->h_name); + for(i=0;h->h_aliases[i];i++) + dotrimdomain(h->h_aliases[i]); + } +#endif + return(h); +} + + +#if NLS +#define bad_config_format(cmd,line) \ + fprintf(stderr, catgets(_libc_cat, NetMiscSet, \ + NetMiscResolvIncorrectFormat, \ + "resolv+: %s:%d: command incorrectly formatted.\n"), \ + hostconf, line); /* for now, don't print cmd */ +#else +#define bad_config_format(cmd,line) \ + fprintf(stderr, "resolv+: %s:%d: command incorrectly formatted.\n", hostconf, line); +#endif + +/* static void debug_breakout(x) +long x; +{ + register int a, b, c, d; + + d = x & 255; x >>= 8; + c = x & 255; x >>= 8; + b = x & 255; x >>= 8; + a = x & 255; x >>= 8; + fprintf(stderr, "resolv+: %d.%d.%d.%d", a,b,c,d ); + + return; +} */ + +/* reorder_addrs -- by Tom Limoncelli + Optimize order of an address list. + + gethostbyaddr() usually returns a list of addresses in some + arbitrary order. Most programs use the first one and throw the + rest away. This routine attempts to find a "best" address and + swap it into the first position in the list. "Best" is defined + as "an address that is on a local subnet". The search ends after + one "best" address is found. If no "best" address is found, + nothing is changed. + + On first execution, a table is built of interfaces, netmasks, + and mask'ed addresses. This is to speed up future queries but + may require you to reboot after changing internet addresses. + (doesn't everyone reboot after changing internet addresses?) + + This routine should not be called if gethostbyaddr() is about + to return only one address. + +*/ + +/* Hal Stern (June 1992) of Sun claimed that more than 4 ethernets in a +Sun 4/690 would not work. This variable is set to 10 to accomodate our +version of reality */ +/* Alan Cox recommends now (Aug 1996) at minimum 64 since it's not unusual to +have about 250 of them... */ +#define MAXINTERFACES (64) + +static void +reorder_addrs( struct hostent *h ) +{ + return; /* IM: the simplest way */ +} + +static void +init_services( void ) +{ + char *cp, *dp, buf[BUFSIZ]; + register int cc = 0; + FILE *fd; + char *tdp = trimdomainbuf; + char *hostconf; + int lineno, errs; + FILE *myfd; /* IM: */ + char *x; + char hostconf_build[1024]; /* RD: Use a better name */ + + /* RD: Use configuration routines now */ + *hostconf_build = '\0'; + x = __lsck_config_getfile(); + if (x != NULL) { + GetPrivateProfileString("main", "host.conf", NULL, + hostconf_build, sizeof(hostconf_build), x); + + /* Diagnostic error message */ + if (__lsck_debug_enabled()) { + if (*hostconf_build == '\0') + fprintf(stderr, + "libsocket: Unable to find host.conf in %s!\n", x); + else + printf("libsocket: Using '%s' as host.conf\n", hostconf_build); + } + } + +#if NLS + libc_nls_init(); +#endif + + /* RD: Environmental override */ + if(NULL==(hostconf=__libc_secure_getenv(ENV_HOSTCONF))){ + hostconf = hostconf_build; + } + + myfd = fopen(hostconf, "rt"); + if (myfd != NULL) { + struct stat sb; + /* Sorry, only world readable files. + * I wouldn't like it to be tricked by smart + * "secure" setuid hackery. */ + if (fstat(fileno(myfd), &sb) || !(sb.st_mode & S_IROTH)) { + fclose(myfd); + myfd = NULL; + } + } + if (myfd == NULL) { + /* RD: I think assuming we have a DNS is a bad idea */ + /* RD: Do we have at least one DNS server? If so, include + * DNS in the default services list. */ + x = __lsck_getdnsaddr(); + + if (x == NULL) { + service_order[0] = SERVICE_HOSTS; + service_order[1] = SERVICE_NONE; + } else { + free(x); + service_order[0] = SERVICE_HOSTS; + service_order[1] = SERVICE_BIND; + service_order[2] = SERVICE_NONE; + } + } else { + fd = myfd; + errs = lineno = 0; + while (fgets(buf, BUFSIZ, fd) != NULL) { + if (errs) { + /* FIXME: NLS */ + fprintf(stderr, "resolv+: errors found, parsing aborted\n"); + break; + } + lineno++; + if ((cp = rindex(buf, '\n')) != NULL) + *cp = '\0'; + if (buf[0] == '#') + continue; + +#ifdef STRICT +#define checkbuf(b, cmd) (!strncasecmp(b, cmd, strlen(cmd)) && \ + (!b[strlen(cmd)] || isspace(b[strlen(cmd)]))) +#else +#define checkbuf(b, cmd) (!strncasecmp(b, cmd, strlen(cmd))) +#endif + + + for (cp=buf; cp && *cp && isspace(*cp); cp++); + if (cp && *cp) { + memmove(buf, cp, strlen(cp) + 1); + if (checkbuf(buf, CMD_ORDER)) { + cp = strpbrk(buf, " \t"); + if (!cp +#ifdef STRICT + || !*(cp+1) +#endif + ) { + errs++; bad_config_format(CMD_ORDER, lineno); + } else { + do { + while (*cp == ' ' || *cp == '\t') + cp++; + dp = strpbrk(cp, TOKEN_SEPARATORS); + if (dp) *dp = '\0'; + if (checkbuf(cp, ORD_BIND)) { + service_order[cc++] = SERVICE_BIND; + if (!(_res.options & RES_INIT)) + res_init(); + } else if (checkbuf(cp, ORD_HOSTS)) + service_order[cc++] = SERVICE_HOSTS; + else if (checkbuf(cp, ORD_NIS)) + service_order[cc++] = SERVICE_NIS; + else { + errs++; bad_config_format(CMD_ORDER, lineno); +#if NLS + fprintf(stderr, catgets(_libc_cat, NetMiscSet, + NetMiscResolvInvalid, + "resolv+: %s:%d: invalid keyword\n"), hostconf, lineno); + fprintf(stderr, catgets(_libc_cat, NetMiscSet, + NetMiscResolvValid, + "resolv+: valid keywords are: %s, %s and %s\n"), + ORD_BIND, ORD_HOSTS, ORD_NIS); +#else + fprintf(stderr, + "resolv+: %s:%d is an invalid keyword\n", hostconf, lineno); + fprintf(stderr, + "resolv+: valid keywords are: %s, %s and %s\n", + ORD_BIND, ORD_HOSTS, ORD_NIS); +#endif + + } + + if (dp) cp = ++dp; + } while (dp != NULL); + if (cc == 0) { + errs++; bad_config_format(CMD_ORDER, lineno); +#if NLS + fprintf(stderr,catgets(_libc_cat, NetMiscSet, + NetMiscUnrecognized, +"resolv+: search order not specified or unrecognized keyword, host resolution will fail.\n")); +#else + fprintf(stderr, +"resolv+: search order not specified or unrecognized keyword, host resolution will fail.\n"); +#endif + } + } + + } else if (checkbuf(buf, CMD_HMA)) { +#ifdef STRICT + +#if NLS +#define check_legal(key,val) { \ + for (cp=strpbrk(buf, " \t"); \ + cp && *cp && isspace(*cp); cp++); \ + if (cp && *cp) {\ + if (strlen(CMD_ON) == strlen(cp) && \ + checkbuf(cp,CMD_ON)) val = 1; \ + else if (strlen(CMD_OFF) == strlen(cp) && \ + checkbuf(cp,CMD_OFF)) val = 0; \ + else { \ + errs++; bad_config_format(key, lineno); \ + fprintf(stderr, catgets(_libc_cat, NetMiscSet, \ + NetMiscResolvInvalid, \ + "resolv+: %s:%d: invalid keyword\n"), hostconf, lineno); \ + } \ + } else { errs++; bad_config_format(key, lineno); } \ + } +#else + +#define check_legal(key,val) { \ + for (cp=strpbrk(buf, " \t"); \ + cp && *cp && isspace(*cp); cp++); \ + if (cp && *cp) { \ + if (strlen(CMD_ON) == strlen(cp) && \ + checkbuf(cp,CMD_ON)) val = 1; \ + else if (strlen(CMD_OFF) == strlen(cp) && \ + checkbuf(cp,CMD_OFF)) val = 0; \ + else { \ + errs++; bad_config_format(key, lineno); \ + fprintf(stderr, "resolv+: %s:%d is an invalid keyword\n", hostconf, lineno); \ + } \ + } else { errs++; bad_config_format(key, lineno); } \ + } +#endif /* NLS */ + check_legal(CMD_HMA,hosts_multiple_addrs); + +#else /* !STRICT */ + if ( cp = strpbrk(buf, " \t") ) { + while (*cp == ' ' || *cp == '\t') cp++; + if (checkbuf(cp, CMD_ON)) + hosts_multiple_addrs = 1; + } else { + errs++; bad_config_format(CMD_HMA, lineno); + } +#endif /* STRICT */ + + } else if (checkbuf(buf, CMD_SPOOF)) { +#ifdef STRICT + check_legal(CMD_SPOOF,spoof); +#else + if ( cp = strpbrk(buf, " \t") ) { + while (*cp == ' ' || *cp == '\t') cp++; + if (checkbuf(cp, CMD_ON)) + spoof = 1; + } else { + errs++; bad_config_format(CMD_SPOOF, lineno); + } +#endif + + + } else if (checkbuf(buf, CMD_SPOOFALERT)) { +#ifdef STRICT + check_legal(CMD_SPOOFALERT,spoofalert); +#else + if ( cp = strpbrk(buf, " \t") ) { + while (*cp == ' ' || *cp == '\t') cp++; + if (checkbuf(cp, CMD_ON)) + spoofalert = 1; + } else { + errs++; bad_config_format(CMD_SPOOFALERT, lineno); + } +#endif + + } else if (checkbuf(buf, CMD_REORDER)) { +#ifdef STRICT + check_legal(CMD_REORDER,reorder); +#else + if (cp = strpbrk(buf, " \t")) { + while (*cp == ' ' || *cp == '\t') cp++; + if (checkbuf(cp, CMD_ON)) + reorder = 1; + } else { + errs++; bad_config_format(CMD_REORDER, lineno); + } +#endif + + } else if (checkbuf(buf, CMD_TRIMDOMAIN)) { + if(numtrimdomainsbuf + anslen; + /* + * find first satisfactory answer + */ + hp = &answer->hdr; + ancount = ntohs(hp->ancount); + qdcount = ntohs(hp->qdcount); + bp = hostbuf; + buflen = sizeof hostbuf; + cp = answer->buf + HFIXEDSZ; + if (qdcount != 1) { + h_errno = NO_RECOVERY; + return (NULL); + } + if ((n = dn_expand(answer->buf, eom, cp, bp, buflen)) < 0) { + h_errno = NO_RECOVERY; + return (NULL); + } +#if NLS + libc_nls_init(); +#endif + cp += n + QFIXEDSZ; + if (qtype == T_A) { + /* 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 = strlen(bp) + 1; /* for the \0 */ + 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; +#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ + host.h_addr_list = h_addr_ptrs; +#endif + haveanswer = 0; + had_error = 0; + while (ancount-- > 0 && cp < eom && !had_error) { + n = dn_expand(answer->buf, eom, cp, bp, buflen); + if (n < 0) { + had_error++; + continue; + } + cp += n; /* name */ + type = _getshort(cp); + cp += INT16SZ; /* type */ + class = _getshort(cp); + cp += INT16SZ + INT32SZ; /* class, TTL */ + n = _getshort(cp); + cp += INT16SZ; /* len */ + if (class != qclass) { + /* XXX - debug? syslog? */ + cp += n; + continue; /* XXX - had_error++ ? */ + } + if (qtype == T_A && type == T_CNAME) { + if (ap >= &host_aliases[MAXALIASES-1]) + continue; + n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); + if (n < 0) { + had_error++; + continue; + } + cp += n; +/* if (host.h_name && strcasecmp(host.h_name, bp) != 0) { + syslog(LOG_NOTICE|LOG_AUTH, +#if NLS + catgets(_libc_cat, NetMiscSet, NetMiscAskedForGotCNAME, + "gethostby*.getanswer: asked for \"%s\", got CNAME for \"%s\""), + +#else + "gethostby*.getanswer: asked for \"%s\", got CNAME for \"%s\"", +#endif + host.h_name, bp); + continue; + } */ + /* Store alias. */ + *ap++ = bp; + n = strlen(bp) + 1; /* for the \0 */ + bp += n; + buflen -= n; + /* Get canonical name. */ + n = strlen(tbuf) + 1; /* for the \0 */ + if (n > buflen) { + had_error++; + continue; + } + strcpy(bp, tbuf); /* cannot overflow */ + 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) { + had_error++; + continue; + } + cp += n; + /* Get canonical name. */ + n = strlen(tbuf) + 1; /* for the \0 */ + if (n > buflen) { + had_error++; + continue; + } + strcpy(bp, tbuf); /* cannot overflow */ +// tname = bp; + bp += n; + buflen -= n; + continue; + } +/* IM: no need if (type != qtype) { + syslog(LOG_NOTICE|LOG_AUTH, +#if NLS + catgets(_libc_cat, NetMiscSet, NetMiscAskedForType, + "gethostby*.getanswer: asked for type %d(%s), got %d(%s)"), +#else + "gethostby*.getanswer: asked for type %d(%s), got %d(%s)", +#endif + qtype, qname, type, bp); + cp += n; + continue; + } */ + switch (type) { + case T_PTR: +/* if (strcasecmp(tname, bp) != 0) { + syslog(LOG_NOTICE|LOG_AUTH, +#if NLS + catgets(_libc_cat, NetMiscSet, NetMiscAskedForGot, AskedForGot), +#else + AskedForGot, +#endif + qname, bp); + cp += n; + continue; + } */ + n = dn_expand(answer->buf, eom, cp, bp, buflen); + if (n < 0) { + had_error++; + break; + } +#if MULTI_PTRS_ARE_ALIASES + cp += n; + if (!haveanswer) + host.h_name = bp; + else if (ap < &host_aliases[MAXALIASES-1]) + *ap++ = bp; + else + n = -1; + if (n != -1) { + n = strlen(bp) + 1; /* for the \0 */ + bp += n; + buflen -= n; + } + break; +#else + host.h_name = bp; + return (&host); +#endif + case T_A: +/* if (strcasecmp(host.h_name, bp) != 0) { + syslog(LOG_NOTICE|LOG_AUTH, +#if NLS + catgets(_libc_cat, NetMiscSet, NetMiscAskedForGot, AskedForGot), +#else + AskedForGot, +#endif + host.h_name, bp); + cp += n; + continue; + } */ + if (haveanswer) { + if (n != host.h_length) { + cp += n; + continue; + } + } else { + register int nn; + + host.h_length = n; + host.h_addrtype = (class == C_IN) + ? AF_INET + : AF_UNSPEC; + host.h_name = bp; + nn = strlen(bp) + 1; /* for the \0 */ + bp += nn; + buflen -= nn; + } + + bp += sizeof(align) - ((u_long)bp % sizeof(align)); + + if (bp + n >= &hostbuf[sizeof hostbuf]) { +#ifdef DEBUG + if (_res.options & RES_DEBUG) + printf("size (%d) too big\n", n); +#endif + had_error++; + continue; + } + if (hap >= &h_addr_ptrs[MAXADDRS-1]) { + if (_res.options & RES_DEBUG && !toobig++) + printf("Too many addresses (%d)\n", + MAXADDRS); + cp += n; + continue; + } + bcopy(cp, *hap++ = bp, n); + bp += n; + cp += n; + break; + default: + abort(); + } /*switch*/ + if (!had_error) + haveanswer++; + } /*while*/ + 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 && + qclass == C_IN && qtype == T_A) + addrsort(h_addr_ptrs, haveanswer); +# endif /*RESOLVSORT*/ +#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ + /* nothing */ +#else + host.h_addr = h_addr_ptrs[0]; +#endif /*BSD*/ + if (!host.h_name) { + n = strlen(qname) + 1; /* for the \0 */ + /* I'm not sure about this one. */ + strcpy(bp, qname); + host.h_name = bp; + } + return (&host); + } else { + h_errno = TRY_AGAIN; + return (NULL); + } +} + +struct hostent * +gethostent( void ) +{ + int cc; + struct hostent *hp; + + if (!service_done) + init_services(); + + for (cc = 0; service_order[cc] != SERVICE_NONE && + cc <= SERVICE_MAX; cc++) + { + switch (service_order[cc]) + { + case SERVICE_BIND: + break; + + case SERVICE_HOSTS: + hp = _gethtent (); + if (h_addr_ptrs[1] && reorder) + reorder_addrs(hp); + if (hp) + { + h_errno = NETDB_SUCCESS; + return hp; + } + h_errno = HOST_NOT_FOUND; + break; + +#ifdef NIS + case SERVICE_NIS: + hp = _getnishost(NULL, "hosts.byname"); + if (h_addr_ptrs[1] && reorder) + reorder_addrs(hp); + if (hp) + { + h_errno = NETDB_SUCCESS; + return hp; + } + h_errno = HOST_NOT_FOUND; + break; +#endif /* NIS */ + + } + } + return ((struct hostent *) NULL); +} + +struct hostent * +gethostbyname(const char *name) +{ + querybuf buf; + const char *cp; + register int cc; + int n; + struct hostent *hp; + + /* + * 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. What if someone types + * 255.255.255.255? The test below will + * succeed spuriously... ??? + */ + if ((host_addr.s_addr = inet_addr(name)) == INADDR_NONE) { + h_errno = HOST_NOT_FOUND; + return((struct hostent *) NULL); + } + host.h_name = name; + host.h_aliases = host_aliases; + host_aliases[0] = NULL; + host.h_addrtype = AF_INET; + host.h_length = sizeof(u_long); + h_addr_ptrs[0] = (char *)&host_addr; + h_addr_ptrs[1] = (char *)0; +#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ + host.h_addr_list = h_addr_ptrs; +#else + host.h_addr = h_addr_ptrs[0]; +#endif + h_errno = NETDB_SUCCESS; + return (&host); + } + if (!isdigit(*cp) && *cp != '.') + break; + } + + if (!service_done) + init_services(); + + for (cc = 0; service_order[cc] != SERVICE_NONE && + cc <= SERVICE_MAX; cc++) { + switch (service_order[cc]) { + case SERVICE_BIND: + if ((n = res_search(name, C_IN, T_A, + buf.buf, sizeof(buf.buf))) < 0) { +#ifdef DEBUG + if (_res.options & RES_DEBUG) + printf("res_search failed\n"); +#endif + break; + } + hp = getanswer(&buf, n, name, C_IN, T_A); + if (h_addr_ptrs[1] && reorder) + reorder_addrs(hp); + if (hp) + { + h_errno = NETDB_SUCCESS; + return trim_domains(hp); + } + break; + case SERVICE_HOSTS: + if (*trimdomain) { + char *p; + p = strdup(name); + dotrimdomain(p); + hp = _gethtbyname(p); + free(p); + } + else + { + hp = _gethtbyname(name); + } + if (h_addr_ptrs[1] && reorder) + reorder_addrs(hp); + if (hp) + { + h_errno = NETDB_SUCCESS; + return trim_domains(hp); + } + h_errno = HOST_NOT_FOUND; + break; +#ifdef NIS + case SERVICE_NIS: + if (*trimdomain) { + char *p; + p = strdup(name); + dotrimdomain(p); + hp = _getnishost(p, "hosts.byname"); + free(p); + } else + hp = _getnishost(name, "hosts.byname"); + if (h_addr_ptrs[1] && reorder) + reorder_addrs(hp); + if (hp) + { + h_errno = NETDB_SUCCESS; + return trim_domains(hp); + } + h_errno = HOST_NOT_FOUND; + break; +#endif /* NIS */ + } + } + return ((struct hostent *) NULL); +} + +struct hostent * +gethostbyaddr(const char *addr, int len, int type) +{ + int n; + querybuf buf; + register int cc; + register struct hostent *hp; + char qbuf[MAXDNAME]; + + if (type != AF_INET) { + h_errno = NETDB_INTERNAL; + return ((struct hostent *) NULL); + } + + if (!service_done) + init_services(); + +#if NLS + libc_nls_init(); +#endif + cc = 0; + while (service_order[cc] != SERVICE_NONE) { + switch (service_order[cc]) { + case SERVICE_BIND: + /* will not overflow */ + (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", + ((unsigned)addr[3] & 0xff), + ((unsigned)addr[2] & 0xff), + ((unsigned)addr[1] & 0xff), + ((unsigned)addr[0] & 0xff)); + n = res_query(qbuf, C_IN, T_PTR, (unsigned char *)&buf, + sizeof(buf)); + if (n < 0) { +#ifdef DEBUG + if (_res.options & RES_DEBUG) + printf("res_query failed\n"); +#endif + break; + } + hp = getanswer(&buf, n, qbuf, C_IN, T_PTR); + if (hp) { + if(spoof){ + /* Spoofing check code by + * Caspar Dik + */ + char nambuf[MAXDNAME+1]; + int ntd, namelen = strlen(hp->h_name); + char **addrs; + + if (namelen >= MAXDNAME) + return (struct hostent *)NULL; + (void) strcpy(nambuf,hp->h_name); + nambuf[namelen] = '.'; + nambuf[namelen+1] = '\0'; + + /* + * turn off domain trimming, + * call gethostbyname(), then turn + * it back on, if applicable. This + * prevents domain trimming from + * making the name comparison fail. + */ + ntd=numtrimdomains; + numtrimdomains=0; + hp=gethostbyname(nambuf); + numtrimdomains=ntd; + nambuf[namelen] = 0; + /* + * the name must exist and the name + * returned by gethostbyaddr must be + * the canonical name and therefore + * identical to the name returned by + * gethostbyname() + */ + if (!hp || strcmp(nambuf, hp->h_name)){ + h_errno = HOST_NOT_FOUND; + return (struct hostent *)NULL; + } + /* + * now check the addresses + */ +#if defined(h_addr) || BSD >= 43 + for (addrs = hp->h_addr_list; + *addrs; addrs++){ + if (!bcmp(addrs[0], addr, len)) + { + h_errno = NETDB_SUCCESS; + return trim_domains(hp); + } + } +#else + if (!bcmp(hp->h_addr, addr, len))) + { + h_errno = NETDB_SUCCESS; + return trim_domains(hp); + } +#endif + /* We've been spoofed */ + h_errno = HOST_NOT_FOUND; +/* if(spoofalert){ + openlog("resolv", LOG_PID, + LOG_AUTH); + syslog(LOG_NOTICE, +#if NLS + catgets(_libc_cat, NetMiscSet, + NetMiscPossibleSpoof, + "gethostbyaddr: %s != %u.%u.%u.%u, possible spoof attempt"), +#else + "gethostbyaddr: %s != %u.%u.%u.%u, possible spoof attempt", +#endif + hp->h_name, + ((unsigned)addr[0]&0xff), + ((unsigned)addr[1]&0xff), + ((unsigned)addr[2]&0xff), + ((unsigned)addr[3]&0xff)); + } */ + return (struct hostent *)NULL; + } + hp->h_addrtype = type; + hp->h_length = len; + h_addr_ptrs[0] = (char *)&host_addr; + h_addr_ptrs[1] = (char *)0; + host_addr = *(const struct in_addr *)addr; +#if BSD < 43 && !defined(h_addr) /* new-style hostent structure */ + hp->h_addr = h_addr_ptrs[0]; +#endif + h_errno = NETDB_SUCCESS; + return trim_domains(hp); + } + h_errno = HOST_NOT_FOUND; + break; + case SERVICE_HOSTS: + hp = _gethtbyaddr(addr, len, type); + if (hp) + { + h_errno = NETDB_SUCCESS; + return hp; + } + h_errno = HOST_NOT_FOUND; + break; +#ifdef NIS + case SERVICE_NIS: + /* won't overflow */ + (void)sprintf(qbuf, "%u.%u.%u.%u", + ((unsigned)addr[0] & 0xff), + ((unsigned)addr[1] & 0xff), + ((unsigned)addr[2] & 0xff), + ((unsigned)addr[3] & 0xff)); + hp = _getnishost(qbuf, "hosts.byaddr"); + if (hp) + { + h_errno = NETDB_SUCCESS; + return hp; + } + h_errno = HOST_NOT_FOUND; + break; +#endif /* NIS */ + } + cc++; + } + return ((struct hostent *)NULL); +} + +void +_sethtent( int f ) +{ + char *x; + + /* RD: Use configuration routines now */ + x = __lsck_config_getfile(); + if (x != NULL) + GetPrivateProfileString("main", "hosts", NULL, + HOSTDB, sizeof(HOSTDB), x); + else + *HOSTDB = '\0'; + + /* + RD: If we can't find the specified file, look in the Windows + directory. + + TODO: Add warning? + */ + if (*HOSTDB == '\0') sprintf(HOSTDB, "%s/hosts", getenv("windir")); + + if (hostf == NULL) { + hostf = fopen(HOSTDB, "rt" ); + + /* RD: Warning message */ + if (hostf == NULL) perror("resolv: Unable to open hosts file"); + } else + rewind(hostf); + stayopen |= f; +} + +void +_endhtent( void ) +{ + if (hostf && !stayopen && !(_res.options & RES_STAYOPEN)) { + (void) fclose(hostf); + hostf = NULL; + } +} + +/* ------------- + - _gethtent - + ------------- */ + +/* RD: Modified this so it doesn't use gotos & is easier to read. */ + +struct hostent *_gethtent (void) +{ + char *p; + register char *cp, **q; + + if ( (hostf == NULL) && (hostf = fopen(HOSTDB, "rt" )) == NULL) { + h_errno = NETDB_INTERNAL; + return (NULL); + } + + /* Read the hosts file line-by-line*/ + while ((p = fgets(hostbuf, BUFSIZ, hostf)) != NULL) { + /* Comment */ + if (*p == '#') continue; + + /* Look for comment/newline and nuke after that point */ + cp = strpbrk(p, "#\n"); + if (cp == NULL) continue; + *cp = '\0'; + + /* Look for whitespace at start and nuke it */ + cp = strpbrk(p, " \t"); + if (cp == NULL) continue; + *cp++ = '\0'; + + /* --- Match --- */ + + /* THIS STUFF IS INTERNET SPECIFIC */ +#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ + host.h_addr_list = host_addrs; +#endif + host.h_addr = hostaddr; + *((u_long *)host.h_addr) = inet_addr(p); + host.h_length = sizeof (u_long); + host.h_addrtype = AF_INET; + + /* Find the host name */ + while (*cp == ' ' || *cp == '\t') cp++; + host.h_name = cp; + + /* Find host aliases */ + q = host.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; + + /* Done successfully */ + h_errno = NETDB_SUCCESS; + return (&host); + } + + /* EOF & no match */ + h_errno = HOST_NOT_FOUND; + return (NULL); +} + +/* End RD */ + +/* if hosts_multiple_addrs set, then gethtbyname behaves as follows: + * - for hosts with multiple addresses, return all addresses, such that + * the first address is most likely to be one on the same net as the + * host we're running on, if one exists. + * - like the dns version of gethostsbyname, the alias field is empty + * unless the name being looked up is an alias itself, at which point the + * alias field contains that name, and the name field contains the primary + * name of the host. Unlike dns, however, this behavior will still take place + * even if the alias applies only to one of the interfaces. + * + * I changed to return aliase list no matter what. H.J. + * + * - determining a "local" address to put first is dependant on the netmask + * being such that the least significant network bit is more significant + * than any host bit. Only strange netmasks will violate this. + * - we assume addresses fit into u_longs. That's quite internet specific. + * - if the host we're running on is not in the host file, the address + * shuffling will not take place. + * - John DiMarco + */ +struct hostent * +_gethtbyname(const char *name) +/* _gethtbyname(const char *name) vch */ +{ + register struct hostent *p; + register char **cp; + char **hap, **lhap, *bp, *lbp; + int htbuflen, locbuflen; + int found=0, localfound=0; + char localname[MAXHOSTNAMELEN]; + + static char htbuf[BUFSIZ+1]; /* buffer for host addresses */ + static char locbuf[BUFSIZ+1]; /* buffer for local hosts's addresses */ + static char *ht_addr_ptrs[MAXADDRS+1]; + static char *loc_addr_ptrs[MAXADDRS+1]; + static struct hostent ht; + static char *aliases[MAXALIASES]; + static char namebuf[MAXHOSTNAMELEN]; + static char aliasebuf[BUFSIZ+1]; + int gap = aliasebuf - hostbuf; + + hap = ht_addr_ptrs; + lhap = loc_addr_ptrs; + *hap = NULL; + *lhap = NULL; + bp=htbuf; + lbp=locbuf; + htbuflen = sizeof(htbuf); + locbuflen = sizeof(locbuf); + + aliases[0]=NULL; + aliases[1]=NULL; + (void) strncpy(namebuf, name, sizeof(namebuf)); + namebuf[sizeof(namebuf)-1] = 0; + + /* RD: Modified registry-based gethostname */ + (void) gethostname(localname, sizeof(localname)); + /* RD: End */ + + _sethtent(0); + while ((p = _gethtent())) { + if (strcasecmp(p->h_name, name) == 0) + found++; + else + for (cp = p->h_aliases; *cp != 0; cp++) + if (strcasecmp(*cp, name) == 0){ + found++; +#if 0 + aliases[0]=name; +#endif + /* + * This should not overflow, but it is + * better to be safe than sorry. + */ + (void) strncpy(namebuf, p->h_name, + sizeof(namebuf)); + namebuf[sizeof(namebuf)-1] = 0; + } + + cp = p->h_aliases; + if (found && aliases[0] == NULL && *cp) + { + unsigned int i; + + memcpy (aliasebuf, hostbuf, sizeof(aliasebuf)); + for (i = 0; *cp != 0 && + i < sizeof (aliases) / sizeof (aliases [0]) - 1; + i++, cp++) + { + aliases [i] = *cp + gap; + } + aliases [i] = NULL; + } + + if (strcasecmp(p->h_name, localname) == 0) + localfound++; + else + for (cp=p->h_aliases; *cp != 0; cp++) + if (strcasecmp(*cp, localname) == 0) + localfound++; + + if(found){ + int n; + + if(!hosts_multiple_addrs){ + /* original behaviour requested */ + _endhtent(); + return(p); + } + n = p->h_length; + + ht.h_addrtype = p->h_addrtype; + ht.h_length = p->h_length; + + if(n<=htbuflen){ + /* add the found address to the list */ + bcopy(p->h_addr_list[0], bp, n); + *hap++=bp; + *hap=NULL; + bp+=n; + htbuflen-=n; + } + found=0; + } + if(localfound){ + int n = p->h_length; + if(n<=locbuflen){ + /* add the found local address to the list */ + bcopy(p->h_addr_list[0], lbp, n); + *lhap++=lbp; + *lhap=NULL; + lbp+=n; + locbuflen-=n; + } + localfound=0; + } + } + _endhtent(); + + if(NULL==ht_addr_ptrs[0]){ + return((struct hostent *)NULL); + } + + ht.h_aliases = aliases; + ht.h_name = namebuf; + + /* shuffle addresses around to ensure one on same net as local host + is first, if exists */ + { + /* "best" address is assumed to be the one with the greatest + number of leftmost bits matching any of the addresses of + the local host. This assumes a netmask in which all net + bits precede host bits. Usually but not always a fair + assumption. */ + + /* portability alert: assumption: iaddr fits in u_long. + This is really internet specific. */ + int i,j, best=0; + u_long bestval = (u_long)~0; + + for(i=0;loc_addr_ptrs[i];i++){ + for(j=0;ht_addr_ptrs[j];j++){ + u_long t, l, h; + /* assert(sizeof(u_long)>=ht.h_length); */ + bcopy(loc_addr_ptrs[i], (char *)&t, + ht.h_length); + l=ntohl(t); + bcopy(ht_addr_ptrs[j], (char *)&h, + ht.h_length); + t=l^h; + + if(t= 43 || defined(h_addr) /* new-style hostent structure */ + h.h_addr_list = host_addrs; +#endif + 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); +} +#endif /* NIS */ + +struct hostent * +_gethtbyaddr(const char *addr, int len, int type) +{ + register struct hostent *p; + + _sethtent(0); + while (( p = _gethtent())) + if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) + break; + _endhtent(); + return (p); +} + +#ifdef RESOLVSORT +static void +addrsort( char **ap, int num ) +{ + int i, j; + char **p; + short aval[MAXADDRS]; + int needsort = 0; + + p = ap; + for (i = 0; i < num; i++, p++) { + for (j = 0 ; 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 diff --git a/src/libc/posix/socket/inet/gnetbyad.c b/src/libc/posix/socket/inet/gnetbyad.c new file mode 100644 index 00000000..0436a403 --- /dev/null +++ b/src/libc/posix/socket/inet/gnetbyad.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University 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 WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include +#include + +extern int _net_stayopen; + +struct netent * +getnetbyaddr(net, type) + register unsigned long net; + register int type; +{ + register struct netent *p; + + setnetent(_net_stayopen); + while ((p = getnetent())) + if (p->n_addrtype == type && p->n_net == net) + break; + if (!_net_stayopen) + endnetent(); + return (p); +} diff --git a/src/libc/posix/socket/inet/gnetbynm.c b/src/libc/posix/socket/inet/gnetbynm.c new file mode 100644 index 00000000..76f603f7 --- /dev/null +++ b/src/libc/posix/socket/inet/gnetbynm.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University 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 WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "i_priv.h" /* RD: inetprivate.h -> i_priv.h */ +#include + +extern int _net_stayopen; + +struct netent *getnetbyname( const char *name) +{ + register struct netent *p; + register char **cp; + + setnetent(_net_stayopen); + while ((p = getnetent())) { + if (strcmp(p->n_name, name) == 0) break; + + for (cp = p->n_aliases; *cp != 0; cp++) + if (strcmp(*cp, name) == 0) goto found; + } + +found: + if (!_net_stayopen) endnetent(); + return (p); +} diff --git a/src/libc/posix/socket/inet/gnetent.c b/src/libc/posix/socket/inet/gnetent.c new file mode 100644 index 00000000..5cb9a77e --- /dev/null +++ b/src/libc/posix/socket/inet/gnetent.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University 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 WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* RD: Some modifications by Richard Dawe for the libsocket project. + Modifications indicated by 'RD' comments like this one. */ + +#include "i_priv.h" /* RD: inetprivate.h -> i_priv.h */ +#include +#include +#include /* RD: Use configuration routines */ +#include /* RD: .ini and .cfg routines */ + +#define MAXALIASES 35 + +static char NETDB[1024]; +static FILE *netf = NULL; +static char line[BUFSIZ+1]; +static struct netent net; +static char *net_aliases[MAXALIASES]; + +int _net_stayopen; + +struct netent *getnetent( void ); +static char *any( register char *, const char * ); +void endnetent( void ); +void setnetent( int f ); + +void +setnetent( int f ) +{ + char *x; + + /* RD: Use configuration routines now */ + x = __lsck_config_getfile(); + if (x != NULL) + GetPrivateProfileString("main", "networks", NULL, + NETDB, sizeof(NETDB), x); + else + *NETDB = '\0'; + + /* + RD: If we can't find the specified file, look in the Windows + directory. + + TODO: Add warning? + */ + if (*NETDB == '\0') sprintf(NETDB, "%s/networks", getenv("windir")); + + if (netf == NULL) { + netf = fopen(NETDB, "rt" ); + + /* RD: Warning message */ + if (netf == NULL) perror("resolv: Unable to open networks file"); + } else + rewind(netf); + _net_stayopen |= f; +} + +void +endnetent( void ) +{ + if (netf) { + fclose(netf); + netf = NULL; + } + _net_stayopen = 0; +} + +/* ----------- + - gnetent - + ----------- */ + +/* RD: Modified not to use gotos, added comments. */ + +struct netent *getnetent( void ) +{ + char *p; + register char *cp, **q; + char *x; + + /* RD: Use configuration routine now */ + x = __lsck_config_getfile(); + if (x != NULL) + GetPrivateProfileString("main", "networks", NULL, + NETDB, sizeof(NETDB), x); + else + *NETDB = '\0'; + + /* + RD: If we can't find the specified file, look in the Windows + directory. + + TODO: Add warning? + */ + if (*NETDB == '\0') sprintf(NETDB, "%s/networks", getenv("windir")); + + if ((netf == NULL) && (netf = fopen(NETDB, "rt" )) == NULL) return (NULL); + + while ((p = fgets(line, BUFSIZ, netf)) != NULL) { + /* Comment */ + if (*p == '#') continue; + + /* Nuke end-of-line (comments) */ + cp = any(p, "#\n"); + if (cp == NULL) continue; + *cp = '\0'; + + /* Network name */ + net.n_name = p; + + /* Look for network aliases */ + cp = any(p, " \t"); + if (cp == NULL) continue; + *cp++ = '\0'; + + while (*cp == ' ' || *cp == '\t') cp++; + p = any(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 = any(cp, " \t"); + if (cp != NULL) *cp++ = '\0'; + } + + /* Found match */ + *q = NULL; + return (&net); + } + + /* EOF with no match = failure */ + return(NULL); +} + +/* End RD */ + +static char * +any( register char *cp, const char *match ) +{ + register const char *mp; + char c; + + while ((c = *cp)) { + for (mp = match; *mp; mp++) + if (*mp == c) + return (cp); + cp++; + } + return ((char *)0); +} diff --git a/src/libc/posix/socket/inet/gprtbyn2.c b/src/libc/posix/socket/inet/gprtbyn2.c new file mode 100644 index 00000000..51812d71 --- /dev/null +++ b/src/libc/posix/socket/inet/gprtbyn2.c @@ -0,0 +1,51 @@ +/* + * 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. + */ + +#include "i_priv.h" /* RD: inetprivate.h -> i_priv.h */ +#include + +extern int _proto_stayopen; + +struct protoent * +getprotobynumber( register int proto ) +{ + register struct protoent *p; + + setprotoent(_proto_stayopen); + while ((p = getprotoent())) + if (p->p_proto == proto) + break; + if (!_proto_stayopen) + endprotoent(); + return (p); +} diff --git a/src/libc/posix/socket/inet/gprtbynm.c b/src/libc/posix/socket/inet/gprtbynm.c new file mode 100644 index 00000000..e45bb039 --- /dev/null +++ b/src/libc/posix/socket/inet/gprtbynm.c @@ -0,0 +1,55 @@ +/* + * 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. + */ + +#include "i_priv.h" /* RD: inetprivate.h -> i_priv.h */ +#include + +extern int _proto_stayopen; + +struct protoent *getprotobyname(const char *name) +{ + register struct protoent *p; + register char **cp; + + setprotoent(_proto_stayopen); + while ((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/src/libc/posix/socket/inet/gprtent.c b/src/libc/posix/socket/inet/gprtent.c new file mode 100644 index 00000000..4ff30ab7 --- /dev/null +++ b/src/libc/posix/socket/inet/gprtent.c @@ -0,0 +1,155 @@ +/* + * 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. + */ + +#include "i_priv.h" /* RD: inetprivate.h -> i_priv.h */ +#include +#include /* RD: Use configuration routines */ +#include /* RD: .ini and .cfg routines */ + +#define MAXALIASES 35 + +static char PROTODB[1024]; +static FILE *protof = NULL; +static char line[BUFSIZ+1]; +static struct protoent proto; +static char *proto_aliases[MAXALIASES]; + +int _proto_stayopen; + +void +setprotoent(f) + int f; +{ + /* IM: added correct PROTODB */ + char *x; + + /* RD: Use configuration routine now */ + x = __lsck_config_getfile(); + if (x != NULL) + GetPrivateProfileString("main", "protocols", NULL, + PROTODB, sizeof(PROTODB), x); + else + *PROTODB = '\0'; + + /* + RD: If we can't find the specified file, look in the Windows + directory. + + TODO: Add warning? + */ + if (*PROTODB == '\0') sprintf(PROTODB, "%s/protocol", getenv("windir")); + + if (protof == NULL) { + protof = fopen(PROTODB, "rt" ); + + /* RD: Warning message */ + if (protof == NULL) perror("resolv: Unable to open protocols file"); + } 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; + char *x; + + /* RD: Use configuration routine now */ + x = __lsck_config_getfile(); + if (x != NULL) + GetPrivateProfileString("main", "protocols", NULL, + PROTODB, sizeof(PROTODB), x); + else + *PROTODB = '\0'; + + /* + RD: If we can't find the specified file, look in the Windows + directory. + + TODO: Add warning? + */ + if (*PROTODB == '\0') sprintf(PROTODB, "%s/protocol", getenv("windir")); + + if (protof == NULL && (protof = fopen(PROTODB, "rt" )) == 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/src/libc/posix/socket/inet/gsrvbynm.c b/src/libc/posix/socket/inet/gsrvbynm.c new file mode 100644 index 00000000..6a9d078b --- /dev/null +++ b/src/libc/posix/socket/inet/gsrvbynm.c @@ -0,0 +1,58 @@ +/* + * 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. + */ + +#include "i_priv.h" /* RD: inetprivate.h -> i_priv.h */ +#include + +extern int _serv_stayopen; + +struct servent *getservbyname(const char *name, const char *proto) +{ + register struct servent *p; + register char **cp; + + setservent(_serv_stayopen); + while ((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(); + return (p); +} diff --git a/src/libc/posix/socket/inet/gsrvbypt.c b/src/libc/posix/socket/inet/gsrvbypt.c new file mode 100644 index 00000000..b7cb4df4 --- /dev/null +++ b/src/libc/posix/socket/inet/gsrvbypt.c @@ -0,0 +1,59 @@ +/* + * 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. + */ + +#include "i_priv.h" /* RD: inetprivate.h -> i_priv.h */ +#include + +extern int _serv_stayopen; + +struct servent * +getservbyport(int port, const char *proto) +{ + register struct servent *p; + +#if 0 + /* use value in network byte order because getservent() + returns the p->s_port value in network byte order. */ + port = htons (port); +#endif + setservent(_serv_stayopen); + while ((p = getservent())) { + if (p->s_port != port) + continue; + if (proto == 0 || strcmp(p->s_proto, proto) == 0) + break; + } + if (!_serv_stayopen) + endservent(); + return (p); +} diff --git a/src/libc/posix/socket/inet/gsrvent.c b/src/libc/posix/socket/inet/gsrvent.c new file mode 100644 index 00000000..bd2d110e --- /dev/null +++ b/src/libc/posix/socket/inet/gsrvent.c @@ -0,0 +1,170 @@ +/* + * 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. + */ + +/* RD: Modifications by Richard Dawe for the libsocket project. Modifications + marked with 'RD' comments like this one. */ + +#include "i_priv.h" /* RD: inetprivate.h -> i_priv.h */ +#include +#include /* RD: Use configuration routines */ +#include /* RD: .ini and .cfg routines */ + +#define MAXALIASES 35 + +static char SERVDB[1024]; +static FILE *servf = NULL; +static char line[BUFSIZ+1]; +static struct servent serv; +static char *serv_aliases[MAXALIASES]; +int _serv_stayopen; + +void +setservent(f) + int f; +{ + char *x; + + /* RD: Use configuration routine now */ + x = __lsck_config_getfile(); + if (x != NULL) + GetPrivateProfileString("main", "services", NULL, + SERVDB, sizeof(SERVDB), x); + else + *SERVDB = '\0'; + + /* + RD: If we can't find the specified file, look in the Windows + directory. + + TODO: Add warning? + */ + if (*SERVDB == '\0') sprintf(SERVDB, "%s/services", getenv("windir")); + + if (servf == NULL) { + servf = fopen(SERVDB, "rt" ); + + /* RD: Warning message */ + if (servf == NULL) perror("resolv: Unable to open services file"); + } else + rewind(servf); + _serv_stayopen |= f; +} + +void +endservent() +{ + if (servf) { + fclose(servf); + servf = NULL; + } + _serv_stayopen = 0; +} + +/* -------------- + - getservent - + -------------- */ + +/* RD: Modified not to use gotos & commented. */ + +struct servent *getservent() +{ + char *p; + register char *cp, **q; + char *x; + + /* RD: Use configuration routine now */ + x = __lsck_config_getfile(); + if (x != NULL) + GetPrivateProfileString("main", "services", NULL, + SERVDB, sizeof(SERVDB), x); + else + *SERVDB = '\0'; + + /* + RD: If we can't find the specified file, look in the Windows + directory. + + TODO: Add warning? + */ + if (*SERVDB == '\0') sprintf(SERVDB, "%s/services", getenv("windir")); + + if ((servf == NULL) && (servf = fopen(SERVDB, "rt" )) == NULL) + return (NULL); + + while ((p = fgets(line, BUFSIZ, servf)) != NULL) { + /* Comment */ + if (*p == '#') continue; + + /* Comment at EOL or EOL */ + cp = strpbrk(p, "#\n"); + if (cp == NULL) continue; + *cp = '\0'; + + /* Service name */ + serv.s_name = p; + + p = strpbrk(p, " \t"); + if (p == NULL) continue; + *p++ = '\0'; + + while (*p == ' ' || *p == '\t') p++; + cp = strpbrk(p, ",/"); + if (cp == NULL) continue; + *cp++ = '\0'; + + /* Port and protocol */ + serv.s_port = htons((u_short)atoi(p)); + serv.s_proto = cp; + + /* Aliases */ + 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; + + /* Matched */ + return (&serv); + } + + /* EOF and no match */ + return (NULL); +} diff --git a/src/libc/posix/socket/inet/herror.c b/src/libc/posix/socket/inet/herror.c new file mode 100644 index 00000000..2f715434 --- /dev/null +++ b/src/libc/posix/socket/inet/herror.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1987 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that: (1) source distributions retain this entire copyright + * notice and comment, and (2) distributions including binaries display + * the following acknowledgement: ``This product includes software + * developed by the University of California, Berkeley and its contributors'' + * in the documentation or other materials provided with the distribution + * and in all advertising materials mentioning features or use of this + * software. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + + +#include "i_priv.h" /* RD: inetprivate.h -> i_priv.h */ +#include +#include /* RD: writev() decl */ + +static const char *h_errlist[] = { + "Error 0", + "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 */ +}; + +static int h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) }; + +/* + * herror -- + * print the error indicated by the h_errno value. + */ +void +herror(char *s) +{ + struct iovec iov[4]; + struct iovec *v = iov; + char delim[] = ": "; + char nl[] = "\n"; + char herr[1024]; +#if NLS + libc_nls_init(); +#endif + + if (s && *s) { + v->iov_base = s; + v->iov_len = strlen(s); + v++; + v->iov_base = delim; + v->iov_len = 2; + v++; + } + strlcpy(herr, h_errno < h_nerr ? + h_errlist[h_errno] : "Unknown error", sizeof(herr)); + v->iov_base = herr; + v->iov_len = strlen(v->iov_base); + v++; + v->iov_base = nl; + v->iov_len = 1; +#if NLS + if ((u_int)h_errno < h_nerr) + fprintf(stderr, (s && *s) ? "%s: %s\n":"%s\n", + (s && *s) ? s: catgets(_libc_cat, HerrorListSet, h_errno+1, (char *) h_errlist[h_errno]), + (s && *s) ? catgets(_libc_cat, HerrorListSet, h_errno+1, (char *) h_errlist[h_errno]): NULL); + else + fprintf(stderr, (s && *s) ? "%s: %s\n":"%s\n", + (s && *s) ? s: catgets(_libc_cat, ErrorListSet, 1, "Unknown error"), + (s && *s) ? catgets(_libc_cat, ErrorListSet, 1, "Unknown error"): NULL); + +#else + writev(2, iov, (v - iov) + 1); +#endif + +} diff --git a/src/libc/posix/socket/inet/i_addr.c b/src/libc/posix/socket/inet/i_addr.c new file mode 100644 index 00000000..c9d63e89 --- /dev/null +++ b/src/libc/posix/socket/inet/i_addr.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 1983, 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. + */ + +/* RD: inetprivate.h -> i_priv.h */ +#include "i_priv.h" + +int inet_aton(const char *cp, struct in_addr *addr); + +/* + * Internet address interpretation routine. + * All the network library routines call this + * routine to interpret entries in the data bases + * which are expected to be an address. + * The value returned is in network order. + */ +u_long +inet_addr(const char *cp) +{ + struct in_addr val; + + if (inet_aton(cp, &val)) + return (val.s_addr); + return (INADDR_NONE); +} + +/* + * Check whether "cp" is a valid ascii representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + */ +int +inet_aton(const char *cp, struct in_addr *addr) +{ + register u_long val; + register int base, n; + register char c; + u_int parts[4]; + register u_int *pp = parts; + + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, other=decimal. + */ + val = 0; base = 10; + if (*cp == '0') { + if (*++cp == 'x' || *cp == 'X') + base = 16, cp++; + else + base = 8; + } + while ((c = *cp) != '\0') { + if (isascii(c) && isdigit(c)) { + val = (val * base) + (c - '0'); + cp++; + continue; + } + if (base == 16 && isascii(c) && isxdigit(c)) { + val = (val << 4) + + (c + 10 - (islower(c) ? 'a' : 'A')); + cp++; + continue; + } + break; + } + if (*cp == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16-bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3 || val > 0xff) + return (0); + *pp++ = val, cp++; + } else + break; + } + /* + * Check for trailing characters. + */ + if (*cp && (!isascii(*cp) || !isspace(*cp))) + return (0); + /* + * Concoct the address according to + * the number of parts specified. + */ + n = pp - parts + 1; + switch (n) { + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffff) + return (0); + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + if (addr) + addr->s_addr = htonl(val); + return (1); +} diff --git a/src/libc/posix/socket/inet/i_lnaof.c b/src/libc/posix/socket/inet/i_lnaof.c new file mode 100644 index 00000000..2950f957 --- /dev/null +++ b/src/libc/posix/socket/inet/i_lnaof.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. + */ + +/* RD: inetprivate.h -> i_priv.h */ +#include "i_priv.h" + +/* + * Return the local network address portion of an + * internet address; handles class a/b/c network + * number formats. + */ +u_long +inet_lnaof(in) + struct in_addr in; +{ + register u_long i = ntohl(in.s_addr); + + if (IN_CLASSA(i)) + return ((i)&IN_CLASSA_HOST); + else if (IN_CLASSB(i)) + return ((i)&IN_CLASSB_HOST); + else + return ((i)&IN_CLASSC_HOST); +} diff --git a/src/libc/posix/socket/inet/i_mkaddr.c b/src/libc/posix/socket/inet/i_mkaddr.c new file mode 100644 index 00000000..44cb76d8 --- /dev/null +++ b/src/libc/posix/socket/inet/i_mkaddr.c @@ -0,0 +1,56 @@ +/* + * 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. + */ + +#include "i_priv.h" /* RD: inetprivate.h -> i_priv.h */ + +/* + * Formulate an Internet address from network + host. Used in + * building addresses stored in the ifnet structure. + */ +struct in_addr +inet_makeaddr(net, host) + u_long net, host; +{ + u_long addr; + + if (net < 128) + addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST); + else if (net < 65536) + addr = (net << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST); + else if (net < 16777216L) + addr = (net << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST); + else + addr = net | host; + addr = htonl(addr); + return (*(struct in_addr *)&addr); +} diff --git a/src/libc/posix/socket/inet/i_net.c b/src/libc/posix/socket/inet/i_net.c new file mode 100644 index 00000000..4d721cbb --- /dev/null +++ b/src/libc/posix/socket/inet/i_net.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * 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. + */ + +/* RD: inetprivate.h -> i_priv.h */ +#include "i_priv.h" + +/* + * Internet network address interpretation routine. + * The library routines call this routine to interpret + * network numbers. + */ +u_int32_t +inet_network(const char *cp) +{ + register u_long val, base, n; + register char c; + u_long parts[4], *pp = parts; + register u_long i; + +again: + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, other=decimal. + */ + val = 0; base = 10; + /* + * The 4.4BSD version of this file also accepts 'x__' as a hexa + * number. I don't think this is correct. -- Uli + */ + if (*cp == '0') { + if (*++cp == 'x' || *cp == 'X') + base = 16, cp++; + else + base = 8; + } + while ((c = *cp)) { + if (isdigit(c)) { + val = (val * base) + (c - '0'); + cp++; + continue; + } + if (base == 16 && isxdigit(c)) { + val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A')); + cp++; + continue; + } + break; + } + if (*cp == '.') { + if (pp >= parts + 4) + return (INADDR_NONE); + *pp++ = val, cp++; + goto again; + } + if (*cp && !isspace(*cp)) + return (INADDR_NONE); + *pp++ = val; + n = pp - parts; + if (n > 4) + return (INADDR_NONE); + for (val = 0, i = 0; i < n; i++) { + val <<= 8; + val |= parts[i] & 0xff; + } + return (val); +} diff --git a/src/libc/posix/socket/inet/i_netof.c b/src/libc/posix/socket/inet/i_netof.c new file mode 100644 index 00000000..5792d78b --- /dev/null +++ b/src/libc/posix/socket/inet/i_netof.c @@ -0,0 +1,53 @@ +/* + * 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. + */ + +/* RD: inetprivate.h -> i_priv.h */ +#include "i_priv.h" + +/* + * Return the network number from an internet + * address; handles class a/b/c network #'s. + */ +u_int32_t +inet_netof(in) + struct in_addr in; +{ + register u_long i = ntohl(in.s_addr); + + if (IN_CLASSA(i)) + return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT); + else if (IN_CLASSB(i)) + return (((i)&IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); + else + return (((i)&IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); +} diff --git a/src/libc/posix/socket/inet/i_nsap.c b/src/libc/posix/socket/inet/i_nsap.c new file mode 100644 index 00000000..af85f80b --- /dev/null +++ b/src/libc/posix/socket/inet/i_nsap.c @@ -0,0 +1,94 @@ +/* + * i_nsap.c + * Copyright unknown - presumably this is part of the Linux networking code. + * + * This file is part of libsocket. + * libsocket Copyright 1997, 1998 by Indrek Mandre + * libsocket Copyright 1997-2000 by Richard Dawe + */ + +/* RD: inetprivate.h -> i_priv.h */ +#include "i_priv.h" + +char *inet_nsap_ntoa( int, register const u_char *, register char * ); +u_int inet_nsap_addr( const char *, u_char *, int ); +static char xtob( register int ); + +#if !defined(isxdigit) /* XXX - could be a function */ +static int +isxdigit(c) + register int c; +{ + return ((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'F')); +} +#endif /* !isxdigit */ + +static char +xtob( register int c ) +{ + return (c - (((c >= '0') && (c <= '9')) ? '0' : '7')); +} + +u_int +inet_nsap_addr( const char *ascii, u_char *binary, int maxlen ) +{ + register u_char c, nib; +/* u_char *start = binary; */ + int len = 0; + + while ((c = *ascii++) != '\0' && len < maxlen) { + if (c == '.' || c == '+' || c == '/') + continue; + if (!isascii(c)) + return (0); + if (islower(c)) + c = toupper(c); + if (isxdigit(c)) { + nib = xtob(c); + if (( c = *ascii++ )) { + c = 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++ = nib + (nib < 10 ? '0' : '7'); + nib = *binary++ & 0x0f; + *ascii++ = nib + (nib < 10 ? '0' : '7'); + if (((i % 2) == 0 && (i + 1) < binlen)) + *ascii++ = '.'; + } + *ascii = '\0'; + return (start); +} diff --git a/src/libc/posix/socket/inet/i_ntoa.c b/src/libc/posix/socket/inet/i_ntoa.c new file mode 100644 index 00000000..1862e151 --- /dev/null +++ b/src/libc/posix/socket/inet/i_ntoa.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. + */ + +/* + * Convert network-format internet address + * to base 256 d.d.d.d representation. + */ + +/* RD: inetprivate.h -> i_priv.h */ +#include "i_priv.h" + +char * +inet_ntoa(in) + struct in_addr in; +{ + static char b[18]; + register char *p; + + p = (char *)∈ +#define UC(b) (((int)b)&0xff) + (void)sprintf(b, + "%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3])); + return (b); +} diff --git a/src/libc/posix/socket/inet/i_ntop.c b/src/libc/posix/socket/inet/i_ntop.c new file mode 100644 index 00000000..9b01d362 --- /dev/null +++ b/src/libc/posix/socket/inet/i_ntop.c @@ -0,0 +1,82 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * i_ntop.c + * + * This module implements the inet_ntop() function, which converts addresses + * from binary (numeric) to text (presentation) format. + * + */ + +#include +#include + +#include +#include + +/* ------------- + * - inet_ntop - + * ------------- */ + +const char *inet_ntop (int af, const void *src, char *dst, size_t size) +{ + char *res = NULL; /* Fail by default */ + const char *p = (const char *) src; + + /* Check we've been passed a valid buffer. */ + if (dst == NULL) { + errno = EFAULT; + return(NULL); + } + + /* Process the address family appropriately. */ + switch(af) { + /* IPv4 */ + case AF_INET: + /* dst must point to a string buffer large enough to + * accommodate the converted address - + * INET_ADDRSTRLEN + * = 16 bytes + * = (3 * 3 digits) + 3 dots + nul. */ + if (size < INET_ADDRSTRLEN) { + errno = ENOSPC; + break; + } + + sprintf(dst, "%d.%d.%d.%d", + ((int) p[0] & 0xff), ((int) p[1] & 0xff), + ((int) p[2] & 0xff), ((int) p[3] & 0xff)); + res = dst; + break; + + /* Unsupported address family */ + default: + errno = EAFNOSUPPORT; + break; + } + + return((const char *) res); +} diff --git a/src/libc/posix/socket/inet/i_priv.h b/src/libc/posix/socket/inet/i_priv.h new file mode 100644 index 00000000..1aac9c47 --- /dev/null +++ b/src/libc/posix/socket/inet/i_priv.h @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +extern void _sethtent(int); +extern void _endhtent(void); +extern struct hostent *_gethtent(void); +extern struct hostent *_gethtbyname(const char *); +extern struct hostent *_gethtbyaddr(const char *, int, int); +extern int _validuser(FILE *, const char *, const char *, const char *, int); +extern int _checkhost(const char *, const char *, int); +extern void putlong(u_long l, u_char *); +extern void putshort(u_short l, u_char *); +extern u_int32_t _getlong(register const u_char *); +extern u_int16_t _getshort(register const u_char *); +extern void p_query(char *); +extern void fp_query(char *, FILE *); +extern char *p_cdname(char *, char *, FILE *); +extern char *p_rr(char *, char *, FILE *); +extern char *p_type(int); +extern char * p_class(int); +extern char *p_time(u_long); +extern char * hostalias(const char *); +extern void sethostfile(char *); +extern void _res_close (void); +extern void ruserpass(const char *, const char **, const char **); diff --git a/src/libc/posix/socket/inet/i_pton.c b/src/libc/posix/socket/inet/i_pton.c new file mode 100644 index 00000000..bda713b8 --- /dev/null +++ b/src/libc/posix/socket/inet/i_pton.c @@ -0,0 +1,65 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * i_pton.c + * + * This module implements the inet_ntop() function, which converts addresses + * from text (presentation) to binary (numeric) format. + * + */ + +#include + +#include +#include + +/* ------------- + * - inet_pton - + * ------------- */ + +int inet_pton (int af, const char *src, void *dst) +{ + int ret = 0; /* Fail by default */ + + switch(af) { + /* IPv4 address */ + case AF_INET: + /* Use the normal IPv4 conversion routine. */ + if (inet_aton(src, (struct in_addr *) dst) != 0) { + /* Success */ + ret = 1; + } + break; + + /* Unsupported address format */ + default: + errno = EAFNOSUPPORT; + ret = -1; + break; + } + + return(ret); +} diff --git a/src/libc/posix/socket/inet/l_herrno.c b/src/libc/posix/socket/inet/l_herrno.c new file mode 100644 index 00000000..01a17522 --- /dev/null +++ b/src/libc/posix/socket/inet/l_herrno.c @@ -0,0 +1,41 @@ +/* + * l_herrno.c + * Copyright unknown - presumably this is part of the Linux networking code. + * + * This file is part of libsocket. + * libsocket Copyright 1997, 1998 by Indrek Mandre + * libsocket Copyright 1997-2000 by Richard Dawe + */ + +#include + +#undef h_errno + +/* The one in libpthread will override __h_errno_location () */ +int *__normal_h_errno_location ( void ); + +/* Richard Dawe (libsocket): The commented code below was used. Since the + * aliasing isn't very useful for DJGPP programs and stops me cross-compiling, + * just point h_errno and __h_errno_location_location at the relevant + * function. */ + +/* Keep gcc 2.95.x happy. */ +/*extern int h_errno __attribute__ ((weak, alias("_h_errno")));*/ +/*#pragma weak h_errno = _h_errno*/ + +/*int _h_errno = 0;*/ +int h_errno = 0; + +/*#pragma weak __h_errno_location = __normal_h_errno_location*/ + +/*int *__h_errno_location (void) + __attribute__ ((weak, alias("__normal_h_errno_location__")));*/ + +typedef int * (*h_errno_loc_func) (void); +h_errno_loc_func __h_errno_location = __normal_h_errno_location; + +int * +__normal_h_errno_location ( void ) +{ + return &h_errno; +} diff --git a/src/libc/posix/socket/inet/l_res.c b/src/libc/posix/socket/inet/l_res.c new file mode 100644 index 00000000..be7ac997 --- /dev/null +++ b/src/libc/posix/socket/inet/l_res.c @@ -0,0 +1,35 @@ +/* + * l_res.c + * Copyright unknown - presumably this is part of the Linux networking code. + * + * This file is part of libsocket. + * libsocket Copyright 1997, 1998 by Indrek Mandre + * libsocket Copyright 1997-2000 by Richard Dawe + */ + +#include +#include + +#include + +/* Richard Dawe (libsocket): Let's keep gcc 2.95.x happy. */ +/*struct __res_state *__res_status_location (void) + __attribute__ ((weak, alias("__normal_res_status_location")));*/ + +/* The one in libpthread will override __res_status_location () */ +struct __res_state *__normal__res_status_location ( void ); + +/* Richard Dawe (libsocket): The commented code below was used. Since the + * aliasing isn't very useful for DJGPP programs and stops me cross-compiling, + * just point __res_status_location at the relevant function. */ + +/*#pragma weak __res_status_location = __normal__res_status_location*/ + +typedef struct __res_state * (*res_state_loc_func) (void); +res_state_loc_func __res_status_location = __normal__res_status_location; + +struct __res_state * +__normal__res_status_location ( void ) +{ + return &_res; +} diff --git a/src/libc/posix/socket/inet/makefile b/src/libc/posix/socket/inet/makefile new file mode 100644 index 00000000..1e7ce148 --- /dev/null +++ b/src/libc/posix/socket/inet/makefile @@ -0,0 +1,42 @@ +# Copyright (C) 2014 DJ Delorie, see COPYING.DJ for details +# Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details +# Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details +TOP=../../.. + +SRC += i_ntoa.c +SRC += i_addr.c +SRC += i_lnaof.c +SRC += i_mkaddr.c +SRC += i_net.c +SRC += i_netof.c +SRC += gprtbynm.c +SRC += gprtbyn2.c +SRC += gprtent.c +SRC += gnetbynm.c +SRC += gnetent.c +SRC += gnetbyad.c +SRC += gsrvbynm.c +SRC += gsrvent.c +SRC += shstent.c +SRC += l_res.c +SRC += r_data.c +SRC += l_herrno.c +SRC += ghstnmad.c +SRC += gsrvbypt.c +SRC += i_nsap.c +SRC += herror.c +SRC += r_debug.c +SRC += r_mkqry.c +SRC += r_qry.c +SRC += r_init.c +SRC += r_comp.c +SRC += r_send.c +SRC += bresvpt.c +SRC += rcmd.c +SRC += rexec.c +SRC += rusrpass.c +SRC += i_pton.c +SRC += i_ntop.c +SRC += gaddrinf.c + +include $(TOP)/../makefile.inc diff --git a/src/libc/posix/socket/inet/r_comp.c b/src/libc/posix/socket/inet/r_comp.c new file mode 100644 index 00000000..afa2af19 --- /dev/null +++ b/src/libc/posix/socket/inet/r_comp.c @@ -0,0 +1,468 @@ +/* + * ++Copyright++ 1985, 1993 + * - + * Copyright (c) 1985, 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-- + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "i_priv.h" /* RD: inetprivate.h -> i_priv.h */ + +#ifdef __STDC__ +int dn_expand ( const u_char *, const u_char *, const u_char *, + char *, int ); +int dn_comp ( const char *, u_char *, int, u_char **, u_char ** ); +static int mklower ( register int ); +static int dn_find ( const u_char *, u_char *, u_char **, u_char ** ); +u_int16_t _getshort ( register const u_char * ); +u_int32_t _getlong ( register const u_char * ); +int __dn_skipname( const u_char *, const u_char * ); +void __putshort ( register u_int16_t, register u_char * ); +void __putlong ( register u_int32_t, register u_char * ); +#else /* __STDC__ */ +int dn_expand (); +int dn_comp (); +int __dn_skipname (); +static int mklower (); +static int dn_find (); +u_int16_t _getshort (); +u_int32_t _getlong (); +void __putshort (); +void __putlong (); +#endif /* __STDC__ */ + +/* Richard Dawe (libsocket): The commented code below was used. Since the + * aliasing isn't very useful for DJGPP programs and stops me + * cross-compiling. So just make the aliases function calls. */ +#if 0 +int dn_skipname (const u_char *a, const u_char *b) { + return(__dn_skipname(a, b)); +} +#endif +void putshort (register u_int16_t a, register u_char *b) { __putshort(a, b); } +void putlong (register u_int32_t a, register u_char *b) { __putlong(a, b); } + +/* RD: gcc 2.95.x dislikes pragmas, so let's keep it happy. */ +/*int dn_skipname (const u_char *, const u_char *) + __attribute__ ((weak, alias("__dn_skipname"))); +void putshort (register u_int16_t, register u_char *) + __attribute__ ((weak, alias("__putshort"))); +void putlong (register u_int32_t, register u_char *) +__attribute__ ((weak, alias("__putlong")));*/ + +/*#pragma weak dn_skipname = __dn_skipname +#pragma weak putlong = __putlong +#pragma weak putshort = __putshort*/ + +/* End RD */ + +/* + * 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. + */ + +#ifdef __STDC__ +int +dn_expand( const u_char *msg, const u_char *eomorig, const u_char *comp_dn, + char *exp_dn, int length ) +#else +int +dn_expand(msg, eomorig, comp_dn, exp_dn, length) + const u_char *msg, *eomorig, *comp_dn; + char *exp_dn; + int length; +#endif +{ + register const u_char *cp; + register char *dn; + register int n, c; + char *eom; + int len = -1, checked = 0; + + dn = exp_dn; + cp = comp_dn; + eom = exp_dn + length; + /* + * fetch next label in domain name + */ + while ((n = *cp++)) { + /* + * Check for indirection + */ + switch (n & INDIR_MASK) { + case 0: + if (dn != exp_dn) { + if (dn >= eom) + return (-1); + *dn++ = '.'; + } + if (dn+n >= eom) + return (-1); + checked += n + 1; + while (--n >= 0) { + if (((c = *cp++) == '.') || (c == '\\')) { + if (dn + n + 2 >= eom) + return (-1); + *dn++ = '\\'; + } + *dn++ = c; + if (cp >= eomorig) /* out of range */ + return (-1); + } + break; + + case INDIR_MASK: + if (len < 0) + len = cp - comp_dn + 1; + cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff)); + if (cp < msg || cp >= eomorig) /* out of range */ + 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 >= eomorig - msg) + return (-1); + break; + + default: + return (-1); /* flag error */ + } + } + *dn = '\0'; + for (dn = exp_dn; (c = *dn) != '\0'; dn++) + if (isascii(c) && isspace(c)) + return (-1); + if (len < 0) + len = cp - comp_dn; + return (len); +} + +/* + * Compress domain name 'exp_dn' into 'comp_dn'. + * Return the size of the compressed name or -1. + * 'length' is the size of the array pointed to by 'comp_dn'. + * 'dnptrs' is a list 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 arrary 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. + */ + +#ifdef __STDC__ +int +dn_comp( const char *exp_dn, u_char *comp_dn, int length, u_char **dnptrs, + u_char **lastdnptr ) +#else +int +dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr) + const char *exp_dn; + u_char *comp_dn, **dnptrs, **lastdnptr; + int length; +#endif +{ + register u_char *cp; + const u_char *dn; + register int c, l; + u_char **cpp, **lpp, *sp, *eob; + u_char *msg; + + dn = (const u_char *)exp_dn; + cp = comp_dn; + eob = cp + length; + lpp = cpp = NULL; + if (dnptrs != NULL) { + if ((msg = *dnptrs++) != NULL) { + for (cpp = dnptrs; *cpp != NULL; cpp++) + ; + lpp = cpp; /* end of list to search */ + } + } else + msg = NULL; + for (c = *dn++; c != '\0'; ) { + /* look to see if we can use pointers */ + if (msg != NULL) { + if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) { + if (cp+1 >= eob) + return (-1); + *cp++ = (l >> 8) | INDIR_MASK; + *cp++ = l % 256; + return (cp - comp_dn); + } + /* not found, save it */ + if (lastdnptr != NULL && cpp < lastdnptr-1) { + *cpp++ = cp; + *cpp = NULL; + } + } + sp = cp++; /* save ptr to length byte */ + do { + if (c == '.') { + c = *dn++; + break; + } + if (c == '\\') { + if ((c = *dn++) == '\0') + break; + } + if (cp >= eob) { + if (msg != NULL) + *lpp = NULL; + return (-1); + } + *cp++ = c; + } while ((c = *dn++) != '\0'); + /* catch trailing '.'s but not '..' */ + if ((l = cp - sp - 1) == 0 && c == '\0') { + cp--; + break; + } + if (l <= 0 || l > MAXLABEL) { + if (msg != NULL) + *lpp = NULL; + return (-1); + } + *sp = l; + } + if (cp >= eob) { + if (msg != NULL) + *lpp = NULL; + return (-1); + } + *cp++ = '\0'; + return (cp - comp_dn); +} + +/* + * Skip over a compressed domain name. Return the size or -1. + */ +#ifdef __STDC__ +int +__dn_skipname( const u_char *comp_dn, const u_char *eom ) +#else +int +__dn_skipname(comp_dn, eom) + const u_char *comp_dn, *eom; +#endif +{ + register const u_char *cp; + register int n; + + cp = comp_dn; + while (cp < eom && (n = *cp++)) { + /* + * check for indirection + */ + switch (n & INDIR_MASK) { + case 0: /* normal case, n == len */ + cp += n; + continue; + case INDIR_MASK: /* indirection */ + cp++; + break; + default: /* illegal type */ + return (-1); + } + break; + } + if (cp > eom) + return (-1); + return (cp - comp_dn); +} + +#ifdef __STDC__ +static int +mklower( register int ch ) +#else +static int +mklower(ch) + register int ch; +#endif +{ + if (isascii(ch) && isupper(ch)) + return (tolower(ch)); + return (ch); +} + +/* + * Search for expanded name from a list of previously compressed names. + * Return the offset from msg if found or -1. + * dnptrs is the pointer to the first name on the list, + * not the pointer to the start of the message. + */ + +#ifdef __STDC__ +static int +dn_find( const u_char *exp_dn, u_char *msg, u_char **dnptrs, u_char **lastdnptr ) +#else +static int +dn_find(exp_dn, msg, dnptrs, lastdnptr) + const u_char *exp_dn, *msg; + u_char **dnptrs, **lastdnptr; +#endif +{ + const u_char *dn; + u_char *cp, **cpp; + register int n; + u_char *sp; + + for (cpp = dnptrs; cpp < lastdnptr; cpp++) { + dn = exp_dn; + sp = cp = *cpp; + while ((n = *cp++)) { + /* + * check for indirection + */ + switch (n & INDIR_MASK) { + case 0: /* normal case, n == len */ + while (--n >= 0) { + if (*dn == '.') + goto next; + if (*dn == '\\') + dn++; + if (mklower(*dn++) != mklower(*cp++)) + goto next; + } + if ((n = *dn++) == '\0' && *cp == '\0') + return (sp - msg); + if (n == '.') + continue; + goto next; + + case INDIR_MASK: /* indirection */ + cp = msg + (((n & 0x3f) << 8) | *cp); + break; + + default: /* illegal type */ + return (-1); + } + } + if (*dn == '\0') + return (sp - msg); + next: ; + } + return (-1); +} + +/* + * Routines to insert/extract short/long's. + */ + +#ifdef __STDC__ +u_int16_t +_getshort( register const u_char *msgp ) +#else +u_int16_t +_getshort(msgp) + register const u_char *msgp; +#endif +{ + register u_int16_t u; + + GETSHORT(u, msgp); + return (u); +} + +#ifdef __STDC__ +u_int32_t +_getlong( register const u_char *msgp ) +#else +u_int32_t +_getlong(msgp) + register const u_char *msgp; +#endif +{ + register u_int32_t u; + + GETLONG(u, msgp); + return (u); +} + +#if defined(__STDC__) || defined(__cplusplus) +void +__putshort(register u_int16_t s, register u_char *msgp) /* must match proto */ +#else +static void +__putshort(s, msgp) + register u_int16_t s; + register u_char *msgp; +#endif +{ + PUTSHORT(s, msgp); +} + +#ifdef __STDC__ +void +__putlong( register u_int32_t l, register u_char *msgp ) +#else +static void +__putlong(l, msgp) + register u_int32_t l; + register u_char *msgp; +#endif +{ + PUTLONG(l, msgp); +} diff --git a/src/libc/posix/socket/inet/r_data.c b/src/libc/posix/socket/inet/r_data.c new file mode 100644 index 00000000..2636a7c0 --- /dev/null +++ b/src/libc/posix/socket/inet/r_data.c @@ -0,0 +1,103 @@ +/* + * ++Copyright++ 1995 + * - + * Copyright (c) 1995 + * 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-- + */ + + +#include +#include +#include + +#include + +#include +#include +#include + +const char *_res_opcodes[] = { + "QUERY", + "IQUERY", + "CQUERYM", + "CQUERYU", /* experimental */ + "NOTIFY", /* experimental */ + "5", + "6", + "7", + "8", + "UPDATEA", + "UPDATED", + "UPDATEDA", + "UPDATEM", + "UPDATEMA", + "ZONEINIT", + "ZONEREF", +}; + +const char *_res_resultcodes[] = { + "NOERROR", + "FORMERR", + "SERVFAIL", + "NXDOMAIN", + "NOTIMP", + "REFUSED", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "14", + "NOCHANGE", +}; diff --git a/src/libc/posix/socket/inet/r_debug.c b/src/libc/posix/socket/inet/r_debug.c new file mode 100644 index 00000000..a4f4e714 --- /dev/null +++ b/src/libc/posix/socket/inet/r_debug.c @@ -0,0 +1,834 @@ +/* + * ++Copyright++ 1985, 1990, 1993 + * - + * Copyright (c) 1985, 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. + * - + * 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-- + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "i_priv.h" /* RD: inetprivate.h -> i_priv.h */ +#include "r_opts.h" /* RD: res_options.h -> r_opts.h */ + +extern const char *_res_opcodes[]; +extern const char *_res_resultcodes[]; + +int __dn_skipname ( const u_char *, const u_char * ); + + char *__p_time ( u_int32_t ); +const char *__p_option ( u_long ); +const char *__p_class ( int ); +const char *__p_type ( int ); +const u_char *__p_rr ( const u_char *, const u_char *, FILE * ); +const u_char *__p_fqname ( const u_char *, const u_char *, FILE * ); +const u_char *__p_cdname ( const u_char *, const u_char *, FILE * ); +const u_char *__p_cdnname ( const u_char *, const u_char *, int, FILE * ); +void __fp_query ( const u_char *, FILE * ); +void __fp_nquery ( const u_char *, int, FILE * ); +void __fp_resstat ( struct __res_state *, FILE * ); +void __p_query ( const u_char * ); +static const u_char *do_rrset ( const u_char *, int, const u_char *, + int, int, FILE *, const char * ); +static const char *deproto ( int ); +static const char *dewks ( int ); +/* + * This is sure a grotesque way to avoid ANSI standards. vch + */ +/* IM: what _is_ this??? + char *p_time ( u_int32_t ) + __attribute__ ((weak, alias ("__p_time"))); +const char *p_option ( u_long ) + __attribute__ ((weak, alias ("__p_option"))); +const char *p_class ( int ) + __attribute__ ((weak, alias ("__p_class"))); +const char *p_type ( int ) + __attribute__ ((weak, alias ("__p_type"))); +const u_char *p_rr ( const u_char *, const u_char *, FILE * ) + __attribute__ ((weak, alias ("__p_rr"))); +const u_char *p_fqname ( const u_char *, const u_char *, FILE * ) + __attribute__ ((weak, alias ("__p_fqname"))); +const u_char *p_cdname ( const u_char *, const u_char *, FILE * ) + __attribute__ ((weak, alias ("__p_cdname"))); +const u_char *p_cdnname ( const u_char *, const u_char *, int, FILE * ) + __attribute__ ((weak, alias ("__p_cdnname"))); +void fp_query ( const u_char *, FILE * ) + __attribute__ ((weak, alias ("__fp_query"))); +void fp_nquery ( const u_char *, int, FILE * ) + __attribute__ ((weak, alias ("__fp_nquery"))); +void fp_resstat ( struct __res_state *, FILE * ) + __attribute__ ((weak, alias ("__fp_resstat"))); +void p_query ( const u_char * ) + __attribute__ ((weak, alias ("__p_query"))); */ +/* +#pragma weak fp_query = __fp_query +#pragma weak fp_nquery = __fp_nquery +#pragma weak fp_resstat = __fp_resstat +#pragma weak p_cdname = __p_cdname +#pragma weak p_cdnname = __p_cdnname +#pragma weak p_class = __p_class +#pragma weak p_fqname = __p_fqname +#pragma weak p_option = __p_option +#pragma weak p_query = __p_query +#pragma weak p_rr = __p_rr +#pragma weak p_time = __p_time +#pragma weak p_type = __p_type */ + +#define p_option __p_option +#define p_cdname __p_cdname +#define fp_query __fp_query +#define fp_nquery __fp_nquery +#define p_cdnname __p_cdnname +#define p_fqname __p_fqname + +/* XXX: we should use getservbyport() instead. */ +static const char * +dewks( int wks ) +{ + static char nbuf[20]; + + switch (wks) { + case 5: return "rje"; + case 7: return "echo"; + case 9: return "discard"; + case 11: return "systat"; + case 13: return "daytime"; + case 15: return "netstat"; + case 17: return "qotd"; + case 19: return "chargen"; + case 20: return "ftp-data"; + case 21: return "ftp"; + case 23: return "telnet"; + case 25: return "smtp"; + case 37: return "time"; + case 39: return "rlp"; + case 42: return "name"; + case 43: return "whois"; + case 53: return "domain"; + case 57: return "apts"; + case 59: return "apfs"; + case 67: return "bootps"; + case 68: return "bootpc"; + case 69: return "tftp"; + case 77: return "rje"; + case 79: return "finger"; + case 87: return "link"; + case 95: return "supdup"; + case 100: return "newacct"; + case 101: return "hostnames"; + case 102: return "iso-tsap"; + case 103: return "x400"; + case 104: return "x400-snd"; + case 105: return "csnet-ns"; + case 109: return "pop-2"; + case 111: return "sunrpc"; + case 113: return "auth"; + case 115: return "sftp"; + case 117: return "uucp-path"; + case 119: return "nntp"; + case 121: return "erpc"; + case 123: return "ntp"; + case 133: return "statsrv"; + case 136: return "profile"; + case 144: return "NeWS"; + case 161: return "snmp"; + case 162: return "snmp-trap"; + case 170: return "print-srv"; + default: (void) sprintf(nbuf, "%d", wks); return (nbuf); + } +} + +/* XXX: we should use getprotobynumber() instead. */ +static const char * +deproto( int protonum ) +{ + static char nbuf[20]; + + switch (protonum) { + case 1: return "icmp"; + case 2: return "igmp"; + case 3: return "ggp"; + case 5: return "st"; + case 6: return "tcp"; + case 7: return "ucl"; + case 8: return "egp"; + case 9: return "igp"; + case 11: return "nvp-II"; + case 12: return "pup"; + case 16: return "chaos"; + case 17: return "udp"; + default: (void) sprintf(nbuf, "%d", protonum); return (nbuf); + } +} + +static const u_char * +do_rrset( const u_char *msg, int len, const u_char *cp, int cnt, + int pflag, FILE *file, const char *hs) +{ + int n; + int sflag; + + /* + * Print answer records. + */ + sflag = (_res.pfcode & pflag); + if ((n = ntohs(cnt))) { + if ((!_res.pfcode) || + ((sflag) && (_res.pfcode & RES_PRF_HEAD1))) + fprintf(file, hs); + while (--n >= 0) { + if ((!_res.pfcode) || sflag) { + cp = __p_rr(cp, msg, file); + } else { + unsigned int dlen; + cp += __dn_skipname(cp, cp + MAXCDNAME); + cp += INT16SZ; + cp += INT16SZ; + cp += INT32SZ; + dlen = _getshort(cp); + cp += INT16SZ; + cp += dlen; + } + if ((cp - msg) > len) + return (NULL); + } + if ((!_res.pfcode) || + ((sflag) && (_res.pfcode & RES_PRF_HEAD1))) + putc('\n', file); + } + return (cp); +} + +void +__p_query( const u_char *msg ) +{ + __fp_query(msg, stdout); +} + + +/* + * Print the current options. + * This is intended to be primarily a debugging routine. + */ + +void +__fp_resstat( struct __res_state *statp, FILE *file ) +{ + register 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); +} + +/* + * 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 ) +{ + register const u_char *cp, *endMark; + register const HEADER *hp; + register int n; + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) + return; + +#define TruncTest(x) if (x >= endMark) goto trunc +#define ErrorTest(x) if (x == NULL) goto error + + /* + * Print header fields. + */ + hp = (const HEADER *)msg; + cp = msg + HFIXEDSZ; + endMark = cp + len; + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) { + fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %d", + _res_opcodes[hp->opcode], + _res_resultcodes[hp->rcode], + ntohs(hp->id)); + putc('\n', file); + } + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX)) + putc(';', file); + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) { + fprintf(file, "; flags:"); + if (hp->qr) + fprintf(file, " qr"); + if (hp->aa) + fprintf(file, " aa"); + if (hp->tc) + fprintf(file, " tc"); + if (hp->rd) + fprintf(file, " rd"); + if (hp->ra) + fprintf(file, " ra"); + } + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) { + fprintf(file, "; Ques: %d", ntohs(hp->qdcount)); + fprintf(file, ", Ans: %d", ntohs(hp->ancount)); + fprintf(file, ", Auth: %d", ntohs(hp->nscount)); + fprintf(file, ", Addit: %d", ntohs(hp->arcount)); + } + if ((!_res.pfcode) || (_res.pfcode & + (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) { + putc('\n',file); + } + /* + * Print question records. + */ + if ((n = ntohs(hp->qdcount))) { + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) + fprintf(file, ";; QUESTIONS:\n"); + while (--n >= 0) { + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) + fprintf(file, ";;\t"); + TruncTest(cp); + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) + cp = p_cdnname(cp, msg, len, file); + else { + int n1; + char name[MAXDNAME]; + + if ((n1 = dn_expand(msg, msg+len, cp, name, + sizeof name)) < 0) + cp = NULL; + else + cp += n1; + } + ErrorTest(cp); + TruncTest(cp); + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) + fprintf(file, ", type = %s", + __p_type(_getshort(cp))); + cp += INT16SZ; + TruncTest(cp); + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) + fprintf(file, ", class = %s\n", + __p_class(_getshort(cp))); + cp += INT16SZ; + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) + putc('\n', file); + } + } + /* + * Print authoritative answer records + */ + TruncTest(cp); + cp = do_rrset(msg, len, cp, hp->ancount, RES_PRF_ANS, file, + ";; ANSWERS:\n"); + ErrorTest(cp); + + /* + * print name server records + */ + TruncTest(cp); + cp = do_rrset(msg, len, cp, hp->nscount, RES_PRF_AUTH, file, + ";; AUTHORITY RECORDS:\n"); + ErrorTest(cp); + + TruncTest(cp); + /* + * print additional records + */ + cp = do_rrset(msg, len, cp, hp->arcount, RES_PRF_ADD, file, + ";; ADDITIONAL RECORDS:\n"); + ErrorTest(cp); + return; + trunc: + fprintf(file, "\n;; ...truncated\n"); + return; + error: + fprintf(file, "\n;; ...malformed\n"); +} + +void +__fp_query( const u_char *msg, FILE *file ) +{ + fp_nquery(msg, PACKETSZ, 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)); +} + +/* XXX: the rest of these functions need to become length-limited, too. (vix) + */ + +const u_char * +__p_fqname( const u_char *cp, const u_char *msg, FILE *file ) +{ + char name[MAXDNAME]; + int n; + + if ((n = dn_expand(msg, cp + MAXCDNAME, cp, name, sizeof name)) < 0) + return (NULL); + if (name[0] == '\0') { + putc('.', file); + } else { + fputs(name, file); + if (name[strlen(name) - 1] != '.') + putc('.', file); + } + return (cp + n); +} + +/* + * Print resource record fields in human readable form. + */ +const u_char * +__p_rr( const u_char *cp, const u_char *msg, FILE *file ) +{ + int type, class, dlen, n, c; + struct in_addr inaddr; + const u_char *cp1, *cp2; + u_int32_t tmpttl, t; + int lcnt; + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + h_errno = NETDB_INTERNAL; + return (NULL); + } + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); /* compression error */ + type = _getshort(cp); + cp += INT16SZ; + class = _getshort(cp); + cp += INT16SZ; + tmpttl = _getlong(cp); + cp += INT32SZ; + dlen = _getshort(cp); + cp += INT16SZ; + cp1 = cp; + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID)) + fprintf(file, "\t%lu", (u_long)tmpttl); + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_CLASS)) + fprintf(file, "\t%s", __p_class(class)); + fprintf(file, "\t%s", __p_type(type)); + /* + * Print type specific data, if appropriate + */ + switch (type) { + case T_A: + switch (class) { + case C_IN: + case C_HS: + bcopy(cp, (char *)&inaddr, INADDRSZ); + if (dlen == 4) { + fprintf(file, "\t%s", inet_ntoa(inaddr)); + cp += dlen; + } else if (dlen == 7) { + char *address; + u_char protocol; + u_short port; + + address = inet_ntoa(inaddr); + cp += INADDRSZ; + protocol = *cp; + cp += sizeof(u_char); + port = _getshort(cp); + cp += INT16SZ; + fprintf(file, "\t%s\t; proto %d, port %d", + address, protocol, port); + } + break; + default: + cp += dlen; + } + break; + case T_CNAME: + case T_MB: + case T_MG: + case T_MR: + case T_NS: + case T_PTR: + putc('\t', file); + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); + break; + + case T_HINFO: + case T_ISDN: + cp2 = cp + dlen; + if ((n = *cp++)) { + fprintf(file, "\t%.*s", n, cp); + cp += n; + } + if ((cp < cp2) && (n = *cp++)) { + fprintf(file, "\t%.*s", n, cp); + cp += n; + } else if (type == T_HINFO) + fprintf(file, "\n;; *** Warning *** OS-type missing"); + break; + + case T_SOA: + putc('\t', file); + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); + putc(' ', file); + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); + fputs(" (\n", file); + t = _getlong(cp); cp += INT32SZ; + fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t); + t = _getlong(cp); cp += INT32SZ; + fprintf(file, "\t\t\t%lu\t; refresh (%s)\n", + (u_long)t, __p_time(t)); + t = _getlong(cp); cp += INT32SZ; + fprintf(file, "\t\t\t%lu\t; retry (%s)\n", + (u_long)t, __p_time(t)); + t = _getlong(cp); cp += INT32SZ; + fprintf(file, "\t\t\t%lu\t; expire (%s)\n", + (u_long)t, __p_time(t)); + t = _getlong(cp); cp += INT32SZ; + fprintf(file, "\t\t\t%lu )\t; minimum (%s)", + (u_long)t, __p_time(t)); + break; + + case T_MX: + case T_AFSDB: + case T_RT: + fprintf(file, "\t%d ", _getshort(cp)); + cp += INT16SZ; + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); + break; + + case T_PX: + fprintf(file, "\t%d ", _getshort(cp)); + cp += INT16SZ; + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); + putc(' ', file); + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); + break; + + case T_TXT: + case T_X25: + (void) fputs("\t\"", file); + cp2 = cp1 + dlen; + while (cp < cp2) { + if ((n = (unsigned char) *cp++)) { + for (c = n; c > 0 && cp < cp2; c--) + if ((*cp == '\n') || (*cp == '"')) { + (void) putc('\\', file); + (void) putc(*cp++, file); + } else + (void) putc(*cp++, file); + } + } + putc('"', file); + break; + + case T_NSAP: + (void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL)); + cp += dlen; + break; + + case T_MINFO: + case T_RP: + putc('\t', file); + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); + putc(' ', file); + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); + break; + + case T_UINFO: + putc('\t', file); + fputs((const char *)cp, file); + cp += dlen; + break; + + case T_UID: + case T_GID: + if (dlen == 4) { + fprintf(file, "\t%u", (unsigned int) _getlong(cp)); + cp += INT32SZ; + } + break; + + case T_WKS: + if (dlen < INT32SZ + 1) + break; + bcopy(cp, (char *)&inaddr, INADDRSZ); + cp += INT32SZ; + fprintf(file, "\t%s %s ( ", + inet_ntoa(inaddr), + deproto((int) *cp)); + cp += sizeof(u_char); + n = 0; + lcnt = 0; + while (cp < cp1 + dlen) { + c = *cp++; + do { + if (c & 0200) { + if (lcnt == 0) { + fputs("\n\t\t\t", file); + lcnt = 5; + } + fputs(dewks(n), file); + putc(' ', file); + lcnt--; + } + c <<= 1; + } while (++n & 07); + } + putc(')', file); + break; + +#ifdef ALLOW_T_UNSPEC + case T_UNSPEC: + { + int NumBytes = 8; + u_char *DataPtr; + int i; + + if (dlen < NumBytes) NumBytes = dlen; + fprintf(file, "\tFirst %d bytes of hex data:", + NumBytes); + for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++) + fprintf(file, " %x", *DataPtr); + cp += dlen; + } + break; +#endif /* ALLOW_T_UNSPEC */ + + default: + fprintf(file, "\t?%d?", type); + cp += dlen; + } +#if 0 + fprintf(file, "\t; dlen=%d, ttl %s\n", dlen, __p_time(tmpttl)); +#else + putc('\n', file); +#endif + if (cp - cp1 != dlen) { + fprintf(file, ";; packet size error (found %d, dlen was %d)\n", + (int)(cp - cp1), dlen); + cp = NULL; + } + return (cp); +} + +/* + * Return a string for the type + */ +const char * +__p_type( int type ) +{ + static char nbuf[20]; + + switch (type) { + case T_A: return "A"; + case T_NS: return "NS"; + case T_CNAME: return "CNAME"; + case T_SOA: return "SOA"; + case T_MB: return "MB"; + case T_MG: return "MG"; + case T_MR: return "MR"; + case T_NULL: return "NULL"; + case T_WKS: return "WKS"; + case T_PTR: return "PTR"; + case T_HINFO: return "HINFO"; + case T_MINFO: return "MINFO"; + case T_MX: return "MX"; + case T_TXT: return "TXT"; + case T_RP: return "RP"; + case T_AFSDB: return "AFSDB"; + case T_X25: return "X25"; + case T_ISDN: return "ISDN"; + case T_RT: return "RT"; + case T_NSAP: return "NSAP"; + case T_NSAP_PTR: return "NSAP_PTR"; + case T_SIG: return "SIG"; + case T_KEY: return "KEY"; + case T_PX: return "PX"; + case T_GPOS: return "GPOS"; + case T_AAAA: return "AAAA"; + case T_LOC: return "LOC"; + case T_AXFR: return "AXFR"; + case T_MAILB: return "MAILB"; + case T_MAILA: return "MAILA"; + case T_ANY: return "ANY"; + case T_UINFO: return "UINFO"; + case T_UID: return "UID"; + case T_GID: return "GID"; +#ifdef ALLOW_T_UNSPEC + case T_UNSPEC: return "UNSPEC"; +#endif /* ALLOW_T_UNSPEC */ + default: (void)sprintf(nbuf, "%d", type); return (nbuf); + } +} + +/* + * Return a mnemonic for class + */ +const char * +__p_class( int class ) +{ + static char nbuf[20]; + + switch (class) { + case C_IN: return "IN"; + case C_HS: return "HS"; + case C_ANY: return "ANY"; + default: (void)sprintf(nbuf, "%d", class); return (nbuf); + } +} + +/* + * 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 + */ +char * +__p_time( u_int32_t value ) +{ + static char nbuf[120]; + int secs, mins, hours, days; + register char *p; + + if (value == 0) { + strcpy(nbuf, "0 secs"); + return (nbuf); + } + + secs = value % 60; + value /= 60; + mins = value % 60; + value /= 60; + hours = value % 24; + value /= 24; + days = value; + value = 0; + +#define PLURALIZE(x) x, (x == 1) ? "" : "s" + p = nbuf; + if (days) { + (void)sprintf(p, "%d day%s", PLURALIZE(days)); + while (*++p); + } + if (hours) { + if (days) + *p++ = ' '; + (void)sprintf(p, "%d hour%s", PLURALIZE(hours)); + while (*++p); + } + if (mins) { + if (days || hours) + *p++ = ' '; + (void)sprintf(p, "%d min%s", PLURALIZE(mins)); + while (*++p); + } + if (secs || ! (days || hours || mins)) { + if (days || hours || mins) + *p++ = ' '; + (void)sprintf(p, "%d sec%s", PLURALIZE(secs)); + } + return (nbuf); +} diff --git a/src/libc/posix/socket/inet/r_init.c b/src/libc/posix/socket/inet/r_init.c new file mode 100644 index 00000000..551d01d7 --- /dev/null +++ b/src/libc/posix/socket/inet/r_init.c @@ -0,0 +1,556 @@ +/* + * ++Copyright++ 1985, 1989, 1993 + * - + * Copyright (c) 1985, 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) 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-- + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "i_priv.h" /* RD: inetprivate.h -> i_priv.h */ +#include "r_opts.h" /* RD: res_options.h -> r_opts.h */ + +#include /* RD: For ls_getdnsaddr() */ +#include /* RD: Use registry-enabled gethostname() */ +#include /* RD: .ini and .cfg functions */ + +extern char *__libc_secure_getenv(const char *); + +/*-------------------------------------- info about "sortlist" -------------- + * Marc Majka 1994/04/16 + * Allan Nathanson 1994/10/29 (BIND 4.9.3.x) + * + * NetInfo resolver configuration directory support. + * + * Allow a NetInfo directory to be created in the hierarchy which + * contains the same information as the resolver configuration file. + * + * - The local domain name is stored as the value of the "domain" property. + * - The Internet address(es) of the name server(s) are stored as values + * of the "nameserver" property. + * - The name server addresses are stored as values of the "nameserver" + * property. + * - The search list for host-name lookup is stored as values of the + * "search" property. + * - The sortlist comprised of IP address netmask pairs are stored as + * values of the "sortlist" property. The IP address and optional netmask + * should be seperated by a slash (/) or ampersand (&) character. + * - Internal resolver variables can be set from the value of the "options" + * property. + */ + +/* 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 + +#if 0 +/* + * Resolver state default settings. + */ +#endif + +/* Richard Dawe (libsocket): The commented code below was used. Since the + * aliasing isn't very useful for DJGPP programs and stops me + * cross-compiling. */ + +/* RD: Let's keep gcc 2.95.x happy. This was originally in l_res.c, but seems + * to belong better here. _res is a weak symbol, so that the resolver state + * location can be overriden. I don't know how benificial this is, but keep + * it anyhow, because it's part of the original resolver code. */ + +/*extern struct __res_state _res __attribute__ ((weak, alias("__res")));*/ +/*struct __res_state __res = {0};*/ + +struct __res_state _res = {0}; + +/* End RD */ + +static void +res_setoptions(options, source) + char *options, *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 { + /* XXX - print a warning here? */ + } + /* skip to next run of spaces */ + while (*cp && *cp != ' ' && *cp != '\t') + cp++; + } +} + +static u_int16_t +res_randomid() +{ + struct timeval now; + + gettimeofday(&now, NULL); + return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid())); +} + +#ifdef RESOLVSORT +/* XXX - should really support CIDR which means explicit masks always. */ +static u_int32_t +net_mask(in) /* XXX - should really use system's version of this */ + 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 + +/* + * 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[BUFSIZ]; + int nserv = 0; /* number of nameserver records read from file */ + int haveenv = 0; + int havesearch = 0; + char _PATH_RESCONF[1024]; + char *x; +#ifdef RESOLVSORT + int nsort = 0; + char *net; +#endif +#ifndef RFC1535 + int dots; +#endif + /* RD: Used by libsocket extensions. */ + struct in_addr a; + char **p, **q; + /* End RD */ + + /* RD: Use configuration routines now */ + x = __lsck_config_getfile(); + if (x != NULL) { + GetPrivateProfileString("main", "resolv.conf", NULL, + _PATH_RESCONF, sizeof(_PATH_RESCONF), x); + + if (__lsck_debug_enabled()) { + if (*_PATH_RESCONF == '\0') + fprintf(stderr, + "libsocket: Unable to find resolv.conf in %s!\n", x); + else + printf("libsocket: Using '%s' as resolv.conf\n", _PATH_RESCONF); + } + } + + /* + * 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 = 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 */ + if ((cp = __libc_secure_getenv("LOCALDOMAIN")) != NULL) { + (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1); + 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')) + +#ifdef NeXT + if (netinfo_res_init(&haveenv, &havesearch) == 0) +#endif + + /* IM: try to get the name from windows registry... WARNING: untested + completely */ + + /* RD: Configure nameservers using libsocket's routines. */ + + /* RD: Get all DNS IP addresses - this list contains those from + * resolv.conf, for backward-compatibility. */ + p = __lsck_getdnsaddrs(); + + /*printf ("Nameserver: [%s]\n", p[0] );*/ /* Goodbye debug message */ + + if ( p != NULL ) { + q = p; + + /* RD: Add all the DNS IP addresses to the list, up to MAXNS. */ + while( (q[0] != NULL) && (nserv < MAXNS) ) { + inet_aton ( q[0], &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 ++; + _res.nscount = nserv; + free(q[0]); q++; + } + + free (p); + } + + /* RD: Now carry on with normal resolver parsing. */ + if ((fp = fopen(_PATH_RESCONF, "rt")) != 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); + 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); + 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; + } + /* RD: This isn't needed anymore - libsocket parses the list + * (see above). */ + + /* 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; + }*/ + /* End RD */ +#ifdef RESOLVSORT + if (MATCH(buf, "sortlist")) { + struct in_addr a1; + + 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, &a1)) { + _res.sort_list[nsort].addr = a1; + if (ISSORTMASK(n)) { + *cp++ = n; + net = cp; + while (*cp && *cp != ';' && + isascii(*cp) && !isspace(*cp)) + cp++; + n = *cp; + *cp = 0; + if (inet_aton(net, &a1)) { + _res.sort_list[nsort].mask = a1.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 = 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); + } + + /* RD: Modifed to use registry-enabled gethostname */ + + 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 /* DEBUG */ +#endif /* !RFC1535 */ + } + + if ((cp = __libc_secure_getenv("RES_OPTIONS")) != NULL) + res_setoptions(cp, "env"); + _res.options |= RES_INIT; + return (0); +} + diff --git a/src/libc/posix/socket/inet/r_mkqry.c b/src/libc/posix/socket/inet/r_mkqry.c new file mode 100644 index 00000000..514fca9e --- /dev/null +++ b/src/libc/posix/socket/inet/r_mkqry.c @@ -0,0 +1,243 @@ +/* + * ++Copyright++ 1985, 1993 + * - + * Copyright (c) 1985, 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-- + */ + +#include +#include + +#include +#include +#include +#include + +#include "i_priv.h" /* RD: inetprivate.h -> i_priv.h */ +#include "r_opts.h" /* RD: res_options.h -> r_opts.h */ + +void __putshort ( register u_int16_t, register u_char * ); +void __putlong ( register u_int32_t, register u_char * ); + +/* + * Form all types of queries. + * Returns the size of the result or -1. + */ +int +res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen) + int op; /* opcode of query */ + const char *dname; /* domain name */ + int class, type; /* class and 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; +#ifdef ALLOW_UPDATES + struct rrec *newrr = (struct rrec *) newrr_in; +#endif + 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); + bzero(buf, 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(type, cp); + cp += INT16SZ; + __putshort(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((const char *)data, cp, buflen, dnptrs, lastdnptr); + if (n < 0) + return (-1); + cp += n; + buflen -= n; + __putshort(T_NULL, cp); + cp += INT16SZ; + __putshort(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(type, cp); + cp += INT16SZ; + __putshort(class, cp); + cp += INT16SZ; + __putlong(0, cp); + cp += INT32SZ; + __putshort(datalen, cp); + cp += INT16SZ; + if (datalen) { + bcopy(data, cp, datalen); + cp += datalen; + } + hp->ancount = htons(1); + break; + +#ifdef ALLOW_UPDATES + /* + * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA + * (Record to be modified is followed by its replacement in msg.) + */ + case UPDATEM: + case UPDATEMA: + + case UPDATED: + /* + * The res code for UPDATED and UPDATEDA is the same; user + * calls them differently: specifies data for UPDATED; server + * ignores data if specified for UPDATEDA. + */ + case UPDATEDA: + buflen -= RRFIXEDSZ + datalen; + if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) + return (-1); + cp += n; + __putshort(type, cp); + cp += INT16SZ; + __putshort(class, cp); + cp += INT16SZ; + __putlong(0, cp); + cp += INT32SZ; + __putshort(datalen, cp); + cp += INT16SZ; + if (datalen) { + bcopy(data, cp, datalen); + cp += datalen; + } + if ( (op == UPDATED) || (op == UPDATEDA) ) { + hp->ancount = htons(0); + break; + } + /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */ + + case UPDATEA: /* Add new resource record */ + buflen -= RRFIXEDSZ + datalen; + if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) + return (-1); + cp += n; + __putshort(newrr->r_type, cp); + cp += INT16SZ; + __putshort(newrr->r_class, cp); + cp += INT16SZ; + __putlong(0, cp); + cp += INT32SZ; + __putshort(newrr->r_size, cp); + cp += INT16SZ; + if (newrr->r_size) { + bcopy(newrr->r_data, cp, newrr->r_size); + cp += newrr->r_size; + } + hp->ancount = htons(0); + break; +#endif /* ALLOW_UPDATES */ + default: + return (-1); + } + + + return (cp - buf); +} diff --git a/src/libc/posix/socket/inet/r_opts.h b/src/libc/posix/socket/inet/r_opts.h new file mode 100644 index 00000000..59b2a4c4 --- /dev/null +++ b/src/libc/posix/socket/inet/r_opts.h @@ -0,0 +1,172 @@ +/* options.h - specify the conditionally-compiled features + * vix 28mar92 [moved out of the Makefile because they were getting too big] + * + * $Id: r_opts.h,v 1.1.1.1 2000/02/06 10:03:36 rich Exp $ + */ + +/* + * ++Copyright++ + * - + * Copyright (c) + * 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-- + */ + +/* Key: + * ucb = U C Berkeley 4.8.3 release + * vix = Paul Vixie of Digital + * del = Don Lewis of Harris + * mcsun = Piet Beertema of EUNet + * asp = Andrew Partan of UUNet + * pma = Paul Albitz of Hewlett Packard + * bb = Bryan Beecher of UMich + * mpa = Mark Andrews of CSIRO - DMS + * rossc = Ross Cartlidge of The Univeritsy of Sydney + * mtr = Marshall Rose of TPC.INT + * bg = Benoit Grange of INRIA + * ckd = Christopher Davis of Kapor Enterprises + * gns = Greg Shapiro of WPI + * + * RD = Richard Dawe, as part of libsocket + */ + +/* RD: Only define this if it hasn't been already! */ +#ifndef DEBUG +#define DEBUG /* enable -d flag and SIGUSR[12] support (ucb) */ +#endif /* DEBUG */ + +/*#define ALLOW_T_UNSPEC *//* enable the "unspec" RR type for old athena (ucb) */ +/*#define INVQ *//* enable inverse queries (nslookup) (ucb/vix) */ +/*#define DSTORAGE *//* debug malloc overruns using storage.o (ucb/vix) */ +/*#define DMALLOC *//* trace malloc orphans using dmalloc.o (vix) */ +#define XFRNETS /* enable "xfrnets" command in named.boot (vix) */ +#define PID_FIX /* be careful about overwriting named.pid file (del) */ +#define FWD_LOOP /* try to break out of forwarding loops (del) */ +#define NO_GLUE /* don't accept or send out-of-zone glue (del) */ +#define BOGUSNS /* detect bogus nameservers (mcsun) */ +#define QRYLOG /* enable SIGWINCH for query logging (bb) */ +/*#define YPKLUDGE *//* deal effectively with broken "ypserv -i" (mcsun) */ +#define TRACEROOT /* trace bogus root servers and ignore them (pma,bb) */ +/*#define LOCALDOM *//* permit "domain" directive in named.boot (ucb) */ +#define FORCED_RELOAD /* refresh secondary zones on SIGHUP (pma) */ +#define SLAVE_FORWARD /* use sensible timeouts on slave forwarders (pma) */ +#define WANT_PIDFILE /* if you want the named.pid file (ucb/arc) */ +#define DOTTED_SERIAL /* if you want to be able to specify dotted serial#s */ +/*#define SENSIBLE_DOTS *//* if you want dotted serial#s to make numeric sense */ +#define NCACHE /* negative caching (anant@isi.edu) */ +/*#define VALIDATE *//* validation procedure (anant@isi.edu) (DO NOT USE!)*/ +/*#define SHORT_FNAMES *//* file names used in named-xfer need to be short */ +#define RESOLVSORT /* allow sorting of addresses in gethostbyname (mpa) */ +#define STUBS /* allow transfers of NS only for a zone (mpa) */ +#if 0 +#define LOGFAC LOG_DAEMON /* what syslog facility should named use? */ +#endif +#define SECURE_ZONES /* if you want to inhibit world access to zones (gns)*/ +#define ROUND_ROBIN /* rotate databuf list after each access (mtr) */ +#define ADDAUTH /* return NS and glue w/ authorative answers (mpa) */ +#define RFC1535 /* use RFC 1535 default for "search" list (vix) */ +#define GEN_AXFR /* distinct zones within each class */ +#define DATUMREFCNT /* use reference counts on datums (mpa) */ +#define LAME_DELEGATION /* lame delegations (original-del,reworked-bb&del)*/ +#define LAME_LOGGING LOG_WARNING /* log lame delegations, set log level */ +#define GETSER_LOGGING LOG_INFO /* log errors/timeouts getting serial number */ +/*#define RETURNSOA *//* good code that the world isn't ready for yet */ +#define CLEANCACHE /* useful and necessary in the face of NCACHE */ +#define PURGE_ZONE /* remove all traces of a zone when reloading (mpa) */ +#define STATS /* keep nameserver statistics; uses more memory */ +#define RENICE /* named-xfer should run at normal priority */ +#define XSTATS /* extended statistics, syslogged periodically (bg) */ +/*#define BIND_NOTIFY *//* experimental - do not enable in customer products */ +/*#define LOC_RR *//* support for (draft) LOC record parsing (ckd) */ + +/*--------------------------------------------* + * no user-servicable parts beyond this point * + *--------------------------------------------*/ + +/* if DSTORAGE is defined, we need to disable DMALLOC and remap + * malloc and free to storage.o's exported names. storage.o also + * includes a calloc and a realloc, but once we drag in its malloc + * and free we'll get the others automatically and so will never + * pull in those routines from libc.a. + */ +#ifdef DSTORAGE +# ifdef DMALLOC +# undef DMALLOC +# endif /*DMALLOC*/ +# define malloc rt_malloc +# define free rt_free +#endif /*DSTORAGE*/ + +/* if DMALLOC is defined, grab the header file which will remap + * all the malloc-style names to those exported by dmalloc.o. note + * that DMALLOC also changes the function signatures of several + * functions in private named source modules, and that this file + * (options.h) must be included before any other private *.h files + * since those *.h files have some conditional remapping to do. + */ +#ifdef DMALLOC +# include "dmalloc.h" +#endif + +/* systems with killall(1M) don't need this + */ +#ifdef __sgi +# ifdef WANT_PIDFILE +# undef WANT_PIDFILE +# endif +#endif + +#ifdef LAME_LOGGING +//# define LAME_DELEGATION +#endif + +#if defined(XSTATS) && !defined(STATS) +# define STATS +#endif diff --git a/src/libc/posix/socket/inet/r_qry.c b/src/libc/posix/socket/inet/r_qry.c new file mode 100644 index 00000000..153fe6d7 --- /dev/null +++ b/src/libc/posix/socket/inet/r_qry.c @@ -0,0 +1,428 @@ +/* + * ++Copyright++ 1988, 1993 + * - + * Copyright (c) 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-- + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "i_priv.h" /* RD: inetprivate.h -> i_priv.h */ +#include "r_opts.h" /* RD: res_options.h -> r_opts.h */ + +extern char *__libc_secure_getenv(const char *); + +#if PACKETSZ > 1024 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 1024 +#endif + +#ifdef __STDC__ +char *__hostalias (const char *); +int res_querydomain (const char *, const char *, int, int, + u_char *, int); +int res_search ( const char *, int, int, u_char *, int ); +int res_query ( const char *, int, int, u_char *, int ); +#else +char *__hostalias (); +int res_querydomain (); +int res_search (); +int res_query (); +#endif + +/* Richard Dawe (libsocket): h_errno is now stored in l_herrno.c. */ +extern int h_errno; + +/* Richard Dawe (libsocket): The commented code below was used. Since the + * aliasing isn't very useful for DJGPP programs and stops me cross-compiling, + * just make hostalias call the relevant function. */ + +/* RD: Keep gcc 2.95.x happy. */ +/*char *hostalias (const char *) +__attribute__ ((weak, alias("__hostalias")));*/ +/*#pragma weak hostalias = __hostalias*/ + +char *hostalias (const char *name) { return(__hostalias(name)); } + +/* + * 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. + */ +#ifdef __STDC__ +int +res_query( const char *name, int class, int type, u_char *answer, int anslen ) +#else +int +res_query(name, class, type, answer, anslen) + const char *name; /* domain name */ + int class, type; /* class and type of query */ + u_char *answer; /* buffer to put answer */ + int anslen; /* size of answer buffer */ +#endif +{ + u_char buf[MAXPACKET]; + register 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. + */ +#ifdef __STDC__ +int +res_search( const char *name, int class, int type, u_char *answer, int anslen ) +#else +int +res_search(name, class, type, answer, anslen) + const char *name; /* domain name */ + int class, type; /* class and type of query */ + u_char *answer; /* buffer to put answer */ + int anslen; /* size of answer */ +#endif +{ + register 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. + */ + if (!tried_as_is) { + 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. + */ +#ifdef __STDC__ +int +res_querydomain( const char *name, const char *domain, int class, int type, + u_char *answer, int anslen ) +#else +int +res_querydomain(name, domain, class, type, answer, anslen) + const char *name, *domain; + int class, type; /* class and type of query */ + u_char *answer; /* buffer to put answer */ + int anslen; /* size of answer */ +#endif +{ + char nbuf[2*MAXDNAME+2]; + const char *longname = nbuf; + int n; + + 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:"", class, type); +#endif + if (domain == NULL) { + /* + * Check for trailing '.'; + * copy without '.' if present. + */ + n = strlen(name) - 1; + if (n != (0 - 1) && name[n] == '.' && n < (int)sizeof(nbuf) - 1) { + bcopy(name, nbuf, n); + nbuf[n] = '\0'; + } else + longname = name; + } else { + /* won't overflow */ + sprintf(nbuf, "%.*s.%.*s", MAXDNAME, name, MAXDNAME, domain); + } + + return (res_query(longname, class, type, answer, anslen)); +} + +#ifdef __STDC__ +char * +__hostalias( register const char *name ) +#else +char * +__hostalias(name) + register const char *name; +#endif +{ + register char *cp1, *cp2; + FILE *fp; + char *file; + char buf[BUFSIZ]; + static char abuf[MAXDNAME]; + + if (_res.options & RES_NOALIASES) + return (NULL); + file = __libc_secure_getenv("HOSTALIASES"); + if (file == NULL || (fp = fopen(file, "rt")) == 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/src/libc/posix/socket/inet/r_send.c b/src/libc/posix/socket/inet/r_send.c new file mode 100644 index 00000000..8b068129 --- /dev/null +++ b/src/libc/posix/socket/inet/r_send.c @@ -0,0 +1,821 @@ +/* + * ++Copyright++ 1985, 1989, 1993 + * - + * Copyright (c) 1985, 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) 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-- + */ + + /* change this to "0" + * if you talk to a lot + * of multi-homed SunOS + * ("broken") name servers. + */ +#define CHECK_SRVR_ADDR 1 /* XXX - should be in options.h */ + +/* + * Send query to name server and wait for reply. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include /* RD: writev() decl */ + +#include "i_priv.h" /* RD: inetprivate.h -> i_priv.h */ +#include "r_opts.h" /* RD: res_options.h -> r_opts.h */ + +/* void _res_close __P((void)); */ + +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 ciruit? */ + +extern void __putshort(u_short l, u_char *msgp); +void __fp_nquery ( const u_char *, int, FILE * ); + +#ifndef FD_SET +/* XXX - should be in portability.h */ +#define NFDBITS 32 +#define FD_SETSIZE 32 +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) +#endif + +# 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, const 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, const 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 /* ndef DEBUG */ + +typedef res_sendhookact (*res_send_qhook)(); +typedef res_sendhookact (*res_send_rhook)(); + +/* 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)); */ + +static res_send_qhook Qhook = NULL; +static res_send_rhook Rhook = NULL; + +void _res_close( void ); +int res_send( const u_char *, int, u_char *, int ); +int res_queriesmatch( const u_char *, const u_char *, + const u_char *, const u_char * ); +int res_nameinquery( const char *, register int, register int, + const u_char *, const u_char * ); +int res_isourserver( const struct sockaddr_in * ); +void res_send_setrhook( res_send_rhook ); +void res_send_setqhook( res_send_qhook ); + +void +res_send_setqhook( res_send_qhook hook ) +{ + + Qhook = hook; +} + +void +res_send_setrhook( res_send_rhook hook ) +{ + + Rhook = hook; +} + +/* Richard Dawe (libsocket): The commented code below was used. Since the + * aliasing isn't very useful for DJGPP programs and stops me + * cross-compiling. So just make the aliases function calls. */ + +/* RD: gcc 2.95.x doesn't like pragmas. */ +/*#pragma weak __res_isourserver = res_isourserver*/ +/*int __res_isourserver (const struct sockaddr_in *inp) + __attribute__ ((weak, alias("res_isourserver")));*/ + +/* Actually, just don't bother with this alias! */ + +/* End RD */ + +/* 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; + register int ns, ret; + + ina = *inp; + ret = 0; + for (ns = 0; ns < _res.nscount; ns++) { + register 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); +} + +/* Richard Dawe (libsocket): The commented code below was used. Since the + * aliasing isn't very useful for DJGPP programs and stops me + * cross-compiling. So just make the aliases function calls. */ + +/* RD: gcc 2.95.x doesn't like pragmas. */ +/*#pragma weak __res_nameinquery = res_nameinquery*/ +/*int __res_nameinquery (const char *name, register int type, + register int class, const u_char *buf, + const u_char *eom) + __attribute__ ((weak, alias("res_nameinquery")));*/ + +/* Actually, don't bother with this alias. */ + +/* End RD */ + +/* int + * res_nameinquery(name, type, class, buf, eom) + * look for (name,type,class) in the query section of packet (buf,eom) + * returns: + * -1 : format error + * 0 : not found + * >0 : found + * author: + * paul vixie, 29may94 + */ +int +res_nameinquery( const char *name, register int type, register int class, + const u_char *buf, const u_char *eom ) +{ + register const u_char *cp = buf + HFIXEDSZ; + int qdcount = ntohs(((const HEADER*)buf)->qdcount); + + while (qdcount-- > 0) { + char tname[MAXDNAME+1]; + register int n, ttype, tclass; + + n = dn_expand(buf, eom, cp, tname, sizeof tname); + if (n < 0) + return (-1); + cp += n; + ttype = _getshort(cp); cp += INT16SZ; + tclass = _getshort(cp); cp += INT16SZ; + if (ttype == type && + tclass == class && + strcasecmp(tname, name) == 0) + return (1); + } + return (0); +} + +/* Richard Dawe (libsocket): The commented code below was used. Since the + * aliasing isn't very useful for DJGPP programs and stops me + * cross-compiling. So just make the aliases function calls. */ + +/* RD: gcc 2.95.x doesn't like pragmas. */ +/*#pragma weak __res_queriesmatch = res_queriesmatch*/ +/*int __res_queriesmatch (const u_char *buf1, const u_char *eom1, + const u_char *buf2, const u_char *eom2) + __attribute__ ((weak, alias("res_queriesmatch")));*/ + +/* Actually, don't bother with this alias. */ + +/* End RD */ + +/* 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 ) +{ + register const u_char *cp = buf1 + HFIXEDSZ; + int qdcount = ntohs(((const HEADER*)buf1)->qdcount); + + if (qdcount != ntohs(((const HEADER*)buf2)->qdcount)) + return (0); + while (qdcount-- > 0) { + char tname[MAXDNAME+1]; + register int n, ttype, tclass; + + n = dn_expand(buf1, eom1, cp, tname, sizeof tname); + if (n < 0) + return (-1); + cp += n; + ttype = _getshort(cp); cp += INT16SZ; + tclass = _getshort(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 ) +{ + const HEADER *hp = (const HEADER *) buf; + HEADER *anhp = (HEADER *) ans; + int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns; + register int n; + u_int badns; /* XXX NSMAX can't exceed #/bits in this var */ + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + /* errno should have been set by res_init() in this case. */ + 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]; + char *bbuf; + u_short len; + u_char *cp; + + /* + * Use virtual circuit; + * at most one attempt per server. + */ + try = _res.retry; + truncated = 0; + if ((s < 0) || (!vc)) { + 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; + if (connect(s, (struct sockaddr *)nsap, + sizeof(struct sockaddr)) < 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; + bbuf = alloca(buflen); + memcpy(bbuf, buf, buflen); + iov[1].iov_base = bbuf; + 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 + */ + cp = ans; + len = INT16SZ; + while ((n = read(s, (char *)cp, (int)len)) > 0) { + cp += n; + if ((len -= n) <= 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 = _getshort(ans); + if (resplen > anssiz) { + Dprint(_res.options & RES_DEBUG, + (stdout, ";; response truncated\n") + ); + truncated = 1; + len = anssiz; + } else + len = resplen; + cp = ans; + while (len != 0 && + (n = read(s, (char *)cp, (int)len)) > 0) { + cp += n; + 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 = resplen - anssiz; + while (len != 0) { + char junk[PACKETSZ]; + + n = (len > sizeof(junk) + ? sizeof(junk) + : len); + if ((n = read(s, junk, n)) > 0) + len -= n; + else + break; + } + } + } else { + /* + * Use datagrams. + */ + struct timeval timeout; + fd_set dsmask; + struct sockaddr_in from; + + /* Richard Dawe (libsocket): int -> size_t */ + size_t fromlen; + + if ((s < 0) || vc) { + if (vc) + _res_close(); + s = socket(PF_INET, SOCK_DGRAM, 0); + if (s < 0) { +#if !CAN_RECONNECT + bad_dg_sock: +#endif + terrno = errno; + Perror(stderr, "socket(dg)", errno); + return (-1); + } + connected = 0; + } + /* + * 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) { + if (connect(s, (struct sockaddr *)nsap, + sizeof(struct sockaddr) + ) < 0) { + Aerror(stderr, + "connect(dg)", + errno, *nsap); + badns |= (1 << ns); + _res_close(); + goto next_ns; + } + connected = 1; + } + if (send(s, (const 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) { +#if 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 + connected = 0; + errno = 0; + } + if (sendto(s, (const char*)buf, buflen, 0, + (struct sockaddr *)nsap, + sizeof(struct sockaddr)) + != buflen) { + Aerror(stderr, "sendto", errno, *nsap); + badns |= (1 << ns); + _res_close(); + goto next_ns; + } + } + + /* + * Wait for reply + */ + 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; + wait: + FD_ZERO(&dsmask); + FD_SET(s, &dsmask); + n = select(s+1, &dsmask, (fd_set *)NULL, + (fd_set *)NULL, &timeout); + if (n < 0) { + /* This is for those applications who + * sets to signal hanlder but not + * restarting system calls. */ + if (errno == EINTR) + goto wait; + Perror(stderr, "select", errno); + _res_close(); + goto next_ns; + } + 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 = 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 (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); + goto wait; + } +#if 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); + 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); + goto wait; + } + if (anhp->rcode == SERVFAIL || + anhp->rcode == NOTIMP || + anhp->rcode == REFUSED) { + DprintQ(_res.options & RES_DEBUG, + (stdout, "server rejected query:\n"), + ans, 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")); +{ + const char *x=""; + DprintQ((_res.options & RES_DEBUG) || + (_res.pfcode & RES_PRF_REPLY), + (stdout, x), + ans, 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(); + + /* RD: Added braces around if to avoid ambiguity */ + if (!v_circuit) { + if (!gotsomewhere) + errno = ECONNREFUSED; /* no nameservers found */ + else + errno = ETIMEDOUT; /* no answer obtained */ + } else + errno = terrno; + /* End RD */ + + 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( void ) +{ + if (s >= 0) { + (void) close(s); + s = -1; + connected = 0; + vc = 0; + } +} diff --git a/src/libc/posix/socket/inet/rcmd.c b/src/libc/posix/socket/inet/rcmd.c new file mode 100644 index 00000000..3c794b74 --- /dev/null +++ b/src/libc/posix/socket/inet/rcmd.c @@ -0,0 +1,608 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University 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 WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + + +#include "i_priv.h" /* RD: inetprivate.h -> i_priv.h */ +#include +#include +#include +#include + +#include +#include +#include + +#include /* RD: Use configuration routines */ +#include /* RD: Use domain name functions */ +#include /* RD: Use .ini functions */ + +#if NLS +#include "nl_types.h" +#endif + +#ifdef YP +#include +extern void setnetgrent(const char *); +extern void endnetgrent(void); +extern int getnetgrent(char **, char **, char **); +static char *nisdomain = NULL; +static int _checknetgrouphost(const char *, const char *, int); +static int _checknetgroupuser(const char *, const char *); +#endif + +static char HEQUIVDB[1024]; +static char name_buf[1024]; + +int +rresvport(alport) + int *alport; +{ + struct sockaddr_in sin; + int s; + + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = INADDR_ANY; + s = socket(AF_INET, SOCK_STREAM, 0); + if (s < 0) + return (-1); + for (;;) { + sin.sin_port = htons((u_short)*alport); + if (bind(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0) + return (s); + if (errno != EADDRINUSE) { + (void) close(s); + return (-1); + } + (*alport)--; + if (*alport == IPPORT_RESERVED/2) { + (void) close(s); + errno = EAGAIN; /* close */ + return (-1); + } + } +} + +int +rcmd(ahost, rport, locuser, remuser, cmd, fd2p) + char **ahost; + unsigned short rport; + const char *locuser, *remuser, *cmd; + int *fd2p; +{ + int s, timo = 1; +#ifdef F_SETOWN + pid_t pid; +#endif +#ifdef _POSIX_SOURCE + sigset_t set, oset; +#else +/* long oldmask; */ +#endif + struct sockaddr_in sin, from; + char c; + int lport = IPPORT_RESERVED - 1; + struct hostent *hp; + +#if NLS + libc_nls_init(); +#endif + +#ifdef F_SETOWN + pid = getpid(); +#endif + hp = gethostbyname(*ahost); + if (hp == 0 || (int)sizeof (sin.sin_addr) < hp->h_length) { +#if NLS + fprintf(stderr, "%s: %s\n", *ahost, + catgets(_libc_cat, HerrorListSet, + 2, "unknown host")); +#else + fprintf(stderr, "%s: unknown host\n", *ahost); +#endif + return (-1); + } + strlcpy(name_buf, hp->h_name, sizeof(name_buf)); + *ahost = name_buf; +#ifdef SIGURG +#ifdef _POSIX_SOURCE + sigemptyset (&set); + sigaddset (&set, SIGURG); + sigprocmask (SIG_BLOCK, &set, &oset); +#else + oldmask = sigblock(sigmask(SIGURG)); +#endif +#endif + for (;;) { + s = rresvport(&lport); + if (s < 0) { + if (errno == EAGAIN) +#if NLS + fprintf(stderr, "socket: %s\n", + catgets(_libc_cat, NetMiscSet, + NetMiscAllPortsInUse, + "All ports in use")); +#else + fprintf(stderr, "socket: All ports in use\n"); +#endif + else +#if NLS + perror(catgets(_libc_cat, NetMiscSet, + NetMiscRcmdSocket, + "rcmd: socket")); +#else + perror("rcmd: socket"); +#endif +#ifdef SIGURG +#ifdef _POSIX_SOURCE + sigprocmask (SIG_SETMASK, &oset, + (sigset_t *)NULL); +#else + sigsetmask(oldmask); +#endif +#endif + return (-1); + } +#ifdef F_SETOWN + fcntl(s, F_SETOWN, pid); +#endif + sin.sin_family = hp->h_addrtype; + bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, hp->h_length); + sin.sin_port = rport; + if (connect(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0) + break; + (void) close(s); + if (errno == EADDRINUSE) { + lport--; + continue; + } + if (errno == ECONNREFUSED && timo <= 16) { + sleep(timo); + timo *= 2; + continue; + } + if (hp->h_addr_list[1] != NULL) { + int oerrno = errno; + + fprintf(stderr, +#if NLS + "%s %s: ", catgets(_libc_cat, NetMiscSet, + NetMiscAllPortsInUse, + "connect to address"), + inet_ntoa(sin.sin_addr)); + +#else + + "connect to address %s: ", inet_ntoa(sin.sin_addr)); +#endif + errno = oerrno; + perror(0); + hp->h_addr_list++; + bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, + hp->h_length); + +#if NLS + fprintf(stderr, catgets(_libc_cat, NetMiscSet, + NetMiscTrying, + "Trying %s...\n"), +#else + fprintf(stderr, "Trying %s...\n", +#endif + inet_ntoa(sin.sin_addr)); + continue; + } + perror(hp->h_name); +#ifdef SIGURG +#ifdef _POSIX_SOURCE + sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL); +#else + sigsetmask(oldmask); +#endif +#endif + return (-1); + } + lport--; + if (fd2p == 0) { + write(s, "", 1); + lport = 0; + } else { + char num[8]; + int s2 = rresvport(&lport), s3; + + /* Richard Dawe (libsocket): int -> size_t */ + size_t len = sizeof (from); + + if (s2 < 0) + goto bad; + listen(s2, 1); + (void) sprintf(num, "%d", lport); + if (write(s, num, strlen(num)+1) != (int)strlen(num)+1) { +#if NLS + perror(catgets(_libc_cat, NetMiscSet, + NetMiscSettingUpStderr, + "write: setting up stderr")); +#else + perror("write: setting up stderr"); +#endif + (void) close(s2); + goto bad; + } + s3 = accept(s2, (struct sockaddr *)&from, &len); + (void) close(s2); + if (s3 < 0) { +#if NLS + perror(catgets(_libc_cat, NetMiscSet, + NetMiscAccept, + "accept")); +#else + perror("accept"); +#endif + lport = 0; + goto bad; + } + *fd2p = s3; + from.sin_port = ntohs((u_short)from.sin_port); + if (from.sin_family != AF_INET || + from.sin_port >= IPPORT_RESERVED) { + fprintf(stderr, +#if NLS + "%s\n", + catgets(_libc_cat, NetMiscSet, + NetMiscProtocolFailure, + "socket: protocol failure in circuit setup.")); +#else + "socket: protocol failure in circuit setup.\n"); +#endif + goto bad2; + } + } + (void) write(s, locuser, strlen(locuser)+1); + (void) write(s, remuser, strlen(remuser)+1); + (void) write(s, cmd, strlen(cmd)+1); + if (read(s, &c, 1) != 1) { + perror(*ahost); + goto bad2; + } + if (c != 0) { + while (read(s, &c, 1) == 1) { + (void) write(2, &c, 1); + if (c == '\n') + break; + } + goto bad2; + } +#ifdef SIGURG +#ifdef _POSIX_SOURCE + sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL); +#else + sigsetmask(oldmask); +#endif +#endif + return (s); +bad2: + if (lport) + (void) close(*fd2p); +bad: + (void) close(s); +#ifdef SIGURG +#ifdef _POSIX_SOURCE + sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL); +#else + sigsetmask(oldmask); +#endif +#endif + return (-1); +} + +int +ruserok(const char *rhost, int superuser, const char *ruser, + const char *luser) +{ + FILE *hostf; + char *fhost; + int first = 1; + register const char *sp; + register char *p; + int baselen = -1; +// uid_t saveuid; + char *x; + + /* RD: Use configuration routine now */ + /*if ( ( x = getenv ( "windir" ) ) == NULL ) HEQUIVDB[0] = 0;*/ + HEQUIVDB[0] = 0; + x = __lsck_config_getfile(); + if (x != NULL) { + GetPrivateProfileString("main", "hosts.equiv", NULL, + HEQUIVDB, sizeof(HEQUIVDB), x); + } + +// saveuid = geteuid(); + sp = rhost; + fhost = alloca (strlen (rhost) + 1); + p = fhost; + while (*sp) { + if (*sp == '.') { + if (baselen == -1) + baselen = sp - rhost; + *p++ = *sp++; + } else { + *p++ = isupper(*sp) ? tolower(*sp++) : *sp++; + } + } + *p = '\0'; + hostf = superuser ? (FILE *)0 : fopen(HEQUIVDB, "rt"); +again: + if (hostf) { + if (!_validuser(hostf, fhost, luser, ruser, baselen)) { + (void) fclose(hostf); +/* IM: no point seteuid(saveuid); */ + return(0); + } + (void) fclose(hostf); + } + if (first == 1) { + struct stat sbuf; + struct passwd *pwd; + char *pbuf; + + first = 0; + + /* RD: Under DJGPP, this will probably fail, so ignore failure. */ + /*if ((pwd = getpwnam(luser)) == NULL) return(-1);*/ + pwd = getpwnam(luser); + + /* RD: Need to be more flexible here */ + /*pbuf = alloca (strlen (pwd->pw_dir) + sizeof ("/.rhosts") + 1);*/ + pbuf = malloc(PATH_MAX); + if (pbuf == NULL) return(-1); + pbuf[0] = '\0'; + + /* + RD: Look for ".rhosts" in various places: + + 1. In the user's home directory, as ".rhosts". + 2. In the user's home directory, as "rhosts". + 3. In the user's home directory, as "_rhosts". + 4. In the place specified in the libsocket configuration file. + */ + + if (pwd != NULL) { + /* .rhosts */ + strcpy(pbuf, pwd->pw_dir); + strcat(pbuf, "/.rhosts"); + + if (access(pbuf, R_OK) != 0) { /* Can't find it! */ + /* Try rhosts */ + strcpy(pbuf, pwd->pw_dir); + strcat(pbuf, "/rhosts"); + + /* Can't find rhosts, so try _rhosts. */ + if (access(pbuf, R_OK) != 0) { + strcpy(pbuf, pwd->pw_dir); + strcat(pbuf, "/_rhosts"); + } pbuf[0] = '\0'; + + /* Can't find it! */ + if (access(pbuf, R_OK) != 0) pbuf[0] = '\0'; + } + } + + /* libsocket configuration */ + if (pbuf[0] == '\0') { + x = __lsck_config_getfile(); + if (x != NULL) { + GetPrivateProfileString("main", ".rhosts", NULL, + pbuf, PATH_MAX, x); + } + } + +/* (void)strcpy(pbuf, pwd->pw_dir); + (void)strcat(pbuf, "/.rhosts");*/ +/* IM: (void)seteuid(pwd->pw_uid); no point */ + + if ((hostf = fopen(pbuf, "rt")) == NULL) { +/* seteuid(saveuid); */ + free(pbuf); /* RD: Stop leaks */ + return(-1); + } + (void)fstat(fileno(hostf), &sbuf); + if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) { + fclose(hostf); +/* seteuid(saveuid); */ + free(pbuf); /* RD: Stop leaks */ + return(-1); + } + free(pbuf); /* RD: Stop leaks */ + goto again; + } +/* seteuid(saveuid); */ + return (-1); +} + +int +_validuser(FILE *hostf, const char *rhost, const char *luser, + const char *ruser, int baselen) +{ + char *user; + char ahost[MAXHOSTNAMELEN]; + register char *p; +#ifdef YP + int hostvalid = 0; + int uservalid = 0; +#endif + + while (fgets(ahost, sizeof (ahost), hostf)) { + /* We need to get rid of all comments. */ + p = strchr (ahost, '#'); + if (p) *p = '\0'; + p = ahost; + while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') { + *p = isupper(*p) ? tolower(*p) : *p; + p++; + } + if (*p == ' ' || *p == '\t') { + *p++ = '\0'; + while (*p == ' ' || *p == '\t') + p++; + user = p; + while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') + p++; + } else + user = p; + *p = '\0'; +#ifdef YP + uservalid = hostvalid = 0; + /* disable host from -hostname entry */ + if ('-' == ahost[0] && '@' != ahost[1] + && _checkhost(rhost, &ahost[1], baselen)) + hostvalid = 1; + /* disable host from -@netgroup entry for host */ + if ('-' == ahost[0] && '@' == ahost[1] && '\0' != ahost[2] + && _checknetgrouphost(rhost, &ahost[2], baselen)) + hostvalid = 1; + /* disable user from -user entry */ + if ('\0' != *user && user[0] == '-' && user[1] != '@' + && !strcmp(&user[1], ruser)) + uservalid = 1; + /* disable user from -@netgroup entry for user */ + if ('\0' != *user && user[0] == '-' && user[1] == '@' + && user[2] != '\0' && _checknetgroupuser(ruser, &user[2])) + uservalid = 1; + if (hostvalid && (uservalid || *user == '\0')) + return -1; + + /* enable host from +@netgroup entry for host */ + if ('+' == ahost[0] && '@' == ahost[1] && '\0' != ahost[2]) + hostvalid = _checknetgrouphost(rhost, &ahost[2], baselen); + else + hostvalid = _checkhost(rhost, ahost, baselen); + /* enable user from +@netgroup entry for user */ + /* -@netgroup entry already gave uservalid=1 */ + if (user[0] == '+') + if (user[1] == '@' && user[2] != '\0') + uservalid = _checknetgroupuser(ruser, &user[2]); + else uservalid = !strcmp(&user[1], ruser); + else if (user[0] == '-') + uservalid = -uservalid; + else + uservalid = !strcmp(ruser, *user ? user : luser); + + if (hostvalid) + if (uservalid == 1) + return 0; + else if (uservalid == -1) + return (-1); +#else + if (_checkhost(rhost, ahost, baselen) && + !strcmp(ruser, *user ? user : luser)) { + return (0); + } +#endif /* YP */ + } + return (-1); +} + +int +_checkhost(const char *rhost, const char *lhost, int len) +{ + static char ldomain[MAXHOSTNAMELEN + 1]; + static char *domainp = NULL; + static int nodomain = 0; + register char *cp; + + if (len == -1) + return(!strcmp(rhost, lhost)); + if (strncmp(rhost, lhost, len)) + return(0); + if (!strcmp(rhost, lhost)) + return(1); + if (*(lhost + len) != '\0') + return(0); + if (nodomain) + return(0); + if (!domainp) { + if (getdomainname(ldomain, sizeof(ldomain)) == -1) { + nodomain = 1; + return(0); + } + ldomain[MAXHOSTNAMELEN] = (char) 0; + domainp = ldomain; + for (cp = domainp; *cp; ++cp) + if (isupper(*cp)) + *cp = tolower(*cp); + } + return(!strcmp(domainp, rhost + len +1)); +} + +#ifdef YP +static int +_checknetgrouphost(const char *rhost, const char *netgr, int baselen) +{ + char *host, *user, *domain; + int status; + + if (NULL == nisdomain) + yp_get_default_domain(&nisdomain); + + setnetgrent(netgr); + while (1) + { + status = getnetgrent(&host, &user, &domain); + + if (0 == status) + { + endnetgrent(); + return 0; + } + + if((domain == NULL || !strcmp(domain, nisdomain)) + && (host == NULL || _checkhost(rhost, host, baselen))) + { + endnetgrent(); + return 1; + } + } +} + +static int +_checknetgroupuser(const char *ruser, const char *netgr) +{ + char *host, *user, *domain; + int status; + + if (NULL == nisdomain) + yp_get_default_domain(&nisdomain); + + setnetgrent(netgr); + while (1) + { + status = getnetgrent(&host, &user, &domain); + + if (0 == status) + { + endnetgrent(); + return 0; + } + + if((domain == NULL || 0 == strcmp(domain, nisdomain)) + && (user == NULL || 0 == strcmp(ruser, user))) + { + endnetgrent(); + return 1; + } + } +} +#endif /* YP */ diff --git a/src/libc/posix/socket/inet/rexec.c b/src/libc/posix/socket/inet/rexec.c new file mode 100644 index 00000000..1332e2a4 --- /dev/null +++ b/src/libc/posix/socket/inet/rexec.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 1980, 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 "i_priv.h" /* RD: inetprivate.h -> i_priv.h */ + +#include + +int rexecoptions; + +int +rexec( char **ahost, int rport, const char *name, const char *pass, + const char *cmd, int *fd2p ) +{ + int s, timo = 1, s3; + struct sockaddr_in sin, sin2, from; + char c; + u_short port; + struct hostent *hp; + static char savename[256]; + +#if NLS + libc_nls_init(); +#endif + hp = gethostbyname(*ahost); + if (hp == 0 || (int)sizeof (sin.sin_addr) < hp->h_length) { +#if NLS + fprintf(stderr, "%s: %s\n", *ahost, + catgets(_libc_cat, HerrorListSet, + 2, "unknown host")); +#else + fprintf(stderr, "%s: unknown host\n", *ahost); +#endif + return (-1); + } + sin.sin_family = hp->h_addrtype; + sin.sin_port = rport; + memcpy ((caddr_t)&sin.sin_addr, hp->h_addr, hp->h_length); + strncpy((*ahost = savename), hp->h_name, sizeof(savename) -1); + ruserpass(*ahost, &name, &pass); +retry: + s = socket(AF_INET, SOCK_STREAM, 0); + if (s < 0) { +#if NLS + perror(catgets(_libc_cat, NetMiscSet, + NetMiscRexecSocket, + "rcmd: socket")); +#else + perror("rexec: socket"); +#endif + return (-1); + } + if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { + if (errno == ECONNREFUSED && timo <= 16) { + (void) close(s); + sleep(timo); + timo *= 2; + goto retry; + } + perror(*ahost); + return (-1); + } + port = 0; /* For GCC */ + if (fd2p == 0) { + (void) write(s, "", 1); + port = 0; + } else { + char num[32]; + int s2; + /* Richard Dawe (libsocket): int -> size_t */ + size_t sin2len; + + s2 = socket(AF_INET, SOCK_STREAM, 0); + if (s2 < 0) { + (void) close(s); + return (-1); + } + sin2len = sizeof (sin2); + sin2.sin_addr.s_addr = INADDR_ANY; + sin2.sin_family = sin.sin_family; + bind(s2, (struct sockaddr *)&sin2, sin2len); + listen(s2, 1); + if (getsockname(s2, (struct sockaddr *)&sin2, &sin2len) < 0 || + sin2len != sizeof (sin2)) { +#if NLS + perror(catgets(_libc_cat, NetMiscSet, + NetMiscGetsockname, + "getsockname")); +#else + perror("getsockname"); +#endif + (void) close(s2); + goto bad; + } + port = ntohs((u_short)sin2.sin_port); + (void) sprintf(num, "%u", port); + (void) write(s, num, strlen(num)+1); + { + /* Richard Dawe (libsocket): int -> size_t */ + size_t len = sizeof (from); + s3 = accept(s2, (struct sockaddr *)&from, &len); + close(s2); + if (s3 < 0) { +#if NLS + perror(catgets(_libc_cat, NetMiscSet, + NetMiscAccept, + "accept")); +#else + perror("accept"); +#endif + port = 0; + goto bad; + } + } + *fd2p = s3; + } + (void) write(s, name, strlen(name) + 1); + /* should public key encypt the password here */ + (void) write(s, pass, strlen(pass) + 1); + (void) write(s, cmd, strlen(cmd) + 1); + if (read(s, &c, 1) != 1) { + perror(*ahost); + goto bad; + } + if (c != 0) { + while (read(s, &c, 1) == 1) { + (void) write(2, &c, 1); + if (c == '\n') + break; + } + goto bad; + } + return (s); +bad: + if (port) + (void) close(*fd2p); + (void) close(s); + return (-1); +} diff --git a/src/libc/posix/socket/inet/rusrpass.c b/src/libc/posix/socket/inet/rusrpass.c new file mode 100644 index 00000000..cb0c4a0e --- /dev/null +++ b/src/libc/posix/socket/inet/rusrpass.c @@ -0,0 +1,1041 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University 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 WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + Some modifications by Richard Dawe (RD) for use with libsocket. Some + modifications made by RD based on Phillipe Hanrigou's (PH) code. Comments + are indicated by "RD:" or "PH:" respectively. +*/ + +#include "i_priv.h" /* RD: inetprivate.h -> i_priv.h */ +#include +#include +#include + +/* RD: Includes */ +#include +#include +#include + +#include + +#include +#include +/* End RD */ + +/* Start RD: utmp def's */ +/* This uses the same order as DJGPP's tmpnam() to find the temporary dir. */ +static char *fake_path_utmp (void) +{ + char *p = NULL; + p = getenv("TMPDIR"); + if (p == NULL) p = getenv("TEMP"); + if (p == NULL) p = getenv("TMP"); + return(p); +} + +#define _PATH_UTMP ( fake_path_utmp() ) + +#define UT_LINESIZE 12 +#define UT_NAMESIZE 8 +#define UT_HOSTSIZE 16 + +struct utmp +{ + short ut_type; /* type of login */ + pid_t ut_pid; /* pid of login-process */ + char ut_line[UT_LINESIZE]; /* devicename of tty -"/dev/", null-term */ + char ut_id[4]; /* inittab id */ + time_t ut_time; /* login time */ + char ut_user[UT_NAMESIZE]; /* username, not null-term */ + char ut_host[UT_HOSTSIZE]; /* hostname for remote login... */ + long ut_addr; /* IP addr of remote host */ +}; +/* End RD */ + +extern char *__libc_secure_getenv(const char *); + +static FILE *cfile; + +static int token( void ); +static void rnetrc(const char *, const char **, const char ** ); +static char *renvlook( const char * ); +static void renv( const char *, const char **, const char ** ); +static void mkpwclear( char *, char, const char * ); +static char *mkenvkey( char ); +static void sreverse( register char *, register char * ); +static struct utmp *getutmp(char * ); +static void blkencrypt(char *, int ); +static void nbssetkey( char * ); +static void enblknot( char *, char * ); +static char *deblkclr( char * ); +static void enblkclr( char *, char * ); +static char *nbs8decrypt( char *, char * ); +static void mkpwclear( char *, char, const char * ); +static char *mkenvkey( char ); +static void sreverse( register char *, register char * ); +static struct utmp *getutmp( char * ); +static void blkencrypt( char *, int ); +static void nbssetkey( char * ); +static void enblknot( char *, char * ); +static char *deblkclr( char * ); +static void enblkclr( char *, char * ); +static char *nbs8decrypt( char *, char * ); +static char *nbsdecrypt( const char *, char *, char * ); + +#if NLS +#include "nl_types.h" +#endif + +void +ruserpass(const char *host, const char **aname, const char **apass) +{ + static char namebuf [256]; + struct hostent *hp; + char name[256]; /* a temp name buffer to avoid overlayyed */ + +#if NLS + libc_nls_init(); +#endif + strncpy(name, host, sizeof(name) - 1); + + if ((hp = gethostbyname (name))) + strncpy(name,hp->h_name, sizeof(name) - 1); + renv(name, aname, apass); + if (*aname == 0 || *apass == 0) + rnetrc(name, aname, apass); /*rnetrc would call gethostbyname */ + if (*aname == 0) { + *aname = getlogin(); + if (*aname == NULL) { + struct passwd *pp = getpwuid(getuid()); + if (pp != NULL) + *aname = pp->pw_name; + } +#if NLS + printf("%s (%s:%s): ", + catgets(_libc_cat, NetMiscSet, NetMiscName, "Name"), + host, *aname); +#else + printf("Name (%s:%s): ", host, *aname); +#endif + fflush(stdout); + if (read(2, namebuf, sizeof (namebuf)) <= 0) { + perror ("read"); + exit(1); + } + if (namebuf [0] != '\n') { + char *ptr; + *aname = namebuf; + namebuf [sizeof (namebuf) - 1] = '0'; + if ((ptr = index(namebuf, '\n'))) + *ptr = 0; + } + } + if (*aname && *apass == 0) { +#if NLS + printf("%s (%s:%s): ", + catgets(_libc_cat, NetMiscSet, NetMiscPassword, "Password"), + host, *aname); +#else + printf("Password (%s:%s): ", host, *aname); +#endif + fflush(stdout); + *apass = getpass(""); + } +} + +static void +renv(const char *host, const char **aname, const char **apass) +{ + register char *cp; + char *comma; + + cp = renvlook(host); + if (cp == NULL) + return; + if (!isalpha(cp[0])) + return; + comma = index(cp, ','); + if (comma == 0) + return; + if (*aname == 0) { + char *_aname = malloc(comma - cp + 1); + strncpy(_aname, cp, comma - cp); + *aname = _aname; + } else + if (strncmp(*aname, cp, comma - cp)) + return; + comma++; + cp = malloc(strlen(comma)+1); + strcpy(cp, comma); + *apass = malloc(16); + mkpwclear(cp, host[0], *apass); +} + +//#if !defined(HAVE_GNU_LD) && !defined (__ELF__) +#define __environ environ +//#endif + +static char * +renvlook(const char *host) +{ + register char *cp, **env; + extern char **__environ; + + for (env = __environ; *env != NULL; env++) + if (!strncmp(*env, "MACH", 4)) { + cp = index(*env, '='); + if (cp == 0) + continue; + if (strncmp(*env+4, host, cp-(*env+4))) + continue; + return (cp+1); + } + return (NULL); +} + +#define DEFAULT 1 +#define LOGIN 2 +#define PASSWD 3 +#define NOTIFY 4 +#define WRITE 5 +#define YES 6 +#define NO 7 +#define COMMAND 8 +#define FORCE 9 +#define ID 10 +#define MACHINE 11 + +static char tokval[100]; + +static struct toktab { + const char *tokstr; + int tval; +} toktab[]= { + { "default", DEFAULT }, + { "login", LOGIN }, + { "password", PASSWD }, + { "notify", NOTIFY }, + { "write", WRITE }, + { "yes", YES }, + { "y", YES }, + { "no", NO }, + { "n", NO }, + { "command", COMMAND }, + { "force", FORCE }, + { "machine", MACHINE }, + { 0, 0 } +}; + +static void +rnetrc(const char *host, const char **aname, const char **apass) +{ + char *hdir, *buf; + int t; + struct stat stb; + struct hostent *hp; + char *cfg = NULL; /* RD: libsocket's config file */ + +#if NLS + libc_nls_init(); +#endif + /* + * Use __libc_secure_getenv -- otherwise you can probably read any + * file on the system by setting $HOME to /tmp/foo and linking + * /tmp/foo/.netrc, if you can find a setuid program using this code. + * Also, if we can't get HOME, fail instead of trying ".", which is + * no improvement. This really should call getpwuid(getuid()). + */ + + /* RD: We need to look a bit harder than this... */ + /*hdir = __libc_secure_getenv("HOME"); + if (hdir == NULL) {*/ + /* hdir = "."; */ + /* NO! return instead */ + /*return; + } + buf = alloca (strlen (hdir) + sizeof ("/.netrc") + 1); + (void)sprintf(buf, "%s/.netrc", hdir);*/ + + /* + Try to find the netrc file in the following way: + + 1. Home directory, called ".netrc". + 2. Home directory, called "netrc". + 3. Home directory, called "_netrc", as suggested by Phillipe Hanrigou. + 4. As specified by ".netrc" in the libsocket configuration file. + */ + + /* Look in the home directory for .netrc, netrc */ + buf = malloc(PATH_MAX); + if (buf == NULL) return; + + hdir = __libc_secure_getenv("HOME"); + if (hdir == NULL) return; + sprintf(buf, "%s/.netrc", hdir); + if (access(buf, R_OK) != 0) sprintf(buf, "%s/netrc", hdir); + if (access(buf, R_OK) != 0) sprintf(buf, "%s/_netrc", hdir); + + /* OK, now try looking at libsocket's config file */ + if (access(buf, R_OK) != 0) { + cfg = __lsck_config_getfile(); + if (cfg == NULL) { free(buf); return; } + GetPrivateProfileString("main", ".netrc", NULL, buf, sizeof(buf), cfg); + } + /* End RD */ + + cfile = fopen(buf, "rt"); + if (cfile == NULL) { + if (errno != ENOENT) + perror(buf); + free(buf); /* RD: Don't want a memory leak! */ + return; + } +next: + while ((t = token())) switch(t) { + + case DEFAULT: + (void) token(); + continue; + + case MACHINE: + if (token() != ID) + continue; + if((hp = gethostbyname (tokval))) + { + if (strcmp(host, hp->h_name)) + continue; + } + else + if (strcmp(host, tokval)) + continue; + while ((t = token()) && t != MACHINE) switch(t) { + + case LOGIN: + if (token()) { + if (*aname == 0) { + char *_aname = malloc(strlen(tokval) + 1); + strcpy(_aname, tokval); + *aname = _aname; + } else { + if (strcmp(*aname, tokval)) + goto next; + } + } + break; + case PASSWD: + /* RD: Phillipe Hanrigou patch here! */ + if ( ((*aname == NULL) || (strcmp(*aname, "anonymous"))) + && (fstat(fileno(cfile), &stb) >= 0) + && ((stb.st_mode & 077) != 0) + ) { +#if NLS + fprintf(stderr, "%s\n", catgets(_libc_cat, NetMiscSet, + NetMiscNetrcWrongPasswordMode, + "Error - .netrc file not correct mode.\n\ + Remove password or correct mode.")); +#else + fprintf(stderr, "Error - .netrc file not correct mode.\n"); + fprintf(stderr, "Remove password or correct mode.\n"); +#endif + /* RD: Too harsh for DJGPP */ + /*exit(1);*/ + + /* + * Philippe HANRIGOU - 11/12/98 + * + * Dos and Windows95 are not really famous as multiuser + * platforms. ;-) Let's allow .netrc to be readable by + * others and just display a warning. + */ + /* RD: Multi-line string used now. */ + fprintf(stderr, "\nWARNING: .netrc file is readable by " + "others and contains password(s) in \nplain " + "text. Please note this is a BIG SECURITY " + "HOLE if somebody else has\naccess to " + "your computer. Maybe it would be a good " + "idea to remove\npassword(s).\n\n"); + } + + if (token() && *apass == 0) { + char *_apass = malloc(strlen(tokval) + 1); + strcpy(_apass, tokval); + *apass = _apass; + } + break; + case COMMAND: + case NOTIFY: + case WRITE: + case FORCE: + (void) token(); + break; + default: +#if NLS + fprintf(stderr, "%s %s\n", + catgets(_libc_cat, NetMiscSet, + NetMiscUnknownNetrcOption, + "Unknown .netrc option"), + tokval); +#else + fprintf(stderr, "Unknown .netrc option %s\n", tokval); +#endif + break; + } + goto done; + } +done: + fclose(cfile); + free(buf); /* RD: Don't want a memory leak! */ +} + +static int +token( void ) +{ + char *cp; + int c; + struct toktab *t; + + if (feof(cfile)) + return (0); +#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(_REENTRANT) +#undef getc +#define getc getc_unlocked + flockfile (cfile); +#endif + while ((c = getc(cfile)) != EOF && + (c == '\n' || c == '\t' || c == ' ' || c == ',')) + continue; + if (c == EOF) + return (0); + cp = tokval; + if (c == '"') { + while ((c = getc(cfile)) != EOF && c != '"') { + if (c == '\\') + c = getc(cfile); + *cp++ = c; + } + } else { + *cp++ = c; + while ((c = getc(cfile)) != EOF + && c != '\n' && c != '\t' && c != ' ' && c != ',') { + if (c == '\\') + c = getc(cfile); + *cp++ = c; + } + } +#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) || defined(_REENTRANT) + funlockfile (cfile); +#endif + *cp = 0; + if (tokval[0] == 0) + return (0); + for (t = toktab; t->tokstr; t++) + if (!strcmp(t->tokstr, tokval)) + return (t->tval); + return (ID); +} + +/* rest is nbs.c stolen from berknet */ + +#if 0 +static char *nbsencrypt(char *, char *, char * ); +static char *nbs8encrypt(char *, char * ); +static char *deblknot(char * ); +#endif + +static char E[48]; + +/* + * The E bit-selection table. + */ +static char e[] = { + 32, 1, 2, 3, 4, 5, + 4, 5, 6, 7, 8, 9, + 8, 9,10,11,12,13, + 12,13,14,15,16,17, + 16,17,18,19,20,21, + 20,21,22,23,24,25, + 24,25,26,27,28,29, + 28,29,30,31,32, 1, +}; + +#if 0 +/* + * Warning -- do not enable any of this without checking it carefully + * for buffer overflows. + */ +static +char *nbsencrypt( char *str, char *key, char *result ) +{ + static char buf[20],oldbuf[20]; + register int j; + result[0] = 0; + strcpy(oldbuf,key); + while(*str){ + for(j=0;j<10;j++)buf[j] = 0; + for(j=0;j<8 && *str;j++)buf[j] = *str++; + strcat(result,nbs8encrypt(buf,oldbuf)); + strcat(result,"$"); + strcpy(oldbuf,buf); + } + return(result); +} + +#endif /* if 0 */ + +static +char *nbsdecrypt( const char *_cpt, char *key, char *result ) +{ + char *s; + char c,oldbuf[20],__cpt[128],*cpt=__cpt; + result[0] = 0; + strcpy(oldbuf,key); + strlcpy(cpt, _cpt, sizeof(cpt)); + while(*cpt){ + for(s = cpt;*s && *s != '$';s++); + c = *s; + *s = 0; + strcpy(oldbuf,nbs8decrypt(cpt,oldbuf)); + strcat(result,oldbuf); + if(c == 0)break; + cpt = s + 1; + } + return(result); +} + +#if 0 +static +char *nbs8encrypt( char *str, char *key ) +{ + static char keyblk[100], blk[100]; + register int i; + + enblkclr(keyblk,key); + nbssetkey(keyblk); + + for(i=0;i<48;i++) E[i] = e[i]; + enblkclr(blk,str); + blkencrypt(blk,0); /* forward dir */ + + return(deblknot(blk)); +} + +#endif /* if 0 */ + +static +char *nbs8decrypt( char *crp, char *key ) +{ + static char keyblk[100], blk[100]; + register int i; + + enblkclr(keyblk,key); + nbssetkey(keyblk); + + for(i=0;i<48;i++) E[i] = e[i]; + enblknot(blk,crp); + blkencrypt(blk,1); /* backward dir */ + + return(deblkclr(blk)); +} + +static void +enblkclr( char *blk, char *str ) + /* ignores top bit of chars in string str */ +{ + register int i,j; + char c; + for(i=0;i<70;i++)blk[i] = 0; + for(i=0; (c= *str) && i<64; str++){ + for(j=0; j<7; j++, i++) + blk[i] = (c>>(6-j)) & 01; + i++; + } +} + +static +char *deblkclr( char *blk ) +{ + register int i,j; + char c; + static char iobuf[30]; + for(i=0; i<10; i++){ + c = 0; + for(j=0; j<7; j++){ + c <<= 1; + c |= blk[8*i+j]; + } + iobuf[i] = c; + } + iobuf[i] = 0; + return(iobuf); +} + +static void +enblknot( char *blk, char *crp ) +{ + register int i,j; + char c; + for(i=0;i<70;i++)blk[i] = 0; + for(i=0; (c= *crp) && i<64; crp++){ + if(c>'Z') c -= 6; + if(c>'9') c -= 7; + c -= '.'; + for(j=0; j<6; j++, i++) + blk[i] = (c>>(5-j)) & 01; + } +} + +#if 0 +static +char *deblknot( char *blk ) +{ + register int i,j; + char c; + static char iobuf[30]; + for(i=0; i<11; i++){ + c = 0; + for(j=0; j<6; j++){ + c <<= 1; + c |= blk[6*i+j]; + } + c += '.'; + if(c > '9')c += 7; + if(c > 'Z')c += 6; + iobuf[i] = c; + } + iobuf[i] = 0; + return(iobuf); +} +#endif + + +/* + * This program implements the + * Proposed Federal Information Processing + * Data Encryption Standard. + * See Federal Register, March 17, 1975 (40FR12134) + */ + +/* + * Initial permutation, + */ +static char IP[] = { + 58,50,42,34,26,18,10, 2, + 60,52,44,36,28,20,12, 4, + 62,54,46,38,30,22,14, 6, + 64,56,48,40,32,24,16, 8, + 57,49,41,33,25,17, 9, 1, + 59,51,43,35,27,19,11, 3, + 61,53,45,37,29,21,13, 5, + 63,55,47,39,31,23,15, 7, +}; + +/* + * Final permutation, FP = IP^(-1) + */ +static char FP[] = { + 40, 8,48,16,56,24,64,32, + 39, 7,47,15,55,23,63,31, + 38, 6,46,14,54,22,62,30, + 37, 5,45,13,53,21,61,29, + 36, 4,44,12,52,20,60,28, + 35, 3,43,11,51,19,59,27, + 34, 2,42,10,50,18,58,26, + 33, 1,41, 9,49,17,57,25, +}; + +/* + * Permuted-choice 1 from the key bits + * to yield C and D. + * Note that bits 8,16... are left out: + * They are intended for a parity check. + */ +static char PC1_C[] = { + 57,49,41,33,25,17, 9, + 1,58,50,42,34,26,18, + 10, 2,59,51,43,35,27, + 19,11, 3,60,52,44,36, +}; + +static char PC1_D[] = { + 63,55,47,39,31,23,15, + 7,62,54,46,38,30,22, + 14, 6,61,53,45,37,29, + 21,13, 5,28,20,12, 4, +}; + +/* + * Sequence of shifts used for the key schedule. +*/ +static char shifts[] = { + 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1, +}; + +/* + * Permuted-choice 2, to pick out the bits from + * the CD array that generate the key schedule. + */ +static char PC2_C[] = { + 14,17,11,24, 1, 5, + 3,28,15, 6,21,10, + 23,19,12, 4,26, 8, + 16, 7,27,20,13, 2, +}; + +static char PC2_D[] = { + 41,52,31,37,47,55, + 30,40,51,45,33,48, + 44,49,39,56,34,53, + 46,42,50,36,29,32, +}; + +/* + * The C and D arrays used to calculate the key schedule. + */ + +static char C[28]; +static char D[28]; +/* + * The key schedule. + * Generated from the key. + */ +static char KS[16][48]; + +/* + * Set up the key schedule from the key. + */ + +static void +nbssetkey( char *key ) +{ + register int i, j, k; + int t; + + /* + * First, generate C and D by permuting + * the key. The low order bit of each + * 8-bit char is not used, so C and D are only 28 + * bits apiece. + */ + for (i=0; i<28; i++) { + C[i] = key[PC1_C[i]-1]; + D[i] = key[PC1_D[i]-1]; + } + /* + * To generate Ki, rotate C and D according + * to schedule and pick up a permutation + * using PC2. + */ + for (i=0; i<16; i++) { + /* + * rotate. + */ + for (k=0; k>3)&01; + f[t+1] = (k>>2)&01; + f[t+2] = (k>>1)&01; + f[t+3] = (k>>0)&01; + } + /* + * The new R is L ^ f(R, K). + * The f here has to be permuted first, though. + */ + for (j=0; j<32; j++) + R[j] = L[j] ^ f[P[j]-1]; + /* + * Finally, the new L (the original R) + * is copied back. + */ + for (j=0; j<32; j++) + L[j] = tempL[j]; + } + /* + * The output L and R are reversed. + */ + for (j=0; j<32; j++) { + t = L[j]; + L[j] = R[j]; + R[j] = t; + } + /* + * The final output + * gets the inverse permutation of the very original. + */ + for (j=0; j<64; j++) + block[j] = L[FP[j]-1]; +} +/* + getutmp() + return a pointer to the system utmp structure associated with + terminal sttyname, e.g. "/dev/tty3" + Is version independent-- will work on v6 systems + return NULL if error +*/ +static +struct utmp *getutmp(char *sttyname) +{ + static struct utmp utmpstr; + FILE *fdutmp; + + if(sttyname == NULL || sttyname[0] == 0)return(NULL); + + fdutmp = fopen(_PATH_UTMP,"rt"); + if(fdutmp == NULL)return(NULL); + + while(fread(&utmpstr,1,sizeof utmpstr,fdutmp) == sizeof utmpstr) + if(strcmp(utmpstr.ut_line,sttyname+5) == 0){ + fclose(fdutmp); + return(&utmpstr); + } + fclose(fdutmp); + return(NULL); +} + +static void +sreverse( register char *sto, register char *sfrom ) +{ + register int i; + + i = strlen(sfrom); + while (i >= 0) + *sto++ = sfrom[i--]; +} + +static +char *mkenvkey(char mch) +{ + static char skey[40]; + register struct utmp *putmp; + char stemp[40], stemp1[40]; + /* FUTURE: remove the limit on this size */ + char sttyname[30]; + register char *sk,*p; + + if (isatty(2)) + strncpy(sttyname,ttyname(2), sizeof(sttyname)); + else if (isatty(0)) + strncpy(sttyname,ttyname(0), sizeof(sttyname)); + else if (isatty(1)) + strncpy(sttyname,ttyname(1), sizeof(sttyname)); + else + return (NULL); + sttyname[sizeof(sttyname)-1] = 0; + putmp = getutmp(sttyname); + if (putmp == NULL) + return (NULL); + sk = skey; + p = putmp->ut_line; + while (*p) + *sk++ = *p++; + *sk++ = mch; + (void)sprintf(stemp, "%ld", (long) putmp->ut_time); + sreverse(stemp1, stemp); + p = stemp1; + while (*p) + *sk++ = *p++; + *sk = 0; + return (skey); +} + +#if 0 +static void +mkpwunclear( char *spasswd, char mch, char *sencpasswd ) +{ + register char *skey; + + if (spasswd[0] == 0) { + sencpasswd[0] = 0; + return; + } + skey = mkenvkey(mch); + if (skey == NULL) { + fprintf(stderr, "Can't make key\n"); + exit(1); + } + nbsencrypt(spasswd, skey, sencpasswd); +} + +#endif + +static void +mkpwclear( char *spasswd, char mch, const char *sencpasswd ) +{ + register char *skey; + + if (sencpasswd[0] == 0) { + spasswd[0] = 0; + return; + } + skey = mkenvkey(mch); + if (skey == NULL) { + fprintf(stderr, "Can't make key\n"); + exit(1); + } + nbsdecrypt(sencpasswd, skey, spasswd); +} diff --git a/src/libc/posix/socket/inet/shstent.c b/src/libc/posix/socket/inet/shstent.c new file mode 100644 index 00000000..b561319d --- /dev/null +++ b/src/libc/posix/socket/inet/shstent.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1985 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University 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 WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "i_priv.h" /* RD: inetprivate.h -> i_priv.h */ +#include +#include + +void +sethostent(int stayopen) +{ + if (stayopen) + _res.options |= RES_STAYOPEN | RES_USEVC; +} + +void +endhostent() +{ + _res.options &= ~(RES_STAYOPEN | RES_USEVC); + _res_close(); + _endhtent (); +} + +void +sethostfile(char *name) +{ +#ifdef lint +name = name; +#endif +} diff --git a/src/libc/posix/socket/ini.c b/src/libc/posix/socket/ini.c new file mode 100644 index 00000000..6497ed9c --- /dev/null +++ b/src/libc/posix/socket/ini.c @@ -0,0 +1,140 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * ini.c - Windows .INI file parsing functions + * + * This file was written by Richard Dawe. + */ + +#include +#include +#include +#include + +#include + +/* --------------------------- + * - GetPrivateProfileString - + * --------------------------- */ + +/* This does the same as the Windows API call of the same name. */ + +int GetPrivateProfileString (const char *appname, const char *keyname, const char *deflt, + char *dest, size_t destsize, char *filename) +{ + FILE *fp; + char buf[256], *line = NULL, *p = NULL, *q = NULL; + int in_section = 0, got_key = 0; + + /* Check appname, keyname != NULL */ + if ((appname == NULL) || (keyname == NULL)) + return (0); + + /* Put the default value in dest */ + if (deflt != NULL) { + if (strlen (deflt) + 1 > destsize) { + strncpy (dest, deflt, destsize - 1); + dest[destsize - 1] = '\0'; + } else + strcpy (dest, deflt); + } else + *dest = '\0'; + + /* Open file, return 0 bytes copied if this fails */ + fp = fopen (filename, "rt"); + if (fp == NULL) + return (0); + + /* Parse the file */ + while (fgets (buf, sizeof (buf), fp) != NULL) { + if (got_key) + break; + + /* Find start of line; skip comment lines */ + line = buf; + while (isspace((int) *line)) line++; + if (*line == ';') continue; + if (*line == '#') continue; /* RD: This won't work with Windows tho! */ + + /* Remove trailing spaces, tabs, newlines, returns, etc. */ + for (p = line + strlen (line) - 1; isspace((int) *p); p--) { + *p = '\0'; + } + + /* Blank line? */ + if (*line == '\0') continue; + + /* Do we have a "application", i.e. section, name? */ + if ((*line == '[') && (*(line + strlen (line) - 1) == ']')) { + line++; + *(line + strlen (line) - 1) = '\0'; + + if (strcmp (line, appname) == 0) { + /* Yes */ + in_section = 1; + } else { + /* No */ + in_section = 0; + } + + continue; + } + + /* In the right section? */ + if (!in_section) continue; + + /* Is this a key line? */ + if ((p = strchr (line, '=')) != NULL) { + /* Split on the equals sign -> line = keyname, p = value */ + *p = '\0'; + p++; + + /* Trim trailing spaces off the key name stored in line. */ + for (q = line + strlen(line) - 1; isspace((int) *q); q--) { + *q = '\0'; + } + + /* Got the right key? */ + if (strcmp (keyname, line) != 0) continue; + + /* Skip any blank spaces at the start. */ + while (isspace((int) *p)) { p++; } + + /* Check buffer size OK */ + if ((strlen (p) + 1) > destsize) { + strncpy (dest, p, destsize - 1); + dest[destsize - 1] = '\0'; + } else + strcpy (dest, p); + + got_key = 1; + } + } + + /* Done */ + fclose (fp); + return (strlen (dest)); +} diff --git a/src/libc/posix/socket/initnt.c b/src/libc/posix/socket/initnt.c new file mode 100644 index 00000000..3fc42bbf --- /dev/null +++ b/src/libc/posix/socket/initnt.c @@ -0,0 +1,318 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * initnt.c + * Written by Richard Dawe + * + * Initialise all networking services. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +extern LSCK_IF *__wsock_init (void); +extern LSCK_IF *__csock_init (void); +extern LSCK_IF *__unix_init (void); + +/* Copyright information */ +static char lsck_version[80] = ""; /* Line of text at maximum */ + +static char lsck_copyright[] = +"Copyright (C) 1997, 1998 by Indrek Mandre, 1997-2000 by Richard Dawe"; + +/* Private variables */ +static int __lsck_inited = 0; + +LSCK_IF *__lsck_interface[LSCK_MAX_IF + 1]; + +typedef LSCK_IF * (*if_init_func_t) (void); + +typedef struct { + int number; + if_init_func_t init; + const char *init_name; +} if_init_t; + +static if_init_t if_init_table[LSCK_MAX_IF + 1] = { + /* Winsock support - WSOCK.VXD */ +// { LSCK_IF_WSOCK, __wsock_init, "wsock" }, + /* Coda filesystem socket helper - SOCK.VXD */ + { LSCK_IF_CSOCK, __csock_init, "csock" }, + /* Unix domain sockets over mailslots */ +// { LSCK_IF_UNIX, __unix_init, "unix" }, + { -1, NULL, NULL } +}; + +extern LSCK_SOCKET *__lsck_socket[__LSCK_NUM_SOCKET]; + +/* Debugging support */ +static int __lsck_debug_level = 0; /* None by default */ + +void __inline__ __lsck_debug_setlevel (int level) +{ + __lsck_debug_level = level; +} + +int __inline__ __lsck_debug_getlevel (void) { + return(__lsck_debug_level); +} + +void __inline__ __lsck_debug_enable (void) +{ + __lsck_debug_setlevel (LSCK_DEBUG_ON); +} + +void __inline__ __lsck_debug_disable (void) +{ + __lsck_debug_setlevel (LSCK_DEBUG_OFF); +} + +int __inline__ __lsck_debug_enabled (void) +{ + return ((__lsck_debug_getlevel () != LSCK_DEBUG_OFF) ? 1 : 0); +} + +/* --------------------- + * - init_version_info - + * --------------------- */ + +/* + * Set up textual versions of the version info in include/lsck/copyrite.h, + * for use in user programs. + */ + +static int init_version_info (void) +{ + static int version_info_inited = 0; + + if (version_info_inited) return(version_info_inited); + +#ifdef LSCK_VERSION_RELEASED +/* Released */ +#if defined(LSCK_VERSION_ALPHA) && (LSCK_VERSION_ALPHA > 0) + sprintf (lsck_version, "libsocket version %i.%i.%i alpha %i", + LSCK_VERSION_MAJOR, LSCK_VERSION_MINOR, LSCK_VERSION_SUBMINOR, + LSCK_VERSION_ALPHA); +#elif defined(LSCK_VERSION_BETA) && (LSCK_VERSION_BETA > 0) + sprintf (lsck_version, "libsocket version %i.%i.%i beta %i", + LSCK_VERSION_MAJOR, LSCK_VERSION_MINOR, LSCK_VERSION_SUBMINOR, + LSCK_VERSION_BETA); +#elif defined(LSCK_VERSION_PRE) && (LSCK_VERSION_PRE > 0) + sprintf (lsck_version, "libsocket version %i.%i.%i pre %i", + LSCK_VERSION_MAJOR, LSCK_VERSION_MINOR, LSCK_VERSION_SUBMINOR, + LSCK_VERSION_PRE); +#else + sprintf (lsck_version, "libsocket version %i.%i.%i", + LSCK_VERSION_MAJOR, LSCK_VERSION_MINOR, + LSCK_VERSION_SUBMINOR); +#endif +#else /* !LSCK_VERSION_RELEASED */ +/* Pre-releases */ +#if defined(LSCK_VERSION_ALPHA) && (LSCK_VERSION_ALPHA > 0) + sprintf (lsck_version, "libsocket version %i.%i.%i alpha %i " + "(pre-release %s)", + LSCK_VERSION_MAJOR, LSCK_VERSION_MINOR, LSCK_VERSION_SUBMINOR, + LSCK_VERSION_ALPHA, LSCK_VERSION_DATE); +#elif defined(LSCK_VERSION_BETA) && (LSCK_VERSION_BETA > 0) + sprintf (lsck_version, "libsocket version %i.%i.%i beta %i " + "(pre-release %s)", + LSCK_VERSION_MAJOR, LSCK_VERSION_MINOR, LSCK_VERSION_SUBMINOR, + LSCK_VERSION_BETA, LSCK_VERSION_DATE); +#elif defined(LSCK_VERSION_PRE) && (LSCK_VERSION_PRE > 0) + sprintf (lsck_version, "libsocket version %i.%i.%i pre %i " + "(pre-release %s)", + LSCK_VERSION_MAJOR, LSCK_VERSION_MINOR, LSCK_VERSION_SUBMINOR, + LSCK_VERSION_PRE, LSCK_VERSION_DATE); +#else + sprintf (lsck_version, "libsocket version %i.%i.%i" + "(pre-release %s)", + LSCK_VERSION_MAJOR, LSCK_VERSION_MINOR, + LSCK_VERSION_SUBMINOR, LSCK_VERSION_DATE); +#endif +#endif /* LSCK_VERSION_RELEASED */ + + version_info_inited = 1; + return(version_info_inited); +} + +/* ------------------------ + * - __lsck_get_copyright - + * ------------------------ */ + +char *__lsck_get_copyright (void) +{ + if (!init_version_info()) return(NULL); + return(lsck_copyright); +} + +/* ---------------------- + * - __lsck_get_version - + * ---------------------- */ + +char *__lsck_get_version (void) +{ + if (!init_version_info()) return(NULL); + return(lsck_version); +} + +/* --------------- + * - __lsck_init - + * --------------- */ + +int __lsck_init (void) +{ + LSCK_IF *interface = NULL; + char *cfg = NULL; + char debug_buf[16]; + char num_buf[33]; + int i, j; + + if (__lsck_inited != 0) return (__lsck_inited); + + /* --- Initialisation --- */ + + /* Set up the version info */ + if (!init_version_info()) return(0); + + /* Check for debugging options */ +#ifdef DEBUG_LIBSOCKET + printf ("libsocket: Use of the define DEBUG_LIBSOCKET is deprecated. " + "Please use the\n" + "libsocket: configuration file option 'debug' in the 'main' " + "section.\n"); + __lsck_debug_setlevel (LSCK_DEBUG_VERBOSE); +#endif + + /* Debug config option */ + cfg = __lsck_config_getfile(); + + if (cfg == NULL) + strcpy(debug_buf, "no"); + else + GetPrivateProfileString ("main", "debug", "false", + debug_buf, sizeof (debug_buf), cfg); + + if ((stricmp (debug_buf, "false") == 0) + || (stricmp (debug_buf, "no") == 0) + || (strcmp (debug_buf, "0") == 0)) { + __lsck_debug_disable (); + } else { + /* Check for verbose option */ + itoa (LSCK_DEBUG_VERBOSE, num_buf, 10); + if ((stricmp (debug_buf, "verbose") == 0) + || (strcmp (debug_buf, num_buf) == 0)) { + __lsck_debug_setlevel (LSCK_DEBUG_VERBOSE); + printf ("libsocket: Reporting verbose debugging " + "messages\n"); + } else { + __lsck_debug_setlevel (LSCK_DEBUG_NORMAL); + } + } + + /* Clear all descriptors */ + for (i = 0; i < __LSCK_NUM_SOCKET; i++) { + __lsck_socket[i] = NULL; + } + + /* Clear all interface info */ + for (i = 0; i < (LSCK_MAX_IF + 1); i++) { + __lsck_interface[i] = NULL; + } + + /* --- Initialise all interfaces --- */ + for (i = 0, j = 0; if_init_table[i].number >= 0; i++) { + interface = if_init_table[i].init(); + + if (interface != NULL) { + /* Debug info */ + if (__lsck_debug_enabled ()) { + /* Module pseudo-name */ + printf("%s: Initialised successfully\n", + if_init_table[i].init_name); + + /* Module description */ + printf("%s: %s\n", + if_init_table[i].init_name, + interface->name); + } + + __lsck_interface[j] = interface; + j++; + } + } + + /* Fail if there are no interfaces available */ + if (__lsck_interface[0] == NULL) { + __lsck_inited = 1; + __lsck_uninit (); + return (0); + } + + /* Set up atexit() handler */ + atexit (__lsck_uninit); + + /* Done */ + __lsck_inited = 1; + return (__lsck_inited); +} + +/* ----------------- + * - __lsck_uninit - + * ----------------- */ + +void __lsck_uninit (void) +{ + int i; + + if (!__lsck_inited) return; + + /* Pre-uninitialisation calls */ + for (i = 0; __lsck_interface[i] != NULL; i++) { + if (__lsck_interface[i]->preuninit != NULL) + __lsck_interface[i]->preuninit (); + } + + /* Free all descriptors after closing the sockets */ + for (i = 0; i < __LSCK_NUM_SOCKET; i++) { + if (__lsck_socket[i] != NULL) { + close (__lsck_socket[i]->fd); + free (__lsck_socket[i]); + } + } + + /* Uninitialise all interfaces */ + for (i = 0; __lsck_interface[i] != NULL; i++) { + if (__lsck_interface[i]->uninit != NULL) + __lsck_interface[i]->uninit (); + } +} diff --git a/src/libc/posix/socket/ioctl.c b/src/libc/posix/socket/ioctl.c new file mode 100644 index 00000000..18257575 --- /dev/null +++ b/src/libc/posix/socket/ioctl.c @@ -0,0 +1,262 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include + +#include +#include /* For Linux ioctl support */ +#include /* For Linux ioctl support */ + +#include +#include + +int ioctlsocket_emulated (LSCK_SOCKET * lsd, int request, int *param); + +/* --------------- + * - ioctlsocket - + * --------------- */ + +int ioctlsocket (int s, int request, int *param) +{ + LSCK_SOCKET *lsd; + int handled = 0; /* If the interface handled it, set to 1. */ + int rv; + int ret; + + /* Find the socket descriptor */ + lsd = __fd_to_lsd (s); + + if (lsd == NULL) { + isfdtype(s, S_IFSOCK); + return (-1); + } + + /* Check for completion of outstanding non-blocking I/O */ + if (lsd->interface->nonblocking_check != NULL) + lsd->interface->nonblocking_check (lsd); + + /* Check param */ + if (param == NULL) { + errno = EFAULT; + return(-1); + } + + /* Use appropriate interface */ + if (lsd->interface->ioctl != NULL) { + /* If the ioctl is not supported by the interface, this should + * return 0, so that it can be emulated. */ + handled = lsd->interface->ioctl(lsd, &rv, request, param); + } + + /* Try to emulate it if the call failed. */ + if (!handled) + ret = ioctlsocket_emulated (lsd, request, param); + else + ret = rv; + + return (ret); +} + +/* ------------------------ + * - ioctlsocket_emulated - + * ------------------------ */ + +int ioctlsocket_emulated (LSCK_SOCKET * lsd, int request, int *param) +{ + LSCK_IF_ADDR_INET *inet = NULL; + struct ifreq *ifr = NULL; + struct sockaddr_in *sin = NULL; + struct sockaddr_in *sin2 = NULL; + char *str = NULL; + int ret = -1; /* Fail by default */ + int i; + + switch (request) { + /* Interface name ioctl */ + case SIOCGIFNAME: + str = (char *) param; + if (lsd->interface->name != NULL) { + strcpy (str, lsd->interface->name); + ret = 0; + } else { + errno = EINVAL; + } + break; + + /* - ioctls returning "struct ifreq *" - */ + + /* Local socket address */ + case SIOCGIFADDR: + /* Internet domain? */ + if (lsd->sockname.sa_family != AF_INET) { + errno = EINVAL; + break; + } + + /* Stream or datagram? */ + if ((lsd->type != SOCK_STREAM) && (lsd->type != SOCK_DGRAM)) { + errno = EINVAL; + break; + } + + /* Stream socket connected? */ + if ( (lsd->type == SOCK_STREAM) + && !lsd->accepted + && !lsd->connected + && !lsd->connecting) { + errno = ENOTCONN; + break; + } + + /* Datagram socket bound? */ + if ( (lsd->type == SOCK_DGRAM) + && !lsd->bound) { + /* TODO: Right error? */ + errno = EAGAIN; + break; + } + + ifr = (struct ifreq *) param; + memcpy (&ifr->ifr_ifru.ifru_addr, + &lsd->sockname, sizeof (struct sockaddr)); + + ret = 0; + break; + + /* Peer socket address */ + case SIOCGIFDSTADDR: + /* Internet domain? */ + if (lsd->sockname.sa_family != AF_INET) { + errno = EINVAL; + break; + } + + /* Stream or datagram? NB: "connected" dgram has a desination + * address associated with it. */ + if ((lsd->type != SOCK_STREAM) && (lsd->type != SOCK_DGRAM)) { + errno = EINVAL; + break; + } + + /* Stream socket connected? */ + if ( (lsd->type == SOCK_STREAM) + && !lsd->accepted + && !lsd->connected) { + errno = ENOTCONN; + break; + } + + /* Datagram socket connected? */ + if ( (lsd->type == SOCK_DGRAM) + && lsd->peernamelen) { + errno = EDESTADDRREQ; + break; + } + + ifr = (struct ifreq *) param; + memcpy (&ifr->ifr_ifru.ifru_dstaddr, + &lsd->peername, sizeof (struct sockaddr)); + + ret = 0; + break; + + /* Subnet mask */ + case SIOCGIFNETMASK: + /* Internet domain? */ + if (lsd->sockname.sa_family != AF_INET) { + errno = EINVAL; + break; + } + + /* Stream or datagram? NB: "connected" dgram has a desination + * address associated with it. */ + if ((lsd->type != SOCK_STREAM) && (lsd->type != SOCK_DGRAM)) { + errno = EINVAL; + break; + } + + /* Stream socket connected? */ + if ( (lsd->type == SOCK_STREAM) + && !lsd->accepted + && !lsd->connected) { + errno = ENOTCONN; + break; + } + + /* Datagram socket connected? */ + if ( (lsd->type == SOCK_DGRAM) + && lsd->peernamelen) { + /* TODO: This is probably the wrong error to use here, + * but what error should be used? This makes a strong + * distinction between streams and datagrams. */ + errno = EDESTADDRREQ; + break; + } + + ifr = (struct ifreq *) param; + bzero (ifr, sizeof (ifr)); + sin = (struct sockaddr_in *) &lsd->sockname; + + /* Scan the interface to find the netmask for the socket + * address. */ + if ((lsd->interface->addr != NULL) + && (lsd->interface->addr->family == AF_INET)) { + for (i = 0; + (inet = lsd->interface->addr->table.inet[i]) + != NULL; + i++) { + if (sin->sin_addr.s_addr + == inet->addr.s_addr) { + sin2 = (struct sockaddr_in *) + &ifr->ifr_ifru.ifru_netmask; + sin2->sin_family = AF_INET; + sin2->sin_addr.s_addr + = inet->netmask.s_addr; + break; + } + } + } else { + errno = EINVAL; + break; + } + + ret = 0; + break; + + case SIOCGIFFLAGS: + case SIOCGIFBRDADDR: /* TODO: Broadcast address? */ + case SIOCGIFMETRIC: + case SIOCGIFMEM: + case SIOCGIFMTU: + default: + errno = EINVAL; + break; + } + + /* Done */ + return (ret); +} diff --git a/src/libc/posix/socket/listen.c b/src/libc/posix/socket/listen.c new file mode 100644 index 00000000..6be717e3 --- /dev/null +++ b/src/libc/posix/socket/listen.c @@ -0,0 +1,81 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include + +#include +#include + +/* ---------- + * - listen - + * ---------- */ + +int listen (int s, int backlog) +{ + LSCK_SOCKET *lsd; + int ret = -1; /* Fail by default */ + + /* Find the socket descriptor */ + lsd = __fd_to_lsd (s); + + if (lsd == NULL) { + isfdtype(s, S_IFSOCK); + return (-1); + } + + /* Check for completion of outstanding non-blocking I/O */ + if (lsd->interface->nonblocking_check != NULL) + lsd->interface->nonblocking_check (lsd); + + /* If it's not a stream socket, we can't listen. */ + if (lsd->type != SOCK_STREAM) { + errno = EOPNOTSUPP; + return (-1); + } + + /* If it's not bound, then this is invalid. */ + if (!lsd->bound) { + errno = EINVAL; + return (-1); + } + + /* Listen */ + if (lsd->interface->listen == NULL) { + errno = EOPNOTSUPP; + return (-1); + } + ret = lsd->interface->listen (lsd, backlog); + + /* Store the new backlog */ + if (ret != -1) { + lsd->listening = 1; + lsd->backlog = backlog; + } + + /* Done */ + return (ret); +} diff --git a/src/libc/posix/socket/makefile b/src/libc/posix/socket/makefile new file mode 100644 index 00000000..5ca6beeb --- /dev/null +++ b/src/libc/posix/socket/makefile @@ -0,0 +1,35 @@ +# Copyright (C) 2014 DJ Delorie, see COPYING.DJ for details +# Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details +# Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details +TOP=../.. + +SRC += initnt.c +SRC += fsext.c +SRC += socket.c +SRC += sockpr.c +SRC += bind.c +SRC += listen.c +SRC += accept.c +SRC += recv.c +SRC += send.c +SRC += connct.c +SRC += gscknm.c +SRC += gprnm.c +SRC += close.c +SRC += sckopt.c +SRC += shtdwn.c +SRC += ioctl.c +SRC += select.c +SRC += fcntl.c +#SRC += newerror.c +SRC += dnsaddr.c +SRC += ini.c +SRC += hstnm.c +SRC += config.c +SRC += addr.c +SRC += if.c +SRC += sockmark.c +#SRC += uname.c +SRC += windows.c + +include $(TOP)/../makefile.inc diff --git a/src/libc/posix/socket/newerror.c b/src/libc/posix/socket/newerror.c new file mode 100644 index 00000000..961ba81e --- /dev/null +++ b/src/libc/posix/socket/newerror.c @@ -0,0 +1,168 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * newerror.c - New libsocket errors for libc. + * Written by Richard Dawe + */ + +#include +#include +#include +#include + +#include + +/* --------------- + * - lsck_perror - + * --------------- */ + +/* This is now obsolete. */ + +/*void lsck_perror (char *s) +{ + fprintf (stderr, "%s: %s\n", s, lsck_strerror (errno)); +}*/ + +/* ------------ + * - strerror - + * ------------ */ + +extern char *__old_djgpp_libc_strerror (int errnum); + +const char *strerror (int errnum) +{ + /* Return our own error message if there is one, else use the libc + * routine. */ + switch (errnum) { + /* This message was taken from DJGPP 2.04. It should be synchronised + * with the DJGPP 2.04 (or later) version. */ + case ELOOP: + return ("Too many levels of symbolic links (ELOOP)"); + + case EREMOTE: + return ("Object is remote (EREMOTE)"); + + case EPROTOTYPE: + return ("Protocol error (EPROTOTYPE)"); + + case EUSERS: + return ("Too many users (EUSERS)"); + + case ENOTSOCK: + return ("Not a socket (ENOTSOCK)"); + + case EDESTADDRREQ: + return ("Destination address required (EDESTADDRREQ)"); + + case EMSGSIZE: + return ("Message too long (EMSGSIZE)"); + + case ENOPROTOOPT: + return ("Protocol not available (ENOPROTOOPT)"); + + case EPROTONOSUPPORT: + return ("Protocol not supported (EPROTONOSUPPORT)"); + + case ESOCKTNOSUPPORT: + return ("Socket type not supported (ESOCKTNOSUPPORT)"); + + case EOPNOTSUPP: + return ("Operation not supported on endpoint (EOPNOTSUPP)"); + + case EPFNOSUPPORT: + return ("Protocol family not supported (EPFNOSUPPORT)"); + + case EAFNOSUPPORT: + return ("Address family not supported (EAFNOSUPPORT)"); + + case EADDRINUSE: + return ("Address already in use (EADDRINUSE)"); + + case EADDRNOTAVAIL: + return ("Cannot assign requested address (EADDRNOTAVAIL)"); + + case ENETDOWN: + return ("Network is down (ENETDOWN)"); + + case ENETUNREACH: + return ("Network is unreachable (ENETUNREACH)"); + + case ENETRESET: + return ("Network dropped connection because of reset (ENETRESET)"); + + case ECONNABORTED: + return ("Software caused connection abort (ECONNABORTED)"); + + case ECONNRESET: + return ("Connection reset by peer (ECONNRESET)"); + + case ENOBUFS: + return ("No buffer space available (ENOBUFS)"); + + case EISCONN: + return ("Transport endpoint is already connected (EISCONN)"); + + case ENOTCONN: + return ("Transport endpoint is not connected (ENOTCONN)"); + + case ESHUTDOWN: + return ("Cannot send after transport endpoint shutdown " + "(ESHUTDOWN)"); + + case ETOOMANYREFS: + return ("Too many references: cannot splice (ETOOMANYREFS)"); + + case ETIMEDOUT: + return ("Connection timed out (ETIMEOUT)"); + + case ECONNREFUSED: + return ("Connection refused (ECONNREFUSED)"); + + case EHOSTDOWN: + return ("Host is down (EHOSTDOWN)"); + + case EHOSTUNREACH: + return ("No route to host (EHOSTUNREACH)"); + + case ESTALE: + return ("Stale NFS handle (ESTALE)"); + + case EDQUOT: + return ("Quota exceeded (EDQUOT)"); + + case EALREADY: + return("Operation already in progress (EALREADY)"); + + case EINPROGRESS: + return("Operation now in progress (EINPROGRESS)"); + + default: + return (__old_djgpp_libc_strerror(errnum)); + } + + /* Safety net */ + return (NULL); +} diff --git a/src/libc/posix/socket/posix/genvsec.c b/src/libc/posix/socket/posix/genvsec.c new file mode 100644 index 00000000..fdc65bdd --- /dev/null +++ b/src/libc/posix/socket/posix/genvsec.c @@ -0,0 +1,38 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * DJGPP doesn't have a __libc_secure_getenv() function, so fake one. Also + * let user code override this, because this isn't very good. + */ + +#include +#include + +char *__libc_secure_getenv (const char *name); +char __attribute__ ((weak)) * __libc_secure_getenv (const char *name) +{ + return (getenv (name)); +} diff --git a/src/libc/posix/socket/posix/makefile b/src/libc/posix/socket/posix/makefile new file mode 100644 index 00000000..709f3aeb --- /dev/null +++ b/src/libc/posix/socket/posix/makefile @@ -0,0 +1,8 @@ +# Copyright (C) 2014 DJ Delorie, see COPYING.DJ for details +# Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details +# Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details +TOP=../../.. + +SRC += genvsec.c + +include $(TOP)/../makefile.inc diff --git a/src/libc/posix/socket/recv.c b/src/libc/posix/socket/recv.c new file mode 100644 index 00000000..1443c5dc --- /dev/null +++ b/src/libc/posix/socket/recv.c @@ -0,0 +1,133 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include + +#include +#include + +/* -------- + * - recv - + * -------- */ + +ssize_t recv (int s, void *buf, size_t len, unsigned int flags) +{ + LSCK_SOCKET *lsd; + ssize_t ret; + + /* Find the socket descriptor */ + lsd = __fd_to_lsd (s); + + if (lsd == NULL) { + isfdtype(s, S_IFSOCK); + return (-1); + } + /* Check for completion of outstanding non-blocking I/O */ + if (lsd->interface->nonblocking_check != NULL) + lsd->interface->nonblocking_check (lsd); + + /* Connect'd? */ + if ((lsd->type == SOCK_STREAM) && !lsd->connected) { + errno = ENOTCONN; + return (-1); + } + + /* No buffer */ + if (buf == NULL) { + errno = EFAULT; + return (-1); + } + + /* recv() allowed? */ + if (!lsd->inbound) + return (0); + + /* Use the appropriate interface */ + if (lsd->interface->recv == NULL) { + errno = EOPNOTSUPP; + return (-1); + } + ret = lsd->interface->recv (lsd, buf, len, flags); + return (ret); +} + +/* ------------ + * - recvfrom - + * ------------ */ + +ssize_t recvfrom (int s, void *buf, size_t len, unsigned int flags, + struct sockaddr *from, size_t *fromlen) +{ + LSCK_SOCKET *lsd; + ssize_t ret; + + /* Find the socket descriptor */ + lsd = __fd_to_lsd (s); + + if (lsd == NULL) { + isfdtype(s, S_IFSOCK); + return (-1); + } + /* Check for completion of outstanding non-blocking I/O */ + if (lsd->interface->nonblocking_check != NULL) + lsd->interface->nonblocking_check (lsd); + + /* No buffer */ + if (buf == NULL) { + errno = EFAULT; + return (-1); + } + + /* NB: from can be NULL */ + if ( (from != NULL) && (fromlen == NULL) ) { + errno = EFAULT; + return (-1); + } + + /* recvfrom() allowed? */ + /* TODO: This should return an error, but what error? */ + if (!lsd->inbound) return (0); + + /* Use the appropriate interface */ + if (lsd->interface->recvfrom == NULL) { + errno = EOPNOTSUPP; + return (-1); + } + + ret = lsd->interface->recvfrom (lsd, buf, len, flags, from, fromlen); + return (ret); +} + +/* ----------- + * - recvmsg - + * ----------- */ + +ssize_t recvmsg (int s, struct msghdr *msg, int flags) +{ + errno = EOPNOTSUPP; + return(-1); +} diff --git a/src/libc/posix/socket/sckopt.c b/src/libc/posix/socket/sckopt.c new file mode 100644 index 00000000..ab2557e3 --- /dev/null +++ b/src/libc/posix/socket/sckopt.c @@ -0,0 +1,206 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you 2can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* INFO: Comments starting with 'IM' indicate that Indrek Mandre made changes. + * Comments starting wiht 'RD' indicate that Richard Dawe made changes. If no + * comment is given, then the code was written by Indrek Mandre. */ + +#include + +#include + +#include +#include + +/* Emulation functions */ +int getsockopt_emulated (LSCK_SOCKET *lsd, int level, int optname, + void *optval, size_t *optlen); + +int setsockopt_emulated (LSCK_SOCKET *lsd, int level, int optname, + const void *optval, size_t optlen); + +/* -------------- + * - getsockopt - + * -------------- */ + +int getsockopt (int s, int level, int optname, void *optval, size_t *optlen) +{ + LSCK_SOCKET *lsd; + void *my_optval = optval; + size_t *my_optlen = optlen; + char buf[16]; /* Temp. buffer if optval == NULL */ + size_t buflen = sizeof(buf); /* Temp. buffer size */ + int handled = 0; /* If interface handled, set to 1. */ + int rv; + int ret = -1; /* Fail by default */ + + /* Find the socket descriptor */ + lsd = __fd_to_lsd (s); + + if (lsd == NULL) { + isfdtype(s, S_IFSOCK); + return (-1); + } + + /* Check for completion of outstanding non-blocking I/O */ + if (lsd->interface->nonblocking_check != NULL) + lsd->interface->nonblocking_check (lsd); + + /* Check parameters */ + if ( (optval != NULL) && (optlen == NULL) ) { + errno = EFAULT; + return(-1); + } + + if (optval == NULL) { + /* Pass the interface our temporary buffer, so it doesn't + * have to worry about valid addresses. */ + my_optval = (void *) buf; + my_optlen = &buflen; + } + + /* Use appropriate interface */ + if (lsd->interface->getsockopt != NULL) { + handled = lsd->interface->getsockopt(lsd, &rv, + level, optname, + my_optval, my_optlen); + } + + /* If the interface hasn't handled the option, emulate it. */ + if (!handled) + ret = getsockopt_emulated(lsd, + level, optname, + my_optval, my_optlen); + else + ret = rv; + + return (ret); +} + +/* ----------------------- + * - getsockopt_emulated - + * ----------------------- */ + +int getsockopt_emulated (LSCK_SOCKET *lsd, int level, int optname, + void *optval, size_t *optlen) +{ + int *i_optval = (int *) optval; + int ret = 0; /* Succeed by default. */ + + /* Only emulate socket-level options for now. */ + if (level != SOL_SOCKET) { + errno = ENOPROTOOPT; + return(-1); + } + + /* Check buffer space */ + switch(optname) { + /* Integer values */ + case SO_ACCEPTCONN: + case SO_TYPE: + if (*optlen < sizeof(int)) { + errno = ENOBUFS; + return(-1); + } + break; + } + + switch(optname) { + /* Socket is listening */ + case SO_ACCEPTCONN: + *i_optval = lsd->listening; + *optlen = sizeof(int); + break; + + /* Socket type */ + case SO_TYPE: + *i_optval = lsd->type; + *optlen = sizeof(int); + break; + + default: + errno = ENOPROTOOPT; + ret = -1; + break; + } + + return(ret); +} + +/* -------------- + * - setsockopt - + * -------------- */ + +int setsockopt (int s, int level, int optname, const void *optval, + size_t optlen) +{ + LSCK_SOCKET *lsd; + int handled = 0; /* If the interface handled it, set to 1. */ + int rv; + int ret = -1; + + /* Find the socket descriptor */ + lsd = __fd_to_lsd (s); + + if (lsd == NULL) { + isfdtype(s, S_IFSOCK); + return (-1); + } + + /* Check for completion of outstanding non-blocking I/O */ + if (lsd->interface->nonblocking_check != NULL) + lsd->interface->nonblocking_check (lsd); + + /* Check param */ + if (optval == NULL) { + errno = EFAULT; + return(-1); + } + + /* Use appropriate interface */ + if (lsd->interface->setsockopt != NULL) { + handled = lsd->interface->setsockopt(lsd, &rv, + level, optname, + optval, optlen); + } + + if (!handled) + ret = setsockopt_emulated(lsd, level, optname, optval, optlen); + else + ret = rv; + + return (ret); +} + +/* ----------------------- + * - setsockopt_emulated - + * ----------------------- */ + +int setsockopt_emulated (LSCK_SOCKET *lsd, int level, int optname, + const void *optval, size_t optlen) +{ + errno = ENOPROTOOPT; + return(-1); +} diff --git a/src/libc/posix/socket/select.c b/src/libc/posix/socket/select.c new file mode 100644 index 00000000..b5a7d113 --- /dev/null +++ b/src/libc/posix/socket/select.c @@ -0,0 +1,60 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include + +#include +#include + +/* ---------------- + * - selectsocket - + * ---------------- */ + +int selectsocket (int s, int event) +{ + LSCK_SOCKET *lsd; + int ret; + + /* Find the socket descriptor */ + lsd = __fd_to_lsd (s); + + if (lsd == NULL) { + isfdtype(s, S_IFSOCK); + return (-1); + } + /* Check for completion of outstanding non-blocking I/O */ + if (lsd->interface->nonblocking_check != NULL) + lsd->interface->nonblocking_check (lsd); + + /* Use appropriate interface */ + if (lsd->interface->select == NULL) { + errno = EOPNOTSUPP; + return (-1); + } + ret = lsd->interface->select (lsd, event); + return (ret); +} diff --git a/src/libc/posix/socket/send.c b/src/libc/posix/socket/send.c new file mode 100644 index 00000000..fd42825d --- /dev/null +++ b/src/libc/posix/socket/send.c @@ -0,0 +1,167 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include + +#include +#include + +/* -------- + * - send - + * -------- */ + +ssize_t send (int s, const void *msg, size_t len, unsigned int flags) +{ + return (sendto(s, msg, len, flags, NULL, 0)); +} + +/* ---------- + * - sendto - + * ---------- */ + +ssize_t sendto (int s, const void *msg, size_t len, unsigned int flags, + struct sockaddr *to, size_t tolen) +{ + LSCK_SOCKET *lsd; + ssize_t ret; + struct sockaddr *my_to = to; + size_t my_tolen = tolen; + + /* Find the socket descriptor */ + lsd = __fd_to_lsd (s); + + if (lsd == NULL) { + isfdtype(s, S_IFSOCK); + return (-1); + } + + /* Check for completion of outstanding non-blocking I/O */ + if (lsd->interface->nonblocking_check != NULL) + lsd->interface->nonblocking_check (lsd); + + /* NOTE: sendto() doesn't need the socket to be in a connect'd state. */ + + /* No buffer */ + if (msg == NULL) { + errno = EFAULT; + return (-1); + } + + /* Check destination params */ + if ( (to != NULL) && (tolen == 0) ) { + errno = EINVAL; + return (-1); + } + + /* sendto() allowed? */ + if (!lsd->outbound) { + raise(SIGPIPE); + errno = EPIPE; + return(-1); + } + + /* Stream sockets */ + if (lsd->type == SOCK_STREAM) { + /* Not connected */ + if (!lsd->connected) { + errno = ENOTCONN; + return(-1); + } + + /* Destination address spec'd? */ + if (my_to == NULL) { + my_to = &lsd->peername; + my_tolen = lsd->peernamelen; + } + + /* Barf if the destination address is not the peer's address. */ + /* TODO: Should there be an error here even if it's the same? + * AlainM wasn't sure. */ + if ( (my_tolen != lsd->peernamelen) + || (memcmp(&lsd->peername, my_to, my_tolen) != 0) ) { + errno = EISCONN; + return(-1); + } + + /* Are we allowed to send? */ + if (!lsd->outbound) { + raise(SIGPIPE); + errno = EPIPE; + return(-1); + } + + /* Use the appropriate transport. Because we don't know how the + * interface implements a sendto, use a send function for the stream- + * type socket. */ + if (lsd->interface->send == NULL) { + errno = EOPNOTSUPP; + return (-1); + } + + ret = lsd->interface->send (lsd, msg, len, flags); + return (ret); + } + + /* Datagram sockets */ + if ( (lsd->type == SOCK_DGRAM) && (my_to == NULL) ) { + if (lsd->peername.sa_family == 0) { + /* No address data! */ + errno = EDESTADDRREQ; + return(-1); + } + + /* Use address assigned by earlier connect() call */ + my_to = &lsd->peername; + my_tolen = lsd->peernamelen; + } + + /* Are we allowed to send? */ + if (!lsd->outbound) { + errno = EPIPE; + return(-1); + } + + /* Use the appropriate transport */ + if (lsd->interface->sendto == NULL) { + errno = EOPNOTSUPP; + return (-1); + } + + ret = lsd->interface->sendto (lsd, msg, len, flags, my_to, my_tolen); + return (ret); +} + +/* ----------- + * - sendmsg - + * ----------- */ + +ssize_t sendmsg (int s, const struct msghdr *msg, int flags) +{ + errno = EOPNOTSUPP; + return(-1); +} diff --git a/src/libc/posix/socket/shtdwn.c b/src/libc/posix/socket/shtdwn.c new file mode 100644 index 00000000..fc95cf7d --- /dev/null +++ b/src/libc/posix/socket/shtdwn.c @@ -0,0 +1,97 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include + +#include +#include + +/* ------------ + * - shutdown - + * ------------ */ + +int shutdown (int s, int how) +{ + LSCK_SOCKET *lsd; + int ret; + + /* Find the socket descriptor */ + lsd = __fd_to_lsd (s); + + if (lsd == NULL) { + isfdtype(s, S_IFSOCK); + return (-1); + } + + /* Check for completion of outstanding non-blocking I/O */ + if (lsd->interface->nonblocking_check != NULL) + lsd->interface->nonblocking_check (lsd); + + /* Is the socket connected? */ + if (!lsd->connected) { + errno = ENOTCONN; + return(-1); + } + + /* Do we have a valid value of how? */ + switch(how) { + case SHUT_RD: + case SHUT_WR: + case SHUT_RDWR: + break; + + default: + errno = EINVAL; + return(-1); + } + + /* Use appropriate interface */ + if (lsd->interface->shutdown == NULL) { + errno = EOPNOTSUPP; + return (-1); + } + ret = lsd->interface->shutdown (lsd, how); + + /* Changes the flags here rather than in the interface code */ + if (ret == 0) { + switch(how) { + case SHUT_RD: + lsd->inbound = 0; + break; + + case SHUT_WR: + lsd->outbound = 0; + break; + + case SHUT_RDWR: + lsd->inbound = lsd->outbound = 0; + break; + } + } + + return (ret); +} diff --git a/src/libc/posix/socket/socket.c b/src/libc/posix/socket/socket.c new file mode 100644 index 00000000..f1af405c --- /dev/null +++ b/src/libc/posix/socket/socket.c @@ -0,0 +1,240 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* This code was originally rewritten by Indrek Mandre, but was completely + * rewritten by Richard Dawe to support different network interfaces. */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +/* Default protocols for given (domain, type) pairs */ +typedef struct _LSCK_SOCKET_DEFAULT { + int domain; + int type; + int protocol; +} LSCK_SOCKET_DEFAULT; + +LSCK_SOCKET_DEFAULT __lsck_socket_default[] = +{ + {AF_INET, SOCK_STREAM, IPPROTO_TCP}, + {AF_INET, SOCK_DGRAM, IPPROTO_UDP}, + {0, 0, 0} +}; + +/* Moved this function to fsext.c -> func. decl. here */ +extern int __lsck_socket_fsext (__FSEXT_Fnumber func_number, + int *rv, va_list args); + +/* Socket information */ +LSCK_SOCKET *__lsck_socket[__LSCK_NUM_SOCKET]; + +/* Interface information */ +extern LSCK_IF *__lsck_interface[LSCK_MAX_IF + 1]; + +/* Function declarations */ +int __socketx (int domain, int type, int protocol, LSCK_IF *interface); + +/* ---------- + * - socket - + * ---------- */ + +int socket (int domain, int type, int protocol) +{ + /* Create a socket with no interface preference. */ + return(__socketx(domain, type, protocol, NULL)); +} + +/* ------------- + * - __socketx - + * ------------- */ + +/* This is an internal function, used to support socketpair(). DO NOT USE IT + * IN PROGRAMS! */ + +int __socketx (int domain, int type, int protocol, LSCK_IF *interface) +{ + int s = 0; /* File descriptor for socket */ + int ret = 0; /* Return value */ + int i = 0; /* Loop variable */ + int freelsd = -1; /* Free socket descriptor */ + LSCK_SOCKET *lsd = NULL; /* Pointer to socket descriptor */ + LSCK_IF *my_if = interface; /* Interface to use to create */ + int olderrno; + + /* Fail if we can't initialise */ + if (!__lsck_init ()) { + /* TODO: Not sure which error to return here. */ + errno = ENODEV; + /*errno = EPROTONOSUPPORT; */ + return (-1); + } + + /* If protocol is 0, convert it to the default protocol for the given + * family & type. If it's a raw socket, just accept the protocol + * value. */ + if ((protocol == 0) && (type != SOCK_RAW)) { + for (i = 0; __lsck_socket_default[i].domain != 0; i++) { + if ( (__lsck_socket_default[i].domain == domain) + && (__lsck_socket_default[i].type == type)) { + protocol = __lsck_socket_default[i].protocol; + break; + } + } + } + + /* Allocate a file descriptor */ + s = __FSEXT_alloc_fd (__lsck_socket_fsext); + + if (s < 0) { + /* No free file descriptors? */ + errno = EMFILE; + return (-1); + } + setmode (s, O_BINARY); + + /* -- Allocate a libsocket socket for the descriptor -- */ + + /* Find the first free descriptor */ + for (i = 0; (__lsck_socket[i] != NULL) && (i < __LSCK_NUM_SOCKET); i++) + {;} + + if ((i == (__LSCK_NUM_SOCKET - 1)) && (__lsck_socket[i] == NULL)) { + /* The last desciptor can be used, but needs special + * checking. */ + freelsd = i; + } else if (i < __LSCK_NUM_SOCKET) { + /* Rest are OK */ + freelsd = i; + } + + /* None free! Free the file descriptor, and return error. */ + if (freelsd < 0) { + __FSEXT_set_function (s, NULL); + _close (s); + errno = EMFILE; + return (-1); + } + + lsd = __lsck_socket[freelsd] = malloc(sizeof(LSCK_SOCKET)); + + if (lsd == NULL) { + __FSEXT_set_function(s, NULL); + _close (s); /* Free the socket descriptor */ + errno = ENOBUFS; + return (-1); + } + + memset (lsd, 0, sizeof (LSCK_SOCKET)); + + /* Set the file descriptor's data to be the socket descriptor. */ + __FSEXT_set_data(s, (void *) lsd); + +/* Define a pseudo-function for clean up. This is complicated by the DJGPP + * version number :( */ +#define __SOCKET_CLEANUP __FSEXT_set_function(s, NULL); \ + __FSEXT_set_data(s, NULL); \ + _close(s); \ + free(lsd); \ + __lsck_socket[freelsd] = NULL + + lsd->family = domain; + lsd->type = type; + lsd->protocol = protocol; + lsd->backlog = 0; /* Need to listen() to set this. */ + lsd->blocking = 1; /* Block by def'lt */ + lsd->fd = s; /* Store file desc. */ + lsd->urgent_pid = getpid (); /* Send SIGURG signals to this pid. */ + lsd->inbound = 1; /* Allow recv(), recvfrom() */ + lsd->outbound = 1; /* Allow send(), sendto() */ + + /* Create the socket on the first matching interface */ + for (i = 0; (my_if == NULL) && (__lsck_interface[i] != NULL); i++) { + if (__lsck_interface[i]->proto_check == NULL) + continue; + + if (__lsck_interface[i]->proto_check(domain, type, protocol)) { + my_if = __lsck_interface[i]; + break; + } + } + + /* If the function user spec'd an interface or we found one, use it. */ + lsd->interface = my_if; + + if (lsd->interface != NULL) { + if (lsd->interface->socket == NULL) + lsd->interface = NULL; + } + + if (lsd->interface == NULL) { + /* No interfaces! */ + __SOCKET_CLEANUP; + errno = EPROTONOSUPPORT; + return (-1); + } + + /* Creation failed, so return error code */ + ret = lsd->interface->socket (lsd); + + if (ret == -1) { + /* TODO: Fix this hack, which is dodgy. */ + olderrno = errno; + __SOCKET_CLEANUP; + errno = olderrno; + } + + /* Return the descriptor - on error, errno should be set by the + * interface's socket() call */ + return ((ret == -1) ? -1 : s); +} + +/* --------------- + * - __fd_to_lsd - + * --------------- */ + +LSCK_SOCKET *__fd_to_lsd (int fd) +{ + LSCK_SOCKET *lsd = NULL; + + /* Check the file descriptor refers to a socket. */ + if (!__fd_is_socket(fd)) return(NULL); + + /* Retrieve the fd's associated data. */ + lsd = (LSCK_SOCKET *) __FSEXT_get_data(fd); + + return (lsd); +} diff --git a/src/libc/posix/socket/sockmark.c b/src/libc/posix/socket/sockmark.c new file mode 100644 index 00000000..a416e16f --- /dev/null +++ b/src/libc/posix/socket/sockmark.c @@ -0,0 +1,62 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include + +#include +#include + +/* -------------- + * - sockatmark - + * -------------- */ + +int sockatmark (int s) +{ + LSCK_SOCKET *lsd; + int ret = -1; /* Fail by default */ + + /* Find the socket descriptor */ + lsd = __fd_to_lsd (s); + + if (lsd == NULL) { + isfdtype(s, S_IFSOCK); + return (-1); + } + + /* Check for completion of outstanding non-blocking I/O */ + if (lsd->interface->nonblocking_check != NULL) + lsd->interface->nonblocking_check (lsd); + + /* Use appropriate interface */ + if (lsd->interface->sockatmark == NULL) { + errno = ENOSYS; + return (-1); + } + + ret = lsd->interface->sockatmark (lsd); + return (ret); +} diff --git a/src/libc/posix/socket/sockpr.c b/src/libc/posix/socket/sockpr.c new file mode 100644 index 00000000..fa8ae518 --- /dev/null +++ b/src/libc/posix/socket/sockpr.c @@ -0,0 +1,139 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include +#include + +#include + +/* Interface information */ +extern LSCK_IF *__lsck_interface[LSCK_MAX_IF + 1]; + +/* Internal create function */ +extern int __socketx (int domain, int type, int protocol, LSCK_IF *interface); + +/* -------------- + * - socketpair - + * -------------- */ + +int socketpair (int domain, int type, int protocol, int sv[2]) +{ + int my_fd[2] = { -1, -1 }; + LSCK_SOCKET *my_lsd[2] = { NULL, NULL }; + LSCK_IF *my_if = NULL; + int olderrno, ret, i; + + /* Check to see if we can create socket pairs first. Find the + * interface that supports the protocol combo and __x_socketpair(). */ + for (i = 0; (my_if == NULL) && (__lsck_interface[i] != NULL); i++) { + if (__lsck_interface[i]->proto_check == NULL) + continue; + + if (!__lsck_interface[i]->proto_check(domain, type, protocol)) + continue; + + if (__lsck_interface[i]->socketpair != NULL) { + my_if = __lsck_interface[i]; + break; + } + } + + if (my_if == NULL) { + errno = EOPNOTSUPP; + return(-1); + } + + /* Now create two sockets on the found interface. */ + my_fd[0] = __socketx(domain, type, protocol, my_if); + my_fd[1] = __socketx(domain, type, protocol, my_if); + + if ((my_fd[0] == -1) || (my_fd[1] == -1)) { + if (my_fd[0] >= 0) close(my_fd[0]); + if (my_fd[1] >= 0) close(my_fd[1]); + return(-1); /* Just pass errno on */ + } + + /* Find the socket descriptors. */ + my_lsd[0] = __fd_to_lsd(my_fd[0]); + my_lsd[1] = __fd_to_lsd(my_fd[1]); + + if ((my_lsd[0] == NULL) || (my_lsd[1] == NULL)) { + /* What's going on here? */ + close(my_fd[0]); + close(my_fd[1]); + errno = ENOMEM; + return(-1); + } + + /* TODO: Is this split of work good? Or should there be some emulation + * code too? I can see that TCP/IP connections could randomly pick + * local ports on the loopback address. Hmmm. */ + + /* Now let the interface connect the two sockets together. */ + ret = my_if->socketpair(my_lsd); + + /* If the call fails, kill the sockets. Else, set up the socket vector + * array and get the socket name and peer name. */ + if (ret == -1) { + olderrno = errno; + close(my_fd[0]); + close(my_fd[1]); + errno = olderrno; + } else { + sv[0] = my_fd[0]; + sv[1] = my_fd[1]; + + /* Socket & peer names */ + /* TODO: This should probably check return values. */ + my_lsd[0]->socknamelen + = my_lsd[0]->peernamelen + = __SOCKADDR_MAX_SIZE; + + getsockname(my_lsd[0]->fd, + &my_lsd[0]->sockname, + &my_lsd[0]->socknamelen); + + getpeername(my_lsd[0]->fd, + &my_lsd[0]->peername, + &my_lsd[0]->peernamelen); + + my_lsd[1]->socknamelen + = my_lsd[1]->peernamelen + = __SOCKADDR_MAX_SIZE; + + getsockname(my_lsd[1]->fd, + &my_lsd[1]->sockname, + &my_lsd[1]->socknamelen); + + getpeername(my_lsd[1]->fd, + &my_lsd[1]->peername, + &my_lsd[1]->peernamelen); + } + + return(ret); +} diff --git a/src/libc/posix/socket/uname.c b/src/libc/posix/socket/uname.c new file mode 100644 index 00000000..9cd744ae --- /dev/null +++ b/src/libc/posix/socket/uname.c @@ -0,0 +1,64 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +int __old_djgpp_libc_uname (struct utsname *u); + +/* --------- + - uname - + --------- */ + +/* This uses the old DJGPP uname() routine, but gets the nodename using our + * gethostname() code. This copies as much of the node's name as possible. */ + +int uname (struct utsname *u) +{ + int ret, len; + char hbuf[MAXGETHOSTNAME]; + char *p = NULL; + + /* NOTE: __old_djgpp_libc_uname() should handle u == NULL */ + ret = __old_djgpp_libc_uname(u); + if (ret != 0) return(ret); /* Pass the error on */ + + /* Find the nodename */ + ret = gethostname(hbuf, sizeof(hbuf)); + if (ret != 0) return(ret); + + p = strchr(hbuf, '.'); + if (p != NULL) *p = '\0'; + + /* Copy it */ + len = sizeof(u->nodename) - 1; /* nul too */ + if (strlen(hbuf) < len) len = strlen(hbuf); + strncpy(u->nodename, hbuf, len); + u->nodename[len] = '\0'; + + return(0); +} diff --git a/src/libc/posix/socket/windows.c b/src/libc/posix/socket/windows.c new file mode 100644 index 00000000..37801c25 --- /dev/null +++ b/src/libc/posix/socket/windows.c @@ -0,0 +1,75 @@ +/* + * libsocket - BSD socket like library for DJGPP + * Copyright 1997, 1998 by Indrek Mandre + * Copyright 1997-2000 by Richard Dawe + * + * Portions of libsocket Copyright 1985-1993 Regents of the University of + * California. + * Portions of libsocket Copyright 1991, 1992 Free Software Foundation, Inc. + * Portions of libsocket Copyright 1997, 1998 by the Regdos Group. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * windows.c - General functions for libsocket, when it's running under + * Windows. + */ + +#include +#include +#include + +#include + +/* ------------------------- + * - __get_windows_version - + * ------------------------- */ + +int __get_windows_version (void) +{ + __dpmi_regs r; + int win_version; + + /* Get the windows version with INT 0x2F sub-function 0x160A, + * Windows 3.1+ installation check. This version check isn't + * amazing, but is probably enough because if the version isn't right + * then the VxDs will fail to load anyway. */ + bzero((void *) &r, sizeof(r)); + r.x.ax = 0x160A; + __dpmi_int(0x2F, &r); + + if (r.h.bh == 3) { + win_version = WIN_311; + } else if (r.h.bh > 3) { + /* TODO: Distinguish between '95, '98? */ + /* Windows '95 or '98 */ + win_version = WIN_95; + } else { + win_version = WIN_NONE; + } + + /* If win_version is WIN_NONE, then we need to use the DOS version to + * determine if this is Windows NT. Thanks to Allegro (Shawn Hargreaves + * et al) for this method. It's also in Ralph Brown's Interrupt list, + * INT 0x21, AX = 0x3306. */ + if (win_version == WIN_NONE) { + if (_get_dos_version(1) == 0x532) { + win_version = WIN_NT; + } + } + + return(win_version); +}