Moving net kit libnet.so and libnetapi.so source code to /current.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@895 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
0fce772df1
commit
f3dfda1779
@ -39,3 +39,4 @@ SubInclude OBOS_TOP src kits support ;
|
||||
SubInclude OBOS_TOP src kits translation ;
|
||||
SubInclude OBOS_TOP src kits device ;
|
||||
SubInclude OBOS_TOP src kits game ;
|
||||
# SubInclude OBOS_TOP src kits net ;
|
||||
|
49
src/kits/network/libnet/Jamfile
Normal file
49
src/kits/network/libnet/Jamfile
Normal file
@ -0,0 +1,49 @@
|
||||
SubDir OBOS_TOP src kits net libnet ;
|
||||
|
||||
UsePosixHeaders ;
|
||||
|
||||
SharedLibrary net :
|
||||
socket.c
|
||||
select.c
|
||||
poll.c
|
||||
compat.c
|
||||
arc4random.c
|
||||
base64.c
|
||||
ethers.c
|
||||
freeaddrinfo.c
|
||||
inet_addr.c
|
||||
inet_ntoa.c
|
||||
inet_neta.c
|
||||
inet_netof.c
|
||||
inet_lnaof.c
|
||||
inet_network.c
|
||||
inet_pton.c
|
||||
inet_ntop.c
|
||||
getaddrinfo.c
|
||||
gethostnamadr.c
|
||||
getnameinfo.c
|
||||
getnetbyaddr.c
|
||||
getnetbyname.c
|
||||
getnetnamadr.c
|
||||
getprotoname.c
|
||||
getnetent.c
|
||||
getproto.c
|
||||
getprotoent.c
|
||||
getservent.c
|
||||
getservbyname.c
|
||||
getservbyport.c
|
||||
linkaddr.c
|
||||
res_comp.c
|
||||
res_data.c
|
||||
res_debug.c
|
||||
res_init.c
|
||||
res_mkquery.c
|
||||
res_query.c
|
||||
res_random.c
|
||||
res_send.c
|
||||
sethostent.c
|
||||
;
|
||||
|
||||
LinkSharedOSLibs libnet.so :
|
||||
root
|
||||
;
|
146
src/kits/network/libnet/arc4random.c
Normal file
146
src/kits/network/libnet/arc4random.c
Normal file
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Arc4 random number generator for OpenBSD.
|
||||
* Copyright 1996 David Mazieres <dm@lcs.mit.edu>.
|
||||
*
|
||||
* Modification and redistribution in source and binary forms is
|
||||
* permitted provided that due credit is given to the author and the
|
||||
* OpenBSD project by leaving this copyright notice intact.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is derived from section 17.1 of Applied Cryptography,
|
||||
* second edition, which describes a stream cipher allegedly
|
||||
* compatible with RSA Labs "RC4" cipher (the actual description of
|
||||
* which is a trade secret). The same algorithm is used as a stream
|
||||
* cipher called "arcfour" in Tatu Ylonen's ssh package.
|
||||
*
|
||||
* Here the stream cipher has been modified always to include the time
|
||||
* when initializing the state. That makes it impossible to
|
||||
* regenerate the same random sequence twice, so this can't be used
|
||||
* for encryption, but will generate good random numbers.
|
||||
*
|
||||
* RC4 is a registered trademark of RSA Laboratories.
|
||||
*/
|
||||
|
||||
#include <kernel/OS.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define inline __inline
|
||||
#else /* !__GNUC__ */
|
||||
#define inline
|
||||
#endif /* !__GNUC__ */
|
||||
|
||||
struct arc4_stream {
|
||||
uint8 i;
|
||||
uint8 j;
|
||||
uint8 s[256];
|
||||
};
|
||||
|
||||
int rs_initialized;
|
||||
static struct arc4_stream rs;
|
||||
|
||||
|
||||
static inline void arc4_init(struct arc4_stream *as)
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < 256; n++)
|
||||
as->s[n] = n;
|
||||
as->i = 0;
|
||||
as->j = 0;
|
||||
}
|
||||
|
||||
|
||||
static inline void arc4_addrandom(struct arc4_stream *as,
|
||||
u_char *dat, int datlen)
|
||||
{
|
||||
int n;
|
||||
uint8 si;
|
||||
|
||||
as->i--;
|
||||
for (n = 0; n < 256; n++) {
|
||||
as->i = (as->i + 1);
|
||||
si = as->s[as->i];
|
||||
as->j = (as->j + si + dat[n % datlen]);
|
||||
as->s[as->i] = as->s[as->j];
|
||||
as->s[as->j] = si;
|
||||
}
|
||||
as->j = as->i;
|
||||
}
|
||||
|
||||
|
||||
static void arc4_stir(struct arc4_stream *as)
|
||||
{
|
||||
int fd;
|
||||
struct {
|
||||
struct timeval tv;
|
||||
u_int rnd[(128 - sizeof(struct timeval)) / sizeof(u_int)];
|
||||
} rdat;
|
||||
|
||||
gettimeofday(&rdat.tv, NULL);
|
||||
fd = open("/dev/arandom", O_RDONLY);
|
||||
if (fd != -1) {
|
||||
read(fd, rdat.rnd, sizeof(rdat.rnd));
|
||||
close(fd);
|
||||
}
|
||||
/* fd < 0 or failed sysctl ? Ah, what the heck. We'll just take
|
||||
* whatever was on the stack... */
|
||||
|
||||
arc4_addrandom(as, (void *) &rdat, sizeof(rdat));
|
||||
}
|
||||
|
||||
|
||||
static inline uint8 arc4_getbyte(struct arc4_stream *as)
|
||||
{
|
||||
uint8 si, sj;
|
||||
|
||||
as->i = (as->i + 1);
|
||||
si = as->s[as->i];
|
||||
as->j = (as->j + si);
|
||||
sj = as->s[as->j];
|
||||
as->s[as->i] = sj;
|
||||
as->s[as->j] = si;
|
||||
return (as->s[(si + sj) & 0xff]);
|
||||
}
|
||||
|
||||
|
||||
static inline uint32 arc4_getword(struct arc4_stream *as)
|
||||
{
|
||||
uint32 val;
|
||||
val = arc4_getbyte(as) << 24;
|
||||
val |= arc4_getbyte(as) << 16;
|
||||
val |= arc4_getbyte(as) << 8;
|
||||
val |= arc4_getbyte(as);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
void arc4random_stir(void)
|
||||
{
|
||||
if (!rs_initialized) {
|
||||
arc4_init(&rs);
|
||||
rs_initialized = 1;
|
||||
}
|
||||
arc4_stir(&rs);
|
||||
}
|
||||
|
||||
void arc4random_addrandom(u_char *dat, int datlen)
|
||||
{
|
||||
if (!rs_initialized)
|
||||
arc4random_stir();
|
||||
arc4_addrandom(&rs, dat, datlen);
|
||||
}
|
||||
|
||||
|
||||
uint32 arc4random()
|
||||
{
|
||||
if (!rs_initialized)
|
||||
arc4random_stir();
|
||||
return arc4_getword(&rs);
|
||||
}
|
315
src/kits/network/libnet/base64.c
Normal file
315
src/kits/network/libnet/base64.c
Normal file
@ -0,0 +1,315 @@
|
||||
/*
|
||||
* Copyright (c) 1996 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
||||
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
||||
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Portions Copyright (c) 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.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <resolv.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define Assert(Cond) if (!(Cond)) abort()
|
||||
|
||||
static const char Base64[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
static const char Pad64 = '=';
|
||||
|
||||
/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
|
||||
The following encoding technique is taken from RFC 1521 by Borenstein
|
||||
and Freed. It is reproduced here in a slightly edited form for
|
||||
convenience.
|
||||
|
||||
A 65-character subset of US-ASCII is used, enabling 6 bits to be
|
||||
represented per printable character. (The extra 65th character, "=",
|
||||
is used to signify a special processing function.)
|
||||
|
||||
The encoding process represents 24-bit groups of input bits as output
|
||||
strings of 4 encoded characters. Proceeding from left to right, a
|
||||
24-bit input group is formed by concatenating 3 8-bit input groups.
|
||||
These 24 bits are then treated as 4 concatenated 6-bit groups, each
|
||||
of which is translated into a single digit in the base64 alphabet.
|
||||
|
||||
Each 6-bit group is used as an index into an array of 64 printable
|
||||
characters. The character referenced by the index is placed in the
|
||||
output string.
|
||||
|
||||
Table 1: The Base64 Alphabet
|
||||
|
||||
Value Encoding Value Encoding Value Encoding Value Encoding
|
||||
0 A 17 R 34 i 51 z
|
||||
1 B 18 S 35 j 52 0
|
||||
2 C 19 T 36 k 53 1
|
||||
3 D 20 U 37 l 54 2
|
||||
4 E 21 V 38 m 55 3
|
||||
5 F 22 W 39 n 56 4
|
||||
6 G 23 X 40 o 57 5
|
||||
7 H 24 Y 41 p 58 6
|
||||
8 I 25 Z 42 q 59 7
|
||||
9 J 26 a 43 r 60 8
|
||||
10 K 27 b 44 s 61 9
|
||||
11 L 28 c 45 t 62 +
|
||||
12 M 29 d 46 u 63 /
|
||||
13 N 30 e 47 v
|
||||
14 O 31 f 48 w (pad) =
|
||||
15 P 32 g 49 x
|
||||
16 Q 33 h 50 y
|
||||
|
||||
Special processing is performed if fewer than 24 bits are available
|
||||
at the end of the data being encoded. A full encoding quantum is
|
||||
always completed at the end of a quantity. When fewer than 24 input
|
||||
bits are available in an input group, zero bits are added (on the
|
||||
right) to form an integral number of 6-bit groups. Padding at the
|
||||
end of the data is performed using the '=' character.
|
||||
|
||||
Since all base64 input is an integral number of octets, only the
|
||||
-------------------------------------------------
|
||||
following cases can arise:
|
||||
|
||||
(1) the final quantum of encoding input is an integral
|
||||
multiple of 24 bits; here, the final unit of encoded
|
||||
output will be an integral multiple of 4 characters
|
||||
with no "=" padding,
|
||||
(2) the final quantum of encoding input is exactly 8 bits;
|
||||
here, the final unit of encoded output will be two
|
||||
characters followed by two "=" padding characters, or
|
||||
(3) the final quantum of encoding input is exactly 16 bits;
|
||||
here, the final unit of encoded output will be three
|
||||
characters followed by one "=" padding character.
|
||||
*/
|
||||
|
||||
int
|
||||
b64_ntop(src, srclength, target, targsize)
|
||||
u_char const *src;
|
||||
size_t srclength;
|
||||
char *target;
|
||||
size_t targsize;
|
||||
{
|
||||
size_t datalength = 0;
|
||||
u_char input[3];
|
||||
u_char output[4];
|
||||
int i;
|
||||
|
||||
while (2 < srclength) {
|
||||
input[0] = *src++;
|
||||
input[1] = *src++;
|
||||
input[2] = *src++;
|
||||
srclength -= 3;
|
||||
|
||||
output[0] = input[0] >> 2;
|
||||
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
|
||||
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
|
||||
output[3] = input[2] & 0x3f;
|
||||
Assert(output[0] < 64);
|
||||
Assert(output[1] < 64);
|
||||
Assert(output[2] < 64);
|
||||
Assert(output[3] < 64);
|
||||
|
||||
if (datalength + 4 > targsize)
|
||||
return (-1);
|
||||
target[datalength++] = Base64[output[0]];
|
||||
target[datalength++] = Base64[output[1]];
|
||||
target[datalength++] = Base64[output[2]];
|
||||
target[datalength++] = Base64[output[3]];
|
||||
}
|
||||
|
||||
/* Now we worry about padding. */
|
||||
if (0 != srclength) {
|
||||
/* Get what's left. */
|
||||
input[0] = input[1] = input[2] = '\0';
|
||||
for (i = 0; i < srclength; i++)
|
||||
input[i] = *src++;
|
||||
|
||||
output[0] = input[0] >> 2;
|
||||
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
|
||||
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
|
||||
Assert(output[0] < 64);
|
||||
Assert(output[1] < 64);
|
||||
Assert(output[2] < 64);
|
||||
|
||||
if (datalength + 4 > targsize)
|
||||
return (-1);
|
||||
target[datalength++] = Base64[output[0]];
|
||||
target[datalength++] = Base64[output[1]];
|
||||
if (srclength == 1)
|
||||
target[datalength++] = Pad64;
|
||||
else
|
||||
target[datalength++] = Base64[output[2]];
|
||||
target[datalength++] = Pad64;
|
||||
}
|
||||
if (datalength >= targsize)
|
||||
return (-1);
|
||||
target[datalength] = '\0'; /* Returned value doesn't count \0. */
|
||||
return (datalength);
|
||||
}
|
||||
|
||||
/* skips all whitespace anywhere.
|
||||
converts characters, four at a time, starting at (or after)
|
||||
src from base - 64 numbers into three 8 bit bytes in the target area.
|
||||
it returns the number of data bytes stored at the target, or -1 on error.
|
||||
*/
|
||||
|
||||
int
|
||||
b64_pton(src, target, targsize)
|
||||
char const *src;
|
||||
u_char *target;
|
||||
size_t targsize;
|
||||
{
|
||||
int tarindex, state, ch;
|
||||
char *pos;
|
||||
|
||||
state = 0;
|
||||
tarindex = 0;
|
||||
|
||||
while ((ch = *src++) != '\0') {
|
||||
if (isspace(ch)) /* Skip whitespace anywhere. */
|
||||
continue;
|
||||
|
||||
if (ch == Pad64)
|
||||
break;
|
||||
|
||||
pos = strchr(Base64, ch);
|
||||
if (pos == 0) /* A non-base64 character. */
|
||||
return (-1);
|
||||
|
||||
switch (state) {
|
||||
case 0:
|
||||
if (target) {
|
||||
if (tarindex >= targsize)
|
||||
return (-1);
|
||||
target[tarindex] = (pos - Base64) << 2;
|
||||
}
|
||||
state = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (target) {
|
||||
if (tarindex + 1 >= targsize)
|
||||
return (-1);
|
||||
target[tarindex] |= (pos - Base64) >> 4;
|
||||
target[tarindex+1] = ((pos - Base64) & 0x0f)
|
||||
<< 4 ;
|
||||
}
|
||||
tarindex++;
|
||||
state = 2;
|
||||
break;
|
||||
case 2:
|
||||
if (target) {
|
||||
if (tarindex + 1 >= targsize)
|
||||
return (-1);
|
||||
target[tarindex] |= (pos - Base64) >> 2;
|
||||
target[tarindex+1] = ((pos - Base64) & 0x03)
|
||||
<< 6;
|
||||
}
|
||||
tarindex++;
|
||||
state = 3;
|
||||
break;
|
||||
case 3:
|
||||
if (target) {
|
||||
if (tarindex >= targsize)
|
||||
return (-1);
|
||||
target[tarindex] |= (pos - Base64);
|
||||
}
|
||||
tarindex++;
|
||||
state = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We are done decoding Base-64 chars. Let's see if we ended
|
||||
* on a byte boundary, and/or with erroneous trailing characters.
|
||||
*/
|
||||
|
||||
if (ch == Pad64) { /* We got a pad char. */
|
||||
ch = *src++; /* Skip it, get next. */
|
||||
switch (state) {
|
||||
case 0: /* Invalid = in first position */
|
||||
case 1: /* Invalid = in second position */
|
||||
return (-1);
|
||||
|
||||
case 2: /* Valid, means one byte of info */
|
||||
/* Skip any number of spaces. */
|
||||
for (; ch != '\0'; ch = *src++)
|
||||
if (!isspace(ch))
|
||||
break;
|
||||
/* Make sure there is another trailing = sign. */
|
||||
if (ch != Pad64)
|
||||
return (-1);
|
||||
ch = *src++; /* Skip the = */
|
||||
/* Fall through to "single trailing =" case. */
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case 3: /* Valid, means two bytes of info */
|
||||
/*
|
||||
* We know this char is an =. Is there anything but
|
||||
* whitespace after it?
|
||||
*/
|
||||
for (; ch != '\0'; ch = *src++)
|
||||
if (!isspace(ch))
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* Now make sure for cases 2 and 3 that the "extra"
|
||||
* bits that slopped past the last full byte were
|
||||
* zeros. If we don't check them, they become a
|
||||
* subliminal channel.
|
||||
*/
|
||||
if (target && target[tarindex] != 0)
|
||||
return (-1);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* We ended by seeing the end of the string. Make sure we
|
||||
* have no partial bytes lying around.
|
||||
*/
|
||||
if (state != 0)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (tarindex);
|
||||
}
|
134
src/kits/network/libnet/compat.c
Normal file
134
src/kits/network/libnet/compat.c
Normal file
@ -0,0 +1,134 @@
|
||||
/* compat.c */
|
||||
|
||||
/* These routines are included in libnet simply because R5 expects them
|
||||
* to be there. They should mostly be no-ops...
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <kernel/OS.h>
|
||||
#include <iovec.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <TLS.h>
|
||||
|
||||
static int32 h_errno_tls;
|
||||
|
||||
/* These should probably be moved to a seperate file as they
|
||||
* are unique to the library as a whole...
|
||||
*/
|
||||
|
||||
void _init()
|
||||
{
|
||||
h_errno_tls = tls_allocate();
|
||||
}
|
||||
|
||||
void _fini()
|
||||
{
|
||||
}
|
||||
|
||||
struct net_settings {
|
||||
int dummy;
|
||||
};
|
||||
|
||||
_EXPORT int closesocket(int sock)
|
||||
{
|
||||
return close(sock);
|
||||
}
|
||||
|
||||
|
||||
_EXPORT const char * hstrerror(int error)
|
||||
{
|
||||
printf("hstrerror() not yet supported.");
|
||||
return "hstrerror() not supported yet";
|
||||
}
|
||||
|
||||
|
||||
_EXPORT int herror()
|
||||
{
|
||||
printf("herror() not yet supported.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
_EXPORT int *_h_errnop()
|
||||
{
|
||||
return (int *)tls_address(h_errno_tls);
|
||||
}
|
||||
|
||||
|
||||
_EXPORT int _socket_interrupt()
|
||||
{
|
||||
printf("_socket_interrupt\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
_EXPORT int _netconfig_find()
|
||||
{
|
||||
printf("_netconfig_find\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is a terrible hack :(
|
||||
* We should really get these settings values by parsing $HOME/config/settings/network file, which
|
||||
* will make both R5 and BONE compatible
|
||||
*/
|
||||
|
||||
_EXPORT char * find_net_setting(struct net_settings * ncw, const char * heading, const char * name, char * value, unsigned nbytes)
|
||||
{
|
||||
|
||||
printf("find_net_setting\n");
|
||||
|
||||
if (strcmp(heading, "GLOBAL") != 0)
|
||||
return NULL;
|
||||
|
||||
if (strcmp(name, "HOSTNAME") == 0)
|
||||
strncpy(value, "hostname", nbytes);
|
||||
else if (strcmp(name, "USERNAME") == 0)
|
||||
strncpy(value, "baron\0", nbytes);
|
||||
else if (strcmp(name, "PASSWORD") == 0)
|
||||
strncpy(value, "password", nbytes);
|
||||
else
|
||||
return NULL;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
_EXPORT status_t set_net_setting(struct net_settings * ncw, const char * heading, const char * name, const char * value)
|
||||
{
|
||||
printf("set_net_setting\n");
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
_EXPORT int gethostname(char * name, size_t length)
|
||||
{
|
||||
printf("gethostname\n");
|
||||
if (find_net_setting(NULL, "GLOBAL", "HOSTNAME", name, length) == NULL)
|
||||
return B_ERROR;
|
||||
|
||||
return strlen(name);
|
||||
}
|
||||
|
||||
|
||||
_EXPORT int getusername(char * name, uint length)
|
||||
{
|
||||
printf("getusername\n");
|
||||
if (find_net_setting(NULL, "GLOBAL", "USERNAME", name, length) == NULL)
|
||||
return B_ERROR;
|
||||
|
||||
return strlen(name);
|
||||
}
|
||||
|
||||
|
||||
_EXPORT int getpassword(char * pwd, uint length)
|
||||
{
|
||||
printf("getpassword\n");
|
||||
if (find_net_setting(NULL, "GLOBAL", "PASSWORD", pwd, length) == NULL)
|
||||
return B_ERROR;
|
||||
|
||||
return strlen(pwd);
|
||||
}
|
||||
|
||||
|
261
src/kits/network/libnet/ethers.c
Normal file
261
src/kits/network/libnet/ethers.c
Normal file
@ -0,0 +1,261 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ethers(3) a la Sun.
|
||||
* Originally Written by Roland McGrath <roland@frob.com> 10/14/93.
|
||||
* Substantially modified by Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/if_ether.h>
|
||||
#include <sys/param.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#ifdef YP
|
||||
#include <rpcsvc/ypclnt.h>
|
||||
#endif
|
||||
|
||||
#include "netdb.h" /* for MAXHOSTNAMELEN */
|
||||
#ifndef _PATH_ETHERS
|
||||
#define _PATH_ETHERS "/etc/ethers"
|
||||
#endif
|
||||
|
||||
static char * _ether_aton (char *, struct ether_addr *);
|
||||
|
||||
char *ether_ntoa(struct ether_addr *e)
|
||||
{
|
||||
static char a[] = "xx:xx:xx:xx:xx:xx";
|
||||
|
||||
if (e->ether_addr_octet[0] > 0xFF || e->ether_addr_octet[1] > 0xFF ||
|
||||
e->ether_addr_octet[2] > 0xFF || e->ether_addr_octet[3] > 0xFF ||
|
||||
e->ether_addr_octet[4] > 0xFF || e->ether_addr_octet[5] > 0xFF) {
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
(void)sprintf(a, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
e->ether_addr_octet[0], e->ether_addr_octet[1],
|
||||
e->ether_addr_octet[2], e->ether_addr_octet[3],
|
||||
e->ether_addr_octet[4], e->ether_addr_octet[5]);
|
||||
|
||||
return (a);
|
||||
}
|
||||
|
||||
|
||||
static char *_ether_aton(char *s, struct ether_addr *e)
|
||||
{
|
||||
int i;
|
||||
long l;
|
||||
char *pp;
|
||||
|
||||
while (isspace(*s))
|
||||
s++;
|
||||
|
||||
/* expect 6 hex octets separated by ':' or space/NUL if last octet */
|
||||
for (i = 0; i < 6; i++) {
|
||||
l = strtol(s, &pp, 16);
|
||||
if (pp == s || l > 0xFF || l < 0)
|
||||
return (NULL);
|
||||
if (!(*pp == ':' || (i == 5 && (isspace(*pp) || *pp == '\0'))))
|
||||
return (NULL);
|
||||
e->ether_addr_octet[i] = (u_char)l;
|
||||
s = pp + 1;
|
||||
}
|
||||
|
||||
/* return character after the octets ala strtol(3) */
|
||||
return (pp);
|
||||
}
|
||||
|
||||
|
||||
struct ether_addr *ether_aton(char *s)
|
||||
{
|
||||
static struct ether_addr n;
|
||||
|
||||
return (_ether_aton(s, &n) ? &n : NULL);
|
||||
}
|
||||
|
||||
|
||||
int ether_ntohost(char *hostname, struct ether_addr *e)
|
||||
{
|
||||
FILE *f;
|
||||
char buf[BUFSIZ+1], *p;
|
||||
size_t len;
|
||||
struct ether_addr try;
|
||||
char lbuf[80];
|
||||
#ifdef YP
|
||||
char trybuf[sizeof("xx:xx:xx:xx:xx:xx")];
|
||||
int trylen;
|
||||
#endif
|
||||
|
||||
if (e->ether_addr_octet[0] > 0xFF || e->ether_addr_octet[1] > 0xFF ||
|
||||
e->ether_addr_octet[2] > 0xFF || e->ether_addr_octet[3] > 0xFF ||
|
||||
e->ether_addr_octet[4] > 0xFF || e->ether_addr_octet[5] > 0xFF) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#ifdef YP
|
||||
sprintf(trybuf, "%x:%x:%x:%x:%x:%x",
|
||||
e->ether_addr_octet[0], e->ether_addr_octet[1],
|
||||
e->ether_addr_octet[2], e->ether_addr_octet[3],
|
||||
e->ether_addr_octet[4], e->ether_addr_octet[5]);
|
||||
trylen = strlen(trybuf);
|
||||
#endif
|
||||
|
||||
f = fopen(_PATH_ETHERS, "r");
|
||||
if (f == NULL)
|
||||
return (-1);
|
||||
while (fgets(lbuf, 80, f) != NULL) {
|
||||
len = strlen(lbuf);
|
||||
p = lbuf;
|
||||
if (p[len-1] == '\n')
|
||||
len--;
|
||||
if (len > sizeof(buf) - 2)
|
||||
continue;
|
||||
(void)memcpy(buf, p, len);
|
||||
buf[len] = '\n'; /* code assumes newlines later on */
|
||||
buf[len+1] = '\0';
|
||||
#ifdef YP
|
||||
/* A + in the file means try YP now. */
|
||||
if (!strncmp(buf, "+\n", sizeof(buf))) {
|
||||
char *ypbuf, *ypdom;
|
||||
int ypbuflen;
|
||||
|
||||
if (yp_get_default_domain(&ypdom))
|
||||
continue;
|
||||
if (yp_match(ypdom, "ethers.byaddr", trybuf,
|
||||
trylen, &ypbuf, &ypbuflen))
|
||||
continue;
|
||||
if (ether_line(ypbuf, &try, hostname) == 0) {
|
||||
free(ypbuf);
|
||||
(void)fclose(f);
|
||||
return (0);
|
||||
}
|
||||
free(ypbuf);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (ether_line(buf, &try, hostname) == 0 &&
|
||||
memcmp((void *)&try, (void *)e, sizeof(try)) == 0) {
|
||||
(void)fclose(f);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
(void)fclose(f);
|
||||
errno = ENOENT;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
int
|
||||
ether_hostton(hostname, e)
|
||||
char *hostname;
|
||||
struct ether_addr *e;
|
||||
{
|
||||
FILE *f;
|
||||
char buf[BUFSIZ+1], *p;
|
||||
char try[MAXHOSTNAMELEN];
|
||||
size_t len;
|
||||
char lbuf[80];
|
||||
#ifdef YP
|
||||
int hostlen = strlen(hostname);
|
||||
#endif
|
||||
|
||||
f = fopen(_PATH_ETHERS, "r");
|
||||
if (f==NULL)
|
||||
return (-1);
|
||||
|
||||
while (fgets(lbuf, 80, f) != NULL) {
|
||||
len = strlen(lbuf);
|
||||
p = lbuf;
|
||||
if (p[len-1] == '\n')
|
||||
len--;
|
||||
if (len > sizeof(buf) - 2)
|
||||
continue;
|
||||
memcpy(buf, p, len);
|
||||
buf[len] = '\n'; /* code assumes newlines later on */
|
||||
buf[len+1] = '\0';
|
||||
#ifdef YP
|
||||
/* A + in the file means try YP now. */
|
||||
if (!strncmp(buf, "+\n", sizeof(buf))) {
|
||||
char *ypbuf, *ypdom;
|
||||
int ypbuflen;
|
||||
|
||||
if (yp_get_default_domain(&ypdom))
|
||||
continue;
|
||||
if (yp_match(ypdom, "ethers.byname", hostname, hostlen,
|
||||
&ypbuf, &ypbuflen))
|
||||
continue;
|
||||
if (ether_line(ypbuf, e, try) == 0) {
|
||||
free(ypbuf);
|
||||
(void)fclose(f);
|
||||
return (0);
|
||||
}
|
||||
free(ypbuf);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (ether_line(buf, e, try) == 0 && strcmp(hostname, try) == 0) {
|
||||
(void)fclose(f);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
(void)fclose(f);
|
||||
errno = ENOENT;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
int ether_line(char *line, struct ether_addr *e, char *hostname)
|
||||
{
|
||||
char *p;
|
||||
size_t n;
|
||||
|
||||
/* Parse "xx:xx:xx:xx:xx:xx" */
|
||||
if ((p = _ether_aton(line, e)) == NULL || (*p != ' ' && *p != '\t'))
|
||||
goto bad;
|
||||
|
||||
/* Now get the hostname */
|
||||
while (isspace(*p))
|
||||
p++;
|
||||
if (*p == '\0')
|
||||
goto bad;
|
||||
n = strcspn(p, " \t\n");
|
||||
if (n >= MAXHOSTNAMELEN)
|
||||
goto bad;
|
||||
strncpy(hostname, p, n + 1);
|
||||
return (0);
|
||||
|
||||
bad:
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
50
src/kits/network/libnet/freeaddrinfo.c
Normal file
50
src/kits/network/libnet/freeaddrinfo.c
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 1997, 1998, 1999, Craig Metz, 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 Craig Metz and
|
||||
* by other contributors.
|
||||
* 4. Neither the name of the author nor the names of 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 <stdlib.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
|
||||
void
|
||||
freeaddrinfo(ai)
|
||||
struct addrinfo *ai;
|
||||
{
|
||||
struct addrinfo *p;
|
||||
|
||||
do {
|
||||
p = ai;
|
||||
ai = ai->ai_next;
|
||||
if (p->ai_canonname)
|
||||
free(p->ai_canonname);
|
||||
free((void *)p);
|
||||
} while (ai);
|
||||
}
|
1822
src/kits/network/libnet/getaddrinfo.c
Normal file
1822
src/kits/network/libnet/getaddrinfo.c
Normal file
File diff suppressed because it is too large
Load Diff
1182
src/kits/network/libnet/gethostnamadr.c
Normal file
1182
src/kits/network/libnet/gethostnamadr.c
Normal file
File diff suppressed because it is too large
Load Diff
358
src/kits/network/libnet/getnameinfo.c
Normal file
358
src/kits/network/libnet/getnameinfo.c
Normal file
@ -0,0 +1,358 @@
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Issues to be discussed:
|
||||
* - Thread safe-ness must be checked
|
||||
* - RFC2553 says that we should raise error on short buffer. X/Open says
|
||||
* we need to truncate the result. We obey RFC2553 (and X/Open should be
|
||||
* modified). ipngwg rough consensus seems to follow RFC2553.
|
||||
* - What is "local" in NI_FQDN?
|
||||
* - NI_NAMEREQD and NI_NUMERICHOST conflict with each other.
|
||||
* - (KAME extension) always attach textual scopeid (fe80::1%lo0), if
|
||||
* sin6_scope_id is filled - standardization status?
|
||||
* XXX breaks backward compat for code that expects no scopeid.
|
||||
* beware on merge.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <netdb.h>
|
||||
#include <resolv.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
|
||||
static const struct afd {
|
||||
int a_af;
|
||||
int a_addrlen;
|
||||
int a_socklen;
|
||||
int a_off;
|
||||
} afdl [] = {
|
||||
#ifdef INET6
|
||||
{PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
|
||||
offsetof(struct sockaddr_in6, sin6_addr)},
|
||||
#endif
|
||||
{PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
|
||||
offsetof(struct sockaddr_in, sin_addr)},
|
||||
{0, 0, 0},
|
||||
};
|
||||
|
||||
struct sockinet {
|
||||
u_char si_len;
|
||||
u_char si_family;
|
||||
u_short si_port;
|
||||
};
|
||||
|
||||
#ifdef INET6
|
||||
static int ip6_parsenumeric (const struct sockaddr *, const char *, char *,
|
||||
size_t, int);
|
||||
static int ip6_sa2str (const struct sockaddr_in6 *, char *, size_t, int);
|
||||
#endif
|
||||
|
||||
int
|
||||
getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
|
||||
const struct sockaddr *sa;
|
||||
socklen_t salen;
|
||||
char *host;
|
||||
size_t hostlen;
|
||||
char *serv;
|
||||
size_t servlen;
|
||||
int flags;
|
||||
{
|
||||
const struct afd *afd;
|
||||
struct servent *sp;
|
||||
struct hostent *hp;
|
||||
u_short port;
|
||||
int family, i;
|
||||
const char *addr;
|
||||
uint32 v4a;
|
||||
int h_error;
|
||||
char numserv[512];
|
||||
char numaddr[512];
|
||||
|
||||
if (sa == NULL)
|
||||
return EAI_FAIL;
|
||||
|
||||
if (sa->sa_len != salen)
|
||||
return EAI_FAIL;
|
||||
|
||||
family = sa->sa_family;
|
||||
for (i = 0; afdl[i].a_af; i++)
|
||||
if (afdl[i].a_af == family) {
|
||||
afd = &afdl[i];
|
||||
goto found;
|
||||
}
|
||||
return EAI_FAMILY;
|
||||
|
||||
found:
|
||||
if (salen != afd->a_socklen)
|
||||
return EAI_FAIL;
|
||||
|
||||
/* network byte order */
|
||||
port = ((const struct sockinet *)sa)->si_port;
|
||||
addr = (const char *)sa + afd->a_off;
|
||||
|
||||
if (serv == NULL || servlen == 0) {
|
||||
/*
|
||||
* do nothing in this case.
|
||||
* in case you are wondering if "&&" is more correct than
|
||||
* "||" here: rfc2553bis-03 says that serv == NULL OR
|
||||
* servlen == 0 means that the caller does not want the result.
|
||||
*/
|
||||
} else {
|
||||
if (flags & NI_NUMERICSERV)
|
||||
sp = NULL;
|
||||
else {
|
||||
sp = getservbyport(port,
|
||||
(flags & NI_DGRAM) ? "udp" : "tcp");
|
||||
}
|
||||
if (sp) {
|
||||
if (strlen(sp->s_name) + 1 > servlen)
|
||||
return EAI_MEMORY;
|
||||
strcpy(serv, sp->s_name);
|
||||
} else {
|
||||
#ifdef _MWERKS_STDIO_H_
|
||||
sprintf(numserv, "%d", ntohs(port));
|
||||
#else
|
||||
snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
|
||||
#endif
|
||||
if (strlen(numserv) + 1 > servlen)
|
||||
return EAI_MEMORY;
|
||||
strcpy(serv, numserv);
|
||||
}
|
||||
}
|
||||
|
||||
switch (sa->sa_family) {
|
||||
case AF_INET:
|
||||
v4a = (uint32)
|
||||
ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr);
|
||||
if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
|
||||
flags |= NI_NUMERICHOST;
|
||||
v4a >>= IN_CLASSA_NSHIFT;
|
||||
if (v4a == 0)
|
||||
flags |= NI_NUMERICHOST;
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
{
|
||||
const struct sockaddr_in6 *sin6;
|
||||
sin6 = (const struct sockaddr_in6 *)sa;
|
||||
switch (sin6->sin6_addr.s6_addr[0]) {
|
||||
case 0x00:
|
||||
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
|
||||
;
|
||||
else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
|
||||
;
|
||||
else
|
||||
flags |= NI_NUMERICHOST;
|
||||
break;
|
||||
default:
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
|
||||
flags |= NI_NUMERICHOST;
|
||||
}
|
||||
else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
|
||||
flags |= NI_NUMERICHOST;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
if (host == NULL || hostlen == 0) {
|
||||
/*
|
||||
* do nothing in this case.
|
||||
* in case you are wondering if "&&" is more correct than
|
||||
* "||" here: rfc2553bis-03 says that host == NULL or
|
||||
* hostlen == 0 means that the caller does not want the result.
|
||||
*/
|
||||
} else if (flags & NI_NUMERICHOST) {
|
||||
int numaddrlen;
|
||||
|
||||
/* NUMERICHOST and NAMEREQD conflicts with each other */
|
||||
if (flags & NI_NAMEREQD)
|
||||
return EAI_NONAME;
|
||||
|
||||
switch(afd->a_af) {
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
{
|
||||
int error;
|
||||
|
||||
if ((error = ip6_parsenumeric(sa, addr, host,
|
||||
hostlen, flags)) != 0)
|
||||
return(error);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
|
||||
== NULL)
|
||||
return EAI_SYSTEM;
|
||||
numaddrlen = strlen(numaddr);
|
||||
if (numaddrlen + 1 > hostlen) /* don't forget terminator */
|
||||
return EAI_MEMORY;
|
||||
strcpy(host, numaddr);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
|
||||
h_error = h_errno;
|
||||
|
||||
if (hp) {
|
||||
#if 0
|
||||
/*
|
||||
* commented out, since "for local host" is not
|
||||
* implemented here - see RFC2553 p30
|
||||
*/
|
||||
if (flags & NI_NOFQDN) {
|
||||
char *p;
|
||||
p = strchr(hp->h_name, '.');
|
||||
if (p)
|
||||
*p = '\0';
|
||||
}
|
||||
#endif
|
||||
if (strlen(hp->h_name) + 1 > hostlen) {
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
strcpy(host, hp->h_name);
|
||||
} else {
|
||||
if (flags & NI_NAMEREQD)
|
||||
return EAI_NONAME;
|
||||
switch(afd->a_af) {
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
{
|
||||
int error;
|
||||
|
||||
if ((error = ip6_parsenumeric(sa, addr, host,
|
||||
hostlen,
|
||||
flags)) != 0)
|
||||
return(error);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
if (inet_ntop(afd->a_af, addr, host,
|
||||
hostlen) == NULL)
|
||||
return EAI_SYSTEM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
static int
|
||||
ip6_parsenumeric(sa, addr, host, hostlen, flags)
|
||||
const struct sockaddr *sa;
|
||||
const char *addr;
|
||||
char *host;
|
||||
size_t hostlen;
|
||||
int flags;
|
||||
{
|
||||
int numaddrlen;
|
||||
char numaddr[512];
|
||||
|
||||
if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) == NULL)
|
||||
return EAI_SYSTEM;
|
||||
|
||||
numaddrlen = strlen(numaddr);
|
||||
if (numaddrlen + 1 > hostlen) /* don't forget terminator */
|
||||
return EAI_MEMORY;
|
||||
strcpy(host, numaddr);
|
||||
|
||||
if (((const struct sockaddr_in6 *)sa)->sin6_scope_id) {
|
||||
char zonebuf[MAXHOSTNAMELEN];
|
||||
int zonelen;
|
||||
|
||||
zonelen = ip6_sa2str(
|
||||
(const struct sockaddr_in6 *)(const void *)sa,
|
||||
zonebuf, sizeof(zonebuf), flags);
|
||||
if (zonelen < 0)
|
||||
return EAI_MEMORY;
|
||||
if (zonelen + 1 + numaddrlen + 1 > hostlen)
|
||||
return EAI_MEMORY;
|
||||
|
||||
/* construct <numeric-addr><delim><zoneid> */
|
||||
memcpy(host + numaddrlen + 1, zonebuf,
|
||||
(size_t)zonelen);
|
||||
host[numaddrlen] = SCOPE_DELIMITER;
|
||||
host[numaddrlen + 1 + zonelen] = '\0';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
ip6_sa2str(sa6, buf, bufsiz, flags)
|
||||
const struct sockaddr_in6 *sa6;
|
||||
char *buf;
|
||||
size_t bufsiz;
|
||||
int flags;
|
||||
{
|
||||
unsigned int ifindex;
|
||||
const struct in6_addr *a6;
|
||||
int n;
|
||||
|
||||
ifindex = (unsigned int)sa6->sin6_scope_id;
|
||||
a6 = &sa6->sin6_addr;
|
||||
|
||||
#ifdef notdef
|
||||
if ((flags & NI_NUMERICSCOPE) != 0) {
|
||||
n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
|
||||
if (n < 0 || n >= bufsiz)
|
||||
return -1;
|
||||
else
|
||||
return n;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* if_indextoname() does not take buffer size. not a good api... */
|
||||
if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) &&
|
||||
bufsiz >= IF_NAMESIZE) {
|
||||
char *p = if_indextoname(ifindex, buf);
|
||||
if (p) {
|
||||
return(strlen(p));
|
||||
}
|
||||
}
|
||||
|
||||
/* last resort */
|
||||
n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
|
||||
if (n < 0 || n >= bufsiz)
|
||||
return -1;
|
||||
else
|
||||
return n;
|
||||
}
|
||||
#endif /* INET6 */
|
54
src/kits/network/libnet/getnetbyaddr.c
Normal file
54
src/kits/network/libnet/getnetbyaddr.c
Normal file
@ -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.
|
||||
*/
|
||||
|
||||
#include <kernel/OS.h>
|
||||
#include "netinet/in.h"
|
||||
#include "netdb.h"
|
||||
|
||||
extern int _net_stayopen;
|
||||
|
||||
struct netent *
|
||||
_getnetbyaddr(net, type)
|
||||
register in_addr_t 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);
|
||||
}
|
60
src/kits/network/libnet/getnetbyname.c
Normal file
60
src/kits/network/libnet/getnetbyname.c
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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 <kernel/OS.h>
|
||||
#include "netinet/in.h"
|
||||
#include "netdb.h"
|
||||
#include <string.h>
|
||||
|
||||
extern int _net_stayopen;
|
||||
|
||||
struct netent *
|
||||
_getnetbyname(name)
|
||||
register const char *name;
|
||||
{
|
||||
register struct netent *p;
|
||||
register char **cp;
|
||||
|
||||
setnetent(_net_stayopen);
|
||||
while ((p = getnetent())) {
|
||||
if (strcasecmp(p->n_name, name) == 0)
|
||||
break;
|
||||
for (cp = p->n_aliases; *cp != 0; cp++)
|
||||
if (strcasecmp(*cp, name) == 0)
|
||||
goto found;
|
||||
}
|
||||
found:
|
||||
if (!_net_stayopen)
|
||||
endnetent();
|
||||
return (p);
|
||||
}
|
131
src/kits/network/libnet/getnetent.c
Normal file
131
src/kits/network/libnet/getnetent.c
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* 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 <sys/types.h>
|
||||
#include <kernel/OS.h>
|
||||
#include "sys/socket.h"
|
||||
#include "netinet/in.h"
|
||||
#include "arpa/inet.h"
|
||||
#include "netdb.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAXALIASES 35
|
||||
|
||||
static FILE *netf;
|
||||
static char line[BUFSIZ+1];
|
||||
static struct netent net;
|
||||
static char *net_aliases[MAXALIASES];
|
||||
int _net_stayopen;
|
||||
|
||||
void
|
||||
setnetent(f)
|
||||
int f;
|
||||
{
|
||||
if (netf == NULL)
|
||||
netf = fopen(_PATH_NETWORKS, "r" );
|
||||
else
|
||||
rewind(netf);
|
||||
_net_stayopen |= f;
|
||||
}
|
||||
|
||||
void
|
||||
endnetent()
|
||||
{
|
||||
if (netf) {
|
||||
fclose(netf);
|
||||
netf = NULL;
|
||||
}
|
||||
_net_stayopen = 0;
|
||||
}
|
||||
|
||||
struct netent *
|
||||
getnetent()
|
||||
{
|
||||
char *p, *cp, **q;
|
||||
size_t len;
|
||||
char buf[80];
|
||||
|
||||
if (netf == NULL && (netf = fopen(_PATH_NETWORKS, "r" )) == NULL)
|
||||
return (NULL);
|
||||
again:
|
||||
if (fgets(buf, 80, netf) == NULL)
|
||||
return NULL;
|
||||
len = strlen(buf);
|
||||
p = &buf[len];
|
||||
// if ((p = fgetln(netf, &len)) == NULL)
|
||||
// return (NULL);
|
||||
if (p[len-1] == '\n')
|
||||
len--;
|
||||
if (len >= sizeof(line) || len == 0)
|
||||
goto again;
|
||||
p = memcpy(line, p, len);
|
||||
line[len] = '\0';
|
||||
if (*p == '#')
|
||||
goto again;
|
||||
if ((cp = strchr(p, '#')) != NULL)
|
||||
*cp = '\0';
|
||||
net.n_name = p;
|
||||
if (strlen(net.n_name) >= MAXHOSTNAMELEN-1)
|
||||
net.n_name[MAXHOSTNAMELEN-1] = '\0';
|
||||
cp = strpbrk(p, " \t");
|
||||
if (cp == NULL)
|
||||
goto again;
|
||||
*cp++ = '\0';
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
p = strpbrk(cp, " \t");
|
||||
if (p != NULL)
|
||||
*p++ = '\0';
|
||||
net.n_net = inet_network(cp);
|
||||
net.n_addrtype = AF_INET;
|
||||
q = net.n_aliases = net_aliases;
|
||||
if (p != NULL)
|
||||
cp = p;
|
||||
while (cp && *cp) {
|
||||
if (*cp == ' ' || *cp == '\t') {
|
||||
cp++;
|
||||
continue;
|
||||
}
|
||||
if (q < &net_aliases[MAXALIASES - 1]) {
|
||||
*q++ = cp;
|
||||
if (strlen(cp) >= MAXHOSTNAMELEN-1)
|
||||
cp[MAXHOSTNAMELEN-1] = '\0';
|
||||
}
|
||||
cp = strpbrk(cp, " \t");
|
||||
if (cp != NULL)
|
||||
*cp++ = '\0';
|
||||
}
|
||||
*q = NULL;
|
||||
return (&net);
|
||||
}
|
393
src/kits/network/libnet/getnetnamadr.c
Normal file
393
src/kits/network/libnet/getnetnamadr.c
Normal file
@ -0,0 +1,393 @@
|
||||
/*
|
||||
* Copyright (c) 1997, Jason Downs. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Jason Downs for the
|
||||
* OpenBSD system.
|
||||
* 4. Neither the name(s) of the author(s) nor the name OpenBSD
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
/* Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
|
||||
* Dep. Matematica Universidade de Coimbra, Portugal, Europe
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*/
|
||||
/*
|
||||
* 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 <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <resolv.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
extern int h_errno;
|
||||
|
||||
struct netent *_getnetbyaddr (in_addr_t net, int type);
|
||||
struct netent *_getnetbyname (const char *name);
|
||||
|
||||
int _hokchar (const char *);
|
||||
|
||||
#define BYADDR 0
|
||||
#define BYNAME 1
|
||||
#define MAXALIASES 35
|
||||
|
||||
#if PACKETSZ > 1024
|
||||
#define MAXPACKET PACKETSZ
|
||||
#else
|
||||
#define MAXPACKET 1024
|
||||
#endif
|
||||
|
||||
typedef union {
|
||||
HEADER hdr;
|
||||
u_char buf[MAXPACKET];
|
||||
} querybuf;
|
||||
|
||||
typedef union {
|
||||
long al;
|
||||
char ac;
|
||||
} align;
|
||||
|
||||
static struct netent *
|
||||
getnetanswer(answer, anslen, net_i)
|
||||
querybuf *answer;
|
||||
int anslen;
|
||||
int net_i;
|
||||
{
|
||||
|
||||
register HEADER *hp;
|
||||
register u_char *cp;
|
||||
register int n;
|
||||
u_char *eom;
|
||||
int type, class, buflen, ancount, qdcount, haveanswer, i, nchar;
|
||||
char aux1[MAXHOSTNAMELEN], aux2[MAXHOSTNAMELEN], ans[MAXHOSTNAMELEN];
|
||||
char *in, *st, *pauxt, *bp, **ap;
|
||||
char *paux1 = &aux1[0], *paux2 = &aux2[0], flag = 0;
|
||||
static struct netent net_entry;
|
||||
static char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1];
|
||||
|
||||
/*
|
||||
* find first satisfactory answer
|
||||
*
|
||||
* answer --> +------------+ ( MESSAGE )
|
||||
* | Header |
|
||||
* +------------+
|
||||
* | Question | the question for the name server
|
||||
* +------------+
|
||||
* | Answer | RRs answering the question
|
||||
* +------------+
|
||||
* | Authority | RRs pointing toward an authority
|
||||
* | Additional | RRs holding additional information
|
||||
* +------------+
|
||||
*/
|
||||
eom = answer->buf + anslen;
|
||||
hp = &answer->hdr;
|
||||
ancount = ntohs(hp->ancount); /* #/records in the answer section */
|
||||
qdcount = ntohs(hp->qdcount); /* #/entries in the question section */
|
||||
bp = netbuf;
|
||||
buflen = sizeof(netbuf);
|
||||
cp = answer->buf + HFIXEDSZ;
|
||||
if (!qdcount) {
|
||||
if (hp->aa)
|
||||
h_errno = HOST_NOT_FOUND;
|
||||
else
|
||||
h_errno = TRY_AGAIN;
|
||||
return (NULL);
|
||||
}
|
||||
while (qdcount-- > 0)
|
||||
cp += __dn_skipname(cp, eom) + QFIXEDSZ;
|
||||
ap = net_aliases;
|
||||
*ap = NULL;
|
||||
net_entry.n_aliases = net_aliases;
|
||||
haveanswer = 0;
|
||||
while (--ancount >= 0 && cp < eom) {
|
||||
n = dn_expand(answer->buf, eom, cp, bp, buflen);
|
||||
#ifdef USE_RESOLV_NAME_OK
|
||||
if ((n < 0) || !res_dnok(bp))
|
||||
#else
|
||||
if ((n < 0) || !_hokchar(bp))
|
||||
#endif
|
||||
break;
|
||||
cp += n;
|
||||
ans[0] = '\0';
|
||||
strncpy(&ans[0], bp, sizeof ans);
|
||||
GETSHORT(type, cp);
|
||||
GETSHORT(class, cp);
|
||||
cp += INT32SZ; /* TTL */
|
||||
GETSHORT(n, cp);
|
||||
if (class == C_IN && type == T_PTR) {
|
||||
n = dn_expand(answer->buf, eom, cp, bp, buflen);
|
||||
#ifdef USE_RESOLV_NAME_OK
|
||||
if ((n < 0) || !res_hnok(bp)) {
|
||||
#else
|
||||
if ((n < 0) || !_hokchar(bp)) {
|
||||
#endif
|
||||
cp += n;
|
||||
return (NULL);
|
||||
}
|
||||
cp += n;
|
||||
*ap++ = bp;
|
||||
bp += strlen(bp) + 1;
|
||||
net_entry.n_addrtype =
|
||||
(class == C_IN) ? AF_INET : AF_UNSPEC;
|
||||
haveanswer++;
|
||||
}
|
||||
}
|
||||
if (haveanswer) {
|
||||
*ap = NULL;
|
||||
switch (net_i) {
|
||||
case BYADDR:
|
||||
net_entry.n_name = *net_entry.n_aliases;
|
||||
net_entry.n_net = 0L;
|
||||
break;
|
||||
case BYNAME:
|
||||
in = *net_entry.n_aliases;
|
||||
net_entry.n_name = &ans[0];
|
||||
aux2[0] = '\0';
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (st = in, nchar = 0;
|
||||
*st != '.';
|
||||
st++, nchar++)
|
||||
;
|
||||
if (nchar != 1 || *in != '0' || flag) {
|
||||
flag = 1;
|
||||
strncpy(paux1,
|
||||
(i==0) ? in : in-1,
|
||||
(i==0) ? nchar+1 : nchar+2);
|
||||
pauxt = paux2;
|
||||
paux2 = strcat(paux1, paux2);
|
||||
paux1 = pauxt;
|
||||
}
|
||||
in = ++st;
|
||||
}
|
||||
net_entry.n_net = inet_network(paux2);
|
||||
break;
|
||||
}
|
||||
net_entry.n_aliases++;
|
||||
return (&net_entry);
|
||||
}
|
||||
h_errno = TRY_AGAIN;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
struct netent *
|
||||
getnetbyaddr(net, net_type)
|
||||
register in_addr_t net;
|
||||
register int net_type;
|
||||
{
|
||||
unsigned int netbr[4];
|
||||
int nn, anslen;
|
||||
querybuf buf;
|
||||
char qbuf[MAXDNAME];
|
||||
in_addr_t net2;
|
||||
struct netent *net_entry = NULL;
|
||||
char lookups[MAXDNSLUS];
|
||||
int i;
|
||||
|
||||
if ((_res.options & RES_INIT) == 0 && res_init() == -1)
|
||||
return(_getnetbyaddr(net, net_type));
|
||||
|
||||
memcpy(lookups, _res.lookups, sizeof lookups);
|
||||
if (lookups[0] == '\0')
|
||||
strncpy(lookups, "bf", sizeof lookups);
|
||||
|
||||
for (i = 0; i < MAXDNSLUS && lookups[i]; i++) {
|
||||
switch (lookups[i]) {
|
||||
#ifdef YP
|
||||
case 'y':
|
||||
/* There is no YP support. */
|
||||
break;
|
||||
#endif /* YP */
|
||||
case 'b':
|
||||
if (net_type != AF_INET)
|
||||
break; /* DNS only supports AF_INET? */
|
||||
|
||||
for (nn = 4, net2 = net; net2; net2 >>= 8)
|
||||
netbr[--nn] = net2 & 0xff;
|
||||
switch (nn) {
|
||||
#ifndef _MWERKS_STDIO_H_
|
||||
case 3: /* Class A */
|
||||
snprintf(qbuf, sizeof(qbuf),
|
||||
"0.0.0.%u.in-addr.arpa", netbr[3]);
|
||||
break;
|
||||
case 2: /* Class B */
|
||||
snprintf(qbuf, sizeof(qbuf),
|
||||
"0.0.%u.%u.in-addr.arpa",
|
||||
netbr[3], netbr[2]);
|
||||
break;
|
||||
case 1: /* Class C */
|
||||
snprintf(qbuf, sizeof(qbuf),
|
||||
"0.%u.%u.%u.in-addr.arpa",
|
||||
netbr[3], netbr[2], netbr[1]);
|
||||
break;
|
||||
case 0: /* Class D - E */
|
||||
snprintf(qbuf, sizeof(qbuf),
|
||||
"%u.%u.%u.%u.in-addr.arpa",
|
||||
netbr[3], netbr[2], netbr[1], netbr[0]);
|
||||
break;
|
||||
#else
|
||||
case 3: /* Class A */
|
||||
sprintf(qbuf,
|
||||
"0.0.0.%u.in-addr.arpa", netbr[3]);
|
||||
break;
|
||||
case 2: /* Class B */
|
||||
sprintf(qbuf,
|
||||
"0.0.%u.%u.in-addr.arpa",
|
||||
netbr[3], netbr[2]);
|
||||
break;
|
||||
case 1: /* Class C */
|
||||
sprintf(qbuf,
|
||||
"0.%u.%u.%u.in-addr.arpa",
|
||||
netbr[3], netbr[2], netbr[1]);
|
||||
break;
|
||||
case 0: /* Class D - E */
|
||||
sprintf(qbuf,
|
||||
"%u.%u.%u.%u.in-addr.arpa",
|
||||
netbr[3], netbr[2], netbr[1], netbr[0]);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
anslen = res_query(qbuf, C_IN, T_PTR, (u_char *)&buf,
|
||||
sizeof(buf));
|
||||
if (anslen < 0) {
|
||||
#ifdef DEBUG
|
||||
if (_res.options & RES_DEBUG)
|
||||
printf("res_query failed\n");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
net_entry = getnetanswer(&buf, anslen, BYADDR);
|
||||
if (net_entry != NULL) {
|
||||
unsigned u_net = net; /* maybe net should be unsigned ? */
|
||||
|
||||
/* Strip trailing zeros */
|
||||
while ((u_net & 0xff) == 0 && u_net != 0)
|
||||
u_net >>= 8;
|
||||
net_entry->n_net = u_net;
|
||||
return (net_entry);
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
net_entry = _getnetbyaddr(net, net_type);
|
||||
if (net_entry != NULL)
|
||||
return (net_entry);
|
||||
}
|
||||
}
|
||||
|
||||
/* Nothing matched. */
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
struct netent *
|
||||
getnetbyname(net)
|
||||
register const char *net;
|
||||
{
|
||||
int anslen;
|
||||
querybuf buf;
|
||||
char qbuf[MAXDNAME];
|
||||
struct netent *net_entry = NULL;
|
||||
char lookups[MAXDNSLUS];
|
||||
int i;
|
||||
|
||||
if ((_res.options & RES_INIT) == 0 && res_init() == -1)
|
||||
return (_getnetbyname(net));
|
||||
|
||||
memcpy(lookups, _res.lookups, sizeof lookups);
|
||||
if (lookups[0] == '\0')
|
||||
strncpy(lookups, "bf", sizeof lookups);
|
||||
|
||||
for (i = 0; i < MAXDNSLUS && lookups[i]; i++) {
|
||||
switch (lookups[i]) {
|
||||
#ifdef YP
|
||||
case 'y':
|
||||
/* There is no YP support. */
|
||||
break;
|
||||
#endif /* YP */
|
||||
case 'b':
|
||||
strncpy(qbuf, net, sizeof qbuf);
|
||||
anslen = res_search(qbuf, C_IN, T_PTR, (u_char *)&buf,
|
||||
sizeof(buf));
|
||||
if (anslen < 0) {
|
||||
#ifdef DEBUG
|
||||
if (_res.options & RES_DEBUG)
|
||||
printf("res_query failed\n");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
net_entry = getnetanswer(&buf, anslen, BYNAME);
|
||||
if (net_entry != NULL)
|
||||
return (net_entry);
|
||||
break;
|
||||
case 'f':
|
||||
net_entry = _getnetbyname(net);
|
||||
if (net_entry != NULL)
|
||||
return (net_entry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Nothing matched. */
|
||||
return (NULL);
|
||||
}
|
50
src/kits/network/libnet/getproto.c
Normal file
50
src/kits/network/libnet/getproto.c
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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 "netinet/in.h"
|
||||
#include <netdb.h>
|
||||
|
||||
extern int _proto_stayopen;
|
||||
|
||||
struct protoent *getprotobynumber(int proto)
|
||||
{
|
||||
struct protoent *p;
|
||||
|
||||
setprotoent(_proto_stayopen);
|
||||
while ((p = getprotoent()))
|
||||
if (p->p_proto == proto)
|
||||
break;
|
||||
if (!_proto_stayopen)
|
||||
endprotoent();
|
||||
return (p);
|
||||
}
|
126
src/kits/network/libnet/getprotoent.c
Normal file
126
src/kits/network/libnet/getprotoent.c
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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 <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include "netinet/in.h"
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAXALIASES 35
|
||||
|
||||
static FILE *protof = NULL;
|
||||
static char line[BUFSIZ+1];
|
||||
static struct protoent proto;
|
||||
static char *proto_aliases[MAXALIASES];
|
||||
int _proto_stayopen;
|
||||
|
||||
void setprotoent(int f)
|
||||
{
|
||||
if (protof == NULL)
|
||||
protof = fopen(_PATH_PROTOCOLS, "r" );
|
||||
else
|
||||
rewind(protof);
|
||||
_proto_stayopen |= f;
|
||||
}
|
||||
|
||||
void endprotoent()
|
||||
{
|
||||
if (protof) {
|
||||
fclose(protof);
|
||||
protof = NULL;
|
||||
}
|
||||
_proto_stayopen = 0;
|
||||
}
|
||||
|
||||
struct protoent *getprotoent()
|
||||
{
|
||||
char *p, *cp, **q, *endp;
|
||||
long l;
|
||||
size_t len;
|
||||
char buf[80];
|
||||
|
||||
if (protof == NULL && (protof = fopen(_PATH_PROTOCOLS, "r" )) == NULL)
|
||||
return (NULL);
|
||||
again:
|
||||
if (fgets(buf, 80, protof) == NULL)
|
||||
return NULL;
|
||||
len = strlen(buf);
|
||||
p = buf;
|
||||
|
||||
// if ((p = fgetln(protof, &len)) == NULL)
|
||||
// return (NULL);
|
||||
if (p[len-1] == '\n')
|
||||
len--;
|
||||
if (len >= sizeof(line) || len == 0)
|
||||
goto again;
|
||||
p = memcpy(line, p, len);
|
||||
line[len] = '\0';
|
||||
if (*p == '#')
|
||||
goto again;
|
||||
if ((cp = strchr(p, '#')) != NULL)
|
||||
*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';
|
||||
l = strtol(cp, &endp, 10);
|
||||
if (endp == cp || *endp != '\0' || l < 0 || l >= INT_MAX)
|
||||
goto again;
|
||||
proto.p_proto = l;
|
||||
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);
|
||||
}
|
58
src/kits/network/libnet/getprotoname.c
Normal file
58
src/kits/network/libnet/getprotoname.c
Normal file
@ -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 "netinet/in.h"
|
||||
#include "netdb.h"
|
||||
#include <string.h>
|
||||
|
||||
extern int _proto_stayopen;
|
||||
|
||||
|
||||
struct protoent *getprotobyname(const char *name)
|
||||
{
|
||||
struct protoent *p;
|
||||
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);
|
||||
}
|
81
src/kits/network/libnet/getservbyname.c
Normal file
81
src/kits/network/libnet/getservbyname.c
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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 "netinet/in.h"
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
|
||||
extern int _serv_stayopen;
|
||||
struct servent *getservent();
|
||||
|
||||
struct servent *
|
||||
getservbyname_r(name, proto, se, buf, buflen)
|
||||
const char *name, *proto;
|
||||
struct servent *se;
|
||||
char *buf;
|
||||
int buflen;
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
struct servent *getservbyname(name, proto)
|
||||
const char *name, *proto;
|
||||
{
|
||||
static char buf[4096];
|
||||
char *bufp = (char*)&buf;
|
||||
|
||||
if (bufp == NULL)
|
||||
return (NULL);
|
||||
return getservbyname_r(name, proto, (struct servent*) bufp,
|
||||
bufp + sizeof(struct servent),
|
||||
sizeof buf - sizeof(struct servent) );
|
||||
}
|
58
src/kits/network/libnet/getservbyport.c
Normal file
58
src/kits/network/libnet/getservbyport.c
Normal file
@ -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 "netinet/in.h"
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
|
||||
extern int _serv_stayopen;
|
||||
struct servent *getservent();
|
||||
|
||||
struct servent *
|
||||
getservbyport(port, proto)
|
||||
int port;
|
||||
const char *proto;
|
||||
{
|
||||
register struct servent *p;
|
||||
|
||||
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);
|
||||
}
|
132
src/kits/network/libnet/getservent.c
Normal file
132
src/kits/network/libnet/getservent.c
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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 <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include "netinet/in.h"
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MAXALIASES 35
|
||||
|
||||
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;
|
||||
{
|
||||
if (servf == NULL)
|
||||
servf = fopen(_PATH_SERVICES, "r" );
|
||||
else
|
||||
rewind(servf);
|
||||
_serv_stayopen |= f;
|
||||
}
|
||||
|
||||
void
|
||||
endservent()
|
||||
{
|
||||
if (servf) {
|
||||
fclose(servf);
|
||||
servf = NULL;
|
||||
}
|
||||
_serv_stayopen = 0;
|
||||
}
|
||||
|
||||
struct servent *
|
||||
getservent()
|
||||
{
|
||||
char *p, *cp, **q, *endp;
|
||||
long l;
|
||||
size_t len;
|
||||
char buf[80];
|
||||
|
||||
if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL)
|
||||
return (NULL);
|
||||
again:
|
||||
if (fgets(buf, 80, servf) == NULL)
|
||||
return NULL;
|
||||
len = strlen(buf);
|
||||
p = buf;
|
||||
|
||||
// if ((p = fgetln(servf, &len)) == NULL)
|
||||
// return (NULL);
|
||||
if (p[len-1] == '\n')
|
||||
len--;
|
||||
if (len >= sizeof(line) || len == 0)
|
||||
goto again;
|
||||
p = memcpy(line, p, len);
|
||||
line[len] = '\0';
|
||||
if (*p == '#')
|
||||
goto again;
|
||||
if ((cp = strchr(p, '#')) != NULL)
|
||||
*cp = '\0';
|
||||
serv.s_name = p;
|
||||
p = strpbrk(p, " \t");
|
||||
if (p == NULL)
|
||||
goto again;
|
||||
*p++ = '\0';
|
||||
while (*p == ' ' || *p == '\t')
|
||||
p++;
|
||||
cp = strpbrk(p, ",/");
|
||||
if (cp == NULL)
|
||||
goto again;
|
||||
*cp++ = '\0';
|
||||
l = strtol(p, &endp, 10);
|
||||
if (endp == p || *endp != '\0' || l < 0 || l > USHRT_MAX)
|
||||
goto again;
|
||||
serv.s_port = htons((in_port_t)l);
|
||||
serv.s_proto = cp;
|
||||
q = serv.s_aliases = serv_aliases;
|
||||
cp = strpbrk(cp, " \t");
|
||||
if (cp != NULL)
|
||||
*cp++ = '\0';
|
||||
while (cp && *cp) {
|
||||
if (*cp == ' ' || *cp == '\t') {
|
||||
cp++;
|
||||
continue;
|
||||
}
|
||||
if (q < &serv_aliases[MAXALIASES - 1])
|
||||
*q++ = cp;
|
||||
cp = strpbrk(cp, " \t");
|
||||
if (cp != NULL)
|
||||
*cp++ = '\0';
|
||||
}
|
||||
*q = NULL;
|
||||
return (&serv);
|
||||
}
|
176
src/kits/network/libnet/inet_addr.c
Normal file
176
src/kits/network/libnet/inet_addr.c
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* ++Copyright++ 1983, 1990, 1993
|
||||
* -
|
||||
* 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.
|
||||
* -
|
||||
* 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 <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/*
|
||||
* Ascii internet address interpretation routine.
|
||||
* The value returned is in network order.
|
||||
*/
|
||||
in_addr_t
|
||||
inet_addr(cp)
|
||||
register 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(cp, addr)
|
||||
register const char *cp;
|
||||
struct in_addr *addr;
|
||||
{
|
||||
register in_addr_t val;
|
||||
register int base, n;
|
||||
register char c;
|
||||
u_int parts[4];
|
||||
register u_int *pp = parts;
|
||||
|
||||
c = *cp;
|
||||
for (;;) {
|
||||
/*
|
||||
* Collect number up to ``.''.
|
||||
* Values are specified as for C:
|
||||
* 0x=hex, 0=octal, isdigit=decimal.
|
||||
*/
|
||||
if (!isdigit(c))
|
||||
return (0);
|
||||
val = 0; base = 10;
|
||||
if (c == '0') {
|
||||
c = *++cp;
|
||||
if (c == 'x' || c == 'X')
|
||||
base = 16, c = *++cp;
|
||||
else
|
||||
base = 8;
|
||||
}
|
||||
for (;;) {
|
||||
if (isascii(c) && isdigit(c)) {
|
||||
val = (val * base) + (c - '0');
|
||||
c = *++cp;
|
||||
} else if (base == 16 && isascii(c) && isxdigit(c)) {
|
||||
val = (val << 4) |
|
||||
(c + 10 - (islower(c) ? 'a' : 'A'));
|
||||
c = *++cp;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
if (c == '.') {
|
||||
/*
|
||||
* 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)
|
||||
return (0);
|
||||
*pp++ = val;
|
||||
c = *++cp;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Check for trailing characters.
|
||||
*/
|
||||
if (c != '\0' && (!isascii(c) || !isspace(c)))
|
||||
return (0);
|
||||
/*
|
||||
* Concoct the address according to
|
||||
* the number of parts specified.
|
||||
*/
|
||||
n = pp - parts + 1;
|
||||
switch (n) {
|
||||
|
||||
case 0:
|
||||
return (0); /* initial nondigit */
|
||||
|
||||
case 1: /* a -- 32 bits */
|
||||
break;
|
||||
|
||||
case 2: /* a.b -- 8.24 bits */
|
||||
if ((val > 0xffffff) || (parts[0] > 0xff))
|
||||
return (0);
|
||||
val |= parts[0] << 24;
|
||||
break;
|
||||
|
||||
case 3: /* a.b.c -- 8.8.16 bits */
|
||||
if ((val > 0xffff) || (parts[0] > 0xff) || (parts[1] > 0xff))
|
||||
return (0);
|
||||
val |= (parts[0] << 24) | (parts[1] << 16);
|
||||
break;
|
||||
|
||||
case 4: /* a.b.c.d -- 8.8.8.8 bits */
|
||||
if ((val > 0xff) || (parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff))
|
||||
return (0);
|
||||
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
|
||||
break;
|
||||
}
|
||||
if (addr)
|
||||
addr->s_addr = htonl(val);
|
||||
return (1);
|
||||
}
|
55
src/kits/network/libnet/inet_lnaof.c
Normal file
55
src/kits/network/libnet/inet_lnaof.c
Normal file
@ -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 <sys/param.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
/*
|
||||
* Return the local network address portion of an
|
||||
* internet address; handles class a/b/c network
|
||||
* number formats.
|
||||
*/
|
||||
in_addr_t
|
||||
inet_lnaof(in)
|
||||
struct in_addr in;
|
||||
{
|
||||
register in_addr_t 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);
|
||||
}
|
73
src/kits/network/libnet/inet_neta.c
Normal file
73
src/kits/network/libnet/inet_neta.c
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 1996 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
||||
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
||||
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* char *
|
||||
* inet_neta(src, dst, size)
|
||||
* format an in_addr_t network number into presentation format.
|
||||
* return:
|
||||
* pointer to dst, or NULL if an error occurred (check errno).
|
||||
* note:
|
||||
* format of ``src'' is as for inet_network().
|
||||
* author:
|
||||
* Paul Vixie (ISC), July 1996
|
||||
*/
|
||||
char *
|
||||
inet_neta(src, dst, size)
|
||||
in_addr_t src;
|
||||
char *dst;
|
||||
size_t size;
|
||||
{
|
||||
char *odst = dst;
|
||||
char *tp;
|
||||
|
||||
while (src & 0xffffffff) {
|
||||
u_char b = (src & 0xff000000) >> 24;
|
||||
|
||||
src <<= 8;
|
||||
if (b) {
|
||||
if (size < sizeof "255.")
|
||||
goto emsgsize;
|
||||
tp = dst;
|
||||
dst += sprintf(dst, "%u", b);
|
||||
if (src != 0L) {
|
||||
*dst++ = '.';
|
||||
*dst = '\0';
|
||||
}
|
||||
size -= (size_t)(dst - tp);
|
||||
}
|
||||
}
|
||||
if (dst == odst) {
|
||||
if (size < sizeof "0.0.0.0")
|
||||
goto emsgsize;
|
||||
strcpy(dst, "0.0.0.0");
|
||||
}
|
||||
return (odst);
|
||||
|
||||
emsgsize:
|
||||
errno = EMSGSIZE;
|
||||
return (NULL);
|
||||
}
|
54
src/kits/network/libnet/inet_netof.c
Normal file
54
src/kits/network/libnet/inet_netof.c
Normal file
@ -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.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
/*
|
||||
* Return the network number from an internet
|
||||
* address; handles class a/b/c network #'s.
|
||||
*/
|
||||
in_addr_t
|
||||
inet_netof(in)
|
||||
struct in_addr in;
|
||||
{
|
||||
register in_addr_t 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);
|
||||
}
|
88
src/kits/network/libnet/inet_network.c
Normal file
88
src/kits/network/libnet/inet_network.c
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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 <sys/types.h>
|
||||
#include "netinet/in.h"
|
||||
#include "arpa/inet.h"
|
||||
#include <ctype.h>
|
||||
|
||||
/*
|
||||
* Internet network address interpretation routine.
|
||||
* The library routines call this routine to interpret
|
||||
* network numbers.
|
||||
*/
|
||||
in_addr_t
|
||||
inet_network(cp)
|
||||
register const char *cp;
|
||||
{
|
||||
register in_addr_t val, base, n;
|
||||
register char c;
|
||||
in_addr_t parts[4], *pp = parts;
|
||||
register int i;
|
||||
|
||||
again:
|
||||
val = 0; base = 10;
|
||||
if (*cp == '0')
|
||||
base = 8, cp++;
|
||||
if (*cp == 'x' || *cp == 'X')
|
||||
base = 16, cp++;
|
||||
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 + 3)
|
||||
return (INADDR_NONE);
|
||||
*pp++ = val, cp++;
|
||||
goto again;
|
||||
}
|
||||
if (*cp && !isspace(*cp))
|
||||
return (INADDR_NONE);
|
||||
*pp++ = val;
|
||||
n = pp - parts;
|
||||
for (val = 0, i = 0; i < 4; i++) {
|
||||
val <<= 8;
|
||||
if (i < n)
|
||||
val |= parts[i] & 0xff;
|
||||
}
|
||||
return (val);
|
||||
}
|
60
src/kits/network/libnet/inet_ntoa.c
Normal file
60
src/kits/network/libnet/inet_ntoa.c
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdio.h>
|
||||
|
||||
char *
|
||||
inet_ntoa(in)
|
||||
struct in_addr in;
|
||||
{
|
||||
static char b[18];
|
||||
register char *p;
|
||||
|
||||
p = (char *)∈
|
||||
#define UC(b) (((int)b)&0xff)
|
||||
#ifdef _MWERKS_STDIO_H_
|
||||
(void)sprintf(b,
|
||||
"%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
|
||||
#else
|
||||
(void)snprintf(b, sizeof(b),
|
||||
"%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
|
||||
#endif
|
||||
return (b);
|
||||
}
|
184
src/kits/network/libnet/inet_ntop.c
Normal file
184
src/kits/network/libnet/inet_ntop.c
Normal file
@ -0,0 +1,184 @@
|
||||
/* Copyright (c) 1996 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
||||
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
||||
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include "sys/socket.h"
|
||||
#include "netinet/in.h"
|
||||
#include "arpa/inet.h"
|
||||
#include "arpa/nameser.h"
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* WARNING: Don't even consider trying to compile this on a system where
|
||||
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
|
||||
*/
|
||||
|
||||
static const char *inet_ntop4 (const u_char *src, char *dst, size_t size);
|
||||
static const char *inet_ntop6 (const u_char *src, char *dst, size_t size);
|
||||
|
||||
/* char *
|
||||
* inet_ntop(af, src, dst, size)
|
||||
* convert a network format address to presentation format.
|
||||
* return:
|
||||
* pointer to presentation format address (`dst'), or NULL (see errno).
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
const char *
|
||||
inet_ntop(af, src, dst, size)
|
||||
int af;
|
||||
const void *src;
|
||||
char *dst;
|
||||
size_t size;
|
||||
{
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
return (inet_ntop4(src, dst, size));
|
||||
case AF_INET6:
|
||||
return (inet_ntop6(src, dst, size));
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
return (NULL);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* const char *
|
||||
* inet_ntop4(src, dst, size)
|
||||
* format an IPv4 address, more or less like inet_ntoa()
|
||||
* return:
|
||||
* `dst' (as a const)
|
||||
* notes:
|
||||
* (1) uses no statics
|
||||
* (2) takes a u_char* not an in_addr as input
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
static const char *
|
||||
inet_ntop4(src, dst, size)
|
||||
const u_char *src;
|
||||
char *dst;
|
||||
size_t size;
|
||||
{
|
||||
static const char fmt[] = "%u.%u.%u.%u";
|
||||
char tmp[sizeof "255.255.255.255"];
|
||||
|
||||
if (sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) > size) {
|
||||
errno = ENOSPC;
|
||||
return (NULL);
|
||||
}
|
||||
strcpy(dst, tmp);
|
||||
return (dst);
|
||||
}
|
||||
|
||||
/* const char *
|
||||
* inet_ntop6(src, dst, size)
|
||||
* convert IPv6 binary address into presentation (printable) format
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
static const char *
|
||||
inet_ntop6(src, dst, size)
|
||||
const u_char *src;
|
||||
char *dst;
|
||||
size_t size;
|
||||
{
|
||||
/*
|
||||
* Note that int32_t and int16_t need only be "at least" large enough
|
||||
* to contain a value of the specified size. On some systems, like
|
||||
* Crays, there is no such thing as an integer variable with 16 bits.
|
||||
* Keep this in mind if you think this function should have been coded
|
||||
* to use pointer overlays. All the world's not a VAX.
|
||||
*/
|
||||
char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
|
||||
struct { int base, len; } best, cur;
|
||||
u_int words[IN6ADDRSZ / INT16SZ];
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Preprocess:
|
||||
* Copy the input (bytewise) array into a wordwise array.
|
||||
* Find the longest run of 0x00's in src[] for :: shorthanding.
|
||||
*/
|
||||
memset(words, '\0', sizeof words);
|
||||
for (i = 0; i < IN6ADDRSZ; i++)
|
||||
words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
|
||||
best.base = -1;
|
||||
cur.base = -1;
|
||||
for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
|
||||
if (words[i] == 0) {
|
||||
if (cur.base == -1)
|
||||
cur.base = i, cur.len = 1;
|
||||
else
|
||||
cur.len++;
|
||||
} else {
|
||||
if (cur.base != -1) {
|
||||
if (best.base == -1 || cur.len > best.len)
|
||||
best = cur;
|
||||
cur.base = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cur.base != -1) {
|
||||
if (best.base == -1 || cur.len > best.len)
|
||||
best = cur;
|
||||
}
|
||||
if (best.base != -1 && best.len < 2)
|
||||
best.base = -1;
|
||||
|
||||
/*
|
||||
* Format the result.
|
||||
*/
|
||||
tp = tmp;
|
||||
for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
|
||||
/* Are we inside the best run of 0x00's? */
|
||||
if (best.base != -1 && i >= best.base &&
|
||||
i < (best.base + best.len)) {
|
||||
if (i == best.base)
|
||||
*tp++ = ':';
|
||||
continue;
|
||||
}
|
||||
/* Are we following an initial run of 0x00s or any real hex? */
|
||||
if (i != 0)
|
||||
*tp++ = ':';
|
||||
/* Is this address an encapsulated IPv4? */
|
||||
if (i == 6 && best.base == 0 &&
|
||||
(best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
|
||||
if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
|
||||
return (NULL);
|
||||
tp += strlen(tp);
|
||||
break;
|
||||
}
|
||||
tp += sprintf(tp, "%x", words[i]);
|
||||
}
|
||||
/* Was it a trailing run of 0x00's? */
|
||||
if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
|
||||
*tp++ = ':';
|
||||
*tp++ = '\0';
|
||||
|
||||
/*
|
||||
* Check for overflow, copy, and we're done.
|
||||
*/
|
||||
if ((size_t)(tp - tmp) > size) {
|
||||
errno = ENOSPC;
|
||||
return (NULL);
|
||||
}
|
||||
strcpy(dst, tmp);
|
||||
return (dst);
|
||||
}
|
212
src/kits/network/libnet/inet_pton.c
Normal file
212
src/kits/network/libnet/inet_pton.c
Normal file
@ -0,0 +1,212 @@
|
||||
/* Copyright (c) 1996 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
||||
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
||||
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include "sys/socket.h"
|
||||
#include "netinet/in.h"
|
||||
#include "arpa/inet.h"
|
||||
#include "arpa/nameser.h"
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* WARNING: Don't even consider trying to compile this on a system where
|
||||
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
|
||||
*/
|
||||
|
||||
static int inet_pton4 (const char *src, u_char *dst);
|
||||
static int inet_pton6 (const char *src, u_char *dst);
|
||||
|
||||
/* int
|
||||
* inet_pton(af, src, dst)
|
||||
* convert from presentation format (which usually means ASCII printable)
|
||||
* to network format (which is usually some kind of binary format).
|
||||
* return:
|
||||
* 1 if the address was valid for the specified address family
|
||||
* 0 if the address wasn't valid (`dst' is untouched in this case)
|
||||
* -1 if some other error occurred (`dst' is untouched in this case, too)
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
int
|
||||
inet_pton(af, src, dst)
|
||||
int af;
|
||||
const char *src;
|
||||
void *dst;
|
||||
{
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
return (inet_pton4(src, dst));
|
||||
case AF_INET6:
|
||||
return (inet_pton6(src, dst));
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
return (-1);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* int
|
||||
* inet_pton4(src, dst)
|
||||
* like inet_aton() but without all the hexadecimal and shorthand.
|
||||
* return:
|
||||
* 1 if `src' is a valid dotted quad, else 0.
|
||||
* notice:
|
||||
* does not touch `dst' unless it's returning 1.
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
static int
|
||||
inet_pton4(src, dst)
|
||||
const char *src;
|
||||
u_char *dst;
|
||||
{
|
||||
static const char digits[] = "0123456789";
|
||||
int saw_digit, octets, ch;
|
||||
u_char tmp[INADDRSZ], *tp;
|
||||
|
||||
saw_digit = 0;
|
||||
octets = 0;
|
||||
*(tp = tmp) = 0;
|
||||
while ((ch = *src++) != '\0') {
|
||||
const char *pch;
|
||||
|
||||
if ((pch = strchr(digits, ch)) != NULL) {
|
||||
u_int new = *tp * 10 + (pch - digits);
|
||||
|
||||
if (new > 255)
|
||||
return (0);
|
||||
if (! saw_digit) {
|
||||
if (++octets > 4)
|
||||
return (0);
|
||||
saw_digit = 1;
|
||||
}
|
||||
*tp = new;
|
||||
} else if (ch == '.' && saw_digit) {
|
||||
if (octets == 4)
|
||||
return (0);
|
||||
*++tp = 0;
|
||||
saw_digit = 0;
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
if (octets < 4)
|
||||
return (0);
|
||||
|
||||
memcpy(dst, tmp, INADDRSZ);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* int
|
||||
* inet_pton6(src, dst)
|
||||
* convert presentation level address to network order binary form.
|
||||
* return:
|
||||
* 1 if `src' is a valid [RFC1884 2.2] address, else 0.
|
||||
* notice:
|
||||
* (1) does not touch `dst' unless it's returning 1.
|
||||
* (2) :: in a full address is silently ignored.
|
||||
* credit:
|
||||
* inspired by Mark Andrews.
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
static int
|
||||
inet_pton6(src, dst)
|
||||
const char *src;
|
||||
u_char *dst;
|
||||
{
|
||||
static const char xdigits_l[] = "0123456789abcdef",
|
||||
xdigits_u[] = "0123456789ABCDEF";
|
||||
u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
|
||||
const char *xdigits, *curtok;
|
||||
int ch, saw_xdigit;
|
||||
u_int val;
|
||||
|
||||
memset((tp = tmp), '\0', IN6ADDRSZ);
|
||||
endp = tp + IN6ADDRSZ;
|
||||
colonp = NULL;
|
||||
/* Leading :: requires some special handling. */
|
||||
if (*src == ':')
|
||||
if (*++src != ':')
|
||||
return (0);
|
||||
curtok = src;
|
||||
saw_xdigit = 0;
|
||||
val = 0;
|
||||
while ((ch = *src++) != '\0') {
|
||||
const char *pch;
|
||||
|
||||
if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
|
||||
pch = strchr((xdigits = xdigits_u), ch);
|
||||
if (pch != NULL) {
|
||||
val <<= 4;
|
||||
val |= (pch - xdigits);
|
||||
if (val > 0xffff)
|
||||
return (0);
|
||||
saw_xdigit = 1;
|
||||
continue;
|
||||
}
|
||||
if (ch == ':') {
|
||||
curtok = src;
|
||||
if (!saw_xdigit) {
|
||||
if (colonp)
|
||||
return (0);
|
||||
colonp = tp;
|
||||
continue;
|
||||
} else if (*src == '\0') {
|
||||
return (0);
|
||||
}
|
||||
if (tp + INT16SZ > endp)
|
||||
return (0);
|
||||
*tp++ = (u_char) (val >> 8) & 0xff;
|
||||
*tp++ = (u_char) val & 0xff;
|
||||
saw_xdigit = 0;
|
||||
val = 0;
|
||||
continue;
|
||||
}
|
||||
if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
|
||||
inet_pton4(curtok, tp) > 0) {
|
||||
tp += INADDRSZ;
|
||||
saw_xdigit = 0;
|
||||
break; /* '\0' was seen by inet_pton4(). */
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
if (saw_xdigit) {
|
||||
if (tp + INT16SZ > endp)
|
||||
return (0);
|
||||
*tp++ = (u_char) (val >> 8) & 0xff;
|
||||
*tp++ = (u_char) val & 0xff;
|
||||
}
|
||||
if (colonp != NULL) {
|
||||
/*
|
||||
* Since some memmove()'s erroneously fail to handle
|
||||
* overlapping regions, we'll do the shift by hand.
|
||||
*/
|
||||
const int n = tp - colonp;
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= n; i++) {
|
||||
endp[- i] = colonp[n - i];
|
||||
colonp[n - i] = 0;
|
||||
}
|
||||
tp = endp;
|
||||
}
|
||||
if (tp != endp)
|
||||
return (0);
|
||||
memcpy(dst, tmp, IN6ADDRSZ);
|
||||
return (1);
|
||||
}
|
155
src/kits/network/libnet/linkaddr.c
Normal file
155
src/kits/network/libnet/linkaddr.c
Normal file
@ -0,0 +1,155 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <kernel/OS.h>
|
||||
#include "sys/socket.h"
|
||||
#include "net/if_dl.h"
|
||||
#include <string.h>
|
||||
|
||||
/* States*/
|
||||
#define NAMING 0
|
||||
#define GOTONE 1
|
||||
#define GOTTWO 2
|
||||
#define RESET 3
|
||||
/* Inputs */
|
||||
#define DIGIT (4*0)
|
||||
#define END (4*1)
|
||||
#define DELIM (4*2)
|
||||
#define LETTER (4*3)
|
||||
|
||||
void
|
||||
link_addr(addr, sdl)
|
||||
register const char *addr;
|
||||
register struct sockaddr_dl *sdl;
|
||||
{
|
||||
register char *cp = sdl->sdl_data;
|
||||
char *cplim = sdl->sdl_len + (char *)sdl;
|
||||
register int byte = 0, state = NAMING, newv = 0;
|
||||
|
||||
memset((char *)&sdl->sdl_family, 0, sdl->sdl_len - 1);
|
||||
sdl->sdl_family = AF_LINK;
|
||||
do {
|
||||
state &= ~LETTER;
|
||||
if ((*addr >= '0') && (*addr <= '9')) {
|
||||
newv = *addr - '0';
|
||||
} else if ((*addr >= 'a') && (*addr <= 'f')) {
|
||||
newv = *addr - 'a' + 10;
|
||||
} else if ((*addr >= 'A') && (*addr <= 'F')) {
|
||||
newv = *addr - 'A' + 10;
|
||||
} else if (*addr == 0) {
|
||||
state |= END;
|
||||
} else if (state == NAMING &&
|
||||
(((*addr >= 'A') && (*addr <= 'Z')) ||
|
||||
((*addr >= 'a') && (*addr <= 'z'))))
|
||||
state |= LETTER;
|
||||
else
|
||||
state |= DELIM;
|
||||
addr++;
|
||||
switch (state /* | INPUT */) {
|
||||
case NAMING | DIGIT:
|
||||
case NAMING | LETTER:
|
||||
*cp++ = addr[-1];
|
||||
continue;
|
||||
case NAMING | DELIM:
|
||||
state = RESET;
|
||||
sdl->sdl_nlen = cp - sdl->sdl_data;
|
||||
continue;
|
||||
case GOTTWO | DIGIT:
|
||||
*cp++ = byte;
|
||||
/* FALLTHROUGH */
|
||||
case RESET | DIGIT:
|
||||
state = GOTONE;
|
||||
byte = newv;
|
||||
continue;
|
||||
case GOTONE | DIGIT:
|
||||
state = GOTTWO;
|
||||
byte = newv + (byte << 4);
|
||||
continue;
|
||||
default: /* | DELIM */
|
||||
state = RESET;
|
||||
*cp++ = byte;
|
||||
byte = 0;
|
||||
continue;
|
||||
case GOTONE | END:
|
||||
case GOTTWO | END:
|
||||
*cp++ = byte;
|
||||
/* FALLTHROUGH */
|
||||
case RESET | END:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
} while (cp < cplim);
|
||||
sdl->sdl_alen = cp - LLADDR(sdl);
|
||||
newv = cp - (char *)sdl;
|
||||
if (newv > sizeof(*sdl))
|
||||
sdl->sdl_len = newv;
|
||||
return;
|
||||
}
|
||||
|
||||
static char hexlist[] = "0123456789abcdef";
|
||||
|
||||
char *
|
||||
link_ntoa(sdl)
|
||||
register const struct sockaddr_dl *sdl;
|
||||
{
|
||||
static char obuf[64];
|
||||
register char *out = obuf;
|
||||
register int i;
|
||||
register u_char *in = (u_char *)LLADDR(sdl);
|
||||
u_char *inlim = in + sdl->sdl_alen;
|
||||
int firsttime = 1;
|
||||
|
||||
if (sdl->sdl_nlen) {
|
||||
memcpy(obuf, sdl->sdl_data, sdl->sdl_nlen);
|
||||
out += sdl->sdl_nlen;
|
||||
if (sdl->sdl_alen)
|
||||
*out++ = ':';
|
||||
}
|
||||
while (in < inlim) {
|
||||
if (firsttime)
|
||||
firsttime = 0;
|
||||
else
|
||||
*out++ = '.';
|
||||
i = *in++;
|
||||
if (i > 0xf) {
|
||||
out[1] = hexlist[i & 0xf];
|
||||
i >>= 4;
|
||||
out[0] = hexlist[i];
|
||||
out += 2;
|
||||
} else
|
||||
*out++ = hexlist[i];
|
||||
}
|
||||
*out = 0;
|
||||
return (obuf);
|
||||
}
|
61
src/kits/network/libnet/poll.c
Normal file
61
src/kits/network/libnet/poll.c
Normal file
@ -0,0 +1,61 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include "sys/select.h"
|
||||
|
||||
#include "poll.h"
|
||||
|
||||
// -------------------------------
|
||||
int poll(struct pollfd * p, int nb, int timeout)
|
||||
{
|
||||
fd_set read_set;
|
||||
fd_set write_set;
|
||||
fd_set exception_set;
|
||||
int i;
|
||||
int n;
|
||||
int rc;
|
||||
|
||||
FD_ZERO(&read_set);
|
||||
FD_ZERO(&write_set);
|
||||
FD_ZERO(&exception_set);
|
||||
|
||||
n = -1;
|
||||
for(i = 0; i < nb; i++) {
|
||||
if (p[i].fd < 0)
|
||||
continue;
|
||||
|
||||
if (p[i].events & POLLIN) FD_SET(p[i].fd, &read_set);
|
||||
if (p[i].events & POLLOUT) FD_SET(p[i].fd, &write_set);
|
||||
if (p[i].events & POLLERR) FD_SET(p[i].fd, &exception_set);
|
||||
|
||||
if (p[i].fd > n)
|
||||
n = p[i].fd;
|
||||
};
|
||||
|
||||
if (n == -1)
|
||||
// Hey!? Nothing to poll, in fact!!!
|
||||
return 0;
|
||||
|
||||
if (timeout < 0)
|
||||
rc = select(n+1, &read_set, &write_set, &exception_set, NULL);
|
||||
else {
|
||||
struct timeval tv;
|
||||
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = 1000 * (timeout % 1000);
|
||||
rc = select(n, &read_set, &write_set, &exception_set, &tv);
|
||||
};
|
||||
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
for(i = 0; i < n; i++) {
|
||||
p[i].revents = 0;
|
||||
|
||||
if (FD_ISSET(p[i].fd, &read_set)) p[i].revents |= POLLIN;
|
||||
if (FD_ISSET(p[i].fd, &write_set)) p[i].revents |= POLLOUT;
|
||||
if (FD_ISSET(p[i].fd, &exception_set)) p[i].revents |= POLLERR;
|
||||
};
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
500
src/kits/network/libnet/res_comp.c
Normal file
500
src/kits/network/libnet/res_comp.c
Normal file
@ -0,0 +1,500 @@
|
||||
/*
|
||||
* ++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 <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include "netinet/in.h"
|
||||
#include "arpa/nameser.h"
|
||||
#include "netdb.h" /* for MAXHOSTNAMELEN */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "resolv.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static int dn_find (u_char *exp_dn, u_char *msg,
|
||||
u_char **dnptrs, u_char **lastdnptr);
|
||||
|
||||
/*
|
||||
* Expand compressed domain name 'comp_dn' to full domain name.
|
||||
* 'msg' is a pointer to the begining of the message,
|
||||
* 'eomorig' points to the first location after the message,
|
||||
* 'exp_dn' is a pointer to a buffer of size 'length' for the result.
|
||||
* Return size of compressed name or -1 if there was an error.
|
||||
*/
|
||||
int
|
||||
dn_expand(msg, eomorig, comp_dn, exp_dn, length)
|
||||
const u_char *msg, *eomorig, *comp_dn;
|
||||
char *exp_dn;
|
||||
int length;
|
||||
{
|
||||
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;
|
||||
if (length > MAXHOSTNAMELEN-1)
|
||||
length = MAXHOSTNAMELEN-1;
|
||||
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';
|
||||
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.
|
||||
*/
|
||||
int
|
||||
dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
|
||||
const char *exp_dn;
|
||||
u_char *comp_dn, **dnptrs, **lastdnptr;
|
||||
int length;
|
||||
{
|
||||
register u_char *cp, *dn;
|
||||
register int c, l;
|
||||
u_char **cpp, **lpp, *sp, *eob;
|
||||
u_char *msg;
|
||||
|
||||
dn = (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.
|
||||
*/
|
||||
int
|
||||
__dn_skipname(comp_dn, eom)
|
||||
const u_char *comp_dn, *eom;
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static int
|
||||
mklower(ch)
|
||||
register int ch;
|
||||
{
|
||||
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.
|
||||
*/
|
||||
static int
|
||||
dn_find(exp_dn, msg, dnptrs, lastdnptr)
|
||||
u_char *exp_dn, *msg;
|
||||
u_char **dnptrs, **lastdnptr;
|
||||
{
|
||||
register u_char *dn, *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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that a domain name uses an acceptable character set.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Note the conspicuous absence of ctype macros in these definitions. On
|
||||
* non-ASCII hosts, we can't depend on string literals or ctype macros to
|
||||
* tell us anything about network-format data. The rest of the BIND system
|
||||
* is not careful about this, but for some reason, we're doing it right here.
|
||||
*/
|
||||
#define PERIOD 0x2e
|
||||
#define hyphenchar(c) ((c) == 0x2d)
|
||||
#define bslashchar(c) ((c) == 0x5c)
|
||||
#define periodchar(c) ((c) == PERIOD)
|
||||
#define asterchar(c) ((c) == 0x2a)
|
||||
#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
|
||||
|| ((c) >= 0x61 && (c) <= 0x7a))
|
||||
#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
|
||||
|
||||
#define borderchar(c) (alphachar(c) || digitchar(c))
|
||||
#define middlechar(c) (borderchar(c) || hyphenchar(c))
|
||||
#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
|
||||
|
||||
int
|
||||
res_hnok(dn)
|
||||
const char *dn;
|
||||
{
|
||||
int pch = PERIOD, ch = *dn++;
|
||||
|
||||
while (ch != '\0') {
|
||||
int nch = *dn++;
|
||||
|
||||
if (periodchar(ch)) {
|
||||
;
|
||||
} else if (periodchar(pch)) {
|
||||
if (!borderchar(ch))
|
||||
return (0);
|
||||
} else if (periodchar(nch) || nch == '\0') {
|
||||
if (!borderchar(ch))
|
||||
return (0);
|
||||
} else {
|
||||
if (!middlechar(ch))
|
||||
return (0);
|
||||
}
|
||||
pch = ch, ch = nch;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* hostname-like (A, MX, WKS) owners can have "*" as their first label
|
||||
* but must otherwise be as a host name.
|
||||
*/
|
||||
int
|
||||
res_ownok(dn)
|
||||
const char *dn;
|
||||
{
|
||||
if (asterchar(dn[0])) {
|
||||
if (periodchar(dn[1]))
|
||||
return (res_hnok(dn+2));
|
||||
if (dn[1] == '\0')
|
||||
return (1);
|
||||
}
|
||||
return (res_hnok(dn));
|
||||
}
|
||||
|
||||
/*
|
||||
* SOA RNAMEs and RP RNAMEs can have any printable character in their first
|
||||
* label, but the rest of the name has to look like a host name.
|
||||
*/
|
||||
int
|
||||
res_mailok(dn)
|
||||
const char *dn;
|
||||
{
|
||||
int ch, escaped = 0;
|
||||
|
||||
/* "." is a valid missing representation */
|
||||
if (*dn == '\0')
|
||||
return(1);
|
||||
|
||||
/* otherwise <label>.<hostname> */
|
||||
while ((ch = *dn++) != '\0') {
|
||||
if (!domainchar(ch))
|
||||
return (0);
|
||||
if (!escaped && periodchar(ch))
|
||||
break;
|
||||
if (escaped)
|
||||
escaped = 0;
|
||||
else if (bslashchar(ch))
|
||||
escaped = 1;
|
||||
}
|
||||
if (periodchar(ch))
|
||||
return (res_hnok(dn));
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is quite liberal, since RFC 1034's character sets are only
|
||||
* recommendations.
|
||||
*/
|
||||
int
|
||||
res_dnok(dn)
|
||||
const char *dn;
|
||||
{
|
||||
int ch;
|
||||
|
||||
while ((ch = *dn++) != '\0')
|
||||
if (!domainchar(ch))
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Routines to insert/extract short/long's.
|
||||
*/
|
||||
|
||||
|
||||
uint16 _getshort(const u_char *msgp)
|
||||
{
|
||||
uint16 u;
|
||||
|
||||
GETSHORT(u, msgp);
|
||||
return (u);
|
||||
}
|
||||
|
||||
#ifdef NeXT
|
||||
/*
|
||||
* nExt machines have some funky library conventions, which we must maintain.
|
||||
*/
|
||||
uint16
|
||||
res_getshort(msgp)
|
||||
register const u_char *msgp;
|
||||
{
|
||||
return (_getshort(msgp));
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32
|
||||
_getlong(msgp)
|
||||
register const u_char *msgp;
|
||||
{
|
||||
register uint32 u;
|
||||
|
||||
GETLONG(u, msgp);
|
||||
return (u);
|
||||
}
|
||||
|
||||
void
|
||||
#if defined(__STDC__) || defined(__cplusplus)
|
||||
__putshort(register uint16 s, register u_char *msgp) /* must match proto */
|
||||
#else
|
||||
__putshort(s, msgp)
|
||||
register uint16 s;
|
||||
register u_char *msgp;
|
||||
#endif
|
||||
{
|
||||
PUTSHORT(s, msgp);
|
||||
}
|
||||
|
||||
void
|
||||
__putlong(l, msgp)
|
||||
register uint32 l;
|
||||
register u_char *msgp;
|
||||
{
|
||||
PUTLONG(l, msgp);
|
||||
}
|
107
src/kits/network/libnet/res_data.c
Normal file
107
src/kits/network/libnet/res_data.c
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* ++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 <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <resolv.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
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",
|
||||
};
|
1507
src/kits/network/libnet/res_debug.c
Normal file
1507
src/kits/network/libnet/res_debug.c
Normal file
File diff suppressed because it is too large
Load Diff
621
src/kits/network/libnet/res_init.c
Normal file
621
src/kits/network/libnet/res_init.c
Normal file
@ -0,0 +1,621 @@
|
||||
/*
|
||||
* ++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 <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include "sys/socket.h"
|
||||
#include <sys/time.h>
|
||||
#include "netinet/in.h"
|
||||
#include "arpa/inet.h"
|
||||
#include "arpa/nameser.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include "resolv.h"
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "netdb.h"
|
||||
|
||||
/*-------------------------------------- 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 separated by a slash (/) or ampersand (&) character.
|
||||
* - Internal resolver variables can be set from the value of the "options"
|
||||
* property.
|
||||
*/
|
||||
|
||||
|
||||
static void res_setoptions (char *, char *);
|
||||
|
||||
#ifdef RESOLVSORT
|
||||
static const char sort_mask[] = "/&";
|
||||
#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
|
||||
static uint32 net_mask (struct in_addr);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Resolver state default settings.
|
||||
*/
|
||||
|
||||
struct __res_state _res
|
||||
# if defined(__BIND_RES_TEXT)
|
||||
= { RES_TIMEOUT, } /* Motorola, et al. */
|
||||
# endif
|
||||
;
|
||||
#ifdef INET6
|
||||
struct __res_state_ext _res_ext;
|
||||
#endif /* INET6 */
|
||||
|
||||
/*
|
||||
* 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;
|
||||
size_t len;
|
||||
char lbuf[80];
|
||||
#ifdef RESOLVSORT
|
||||
int nsort = 0;
|
||||
char *net;
|
||||
#endif
|
||||
#ifndef RFC1535
|
||||
int dots;
|
||||
#endif
|
||||
/*
|
||||
* These three fields used to be statically initialized. This made
|
||||
* it hard to use this code in a shared library. It is necessary,
|
||||
* now that we're doing dynamic initialization here, that we preserve
|
||||
* the old semantics: if an application modifies one of these three
|
||||
* fields of _res before res_init() is called, res_init() will not
|
||||
* alter them. Of course, if an application is setting them to
|
||||
* _zero_ before calling res_init(), hoping to override what used
|
||||
* to be the static default, we can't detect it and unexpected results
|
||||
* will follow. Zero for any of these fields would make no sense,
|
||||
* so one can safely assume that the applications were already getting
|
||||
* unexpected results.
|
||||
*
|
||||
* _res.options is tricky since some apps were known to diddle the bits
|
||||
* before res_init() was first called. We can't replicate that semantic
|
||||
* with dynamic initialization (they may have turned bits off that are
|
||||
* set in RES_DEFAULT). Our solution is to declare such applications
|
||||
* "broken". They could fool us by setting RES_INIT but none do (yet).
|
||||
*/
|
||||
if (!_res.retrans)
|
||||
_res.retrans = RES_TIMEOUT;
|
||||
if (!_res.retry)
|
||||
_res.retry = 4;
|
||||
if (!(_res.options & RES_INIT))
|
||||
_res.options = RES_DEFAULT;
|
||||
|
||||
#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.nsaddr.sin_len = sizeof(struct sockaddr_in);
|
||||
#ifdef INET6
|
||||
if (sizeof(_res_ext.nsaddr) >= _res.nsaddr.sin_len)
|
||||
memcpy(&_res_ext.nsaddr, &_res.nsaddr, _res.nsaddr.sin_len);
|
||||
#endif
|
||||
_res.nscount = 1;
|
||||
_res.ndots = 1;
|
||||
_res.pfcode = 0;
|
||||
strncpy(_res.lookups, "f", sizeof _res.lookups);
|
||||
|
||||
/* Allow user to override the local domain definition */
|
||||
if ((cp = getenv("LOCALDOMAIN")) != NULL) {
|
||||
strncpy(_res.defdname, cp, sizeof(_res.defdname));
|
||||
haveenv++;
|
||||
|
||||
/*
|
||||
* Set search list to be blank-separated strings
|
||||
* from rest of env value. Permits users of LOCALDOMAIN
|
||||
* to still have a search list, and anyone to set the
|
||||
* one that they want to use as an individual (even more
|
||||
* important now that the rfc1535 stuff restricts searches)
|
||||
*/
|
||||
cp = _res.defdname;
|
||||
pp = _res.dnsrch;
|
||||
*pp++ = cp;
|
||||
for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
|
||||
if (*cp == '\n') /* silly backwards compat */
|
||||
break;
|
||||
else if (*cp == ' ' || *cp == '\t') {
|
||||
*cp = 0;
|
||||
n = 1;
|
||||
} else if (n) {
|
||||
*pp++ = cp;
|
||||
n = 0;
|
||||
havesearch = 1;
|
||||
}
|
||||
}
|
||||
/* null terminate last domain if there are excess */
|
||||
while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
|
||||
cp++;
|
||||
*cp = '\0';
|
||||
*pp++ = 0;
|
||||
}
|
||||
|
||||
#define MATCH(line, name) \
|
||||
(!strncmp(line, name, sizeof(name) - 1) && \
|
||||
(line[sizeof(name) - 1] == ' ' || \
|
||||
line[sizeof(name) - 1] == '\t'))
|
||||
|
||||
if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
|
||||
strncpy(_res.lookups, "bf", sizeof _res.lookups);
|
||||
|
||||
/* read the config file */
|
||||
buf[0] = '\0';
|
||||
while (fgets(lbuf, 80, fp) != NULL) {
|
||||
/* skip lines that are too long or zero length */
|
||||
len = strlen(lbuf) - 1;
|
||||
cp = lbuf;
|
||||
if (len >= sizeof(buf) || len == 0)
|
||||
continue;
|
||||
memcpy(buf, cp, len);
|
||||
buf[len] = '\0';
|
||||
/* skip comments */
|
||||
if ((cp = strpbrk(buf, ";#")) != NULL)
|
||||
*cp = '\0';
|
||||
if (buf[0] == '\0')
|
||||
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));
|
||||
if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL)
|
||||
*cp = '\0';
|
||||
havesearch = 0;
|
||||
continue;
|
||||
}
|
||||
/* lookup types */
|
||||
if (MATCH(buf, "lookup")) {
|
||||
char *sp = NULL;
|
||||
memset(_res.lookups, 0, sizeof _res.lookups);
|
||||
cp = buf + sizeof("lookup") - 1;
|
||||
for (n = 0;; cp++) {
|
||||
if (n == MAXDNSLUS)
|
||||
break;
|
||||
if ((*cp == '\0') || (*cp == '\n')) {
|
||||
if (sp) {
|
||||
if (*sp=='y' || *sp=='b' || *sp=='f')
|
||||
_res.lookups[n++] = *sp;
|
||||
sp = NULL;
|
||||
}
|
||||
break;
|
||||
} else if ((*cp == ' ') || (*cp == '\t') || (*cp == ',')) {
|
||||
if (sp) {
|
||||
if (*sp=='y' || *sp=='b' || *sp=='f')
|
||||
_res.lookups[n++] = *sp;
|
||||
sp = NULL;
|
||||
}
|
||||
} else if (sp == NULL)
|
||||
sp = cp;
|
||||
}
|
||||
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));
|
||||
if ((cp = strchr(_res.defdname, '\n')) != NULL)
|
||||
*cp = '\0';
|
||||
/*
|
||||
* Set search list to be blank-separated strings
|
||||
* on rest of line.
|
||||
*/
|
||||
cp = _res.defdname;
|
||||
pp = _res.dnsrch;
|
||||
*pp++ = cp;
|
||||
for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
|
||||
if (*cp == ' ' || *cp == '\t') {
|
||||
*cp = 0;
|
||||
n = 1;
|
||||
} else if (n) {
|
||||
*pp++ = cp;
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
/* null terminate last domain if there are excess */
|
||||
while (*cp != '\0' && *cp != ' ' && *cp != '\t')
|
||||
cp++;
|
||||
*cp = '\0';
|
||||
*pp++ = 0;
|
||||
havesearch = 1;
|
||||
continue;
|
||||
}
|
||||
/* read nameservers to query */
|
||||
if (MATCH(buf, "nameserver") && nserv < MAXNS) {
|
||||
#ifdef INET6
|
||||
char *q;
|
||||
struct addrinfo hints, *res;
|
||||
char pbuf[NI_MAXSERV];
|
||||
#else
|
||||
struct in_addr a;
|
||||
#endif /* INET6 */
|
||||
cp = buf + sizeof("nameserver") - 1;
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
#ifdef INET6
|
||||
if ((*cp == '\0') || (*cp == '\n'))
|
||||
continue;
|
||||
for (q = cp; *q; q++) {
|
||||
if (isspace(*q)) {
|
||||
*q = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
snprintf(pbuf, sizeof(pbuf), "%d", NAMESERVER_PORT);
|
||||
res = NULL;
|
||||
if (getaddrinfo(cp, pbuf, &hints, &res) == 0 &&
|
||||
res->ai_next == NULL) {
|
||||
if (res->ai_addrlen <= sizeof(_res_ext.nsaddr_list[nserv])) {
|
||||
memcpy(&_res_ext.nsaddr_list[nserv], res->ai_addr,
|
||||
res->ai_addrlen);
|
||||
} else {
|
||||
memset(&_res_ext.nsaddr_list[nserv], 0,
|
||||
sizeof(_res_ext.nsaddr_list[nserv]));
|
||||
}
|
||||
if (res->ai_addrlen <= sizeof(_res.nsaddr_list[nserv])) {
|
||||
memcpy(&_res.nsaddr_list[nserv], res->ai_addr,
|
||||
res->ai_addrlen);
|
||||
} else {
|
||||
memset(&_res.nsaddr_list[nserv], 0,
|
||||
sizeof(_res.nsaddr_list[nserv]));
|
||||
}
|
||||
nserv++;
|
||||
}
|
||||
if (res)
|
||||
freeaddrinfo(res);
|
||||
#else /* INET6 */
|
||||
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);
|
||||
_res.nsaddr_list[nserv].sin_len = sizeof(struct sockaddr_in);
|
||||
nserv++;
|
||||
}
|
||||
#endif /* INET6 */
|
||||
continue;
|
||||
}
|
||||
#ifdef RESOLVSORT
|
||||
if (MATCH(buf, "sortlist")) {
|
||||
struct in_addr a;
|
||||
#ifdef INET6
|
||||
struct in6_addr a6;
|
||||
int m, i;
|
||||
u_char *u;
|
||||
#endif /* INET6 */
|
||||
|
||||
cp = buf + sizeof("sortlist") - 1;
|
||||
while (nsort < MAXRESOLVSORT) {
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
if (*cp == '\0' || *cp == '\n' || *cp == ';')
|
||||
break;
|
||||
net = cp;
|
||||
while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
|
||||
isascii(*cp) && !isspace(*cp))
|
||||
cp++;
|
||||
n = *cp;
|
||||
*cp = 0;
|
||||
if (inet_aton(net, &a)) {
|
||||
_res.sort_list[nsort].addr = a;
|
||||
if (ISSORTMASK(n)) {
|
||||
*cp++ = n;
|
||||
net = cp;
|
||||
while (*cp && *cp != ';' &&
|
||||
isascii(*cp) && !isspace(*cp))
|
||||
cp++;
|
||||
n = *cp;
|
||||
*cp = 0;
|
||||
if (inet_aton(net, &a)) {
|
||||
_res.sort_list[nsort].mask = a.s_addr;
|
||||
} else {
|
||||
_res.sort_list[nsort].mask =
|
||||
net_mask(_res.sort_list[nsort].addr);
|
||||
}
|
||||
} else {
|
||||
_res.sort_list[nsort].mask =
|
||||
net_mask(_res.sort_list[nsort].addr);
|
||||
}
|
||||
#ifdef INET6
|
||||
_res_ext.sort_list[nsort].af = AF_INET;
|
||||
_res_ext.sort_list[nsort].addr.ina =
|
||||
_res.sort_list[nsort].addr;
|
||||
_res_ext.sort_list[nsort].mask.ina.s_addr =
|
||||
_res.sort_list[nsort].mask;
|
||||
#endif /* INET6 */
|
||||
nsort++;
|
||||
}
|
||||
#ifdef INET6
|
||||
else if (inet_pton(AF_INET6, net, &a6) == 1) {
|
||||
_res_ext.sort_list[nsort].af = AF_INET6;
|
||||
_res_ext.sort_list[nsort].addr.in6a = a6;
|
||||
u = (u_char *)&_res_ext.sort_list[nsort].mask.in6a;
|
||||
*cp++ = n;
|
||||
net = cp;
|
||||
while (*cp && *cp != ';' &&
|
||||
isascii(*cp) && !isspace(*cp))
|
||||
cp++;
|
||||
m = n;
|
||||
n = *cp;
|
||||
*cp = 0;
|
||||
switch (m) {
|
||||
case '/':
|
||||
m = atoi(net);
|
||||
break;
|
||||
case '&':
|
||||
if (inet_pton(AF_INET6, net, u) == 1) {
|
||||
m = -1;
|
||||
break;
|
||||
}
|
||||
/*FALLTHRU*/
|
||||
default:
|
||||
m = sizeof(struct in6_addr) * NBBY;
|
||||
break;
|
||||
}
|
||||
if (m >= 0) {
|
||||
for (i = 0; i < sizeof(struct in6_addr); i++) {
|
||||
if (m <= 0) {
|
||||
*u = 0;
|
||||
} else {
|
||||
m -= NBBY;
|
||||
*u = (u_char)~0;
|
||||
if (m < 0)
|
||||
*u <<= -m;
|
||||
}
|
||||
u++;
|
||||
}
|
||||
}
|
||||
nsort++;
|
||||
}
|
||||
#endif /* INET6 */
|
||||
*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);
|
||||
}
|
||||
if (_res.defdname[0] == 0 &&
|
||||
gethostname(buf, sizeof(_res.defdname) - 1) == 0 &&
|
||||
(cp = strchr(buf, '.')) != NULL)
|
||||
{
|
||||
strncpy(_res.defdname, cp + 1,
|
||||
sizeof(_res.defdname));
|
||||
}
|
||||
|
||||
/* 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 (issetugid())
|
||||
// _res.options |= RES_NOALIASES;
|
||||
// else
|
||||
if ((cp = getenv("RES_OPTIONS")) != NULL)
|
||||
res_setoptions(cp, "env");
|
||||
_res.options |= RES_INIT;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
res_setoptions(options, source)
|
||||
char *options, *source;
|
||||
{
|
||||
char *cp = options;
|
||||
char *endp;
|
||||
long l;
|
||||
|
||||
#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)) {
|
||||
char *p = cp + sizeof("ndots:") - 1;
|
||||
l = strtol(p, &endp, 10);
|
||||
if (l >= 0 && endp != p &&
|
||||
(*endp = '\0' || isspace(*endp))) {
|
||||
if (l <= RES_MAXNDOTS)
|
||||
_res.ndots = l;
|
||||
else
|
||||
_res.ndots = RES_MAXNDOTS;
|
||||
#ifdef DEBUG
|
||||
if (_res.options & RES_DEBUG)
|
||||
printf(";;\tndots=%d\n", _res.ndots);
|
||||
#endif
|
||||
}
|
||||
} else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
|
||||
#ifdef DEBUG
|
||||
if (!(_res.options & RES_DEBUG)) {
|
||||
printf(";; res_setoptions(\"%s\", \"%s\")..\n",
|
||||
options, source);
|
||||
_res.options |= RES_DEBUG;
|
||||
}
|
||||
printf(";;\tdebug\n");
|
||||
#endif
|
||||
} else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
|
||||
_res.options |= RES_USE_INET6;
|
||||
} else if (!strncmp(cp, "insecure1", sizeof("insecure1") - 1)) {
|
||||
_res.options |= RES_INSECURE1;
|
||||
} else if (!strncmp(cp, "insecure2", sizeof("insecure2") - 1)) {
|
||||
_res.options |= RES_INSECURE2;
|
||||
} else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
|
||||
_res.options |= RES_USE_EDNS0;
|
||||
} else {
|
||||
/* XXX - print a warning here? */
|
||||
}
|
||||
/* skip to next run of spaces */
|
||||
while (*cp && *cp != ' ' && *cp != '\t')
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RESOLVSORT
|
||||
/* XXX - should really support CIDR which means explicit masks always. */
|
||||
|
||||
static uint32 net_mask(struct in_addr in) /* XXX - should really use system's version of this */
|
||||
{
|
||||
register uint32 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
|
231
src/kits/network/libnet/res_mkquery.c
Normal file
231
src/kits/network/libnet/res_mkquery.c
Normal file
@ -0,0 +1,231 @@
|
||||
/*
|
||||
* ++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 <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <resolv.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* Form all types of queries.
|
||||
* Returns the size of the result or -1.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
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;
|
||||
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.
|
||||
*
|
||||
* A special random number generator is used to create non predictable
|
||||
* and non repeating ids over a long period. It also avoids reuse
|
||||
* by switching between two distinct number cycles.
|
||||
*/
|
||||
|
||||
if ((buf == NULL) || (buflen < HFIXEDSZ))
|
||||
return (-1);
|
||||
|
||||
memset(buf, 0, HFIXEDSZ);
|
||||
hp = (HEADER *) buf;
|
||||
_res.id = res_randomid();
|
||||
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((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) {
|
||||
memcpy(cp, data, datalen);
|
||||
cp += datalen;
|
||||
}
|
||||
hp->ancount = htons(1);
|
||||
break;
|
||||
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
return (cp - buf);
|
||||
}
|
||||
|
||||
/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */
|
||||
int
|
||||
res_opt(n0, buf, buflen, anslen)
|
||||
int n0;
|
||||
u_char *buf; /* buffer to put query */
|
||||
int buflen; /* size of buffer */
|
||||
int anslen; /* answer buffer length */
|
||||
{
|
||||
register HEADER *hp;
|
||||
register u_char *cp;
|
||||
|
||||
hp = (HEADER *) buf;
|
||||
cp = buf + n0;
|
||||
buflen -= n0;
|
||||
|
||||
if (buflen < 1 + RRFIXEDSZ)
|
||||
return -1;
|
||||
|
||||
*cp++ = 0; /* "." */
|
||||
buflen--;
|
||||
|
||||
__putshort(T_OPT, cp); /* TYPE */
|
||||
cp += INT16SZ;
|
||||
__putshort(anslen & 0xffff, cp); /* CLASS = UDP payload size */
|
||||
cp += INT16SZ;
|
||||
*cp++ = NOERROR; /* extended RCODE */
|
||||
*cp++ = 0; /* EDNS version */
|
||||
if (_res.options & RES_USE_DNSSEC) {
|
||||
#ifdef DEBUG
|
||||
if (_res.options & RES_DEBUG)
|
||||
printf(";; res_opt()... ENDS0 DNSSEC OK\n");
|
||||
#endif /* DEBUG */
|
||||
__putshort(DNS_MESSAGEEXTFLAG_DO, cp); /* EDNS Z field */
|
||||
cp += INT16SZ;
|
||||
} else {
|
||||
__putshort(0, cp); /* EDNS Z field */
|
||||
cp += INT16SZ;
|
||||
}
|
||||
__putshort(0, cp); /* RDLEN */
|
||||
cp += INT16SZ;
|
||||
hp->arcount = htons(ntohs(hp->arcount) + 1);
|
||||
buflen -= RRFIXEDSZ;
|
||||
|
||||
return cp - buf;
|
||||
}
|
396
src/kits/network/libnet/res_query.c
Normal file
396
src/kits/network/libnet/res_query.c
Normal file
@ -0,0 +1,396 @@
|
||||
/*
|
||||
* ++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 <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <resolv.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if PACKETSZ > 1024
|
||||
#define MAXPACKET PACKETSZ
|
||||
#else
|
||||
#define MAXPACKET 1024
|
||||
#endif
|
||||
|
||||
const char *hostalias (const char *);
|
||||
int h_errno;
|
||||
extern int res_opt (int, u_char *, int, int);
|
||||
|
||||
/*
|
||||
* Formulate a normal query, send, and await answer.
|
||||
* Returned answer is placed in supplied buffer "answer".
|
||||
* Perform preliminary check of answer, returning success only
|
||||
* if no error is indicated and the answer count is nonzero.
|
||||
* Return the size of the response on success, -1 on error.
|
||||
* Error number is left in h_errno.
|
||||
*
|
||||
* Caller must parse answer and determine whether it answers the question.
|
||||
*/
|
||||
int
|
||||
res_query(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 */
|
||||
{
|
||||
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 && ((_res.options & RES_USE_EDNS0) ||
|
||||
(_res.options & RES_USE_DNSSEC))) {
|
||||
n = res_opt(n, buf, sizeof(buf), anslen);
|
||||
}
|
||||
|
||||
if (n <= 0) {
|
||||
#ifdef DEBUG
|
||||
if (_res.options & RES_DEBUG)
|
||||
printf(";; res_query: mkquery failed\n");
|
||||
#endif
|
||||
h_errno = NO_RECOVERY;
|
||||
return (n);
|
||||
}
|
||||
n = res_send(buf, n, answer, anslen);
|
||||
if (n < 0) {
|
||||
#ifdef DEBUG
|
||||
if (_res.options & RES_DEBUG)
|
||||
printf(";; res_query: send error\n");
|
||||
#endif
|
||||
h_errno = TRY_AGAIN;
|
||||
return (n);
|
||||
}
|
||||
|
||||
if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
|
||||
#ifdef DEBUG
|
||||
if (_res.options & RES_DEBUG)
|
||||
printf(";; rcode = %d, ancount=%d\n", hp->rcode,
|
||||
ntohs(hp->ancount));
|
||||
#endif
|
||||
switch (hp->rcode) {
|
||||
case NXDOMAIN:
|
||||
h_errno = HOST_NOT_FOUND;
|
||||
break;
|
||||
case SERVFAIL:
|
||||
h_errno = TRY_AGAIN;
|
||||
break;
|
||||
case NOERROR:
|
||||
h_errno = NO_DATA;
|
||||
break;
|
||||
case FORMERR:
|
||||
case NOTIMP:
|
||||
case REFUSED:
|
||||
default:
|
||||
h_errno = NO_RECOVERY;
|
||||
break;
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
return (n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Formulate a normal query, send, and retrieve answer in supplied buffer.
|
||||
* Return the size of the response on success, -1 on error.
|
||||
* If enabled, implement search rules until answer or unrecoverable failure
|
||||
* is detected. Error code, if any, is left in h_errno.
|
||||
*/
|
||||
int
|
||||
res_search(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 */
|
||||
{
|
||||
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.
|
||||
*/
|
||||
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 */
|
||||
{
|
||||
char nbuf[MAXDNAME*2+1+1];
|
||||
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:"<Nil>", class, type);
|
||||
#endif
|
||||
if (domain == NULL) {
|
||||
/*
|
||||
* Check for trailing '.';
|
||||
* copy without '.' if present.
|
||||
*/
|
||||
n = strlen(name) - 1;
|
||||
if (n != (0 - 1) && name[n] == '.' && n < sizeof(nbuf) - 1) {
|
||||
memcpy(nbuf, name, n);
|
||||
nbuf[n] = '\0';
|
||||
} else
|
||||
longname = name;
|
||||
} else
|
||||
sprintf(nbuf, "%.*s.%.*s", MAXDNAME, name, MAXDNAME, domain);
|
||||
|
||||
return (res_query(longname, class, type, answer, anslen));
|
||||
}
|
||||
|
||||
const char *
|
||||
hostalias(name)
|
||||
register const char *name;
|
||||
{
|
||||
register char *cp1, *cp2;
|
||||
FILE *fp;
|
||||
char *file;
|
||||
char buf[BUFSIZ];
|
||||
static char abuf[MAXDNAME];
|
||||
size_t len;
|
||||
|
||||
if (_res.options & RES_NOALIASES)
|
||||
return (NULL);
|
||||
file = getenv("HOSTALIASES");
|
||||
// if (issetugid() != 0 || file == NULL || (fp = fopen(file, "r")) == NULL)
|
||||
if (file == NULL || (fp = fopen(file, "r")) == NULL)
|
||||
return (NULL);
|
||||
setbuf(fp, NULL);
|
||||
while ((cp1 = fgets(buf, sizeof(buf), fp)) != NULL) {
|
||||
// while ((cp1 = fgetln(fp, &len)) != NULL) {
|
||||
len = strlen(buf);
|
||||
if (cp1[len-1] == '\n')
|
||||
len--;
|
||||
// if (len >= sizeof(buf) || len == 0)
|
||||
// continue;
|
||||
// (void)memcpy(buf, cp1, len);
|
||||
buf[len] = '\0';
|
||||
|
||||
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)
|
||||
;
|
||||
*cp2 = '\0';
|
||||
strncpy(abuf, cp1, sizeof(abuf));
|
||||
fclose(fp);
|
||||
return (abuf);
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
return (NULL);
|
||||
}
|
238
src/kits/network/libnet/res_random.c
Normal file
238
src/kits/network/libnet/res_random.c
Normal file
@ -0,0 +1,238 @@
|
||||
/*
|
||||
* Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Theo de Raadt <deraadt@openbsd.org> came up with the idea of using
|
||||
* such a mathematical system to generate more random (yet non-repeating)
|
||||
* ids to solve the resolver/named problem. But Niels designed the
|
||||
* actual system based on the constraints.
|
||||
*
|
||||
* 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 Niels Provos.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* seed = random 15bit
|
||||
* n = prime, g0 = generator to n,
|
||||
* j = random so that gcd(j,n-1) == 1
|
||||
* g = g0^j mod n will be a generator again.
|
||||
*
|
||||
* X[0] = random seed.
|
||||
* X[n] = a*X[n-1]+b mod m is a Linear Congruential Generator
|
||||
* with a = 7^(even random) mod m,
|
||||
* b = random with gcd(b,m) == 1
|
||||
* m = 31104 and a maximal period of m-1.
|
||||
*
|
||||
* The transaction id is determined by:
|
||||
* id[n] = seed xor (g^X[n] mod n)
|
||||
*
|
||||
* Effectivly the id is restricted to the lower 15 bits, thus
|
||||
* yielding two different cycles by toggling the msb on and off.
|
||||
* This avoids reuse issues caused by reseeding.
|
||||
*
|
||||
* The 16 bit space is very small and brute force attempts are
|
||||
* entirly feasible, we skip a random number of transaction ids
|
||||
* so that an attacker will not get sequential ids.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "netinet/in.h"
|
||||
#include <sys/time.h>
|
||||
#include "resolv.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* arc4random is defined in stdlib.h on OpenBSD, so we'll just forward
|
||||
* declare the prototype here to stop the compiler moaning.
|
||||
*/
|
||||
uint32 arc4random(void);
|
||||
|
||||
#define RU_OUT 180 /* Time after wich will be reseeded */
|
||||
#define RU_MAX 30000 /* Uniq cycle, avoid blackjack prediction */
|
||||
#define RU_GEN 2 /* Starting generator */
|
||||
#define RU_N 32749 /* RU_N-1 = 2*2*3*2729 */
|
||||
#define RU_AGEN 7 /* determine ru_a as RU_AGEN^(2*rand) */
|
||||
#define RU_M 31104 /* RU_M = 2^7*3^5 - don't change */
|
||||
|
||||
#define PFAC_N 3
|
||||
const static uint16 pfacts[PFAC_N] = {
|
||||
2,
|
||||
3,
|
||||
2729
|
||||
};
|
||||
|
||||
static uint16 ru_x;
|
||||
static uint16 ru_seed, ru_seed2;
|
||||
static uint16 ru_a, ru_b;
|
||||
static uint16 ru_g;
|
||||
static uint16 ru_counter = 0;
|
||||
static uint16 ru_msb = 0;
|
||||
static long ru_reseed;
|
||||
static uint32 tmp; /* Storage for unused random */
|
||||
static struct timeval tv;
|
||||
|
||||
static uint16 pmod (uint16, uint16, uint16);
|
||||
static void res_initid (void);
|
||||
|
||||
/*
|
||||
* Do a fast modular exponation, returned value will be in the range
|
||||
* of 0 - (mod-1)
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
static uint16
|
||||
pmod(uint16 gen, uint16 exp, uint16 mod)
|
||||
#else
|
||||
static uint16
|
||||
pmod(gen, exp, mod)
|
||||
uint16 gen, exp, mod;
|
||||
#endif
|
||||
{
|
||||
uint16 s, t, u;
|
||||
|
||||
s = 1;
|
||||
t = gen;
|
||||
u = exp;
|
||||
|
||||
while (u) {
|
||||
if (u & 1)
|
||||
s = (s*t) % mod;
|
||||
u >>= 1;
|
||||
t = (t*t) % mod;
|
||||
}
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes the seed and chooses a suitable generator. Also toggles
|
||||
* the msb flag. The msb flag is used to generate two distinct
|
||||
* cycles of random numbers and thus avoiding reuse of ids.
|
||||
*
|
||||
* This function is called from res_randomid() when needed, an
|
||||
* application does not have to worry about it.
|
||||
*/
|
||||
static void
|
||||
res_initid()
|
||||
{
|
||||
uint16 j, i;
|
||||
int noprime = 1;
|
||||
|
||||
tmp = arc4random();
|
||||
ru_x = (tmp & 0xFFFF) % RU_M;
|
||||
|
||||
/* 15 bits of random seed */
|
||||
ru_seed = (tmp >> 16) & 0x7FFF;
|
||||
tmp = arc4random();
|
||||
ru_seed2 = tmp & 0x7FFF;
|
||||
|
||||
tmp = arc4random();
|
||||
|
||||
/* Determine the LCG we use */
|
||||
ru_b = (tmp & 0xfffe) | 1;
|
||||
ru_a = pmod(RU_AGEN, (tmp >> 16) & 0xfffe, RU_M);
|
||||
while (ru_b % 3 == 0)
|
||||
ru_b += 2;
|
||||
|
||||
tmp = arc4random();
|
||||
j = tmp % RU_N;
|
||||
tmp = tmp >> 16;
|
||||
|
||||
/*
|
||||
* Do a fast gcd(j,RU_N-1), so we can find a j with
|
||||
* gcd(j, RU_N-1) == 1, giving a new generator for
|
||||
* RU_GEN^j mod RU_N
|
||||
*/
|
||||
|
||||
while (noprime) {
|
||||
for (i=0; i<PFAC_N; i++)
|
||||
if (j%pfacts[i] == 0)
|
||||
break;
|
||||
|
||||
if (i>=PFAC_N)
|
||||
noprime = 0;
|
||||
else
|
||||
j = (j+1) % RU_N;
|
||||
}
|
||||
|
||||
ru_g = pmod(RU_GEN,j,RU_N);
|
||||
ru_counter = 0;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
ru_reseed = tv.tv_sec + RU_OUT;
|
||||
ru_msb = ru_msb == 0x8000 ? 0 : 0x8000;
|
||||
}
|
||||
|
||||
u_int
|
||||
res_randomid()
|
||||
{
|
||||
int i, n;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
if (ru_counter >= RU_MAX || tv.tv_sec > ru_reseed)
|
||||
res_initid();
|
||||
|
||||
if (!tmp)
|
||||
tmp = arc4random();
|
||||
|
||||
/* Skip a random number of ids */
|
||||
n = tmp & 0x7; tmp = tmp >> 3;
|
||||
if (ru_counter + n >= RU_MAX)
|
||||
res_initid();
|
||||
|
||||
for (i=0; i<=n; i++)
|
||||
/* Linear Congruential Generator */
|
||||
ru_x = (ru_a*ru_x + ru_b) % RU_M;
|
||||
|
||||
ru_counter += i;
|
||||
|
||||
return (ru_seed ^ pmod(ru_g,ru_seed2 ^ ru_x,RU_N)) | ru_msb;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int i, n;
|
||||
uint16 wert;
|
||||
|
||||
res_initid();
|
||||
|
||||
printf("Generator: %d\n", ru_g);
|
||||
printf("Seed: %d\n", ru_seed);
|
||||
printf("Reseed at %ld\n", ru_reseed);
|
||||
printf("Ru_X: %d\n", ru_x);
|
||||
printf("Ru_A: %d\n", ru_a);
|
||||
printf("Ru_B: %d\n", ru_b);
|
||||
|
||||
n = atoi(argv[1]);
|
||||
for (i=0;i<n;i++) {
|
||||
wert = res_randomid();
|
||||
printf("%06d\n", wert);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
883
src/kits/network/libnet/res_send.c
Normal file
883
src/kits/network/libnet/res_send.c
Normal file
@ -0,0 +1,883 @@
|
||||
/*
|
||||
* ++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 <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include "sys/socket.h"
|
||||
#include <sys/uio.h>
|
||||
#include "netinet/in.h"
|
||||
#include "arpa/nameser.h"
|
||||
#include "arpa/inet.h"
|
||||
#include "sys/select.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include "netdb.h"
|
||||
#include <errno.h>
|
||||
#include "resolv.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
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? */
|
||||
static int af = 0; /* address family of socket */
|
||||
|
||||
#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 char abuf[NI_MAXHOST];
|
||||
static char pbuf[NI_MAXSERV];
|
||||
static void Aerror (FILE *, char *, int, struct sockaddr *);
|
||||
static void Perror (FILE *, char *, int);
|
||||
|
||||
static void
|
||||
Aerror(file, string, error, address)
|
||||
FILE *file;
|
||||
char *string;
|
||||
int error;
|
||||
struct sockaddr *address;
|
||||
{
|
||||
int save = errno;
|
||||
|
||||
if (_res.options & RES_DEBUG) {
|
||||
if (getnameinfo(address, address->sa_len, abuf, sizeof(abuf),
|
||||
pbuf, sizeof(pbuf),
|
||||
NI_NUMERICHOST|NI_NUMERICSERV|NI_WITHSCOPEID) != 0) {
|
||||
strncpy(abuf, "?", sizeof(abuf));
|
||||
strncpy(pbuf, "?", sizeof(pbuf));
|
||||
}
|
||||
fprintf(file, "res_send: %s ([%s].%s): %s\n",
|
||||
string, abuf, pbuf, strerror(error));
|
||||
}
|
||||
errno = save;
|
||||
}
|
||||
static void
|
||||
Perror(file, string, error)
|
||||
FILE *file;
|
||||
char *string;
|
||||
int error;
|
||||
{
|
||||
int save = errno;
|
||||
|
||||
if (_res.options & RES_DEBUG) {
|
||||
fprintf(file, "res_send: %s: %s\n",
|
||||
string, strerror(error));
|
||||
}
|
||||
errno = save;
|
||||
}
|
||||
#endif
|
||||
|
||||
static res_send_qhook Qhook = NULL;
|
||||
static res_send_rhook Rhook = NULL;
|
||||
|
||||
void
|
||||
res_send_setqhook(hook)
|
||||
res_send_qhook hook;
|
||||
{
|
||||
|
||||
Qhook = hook;
|
||||
}
|
||||
|
||||
void
|
||||
res_send_setrhook(hook)
|
||||
res_send_rhook hook;
|
||||
{
|
||||
|
||||
Rhook = hook;
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
static struct sockaddr * get_nsaddr (size_t);
|
||||
|
||||
/*
|
||||
* pick appropriate nsaddr_list for use. see res_init() for initialization.
|
||||
*/
|
||||
static struct sockaddr *
|
||||
get_nsaddr(n)
|
||||
size_t n;
|
||||
{
|
||||
|
||||
if (!_res.nsaddr_list[n].sin_family) {
|
||||
/*
|
||||
* - _res_ext.nsaddr_list[n] holds an address that is larger
|
||||
* than struct sockaddr, and
|
||||
* - user code did not update _res.nsaddr_list[n].
|
||||
*/
|
||||
return (struct sockaddr *)&_res_ext.nsaddr_list[n];
|
||||
} else {
|
||||
/*
|
||||
* - user code updated _res.nsaddr_list[n], or
|
||||
* - _res.nsaddr_list[n] has the same content as
|
||||
* _res_ext.nsaddr_list[n].
|
||||
*/
|
||||
return (struct sockaddr *)&_res.nsaddr_list[n];
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define get_nsaddr(n) ((struct sockaddr *)&_res.nsaddr_list[(n)])
|
||||
#endif
|
||||
|
||||
/* 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(inp)
|
||||
const struct sockaddr_in *inp;
|
||||
{
|
||||
#ifdef INET6
|
||||
const struct sockaddr_in6 *in6p = (const struct sockaddr_in6 *)inp;
|
||||
const struct sockaddr_in6 *srv6;
|
||||
#endif
|
||||
const struct sockaddr_in *srv;
|
||||
int ns, ret;
|
||||
|
||||
ret = 0;
|
||||
|
||||
/* XXX - debug code to see why we fail in this routine! */
|
||||
printf("inp->sin_family = %d (AF_INET = %d)\n",
|
||||
inp->sin_family, AF_INET);
|
||||
|
||||
switch (inp->sin_family) {
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
for (ns = 0; ns < _res.nscount; ns++) {
|
||||
srv6 = (struct sockaddr_in6 *)get_nsaddr(ns);
|
||||
if (srv6->sin6_family == in6p->sin6_family &&
|
||||
srv6->sin6_port == in6p->sin6_port &&
|
||||
srv6->sin6_scope_id == in6p->sin6_scope_id &&
|
||||
(IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
|
||||
IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr,
|
||||
&in6p->sin6_addr))) {
|
||||
ret++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case AF_INET:
|
||||
for (ns = 0; ns < _res.nscount; ns++) {
|
||||
srv = (struct sockaddr_in *)get_nsaddr(ns);
|
||||
if (srv->sin_family == inp->sin_family &&
|
||||
srv->sin_port == inp->sin_port &&
|
||||
(srv->sin_addr.s_addr == INADDR_ANY ||
|
||||
srv->sin_addr.s_addr == inp->sin_addr.s_addr)) {
|
||||
ret++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* 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(name, type, class, buf, eom)
|
||||
const char *name;
|
||||
register int type, class;
|
||||
const u_char *buf, *eom;
|
||||
{
|
||||
register const u_char *cp = buf + HFIXEDSZ;
|
||||
int qdcount = ntohs(((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);
|
||||
}
|
||||
|
||||
/* 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(buf1, eom1, buf2, eom2)
|
||||
const u_char *buf1, *eom1;
|
||||
const u_char *buf2, *eom2;
|
||||
{
|
||||
register const u_char *cp = buf1 + HFIXEDSZ;
|
||||
int qdcount = ntohs(((HEADER*)buf1)->qdcount);
|
||||
|
||||
if (qdcount != ntohs(((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(buf, buflen, ans, anssiz)
|
||||
const u_char *buf;
|
||||
int buflen;
|
||||
u_char *ans;
|
||||
int anssiz;
|
||||
{
|
||||
HEADER *hp = (HEADER *) buf;
|
||||
HEADER *anhp = (HEADER *) ans;
|
||||
int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns;
|
||||
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 *nsap = get_nsaddr(ns);
|
||||
uint32 salen;
|
||||
|
||||
if (nsap->sa_len)
|
||||
salen = nsap->sa_len;
|
||||
#ifdef INET6
|
||||
else if (nsap->sa_family == AF_INET6)
|
||||
salen = sizeof(struct sockaddr_in6);
|
||||
#endif
|
||||
else if (nsap->sa_family == AF_INET)
|
||||
salen = sizeof(struct sockaddr_in);
|
||||
else
|
||||
salen = 0; /*unknown, die on connect*/
|
||||
|
||||
same_ns:
|
||||
if (badns & (1 << ns)) {
|
||||
res_close();
|
||||
goto next_ns;
|
||||
}
|
||||
|
||||
if (Qhook) {
|
||||
int done = 0, loops = 0;
|
||||
|
||||
do {
|
||||
res_sendhookact act;
|
||||
|
||||
act = (*Qhook)((struct sockaddr_in **)&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) &&
|
||||
getnameinfo(nsap, salen, abuf, sizeof(abuf),
|
||||
NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID) == 0,
|
||||
(stdout, ";; Querying server (# %d) address = %s\n",
|
||||
ns + 1, abuf));
|
||||
|
||||
if (v_circuit) {
|
||||
int truncated;
|
||||
struct iovec iov[2];
|
||||
u_short len;
|
||||
u_char *cp;
|
||||
|
||||
/*
|
||||
* Use virtual circuit;
|
||||
* at most one attempt per server.
|
||||
*/
|
||||
try = _res.retry;
|
||||
truncated = 0;
|
||||
if ((s < 0) || (!vc) || (af != nsap->sa_family)) {
|
||||
if (s >= 0)
|
||||
res_close();
|
||||
|
||||
af = nsap->sa_family;
|
||||
s = socket(af, SOCK_STREAM, 0);
|
||||
if (s < 0) {
|
||||
terrno = errno;
|
||||
Perror(stderr, "socket(vc)", errno);
|
||||
#if 0
|
||||
return (-1);
|
||||
#else
|
||||
badns |= (1 << ns);
|
||||
res_close();
|
||||
goto next_ns;
|
||||
#endif
|
||||
}
|
||||
errno = 0;
|
||||
if (connect(s, nsap, salen) < 0) {
|
||||
terrno = errno;
|
||||
Aerror(stderr, "connect/vc",
|
||||
errno, nsap);
|
||||
badns |= (1 << ns);
|
||||
res_close();
|
||||
goto next_ns;
|
||||
}
|
||||
vc = 1;
|
||||
}
|
||||
/*
|
||||
* Send length & message
|
||||
*/
|
||||
putshort((u_short)buflen, (u_char*)&len);
|
||||
iov[0].iov_base = (caddr_t)&len;
|
||||
iov[0].iov_len = INT16SZ;
|
||||
iov[1].iov_base = (caddr_t)buf;
|
||||
iov[1].iov_len = buflen;
|
||||
if (writev(s, iov, 2) != (INT16SZ + buflen)) {
|
||||
terrno = errno;
|
||||
Perror(stderr, "write failed", errno);
|
||||
badns |= (1 << ns);
|
||||
res_close();
|
||||
goto next_ns;
|
||||
}
|
||||
/*
|
||||
* Receive length & response
|
||||
*/
|
||||
read_len:
|
||||
cp = ans;
|
||||
len = INT16SZ;
|
||||
while ((n = read(s, (char *)cp, (int)len)) > 0) {
|
||||
cp += n;
|
||||
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;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* The calling applicating has bailed out of
|
||||
* a previous call and failed to arrange to have
|
||||
* the circuit closed or the server has got
|
||||
* itself confused. Anyway drop the packet and
|
||||
* wait for the correct one.
|
||||
*/
|
||||
if (hp->id != anhp->id) {
|
||||
DprintQ((_res.options & RES_DEBUG) ||
|
||||
(_res.pfcode & RES_PRF_REPLY),
|
||||
(stdout, ";; old answer (unexpected):\n"),
|
||||
ans, (resplen>anssiz)?anssiz:resplen);
|
||||
goto read_len;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Use datagrams.
|
||||
*/
|
||||
struct timeval timeout;
|
||||
fd_set *dsmaskp;
|
||||
struct sockaddr_storage from;
|
||||
size_t fromlen;
|
||||
|
||||
if ((s < 0) || vc || (af != nsap->sa_family)) {
|
||||
if (vc)
|
||||
res_close();
|
||||
af = nsap->sa_family;
|
||||
s = socket(af, SOCK_DGRAM, 0);
|
||||
if (s < 0) {
|
||||
#if !CAN_RECONNECT
|
||||
bad_dg_sock:
|
||||
#endif
|
||||
terrno = errno;
|
||||
Perror(stderr, "socket(dg)", errno);
|
||||
#if 0
|
||||
return (-1);
|
||||
#else
|
||||
badns |= (1 << ns);
|
||||
res_close();
|
||||
goto next_ns;
|
||||
#endif
|
||||
}
|
||||
#ifdef IPV6_MINMTU
|
||||
if (af == AF_INET6) {
|
||||
const int yes = 1;
|
||||
(void)setsockopt(s, IPPROTO_IPV6,
|
||||
IPV6_USE_MIN_MTU, &yes,
|
||||
sizeof(yes));
|
||||
}
|
||||
#endif
|
||||
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.options & RES_INSECURE1) &&
|
||||
(_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, nsap, salen) < 0) {
|
||||
Aerror(stderr,
|
||||
"connect(dg)",
|
||||
errno, nsap);
|
||||
badns |= (1 << ns);
|
||||
res_close();
|
||||
goto next_ns;
|
||||
}
|
||||
connected = 1;
|
||||
}
|
||||
if (send(s, (char*)buf, buflen, 0) != buflen) {
|
||||
Perror(stderr, "send", errno);
|
||||
badns |= (1 << ns);
|
||||
res_close();
|
||||
goto next_ns;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Disconnect if we want to listen
|
||||
* for responses from more than one server.
|
||||
*/
|
||||
if (connected) {
|
||||
#if CAN_RECONNECT
|
||||
#ifdef INET6
|
||||
/* XXX: any errornous address */
|
||||
#endif /* INET6 */
|
||||
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(af, 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
|
||||
#ifdef IPV6_MINMTU
|
||||
if (af == AF_INET6) {
|
||||
const int yes = 1;
|
||||
(void)setsockopt(s, IPPROTO_IPV6,
|
||||
IPV6_USE_MIN_MTU, &yes,
|
||||
sizeof(yes));
|
||||
}
|
||||
#endif
|
||||
connected = 0;
|
||||
errno = 0;
|
||||
}
|
||||
if (sendto(s, (char*)buf, buflen, 0,
|
||||
nsap, salen) != 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:
|
||||
dsmaskp = (fd_set *)malloc(sizeof(fd_set));
|
||||
memset((void*)dsmaskp, 0, sizeof(fd_set));
|
||||
if (dsmaskp == NULL) {
|
||||
res_close();
|
||||
goto next_ns;
|
||||
}
|
||||
FD_SET(s, dsmaskp);
|
||||
n = select(s+1, dsmaskp, (fd_set *)NULL,
|
||||
(fd_set *)NULL, &timeout);
|
||||
free(dsmaskp);
|
||||
if (n < 0) {
|
||||
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(from);
|
||||
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>anssiz)?anssiz:resplen);
|
||||
goto wait;
|
||||
}
|
||||
/* XXX - We should really be using this section of code, but on my server
|
||||
* this causes the name lookup to fail as the sin_family returned is 0, and
|
||||
* thus we fail the res_isourserver check. Not sure if this is specific
|
||||
* to my server or it's setup, but it's annoying.
|
||||
* Can other people remove the comment and see if this works for them?
|
||||
*/
|
||||
#if 0//CHECK_SRVR_ADDR
|
||||
if (!(_res.options & RES_INSECURE1) &&
|
||||
!res_isourserver((struct sockaddr_in *)&from)) {
|
||||
/*
|
||||
* response from wrong server? ignore it.
|
||||
* XXX - potential security hazard could
|
||||
* be detected here.
|
||||
*/
|
||||
DprintQ((_res.options & RES_DEBUG) ||
|
||||
(_res.pfcode & RES_PRF_REPLY),
|
||||
(stdout, ";; not our server:\n"),
|
||||
ans, (resplen>anssiz)?anssiz:resplen);
|
||||
|
||||
goto wait;
|
||||
}
|
||||
#endif
|
||||
if (!(_res.options & RES_INSECURE2) &&
|
||||
!res_queriesmatch(buf, buf + buflen,
|
||||
ans, ans + anssiz)) {
|
||||
/*
|
||||
* response contains wrong query? ignore it.
|
||||
* XXX - potential security hazard could
|
||||
* be detected here.
|
||||
*/
|
||||
DprintQ((_res.options & RES_DEBUG) ||
|
||||
(_res.pfcode & RES_PRF_REPLY),
|
||||
(stdout, ";; wrong query name:\n"),
|
||||
ans, (resplen>anssiz)?anssiz:resplen);
|
||||
goto wait;
|
||||
}
|
||||
|
||||
if (anhp->rcode == SERVFAIL ||
|
||||
anhp->rcode == NOTIMP ||
|
||||
anhp->rcode == REFUSED) {
|
||||
DprintQ(_res.options & RES_DEBUG,
|
||||
(stdout, "server rejected query:\n"),
|
||||
ans, (resplen>anssiz)?anssiz:resplen);
|
||||
badns |= (1 << ns);
|
||||
res_close();
|
||||
/* don't retry if called from dig */
|
||||
if (!_res.pfcode)
|
||||
goto next_ns;
|
||||
}
|
||||
if (!(_res.options & RES_IGNTC) && anhp->tc) {
|
||||
/*
|
||||
* get rest of answer;
|
||||
* use TCP with same server.
|
||||
*/
|
||||
Dprint(_res.options & RES_DEBUG,
|
||||
(stdout, ";; truncated answer\n"));
|
||||
v_circuit = 1;
|
||||
res_close();
|
||||
goto same_ns;
|
||||
}
|
||||
} /*if vc/dg*/
|
||||
Dprint((_res.options & RES_DEBUG) ||
|
||||
((_res.pfcode & RES_PRF_REPLY) &&
|
||||
(_res.pfcode & RES_PRF_HEAD1)),
|
||||
(stdout, ";; got answer:\n"));
|
||||
DprintQ((_res.options & RES_DEBUG) ||
|
||||
(_res.pfcode & RES_PRF_REPLY),
|
||||
(stdout, "%s", ""),
|
||||
ans, (resplen>anssiz)?anssiz:resplen);
|
||||
/*
|
||||
* If using virtual circuits, we assume that the first server
|
||||
* is preferred over the rest (i.e. it is on the local
|
||||
* machine) and only keep that one open.
|
||||
* If we have temporarily opened a virtual circuit,
|
||||
* or if we haven't been asked to keep a socket open,
|
||||
* close the socket.
|
||||
*/
|
||||
if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) ||
|
||||
!(_res.options & RES_STAYOPEN)) {
|
||||
res_close();
|
||||
}
|
||||
if (Rhook) {
|
||||
int done = 0, loops = 0;
|
||||
|
||||
do {
|
||||
res_sendhookact act;
|
||||
|
||||
act = (*Rhook)((struct sockaddr_in *)nsap,
|
||||
buf, buflen,
|
||||
ans, anssiz, &resplen);
|
||||
switch (act) {
|
||||
case res_goahead:
|
||||
case res_done:
|
||||
done = 1;
|
||||
break;
|
||||
case res_nextns:
|
||||
res_close();
|
||||
goto next_ns;
|
||||
case res_modified:
|
||||
/* give the hook another try */
|
||||
if (++loops < 42) /*doug adams*/
|
||||
break;
|
||||
/*FALLTHROUGH*/
|
||||
case res_error:
|
||||
/*FALLTHROUGH*/
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
} while (!done);
|
||||
|
||||
}
|
||||
return (resplen);
|
||||
next_ns: ;
|
||||
} /*foreach ns*/
|
||||
} /*foreach retry*/
|
||||
res_close();
|
||||
if (!v_circuit) {
|
||||
if (!gotsomewhere)
|
||||
errno = ECONNREFUSED; /* no nameservers found */
|
||||
else
|
||||
errno = ETIMEDOUT; /* no answer obtained */
|
||||
} else
|
||||
errno = terrno;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine is for closing the socket if a virtual circuit is used and
|
||||
* the program wants to close it. This provides support for endhostent()
|
||||
* which expects to close the socket.
|
||||
*
|
||||
* This routine is not expected to be user visible.
|
||||
*/
|
||||
void
|
||||
res_close()
|
||||
{
|
||||
if (s >= 0) {
|
||||
(void) close(s);
|
||||
s = -1;
|
||||
connected = 0;
|
||||
vc = 0;
|
||||
af = 0;
|
||||
}
|
||||
}
|
175
src/kits/network/libnet/select.c
Normal file
175
src/kits/network/libnet/select.c
Normal file
@ -0,0 +1,175 @@
|
||||
#include <unistd.h>
|
||||
#include <kernel/image.h>
|
||||
#include <kernel/OS.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/select.h>
|
||||
#include <posix/errno.h>
|
||||
|
||||
#include "net_stack_driver.h"
|
||||
|
||||
#ifndef BONE_VERSION
|
||||
|
||||
static int fd_set_count(fd_set * bits, int nbits)
|
||||
{
|
||||
int count;
|
||||
int fd;
|
||||
|
||||
count = 0;
|
||||
for (fd = 0; fd < nbits; fd++)
|
||||
if (FD_ISSET(fd, bits))
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
_EXPORT int select(int nbits, struct fd_set * rbits,
|
||||
struct fd_set * wbits,
|
||||
struct fd_set * ebits,
|
||||
struct timeval * tv)
|
||||
{
|
||||
int fd;
|
||||
int n;
|
||||
struct select_args args;
|
||||
status_t status;
|
||||
area_id area;
|
||||
struct r5_selectsync * rss;
|
||||
|
||||
#define ROUND_TO_PAGE_SIZE(x) (((x) + (B_PAGE_SIZE) - 1) & ~((B_PAGE_SIZE) - 1))
|
||||
|
||||
// We share a area with the fd_set on it with the network stack code.
|
||||
// The r5_notify_select_event in the net_stack_driver code will fill it and wakeup us
|
||||
// when a event raise.
|
||||
|
||||
area = create_area("r5_selectsync", (void **) &rss,
|
||||
B_ANY_ADDRESS, ROUND_TO_PAGE_SIZE(sizeof(*rss)), B_NO_LOCK,
|
||||
B_READ_AREA | B_WRITE_AREA);
|
||||
if (area < B_OK) {
|
||||
errno = area;
|
||||
return -1;
|
||||
};
|
||||
|
||||
// The area is multi-thread protected by a semaphore locker
|
||||
rss->lock = create_sem(1, "r5_selectsync_lock");
|
||||
if (rss->lock < B_OK) {
|
||||
errno = rss->lock;
|
||||
goto error;
|
||||
};
|
||||
|
||||
// Create the wakeup call semaphore
|
||||
rss->wakeup = create_sem(0, "r5_selectsync_wakeup");
|
||||
if (rss->wakeup < B_OK) {
|
||||
errno = rss->wakeup;
|
||||
goto error;
|
||||
};
|
||||
|
||||
FD_ZERO(&rss->rbits);
|
||||
FD_ZERO(&rss->wbits);
|
||||
FD_ZERO(&rss->ebits);
|
||||
|
||||
/* Beware, ugly hacky hack: we pass the area_id of our shared r5_selectsync,
|
||||
that net_stack_driver should udate directly
|
||||
*/
|
||||
args.sync = (struct selectsync *) area;
|
||||
|
||||
/* call, indirectly, net_stack_select() for each event to monitor
|
||||
* as we are not the vfs, we can't call this device hook ourself, but
|
||||
* our NET_STACK_SELECT opcode would do it for us...
|
||||
*/
|
||||
n = 0;
|
||||
for (fd = 0; fd < nbits; fd++) {
|
||||
if (rbits && FD_ISSET(fd, rbits)) {
|
||||
args.ref = (fd << 8) | 1;
|
||||
if (ioctl(fd, NET_STACK_SELECT, &args, sizeof(args)) >= 0)
|
||||
n++;
|
||||
};
|
||||
if (wbits && FD_ISSET(fd, wbits)) {
|
||||
args.ref = (fd << 8) | 2;
|
||||
if (ioctl(fd, NET_STACK_SELECT, &args, sizeof(args)) >= 0)
|
||||
n++;
|
||||
};
|
||||
if (ebits && FD_ISSET(fd, ebits)) {
|
||||
args.ref = (fd << 8) | 3;
|
||||
if (ioctl(fd, NET_STACK_SELECT, &args, sizeof(args)) >= 0)
|
||||
n++;
|
||||
};
|
||||
}
|
||||
|
||||
if (n < 1) {
|
||||
// TODO: maybe we could hack a workaround for select() on file/dev here:
|
||||
// If no fd handle the NET_STACK_SELECT, assume they're files, so always
|
||||
// readable and writable?
|
||||
errno = B_BAD_VALUE;
|
||||
n = -1;
|
||||
goto error;
|
||||
};
|
||||
|
||||
// Okay, now wait for our wakeup call.
|
||||
// Maybe his's already there, even... (when the select event is already raised)
|
||||
if (tv) {
|
||||
bigtime_t timeout;
|
||||
|
||||
timeout = tv->tv_sec * 1000000 + tv->tv_usec;
|
||||
status = acquire_sem_etc(rss->wakeup, 1, B_RELATIVE_TIMEOUT | B_CAN_INTERRUPT, timeout);
|
||||
} else
|
||||
status = acquire_sem(rss->wakeup);
|
||||
|
||||
// we don't need it anymore, and we say "select() party is over" that way, too :-)
|
||||
delete_sem(rss->lock);
|
||||
delete_sem(rss->wakeup);
|
||||
rss->lock = rss->wakeup = -1;
|
||||
|
||||
// unregister socket event notification
|
||||
for(fd = 0; fd < nbits; fd++) {
|
||||
if (rbits && FD_ISSET(fd, rbits)) {
|
||||
args.ref = (fd << 8) | 1;
|
||||
ioctl(fd, NET_STACK_DESELECT, &args, sizeof(args));
|
||||
};
|
||||
if (wbits && FD_ISSET(fd, wbits)) {
|
||||
args.ref = (fd << 8) | 2;
|
||||
ioctl(fd, NET_STACK_DESELECT, &args, sizeof(args));
|
||||
};
|
||||
if (ebits && FD_ISSET(fd, ebits)) {
|
||||
args.ref = (fd << 8) | 3;
|
||||
ioctl(fd, NET_STACK_DESELECT, &args, sizeof(args));
|
||||
};
|
||||
};
|
||||
|
||||
// Okay, what the final result?
|
||||
switch (status) {
|
||||
case B_OK:
|
||||
case B_WOULD_BLOCK:
|
||||
case B_TIMED_OUT: // logicly, 'n' should stay to 0 in this case...
|
||||
n = 0;
|
||||
if (rbits) {
|
||||
memcpy(rbits, &rss->rbits, sizeof(*rbits));
|
||||
n += fd_set_count(rbits, nbits);
|
||||
};
|
||||
if (wbits) {
|
||||
memcpy(wbits, &rss->wbits, sizeof(*wbits));
|
||||
n += fd_set_count(wbits, nbits);
|
||||
};
|
||||
if (ebits) {
|
||||
memcpy(ebits, &rss->ebits, sizeof(*ebits));
|
||||
n += fd_set_count(ebits, nbits);
|
||||
};
|
||||
break;
|
||||
|
||||
default:
|
||||
errno = status;
|
||||
n = -1;
|
||||
break;
|
||||
};
|
||||
|
||||
error:
|
||||
if (rss->lock >= 0)
|
||||
delete_sem(rss->lock);
|
||||
if (rss->wakeup >= 0)
|
||||
delete_sem(rss->wakeup);
|
||||
|
||||
delete_area(area);
|
||||
return n;
|
||||
}
|
||||
|
||||
#endif
|
56
src/kits/network/libnet/sethostent.c
Normal file
56
src/kits/network/libnet/sethostent.c
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <netdb.h>
|
||||
#include <resolv.h>
|
||||
|
||||
void
|
||||
sethostent(stayopen)
|
||||
int stayopen;
|
||||
{
|
||||
|
||||
if ((_res.options & RES_INIT) == 0 && res_init() == -1)
|
||||
return;
|
||||
if (stayopen)
|
||||
_res.options |= RES_STAYOPEN | RES_USEVC;
|
||||
}
|
||||
|
||||
void
|
||||
endhostent()
|
||||
{
|
||||
_res.options &= ~(RES_STAYOPEN | RES_USEVC);
|
||||
res_close();
|
||||
}
|
476
src/kits/network/libnet/socket.c
Normal file
476
src/kits/network/libnet/socket.c
Normal file
@ -0,0 +1,476 @@
|
||||
/* socket.c */
|
||||
|
||||
/* This is a very simple little shared library that acts as a wrapper
|
||||
* for our device/kernel stack!
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <kernel/OS.h>
|
||||
#include <iovec.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "sys/socket.h"
|
||||
#include "sys/sockio.h"
|
||||
#include "netinet/in.h"
|
||||
|
||||
#include "net_stack_driver.h"
|
||||
|
||||
const char *g_stack_driver_path = "/dev/" NET_STACK_DRIVER_PATH;
|
||||
|
||||
bool g_beos_r5_compatibility = false;
|
||||
|
||||
struct beosr5_sockaddr_in {
|
||||
uint16 sin_family;
|
||||
uint16 sin_port;
|
||||
uint32 sin_addr;
|
||||
char sin_zero[4];
|
||||
};
|
||||
|
||||
static void convert_from_beos_r5_sockaddr(struct sockaddr *to, const struct sockaddr *from);
|
||||
static void convert_to_beos_r5_sockaddr(struct sockaddr *to, const struct sockaddr *from);
|
||||
static void convert_from_beos_r5_sockopt(int *level, int *optnum);
|
||||
|
||||
_EXPORT int socket(int family, int type, int protocol)
|
||||
{
|
||||
int sock;
|
||||
int rv;
|
||||
struct socket_args args;
|
||||
|
||||
sock = open(g_stack_driver_path, O_RDWR);
|
||||
if (sock < 0)
|
||||
return sock;
|
||||
|
||||
/* work around the old Be header values... *
|
||||
*
|
||||
* This really sucks...
|
||||
*
|
||||
* Basically we've modified the new stack SOCK_ values to be
|
||||
* start at 10, so if it's below that we're being called by
|
||||
* an R5 app.
|
||||
*
|
||||
* NB
|
||||
* Of course this places a lot of restrictions on what we can
|
||||
* do with library replacements and improvements as no other
|
||||
* component of the "team" can be built using the new
|
||||
* stack.
|
||||
*/
|
||||
if (type < SOCK_DGRAM) {
|
||||
g_beos_r5_compatibility = true;
|
||||
/* we have old be types... convert... */
|
||||
if (type == 1)
|
||||
type = SOCK_DGRAM;
|
||||
else if (type == 2)
|
||||
type = SOCK_STREAM;
|
||||
|
||||
if (protocol == 1)
|
||||
protocol = IPPROTO_UDP;
|
||||
else if (protocol == 2)
|
||||
protocol = IPPROTO_TCP;
|
||||
else if (protocol == 3)
|
||||
protocol = IPPROTO_ICMP;
|
||||
|
||||
/* also convert AF_INET */
|
||||
if (family == 1)
|
||||
family = AF_INET;
|
||||
};
|
||||
|
||||
args.family = family;
|
||||
args.type = type;
|
||||
args.proto = protocol;
|
||||
|
||||
rv = ioctl(sock, NET_STACK_SOCKET, &args, sizeof(args));
|
||||
if (rv < 0) {
|
||||
close(sock);
|
||||
return rv;
|
||||
};
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
|
||||
_EXPORT int bind(int sock, const struct sockaddr *addr, int addrlen)
|
||||
{
|
||||
struct sockaddr temp;
|
||||
struct sockaddr_args args;
|
||||
|
||||
if (g_beos_r5_compatibility) {
|
||||
convert_from_beos_r5_sockaddr(&temp, addr);
|
||||
addr = &temp;
|
||||
addrlen = sizeof(struct sockaddr_in);
|
||||
}
|
||||
|
||||
args.addr = (struct sockaddr *) addr;
|
||||
args.addrlen = addrlen;
|
||||
|
||||
return ioctl(sock, NET_STACK_BIND, &args, sizeof(args));
|
||||
}
|
||||
|
||||
|
||||
_EXPORT int shutdown(int sock, int how)
|
||||
{
|
||||
struct int_args args;
|
||||
|
||||
args.value = how;
|
||||
|
||||
return ioctl(sock, NET_STACK_SHUTDOWN, &args, sizeof(args));
|
||||
}
|
||||
|
||||
|
||||
_EXPORT int connect(int sock, const struct sockaddr *addr, int addrlen)
|
||||
{
|
||||
struct sockaddr temp;
|
||||
struct sockaddr_args args;
|
||||
|
||||
if (g_beos_r5_compatibility) {
|
||||
convert_from_beos_r5_sockaddr(&temp, addr);
|
||||
addr = &temp;
|
||||
addrlen = sizeof(struct sockaddr_in);
|
||||
}
|
||||
|
||||
args.addr = (struct sockaddr *) addr;
|
||||
args.addrlen = addrlen;
|
||||
|
||||
return ioctl(sock, NET_STACK_CONNECT, &args, sizeof(args));
|
||||
}
|
||||
|
||||
|
||||
_EXPORT int listen(int sock, int backlog)
|
||||
{
|
||||
struct int_args args;
|
||||
|
||||
args.value = backlog;
|
||||
|
||||
return ioctl(sock, NET_STACK_LISTEN, &args, sizeof(args));
|
||||
}
|
||||
|
||||
|
||||
_EXPORT int accept(int sock, struct sockaddr *addr, int *addrlen)
|
||||
{
|
||||
struct sockaddr temp;
|
||||
struct accept_args args;
|
||||
int rv;
|
||||
int new_sock;
|
||||
void *cookie;
|
||||
|
||||
new_sock = open(g_stack_driver_path, O_RDWR);
|
||||
if (new_sock < 0)
|
||||
return new_sock;
|
||||
|
||||
// The network stack driver will need to know to which net_stack_cookie to
|
||||
// *bind* with the new accepted socket. He can't know himself find out
|
||||
// the net_stack_cookie of our new_sock file descriptor, the just open() one...
|
||||
// So, here, we ask him the net_stack_cookie value for our fd... :-)
|
||||
rv = ioctl(new_sock, NET_STACK_GET_COOKIE, &cookie);
|
||||
if (rv < 0) {
|
||||
close(new_sock);
|
||||
return rv;
|
||||
};
|
||||
|
||||
args.cookie = cookie; // this way driver can use the right fd/cookie for the new_sock!
|
||||
|
||||
args.addr = g_beos_r5_compatibility ? &temp : addr;
|
||||
args.addrlen = g_beos_r5_compatibility ? sizeof(temp) : *addrlen;
|
||||
|
||||
rv = ioctl(sock, NET_STACK_ACCEPT, &args, sizeof(args));
|
||||
if (rv < 0) {
|
||||
close(new_sock);
|
||||
return rv;
|
||||
};
|
||||
|
||||
if (g_beos_r5_compatibility) {
|
||||
convert_to_beos_r5_sockaddr(addr, &temp);
|
||||
*addrlen = sizeof(struct beosr5_sockaddr_in);
|
||||
} else
|
||||
*addrlen = args.addrlen;
|
||||
|
||||
return new_sock;
|
||||
}
|
||||
|
||||
|
||||
_EXPORT ssize_t recvfrom(int sock, void *buffer, size_t buflen, int flags,
|
||||
struct sockaddr *addr, size_t *addrlen)
|
||||
{
|
||||
struct sockaddr temp;
|
||||
struct msghdr mh;
|
||||
struct iovec iov;
|
||||
int rv;
|
||||
|
||||
/* XXX - would this be better done as scatter gather? */
|
||||
mh.msg_name = g_beos_r5_compatibility ? (caddr_t)&temp : (caddr_t)addr;
|
||||
mh.msg_namelen = g_beos_r5_compatibility ? sizeof(temp) : addrlen ? *addrlen : 0;
|
||||
mh.msg_flags = flags;
|
||||
mh.msg_control = NULL;
|
||||
mh.msg_controllen = 0;
|
||||
iov.iov_base = buffer;
|
||||
iov.iov_len = buflen;
|
||||
mh.msg_iov = &iov;
|
||||
mh.msg_iovlen = 1;
|
||||
|
||||
rv = ioctl(sock, NET_STACK_RECVFROM, &mh, sizeof(mh));
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
if (g_beos_r5_compatibility && addr)
|
||||
convert_to_beos_r5_sockaddr(addr, &temp);
|
||||
|
||||
if (addrlen) {
|
||||
if (g_beos_r5_compatibility)
|
||||
*addrlen = sizeof(struct beosr5_sockaddr_in);
|
||||
else
|
||||
*addrlen = mh.msg_namelen;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
_EXPORT ssize_t sendto(int sock, const void *buffer, size_t buflen, int flags,
|
||||
const struct sockaddr *addr, size_t addrlen)
|
||||
{
|
||||
struct sockaddr temp;
|
||||
struct msghdr mh;
|
||||
struct iovec iov;
|
||||
|
||||
if (g_beos_r5_compatibility) {
|
||||
convert_from_beos_r5_sockaddr(&temp, addr);
|
||||
addr = &temp;
|
||||
addrlen = sizeof(struct sockaddr_in);
|
||||
}
|
||||
|
||||
/* XXX - would this be better done as scatter gather? */
|
||||
mh.msg_name = (caddr_t)addr;
|
||||
mh.msg_namelen = addrlen;
|
||||
mh.msg_flags = flags;
|
||||
mh.msg_control = NULL;
|
||||
mh.msg_controllen = 0;
|
||||
iov.iov_base = (caddr_t)buffer;
|
||||
iov.iov_len = buflen;
|
||||
mh.msg_iov = &iov;
|
||||
mh.msg_iovlen = 1;
|
||||
|
||||
return ioctl(sock, NET_STACK_SENDTO, &mh, sizeof(mh));
|
||||
}
|
||||
|
||||
|
||||
/* These need to be adjusted to take account of the MSG_PEEK
|
||||
* flag, but old R5 doesn't use it...
|
||||
*/
|
||||
_EXPORT ssize_t recv(int sock, void *data, size_t datalen, int flags)
|
||||
{
|
||||
struct data_xfer_args args;
|
||||
int rv;
|
||||
|
||||
args.data = data;
|
||||
args.datalen = datalen;
|
||||
args.flags = flags;
|
||||
args.addr = NULL;
|
||||
args.addrlen = 0;
|
||||
|
||||
rv = ioctl(sock, NET_STACK_RECV, &args, sizeof(args));
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
return args.datalen;
|
||||
}
|
||||
|
||||
|
||||
_EXPORT ssize_t send(int sock, const void *data, size_t datalen, int flags)
|
||||
{
|
||||
struct data_xfer_args args;
|
||||
int rv;
|
||||
|
||||
args.data = (void *) data;
|
||||
args.datalen = datalen;
|
||||
args.flags = flags;
|
||||
args.addr = NULL;
|
||||
args.addrlen = 0;
|
||||
|
||||
rv = ioctl(sock, NET_STACK_SEND, &args, sizeof(args));
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
return args.datalen;
|
||||
}
|
||||
|
||||
|
||||
_EXPORT int getsockopt(int sock, int level, int option, void *optval, size_t *optlen)
|
||||
{
|
||||
struct sockopt_args args;
|
||||
int rv;
|
||||
|
||||
if (g_beos_r5_compatibility && option == 5) { // BeOS R5 SO_FIONREAD
|
||||
status_t rv;
|
||||
int temp;
|
||||
rv = ioctl(sock, FIONREAD, &temp);
|
||||
*(int*) optval = temp;
|
||||
*optlen = sizeof(temp);
|
||||
return rv;
|
||||
};
|
||||
|
||||
if (g_beos_r5_compatibility)
|
||||
convert_from_beos_r5_sockopt(&level, &option);
|
||||
|
||||
args.level = level;
|
||||
args.option = option;
|
||||
args.optval = optval;
|
||||
args.optlen = *optlen;
|
||||
|
||||
rv = ioctl(sock, NET_STACK_GETSOCKOPT, &args, sizeof(args));
|
||||
if (rv ==0)
|
||||
*optlen = args.optlen;
|
||||
return rv;
|
||||
}
|
||||
|
||||
_EXPORT int setsockopt(int sock, int level, int option, const void *optval, size_t optlen)
|
||||
{
|
||||
struct sockopt_args args;
|
||||
|
||||
/* BeOS R5 uses
|
||||
* setsockopt(sock, SOL_SOCKET, SO_NONBLOCK, &i, sizeof(i));
|
||||
* Try to capture that here and the do the correct thing.
|
||||
*/
|
||||
if (g_beos_r5_compatibility && option == 3) {
|
||||
int temp = *(int*) optval;
|
||||
return ioctl(sock, FIONBIO, &temp);
|
||||
}
|
||||
|
||||
if (g_beos_r5_compatibility)
|
||||
convert_from_beos_r5_sockopt(&level, &option);
|
||||
|
||||
args.level = level;
|
||||
args.option = option;
|
||||
args.optval = (void *) optval;
|
||||
args.optlen = optlen;
|
||||
|
||||
return ioctl(sock, NET_STACK_SETSOCKOPT, &args, sizeof(args));
|
||||
}
|
||||
|
||||
_EXPORT int getpeername(int sock, struct sockaddr *addr, int *addrlen)
|
||||
{
|
||||
struct sockaddr temp;
|
||||
struct sockaddr_args args;
|
||||
int rv;
|
||||
|
||||
args.addr = g_beos_r5_compatibility ? &temp : addr;
|
||||
args.addrlen = g_beos_r5_compatibility ? sizeof(temp) : *addrlen;
|
||||
|
||||
rv = ioctl(sock, NET_STACK_GETPEERNAME, &args, sizeof(args));
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
if (g_beos_r5_compatibility) {
|
||||
convert_to_beos_r5_sockaddr(addr, &temp);
|
||||
*addrlen = sizeof(struct beosr5_sockaddr_in);
|
||||
} else
|
||||
*addrlen = args.addrlen;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
_EXPORT int getsockname(int sock, struct sockaddr *addr, int *addrlen)
|
||||
{
|
||||
struct sockaddr temp;
|
||||
struct sockaddr_args args;
|
||||
int rv;
|
||||
|
||||
args.addr = g_beos_r5_compatibility ? &temp : addr;
|
||||
args.addrlen = g_beos_r5_compatibility ? sizeof(temp) : *addrlen;
|
||||
|
||||
rv = ioctl(sock, NET_STACK_GETSOCKNAME, &args, sizeof(args));
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
if (g_beos_r5_compatibility) {
|
||||
convert_to_beos_r5_sockaddr(addr, &temp);
|
||||
*addrlen = sizeof(struct beosr5_sockaddr_in);
|
||||
} else
|
||||
*addrlen = args.addrlen;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
_EXPORT int sysctl (int *name, uint namelen, void *oldp, size_t *oldlenp,
|
||||
void *newp, size_t newlen)
|
||||
{
|
||||
int s;
|
||||
struct sysctl_args sa;
|
||||
int rv;
|
||||
|
||||
s = socket(PF_ROUTE, SOCK_RAW, 0);
|
||||
if (s < 0)
|
||||
return s;
|
||||
|
||||
sa.name = name;
|
||||
sa.namelen = namelen;
|
||||
sa.oldp = oldp;
|
||||
sa.oldlenp = oldlenp;
|
||||
sa.newp = newp;
|
||||
sa.newlen = newlen;
|
||||
|
||||
rv = ioctl(s, NET_STACK_SYSCTL, &sa, sizeof(sa));
|
||||
|
||||
close(s);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Private routines
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
static void convert_from_beos_r5_sockaddr(struct sockaddr *_to, const struct sockaddr *_from)
|
||||
{
|
||||
const struct beosr5_sockaddr_in *from = (struct beosr5_sockaddr_in *)_from;
|
||||
struct sockaddr_in *to = (struct sockaddr_in *)_to;
|
||||
memset(to, 0, sizeof(*to));
|
||||
to->sin_len = sizeof(*to);
|
||||
if (from->sin_family == 1)
|
||||
to->sin_family = AF_INET;
|
||||
else
|
||||
to->sin_family = from->sin_family;
|
||||
to->sin_port = from->sin_port;
|
||||
to->sin_addr.s_addr = from->sin_addr;
|
||||
}
|
||||
|
||||
static void convert_to_beos_r5_sockaddr(struct sockaddr *_to, const struct sockaddr *_from)
|
||||
{
|
||||
const struct sockaddr_in *from = (struct sockaddr_in *)_from;
|
||||
struct beosr5_sockaddr_in *to = (struct beosr5_sockaddr_in *)_to;
|
||||
memset(to, 0, sizeof(*to));
|
||||
if (from->sin_family == AF_INET)
|
||||
to->sin_family = 1;
|
||||
else
|
||||
to->sin_family = from->sin_family;
|
||||
to->sin_port = from->sin_port;
|
||||
to->sin_addr = from->sin_addr.s_addr;
|
||||
}
|
||||
|
||||
static void convert_from_beos_r5_sockopt(int *level, int *optnum)
|
||||
{
|
||||
if (*level == 1)
|
||||
*level = SOL_SOCKET;
|
||||
|
||||
switch (*optnum) {
|
||||
case 1:
|
||||
*optnum = SO_DEBUG;
|
||||
break;
|
||||
case 2:
|
||||
*optnum = SO_REUSEADDR;
|
||||
break;
|
||||
/*
|
||||
case 3:
|
||||
*optnum = SO_NONBLOCK;
|
||||
break;
|
||||
*/
|
||||
case 4:
|
||||
*optnum = SO_REUSEPORT;
|
||||
break;
|
||||
/*
|
||||
case 5:
|
||||
*optnum = SO_FIONREAD;
|
||||
break;
|
||||
*/
|
||||
};
|
||||
}
|
14
src/kits/network/libnetapi/Jamfile
Normal file
14
src/kits/network/libnetapi/Jamfile
Normal file
@ -0,0 +1,14 @@
|
||||
SubDir OBOS_TOP src kits net libnetapi ;
|
||||
|
||||
UsePosixHeaders ;
|
||||
|
||||
SharedLibrary netapi :
|
||||
NetEndpoint.cpp
|
||||
NetAddress.cpp
|
||||
NetBuffer.cpp
|
||||
NetDebug.cpp
|
||||
;
|
||||
|
||||
LinkSharedOSLibs libnetapi.so :
|
||||
root
|
||||
;
|
181
src/kits/network/libnetapi/NetAddress.cpp
Normal file
181
src/kits/network/libnetapi/NetAddress.cpp
Normal file
@ -0,0 +1,181 @@
|
||||
/******************************************************************************
|
||||
/
|
||||
/ File: NetAddress.cpp
|
||||
/
|
||||
/ Description: The Network API.
|
||||
/
|
||||
/ Copyright 2002, OpenBeOS Project, All Rights Reserved.
|
||||
/
|
||||
******************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include "NetAddress.h"
|
||||
|
||||
BNetAddress::BNetAddress(BMessage *archive)
|
||||
: fStatus(B_OK),
|
||||
fName()
|
||||
{
|
||||
// TODO
|
||||
fStatus = B_ERROR;
|
||||
}
|
||||
|
||||
BNetAddress::~BNetAddress()
|
||||
{
|
||||
}
|
||||
|
||||
status_t BNetAddress::Archive(BMessage *into, bool deep) const
|
||||
{
|
||||
// TODO
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
BArchivable *BNetAddress::Instantiate(BMessage *archive)
|
||||
{
|
||||
// TODO
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BNetAddress::BNetAddress(const char * hostname, unsigned short port)
|
||||
: fStatus(B_OK),
|
||||
fName()
|
||||
{
|
||||
fStatus = SetTo(hostname, port);
|
||||
}
|
||||
|
||||
BNetAddress::BNetAddress(const sockaddr_in & address)
|
||||
: fStatus(B_OK),
|
||||
fName()
|
||||
{
|
||||
fStatus = SetTo(address);
|
||||
}
|
||||
|
||||
BNetAddress::BNetAddress(in_addr address, int port)
|
||||
: fStatus(B_OK),
|
||||
fName()
|
||||
{
|
||||
fStatus = SetTo(address, port);
|
||||
}
|
||||
|
||||
BNetAddress::BNetAddress(uint32 address, int port)
|
||||
: fStatus(B_OK),
|
||||
fName()
|
||||
{
|
||||
fStatus = SetTo(address, port);
|
||||
}
|
||||
|
||||
BNetAddress::BNetAddress(const BNetAddress & address)
|
||||
: fStatus(B_OK),
|
||||
fName(address.fName)
|
||||
{
|
||||
}
|
||||
|
||||
BNetAddress::BNetAddress(const char * hostname,
|
||||
const char * protocol,
|
||||
const char * service)
|
||||
: fStatus(B_OK),
|
||||
fName()
|
||||
{
|
||||
fStatus = SetTo(hostname, protocol, service);
|
||||
}
|
||||
|
||||
BNetAddress & BNetAddress::operator = (const BNetAddress & address)
|
||||
{
|
||||
fName = address.fName;
|
||||
return *this;
|
||||
}
|
||||
|
||||
status_t BNetAddress::InitCheck() const
|
||||
{
|
||||
return fStatus;
|
||||
}
|
||||
|
||||
|
||||
status_t BNetAddress::SetTo(const char * hostname, const char * protocol,
|
||||
const char * service)
|
||||
{
|
||||
struct hostent *host = gethostbyname(hostname);
|
||||
struct servent *serv = getservbyname(service, protocol);
|
||||
|
||||
if (host != NULL && serv != NULL) {
|
||||
fName.sin_family = host->h_addrtype;
|
||||
fName.sin_port = serv->s_port;
|
||||
fName.sin_addr = *((in_addr *) host->h_addr);
|
||||
return B_OK;
|
||||
}
|
||||
else {
|
||||
fName.sin_family = AF_UNSPEC;
|
||||
fName.sin_port = 0;
|
||||
fName.sin_addr.s_addr = INADDR_ANY;
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
status_t BNetAddress::SetTo(const char * hostname, unsigned short port)
|
||||
{
|
||||
struct hostent *host;
|
||||
|
||||
if (hostname != NULL && (host = gethostbyname(hostname)) != NULL) {
|
||||
fName.sin_family = host->h_addrtype;
|
||||
fName.sin_port = htons(port);
|
||||
fName.sin_addr = *((in_addr *) host->h_addr);
|
||||
return B_OK;
|
||||
}
|
||||
else {
|
||||
fName.sin_family = AF_UNSPEC;
|
||||
fName.sin_port = 0;
|
||||
fName.sin_addr.s_addr = INADDR_ANY;
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
status_t BNetAddress::SetTo(const sockaddr_in & address)
|
||||
{
|
||||
fName = address;
|
||||
return (fName.sin_family != AF_UNSPEC ? B_OK : B_ERROR);
|
||||
}
|
||||
|
||||
status_t BNetAddress::SetTo(in_addr address, int port)
|
||||
{
|
||||
fName.sin_family = AF_INET;
|
||||
fName.sin_port = port;
|
||||
fName.sin_addr = address;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t BNetAddress::SetTo(uint32 address, int port)
|
||||
{
|
||||
fName.sin_family = AF_INET;
|
||||
fName.sin_port = port;
|
||||
fName.sin_addr.s_addr = address;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t BNetAddress::GetAddr(char * hostname = 0, unsigned short * port = 0) const
|
||||
{
|
||||
struct hostent *host = gethostbyaddr((const char *) &fName.sin_addr,
|
||||
sizeof(fName.sin_addr), fName.sin_family);
|
||||
if (host != NULL) {
|
||||
strcpy(hostname, host->h_name);
|
||||
if (port != 0)
|
||||
*port = ntohs(fName.sin_port);
|
||||
return B_OK;
|
||||
}
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
status_t BNetAddress::GetAddr(sockaddr_in & address) const
|
||||
{
|
||||
address = fName;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t BNetAddress::GetAddr(in_addr & address, unsigned short * port) const
|
||||
{
|
||||
address = fName.sin_addr;
|
||||
if (port != 0)
|
||||
*port = ntohs(fName.sin_port);
|
||||
return B_OK;
|
||||
}
|
257
src/kits/network/libnetapi/NetBuffer.cpp
Normal file
257
src/kits/network/libnetapi/NetBuffer.cpp
Normal file
@ -0,0 +1,257 @@
|
||||
/******************************************************************************
|
||||
/
|
||||
/ File: NetBuffer.cpp
|
||||
/
|
||||
/ Description: The Network API.
|
||||
/
|
||||
/ Copyright 2002, OpenBeOS Project, All Rights Reserved.
|
||||
/
|
||||
******************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ByteOrder.h>
|
||||
#include "NetBuffer.h"
|
||||
|
||||
BNetBuffer::BNetBuffer(size_t size)
|
||||
: fStatus(B_OK),
|
||||
fData(NULL),
|
||||
fSize(0),
|
||||
fOffset(0)
|
||||
{
|
||||
fStatus = Resize(size);
|
||||
}
|
||||
|
||||
BNetBuffer::BNetBuffer(const BNetBuffer & buffer)
|
||||
: fStatus(B_OK),
|
||||
fData(NULL),
|
||||
fSize(0),
|
||||
fOffset(0)
|
||||
{
|
||||
fStatus = AppendData(buffer.Data(), buffer.Size());
|
||||
}
|
||||
|
||||
BNetBuffer::BNetBuffer(BMessage *archive)
|
||||
: fStatus(B_OK),
|
||||
fData(NULL),
|
||||
fSize(0),
|
||||
fOffset(0)
|
||||
{
|
||||
// TODO
|
||||
fStatus = B_ERROR;
|
||||
}
|
||||
|
||||
BNetBuffer::~BNetBuffer()
|
||||
{
|
||||
if (fData != NULL)
|
||||
free(fData);
|
||||
}
|
||||
|
||||
status_t BNetBuffer::Archive(BMessage *into, bool deep) const
|
||||
{
|
||||
// TODO
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
BArchivable *BNetBuffer::Instantiate(BMessage *archive)
|
||||
{
|
||||
// TODO
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BNetBuffer & BNetBuffer::operator = (const BNetBuffer & buffer)
|
||||
{
|
||||
Resize(0);
|
||||
AppendData(buffer.Data(), buffer.Size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
status_t BNetBuffer::InitCheck() const
|
||||
{
|
||||
return fStatus;
|
||||
}
|
||||
|
||||
const unsigned char * BNetBuffer::Data() const
|
||||
{
|
||||
return fData;
|
||||
}
|
||||
|
||||
unsigned char * BNetBuffer::Data()
|
||||
{
|
||||
return fData;
|
||||
}
|
||||
|
||||
size_t BNetBuffer::Size() const
|
||||
{
|
||||
return fSize;
|
||||
}
|
||||
|
||||
size_t BNetBuffer::BytesRemaining() const
|
||||
{
|
||||
return fSize - fOffset;
|
||||
}
|
||||
|
||||
status_t BNetBuffer::AppendInt8(int8 value)
|
||||
{
|
||||
return AppendData(&value, sizeof(value));
|
||||
}
|
||||
|
||||
status_t BNetBuffer::AppendUInt8(uint8 value)
|
||||
{
|
||||
return AppendData(&value, sizeof(value));
|
||||
}
|
||||
|
||||
status_t BNetBuffer::AppendInt16(int16 value)
|
||||
{
|
||||
value = B_HOST_TO_BENDIAN_INT16(value);
|
||||
return AppendData(&value, sizeof(value));
|
||||
}
|
||||
|
||||
status_t BNetBuffer::AppendUInt16(uint16 value)
|
||||
{
|
||||
value = B_HOST_TO_BENDIAN_INT16(value);
|
||||
return AppendData(&value, sizeof(value));
|
||||
}
|
||||
|
||||
status_t BNetBuffer::AppendInt32(int32 value)
|
||||
{
|
||||
value = B_HOST_TO_BENDIAN_INT32(value);
|
||||
return AppendData(&value, sizeof(value));
|
||||
}
|
||||
|
||||
status_t BNetBuffer::AppendUInt32(uint32 value)
|
||||
{
|
||||
value = B_HOST_TO_BENDIAN_INT32(value);
|
||||
return AppendData(&value, sizeof(value));
|
||||
}
|
||||
|
||||
status_t BNetBuffer::AppendFloat(float value)
|
||||
{
|
||||
return AppendData(&value, sizeof(value));
|
||||
}
|
||||
|
||||
status_t BNetBuffer::AppendDouble(double value)
|
||||
{
|
||||
return AppendData(&value, sizeof(value));
|
||||
}
|
||||
|
||||
status_t BNetBuffer::AppendString(const char * value)
|
||||
{
|
||||
return AppendData(value, strlen(value) + 1);
|
||||
}
|
||||
|
||||
status_t BNetBuffer::AppendData(const void * data, size_t length)
|
||||
{
|
||||
if (Resize(fSize + length) == B_OK) {
|
||||
memcpy(fData + fSize - length, data, length);
|
||||
return B_OK;
|
||||
}
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
status_t BNetBuffer::AppendInt64(int64 value)
|
||||
{
|
||||
value = B_HOST_TO_BENDIAN_INT64(value);
|
||||
return AppendData(&value, sizeof(value));
|
||||
}
|
||||
|
||||
status_t BNetBuffer::AppendUInt64(uint64 value)
|
||||
{
|
||||
value = B_HOST_TO_BENDIAN_INT64(value);
|
||||
return AppendData(&value, sizeof(value));
|
||||
}
|
||||
|
||||
status_t BNetBuffer::RemoveInt8(int8 & value)
|
||||
{
|
||||
return RemoveData(&value, sizeof(value));
|
||||
}
|
||||
|
||||
status_t BNetBuffer::RemoveUInt8(uint8 & value)
|
||||
{
|
||||
return RemoveData(&value, sizeof(value));
|
||||
}
|
||||
|
||||
status_t BNetBuffer::RemoveInt16(int16 & value)
|
||||
{
|
||||
status_t status = RemoveData(&value, sizeof(value));
|
||||
value = B_BENDIAN_TO_HOST_INT16(value);
|
||||
return status;
|
||||
}
|
||||
|
||||
status_t BNetBuffer::RemoveUInt16(uint16 & value)
|
||||
{
|
||||
status_t status = RemoveData(&value, sizeof(value));
|
||||
value = B_BENDIAN_TO_HOST_INT16(value);
|
||||
return status;
|
||||
}
|
||||
|
||||
status_t BNetBuffer::RemoveInt32(int32 & value)
|
||||
{
|
||||
status_t status = RemoveData(&value, sizeof(value));
|
||||
value = B_BENDIAN_TO_HOST_INT32(value);
|
||||
return status;
|
||||
}
|
||||
|
||||
status_t BNetBuffer::RemoveUInt32(uint32 & value)
|
||||
{
|
||||
status_t status = RemoveData(&value, sizeof(value));
|
||||
value = B_BENDIAN_TO_HOST_INT32(value);
|
||||
return status;
|
||||
}
|
||||
|
||||
status_t BNetBuffer::RemoveFloat(float & value)
|
||||
{
|
||||
return RemoveData(&value, sizeof(value));
|
||||
}
|
||||
|
||||
status_t BNetBuffer::RemoveDouble(double & value)
|
||||
{
|
||||
return RemoveData(&value, sizeof(value));
|
||||
}
|
||||
|
||||
status_t BNetBuffer::RemoveString(char * value, size_t length)
|
||||
{
|
||||
if (fOffset < fSize && length > 0) {
|
||||
while (--length > 0 && fOffset < fSize && fData[fOffset] != 0) {
|
||||
*value++ = fData[fOffset++];
|
||||
}
|
||||
*value = 0;
|
||||
return B_OK;
|
||||
}
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
status_t BNetBuffer::RemoveData(void * data, size_t length)
|
||||
{
|
||||
if (fOffset + length <= fSize) {
|
||||
memcpy(data, fData + fOffset, length);
|
||||
fOffset += length;
|
||||
return B_OK;
|
||||
}
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
status_t BNetBuffer::RemoveInt64(int64 & value)
|
||||
{
|
||||
status_t status = RemoveData(&value, sizeof(value));
|
||||
value = B_BENDIAN_TO_HOST_INT64(value);
|
||||
return status;
|
||||
}
|
||||
|
||||
status_t BNetBuffer::RemoveUInt64(uint64 & value)
|
||||
{
|
||||
status_t status = RemoveData(&value, sizeof(value));
|
||||
value = B_BENDIAN_TO_HOST_INT64(value);
|
||||
return status;
|
||||
}
|
||||
|
||||
status_t BNetBuffer::Resize(size_t size)
|
||||
{
|
||||
unsigned char * data = (unsigned char *) realloc(fData, (size + 16) & ~15);
|
||||
if (data != NULL || size == 0) {
|
||||
fData = data;
|
||||
fSize = size;
|
||||
return B_OK;
|
||||
}
|
||||
return B_ERROR;
|
||||
}
|
16
src/kits/network/libnetapi/NetDebug.cpp
Normal file
16
src/kits/network/libnetapi/NetDebug.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
#include <size_t.h>
|
||||
|
||||
#include "NetDebug.h"
|
||||
|
||||
void BNetDebug::Enable(bool) {
|
||||
}
|
||||
|
||||
bool BNetDebug::IsEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void BNetDebug::Print(const char *msg) {
|
||||
}
|
||||
|
||||
void BNetDebug::Dump(const char *data, size_t size, const char *title) {
|
||||
}
|
289
src/kits/network/libnetapi/NetEndpoint.cpp
Normal file
289
src/kits/network/libnetapi/NetEndpoint.cpp
Normal file
@ -0,0 +1,289 @@
|
||||
/******************************************************************************
|
||||
/
|
||||
/ File: NetEndpoint.cpp
|
||||
/
|
||||
/ Description: The Network API.
|
||||
/
|
||||
/ Copyright 2002, OpenBeOS Project, All Rights Reserved.
|
||||
/
|
||||
******************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include "NetEndpoint.h"
|
||||
|
||||
BNetEndpoint::BNetEndpoint(int protocol)
|
||||
: fStatus(B_OK),
|
||||
fSocket(0),
|
||||
fTimeout(B_INFINITE_TIMEOUT),
|
||||
fLocalAddr(),
|
||||
fRemoteAddr()
|
||||
{
|
||||
if ((fSocket = socket(AF_INET, protocol, 0)) < 0)
|
||||
fStatus = B_ERROR;
|
||||
}
|
||||
|
||||
BNetEndpoint::BNetEndpoint(int handle, bigtime_t timeout)
|
||||
: fStatus(B_OK),
|
||||
fSocket(0),
|
||||
fTimeout(timeout),
|
||||
fLocalAddr(),
|
||||
fRemoteAddr()
|
||||
{
|
||||
if ((fSocket = dup(handle)) < 0)
|
||||
fStatus = B_ERROR;
|
||||
}
|
||||
|
||||
BNetEndpoint::BNetEndpoint(const BNetEndpoint & endpoint)
|
||||
: fStatus(endpoint.fStatus),
|
||||
fSocket(endpoint.fSocket),
|
||||
fTimeout(endpoint.fTimeout),
|
||||
fLocalAddr(endpoint.fLocalAddr),
|
||||
fRemoteAddr(endpoint.fRemoteAddr)
|
||||
{
|
||||
}
|
||||
|
||||
BNetEndpoint::~BNetEndpoint()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
BNetEndpoint::BNetEndpoint(BMessage *archive)
|
||||
: fStatus(B_OK),
|
||||
fSocket(0),
|
||||
fTimeout(B_INFINITE_TIMEOUT),
|
||||
fLocalAddr(),
|
||||
fRemoteAddr()
|
||||
{
|
||||
// TODO
|
||||
fStatus = B_ERROR;
|
||||
}
|
||||
|
||||
status_t BNetEndpoint::Archive(BMessage *into, bool deep = true) const
|
||||
{
|
||||
// TODO
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
BArchivable *BNetEndpointInstantiate(BMessage *archive)
|
||||
{
|
||||
// TODO
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status_t BNetEndpoint::InitCheck() const
|
||||
{
|
||||
return fStatus;
|
||||
}
|
||||
|
||||
int BNetEndpoint::Socket() const
|
||||
{
|
||||
return fSocket;
|
||||
}
|
||||
|
||||
const BNetAddress & BNetEndpoint::LocalAddr() const
|
||||
{
|
||||
return fLocalAddr;
|
||||
}
|
||||
|
||||
const BNetAddress & BNetEndpoint::RemoteAddr() const
|
||||
{
|
||||
return fRemoteAddr;
|
||||
}
|
||||
|
||||
status_t BNetEndpoint::SetProtocol(int protocol)
|
||||
{
|
||||
Close();
|
||||
if ((fSocket = ::socket(AF_INET, protocol, 0)) < 0)
|
||||
return B_ERROR;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t BNetEndpoint::SetOption(int32 option, int32 level,
|
||||
const void * data, unsigned int length)
|
||||
{
|
||||
if (setsockopt(fSocket, level, option, data, length) < 0)
|
||||
return B_ERROR;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t BNetEndpoint::SetNonBlocking(bool enable)
|
||||
{
|
||||
int flags = fcntl(fSocket, F_GETFL);
|
||||
if (enable)
|
||||
flags |= O_NONBLOCK;
|
||||
else
|
||||
flags &= ~O_NONBLOCK;
|
||||
if (fcntl(fSocket, F_SETFL, flags) < 0)
|
||||
return B_ERROR;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t BNetEndpoint::SetReuseAddr(bool enable)
|
||||
{
|
||||
return SetOption(SO_REUSEADDR, SOL_SOCKET, &enable, sizeof(enable));
|
||||
}
|
||||
|
||||
void BNetEndpoint::SetTimeout(bigtime_t timeout)
|
||||
{
|
||||
fTimeout = timeout;
|
||||
}
|
||||
|
||||
status_t BNetEndpoint::Bind(const BNetAddress & address)
|
||||
{
|
||||
sockaddr_in addr;
|
||||
if (address.GetAddr(addr) == B_OK) {
|
||||
if (bind(fSocket, (sockaddr *) &addr, sizeof(addr)) >= 0) {
|
||||
sockaddr_in name;
|
||||
int length = sizeof(name);
|
||||
|
||||
if (getsockname(fSocket, (sockaddr *) &name, &length) >= 0)
|
||||
fLocalAddr.SetTo(name);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
status_t BNetEndpoint::Bind(int port)
|
||||
{
|
||||
char hostname[256];
|
||||
|
||||
if (gethostname(hostname, sizeof(hostname)) >= 0)
|
||||
return BNetEndpoint::Bind(BNetAddress(hostname, port));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
void BNetEndpoint::Close()
|
||||
{
|
||||
close(fSocket);
|
||||
fSocket = 0;
|
||||
}
|
||||
|
||||
status_t BNetEndpoint::Connect(const BNetAddress & address)
|
||||
{
|
||||
sockaddr_in addr;
|
||||
if (address.GetAddr(addr) == B_OK) {
|
||||
if (connect(fSocket, (sockaddr *) &addr, sizeof(addr)) >= 0) {
|
||||
sockaddr_in name;
|
||||
int length = sizeof(name);
|
||||
|
||||
if (getpeername(fSocket, (sockaddr *) &name, &length) >= 0)
|
||||
fRemoteAddr.SetTo(name);
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
status_t BNetEndpoint::Connect(const char * hostname, int port)
|
||||
{
|
||||
BNetAddress address(hostname, port);
|
||||
|
||||
return BNetEndpoint::Connect(address);
|
||||
}
|
||||
|
||||
status_t BNetEndpoint::Listen(int backlog)
|
||||
{
|
||||
if (listen(fSocket, backlog) < 0)
|
||||
return B_ERROR;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
BNetEndpoint *BNetEndpoint::Accept(int32 timeout)
|
||||
{
|
||||
if (IsDataPending(timeout < 0 ? B_INFINITE_TIMEOUT : 1000LL * timeout)) {
|
||||
sockaddr_in name;
|
||||
int length = sizeof(name);
|
||||
|
||||
int handle = accept(fSocket, (sockaddr *) &name, &length);
|
||||
if (handle >= 0) {
|
||||
BNetEndpoint * endpoint = new BNetEndpoint(handle, fTimeout);
|
||||
if (endpoint != NULL) {
|
||||
endpoint->fRemoteAddr.SetTo(name);
|
||||
if (getsockname(handle, (sockaddr *) &name, &length) >= 0)
|
||||
endpoint->fLocalAddr.SetTo(name);
|
||||
}
|
||||
return endpoint;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool BNetEndpoint::IsDataPending(bigtime_t timeout)
|
||||
{
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fSocket, &fds);
|
||||
|
||||
tv.tv_sec = timeout / 1000000;
|
||||
tv.tv_usec = (timeout % 1000000);
|
||||
|
||||
return (select(fSocket + 1, &fds, NULL, NULL, &tv) > 0);
|
||||
}
|
||||
|
||||
int32 BNetEndpoint::Receive(void * buffer, size_t length, int flags)
|
||||
{
|
||||
if (IsDataPending(fTimeout))
|
||||
return recv(fSocket, buffer, length, flags);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32 BNetEndpoint::Receive(BNetBuffer & buffer, size_t length, int flags)
|
||||
{
|
||||
BNetBuffer chunk(length);
|
||||
length = Receive(chunk.Data(), chunk.Size(), flags);
|
||||
buffer.AppendData(chunk.Data(), length);
|
||||
return length;
|
||||
}
|
||||
|
||||
int32 BNetEndpoint::ReceiveFrom(void * buffer, size_t length,
|
||||
const BNetAddress & address, int flags)
|
||||
{
|
||||
sockaddr_in addr;
|
||||
int addrlen = sizeof(addr);
|
||||
if (address.GetAddr(addr) == B_OK && IsDataPending(fTimeout))
|
||||
return recvfrom(fSocket, buffer, length, flags,
|
||||
(sockaddr *) &addr, &addrlen);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32 BNetEndpoint::ReceiveFrom(BNetBuffer & buffer,
|
||||
const BNetAddress & address, int flags)
|
||||
{
|
||||
return ReceiveFrom(buffer.Data(), buffer.Size(), address, flags);
|
||||
}
|
||||
|
||||
int32 BNetEndpoint::Send(const void * buffer, size_t length, int flags)
|
||||
{
|
||||
return send(fSocket, (const char *) buffer, length, flags);
|
||||
}
|
||||
|
||||
int32 BNetEndpoint::Send(const BNetBuffer & buffer, int flags)
|
||||
{
|
||||
return Send(buffer.Data(), buffer.Size(), flags);
|
||||
}
|
||||
|
||||
int32 BNetEndpoint::SendTo(const void * buffer, size_t length,
|
||||
const BNetAddress & address, int flags)
|
||||
{
|
||||
sockaddr_in addr;
|
||||
address.GetAddr(addr);
|
||||
return sendto(fSocket, buffer, length, flags,
|
||||
(sockaddr *) &addr, sizeof(addr));
|
||||
}
|
||||
|
||||
int32 BNetEndpoint::SendTo(const BNetBuffer & buffer,
|
||||
const BNetAddress & address, int flags)
|
||||
{
|
||||
return SendTo(buffer.Data(), buffer.Size(), address, flags);
|
||||
}
|
Loading…
Reference in New Issue
Block a user