Initial revision

This commit is contained in:
Ben Gras
2005-04-21 14:53:53 +00:00
commit 9865aeaa79
2264 changed files with 411685 additions and 0 deletions
+151
View File
@@ -0,0 +1,151 @@
# Makefile for lib/ip.
#
# Note: The oneC_sum.c file is not used if there is an assembly equivalent.
CFLAGS = -O -D_MINIX -D_POSIX_SOURCE -I. -DNDEBUG
CC1 = $(CC) $(CFLAGS) -c
MAKE = exec make -$(MAKEFLAGS)
LIBRARY = ../libc.a
all: $(LIBRARY)
OBJECTS = \
$(LIBRARY)(dhcp_gettag.o) \
$(LIBRARY)(dhcp_settag.o) \
$(LIBRARY)(ether_line.o) \
$(LIBRARY)(ethera2n.o) \
$(LIBRARY)(ethere2a.o) \
$(LIBRARY)(etherh2n.o) \
$(LIBRARY)(ethern2h.o) \
$(LIBRARY)(getdomain.o) \
$(LIBRARY)(gethnmadr.o) \
$(LIBRARY)(gethostent.o) \
$(LIBRARY)(gethostname.o) \
$(LIBRARY)(getnetent.o) \
$(LIBRARY)(getnetbyname.o) \
$(LIBRARY)(getnetbyaddr.o) \
$(LIBRARY)(getproto.o) \
$(LIBRARY)(getprotoent.o) \
$(LIBRARY)(getservent.o) \
$(LIBRARY)(getsrvbyname.o) \
$(LIBRARY)(getsrvbyport.o) \
$(LIBRARY)(hton.o) \
$(LIBRARY)(inet_addr.o) \
$(LIBRARY)(inet_network.o) \
$(LIBRARY)(inet_ntoa.o) \
$(LIBRARY)(memcspn.o) \
$(LIBRARY)(rcmd.o) \
$(LIBRARY)(res_comp.o) \
$(LIBRARY)(res_init.o) \
$(LIBRARY)(res_mkquery.o) \
$(LIBRARY)(res_query.o) \
$(LIBRARY)(res_send.o) \
$(LIBRARY)(ruserok.o) \
$(LIBRARY)(servxcheck.o) \
$(LIBRARY)(strcasecmp.o) \
$(LIBRARY): $(OBJECTS)
aal cr $@ *.o
rm *.o
$(LIBRARY)(dhcp_gettag.o): dhcp_gettag.c
$(CC1) dhcp_gettag.c
$(LIBRARY)(dhcp_settag.o): dhcp_settag.c
$(CC1) dhcp_settag.c
$(LIBRARY)(ether_line.o): ether_line.c
$(CC1) ether_line.c
$(LIBRARY)(ethera2n.o): ethera2n.c
$(CC1) ethera2n.c
$(LIBRARY)(ethere2a.o): ethere2a.c
$(CC1) ethere2a.c
$(LIBRARY)(etherh2n.o): etherh2n.c
$(CC1) etherh2n.c
$(LIBRARY)(ethern2h.o): ethern2h.c
$(CC1) ethern2h.c
$(LIBRARY)(getdomain.o): getdomain.c
$(CC1) getdomain.c
$(LIBRARY)(gethnmadr.o): gethnmadr.c
$(CC1) gethnmadr.c
$(LIBRARY)(gethostent.o): gethostent.c
$(CC1) gethostent.c
$(LIBRARY)(gethostname.o): gethostname.c
$(CC1) gethostname.c
$(LIBRARY)(getnetent.o): getnetent.c
$(CC1) getnetent.c
$(LIBRARY)(getnetbyname.o): getnetbyname.c
$(CC1) getnetbyname.c
$(LIBRARY)(getnetbyaddr.o): getnetbyaddr.c
$(CC1) getnetbyaddr.c
$(LIBRARY)(getproto.o): getproto.c
$(CC1) getproto.c
$(LIBRARY)(getprotoent.o): getprotoent.c
$(CC1) getprotoent.c
$(LIBRARY)(getservent.o): getservent.c
$(CC1) getservent.c
$(LIBRARY)(getsrvbyname.o): getsrvbyname.c
$(CC1) getsrvbyname.c
$(LIBRARY)(getsrvbyport.o): getsrvbyport.c
$(CC1) getsrvbyport.c
$(LIBRARY)(hton.o): hton.c
$(CC1) hton.c
$(LIBRARY)(inet_addr.o): inet_addr.c
$(CC1) inet_addr.c
$(LIBRARY)(inet_network.o): inet_network.c
$(CC1) inet_network.c
$(LIBRARY)(inet_ntoa.o): inet_ntoa.c
$(CC1) inet_ntoa.c
$(LIBRARY)(memcspn.o): memcspn.c
$(CC1) memcspn.c
$(LIBRARY)(oneC_sum.o): oneC_sum.c
$(CC1) oneC_sum.c
$(LIBRARY)(rcmd.o): rcmd.c
$(CC1) rcmd.c
$(LIBRARY)(res_comp.o): res_comp.c
$(CC1) res_comp.c
$(LIBRARY)(res_init.o): res_init.c
$(CC1) res_init.c
$(LIBRARY)(res_mkquery.o): res_mkquery.c
$(CC1) res_mkquery.c
$(LIBRARY)(res_query.o): res_query.c
$(CC1) res_query.c
$(LIBRARY)(res_send.o): res_send.c
$(CC1) res_send.c
$(LIBRARY)(ruserok.o): ruserok.c
$(CC1) ruserok.c
$(LIBRARY)(servxcheck.o): servxcheck.c
$(CC1) servxcheck.c
$(LIBRARY)(strcasecmp.o): strcasecmp.c
$(CC1) strcasecmp.c
+55
View File
@@ -0,0 +1,55 @@
/* dhcp_gettag() Author: Kees J. Bot
* 1 Dec 2000
*/
#define nil ((void*)0)
#include <stddef.h>
#include <string.h>
#include <sys/types.h>
#include <net/hton.h>
#include <net/gen/in.h>
#include <net/gen/dhcp.h>
#define arraysize(a) (sizeof(a) / sizeof((a)[0]))
int dhcp_gettag(dhcp_t *dp, int searchtag, u8_t **pdata, size_t *plen)
{
/* Find a tag in the options field, or possibly in the file or sname
* fields. Return true iff found, and return the data and/or length if
* their pointers are non-null.
*/
u8_t *p;
u8_t *optfield[3];
size_t optlen[3];
int i, tag, len;
/* The DHCP magic number must be correct, or no tags. */
if (dp->magic != DHCP_MAGIC) return 0;
optfield[0]= dp->options;
optlen[0]= arraysize(dp->options);
optfield[1]= dp->file;
optlen[1]= 0; /* Unknown if used for options yet. */
optfield[2]= dp->sname;
optlen[2]= 0;
for (i= 0; i < 3; i++) {
p= optfield[i];
while (p < optfield[i] + optlen[i]) {
tag= *p++;
if (tag == 255) break;
len= tag == 0 ? 0 : *p++;
if (tag == searchtag) {
if (pdata != nil) *pdata= p;
if (plen != nil) *plen= len;
return 1;
}
if (tag == DHCP_TAG_OVERLOAD) {
/* There are also options in the file or sname field. */
if (*p & 1) optlen[1]= arraysize(dp->file);
if (*p & 2) optlen[1]= arraysize(dp->sname);
}
p += len;
}
}
return 0;
}
+57
View File
@@ -0,0 +1,57 @@
/* dhcp_init(), dhcp_settag() Author: Kees J. Bot
* 1 Dec 2000
*/
#define nil ((void*)0)
#include <stddef.h>
#include <string.h>
#include <sys/types.h>
#include <net/hton.h>
#include <net/gen/in.h>
#include <net/gen/dhcp.h>
#define arraysize(a) (sizeof(a) / sizeof((a)[0]))
#define arraylimit(a) ((a) + arraysize(a))
void dhcp_init(dhcp_t *dp)
{
/* Initialize a DHCP packet. */
memset(dp, 0, offsetof(dhcp_t, magic));
dp->magic= DHCP_MAGIC;
memset(dp->options, 255, sizeof(dp->options));
}
int dhcp_settag(dhcp_t *dp, int tag, void *data, size_t len)
{
/* Add a tag to a DHCP packet. No padding. Only do the options field.
* (This is Minix, we don't need megabytes of silly bits of data.)
* The length may be zero to delete a tag.
*/
u8_t *p;
int n;
if (tag <= 0 || tag >= 255) return 0;
for (p= dp->options; p < arraylimit(dp->options) && *p != 255; p += n) {
n= 1 + 1 + p[1];
if (*p == tag) {
/* The tag is already there, remove it so it gets replaced. */
memmove(p, p + n, arraylimit(dp->options) - (p + n));
memset(arraylimit(dp->options) - n, 255, n);
n= 0;
}
}
/* Add tag. */
if (len == 0) {
/* We're merely deleting a tag. */
} else
if (p + 1 + 1 + len <= arraylimit(dp->options)) {
*p++ = tag;
*p++ = len;
memcpy(p, data, len);
} else {
/* Oops, it didn't fit? Is this really Minix??? */
return 0;
}
return 1;
}
+30
View File
@@ -0,0 +1,30 @@
/*
domainname.c
*/
#include <stdio.h>
#include <string.h>
#include <net/netlib.h>
int getdomainname(domain, size)
char *domain;
size_t size;
{
FILE *domainfile;
char *line;
domainfile= fopen("/etc/domainname", "r");
if (!domainfile)
{
return -1;
}
line= fgets(domain, size, domainfile);
fclose(domainfile);
if (!line)
return -1;
line= strchr(domain, '\n');
if (line)
*line= '\0';
return 0;
}
Executable
+151
View File
@@ -0,0 +1,151 @@
/* $Id$ */
/* Interface definitions for ethernet access library */
typedef union etheraddr
{
unsigned char bytes[6]; /* byteorder safe initialization */
unsigned short shorts[3]; /* force 2-byte alignment */
}
ether_addr;
typedef struct etherpacket
{
ether_addr dest;
ether_addr src;
unsigned char type[2]; /* in network byte order! */
unsigned short pktlen; /* length of pktbuf ONLY */
char *pktbuf;
}
ether_packet;
typedef struct ethervec
{
ether_addr dest;
ether_addr src;
unsigned char type[2]; /* in network byte order! */
unsigned short iovcnt; /* number of iovec to use */
struct iovec *iov; /* ptr to array of iovec */
}
ether_vec;
#ifndef __ETHER_BCAST_ADDR__
extern ether_addr ether_bcast_addr;
#endif
#ifdef __STDC__
int ether_open (char *name, unsigned type, ether_addr * address);
ether_addr *ether_address (int fd, ether_addr * address);
ether_addr *ether_intfaddr (char *intf, ether_addr * address);
char **ether_interfaces (void);
int ether_write (int fd, ether_packet * packet);
int ether_writev (int fd, ether_vec * packet);
int ether_read (int fd, ether_packet * packet);
int ether_readv (int fd, ether_vec * packet);
int ether_blocking (int fd, int state);
int ether_send_self (int fd);
int ether_mcast_self (int fd);
int ether_bcast_self (int fd);
char *ether_ntoa (ether_addr *);
ether_addr *ether_aton (char *);
#ifdef __GNUC__
/*
* Avoid stupid warnings if structs aren't defined
*/
typedef struct in_addr *_ether_NoNsEnSe;
typedef struct hostent *_ether_nOnSeNsE;
#endif
char *ether_e2a (ether_addr *, char *);
ether_addr *ether_a2e (char *, ether_addr *);
struct in_addr *ether_e2ip (ether_addr *, struct in_addr *);
ether_addr *ether_ip2e (struct in_addr *, ether_addr *);
char *ether_e2host (ether_addr *, char *);
ether_addr *ether_host2e (char *, ether_addr *);
ether_addr *ether_hostent2e (struct hostent *, ether_addr *);
#else
int ether_open ();
ether_addr *ether_address ();
ether_addr *ether_intfaddr ();
char **ether_interfaces ();
int ether_write ();
int ether_writev ();
int ether_read ();
int ether_readv ();
int ether_blocking ();
int ether_send_self ();
int ether_mcast_self ();
int ether_bcast_self ();
char *ether_ntoa ();
ether_addr *ether_aton ();
char *ether_e2a ();
ether_addr *ether_a2e ();
struct in_addr *ether_e2ip ();
ether_addr *ether_ip2e ();
char *ether_e2host ();
ether_addr *ether_host2e ();
ether_addr *ether_hostent2e ();
#endif
#undef ether_cmp /* lose def from netinet/if_ether.h */
#define ether_cmp(addr1,addr2) \
((addr1)->shorts[0] != (addr2)->shorts[0] \
|| (addr1)->shorts[1] != (addr2)->shorts[1] \
|| (addr1)->shorts[2] != (addr2)->shorts[2])
#define ETHERSTRLEN 18 /* max length of "xx:xx:xx:xx:xx:xx" */
#ifdef NOFILE /* i.e. we have included sys/param.h */
#ifndef MAXHOSTNAMELEN /* but MAXHOSTNAMELEN still isnt set */
#define MAXHOSTNAMELEN 64
#endif
#endif
/* should be defined in terms of ether_packet struct; need offsetof() macro */
#define ETHER_DST 0
#define ETHER_SRC 6
#define ETHER_TYPE 12
#define ETHER_PKT 14
#define ETHER_MIN 46
#define ETHER_MAX 1500
#define ETHER_MINTYPE 0x5DD /* lowest protocol not valid IEEE802 */
#define ETHER_MAXTYPE 0xFFFF /* largest possible protocol */
#define ETHER_MCAST(addr) (((unsigned char *) (addr))[0] & 0x01)
#ifdef NT_ALLTYPES
#define ETHER_ALLTYPES NT_ALLTYPES
#else
#define ETHER_ALLTYPES ((unsigned) -1)
#endif
+58
View File
@@ -0,0 +1,58 @@
/*
** ETHER_LINE
**
** This routine parses the array pointed to by "line" (which should be
** from a file in the format of /etc/ethers) and returns in "eaddr" the
** ethernet address at the start of the line and the corresponding host
** name in "hostname". It assumes either tabs or spaces separate the
** two. The buffer pointed to by "hostname" must be big enough to hold
** the host name plus a NULL byte.
** The function returns 0 on success and 1 on failure.
** Arguments are assumed sensible. Null pointers will probably cause
** exceptions.
** Author: Gregory J. Sharp, July 1990
** Adapted to MINIX: Philip Homburg, May 1992
*/
#include <sys/types.h>
#include <ctype.h>
#include <stdlib.h>
#include <net/gen/ether.h>
#include <net/gen/if_ether.h>
int
ether_line(line, eaddr, hostname)
char * line;
struct ether_addr * eaddr;
char * hostname;
{
register int i;
register unsigned long val;
/* skip leading white space */
while (*line != '\n' && (*line == ' ' || *line == '\t'))
line++;
/* read the ethernet address */
for (i = 0; i < 5; i++)
{
val = (unsigned long) strtol(line, &line, 16);
if (val > 255 || *line++ != ':')
return 1;
eaddr->ea_addr[i] = val & 0xff;
}
val = (unsigned long) strtol(line, &line, 16);
if (val > 255 || (*line != ' ' && *line != '\t'))
return 1;
eaddr->ea_addr[i] = val & 0xff;
/* skip leading white space */
while (*line != '\n' && (*line == ' ' || *line == '\t'))
line++;
/* read in the hostname */
while (!isspace(*line))
*hostname++ = *line++;
*hostname = '\0';
return 0;
}
+42
View File
@@ -0,0 +1,42 @@
/*
ethera2n.c
Convert an ASCII string with an ethernet address into a struct ether_addr.
Created: Nov 17, 1992 by Philip Homburg
*/
#include <sys/types.h>
#include <stdlib.h>
#include <net/netlib.h>
#include <net/gen/ether.h>
#include <net/gen/if_ether.h>
struct ether_addr *ether_aton(s)
_CONST char *s;
{
static struct ether_addr ea;
int i;
long v;
char *check;
if (s == NULL)
return NULL;
for (i=0; i<6; i++)
{
v= strtol(s, &check, 16);
if (v<0 || v>255)
return NULL;
if ((i<5 && check[0] != ':') || (i == 5 && check[0] != '\0'))
return NULL;
ea.ea_addr[i]= v;
s= check+1;
}
return &ea;
}
/*
* $PchId: ethera2n.c,v 1.3 1996/02/22 21:10:01 philip Exp $
*/
+50
View File
@@ -0,0 +1,50 @@
/* $Id$ */
/* This file was part of the etherlib package. */
#include <stdio.h>
#ifdef _MINIX
#include <sys/types.h>
#include <stdlib.h>
#include <net/gen/ether.h>
#include <net/gen/if_ether.h>
#define ETHERSTRLEN 18 /* max length of "xx:xx:xx:xx:xx:xx" */
#define ether_addr ether_addr_t
#define bytes ea_addr
char *ether_e2a _ARGS(( ether_addr_t *a, char *e ));
#else
#include "libether.h"
#endif
char *
ether_e2a (addr, estring)
ether_addr *addr;
char *estring;
{
#ifdef lint
char *sprintf ();
#endif
if (estring == NULL)
estring = (char *) malloc (ETHERSTRLEN);
if (estring != NULL)
(void) sprintf (estring, "%x:%x:%x:%x:%x:%x",
addr->bytes[0], addr->bytes[1], addr->bytes[2],
addr->bytes[3], addr->bytes[4], addr->bytes[5]);
return (estring);
}
#ifndef ETHERDB
char *
ether_ntoa (addr)
ether_addr *addr;
{
static char estring[ETHERSTRLEN];
return (ether_e2a (addr, estring));
}
#endif
+33
View File
@@ -0,0 +1,33 @@
/*
etherh2n.c
Created: May 20, 1992 by Philip Homburg
*/
#include <stdio.h>
#include <string.h>
#include <net/gen/if_ether.h>
int
ether_hostton(hostname, e)
char *hostname;
struct ether_addr *e;
{
FILE *etherf;
char b[256], hn[256];
etherf= fopen(_PATH_ETHERS, "r");
if (etherf == NULL)
return 1;
while(fgets(b, sizeof(b), etherf) != NULL)
{
if (ether_line(b, e, hn) == 0 && strcmp(hn, hostname) == 0)
{
fclose(etherf);
return 0;
}
}
fclose(etherf);
return 1;
}
+37
View File
@@ -0,0 +1,37 @@
/*
ethern2h.c
Created: Nov 12, 1992 by Philip Homburg
*/
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <net/gen/ether.h>
#include <net/gen/if_ether.h>
int
ether_ntohost(hostname, e)
char *hostname;
struct ether_addr *e;
{
FILE *etherf;
char b[256];
struct ether_addr e_tmp;
etherf= fopen(_PATH_ETHERS, "r");
if (etherf == NULL)
return 1;
while(fgets(b, sizeof(b), etherf) != NULL)
{
if (ether_line(b, &e_tmp, hostname) == 0 &&
memcmp(&e_tmp, e, sizeof(e_tmp)) == 0)
{
fclose(etherf);
return 0;
}
}
fclose(etherf);
return 1;
}
+23
View File
@@ -0,0 +1,23 @@
/* getdomainname() Author: Kees J. Bot
* 2 Dec 1994
*/
#define nil 0
#include <sys/types.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <string.h>
int getdomainname(char *domain, size_t size)
{
char nodename[256];
char *dot;
if (gethostname(nodename, sizeof(nodename)) < 0)
return -1;
nodename[sizeof(nodename)-1]= 0;
if ((dot= strchr(nodename, '.')) == nil) dot= ".";
strncpy(domain, dot+1, size);
if (size > 0) domain[size-1]= 0;
return 0;
}
+338
View File
@@ -0,0 +1,338 @@
/*
* Copyright (c) 1985, 1988 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)gethostnamadr.c 6.41 (Berkeley) 6/1/90";
#endif /* LIBC_SCCS and not lint */
#ifdef _MINIX
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <net/hton.h>
#include <net/gen/nameser.h>
#include <net/gen/netdb.h>
#include <net/gen/in.h>
#include <net/gen/inet.h>
#include <net/gen/resolv.h>
#include <net/gen/socket.h>
#else
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <ctype.h>
#include <netdb.h>
#include <stdio.h>
#include <errno.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <resolv.h>
#endif /* AMOEABA */
#define MAXALIASES 35
#define MAXADDRS 35
static char *h_addr_ptrs[MAXADDRS + 1];
#ifdef _MINIX
struct in_addr
{
ipaddr_t s_addr;
};
typedef u32_t u_long;
typedef u16_t u_short;
typedef u8_t u_char;
union querybuf;
extern int dn_skipname _ARGS(( const u_char *comp_dn, const u_char *eom ));
#define getshort _getshort
static struct hostent *getanswer _ARGS(( union querybuf *answer, int anslen,
int iquery ));
#define bcmp memcmp
#define bcopy(s, d, l) memcpy(d, s, l)
#endif /* _MINIX */
static struct hostent host;
static char *host_aliases[MAXALIASES];
static char hostbuf[BUFSIZ+1];
static struct in_addr host_addr;
#ifndef _MINIX
char *strpbrk();
#endif /* !_MINIX */
#if PACKETSZ > 1024
#define MAXPACKET PACKETSZ
#else
#define MAXPACKET 1024
#endif
typedef union querybuf
{
dns_hdr_t hdr;
u_char buf[MAXPACKET];
} querybuf_t;
typedef union align {
long al;
char ac;
} align_t;
static struct hostent *
getanswer(answer, anslen, iquery)
querybuf_t *answer;
int anslen;
int iquery;
{
register dns_hdr_t *hp;
register u_char *cp;
register int n;
u_char *eom;
char *bp, **ap;
int type, class, buflen, ancount, qdcount;
int haveanswer, getclass = C_ANY;
char **hap;
eom = answer->buf + anslen;
/*
* find first satisfactory answer
*/
hp = &answer->hdr;
ancount = ntohs(hp->dh_ancount);
qdcount = ntohs(hp->dh_qdcount);
bp = hostbuf;
buflen = sizeof(hostbuf);
cp = answer->buf + sizeof(dns_hdr_t);
if (qdcount) {
if (iquery) {
if ((n = dn_expand((u_char *)answer->buf, eom,
cp, (u_char *)bp, buflen)) < 0) {
h_errno = NO_RECOVERY;
return ((struct hostent *) NULL);
}
cp += n + QFIXEDSZ;
host.h_name = bp;
n = strlen(bp) + 1;
bp += n;
buflen -= n;
} else
cp += dn_skipname(cp, eom) + QFIXEDSZ;
while (--qdcount > 0)
cp += dn_skipname(cp, eom) + QFIXEDSZ;
} else if (iquery) {
if (hp->dh_flag1 & DHF_AA)
h_errno = HOST_NOT_FOUND;
else
h_errno = TRY_AGAIN;
return ((struct hostent *) NULL);
}
ap = host_aliases;
*ap = NULL;
host.h_aliases = host_aliases;
hap = h_addr_ptrs;
*hap = NULL;
#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
host.h_addr_list = h_addr_ptrs;
#endif
haveanswer = 0;
while (--ancount >= 0 && cp < eom) {
if ((n = dn_expand((u_char *)answer->buf, eom, cp, (u_char *)bp,
buflen)) < 0)
break;
cp += n;
type = getshort(cp);
cp += sizeof(u_short);
class = getshort(cp);
cp += sizeof(u_short) + sizeof(u_long);
n = getshort(cp);
cp += sizeof(u_short);
if (type == T_CNAME) {
cp += n;
if (ap >= &host_aliases[MAXALIASES-1])
continue;
*ap++ = bp;
n = strlen(bp) + 1;
bp += n;
buflen -= n;
continue;
}
if (iquery && type == T_PTR) {
if ((n = dn_expand((u8_t *)answer->buf, eom,
cp, (u8_t *)bp, buflen)) < 0) {
cp += n;
continue;
}
cp += n;
host.h_name = bp;
return(&host);
}
if (iquery || type != T_A) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
printf("unexpected answer type %d, size %d\n",
type, n);
#endif
cp += n;
continue;
}
if (haveanswer) {
if (n != host.h_length) {
cp += n;
continue;
}
if (class != getclass) {
cp += n;
continue;
}
} else {
host.h_length = n;
getclass = class;
host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC;
if (!iquery) {
host.h_name = bp;
bp += strlen(bp) + 1;
}
}
bp += (size_t)(sizeof(align_t) -
((u_long)bp % sizeof(align_t)));
if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
printf("size (%d) too big\n", n);
#endif
break;
}
bcopy(cp, *hap++ = bp, n);
bp +=n;
cp += n;
haveanswer++;
}
if (haveanswer) {
*ap = NULL;
#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
*hap = NULL;
#else
host.h_addr = h_addr_ptrs[0];
#endif
return (&host);
} else {
h_errno = TRY_AGAIN;
return ((struct hostent *) NULL);
}
}
struct hostent *
gethostbyname(name)
_CONST char *name;
{
querybuf_t buf;
register _CONST char *cp;
int n;
/*
* disallow names consisting only of digits/dots, unless
* they end in a dot.
*/
if (isdigit(name[0]))
for (cp = name;; ++cp) {
if (!*cp) {
if (*--cp == '.')
break;
/*
* All-numeric, no dot at the end.
* Fake up a hostent as if we'd actually
* done a lookup. What if someone types
* 255.255.255.255? The test below will
* succeed spuriously... ???
*/
if ((host_addr.s_addr = inet_addr(name)) == -1) {
h_errno = HOST_NOT_FOUND;
return((struct hostent *) NULL);
}
host.h_name = (char *) name;
host.h_aliases = host_aliases;
host_aliases[0] = NULL;
host.h_addrtype = AF_INET;
host.h_length = sizeof(u_long);
h_addr_ptrs[0] = (char *)&host_addr;
h_addr_ptrs[1] = (char *)0;
#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
host.h_addr_list = h_addr_ptrs;
#else
host.h_addr = h_addr_ptrs[0];
#endif
return (&host);
}
if (!isdigit(*cp) && *cp != '.')
break;
}
if ((n = res_search((char*)name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
printf("res_search failed\n");
#endif
return ((struct hostent *) NULL);
}
return (getanswer(&buf, n, 0));
}
struct hostent *
gethostbyaddr(addr, len, type)
const char *addr;
int len, type;
{
int n;
querybuf_t buf;
register struct hostent *hp;
char qbuf[MAXDNAME];
if (type != AF_INET)
return ((struct hostent *) NULL);
(void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
((unsigned)addr[3] & 0xff),
((unsigned)addr[2] & 0xff),
((unsigned)addr[1] & 0xff),
((unsigned)addr[0] & 0xff));
n = res_query(qbuf, C_IN, T_PTR, (u8_t *)&buf, sizeof(buf));
if (n < 0) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
printf("res_query failed\n");
#endif
return ((struct hostent *) NULL);
}
hp = getanswer(&buf, n, 1);
if (hp == NULL)
return ((struct hostent *) NULL);
hp->h_addrtype = type;
hp->h_length = len;
h_addr_ptrs[0] = (char *)&host_addr;
h_addr_ptrs[1] = (char *)0;
host_addr = *(struct in_addr *)addr;
#if BSD < 43 && !defined(h_addr) /* new-style hostent structure */
hp->h_addr = h_addr_ptrs[0];
#endif
return(hp);
}
+168
View File
@@ -0,0 +1,168 @@
/* gethostent() - Interface to /etc/hosts Author: Kees J. Bot
* 31 May 1999
*/
/* Prefix the functions defined here with underscores to distinguish them
* from the newer replacements in the resolver library.
*/
#define sethostent _sethostent
#define endhostent _endhostent
#define gethostent _gethostent
#define gethostbyname _gethostbyname
#define gethostbyaddr _gethostbyaddr
#define nil 0
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <net/gen/netdb.h>
#include <net/gen/in.h>
#include <net/gen/inet.h>
#include <net/gen/socket.h>
#define arraysize(a) (sizeof(a) / sizeof((a)[0]))
#define arraylimit(a) ((a) + arraysize(a))
#define isspace(c) ((unsigned) (c) <= ' ')
static char HOSTS[]= _PATH_HOSTS;
static char *hosts= HOSTS; /* Current hosts file. */
static FILE *hfp; /* Open hosts file. */
void sethostent(int stayopen)
/* Start search. (Same as ending it.) */
{
endhostent();
}
void endhostent(void)
/* End search and reinitialize. */
{
if (hfp != nil) {
fclose(hfp);
hfp= nil;
}
hosts= _PATH_HOSTS;
}
struct hostent *gethostent(void)
/* Return the next entry from the hosts files. */
{
static char line[256]; /* One line in a hosts file. */
static ipaddr_t addr; /* IP address found first on the line. */
static char *names[16]; /* Pointers to the words on the line. */
static char *addrs[2]= { /* List of IP addresses (just one.) */
(char *) &addr,
nil,
};
static struct hostent host = {
nil, /* h_name, will set to names[1]. */
names + 2, /* h_aliases, the rest of the names. */
AF_INET, /* h_addrtype */
sizeof(ipaddr_t), /* Size of an address in the address list. */
addrs, /* List of IP addresses. */
};
static char nexthosts[128]; /* Next hosts file to include. */
char *lp, **np;
int c;
for (;;) {
if (hfp == nil) {
/* No hosts file open, try to open the next one. */
if (hosts == 0) return nil;
if ((hfp= fopen(hosts, "r")) == nil) { hosts= nil; continue; }
}
/* Read a line. */
lp= line;
while ((c= getc(hfp)) != EOF && c != '\n') {
if (lp < arraylimit(line)) *lp++= c;
}
/* EOF? Then close and prepare for reading the next file. */
if (c == EOF) {
fclose(hfp);
hfp= nil;
hosts= nil;
continue;
}
if (lp == arraylimit(line)) continue;
*lp= 0;
/* Break the line up in words. */
np= names;
lp= line;
for (;;) {
while (isspace(*lp) && *lp != 0) lp++;
if (*lp == 0 || *lp == '#') break;
if (np == arraylimit(names)) break;
*np++= lp;
while (!isspace(*lp) && *lp != 0) lp++;
if (*lp == 0) break;
*lp++= 0;
}
if (np == arraylimit(names)) continue;
*np= nil;
/* Special "include file" directive. */
if (np == names + 2 && strcmp(names[0], "include") == 0) {
fclose(hfp);
hfp= nil;
hosts= nil;
if (strlen(names[1]) < sizeof(nexthosts)) {
strcpy(nexthosts, names[1]);
hosts= nexthosts;
}
continue;
}
/* At least two words, the first of which is an IP address. */
if (np < names + 2) continue;
if (!inet_aton((char *) names[0], &addr)) continue;
host.h_name= (char *) names[1];
return &host;
}
}
/* Rest kept in reserve, we probably never need 'em. */
#if XXX
struct hostent *gethostbyname(const char *name)
{
struct hostent *he;
char **pa;
char alias[256];
char *domain;
sethostent(0);
while ((he= gethostent()) != nil) {
if (strcasecmp(he->h_name, name) == 0) goto found;
domain= strchr(he->h_name, '.');
for (pa= he->h_aliases; *pa != nil; pa++) {
strcpy(alias, *pa);
if (domain != nil && strchr(alias, '.') == nil) {
strcat(alias, domain);
}
if (strcasecmp(alias, name) == 0) goto found;
}
}
found:
endhostent();
return he;
}
struct hostent *gethostbyaddr(const char *addr, int len, int type)
{
struct hostent *he;
sethostent(0);
while ((he= gethostent()) != nil) {
if (he->h_name[0] == '%') continue;
if (type == AF_INET && memcmp(he->h_addr, addr, len) == 0) break;
}
endhostent();
return he;
}
#endif
+27
View File
@@ -0,0 +1,27 @@
/* gethostname(2) system call emulation */
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/gen/netdb.h>
#define HOSTNAME_FILE "/etc/hostname.file"
int gethostname(char *buf, size_t len)
{
int fd;
int r;
char *nl;
if ((fd= open(HOSTNAME_FILE, O_RDONLY)) < 0) return -1;
r= read(fd, buf, len);
close(fd);
if (r == -1) return -1;
buf[len-1]= '\0';
if ((nl= strchr(buf, '\n')) != NULL) *nl= '\0';
return 0;
}
+56
View File
@@ -0,0 +1,56 @@
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)getnetbyaddr.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <net/gen/netdb.h>
extern int _net_stayopen;
struct netent *
getnetbyaddr(net, type)
register long net;
register int type;
{
register struct netent *p;
setnetent(_net_stayopen);
while (p = getnetent())
if (p->n_addrtype == type && p->n_net == net)
break;
if (!_net_stayopen)
endnetent();
return (p);
}
+62
View File
@@ -0,0 +1,62 @@
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)getnetbyname.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <string.h>
#include <net/gen/netdb.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 (strcmp(p->n_name, name) == 0)
break;
for (cp = p->n_aliases; *cp != 0; cp++)
if (strcmp(*cp, name) == 0)
goto found;
}
found:
if (!_net_stayopen)
endnetent();
return (p);
}
+121
View File
@@ -0,0 +1,121 @@
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)getnetent.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <net/gen/in.h>
#include <net/gen/netdb.h>
#include <net/gen/inet.h>
#include <net/gen/socket.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;
register char *cp, **q;
if (netf == NULL && (netf = fopen(_PATH_NETWORKS, "r" )) == NULL)
return (NULL);
again:
p = fgets(line, BUFSIZ, netf);
if (p == NULL)
return (NULL);
if (*p == '#')
goto again;
cp = strpbrk(p, "#\n");
if (cp == NULL)
goto again;
*cp = '\0';
net.n_name = p;
cp = strpbrk(p, " \t");
if (cp == NULL)
goto again;
*cp++ = '\0';
while (*cp == ' ' || *cp == '\t')
cp++;
p = strpbrk(cp, " \t");
if (p != NULL)
*p++ = '\0';
net.n_net = inet_network(cp);
net.n_addrtype = AF_INET;
q = net.n_aliases = net_aliases;
if (p != NULL)
cp = p;
while (cp && *cp) {
if (*cp == ' ' || *cp == '\t') {
cp++;
continue;
}
if (q < &net_aliases[MAXALIASES - 1])
*q++ = cp;
cp = strpbrk(cp, " \t");
if (cp != NULL)
*cp++ = '\0';
}
*q = NULL;
return (&net);
}
+46
View File
@@ -0,0 +1,46 @@
/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)getproto.c 5.6 (Berkeley) 6/1/90";
#endif /* LIBC_SCCS and not lint */
#include <stddef.h>
#ifdef _MINIX
#include <ansi.h>
#include <net/gen/netdb.h>
#endif
extern int _proto_stayopen;
struct protoent *
getprotobynumber(proto)
register int proto;
{
register struct protoent *p;
setprotoent(_proto_stayopen);
while (p = getprotoent())
if (p->p_proto == proto)
break;
if (!_proto_stayopen)
endprotoent();
return (p);
}
+124
View File
@@ -0,0 +1,124 @@
/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)getprotoent.c 5.7 (Berkeley) 6/1/90";
#endif /* LIBC_SCCS and not lint */
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef _MINIX
#include <net/gen/netdb.h>
static char *any _ARGS(( char *cp, char *match ));
#endif
#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(f)
int f;
{
if (protof == NULL)
protof = fopen(_PATH_PROTOCOLS, "r" );
else
rewind(protof);
_proto_stayopen |= f;
}
void
endprotoent()
{
if (protof) {
fclose(protof);
protof = NULL;
}
_proto_stayopen = 0;
}
struct protoent *
getprotoent()
{
char *p;
register char *cp, **q;
if (protof == NULL && (protof = fopen(_PATH_PROTOCOLS, "r" )) == NULL)
return (NULL);
again:
if ((p = fgets(line, BUFSIZ, protof)) == NULL)
return (NULL);
if (*p == '#')
goto again;
cp = any(p, "#\n");
if (cp == NULL)
goto again;
*cp = '\0';
proto.p_name = p;
cp = any(p, " \t");
if (cp == NULL)
goto again;
*cp++ = '\0';
while (*cp == ' ' || *cp == '\t')
cp++;
p = any(cp, " \t");
if (p != NULL)
*p++ = '\0';
proto.p_proto = atoi(cp);
q = proto.p_aliases = proto_aliases;
if (p != NULL) {
cp = p;
while (cp && *cp) {
if (*cp == ' ' || *cp == '\t') {
cp++;
continue;
}
if (q < &proto_aliases[MAXALIASES - 1])
*q++ = cp;
cp = any(cp, " \t");
if (cp != NULL)
*cp++ = '\0';
}
}
*q = NULL;
return (&proto);
}
static char *
any(cp, match)
register char *cp;
char *match;
{
register char *mp, c;
while (c = *cp) {
for (mp = match; *mp; mp++)
if (*mp == c)
return (cp);
cp++;
}
return ((char *)0);
}
+126
View File
@@ -0,0 +1,126 @@
/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)getservent.c 5.8 (Berkeley) 6/1/90";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <net/hton.h>
#include <net/gen/netdb.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;
static char *any _ARGS(( char *cp, char *match ));
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;
register char *cp, **q;
if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL)
return (NULL);
again:
if ((p = fgets(line, BUFSIZ, servf)) == NULL)
return (NULL);
if (*p == '#')
goto again;
cp = any(p, "#\n");
if (cp == NULL)
goto again;
*cp = '\0';
serv.s_name = p;
p = any(p, " \t");
if (p == NULL)
goto again;
*p++ = '\0';
while (*p == ' ' || *p == '\t')
p++;
cp = any(p, ",/");
if (cp == NULL)
goto again;
*cp++ = '\0';
serv.s_port = htons((u16_t)atoi(p));
serv.s_proto = cp;
q = serv.s_aliases = serv_aliases;
cp = any(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 = any(cp, " \t");
if (cp != NULL)
*cp++ = '\0';
}
*q = NULL;
return (&serv);
}
static char *
any(cp, match)
register char *cp;
char *match;
{
register char *mp, c;
while (c = *cp) {
for (mp = match; *mp; mp++)
if (*mp == c)
return (cp);
cp++;
}
return ((char *)0);
}
+52
View File
@@ -0,0 +1,52 @@
/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)getservbyname.c 5.6 (Berkeley) 6/1/90";
#endif /* LIBC_SCCS and not lint */
#include <string.h>
#include <net/gen/netdb.h>
extern int _serv_stayopen;
struct servent *
getservbyname(name, proto)
const char *name, *proto;
{
register struct servent *p;
register char **cp;
setservent(_serv_stayopen);
while (p = getservent()) {
if (strcmp(name, p->s_name) == 0)
goto gotname;
for (cp = p->s_aliases; *cp; cp++)
if (strcmp(name, *cp) == 0)
goto gotname;
continue;
gotname:
if (proto == 0 || strcmp(p->s_proto, proto) == 0)
break;
}
if (!_serv_stayopen)
endservent();
return (p);
}
+50
View File
@@ -0,0 +1,50 @@
/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)getservbyport.c 5.6 (Berkeley) 6/1/90";
#endif /* LIBC_SCCS and not lint */
#include <stddef.h>
#include <string.h>
#ifdef _MINIX
#include <net/gen/netdb.h>
#endif
extern int _serv_stayopen;
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);
}
Executable
+10
View File
@@ -0,0 +1,10 @@
/*
hton.c
*/
#include <sys/types.h>
#include <minix/config.h>
#include <net/hton.h>
u16_t _tmp;
u32_t _tmp_l;
+149
View File
@@ -0,0 +1,149 @@
/*
* Copyright (c) 1983, 1990 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted provided
* that: (1) source distributions retain this entire copyright notice and
* comment, and (2) distributions including binaries display the following
* acknowledgement: ``This product includes software developed by the
* University of California, Berkeley and its contributors'' in the
* documentation or other materials provided with the distribution and in
* all advertising materials mentioning features or use of this software.
* Neither the name of the University nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)inet_addr.c 5.8 (Berkeley) 6/23/90";
#endif /* LIBC_SCCS and not lint */
#if _MINIX
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#include <net/hton.h>
#include <net/gen/in.h>
#include <net/gen/inet.h>
#endif
#ifdef __STDC__
#define _CONST const
#else
#define _CONST
#endif
/*
* Ascii internet address interpretation routine.
* The value returned is in network order.
*/
ipaddr_t
inet_addr(cp)
register _CONST char *cp;
{
ipaddr_t val;
if (inet_aton(cp, &val))
return (val);
errno= EINVAL;
return (ipaddr_t)-1;
}
/*
* 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;
ipaddr_t *addr;
{
register u32_t val, base, n;
register char c;
u32_t parts[4], *pp = parts;
for (;;) {
/*
* Collect number up to ``.''.
* Values are specified as for C:
* 0x=hex, 0=octal, other=decimal.
*/
val = 0; base = 10;
if (*cp == '0') {
if (*++cp == 'x' || *cp == 'X')
base = 16, cp++;
else
base = 8;
}
while ((c = *cp) != '\0') {
if (isascii(c) && isdigit(c)) {
val = (val * base) + (c - '0');
cp++;
continue;
}
if (base == 16 && isascii(c) && isxdigit(c)) {
val = (val << 4) +
(c + 10 - (islower(c) ? 'a' : 'A'));
cp++;
continue;
}
break;
}
if (*cp == '.') {
/*
* Internet format:
* a.b.c.d
* a.b.c (with c treated as 16-bits)
* a.b (with b treated as 24 bits)
*/
if (pp >= parts + 3 || val > 0xff)
return (0);
*pp++ = val, cp++;
} else
break;
}
/*
* Check for trailing characters.
*/
if (*cp && (!isascii(*cp) || !isspace(*cp)))
return (0);
/*
* Concoct the address according to
* the number of parts specified.
*/
n = pp - parts + 1;
switch (n) {
case 1: /* a -- 32 bits */
break;
case 2: /* a.b -- 8.24 bits */
if (val > 0xffffff)
return (0);
val |= parts[0] << 24;
break;
case 3: /* a.b.c -- 8.8.16 bits */
if (val > 0xffff)
return (0);
val |= (parts[0] << 24) | (parts[1] << 16);
break;
case 4: /* a.b.c.d -- 8.8.8.8 bits */
if (val > 0xff)
return (0);
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
break;
}
if (addr)
*addr = htonl(val);
return (1);
}
+95
View File
@@ -0,0 +1,95 @@
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)inet_network.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#include <ctype.h>
#include <net/gen/in.h>
#include <net/gen/inet.h>
#define INADDR_NONE ((ipaddr_t) -1)
/*
* Internet network address interpretation routine.
* The library routines call this routine to interpret
* network numbers.
*/
ipaddr_t
inet_network(cp)
register const char *cp;
{
register ipaddr_t val, base, n;
register char c;
ipaddr_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 + 4)
return (INADDR_NONE);
*pp++ = val, cp++;
goto again;
}
if (*cp && !isspace(*cp))
return (INADDR_NONE);
*pp++ = val;
n = pp - parts;
if (n > 4)
return (INADDR_NONE);
for (val = 0, i = 0; i < n; i++) {
val <<= 8;
val |= parts[i] & 0xff;
}
return (val);
}
+45
View File
@@ -0,0 +1,45 @@
/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)inet_ntoa.c 5.5 (Berkeley) 6/1/90";
#endif /* LIBC_SCCS and not lint */
/*
* Convert network-format internet address
* to base 256 d.d.d.d representation.
*/
#include <sys/types.h>
#include <stdio.h>
#include <net/gen/in.h>
#include <net/gen/inet.h>
char *
inet_ntoa(in)
ipaddr_t in;
{
static char b[18];
register u8_t *p;
p = (u8_t *)&in;
sprintf(b, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
return (b);
}
+22
View File
@@ -0,0 +1,22 @@
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* $Header$ */
#include <string.h>
size_t
memcspn(const char *string, size_t strlen, const char *notin, size_t notinlen)
{
register const char *s1, *s2;
int i,j;
for (s1 = string, i = 0; i<strlen; s1++, i++) {
for(s2 = notin, j = 0; *s2 != *s1 && j < notinlen; s2++, j++)
/* EMPTY */ ;
if (j != notinlen)
break;
}
return s1 - string;
}
+61
View File
@@ -0,0 +1,61 @@
/* oneC_sum() - One complement's checksum Author: Kees J. Bot
* 8 May 1995
* See RFC 1071, "Computing the Internet checksum"
*/
#include <sys/types.h>
#include <net/gen/oneCsum.h>
u16_t oneC_sum(U16_t prev, void *data, size_t size)
{
u8_t *dptr;
size_t n;
u16_t word;
u32_t sum;
int swap= 0;
sum= prev;
dptr= data;
n= size;
swap= ((size_t) dptr & 1);
if (swap) {
sum= ((sum & 0xFF) << 8) | ((sum & 0xFF00) >> 8);
if (n > 0) {
((u8_t *) &word)[0]= 0;
((u8_t *) &word)[1]= dptr[0];
sum+= (u32_t) word;
dptr+= 1;
n-= 1;
}
}
while (n >= 8) {
sum+= (u32_t) ((u16_t *) dptr)[0]
+ (u32_t) ((u16_t *) dptr)[1]
+ (u32_t) ((u16_t *) dptr)[2]
+ (u32_t) ((u16_t *) dptr)[3];
dptr+= 8;
n-= 8;
}
while (n >= 2) {
sum+= (u32_t) ((u16_t *) dptr)[0];
dptr+= 2;
n-= 2;
}
if (n > 0) {
((u8_t *) &word)[0]= dptr[0];
((u8_t *) &word)[1]= 0;
sum+= (u32_t) word;
}
sum= (sum & 0xFFFF) + (sum >> 16);
if (sum > 0xFFFF) sum++;
if (swap) {
sum= ((sum & 0xFF) << 8) | ((sum & 0xFF00) >> 8);
}
return sum;
}
Executable
+284
View File
@@ -0,0 +1,284 @@
/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)rcmd.c 5.22 (Berkeley) 6/1/90";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <net/gen/netdb.h>
#include <net/gen/in.h>
#include <net/gen/tcp.h>
#include <net/gen/tcp_io.h>
#include <net/hton.h>
#include <net/netlib.h>
#define MAXHOSTNAMELEN 256
#define MAXPATHLEN PATH_MAX
#ifdef __STDC__
#define CONST const
#else
#define CONST
#endif
extern errno;
int rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
char **ahost;
int rport;
CONST char *locuser, *remuser, *cmd;
int *fd2p;
{
int fd, fd2, result;
struct hostent *hp;
int n;
static tcpport_t lport;
nwio_tcpconf_t tcpconf;
nwio_tcpcl_t tcpconnopt;
pid_t pid;
char num[8];
char c;
char *tcp_device;
fd= -1;
fd2= -1;
if (lport == 0) {
pid = getpid();
lport = 1;
do {
lport = (lport << 1) | (pid & 1);
pid >>= 1;
} while (lport < TCPPORT_RESERVED/2);
}
tcp_device= getenv("TCP_DEVICE");
if (tcp_device == NULL)
tcp_device= TCP_DEVICE;
hp= gethostbyname(*ahost);
if (!hp)
{
fprintf(stderr, "%s: unknown host\n", *ahost);
return -1;
}
*ahost= hp->h_name;
n = TCPPORT_RESERVED/2;
do
{
if (--lport < TCPPORT_RESERVED/2)
lport = TCPPORT_RESERVED-1;
fd= open (tcp_device, O_RDWR);
if (fd<0)
{
fprintf(stderr, "unable to open %s: %s\n",
tcp_device, strerror(errno));
goto bad;
}
tcpconf.nwtc_flags= NWTC_LP_SET | NWTC_SET_RA | NWTC_SET_RP |
NWTC_EXCL;
tcpconf.nwtc_locport= htons(lport);
tcpconf.nwtc_remport= rport;
tcpconf.nwtc_remaddr= *(ipaddr_t *)hp->h_addr;
result= ioctl(fd, NWIOSTCPCONF, &tcpconf);
if (result<0)
{
if (errno == EADDRINUSE)
{
close(fd);
continue;
}
fprintf(stderr, "unable to ioctl(NWIOSTCPCONF): %s\n",
strerror(errno));
goto bad;
}
tcpconf.nwtc_flags= NWTC_SHARED;
result= ioctl(fd, NWIOSTCPCONF, &tcpconf);
if (result<0)
{
fprintf(stderr, "unable to ioctl(NWIOSTCPCONF): %s\n",
strerror(errno));
goto bad;
}
tcpconnopt.nwtcl_flags= 0;
do
{
result= ioctl (fd, NWIOTCPCONN, &tcpconnopt);
if (result<0 && errno == EAGAIN)
{
sleep(2);
}
} while (result<0 && errno == EAGAIN);
if (result<0 && errno != EADDRINUSE)
{
fprintf(stderr,
"unable to ioctl(NWIOTCPCONN): %s\n",
strerror(errno));
goto bad;
}
if (result>=0)
break;
} while (--n > 0);
if (n == 0)
{
fprintf(stderr, "can't get port\n");
return -1;
}
if (!fd2p)
{
if (write(fd, "", 1) != 1)
{
fprintf(stderr, "unable to write: %s", strerror(errno));
goto bad;
}
}
else
{
fd2= open (tcp_device, O_RDWR);
if (fd2<0)
{
fprintf(stderr, "unable to open %s: %s\n",
tcp_device, strerror(errno));
goto bad;
}
tcpconf.nwtc_flags= NWTC_LP_SET | NWTC_UNSET_RA |
NWTC_UNSET_RP | NWTC_SHARED;
tcpconf.nwtc_locport= htons(lport);
result= ioctl(fd2, NWIOSTCPCONF, &tcpconf);
if (result<0)
{
fprintf(stderr,
"unable to ioctl(NWIOSTCPCONF): %s\n",
strerror(errno));
goto bad;
}
pid= fork();
if (pid<0)
{
fprintf(stderr, "unable to fork: %s\n",
strerror(errno));
goto bad;
}
if (!pid)
{
alarm(0);
signal(SIGALRM, SIG_DFL);
alarm(30); /* give up after half a minute */
tcpconnopt.nwtcl_flags= 0;
do
{
result= ioctl (fd2, NWIOTCPLISTEN,
&tcpconnopt);
if (result<0 && errno == EAGAIN)
{
sleep(2);
}
} while (result<0 && errno == EAGAIN);
if (result<0 && errno != EADDRINUSE)
{
fprintf(stderr,
"unable to ioctl(NWIOTCPLISTEN): %s\n",
strerror(errno));
exit(1);
}
if (result>=0)
exit(0);
else
exit(1);
}
/*
* This sleep is a HACK. The command that we are starting
* will try to connect to the fd2 port. It seems that for
* this to succeed the child process must have already made
* the call to ioctl above (the NWIOTCPLISTEN) call.
* The sleep gives the child a chance to make the call
* before the parent sends the port number to the
* command being started.
*/
sleep(1);
sprintf(num, "%d", lport);
if (write(fd, num, strlen(num)+1) != strlen(num)+1)
{
fprintf(stderr, "unable to write: %s\n",
strerror(errno));
goto bad;
}
}
write (fd, locuser, strlen(locuser)+1);
write (fd, remuser, strlen(remuser)+1);
write (fd, cmd, strlen(cmd)+1);
if (read(fd, &c, 1) != 1)
{
fprintf(stderr, "unable to read: %s\n", strerror(errno) );
goto bad;
}
if (c != 0)
{
while (read(fd, &c, 1) == 1)
{
write(2, &c, 1);
if (c == '\n')
break;
}
goto bad;
}
if (fd2p)
{
*fd2p= fd2;
result= ioctl(fd2, NWIOGTCPCONF, &tcpconf);
if (result<0)
{
fprintf(stderr, "unable to ioctl(NWIOGTCPCONF): %s\n",
strerror(errno) );
goto bad;
}
if (ntohs(tcpconf.nwtc_remport) >= TCPPORT_RESERVED)
{
fprintf(stderr, "unable to setup 2nd channel\n");
goto bad;
}
}
return fd;
bad:
if (fd>=0)
close(fd);
if (fd2>=0)
close(fd2);
return -1;
}
+351
View File
@@ -0,0 +1,351 @@
/*
* Copyright (c) 1985 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted provided
* that: (1) source distributions retain this entire copyright notice and
* comment, and (2) distributions including binaries display the following
* acknowledgement: ``This product includes software developed by the
* University of California, Berkeley and its contributors'' in the
* documentation or other materials provided with the distribution and in
* all advertising materials mentioning features or use of this software.
* Neither the name of the University nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)res_comp.c 6.18 (Berkeley) 6/27/90";
#endif /* LIBC_SCCS and not lint */
#if _MINIX
#include <sys/types.h>
#include <stdlib.h>
#include <net/gen/in.h>
#include <net/gen/nameser.h>
#include <net/gen/resolv.h>
typedef u8_t u_char;
typedef u16_t u_short;
typedef u32_t u_long;
static int dn_find _ARGS(( const u_char *exp_dn, const u_char *msg,
u_char **dnptrs, u_char **lastdnptr ));
int dn_skipname _ARGS(( const u_char *comp_dn, const u_char *eom ));
#define getshort _getshort
#define getlong _getlong
#define putshort __putshort
#define putlong __putlong
#else
#include <sys/types.h>
#include <stdio.h>
#include <arpa/nameser.h>
static dn_find();
#endif
#ifdef __STDC__
#define CONST const
#else
#define CONST
#endif
/*
* 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.
*/
dn_expand(msg, eomorig, comp_dn, exp_dn, length)
CONST u_char *msg, *eomorig, *comp_dn;
u_char *exp_dn;
int length;
{
register CONST u_char *cp;
register u_char *dn;
register int n, c;
CONST u_char *eom;
int len = -1, checked = 0;
dn = exp_dn;
cp = comp_dn;
eom = exp_dn + length;
/*
* fetch next label in domain name
*/
while (n = *cp++) {
/*
* Check for indirection
*/
switch (n & INDIR_MASK) {
case 0:
if (dn != exp_dn) {
if (dn >= eom)
return (-1);
*dn++ = '.';
}
if (dn+n >= eom)
return (-1);
checked += n + 1;
while (--n >= 0) {
if ((c = *cp++) == '.') {
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 u_char *exp_dn;
u_char *comp_dn;
int length;
u_char **dnptrs, **lastdnptr;
{
register u_char *cp;
register CONST u_char *dn;
register int c, l;
u_char **cpp, **lpp, *sp, *eob;
u_char *msg;
dn = exp_dn;
cp = comp_dn;
eob = cp + length;
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.
*/
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;
default: /* illegal type */
return (-1);
case INDIR_MASK: /* indirection */
cp++;
}
break;
}
return (cp - comp_dn);
}
/*
* 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)
CONST u_char *exp_dn, *msg;
u_char **dnptrs, **lastdnptr;
{
CONST register u_char *dn, *cp;
register u_char **cpp;
register int n;
CONST 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 (*dn++ != *cp++)
goto next;
}
if ((n = *dn++) == '\0' && *cp == '\0')
return (sp - msg);
if (n == '.')
continue;
goto next;
default: /* illegal type */
return (-1);
case INDIR_MASK: /* indirection */
cp = msg + (((n & 0x3f) << 8) | *cp);
}
}
if (*dn == '\0')
return (sp - msg);
next: ;
}
return (-1);
}
/*
* Routines to insert/extract short/long's. Must account for byte
* order and non-alignment problems. This code at least has the
* advantage of being portable.
*
* used by sendmail.
*/
u16_t
getshort(msgp)
CONST u8_t *msgp;
{
return ((msgp[0] << 8) | (msgp[1] << 0));
}
u32_t
getlong(msgp)
CONST u8_t *msgp;
{
return ( ((u32_t) msgp[0] << 24)
| ((u32_t) msgp[1] << 16)
| ((u32_t) msgp[2] << 8)
| ((u32_t) msgp[3] << 0));
}
void
putshort(s, msgp)
register U16_t s;
register u8_t *msgp;
{
msgp[1] = s;
msgp[0] = s >> 8;
}
void
putlong(l, msgp)
register u32_t l;
register u8_t *msgp;
{
msgp[3] = l;
msgp[2] = (l >>= 8);
msgp[1] = (l >>= 8);
msgp[0] = l >> 8;
}
+197
View File
@@ -0,0 +1,197 @@
/*-
* Copyright (c) 1985, 1989 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted provided
* that: (1) source distributions retain this entire copyright notice and
* comment, and (2) distributions including binaries display the following
* acknowledgement: ``This product includes software developed by the
* University of California, Berkeley and its contributors'' in the
* documentation or other materials provided with the distribution and in
* all advertising materials mentioning features or use of this software.
* Neither the name of the University nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)res_init.c 6.14 (Berkeley) 6/27/90";
#endif /* LIBC_SCCS and not lint */
#if _MINIX
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/hton.h>
#include <net/gen/in.h>
#include <net/gen/inet.h>
#include <net/gen/nameser.h>
#include <net/gen/netdb.h>
#include <net/gen/resolv.h>
#include <net/gen/socket.h>
#define index(s,c) strchr(s,c)
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <arpa/nameser.h>
#include <resolv.h>
#endif
/*
* Resolver state
*/
struct state _res;
/*
* Set up default settings. If the configuration file exist, the values
* there will have precedence. Otherwise, the server address is set to
* 127.0.0.1 (localhost) and the default domain name comes from gethostname().
*
* The configuration file should only be used if you want to redefine your
* domain or run without a server on your machine.
*
* 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 haveenv = 0;
int havesearch = 0;
struct servent* servent;
u16_t nameserver_port;
/* Resolver state default settings */
_res.retrans = RES_TIMEOUT; /* retransmition time interval */
_res.retry = 4; /* number of times to retransmit */
_res.options = RES_DEFAULT; /* options flags */
_res.nscount = 0; /* number of name servers */
_res.defdname[0] = 0; /* domain */
servent= getservbyname("domain", NULL);
if (!servent)
{
h_errno= NO_RECOVERY;
return -1;
}
nameserver_port= servent->s_port;
/* Allow user to override the local domain definition */
if ((cp = getenv("LOCALDOMAIN")) != NULL) {
(void)strncpy(_res.defdname, cp, sizeof(_res.defdname));
haveenv++;
}
if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
/* read the config file */
while (fgets(buf, sizeof(buf), fp) != NULL) {
/* read default domain name */
if (!strncmp(buf, "domain", sizeof("domain") - 1)) {
if (haveenv) /* skip if have from environ */
continue;
cp = buf + sizeof("domain") - 1;
while (*cp == ' ' || *cp == '\t')
cp++;
if ((*cp == '\0') || (*cp == '\n'))
continue;
(void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
if ((cp = index(_res.defdname, '\n')) != NULL)
*cp = '\0';
havesearch = 0;
continue;
}
/* set search list */
if (!strncmp(buf, "search", sizeof("search") - 1)) {
if (haveenv) /* skip if have from environ */
continue;
cp = buf + sizeof("search") - 1;
while (*cp == ' ' || *cp == '\t')
cp++;
if ((*cp == '\0') || (*cp == '\n'))
continue;
(void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
if ((cp = index(_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 (!strncmp(buf, "nameserver", sizeof("nameserver") - 1) &&
_res.nscount < MAXNS) {
cp = buf + sizeof("nameserver") - 1;
while (*cp == ' ' || *cp == '\t')
cp++;
if ((*cp == '\0') || (*cp == '\n'))
continue;
if (!inet_aton(cp, &_res.nsaddr_list[_res.nscount]))
continue;
_res.nsport_list[_res.nscount]= nameserver_port;
_res.nscount++;
continue;
}
}
(void) fclose(fp);
}
if (_res.nscount == 0) {
/* "localhost" is the default nameserver. */
_res.nsaddr_list[0]= HTONL(0x7F000001);
_res.nsport_list[0]= nameserver_port;
_res.nscount= 1;
}
if (_res.defdname[0] == 0) {
if (gethostname(buf, sizeof(_res.defdname)) == 0 &&
(cp = index(buf, '.')))
(void)strcpy(_res.defdname, cp + 1);
}
/* find components of local domain that might be searched */
if (havesearch == 0) {
pp = _res.dnsrch;
*pp++ = _res.defdname;
for (cp = _res.defdname, n = 0; *cp; cp++)
if (*cp == '.')
n++;
cp = _res.defdname;
for (; n >= LOCALDOMAINPARTS && pp < _res.dnsrch + MAXDFLSRCH;
n--) {
cp = index(cp, '.');
*pp++ = ++cp;
}
*pp++ = 0;
}
_res.options |= RES_INIT;
return (0);
}
+222
View File
@@ -0,0 +1,222 @@
/*
* Copyright (c) 1985 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)res_mkquery.c 6.12 (Berkeley) 6/1/90";
#endif /* LIBC_SCCS and not lint */
#if _MINIX
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <net/hton.h>
#include <net/gen/in.h>
#include <net/gen/nameser.h>
#include <net/gen/resolv.h>
typedef u16_t u_short;
typedef unsigned u_int;
typedef u32_t u_long;
#define bzero(b,l) memset(b,0,l)
#define bcopy(s,d,l) memcpy(d,s,l)
#define putshort __putshort
#define putlong __putlong
#else
#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#endif
#ifdef __STDC__
#define _CONST const
#else
#define _CONST
#endif
/*
* Form all types of queries.
* Returns the size of the result or -1.
*/
res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen)
int op; /* opcode of query */
_CONST char *dname; /* domain name */
int class, type; /* class and type of query */
_CONST char *data; /* resource record data */
int datalen; /* length of data */
_CONST struct rrec *newrr; /* new rr for modify or append */
char *buf; /* buffer to put query */
int buflen; /* size of buffer */
{
register dns_hdr_t *hp;
register char *cp;
register int n;
char *dnptrs[10], **dpp, **lastdnptr;
#ifdef DEBUG
if (_res.options & RES_DEBUG)
printf("res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type);
#endif /* DEBUG */
/*
* Initialize header fields.
*/
if ((buf == NULL) || (buflen < sizeof(dns_hdr_t)))
return(-1);
bzero(buf, sizeof(dns_hdr_t));
hp = (dns_hdr_t *) buf;
hp->dh_id = htons(++_res.id);
hp->dh_flag1= 0;
hp->dh_flag2= 0;
hp->dh_flag1 |= (op << 3) & DHF_OPCODE;
hp->dh_flag2 |= ((_res.options & RES_PRIMARY) != 0 ? 1 : 0) << 6;
hp->dh_flag1 |= (_res.options & RES_RECURSE) != 0 ? 1 : 0;
hp->dh_flag2 |= NOERROR & DHF_RCODE;
cp = buf + sizeof(dns_hdr_t);
buflen -= sizeof(dns_hdr_t);
dpp = dnptrs;
*dpp++ = buf;
*dpp++ = NULL;
lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]);
/*
* perform opcode specific processing
*/
switch (op) {
case QUERY:
if ((buflen -= QFIXEDSZ) < 0)
return(-1);
if ((n = dn_comp((u8_t *)dname, (u8_t *)cp, buflen,
(u8_t **)dnptrs, (u8_t **)lastdnptr)) < 0)
return (-1);
cp += n;
buflen -= n;
putshort(type, (u8_t *)cp);
cp += sizeof(u_short);
putshort(class, (u8_t *)cp);
cp += sizeof(u_short);
hp->dh_qdcount = HTONS(1);
if (op == QUERY || data == NULL)
break;
/*
* Make an additional record for completion domain.
*/
buflen -= RRFIXEDSZ;
if ((n = dn_comp((u8_t *)data, (u8_t *)cp, buflen,
(u8_t **)dnptrs, (u8_t **)lastdnptr)) < 0)
return (-1);
cp += n;
buflen -= n;
putshort(T_NULL, (u8_t *)cp);
cp += sizeof(u_short);
putshort(class, (u8_t *)cp);
cp += sizeof(u_short);
putlong(0, (u8_t *)cp);
cp += sizeof(u_long);
putshort(0, (u8_t *)cp);
cp += sizeof(u_short);
hp->dh_arcount = HTONS(1);
break;
case IQUERY:
/*
* Initialize answer section
*/
if (buflen < 1 + RRFIXEDSZ + datalen)
return (-1);
*cp++ = '\0'; /* no domain name */
putshort(type, (u8_t *)cp);
cp += sizeof(u_short);
putshort(class, (u8_t *)cp);
cp += sizeof(u_short);
putlong(0, (u8_t *)cp);
cp += sizeof(u_long);
putshort(datalen, (u8_t *)cp);
cp += sizeof(u_short);
if (datalen) {
bcopy(data, cp, datalen);
cp += datalen;
}
hp->dh_ancount = HTONS(1);
break;
#ifdef ALLOW_UPDATES
/*
* For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
* (Record to be modified is followed by its replacement in msg.)
*/
case UPDATEM:
case UPDATEMA:
case UPDATED:
/*
* The res code for UPDATED and UPDATEDA is the same; user
* calls them differently: specifies data for UPDATED; server
* ignores data if specified for UPDATEDA.
*/
case UPDATEDA:
buflen -= RRFIXEDSZ + datalen;
if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
return (-1);
cp += n;
putshort(type, cp);
cp += sizeof(u_short);
putshort(class, cp);
cp += sizeof(u_short);
putlong(0, cp);
cp += sizeof(u_long);
putshort(datalen, cp);
cp += sizeof(u_short);
if (datalen) {
bcopy(data, cp, datalen);
cp += datalen;
}
if ( (op == UPDATED) || (op == UPDATEDA) ) {
hp->ancount = HTONS(0);
break;
}
/* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
case UPDATEA: /* Add new resource record */
buflen -= RRFIXEDSZ + datalen;
if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
return (-1);
cp += n;
putshort(newrr->r_type, cp);
cp += sizeof(u_short);
putshort(newrr->r_class, cp);
cp += sizeof(u_short);
putlong(0, cp);
cp += sizeof(u_long);
putshort(newrr->r_size, cp);
cp += sizeof(u_short);
if (newrr->r_size) {
bcopy(newrr->r_data, cp, newrr->r_size);
cp += newrr->r_size;
}
hp->ancount = HTONS(0);
break;
#endif /* ALLOW_UPDATES */
}
return (cp - buf);
}
+299
View File
@@ -0,0 +1,299 @@
/*
* Copyright (c) 1988 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by the University of California, Berkeley and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)res_query.c 5.7 (Berkeley) 6/1/90";
#endif /* LIBC_SCCS and not lint */
#if _MINIX
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <net/hton.h>
#include <net/gen/in.h>
#include <net/gen/nameser.h>
#include <net/gen/netdb.h>
#include <net/gen/resolv.h>
typedef u8_t u_char;
#define bcopy(s,d,l) memcpy(d,s,l)
#define hostalias __hostalias
#else
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <ctype.h>
#include <netdb.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <resolv.h>
extern int errno;
#endif
#if __STDC__
#define CONST const
#else
#define CONST
#endif
#if PACKETSZ > 1024
#define MAXPACKET PACKETSZ
#else
#define MAXPACKET 1024
#endif
int h_errno;
/*
* 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)
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 */
{
char buf[MAXPACKET];
dns_hdr_t *hp;
int n;
if ((_res.options & RES_INIT) == 0 && res_init() == -1)
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, (char *)NULL, 0, NULL,
buf, sizeof(buf));
if (n <= 0) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
printf("res_query: mkquery failed\n");
#endif
h_errno = NO_RECOVERY;
return (n);
}
n = res_send(buf, n, (char *)answer, anslen);
if (n < 0) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
printf("res_query: send error(%d)\n", errno);
#endif
h_errno = TRY_AGAIN;
return(n);
}
hp = (dns_hdr_t *) answer;
if ((hp->dh_flag2 & DHF_RCODE) != NOERROR ||
ntohs(hp->dh_ancount) == 0) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
printf("rcode = %d, ancount=%d\n",
hp->dh_flag2 & DHF_RCODE,
ntohs(hp->dh_ancount));
#endif
switch (hp->dh_flag2 & DHF_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 number is left in h_errno.
* Only useful for queries in the same name hierarchy as the local host
* (not, for example, for host address-to-name lookups in domain in-addr.arpa).
*/
res_search(name, class, type, answer, anslen)
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 char *cp, **domain;
int n, ret, got_nodata = 0;
if ((_res.options & RES_INIT) == 0 && res_init() == -1)
return (-1);
errno = 0;
h_errno = HOST_NOT_FOUND; /* default, if we never query */
for (cp = name, n = 0; *cp; cp++)
if (*cp == '.')
n++;
if (n == 0 && (cp = hostalias(name)))
return (res_query(cp, class, type, answer, anslen));
/*
* 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 ((n == 0 && _res.options & RES_DEFNAMES) ||
(n != 0 && *--cp != '.' && _res.options & RES_DNSRCH))
for (domain = _res.dnsrch; *domain; 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);
}
if (h_errno == NO_DATA)
got_nodata++;
if ((h_errno != HOST_NOT_FOUND && h_errno != NO_DATA) ||
(_res.options & RES_DNSRCH) == 0)
break;
}
/*
* If the search/default failed, try the name as fully-qualified,
* but only if it contained at least one dot (even trailing).
* This is purely a heuristic; we assume that any reasonable query
* about a top-level domain (for servers, SOA, etc) will not use
* res_search.
*/
if (n && (ret = res_querydomain(name, (char *)NULL, class, type,
answer, anslen)) > 0)
return (ret);
if (got_nodata)
h_errno = NO_DATA;
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)
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[2*MAXDNAME+2];
char *longname = nbuf;
int n;
#ifdef DEBUG
if (_res.options & RES_DEBUG)
printf("res_querydomain(%s, %s, %d, %d)\n",
name, domain, class, type);
#endif
if (domain == NULL) {
/*
* Check for trailing '.';
* copy without '.' if present.
*/
n = strlen(name) - 1;
if (name[n] == '.' && n < sizeof(nbuf) - 1) {
bcopy(name, nbuf, n);
nbuf[n] = '\0';
} else
longname = name;
} else
(void)sprintf(nbuf, "%.*s.%.*s",
MAXDNAME, name, MAXDNAME, domain);
return (res_query(longname, class, type, answer, anslen));
}
char *
hostalias(name)
register CONST char *name;
{
register char *C1, *C2;
FILE *fp;
char *file;
char buf[BUFSIZ];
static char abuf[MAXDNAME];
file = getenv("HOSTALIASES");
if (file == NULL || (fp = fopen(file, "r")) == NULL)
return (NULL);
buf[sizeof(buf) - 1] = '\0';
while (fgets(buf, sizeof(buf), fp)) {
for (C1 = buf; *C1 && !isspace(*C1); ++C1);
if (!*C1)
break;
*C1 = '\0';
if (!strcasecmp(buf, name)) {
while (isspace(*++C1));
if (!*C1)
break;
for (C2 = C1 + 1; *C2 && !isspace(*C2); ++C2);
abuf[sizeof(abuf) - 1] = *C2 = '\0';
(void)strncpy(abuf, C1, sizeof(abuf) - 1);
fclose(fp);
return (abuf);
}
}
fclose(fp);
return (NULL);
}
+905
View File
@@ -0,0 +1,905 @@
/*
* Copyright (c) 1985, 1989 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)res_send.c 6.27 (Berkeley) 2/24/91";
#endif /* LIBC_SCCS and not lint */
/*
* Send query to name server and wait for reply.
*/
#if !_MINIX
#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 <stdio.h>
#include <errno.h>
#include <resolv.h>
#include <unistd.h>
#include <string.h>
#else /* _MINIX */
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/hton.h>
#include <net/netlib.h>
#include <net/gen/in.h>
#include <net/gen/inet.h>
#include <net/gen/netdb.h>
#include <net/gen/nameser.h>
#include <net/gen/resolv.h>
#include <net/gen/tcp.h>
#include <net/gen/tcp_io.h>
#include <net/gen/udp.h>
#include <net/gen/udp_hdr.h>
#include <net/gen/udp_io.h>
typedef u16_t u_short;
static int tcp_connect _ARGS(( ipaddr_t host, Tcpport_t port, int *terrno ));
static int tcpip_writeall _ARGS(( int fd, const char *buf, size_t siz ));
static int udp_connect _ARGS(( void ));
static int udp_sendto _ARGS(( int fd, const char *buf, unsigned buflen,
ipaddr_t addr, Udpport_t port ));
static int udp_receive _ARGS(( int fd, char *buf, unsigned buflen,
time_t timeout ));
static void alarm_handler _ARGS(( int sig ));
#endif /* !_MINIX */
static int s = -1; /* socket used for communications */
#if !_MINIX
static struct sockaddr no_addr;
#ifndef FD_SET
#define NFDBITS 32
#define FD_SETSIZE 32
#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
#endif /* FD_SET */
#endif /* _MINIX */
res_send(buf, buflen, answer, anslen)
const char *buf;
int buflen;
char *answer;
int anslen;
{
register int n;
int try, v_circuit, resplen, ns;
int gotsomewhere = 0, connected = 0;
int connreset = 0;
#if !_MINIX
u_short id, len;
#else /* _MINIX */
u16_t id, len;
#endif /* !_MINIX */
char *cp;
#if !_MINIX
fd_set dsmask;
struct timeval timeout;
HEADER *hp = (HEADER *) buf;
HEADER *anhp = (HEADER *) answer;
struct iovec iov[2];
#else /* _MINIX */
time_t timeout;
dns_hdr_t *hp = (dns_hdr_t *) buf;
dns_hdr_t *anhp = (dns_hdr_t *) answer;
#endif /* !_MINIX */
int terrno = ETIMEDOUT;
char junk[512];
#ifdef DEBUG
if (_res.options & RES_DEBUG) {
printf("res_send()\n");
__p_query(buf);
}
#endif /* DEBUG */
if (!(_res.options & RES_INIT))
if (res_init() == -1) {
return(-1);
}
v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
#if !_MINIX
id = hp->id;
#else /* _MINIX */
id = hp->dh_id;
#endif /* !_MINIX */
/*
* Send request, RETRY times, or until successful
*/
for (try = 0; try < _res.retry; try++) {
for (ns = 0; ns < _res.nscount; ns++) {
#ifdef DEBUG
#if !_MINIX
if (_res.options & RES_DEBUG)
printf("Querying server (# %d) address = %s\n", ns+1,
inet_ntoa(_res.nsaddr_list[ns].sin_addr));
#else /* _MINIX */
if (_res.options & RES_DEBUG)
printf("Querying server (# %d) address = %s\n", ns+1,
inet_ntoa(_res.nsaddr_list[ns]));
#endif /* !_MINIX */
#endif /* DEBUG */
usevc:
if (v_circuit) {
#if !_MINIX
int truncated = 0;
/*
* Use virtual circuit;
* at most one attempt per server.
*/
try = _res.retry;
if (s < 0) {
s = socket(AF_INET, SOCK_STREAM, 0);
if (s < 0) {
terrno = errno;
#ifdef DEBUG
if (_res.options & RES_DEBUG)
perror("socket (vc) failed");
#endif /* DEBUG */
continue;
}
if (connect(s,
(struct sockaddr *)&(_res.nsaddr_list[ns]),
sizeof(struct sockaddr)) < 0) {
terrno = errno;
#ifdef DEBUG
if (_res.options & RES_DEBUG)
perror("connect failed");
#endif /* DEBUG */
(void) close(s);
s = -1;
continue;
}
}
/*
* Send length & message
*/
len = htons((u_short)buflen);
iov[0].iov_base = (caddr_t)&len;
iov[0].iov_len = sizeof(len);
iov[1].iov_base = (char *)buf;
iov[1].iov_len = buflen;
if (writev(s, iov, 2) != sizeof(len) + buflen) {
terrno = errno;
#ifdef DEBUG
if (_res.options & RES_DEBUG)
perror("write failed");
#endif /* DEBUG */
(void) close(s);
s = -1;
continue;
}
/*
* Receive length & response
*/
cp = answer;
len = sizeof(short);
while (len != 0 &&
(n = read(s, (char *)cp, (int)len)) > 0) {
cp += n;
len -= n;
}
if (n <= 0) {
terrno = errno;
#ifdef DEBUG
if (_res.options & RES_DEBUG)
perror("read failed");
#endif /* DEBUG */
(void) close(s);
s = -1;
/*
* 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;
ns--;
}
continue;
}
cp = answer;
if ((resplen = ntohs(*(u_short *)cp)) > anslen) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
fprintf(stderr, "response truncated\n");
#endif /* DEBUG */
len = anslen;
truncated = 1;
} else
len = resplen;
while (len != 0 &&
(n = read(s, (char *)cp, (int)len)) > 0) {
cp += n;
len -= n;
}
if (n <= 0) {
terrno = errno;
#ifdef DEBUG
if (_res.options & RES_DEBUG)
perror("read failed");
#endif /* DEBUG */
(void) close(s);
s = -1;
continue;
}
if (truncated) {
/*
* Flush rest of answer
* so connection stays in synch.
*/
anhp->tc = 1;
len = resplen - anslen;
while (len != 0) {
n = (len > sizeof(junk) ?
sizeof(junk) : len);
if ((n = read(s, junk, n)) > 0)
len -= n;
else
break;
}
}
#else /* _MINIX */
int truncated = 0;
int nbytes;
/*
* Use virtual circuit;
* at most one attempt per server.
*/
try = _res.retry;
if (s < 0)
{
s= tcp_connect(_res.nsaddr_list[ns],
_res.nsport_list[ns], &terrno);
if (s == -1)
continue;
}
/*
* Send length & message
*/
len = htons((u_short)buflen);
nbytes= tcpip_writeall(s, (char *)&len,
sizeof(len));
if (nbytes != sizeof(len))
{
terrno= errno;
#ifdef DEBUG
if (_res.options & RES_DEBUG)
fprintf(stderr, "write failed: %s\n",
strerror(terrno));
#endif /* DEBUG */
close(s);
s= -1;
continue;
}
nbytes= tcpip_writeall(s, buf, buflen);
if (nbytes != buflen)
{
terrno= errno;
#ifdef DEBUG
if (_res.options & RES_DEBUG)
fprintf(stderr, "write failed: %s\n",
strerror(terrno));
#endif /* DEBUG */
close(s);
s= -1;
continue;
}
/*
* Receive length & response
*/
cp = answer;
len = sizeof(short);
while (len != 0)
{
n = read(s, (char *)cp, (int)len);
if (n <= 0)
break;
cp += n;
assert(len >= n);
len -= n;
}
if (len) {
terrno = errno;
#ifdef DEBUG
if (_res.options & RES_DEBUG)
fprintf(stderr, "read failed: %s\n",
strerror(terrno));
#endif /* DEBUG */
close(s);
s= -1;
/*
* 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;
ns--;
}
continue;
}
cp = answer;
if ((resplen = ntohs(*(u_short *)cp)) > anslen) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
fprintf(stderr, "response truncated\n");
#endif /* DEBUG */
len = anslen;
truncated = 1;
} else
len = resplen;
while (len != 0)
{
n= read(s, (char *)cp, (int)len);
if (n <= 0)
break;
cp += n;
assert(len >= n);
len -= n;
}
if (len) {
terrno = errno;
#ifdef DEBUG
if (_res.options & RES_DEBUG)
fprintf(stderr, "read failed: %s\n",
strerror(terrno));
#endif /* DEBUG */
close(s);
s= -1;
continue;
}
if (truncated) {
/*
* Flush rest of answer
* so connection stays in synch.
*/
anhp->dh_flag1 |= DHF_TC;
len = resplen - anslen;
while (len != 0) {
n = (len > sizeof(junk) ?
sizeof(junk) : len);
n = read(s, junk, n);
if (n <= 0)
{
assert(len >= n);
len -= n;
}
else
break;
}
}
#endif /* _MINIX */
} else {
#if !_MINIX
/*
* Use datagrams.
*/
if (s < 0) {
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
terrno = errno;
#ifdef DEBUG
if (_res.options & RES_DEBUG)
perror("socket (dg) failed");
#endif /* DEBUG */
continue;
}
}
#if BSD >= 43
/*
* I'm tired of answering this question, so:
* On a 4.3BSD+ machine (client and server,
* actually), sending to a nameserver datagram
* port with no nameserver will cause an
* ICMP port unreachable message to be returned.
* If our datagram socket is "connected" to the
* server, we get an ECONNREFUSED error on the next
* socket operation, and select returns if the
* error message is received. We can thus detect
* the absence of a nameserver without timing out.
* If we have sent queries to at least two servers,
* however, we don't want to remain connected,
* as we wish to receive answers from the first
* server to respond.
*/
if (_res.nscount == 1 || (try == 0 && ns == 0)) {
/*
* Don't use connect if we might
* still receive a response
* from another server.
*/
if (connected == 0) {
if (connect(s, (struct sockaddr *)&_res.nsaddr_list[ns],
sizeof(struct sockaddr)) < 0) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
perror("connect");
#endif /* DEBUG */
continue;
}
connected = 1;
}
if (send(s, buf, buflen, 0) != buflen) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
perror("send");
#endif /* DEBUG */
continue;
}
} else {
/*
* Disconnect if we want to listen
* for responses from more than one server.
*/
if (connected) {
(void) connect(s, &no_addr,
sizeof(no_addr));
connected = 0;
}
#endif /* BSD */
if (sendto(s, buf, buflen, 0,
(struct sockaddr *)&_res.nsaddr_list[ns],
sizeof(struct sockaddr)) != buflen) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
perror("sendto");
#endif /* DEBUG */
continue;
}
#if BSD >= 43
}
#endif /* BSD */
/*
* Wait for reply
*/
timeout.tv_sec = (_res.retrans << try);
if (try > 0)
timeout.tv_sec /= _res.nscount;
if (timeout.tv_sec <= 0)
timeout.tv_sec = 1;
timeout.tv_usec = 0;
wait:
FD_ZERO(&dsmask);
FD_SET(s, &dsmask);
n = select(s+1, &dsmask, (fd_set *)NULL,
(fd_set *)NULL, &timeout);
if (n < 0) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
perror("select");
#endif /* DEBUG */
continue;
}
if (n == 0) {
/*
* timeout
*/
#ifdef DEBUG
if (_res.options & RES_DEBUG)
printf("timeout\n");
#endif /* DEBUG */
#if BSD >= 43
gotsomewhere = 1;
#endif
continue;
}
if ((resplen = recv(s, answer, anslen, 0)) <= 0) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
perror("recvfrom");
#endif /* DEBUG */
continue;
}
gotsomewhere = 1;
if (id != anhp->id) {
/*
* response from old query, ignore it
*/
#ifdef DEBUG
if (_res.options & RES_DEBUG) {
printf("old answer:\n");
__p_query(answer);
}
#endif /* DEBUG */
goto wait;
}
if (!(_res.options & RES_IGNTC) && anhp->tc) {
/*
* get rest of answer;
* use TCP with same server.
*/
#ifdef DEBUG
if (_res.options & RES_DEBUG)
printf("truncated answer\n");
#endif /* DEBUG */
(void) close(s);
s = -1;
v_circuit = 1;
goto usevc;
}
#else /* _MINIX */
/*
* Use datagrams.
*/
if (s < 0) {
s = udp_connect();
if (s < 0) {
terrno = errno;
#ifdef DEBUG
if (_res.options & RES_DEBUG)
perror("udp_connect failed");
#endif /* DEBUG */
continue;
}
}
if (udp_sendto(s, buf, buflen, _res.nsaddr_list[ns],
_res.nsport_list[ns]) != buflen) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
perror("sendto");
#endif /* DEBUG */
continue;
}
/*
* Wait for reply
*/
timeout= (_res.retrans << try);
if (try > 0)
timeout /= _res.nscount;
if (timeout <= 0)
timeout= 1;
wait:
if ((resplen= udp_receive(s, answer, anslen, timeout))
== -1)
{
if (errno == EINTR)
{
/*
* timeout
*/
#ifdef DEBUG
if (_res.options & RES_DEBUG)
printf("timeout\n");
#endif /* DEBUG */
gotsomewhere = 1;
}
else
{
#ifdef DEBUG
if (_res.options & RES_DEBUG)
perror("udp_receive");
#endif /* DEBUG */
}
continue;
}
gotsomewhere = 1;
if (id != anhp->dh_id) {
/*
* response from old query, ignore it
*/
#ifdef DEBUG
if (_res.options & RES_DEBUG) {
printf("old answer:\n");
__p_query(answer);
}
#endif /* DEBUG */
goto wait;
}
if (!(_res.options & RES_IGNTC) &&
(anhp->dh_flag1 & DHF_TC)) {
/*
* get rest of answer;
* use TCP with same server.
*/
#ifdef DEBUG
if (_res.options & RES_DEBUG)
printf("truncated answer\n");
#endif /* DEBUG */
(void) close(s);
s = -1;
v_circuit = 1;
goto usevc;
}
#endif /* !_MINIX */
}
#ifdef DEBUG
if (_res.options & RES_DEBUG) {
printf("got answer:\n");
__p_query(answer);
}
#endif /* DEBUG */
/*
* 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) == 0 || ns != 0)) ||
(_res.options & RES_STAYOPEN) == 0) {
(void) close(s);
s = -1;
}
return (resplen);
}
}
if (s >= 0) {
(void) close(s);
s = -1;
}
if (v_circuit == 0)
if (gotsomewhere == 0)
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 != -1) {
(void) close(s);
s = -1;
}
}
#if _MINIX
static int tcp_connect(host, port, terrno)
ipaddr_t host;
tcpport_t port;
int *terrno;
{
char *dev_name;
int fd;
int error;
nwio_tcpconf_t tcpconf;
nwio_tcpcl_t clopt;
dev_name= getenv("TCP_DEVICE");
if (!dev_name)
dev_name= TCP_DEVICE;
fd= open(dev_name, O_RDWR);
if (fd == -1)
{
*terrno= errno;
return -1;
}
tcpconf.nwtc_flags= NWTC_EXCL | NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP;
tcpconf.nwtc_remaddr= host;
tcpconf.nwtc_remport= port;
error= ioctl(fd, NWIOSTCPCONF, &tcpconf);
if (error == -1)
{
*terrno= errno;
close(fd);
return -1;
}
clopt.nwtcl_flags= 0;
error= ioctl(fd, NWIOTCPCONN, &clopt);
if (error == -1)
{
*terrno= errno;
close(fd);
return -1;
}
*terrno= 0;
return fd;
}
static int tcpip_writeall(fd, buf, siz)
int fd;
const char *buf;
size_t siz;
{
size_t siz_org;
int nbytes;
siz_org= siz;
while (siz)
{
nbytes= write(fd, buf, siz);
if (nbytes <= 0)
return siz_org-siz;
assert(siz >= nbytes);
buf += nbytes;
siz -= nbytes;
}
return siz_org;
}
static int udp_connect()
{
nwio_udpopt_t udpopt;
char *dev_name;
int fd, r, terrno;
dev_name= getenv("UDP_DEVICE");
if (!dev_name)
dev_name= UDP_DEVICE;
fd= open(dev_name, O_RDWR);
if (fd == -1)
return -1;
udpopt.nwuo_flags= NWUO_COPY | NWUO_LP_SEL | NWUO_EN_LOC |
NWUO_EN_BROAD | NWUO_RP_ANY | NWUO_RA_ANY | NWUO_RWDATALL |
NWUO_DI_IPOPT;
r= ioctl(fd, NWIOSUDPOPT, &udpopt);
if (r == -1)
{
terrno= errno;
close(fd);
errno= terrno;
return -1;
}
return fd;
}
static int udp_sendto(fd, buf, buflen, addr, port)
int fd;
const char *buf;
unsigned buflen;
ipaddr_t addr;
udpport_t port;
{
char *newbuf;
udp_io_hdr_t *udp_io_hdr;
int r, terrno;
newbuf= malloc(sizeof(*udp_io_hdr) + buflen);
if (newbuf == NULL)
{
errno= ENOMEM;
return -1;
}
udp_io_hdr= (udp_io_hdr_t *)newbuf;
udp_io_hdr->uih_dst_addr= addr;
udp_io_hdr->uih_dst_port= port;
udp_io_hdr->uih_ip_opt_len= 0;
udp_io_hdr->uih_data_len= buflen;
memcpy(newbuf + sizeof(*udp_io_hdr), buf, buflen);
r= write(fd, newbuf, sizeof(*udp_io_hdr) + buflen);
terrno= errno;
free(newbuf);
if (r >= sizeof(*udp_io_hdr))
r -= sizeof(*udp_io_hdr);
errno= terrno;
return r;
}
static void alarm_handler(sig)
int sig;
{
signal(SIGALRM, alarm_handler);
alarm(1);
}
static int udp_receive(fd, buf, buflen, timeout)
int fd;
char *buf;
unsigned buflen;
time_t timeout;
{
char *newbuf;
udp_io_hdr_t *udp_io_hdr;
int r, terrno;
void (*u_handler) _ARGS(( int sig ));
time_t u_timeout;
newbuf= malloc(sizeof(*udp_io_hdr) + buflen);
if (newbuf == NULL)
{
errno= ENOMEM;
return -1;
}
u_handler= signal(SIGALRM, alarm_handler);
u_timeout= alarm(timeout);
r= read(fd, newbuf, sizeof(*udp_io_hdr) + buflen);
terrno= errno;
if (r < 0 || r <= sizeof(*udp_io_hdr))
{
if (r > 0)
r= 0;
free(newbuf);
alarm(0);
signal(SIGALRM, u_handler);
alarm(u_timeout);
errno= terrno;
return r;
}
memcpy(buf, newbuf + sizeof(*udp_io_hdr), r - sizeof(*udp_io_hdr));
free(newbuf);
alarm(0);
signal(SIGALRM, u_handler);
alarm(u_timeout);
return r-sizeof(*udp_io_hdr);
}
#endif
+187
View File
@@ -0,0 +1,187 @@
/* ruserok() - hosts.equiv and .rhosts check Author: Kees J. Bot
* 25 May 2001
*
* Under Minix one can use IP addresses, CIDR network blocks, and hostnames
* with wildcards in .rhosts files. Only the iruserok() interface can be
* used, and the IP address is reverse/forward crosschecked if a hostname
* match is done. Ruserok() is dead and buried. The superuser parameter is
* ignored, because it makes root too special. Most users on Minix can be
* root, so hosts.equiv would become useless if root can't use it. Likewise
* .rhosts isn't checked to be root or user owned and stuff, users have to
* be careful themselves.
*/
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <limits.h>
#include <pwd.h>
#include <net/hton.h>
#include <net/gen/in.h>
#include <net/gen/netdb.h>
#include <net/gen/inet.h>
#include <net/gen/socket.h>
#include <net/gen/nameser.h>
/* Odd global variable. Seems to be used by lpd(8). */
int __check_rhosts_file = 1;
static int cidr_aton(char *word, ipaddr_t *addr, ipaddr_t *mask)
/* Try to interpret 'word' as an CIDR spec, e.g. 172.16.102.64/27. */
{
char *slash;
int r;
static char S32[]= "/32";
if (*word == 0) return 0;
if ((slash= strchr(word, '/')) == NULL) slash= S32;
*slash= 0;
r= inet_aton(word, addr);
*slash++= '/';
if (!r) return 0;
r= 0;
while ((*slash - '0') < 10u) {
r= 10*r + (*slash++ - '0');
if (r > 32) return 0;
}
if (*slash != 0 || slash[-1] == '/') return 0;
*mask= htonl(r == 0 ? 0L : (0xFFFFFFFFUL >> (32 - r)) << (32 - r));
return 1;
}
static int match(const char *word, const char *pattern)
/* Match word onto a pattern. Pattern may contain the * wildcard. */
{
unsigned cw, cp;
#define lc(c, d) ((((c)= (d)) - 'A') <= ('Z' - 'A') ? (c)+= ('a' - 'A') : 0)
for (;;) {
lc(cw, *word);
lc(cp, *pattern);
if (cp == '*') {
do pattern++; while (*pattern == '*');
lc(cp, *pattern);
if (cp == 0) return 1;
while (cw != 0) {
if (cw == cp && match(word+1, pattern+1)) return 1;
word++;
lc(cw, *word);
}
return 0;
} else
if (cw == 0 || cp == 0) {
return cw == cp;
} else
if (cw == cp) {
word++;
pattern++;
} else {
return 0;
}
}
#undef lc
}
static int get_name(ipaddr_t addr, char *name)
/* Do a reverse lookup on the remote IP address followed by a forward lookup
* to check if the host has that address. Return true if this is so, return
* either the true name or the ascii IP address in name[].
*/
{
struct hostent *he;
int ok, i;
ok= 0;
he= gethostbyaddr((char *) &addr, sizeof(addr), AF_INET);
if (he != NULL) {
strcpy(name, he->h_name);
he= gethostbyname(name);
if (he != NULL && he->h_addrtype == AF_INET) {
for (i= 0; he->h_addr_list[i] != NULL; i++) {
if (memcmp(he->h_addr_list[i], &addr, sizeof(addr)) == 0) {
ok= 1;
break;
}
}
}
}
strcpy(name, ok ? he->h_name : inet_ntoa(addr));
return ok;
}
int __ivaliduser(FILE *hostf, unsigned long raddr,
const char *luser, const char *ruser)
{
register char *p;
char buf[MAXDNAME + 128]; /* host + login */
char rhost[MAXDNAME]; /* remote host */
char *word[2];
int i, ch, got_name;
ipaddr_t addr, mask;
got_name = -1;
while (fgets(buf, sizeof(buf), hostf)) {
/* Skip lines that are too long. */
if (strchr(buf, '\n') == NULL) {
while ((ch = fgetc(hostf)) != '\n' && ch != EOF);
continue;
}
i = 0;
p = buf;
for (;;) {
while (isspace(*p)) *p++ = '\0';
if (*p == '\0') break;
if (i < 2) word[i] = p;
i++;
while (*p != '\0' && !isspace(*p)) p++;
}
if (i != 1 && i != 2) continue;
if (word[0][0] == '#') continue;
if (strcmp(ruser, i == 2 ? word[1] : luser) != 0) continue;
if (cidr_aton(word[0], &addr, &mask)) {
if (((raddr ^ addr) & mask) == 0) return (0);
continue;
}
if (got_name == -1) got_name = get_name(raddr, rhost);
if (match(rhost, word[0])) return (0);
}
return (-1);
}
int iruserok(unsigned long raddr, int superuser,
const char *ruser, const char *luser)
{
/* Returns 0 if ok, -1 if not ok. */
struct passwd *pwd;
FILE *hostf;
int i, r;
char pbuf[PATH_MAX];
for (i = 0; i < 2; i++) {
if (i == 0) {
strcpy(pbuf, _PATH_HEQUIV);
} else {
if (!__check_rhosts_file) return (-1);
if ((pwd = getpwnam(luser)) == NULL) return (-1);
(void)strcpy(pbuf, pwd->pw_dir);
(void)strcat(pbuf, "/.rhosts");
}
if ((hostf = fopen(pbuf, "r")) == NULL) return (-1);
r = __ivaliduser(hostf, raddr, luser, ruser);
(void)fclose(hostf);
if (r == 0) return (0);
}
return (-1);
}
+302
View File
@@ -0,0 +1,302 @@
/* servxcheck() - Service access check. Author: Kees J. Bot
* 8 Jan 1997
*/
#define nil 0
#define ioctl _ioctl
#define open _open
#define write _write
#define close _close
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <sys/ioctl.h>
#include <net/hton.h>
#include <net/gen/in.h>
#include <net/gen/tcp.h>
#include <net/gen/tcp_io.h>
#include <net/gen/inet.h>
#include <net/gen/socket.h>
#include <net/gen/netdb.h>
/* Default service access file. */
static const char *path_servacces = _PATH_SERVACCES;
#define WLEN 256
static int getword(FILE *fp, char *word)
/* Read a word from the file open by 'fp', skip whitespace and comments.
* Colon and semicolon are returned as a one character "word". Returns
* word[0] or EOF.
*/
{
int c;
char *pw;
int wc;
wc= 0;
for (;;) {
if ((c= getc(fp)) == EOF) return EOF;
if (c == '#') { wc= 1; continue; }
if (c == '\n') { wc= 0; continue; }
if (wc) continue;
if (c <= ' ') continue;
break;
}
pw= word;
if (c == ':' || c == ';') {
*pw++ = c;
} else {
do {
if (pw < word + WLEN-1) *pw++ = c;
c= getc(fp);
} while (c != EOF && c > ' ' && c != ':' && c != ';');
if (c != EOF) ungetc(c, fp);
}
*pw= 0;
return word[0];
}
static int netspec(char *word, ipaddr_t *addr, ipaddr_t *mask)
/* Try to interpret 'word' as an network spec, e.g. 172.16.102.64/27. */
{
char *slash;
int r;
static char S32[]= "/32";
if (*word == 0) return 0;
if ((slash= strchr(word, '/')) == NULL) slash= S32;
*slash= 0;
r= inet_aton(word, addr);
*slash++= '/';
if (!r) return 0;
r= 0;
while ((*slash - '0') < 10u) {
r= 10*r + (*slash++ - '0');
if (r > 32) return 0;
}
if (*slash != 0 || slash[-1] == '/') return 0;
*mask= htonl(r == 0 ? 0L : (0xFFFFFFFFUL >> (32 - r)) << (32 - r));
return 1;
}
static int match(const char *word, const char *pattern)
/* Match word onto a pattern. Pattern may contain the * wildcard. */
{
unsigned cw, cp;
#define lc(c, d) ((((c)= (d)) - 'A') <= ('Z' - 'A') ? (c)+= ('a' - 'A') : 0)
for (;;) {
lc(cw, *word);
lc(cp, *pattern);
if (cp == '*') {
do pattern++; while (*pattern == '*');
lc(cp, *pattern);
if (cp == 0) return 1;
while (cw != 0) {
if (cw == cp && match(word+1, pattern+1)) return 1;
word++;
lc(cw, *word);
}
return 0;
} else
if (cw == 0 || cp == 0) {
return cw == cp;
} else
if (cw == cp) {
word++;
pattern++;
} else {
return 0;
}
}
#undef lc
}
static int get_name(ipaddr_t addr, char *name)
/* Do a reverse lookup on the remote IP address followed by a forward lookup
* to check if the host has that address. Return true if this is so, return
* either the true name or the ascii IP address in name[].
*/
{
struct hostent *he;
int i;
he= gethostbyaddr((char *) &addr, sizeof(addr), AF_INET);
if (he != NULL) {
strcpy(name, he->h_name);
he= gethostbyname(name);
if (he != NULL && he->h_addrtype == AF_INET) {
for (i= 0; he->h_addr_list[i] != NULL; i++) {
if (memcmp(he->h_addr_list[i], &addr, sizeof(addr)) == 0) {
strcpy(name, he->h_name);
return 1;
}
}
}
}
strcpy(name, inet_ntoa(addr));
return 0;
}
/* "state" and "log" flags, made to be bitwise comparable. */
#define DEFFAIL 0x01
#define FAIL (0x02 | DEFFAIL)
#define PASS 0x04
int servxcheck(ipaddr_t peer, const char *service,
void (*logf)(int pass, const char *name))
{
FILE *fp;
char word[WLEN];
char name[WLEN];
int c;
int got_name, slist, seen, explicit, state, log;
ipaddr_t addr, mask;
/* Localhost? */
if ((peer & HTONL(0xFF000000)) == HTONL(0x7F000000)) return 1;
if ((fp= fopen(path_servacces, "r")) == nil) {
/* Succeed on error, fail if simply nonexistent. */
return (errno != ENOENT);
}
slist= 1; /* Services list (before the colon.) */
seen= 0; /* Given service not yet seen. */
explicit= 0; /* Service mentioned explicitly. */
got_name= -1; /* No reverse lookup done yet. */
log= FAIL; /* By default log failures only. */
state= DEFFAIL; /* Access denied until we know better. */
while ((c= getword(fp, word)) != EOF) {
if (c == ':') {
slist= 0; /* Switch to access list. */
} else
if (c == ';') {
slist= 1; /* Back to list of services. */
seen= 0;
} else
if (slist) {
/* Traverse services list. */
if (match(service, word)) {
/* Service has been spotted! */
if (match(word, service)) {
/* Service mentioned without wildcards. */
seen= explicit= 1;
} else {
/* Matched by a wildcard. */
if (!explicit) seen= 1;
}
}
} else {
/* Traverse access list. */
if (c == 'l' && strcmp(word, "log") == 0) {
if (seen) {
/* Log failures and successes. */
log= FAIL|PASS;
}
continue;
}
if (c != '-' && c != '+') {
if (logf == nil) {
fprintf(stderr, "%s: strange check word '%s'\n",
path_servacces, word);
}
continue;
}
if (seen) {
if (state == DEFFAIL) {
/* First check determines the default. */
state= c == '+' ? FAIL : PASS;
}
if ((state == PASS) == (c == '+')) {
/* This check won't change state. */
} else
if (word[1] == 0) {
/* Lone + or - allows all or none. */
state= c == '-' ? FAIL : PASS;
} else
if (netspec(word+1, &addr, &mask)) {
/* Remote host is on the specified network? */
if (((peer ^ addr) & mask) == 0) {
state= c == '-' ? FAIL : PASS;
}
} else {
/* Name check. */
if (got_name == -1) {
got_name= get_name(peer, name);
}
/* Remote host name matches the word? */
if (!got_name) {
state= FAIL;
} else
if (match(name, word+1)) {
state= c == '-' ? FAIL : PASS;
}
}
}
}
}
fclose(fp);
if ((log & state) != 0) {
/* Log the result of the check. */
if (got_name == -1) (void) get_name(peer, name);
if (logf != nil) {
(*logf)(state == PASS, name);
} else {
int lfd;
char line[128+WLEN];
time_t t;
struct tm *tm;
char month[][4]= {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
};
if ((lfd= open("/usr/adm/log", O_WRONLY|O_APPEND)) != -1) {
time(&t);
tm= localtime(&t);
sprintf(line, "%s %02d %02d:%02d:%02d service '%s' %s to %s\n",
month[tm->tm_mon],
tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec,
service,
state == PASS ? "granted" : "denied",
name);
(void) write(lfd, line, strlen(line));
close(lfd);
}
}
}
return state == PASS;
}
char *servxfile(const char *file)
/* Specify a file to use for the access checks other than the default. Return
* the old path.
*/
{
const char *oldpath= path_servacces;
path_servacces= file;
return (char *) oldpath; /* (avoid const poisoning) */
}
+43
View File
@@ -0,0 +1,43 @@
/*
strcasecmp.c
Created Oct 14, 1991 by Philip Homburg
*/
#include <ctype.h>
#include <string.h>
#ifdef __STDC__
#define _CONST const
#else
#define _CONST
#endif
int
strcasecmp(s1, s2)
_CONST char *s1, *s2;
{
int c1, c2;
while (c1= toupper(*s1++), c2= toupper(*s2++), c1 == c2 && (c1 & c2))
;
if (c1 & c2)
return c1 < c2 ? -1 : 1;
return c1 ? 1 : (c2 ? -1 : 0);
}
int
strncasecmp(s1, s2, len)
_CONST char *s1, *s2;
size_t len;
{
int c1, c2;
do {
if (len == 0)
return 0;
len--;
} while (c1= toupper(*s1++), c2= toupper(*s2++), c1 == c2 && (c1 & c2))
;
if (c1 & c2)
return c1 < c2 ? -1 : 1;
return c1 ? 1 : (c2 ? -1 : 0);
}