2 * Copyright (C) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
3 * Helsinki University of Technology, Finland.
5 * Copyright (C) 2005 - 2007 The AROS Dev Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
24 * Copyright (c) 1985, 1988 Regents of the University of California.
25 * All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. All advertising materials mentioning features or use of this software
36 * must display the following acknowledgement:
37 * This product includes software developed by the University of
38 * California, Berkeley and its contributors.
39 * 4. Neither the name of the University nor the names of its contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 #if defined(LIBC_SCCS) && !defined(lint)
57 static char sccsid
[] = "@(#)gethostnamadr.c 6.45 (Berkeley) 2/24/91";
58 #endif /* LIBC_SCCS and not lint */
62 #include <aros/libcall.h>
64 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/socket.h>
67 #include <sys/malloc.h>
68 #include <netinet/in.h>
69 #include <net/if.h> /* for the gethostid() needs */
70 #include <arpa/inet.h>
73 #include <sys/errno.h>
75 #include <arpa/nameser.h>
76 #include <api/resolv.h>
77 #include <kern/amiga_includes.h>
78 #include <api/amiga_api.h>
79 #include <api/amiga_libcallentry.h>
80 #include <api/amiga_raf.h>
81 #include <api/allocdatabuffer.h>
82 #include <kern/amiga_subr.h>
84 #include <api/gethtbynamadr.h> /* prototypes (NO MORE BUGS HERE) */
85 #include <api/apicalls.h>
87 #include <proto/bsdsocket.h>
93 #define MAXPACKET PACKETSZ
95 #define MAXPACKET 1024
100 u_char buf
[MAXPACKET
];
109 * macro for getting error value from another library base function
110 * ( which is called directly here )
114 * hostent structure in SocketBase
116 #define HOSTENT ((struct hostent *)libPtr->hostents.db_Addr)
119 * longword align given pointer (i.e. divides by 4)
121 #define ALIGN(p) (((long)(p) + (sizeof(long) - 1)) &~ (sizeof (long) -1))
123 #define MAXALIASES 35
126 typedef char hostbuf_t
[512];
129 char * host_aliases
[MAXALIASES
+ 1];
130 char * h_addr_ptrs
[MAXADDRS
+ 1];
131 short host_alias_count
;
137 static struct hostent
* makehostent(struct SocketBase
* libPtr
,
138 struct hoststruct
* HS
,
144 getanswer(struct SocketBase
* libPtr
, querybuf
*answer
,int anslen
, int iquery
,
145 struct hoststruct
* HS
)
148 register u_char
*cp
; /* pointer to traverse in 'answer' */
151 int buflen
= sizeof HS
->hostbuf
;
152 char *bp
; /* bp -- answer buffer pointer */
153 int type
, class, ancount
, qdcount
;
154 int haveanswer
, getclass
= C_ANY
;
157 #if defined(__AROS__)
158 D(bug("[AROSTCP](gethostnameadr.c) getanswer()\n"));
161 eom
= answer
->buf
+ anslen
;
163 * find first satisfactory answer
166 ancount
= ntohs(hp
->ancount
); /* how many answers returned from nameserver */
167 qdcount
= ntohs(hp
->qdcount
); /* how many questions in nameserver query */
170 * bp, points to start of buffer space where new resolved answer is to
171 * be written. the bp is moved to next free space. Initially it is
172 * set below, to start of buffer allocated for it-
176 * address cp to start of nameserver answers (after static sized header)
178 cp
= answer
->buf
+ sizeof(HEADER
);
181 * Any questions asked..hmm this should always be the case
184 #if 0 /* added by too 8.Sep.1993: skipping strange parts */
186 * gethostbyaddr uses inverse query...
189 if ((n
= dn_expand((u_char
*)answer
->buf
,
190 (u_char
*)eom
, (u_char
*)cp
, (u_char
*)bp
,
192 h_errno
= NO_RECOVERY
;
197 * Hostname in final hostent structure is written here in case
198 * of gethostbyaddr. (from question section ???)
200 HS
->host
.h_name
= bp
;
206 #endif /* 0 */ /* 8Sep93: now code below skips all question strings */
208 * here is normal query (gethostbyname). skipping query section
209 * hmm, wondering why is it originally implemented as 2
210 * __dn_skipname function calls ?
212 cp
+= __dn_skipname(cp
, eom
) + QFIXEDSZ
;
213 while (--qdcount
> 0)
214 cp
+= __dn_skipname(cp
, eom
) + QFIXEDSZ
;
218 * no questions and inverse query :o
221 h_errno
= HOST_NOT_FOUND
;
226 ap
= HS
->host_aliases
;
227 HS
->host_alias_count
= 1; /* there is always NULL as last pointer */
228 hap
= HS
->h_addr_ptrs
;
229 HS
->h_addr_count
= 1; /* there is always NULL as last pointer */
232 while (--ancount
>= 0 && cp
< eom
) {
233 if ((n
= dn_expand((u_char
*)answer
->buf
, (u_char
*)eom
,
234 (u_char
*)cp
, (u_char
*)bp
, buflen
)) < 0)
238 * Type and class are type and class of answer in returned resource
239 * record. see arpa[_/]nameserver.h for more information.
241 type
= _getshort(cp
);
242 cp
+= sizeof(u_short
);
243 class = _getshort(cp
);
244 cp
+= sizeof(u_short
) + sizeof(u_int32_t
);
246 cp
+= sizeof(u_short
);
248 if (type
== T_CNAME
) { /* canonical name (add alias names)*/
250 if (HS
->host_alias_count
>= MAXALIASES
)
253 HS
->host_alias_count
++;
259 if (iquery
&& type
== T_PTR
) { /* domain name pointer (get domain
261 if ((n
= dn_expand((u_char
*)answer
->buf
,
262 (u_char
*)eom
, (u_char
*)cp
, (u_char
*)bp
,
268 HS
->host
.h_name
= bp
; /* well, rewrites name pointer if there were
269 returned questions also... */
271 bp
+= (strlen(bp
) + 1);
274 if (iquery
|| type
!= T_A
) {
276 * here is strange answer from nameserver: inverse query should have
277 * been handled earlyer and there should not be any other types
278 * left than "host address"
281 printf("unexpected answer type %d, size %d\n",
289 * Here if one host address answer is already returned (rather odd...)
291 if (n
!= HS
->host
.h_length
) {
295 if (class != getclass
) {
302 * Fill in host address data and comparing info for next cycle (if any)
304 HS
->host
.h_length
= n
;
306 HS
->host
.h_addrtype
= (class == C_IN
) ?
310 * if not inverse query and haveanswer = 0 host name is first in
311 * bp pointed buffer. (rather strange if answer already returned
312 * and new addresses are to be added since aren't in that case
313 * also names returned or is it inconsistent or have i missed
318 HS
->host
.h_name
= bp
;
325 // bp = (char *)ALIGN(bp); /* align answer buffer for next host address */
327 if (HS
->host
.h_length
>= buflen
) {
329 printf("size (%d) too big\n", HS
->host
.h_length
);
334 * Fill next host address in address list
336 bcopy(cp
, *hap
++ = bp
, n
);
342 } /* while (--ancount ...) */
355 int isipaddr(const char *name
)
372 struct hostent
*__gethostbyname(const char *name
, struct SocketBase
*libPtr
)
377 struct hoststruct
* HS
= NULL
;
378 struct hostent
* anshost
= NULL
;
380 #if defined(__AROS__)
381 D(bug("[AROSTCP](gethostnameadr.c) gethostbyname('%s')\n", name
));
387 * check if name consists of only dots and digits.
389 if (isipaddr(name
)) {
390 struct in_addr inaddr
;
393 #if defined(__AROS__)
394 D(bug("[AROSTCP](gethostnameadr.c) gethostbyname: name IS an IP address\n"));
397 if (!__inet_aton(name
, &inaddr
)) {
398 writeErrnoValue(libPtr
, EINVAL
);
403 if (allocDataBuffer(&libPtr
->hostents
,
404 sizeof (struct hostent
) + 28) == FALSE
) {
405 writeErrnoValue(libPtr
, ENOMEM
);
409 HOSTENT
->h_addrtype
= AF_INET
;
410 HOSTENT
->h_length
= sizeof (struct in_addr
);
411 lptr
= (u_long
*)(HOSTENT
+ 1);
412 *lptr
++ = inaddr
.s_addr
;
413 *(u_long
**)(lptr
) = lptr
- 1;
414 HOSTENT
->h_addr_list
= (char **)lptr
;
416 HOSTENT
->h_aliases
= (char **)lptr
;
417 HOSTENT
->h_name
= strcpy((char *)++lptr
, name
);
423 #if defined(__AROS__)
424 D(bug("[AROSTCP](gethostnameadr.c) gethostbyname: name ISNT an IP address\n"));
429 * Search local database (first) is usens not FIRST
432 if ((anshost
=_gethtbyname(libPtr
, name
)) != NULL
|| usens
== 0)
434 #if defined(__AROS__)
435 D(bug("[AROSTCP](gethostnameadr.c) gethostbyname: host found in local database\n"));
440 * Here if usens is FIRST or host not in local database and usens is SECOND
442 if ((HS
= bsd_malloc(sizeof (querybuf
) + sizeof (struct hoststruct
),
443 M_TEMP
, M_WAITOK
)) == NULL
) {
444 #if defined(__AROS__)
445 D(bug("[AROSTCP](gethostnameadr.c) gethostbyname: couldnt allocate memory for res search entry\n"));
447 writeErrnoValue(libPtr
, ENOMEM
);
450 buf
= (querybuf
*)(HS
+ 1);
452 n
= res_search(libPtr
, name
, C_IN
, T_A
, buf
->buf
, sizeof (querybuf
));
454 #if defined(__AROS__)
455 D(bug("[AROSTCP](gethostnameadr.c) gethostbyname: [res_search] returns %d\n", n
));
457 ptr
= getanswer(libPtr
, buf
, n
, 0, HS
);
459 #if defined(__AROS__)
460 D(bug("[AROSTCP](gethostnameadr.c) gethostbyname: [getanswer] returns valid ptr\n"));
462 if ((anshost
= makehostent(libPtr
, HS
, ptr
)) != NULL
) {
463 #if defined(__AROS__)
464 D(bug("[AROSTCP](gethostnameadr.c) gethostbyname: [makehostent] returns success\n"));
466 anshost
->h_addrtype
= HS
->host
.h_addrtype
;
467 anshost
->h_length
= HS
->host
.h_length
;
472 #if defined(__AROS__)
473 D(bug("[AROSTCP](gethostnameadr.c) gethostbyname: [res_search] failed\n"));
476 printf("res_search failed\n");
479 * If usens is FIRST and host not found using resolver.
482 anshost
=_gethtbyname(libPtr
, name
);
484 #if defined(__AROS__)
485 D(bug("[AROSTCP](gethostnameadr.c) gethostbyname: finished search\n"));
489 bsd_free(HS
, M_TEMP
);
493 AROS_LH1(struct hostent
*, gethostbyname
,
494 AROS_LHA(char *, name
, A0
),
495 struct SocketBase
*, libPtr
, 35, UL
)
498 return __gethostbyname(name
, libPtr
);
504 struct hostent
* __gethostbyaddr(UBYTE
*addr
, int len
, int type
, struct SocketBase
* libPtr
)
509 struct hoststruct
* HS
= NULL
;
511 struct hostent
* anshost
= NULL
;
513 #if defined(__AROS__)
514 D(bug("[AROSTCP](gethostnameadr.c) __gethostbyaddr()\n"));
520 return ((struct hostent
*) NULL
);
523 * Search local database (first) is usens not FIRST
526 if ((anshost
=_gethtbyaddr(libPtr
, addr
, len
, type
)) != NULL
|| usens
== 0)
530 * Here if usens is FIRST or host not in local database and usens is SECOND
532 if ((HS
= bsd_malloc(sizeof (querybuf
) + MAXDNAME
+ 1 +
533 sizeof (struct hoststruct
), M_TEMP
, M_WAITOK
))
535 writeErrnoValue(libPtr
, ENOMEM
);
538 buf
= (querybuf
*)(HS
+ 1);
539 qbuf
= (caddr_t
)(buf
+ 1);
541 (void)sprintf(qbuf
, "%lu.%lu.%lu.%lu.in-addr.arpa",
542 ((unsigned long)addr
[3] & 0xff),
543 ((unsigned long)addr
[2] & 0xff),
544 ((unsigned long)addr
[1] & 0xff),
545 ((unsigned long)addr
[0] & 0xff));
546 n
= res_query(libPtr
, qbuf
, C_IN
, T_PTR
, (char *)buf
, sizeof (querybuf
));
549 ptr
= getanswer(libPtr
, buf
, n
, 1, HS
);
551 if (HS
->h_addr_count
== 1) {
553 bcopy(addr
, ptr
, len
);
554 HS
->h_addr_ptrs
[0] = ptr
;
558 bcopy(addr
, &HS
->h_addr_ptrs
[0], len
);
559 HS
->h_addr_ptrs
[1] = NULL
;
560 if ((anshost
= makehostent(libPtr
, HS
, ptr
)) != NULL
) {
561 anshost
->h_addrtype
= type
;
562 anshost
->h_length
= len
;
568 printf("res_query failed\n");
571 * If usens is FIRST and host not found using resolver.
574 anshost
= _gethtbyaddr(libPtr
, addr
, len
, type
);
577 bsd_free(HS
, M_TEMP
);
581 AROS_LH3(struct hostent
*, gethostbyaddr
,
582 AROS_LHA(UBYTE
*, addr
, A0
),
583 AROS_LHA(int, len
, D0
),
584 AROS_LHA(int, type
, D1
),
585 struct SocketBase
*, libPtr
, 36, UL
)
588 #if defined(__AROS__)
589 D(bug("[AROSTCP](gethostnameadr.c) gethostbyaddr()\n"));
592 return __gethostbyaddr(addr
, len
, type
, libPtr
);
596 static struct hostent
* makehostent(struct SocketBase
* libPtr
,
597 struct hoststruct
* HS
,
602 #if defined(__AROS__)
603 D(bug("[AROSTCP](gethostnameadr.c) makehostent()\n"));
606 i
= (caddr_t
)ALIGN(ptr
) - (caddr_t
)&HS
->hostbuf
;
607 n
= i
+ sizeof (struct hostent
) + HS
->h_addr_count
* sizeof (char *) +
608 HS
->host_alias_count
* sizeof (char *);
610 if (allocDataBuffer(&libPtr
->hostents
, n
) == FALSE
) {
611 writeErrnoValue(libPtr
, ENOMEM
);
615 * copy ent data to user buffer (pointers will be set later)
617 bcopy(HS
->hostbuf
, (caddr_t
)(HOSTENT
+ 1), i
);
620 * how much to add to old pointers
622 n
= (caddr_t
)HOSTENT
+ sizeof(struct hostent
) - (caddr_t
)&HS
->hostbuf
;
625 * fill vital fields in user hostent structure
627 HOSTENT
->h_name
= HS
->host
.h_name
+ n
;
629 HOSTENT
->h_aliases
= (char **)((char *)(HOSTENT
+ 1) + i
);
630 for (i
= 0; HS
->host_aliases
[i
]; i
++)
631 HOSTENT
->h_aliases
[i
] = HS
->host_aliases
[i
] + n
;
632 HOSTENT
->h_aliases
[i
++] = NULL
;
634 HOSTENT
->h_addr_list
= HOSTENT
->h_aliases
+ i
;
635 for (i
= 0; HS
->h_addr_ptrs
[i
]; i
++)
636 HOSTENT
->h_addr_list
[i
] = HS
->h_addr_ptrs
[i
] + n
;
637 HOSTENT
->h_addr_list
[i
] = NULL
;
643 * id_addr variable is used by both the gethostname() and gethostid().
645 * host_name is the host_name configuration variable.
647 static ULONG id_addr
= 0;
649 void findid(ULONG
*); /* defined in net/if.c */
652 * Global host name and name length
654 char host_name
[MAXHOSTNAMELEN
+1] = { 0 };
655 size_t host_namelen
= 0;
657 /****i* AmiTCP/sethostname *********************************************
660 * sethostname -- set the name of the host
663 * error = sethostname(name, namelen);
665 * int sethostname(const char *, size_t);
668 * Set the name of the host to the given 'name' of length 'namelen'.
671 * name - Pointer to the name string.
672 * namelen - Length of the name.
675 * error - 0 on success.
680 * This function is not intended to be provided to the applications,
681 * this is for AmiTCP internal use only (at least for now).
686 *****************************************************************************
689 int sethostname(const char *name
, size_t namelen
)
691 #if defined(__AROS__)
692 D(bug("[AROSTCP](gethostnameadr.c) sethostname()\n"));
695 if (namelen
> MAXHOSTNAMELEN
)
696 namelen
= MAXHOSTNAMELEN
;
698 memcpy(host_name
, name
, namelen
);
699 host_name
[namelen
] = '\0';
700 host_namelen
= namelen
;
701 SetVar("HOSTNAME", name
, namelen
, GVF_GLOBAL_ONLY
);
706 /****** bsdsocket.library/gethostname *************************************
709 * gethostname -- get the name of the host
712 * error = gethostname(name, namelen);
714 * long gethostname(char *, long);
717 * Get the name of the host to the buffer name of length namelen.
718 * The name is queried from the netdb and/or the name server if
719 * it is not explicitly configured (configuration variable
723 * name - Pointer to the buffer where the name should be
725 * namelen - Length of the buffer name.
728 * error - 0 on success.
731 * char hostname[MAXHOSTNAMELEN];
734 * error = gethostname(hostname, sizeof(hostname));
738 * printf("My name is \"%s\".\n", hostname);
743 * Unlike the Unix version, this version assures that the
744 * resulting string is always NULL-terminated.
748 *****************************************************************************
751 LONG
__gethostname(STRPTR name
, LONG namelen
, struct SocketBase
* libPtr
)
753 size_t host_namelen
= 0;
755 #if defined(__AROS__)
756 D(bug("[AROSTCP](gethostnameadr.c) __gethostname()\n"));
762 * Get the name with the gethostbyaddr(), if the name is not set yet.
764 if (*host_name
== '\0')
766 struct hostent
* hent
;
772 { /* query if we have an address */
773 hent
= __gethostbyaddr((UBYTE
*)&id_addr
,
774 sizeof(id_addr
), AF_INET
, libPtr
);
778 host_namelen
= strlen(hent
->h_name
);
779 sethostname(hent
->h_name
, host_namelen
);
783 #if defined(__AROS__)
784 D(bug("[AROSTCP](gethostnameadr.c) __gethostname: BUG!?! No Host ??\n"));
789 else host_namelen
= strlen(host_name
);
791 #if defined(__AROS__)
792 D(bug("[AROSTCP](gethostnameadr.c) __gethostname: namelen: %d host_namelen: %d\n", namelen
, host_namelen
));
796 * Copy the name to the user buffer. stccpy() ensures that the buffer
797 * is not written over and that it will be null-terminated.
799 if (namelen
> host_namelen
)
800 namelen
= host_namelen
;
802 namelen
--; /* make space for the trailing '\0' */
804 memcpy(name
, host_name
, namelen
);
805 name
[namelen
] = '\0';
807 API_STD_RETURN(0, 0);
810 AROS_LH2(LONG
, gethostname
,
811 AROS_LHA(STRPTR
, name
, A0
),
812 AROS_LHA(LONG
, namelen
, D0
),
813 struct SocketBase
*, libPtr
, 47, UL
)
816 #if defined(__AROS__)
817 D(bug("[AROSTCP](gethostnameadr.c) gethostname()\n"));
819 return __gethostname(name
, namelen
, libPtr
);
823 /****** bsdsocket.library/gethostid ***************************************
826 * gethostid -- get an unique 32-bit id to this host
831 * ULONG gethostid(void);
834 * Return the 32-bit unique id for this host. The Internet
835 * address if the primary interface is used as the unique id.
836 * This means that this function is also a supported way to get
837 * the hosts IP address in AmiTCP/IP. If no interfaces are
838 * configured, zero is returned. Any non-loobpack interface with
839 * is preferred. Only if no other interfaces are present, is the
840 * loopback address returned.
845 * id - non-zero on success.
854 * printf("My primary IP address is: %s.\n", Inet_NtoA(id));
857 * Non-zero id is returned as soon as a interface is configured.
858 * After that the id will not change, not even if the id is the
859 * address of the loopback interface.
864 *****************************************************************************
867 /*ULONG SAVEDS gethostid(
868 REG(a6, struct SocketBase * libPtr))*/
869 AROS_LH0(ULONG
, gethostid
,
870 struct SocketBase
*, libPtr
, 48, UL
)
874 #if defined(__AROS__)
875 D(bug("[AROSTCP](gethostnameadr.c) gethostid()\n"));