home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / internet / amitcp3.0b / src.lha / src / amitcp / api / gethostnamadr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-08  |  20.7 KB  |  791 lines

  1. /*
  2.  * $Id: gethostnamadr.c,v 3.9 1994/04/02 11:06:28 jraja Exp $
  3.  *
  4.  * Last modified: Sat Feb 26 20:10:41 1994 jraja
  5.  *
  6.  * HISTORY
  7.  * $Log: gethostnamadr.c,v $
  8.  * Revision 3.9  1994/04/02  11:06:28  jraja
  9.  * Moved global resolver variables to SocketBase, removed res_lock.
  10.  *
  11.  * Revision 3.8  1994/02/26  18:11:04  jraja
  12.  * Fixed hethostid() name on the autodoc entry.
  13.  *
  14.  * Revision 3.7  1994/02/15  23:22:21  jraja
  15.  * Added prototype for the findid().
  16.  *
  17.  * Revision 3.6  1994/01/20  02:18:33  jraja
  18.  * Changed include <errno.h> to <sys/errno.h>, removed errno definition,
  19.  * added <conf.h> as the first include.
  20.  *
  21.  * Revision 3.5  1994/01/18  19:21:17  jraja
  22.  * Changed errno macro to use baseErrno() macro.
  23.  *
  24.  * Revision 3.4  1994/01/18  02:10:09  jraja
  25.  * Implemented gethostname(). Added internal sethostname(). Added autodoc
  26.  * for the gethostid().
  27.  *
  28.  * Revision 3.3  1994/01/13  07:35:25  jraja
  29.  * Added implementation for the gethostid().
  30.  *
  31.  * Revision 3.2  1994/01/09  21:06:45  too
  32.  * Added setting of h_errno to rest returns
  33.  *
  34.  * Revision 3.1  1994/01/04  14:10:25  too
  35.  * Removed "extern int h_errno". Now it is defined to
  36.  * libPtr->hErrno in resolv.h. Added cores for gethostname() and
  37.  * gethostid()
  38.  *
  39.  * Revision 1.7  1993/09/08  14:26:47  too
  40.  * Fixed getanswer (from gethostbyaddr) further. Now alias and addr lists
  41.  * are NULL terminated. question is no longer copied. Removed that
  42.  * unnecessary aligment by accident.
  43.  *
  44.  * Revision 1.6  1993/08/20  17:26:34  too
  45.  * Fixed bug in getanswer that caused gethostbyaddr() to return
  46.  * hostname w/ garpage at the end.
  47.  * Added some comments w/ wponders
  48.  * now answer buffer is aligned before host addresses are written.
  49.  * this is unnecessary though.
  50.  * getanswer still writes the question to the answer buffer. This will
  51.  * be fixed later since it doesn't affect functionality
  52.  *
  53.  * Revision 1.5  1993/06/07  12:37:20  too
  54.  * Changed inet_ntoa, netdatabase functions and WaitSelect() use
  55.  * separate buffers for their dynamic buffers
  56.  *
  57.  */
  58. /*
  59.  * Copyright (c) 1985, 1988 Regents of the University of California.
  60.  * All rights reserved.
  61.  *
  62.  * Redistribution and use in source and binary forms, with or without
  63.  * modification, are permitted provided that the following conditions
  64.  * are met:
  65.  * 1. Redistributions of source code must retain the above copyright
  66.  *    notice, this list of conditions and the following disclaimer.
  67.  * 2. Redistributions in binary form must reproduce the above copyright
  68.  *    notice, this list of conditions and the following disclaimer in the
  69.  *    documentation and/or other materials provided with the distribution.
  70.  * 3. All advertising materials mentioning features or use of this software
  71.  *    must display the following acknowledgement:
  72.  *    This product includes software developed by the University of
  73.  *    California, Berkeley and its contributors.
  74.  * 4. Neither the name of the University nor the names of its contributors
  75.  *    may be used to endorse or promote products derived from this software
  76.  *    without specific prior written permission.
  77.  *
  78.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  79.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  80.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  81.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  82.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  83.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  84.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  85.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  86.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  87.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  88.  * SUCH DAMAGE.
  89.  */
  90.  
  91. #if defined(LIBC_SCCS) && !defined(lint)
  92. static char sccsid[] = "@(#)gethostnamadr.c    6.45 (Berkeley) 2/24/91";
  93. #endif /* LIBC_SCCS and not lint */
  94.  
  95. #include <conf.h>
  96.  
  97. #include <sys/param.h>
  98. #include <sys/systm.h>
  99. #include <sys/socket.h>
  100. #include <sys/malloc.h>
  101. #include <netinet/in.h>
  102. #include <net/if.h> /* for the gethostid() needs */
  103. #include <arpa/inet.h>
  104. #include <netdb.h>
  105. #include <ctype.h>
  106. #include <sys/errno.h>
  107.  
  108. #include <api/arpa_nameser.h>
  109. #include <api/resolv.h>
  110. #include <kern/amiga_includes.h>
  111. #include <api/amiga_api.h>
  112. #include <api/amiga_libcallentry.h>
  113. #include <api/amiga_raf.h>
  114. #include <api/allocdatabuffer.h>     
  115. #include <kern/amiga_subr.h>
  116.  
  117. #include <api/gethtbynamadr.h>     /* prototypes (NO MORE BUGS HERE) */
  118. #include <api/apicalls.h>
  119.      
  120. #define    MAXALIASES    35
  121. #define    MAXADDRS    35
  122.  
  123. #if PACKETSZ > 1024
  124. #define    MAXPACKET    PACKETSZ
  125. #else
  126. #define    MAXPACKET    1024
  127. #endif
  128.  
  129. typedef union {
  130.     HEADER hdr;
  131.     u_char buf[MAXPACKET];
  132. } querybuf;
  133.  
  134. typedef union {
  135.     long al;
  136.     char ac;
  137. } align;
  138.  
  139. /*
  140.  * macro for getting error value from another library base function
  141.  * ( which is called directly here )
  142.  */
  143.  
  144. /*
  145.  * hostent structure in SocketBase
  146.  */
  147. #define HOSTENT ((struct hostent *)libPtr->hostents.db_Addr)
  148.  
  149. /*
  150.  * longword align given pointer (i.e. divides by 4)
  151.  */
  152. #define ALIGN(p) (((u_int)(p) + (sizeof(long) - 1)) &~ (sizeof (long) -1))
  153.  
  154. #define MAXALIASES    35
  155. #define MAXADDRS    35  
  156.   
  157. typedef char hostbuf_t[512];
  158.  
  159. struct hoststruct {
  160.   char * host_aliases[MAXALIASES + 1];
  161.   char * h_addr_ptrs[MAXADDRS + 1];
  162.   short host_alias_count;
  163.   short h_addr_count;
  164.   struct hostent host;
  165.   hostbuf_t hostbuf;
  166. };
  167.  
  168. static struct hostent * makehostent(struct SocketBase * libPtr,
  169.                     struct hoststruct * HS,
  170.                     char * ptr);
  171.  
  172. LONG usens = 1;
  173.  
  174. static char *
  175.  getanswer(struct SocketBase * libPtr, querybuf *answer,int anslen, int iquery,
  176.         struct hoststruct * HS)
  177. {
  178.   register HEADER *hp;
  179.   register u_char *cp; /* pointer to traverse in 'answer' */
  180.   register int n;
  181.   u_char *eom;
  182.   int buflen = sizeof HS->hostbuf;
  183.   char *bp; /* bp -- answer buffer pointer */
  184.   int type, class, ancount, qdcount;
  185.   int haveanswer, getclass = C_ANY;
  186.   char **ap, **hap;
  187.   
  188.   eom = answer->buf + anslen;
  189.   /*
  190.    * find first satisfactory answer
  191.    */
  192.   hp = &answer->hdr;
  193.   ancount = ntohs(hp->ancount); /* how many answers returned from nameserver */
  194.   qdcount = ntohs(hp->qdcount); /* how many questions in nameserver query */
  195.  
  196.   /*
  197.    *  bp, points to start of buffer space where new resolved answer is to 
  198.    *  be written. the bp is moved to next free space. Initially it is
  199.    *  set below, to start of buffer allocated for it-
  200.    */
  201.   bp = HS->hostbuf;
  202.   /*
  203.    * address cp to start of nameserver answers (after static sized header)
  204.    */
  205.   cp = answer->buf + sizeof(HEADER);
  206.  
  207.   /*
  208.    * Any questions asked..hmm this should always be the case
  209.    */
  210.   if (qdcount) {
  211. #if 0            /* added by too 8.Sep.1993: skipping strange parts */
  212.     /*
  213.      * gethostbyaddr uses inverse query...
  214.      */
  215.     if (iquery) {
  216.       if ((n = dn_expand((u_char *)answer->buf,
  217.              (u_char *)eom, (u_char *)cp, (u_char *)bp,
  218.              buflen)) < 0) {
  219.     h_errno = NO_RECOVERY;
  220.     return NULL;
  221.       }
  222.       cp += n + QFIXEDSZ;
  223.       /*
  224.        * Hostname in final hostent structure is written here in case
  225.        * of gethostbyaddr. (from question section ???)
  226.        */
  227.       HS->host.h_name = bp;
  228.       n = strlen(bp) + 1;
  229.       bp += n;
  230.       buflen -= n;
  231.     }
  232.     else
  233. #endif    /* 0 */        /* 8Sep93: now code below skips all question strings */
  234.       /*
  235.        * here is normal query (gethostbyname). skipping query section
  236.        * hmm, wondering why is it originally implemented as 2
  237.        * __dn_skipname function calls ?
  238.        */
  239.       cp += __dn_skipname(cp, eom) + QFIXEDSZ;
  240.     while (--qdcount > 0)
  241.       cp += __dn_skipname(cp, eom) + QFIXEDSZ;
  242.   }
  243.   else if (iquery) {
  244.     /*
  245.      * no questions and inverse query :o
  246.      */
  247.     if (hp->aa)
  248.       h_errno = HOST_NOT_FOUND;
  249.     else
  250.       h_errno = TRY_AGAIN;
  251.     return NULL;
  252.   }
  253.   ap = HS->host_aliases;
  254.   HS->host_alias_count = 1; /* there is always NULL as last pointer */
  255.   hap = HS->h_addr_ptrs;
  256.   HS->h_addr_count = 1; /* there is always NULL as last pointer */
  257.   
  258.   haveanswer = 0;
  259.   while (--ancount >= 0 && cp < eom) {
  260.     if ((n = dn_expand((u_char *)answer->buf, (u_char *)eom,
  261.                (u_char *)cp, (u_char *)bp, buflen)) < 0)
  262.       break;
  263.     cp += n;
  264.     /*
  265.      * Type and class are type and class of answer in returned resource
  266.      * record. see arpa[_/]nameserver.h for more information.
  267.      */
  268.     type = _getshort(cp); 
  269.     cp += sizeof(u_short);
  270.     class = _getshort(cp);
  271.     cp += sizeof(u_short) + sizeof(u_long);
  272.     n = _getshort(cp);
  273.     cp += sizeof(u_short);
  274.     
  275.     if (type == T_CNAME) {   /* canonical name (add alias names)*/
  276.       cp += n;
  277.       if (HS->host_alias_count >= MAXALIASES)
  278.     continue;
  279.       *ap++ = bp;
  280.       HS->host_alias_count++;
  281.       n = strlen(bp) + 1;
  282.       bp += n;
  283.       buflen -= n;
  284.       continue;
  285.     }
  286.     if (iquery && type == T_PTR) {  /* domain name pointer (get domain
  287.                        name and return) */
  288.       if ((n = dn_expand((u_char *)answer->buf,
  289.              (u_char *)eom, (u_char *)cp, (u_char *)bp,
  290.              buflen)) < 0) {
  291.     cp += n;
  292.     continue;
  293.       }
  294.       cp += n;
  295.       HS->host.h_name = bp;   /* well, rewrites name pointer if there were
  296.                  returned questions also... */
  297.       haveanswer = 1;
  298.       bp+= (strlen(bp) + 1);
  299.       break;
  300.     }
  301.     if (iquery || type != T_A)  {
  302.       /*
  303.        * here is strange answer from nameserver: inverse query should have
  304.        * been handled earlyer and there should not be any other types
  305.        * left than "host address"
  306.        */
  307. #ifdef RES_DEBUG
  308.       printf("unexpected answer type %d, size %d\n",
  309.          type, n);
  310. #endif
  311.       cp += n;
  312.       continue;
  313.     }
  314.     if (haveanswer) {
  315.       /*
  316.        * Here if one host address answer is already returned (rather odd...)
  317.        */
  318.       if (n != HS->host.h_length) {
  319.     cp += n;
  320.     continue;
  321.       }
  322.       if (class != getclass) {
  323.     cp += n;
  324.     continue;
  325.       }
  326.     }
  327.     else {
  328.       /*
  329.        * Fill in host address data and comparing info for next cycle (if any)
  330.        */
  331.       HS->host.h_length = n;
  332.       getclass = class;
  333.       HS->host.h_addrtype = (class == C_IN) ?
  334.     AF_INET : AF_UNSPEC;
  335.       if (!iquery) {
  336.     /*
  337.      * if not inverse query and haveanswer = 0 host name is first in
  338.      * bp pointed buffer. (rather strange if answer already returned
  339.      * and new addresses are to be added since aren't in that case
  340.      * also names returned or is it inconsistent or have i missed
  341.      * something ?
  342.      */
  343.     int n1;
  344.  
  345.     HS->host.h_name = bp;
  346.     n1 = strlen(bp) + 1;
  347.     bp += n1;
  348.     buflen -= n1;
  349.       }
  350.     }
  351.  
  352. /*    bp = (char *)ALIGN(bp); /* align answer buffer for next host address */
  353.         
  354.     if (HS->host.h_length >= buflen) {
  355. #ifdef RES_DEBUG
  356.       printf("size (%d) too big\n", host->h_length);
  357. #endif
  358.       break;
  359.     }
  360.     /*
  361.      * Fill next host address in address list
  362.      */
  363.     bcopy(cp, *hap++ = bp, n);
  364.     HS->h_addr_count++;
  365.     bp += n;
  366.     buflen -= n;
  367.     cp += n;
  368.     haveanswer++;
  369.   } /* while (--ancount ...) */
  370.   
  371.   if (haveanswer) {
  372.     *ap = NULL;
  373.     *hap = NULL;
  374.     return bp;
  375.   }
  376.   else {
  377.     h_errno = TRY_AGAIN;
  378.     return NULL;
  379.   }
  380. }
  381.  
  382. struct hostent * SAVEDS RAF2 (_gethostbyname,
  383.                   struct SocketBase *,    libPtr,    a6,
  384.                   const char *,        name,    a0)
  385. #if 0
  386. {
  387. #endif  
  388.   querybuf *buf;
  389.   int n;
  390.   char * ptr;
  391.   extern int inet_aton(const char *name, struct in_addr *ia);
  392.   struct hoststruct * HS = NULL;
  393.   struct hostent * anshost = NULL;
  394.   
  395.   CHECK_TASK2();
  396.   
  397.   /*
  398.    * check if name consists only dots and digits.
  399.    */
  400.   if (isdigit(name[0])) {
  401.     struct in_addr inaddr;
  402.     u_long * lptr;
  403.     
  404.     if (!inet_aton(name, &inaddr)) {
  405.       writeErrnoValue(libPtr, EINVAL);
  406.       h_errno = 0;
  407.       return NULL;
  408.     }
  409.     
  410.     if (allocDataBuffer(&libPtr->hostents,
  411.             sizeof (struct hostent) + 28) == FALSE) {
  412.       writeErrnoValue(libPtr, ENOMEM);
  413.       h_errno = 0;
  414.       return NULL;
  415.     }
  416.     HOSTENT->h_addrtype = AF_INET;
  417.     HOSTENT->h_length = sizeof (struct in_addr);
  418.     lptr = (u_long *)(HOSTENT + 1);
  419.     *lptr++ = inaddr.s_addr;
  420.     *(u_long **)(lptr) = lptr - 1;
  421.     HOSTENT->h_addr_list = (char **)lptr;
  422.     *++lptr = NULL;
  423.     HOSTENT->h_aliases = (char **)lptr;
  424.     HOSTENT->h_name = strcpy((char *)++lptr, name);
  425.     
  426.     return HOSTENT;
  427.   }
  428.   /*
  429.    * Search local database (first) is usens not FIRST
  430.    */
  431.   if (usens != 1)
  432.     if ((anshost =_gethtbyname(libPtr, name)) != NULL || usens == 0)
  433.       return anshost;
  434.   /*
  435.    * Here if usens is FIRST or host not in local database and usens is SECOND
  436.    */
  437.   if ((HS = bsd_malloc(sizeof (querybuf) + sizeof (struct hoststruct),
  438.                M_TEMP, M_WAITOK)) == NULL) {
  439.     writeErrnoValue(libPtr, ENOMEM);
  440.     return NULL;
  441.   }
  442.   buf = (querybuf *)(HS + 1);
  443.   
  444.   n = res_search(libPtr, name, C_IN, T_A, buf->buf, sizeof (querybuf));
  445.   if (n >= 0) {
  446.     ptr = getanswer(libPtr, buf, n, 0, HS);
  447.     if (ptr != NULL) {
  448.       if ((anshost = makehostent(libPtr, HS, ptr)) != NULL) {
  449.     anshost->h_addrtype = HS->host.h_addrtype;
  450.     anshost->h_length = HS->host.h_length;
  451.       }    
  452.     }
  453.   }
  454.   else {
  455. #ifdef RES_DEBUG
  456.     printf("res_search failed\n");
  457. #endif
  458.     /*
  459.      * If usens is FIRST and host not found using resolver.
  460.      */
  461.     if (usens != 2)
  462.       anshost =_gethtbyname(libPtr, name);
  463.   }
  464.   if (HS)
  465.     bsd_free(HS, M_TEMP);
  466.   return anshost;
  467.   
  468. }
  469.  
  470. struct hostent * SAVEDS RAF4 (_gethostbyaddr,
  471.                   struct SocketBase *,    libPtr,    a6,
  472.                   const UBYTE *,        addr,    a0,
  473.                   int,            len,    d0,
  474.                   int,            type,    d1)
  475. #if 0
  476. {
  477. #endif  
  478.   querybuf * buf;
  479.   int n;
  480.   char * ptr;
  481.   struct hoststruct * HS = NULL;
  482.   char * qbuf;
  483.   struct hostent * anshost = NULL;
  484.   
  485.   CHECK_TASK2();
  486.   
  487.   if (type != AF_INET)
  488.     return ((struct hostent *) NULL);
  489.   
  490.   /*
  491.    * Search local database (first) is usens not FIRST
  492.    */
  493.   if (usens != 1)
  494.     if ((anshost =_gethtbyaddr(libPtr, addr, len, type)) != NULL || usens == 0)
  495.       return anshost;
  496.  
  497.   /*
  498.    * Here if usens is FIRST or host not in local database and usens is SECOND
  499.    */
  500.   if ((HS = bsd_malloc(sizeof (querybuf) + MAXDNAME + 1 +
  501.                sizeof (struct hoststruct),  M_TEMP, M_WAITOK))
  502.       == NULL) {
  503.     writeErrnoValue(libPtr, ENOMEM);
  504.     return NULL;
  505.   }
  506.   buf = (querybuf *)(HS + 1);
  507.   qbuf = (caddr_t)(buf + 1);
  508.   
  509.   (void)sprintf(qbuf, "%lu.%lu.%lu.%lu.in-addr.arpa",
  510.         ((unsigned)addr[3] & 0xff),
  511.         ((unsigned)addr[2] & 0xff),
  512.         ((unsigned)addr[1] & 0xff),
  513.         ((unsigned)addr[0] & 0xff));
  514.   n = res_query(libPtr, qbuf, C_IN, T_PTR, (char *)buf, sizeof (querybuf));
  515.  
  516.   if (n >= 0) {
  517.     ptr = getanswer(libPtr, buf, n, 1, HS);
  518.     if (ptr != NULL) {
  519.       if (HS->h_addr_count == 1) {
  520.     HS->h_addr_count++;
  521.     bcopy(addr, ptr, len);
  522.     HS->h_addr_ptrs[0] = ptr;
  523.     ptr += len;
  524.       }      
  525.       else
  526.     bcopy(addr, &HS->h_addr_ptrs[0], len);
  527.       HS->h_addr_ptrs[1] = NULL;
  528.       if ((anshost = makehostent(libPtr, HS, ptr)) != NULL) {
  529.     anshost->h_addrtype = type;
  530.     anshost->h_length = len;
  531.       }
  532.     }
  533.   }
  534.   else {
  535. #ifdef RES_DEBUG
  536.     printf("res_query failed\n");
  537. #endif
  538.     /*
  539.      * If usens is FIRST and host not found using resolver.
  540.      */
  541.     if (usens != 2)
  542.       anshost = _gethtbyaddr(libPtr, addr, len, type);
  543.   }
  544.   if (HS)
  545.     bsd_free(HS, M_TEMP);
  546.   return anshost;
  547. }
  548.  
  549. static struct hostent * makehostent(struct SocketBase * libPtr,
  550.                     struct hoststruct * HS,
  551.                     char * ptr)
  552. {
  553.   int n, i;
  554.  
  555.   i = (caddr_t)ALIGN(ptr) - (caddr_t)&HS->hostbuf;
  556.   n = i + sizeof (struct hostent) + HS->h_addr_count * sizeof (char *) +
  557.     HS->host_alias_count * sizeof (char *);
  558.     
  559.   if (allocDataBuffer(&libPtr->hostents, n) == FALSE) {
  560.     writeErrnoValue(libPtr, ENOMEM);    
  561.     return NULL;
  562.   }
  563.   /*
  564.    * copy ent data to user buffer (pointers will be set later)
  565.    */
  566.   bcopy(HS->hostbuf, (caddr_t)(HOSTENT + 1), i);
  567.  
  568.   /*
  569.    * how much to add to old pointers
  570.    */
  571.   n = (caddr_t)HOSTENT + sizeof(struct hostent) - (caddr_t)&HS->hostbuf;
  572.   
  573.   /*
  574.    * fill vital fields in user hostent structure
  575.    */
  576.   HOSTENT->h_name = HS->host.h_name + n;
  577.  
  578.   HOSTENT->h_aliases = (char **)((char *)(HOSTENT + 1) + i);
  579.   for (i = 0; HS->host_aliases[i]; i++)
  580.     HOSTENT->h_aliases[i] = HS->host_aliases[i] + n;
  581.   HOSTENT->h_aliases[i++] = NULL;
  582.  
  583.   HOSTENT->h_addr_list = HOSTENT->h_aliases + i;
  584.   for (i = 0; HS->h_addr_ptrs[i]; i++)
  585.     HOSTENT->h_addr_list[i] = HS->h_addr_ptrs[i] + n;
  586.   HOSTENT->h_addr_list[i] = NULL;
  587.  
  588.   return HOSTENT;
  589. }
  590.  
  591. /*
  592.  * id_addr variable is used by both the gethostname() and gethostid().
  593.  * 
  594.  * host_name is the host_name configuration variable.
  595.  */
  596. static ULONG id_addr = 0;
  597.  
  598. void findid(ULONG *); /* defined in net/if.c */
  599.  
  600. /*
  601.  * Global host name and name length
  602.  */
  603. char host_name[MAXHOSTNAMELEN+1] = { 0 };
  604. size_t host_namelen = 0;
  605.  
  606. /****i* AmiTCP/sethostname *********************************************
  607. *
  608. *   NAME   
  609. *       sethostname -- set the name of the host
  610. *
  611. *   SYNOPSIS
  612. *       error = sethostname(name, namelen);
  613. *
  614. *       int sethostname(const char *, size_t);
  615. *
  616. *   FUNCTION
  617. *       Set the name of the host to the given 'name' of length 'namelen'.
  618. *
  619. *   INPUTS
  620. *       name    - Pointer to the name string.
  621. *       namelen - Length of the name.
  622. *
  623. *   RESULT
  624. *       error   - 0 on success.
  625. *  
  626. *   EXAMPLE
  627. *
  628. *   NOTES
  629. *       This function is not intended to be provided to the applications,
  630. *       this is for AmiTCP internal use only (at least for now).
  631. *
  632. *   BUGS
  633. *
  634. *   SEE ALSO
  635. *****************************************************************************
  636. *
  637. */
  638. int
  639. sethostname(const char * name, size_t namelen)
  640. {
  641.   if (namelen > MAXHOSTNAMELEN)
  642.     namelen = MAXHOSTNAMELEN;
  643.  
  644.   memcpy(host_name, name, namelen);
  645.   host_name[namelen] = '\0';
  646.   host_namelen = namelen;
  647.  
  648.   return 0;
  649. }
  650.  
  651. /****** bsdsocket.library/gethostname *************************************
  652. *
  653. *   NAME   
  654. *       gethostname -- get the name of the host
  655. *
  656. *   SYNOPSIS
  657. *       error = gethostname(name, namelen);
  658. *
  659. *       long gethostname(char *, long);
  660. *
  661. *   FUNCTION
  662. *       Get the name of the host to the buffer name of length namelen.
  663. *       The name is queried from the netdb and/or the name server if 
  664. *       it is not explicitly configured (configuration variable
  665. *       HOSTNAME).
  666. *
  667. *   INPUTS
  668. *       name    - Pointer to the buffer where the name should be
  669. *                 stored.
  670. *       namelen - Length of the buffer name.
  671. *
  672. *   RESULT
  673. *       error   - 0 on success.
  674. *  
  675. *   EXAMPLE
  676. *       char hostname[MAXHOSTNAMELEN];
  677. *       long error;
  678. *       
  679. *       error = gethostname(hostname, sizeof(hostname));
  680. *       if (error < 0)
  681. *         exit(10);
  682. *       
  683. *       printf("My name is \"%s\".\n", hostname);
  684. *
  685. *   NOTES
  686. *
  687. *   BUGS
  688. *       Unlike the Unix version, this version assures that the
  689. *       resulting string is always NULL-terminated.
  690. *
  691. *   SEE ALSO
  692. *       gethostid()
  693. *****************************************************************************
  694. *
  695. */
  696. LONG SAVEDS RAF3(_gethostname,
  697.          struct SocketBase *,    libPtr,        a6,
  698.          STRPTR,        name,        a0,
  699.          LONG,            namelen,    d0)
  700. #if 0     
  701. {
  702. #endif
  703.   CHECK_TASK();
  704.  
  705.   /*
  706.    * Get the name with the gethostbyaddr(), if the name is not set yet.
  707.    */
  708.   if (*host_name == '\0') {
  709.     struct hostent * hent;
  710.     /* gethostid() */
  711.     if (id_addr == 0)
  712.       findid(&id_addr);
  713.     if (id_addr != 0) { /* query if we have an address */
  714.       hent = gethostbyaddr(libPtr, (const UBYTE *)&id_addr,
  715.                sizeof(id_addr), AF_INET);
  716.       if (hent != NULL) {
  717.     sethostname(hent->h_name, strlen(hent->h_name));
  718.       }
  719.     }
  720.   }
  721.   
  722.   /*
  723.    * Copy the name to the user buffer. stccpy() ensures that the buffer
  724.    * is not written over and that it will be null-terminated.
  725.    */
  726.   if (namelen > host_namelen)
  727.     namelen = host_namelen;
  728.   else
  729.     namelen--;            /* make space for the trailing '\0' */
  730.  
  731.   memcpy(name, host_name, namelen);
  732.   name[namelen] = '\0';
  733.  
  734.   API_STD_RETURN(0, 0);
  735. }
  736.  
  737. /****** bsdsocket.library/gethostid ***************************************
  738. *
  739. *   NAME   
  740. *       gethostid -- get an unique 32-bit id to this host
  741. *
  742. *   SYNOPSIS
  743. *       id = gethostid();
  744. *
  745. *       ULONG gethostid(void);
  746. *
  747. *   FUNCTION
  748. *       Return the 32-bit unique id for this host. The Internet
  749. *       address if the primary interface is used as the unique id.
  750. *       This means that this function is also a supported way to get
  751. *       the hosts IP address in AmiTCP/IP. If no interfaces are
  752. *       configured, zero is returned. Any non-loobpack interface with
  753. *       is preferred. Only if no other interfaces are present, is the
  754. *       loopback address returned.
  755. *       
  756. *   INPUTS
  757. *
  758. *   RESULT
  759. *       id  - non-zero on success.
  760. *  
  761. *   EXAMPLE
  762. *       ULONG id;
  763. *       
  764. *       id = gethostid();
  765. *       if (id == 0)
  766. *         exit(10);
  767. *       
  768. *       printf("My primary IP address is: %s.\n", Inet_NtoA(id));
  769. *
  770. *   NOTES
  771. *       Non-zero id is returned as soon as a interface is configured.
  772. *       After that the id will not change, not even if the id is the
  773. *       address of the loopback interface.
  774. *
  775. *   BUGS
  776. *
  777. *   SEE ALSO
  778. *****************************************************************************
  779. *
  780. */
  781. ULONG SAVEDS RAF1(_gethostid,
  782.           struct SocketBase *,    libPtr,    a6)
  783. #if 0     
  784. {
  785. #endif
  786.  
  787.   if (id_addr == 0)
  788.     findid(&id_addr);
  789.   return id_addr;
  790. }
  791.