Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals

utils.c

Go to the documentation of this file.
00001 /* 00002 * Asterisk -- A telephony toolkit for Linux. 00003 * 00004 * Utility functions 00005 * 00006 * Copyright (C) 2004, Digium 00007 * 00008 * This program is free software, distributed under the terms of 00009 * the GNU General Public License 00010 */ 00011 00012 #include <ctype.h> 00013 #include <string.h> 00014 #include <asterisk/lock.h> 00015 #include <asterisk/utils.h> 00016 00017 #if defined(__FreeBSD__) 00018 00019 /* duh? ERANGE value copied from web... */ 00020 #define ERANGE 34 00021 #undef gethostbyname 00022 00023 AST_MUTEX_DEFINE_STATIC(__mutex); 00024 00025 int gethostbyname_r (const char *name, struct hostent *ret, char *buf, 00026 size_t buflen, struct hostent **result, 00027 int *h_errnop) 00028 { 00029 int hsave; 00030 struct hostent *ph; 00031 ast_mutex_lock(&__mutex); /* begin critical area */ 00032 hsave = h_errno; 00033 00034 ph = gethostbyname(name); 00035 *h_errnop = h_errno; /* copy h_errno to *h_herrnop */ 00036 if (ph == NULL) { 00037 *result = NULL; 00038 } else { 00039 char **p, **q; 00040 char *pbuf; 00041 int nbytes=0; 00042 int naddr=0, naliases=0; 00043 /* determine if we have enough space in buf */ 00044 00045 /* count how many addresses */ 00046 for (p = ph->h_addr_list; *p != 0; p++) { 00047 nbytes += ph->h_length; /* addresses */ 00048 nbytes += sizeof(*p); /* pointers */ 00049 naddr++; 00050 } 00051 nbytes += sizeof(*p); /* one more for the terminating NULL */ 00052 00053 /* count how many aliases, and total length of strings */ 00054 for (p = ph->h_aliases; *p != 0; p++) { 00055 nbytes += (strlen(*p)+1); /* aliases */ 00056 nbytes += sizeof(*p); /* pointers */ 00057 naliases++; 00058 } 00059 nbytes += sizeof(*p); /* one more for the terminating NULL */ 00060 00061 /* here nbytes is the number of bytes required in buffer */ 00062 /* as a terminator must be there, the minimum value is ph->h_length */ 00063 if(nbytes > buflen) { 00064 *result = NULL; 00065 ast_mutex_unlock(&__mutex); /* end critical area */ 00066 return ERANGE; /* not enough space in buf!! */ 00067 } 00068 00069 /* There is enough space. Now we need to do a deep copy! */ 00070 /* Allocation in buffer: 00071 from [0] to [(naddr-1) * sizeof(*p)]: 00072 pointers to addresses 00073 at [naddr * sizeof(*p)]: 00074 NULL 00075 from [(naddr+1) * sizeof(*p)] to [(naddr+naliases) * sizeof(*p)] : 00076 pointers to aliases 00077 at [(naddr+naliases+1) * sizeof(*p)]: 00078 NULL 00079 then naddr addresses (fixed length), and naliases aliases (asciiz). 00080 */ 00081 00082 *ret = *ph; /* copy whole structure (not its address!) */ 00083 00084 /* copy addresses */ 00085 q = (char **)buf; /* pointer to pointers area (type: char **) */ 00086 ret->h_addr_list = q; /* update pointer to address list */ 00087 pbuf = buf + ((naddr+naliases+2)*sizeof(*p)); /* skip that area */ 00088 for (p = ph->h_addr_list; *p != 0; p++) { 00089 memcpy(pbuf, *p, ph->h_length); /* copy address bytes */ 00090 *q++ = pbuf; /* the pointer is the one inside buf... */ 00091 pbuf += ph->h_length; /* advance pbuf */ 00092 } 00093 *q++ = NULL; /* address list terminator */ 00094 00095 /* copy aliases */ 00096 ret->h_aliases = q; /* update pointer to aliases list */ 00097 for (p = ph->h_aliases; *p != 0; p++) { 00098 strcpy(pbuf, *p); /* copy alias strings */ 00099 *q++ = pbuf; /* the pointer is the one inside buf... */ 00100 pbuf += strlen(*p); /* advance pbuf */ 00101 *pbuf++ = 0; /* string terminator */ 00102 } 00103 *q++ = NULL; /* terminator */ 00104 00105 strcpy(pbuf, ph->h_name); /* copy alias strings */ 00106 ret->h_name = pbuf; 00107 pbuf += strlen(ph->h_name); /* advance pbuf */ 00108 *pbuf++ = 0; /* string terminator */ 00109 00110 *result = ret; /* and let *result point to structure */ 00111 00112 } 00113 h_errno = hsave; /* restore h_errno */ 00114 ast_mutex_unlock(&__mutex); /* end critical area */ 00115 00116 return (*result == NULL); /* return 0 on success, non-zero on error */ 00117 } 00118 00119 00120 #endif 00121 00122 struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp) 00123 { 00124 int res; 00125 int herrno; 00126 const char *s; 00127 struct hostent *result = NULL; 00128 /* Although it is perfectly legitimate to lookup a pure integer, for 00129 the sake of the sanity of people who like to name their peers as 00130 integers, we break with tradition and refuse to look up a 00131 pure integer */ 00132 s = host; 00133 while(s && *s) { 00134 if (!isdigit(*s)) 00135 break; 00136 s++; 00137 } 00138 if (!s || !*s) 00139 return NULL; 00140 res = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &result, &herrno); 00141 00142 if (res || !result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0]) 00143 return NULL; 00144 return &hp->hp; 00145 }

Generated on Sat Jun 12 16:40:59 2004 for Asterisk by doxygen 1.3.7