| The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright (C) 2008 The Android Open Source Project | 
|  | 3 | * All rights reserved. | 
|  | 4 | * | 
|  | 5 | * Redistribution and use in source and binary forms, with or without | 
|  | 6 | * modification, are permitted provided that the following conditions | 
|  | 7 | * are met: | 
|  | 8 | *  * Redistributions of source code must retain the above copyright | 
|  | 9 | *    notice, this list of conditions and the following disclaimer. | 
|  | 10 | *  * Redistributions in binary form must reproduce the above copyright | 
|  | 11 | *    notice, this list of conditions and the following disclaimer in | 
|  | 12 | *    the documentation and/or other materials provided with the | 
|  | 13 | *    distribution. | 
|  | 14 | * | 
|  | 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
|  | 16 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
|  | 17 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | 
|  | 18 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 
|  | 19 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | 
|  | 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | 
|  | 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | 
|  | 22 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 
|  | 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | 
|  | 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | 
|  | 25 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 
|  | 26 | * SUCH DAMAGE. | 
|  | 27 | */ | 
|  | 28 | #include <sys/cdefs.h> | 
|  | 29 | #include <sys/types.h> | 
|  | 30 | #include <arpa/inet.h> | 
|  | 31 | #include "arpa_nameser.h" | 
|  | 32 | #include <netdb.h> | 
|  | 33 | #include "resolv_private.h" | 
|  | 34 | #include "resolv_cache.h" | 
|  | 35 | #include <pthread.h> | 
|  | 36 | #include <stdlib.h> | 
|  | 37 |  | 
|  | 38 | #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ | 
|  | 39 | #include <sys/_system_properties.h> | 
|  | 40 |  | 
|  | 41 | static pthread_key_t   _res_key; | 
|  | 42 | static pthread_once_t  _res_once; | 
|  | 43 |  | 
|  | 44 | typedef struct { | 
|  | 45 | int                    _h_errno; | 
|  | 46 | struct __res_state     _nres[1]; | 
|  | 47 | unsigned               _serial; | 
|  | 48 | struct prop_info*      _pi; | 
|  | 49 | struct res_static      _rstatic[1]; | 
|  | 50 | } _res_thread; | 
|  | 51 |  | 
|  | 52 | static _res_thread* | 
|  | 53 | _res_thread_alloc(void) | 
|  | 54 | { | 
|  | 55 | _res_thread*  rt = malloc(sizeof(*rt)); | 
|  | 56 |  | 
|  | 57 | if (rt) { | 
|  | 58 | rt->_h_errno = 0; | 
|  | 59 | /* Special system property which tracks any changes to 'net.*'. */ | 
|  | 60 | rt->_serial = 0; | 
|  | 61 | rt->_pi = (struct prop_info*) __system_property_find("net.change"); | 
|  | 62 | if (rt->_pi) { | 
|  | 63 | rt->_serial = rt->_pi->serial; | 
|  | 64 | } | 
|  | 65 | if ( res_ninit( rt->_nres ) < 0 ) { | 
|  | 66 | free(rt); | 
|  | 67 | rt = NULL; | 
|  | 68 | } else { | 
|  | 69 | memset(rt->_rstatic, 0, sizeof rt->_rstatic); | 
|  | 70 | } | 
|  | 71 | } | 
|  | 72 | return rt; | 
|  | 73 | } | 
|  | 74 |  | 
|  | 75 | static void | 
|  | 76 | _res_static_done( res_static  rs ) | 
|  | 77 | { | 
|  | 78 | /* fortunately, there is nothing to do here, since the | 
|  | 79 | * points in h_addr_ptrs and host_aliases should all | 
|  | 80 | * point to 'hostbuf' | 
|  | 81 | */ | 
|  | 82 | if (rs->hostf) {  /* should not happen in theory, but just be safe */ | 
|  | 83 | fclose(rs->hostf); | 
|  | 84 | rs->hostf = NULL; | 
|  | 85 | } | 
|  | 86 | free(rs->servent.s_aliases); | 
|  | 87 | } | 
|  | 88 |  | 
|  | 89 | static void | 
|  | 90 | _res_thread_free( void*  _rt ) | 
|  | 91 | { | 
|  | 92 | _res_thread*  rt = _rt; | 
|  | 93 |  | 
|  | 94 | _res_static_done(rt->_rstatic); | 
|  | 95 | res_ndestroy(rt->_nres); | 
|  | 96 | free(rt); | 
|  | 97 | } | 
|  | 98 |  | 
|  | 99 | static void | 
|  | 100 | _res_init_key( void ) | 
|  | 101 | { | 
|  | 102 | pthread_key_create( &_res_key, _res_thread_free ); | 
|  | 103 | } | 
|  | 104 |  | 
|  | 105 | static _res_thread* | 
|  | 106 | _res_thread_get(void) | 
|  | 107 | { | 
|  | 108 | _res_thread*  rt; | 
|  | 109 | pthread_once( &_res_once, _res_init_key ); | 
|  | 110 | rt = pthread_getspecific( _res_key ); | 
|  | 111 | if (rt == NULL) { | 
|  | 112 | if ((rt = _res_thread_alloc()) == NULL) { | 
|  | 113 | return NULL; | 
|  | 114 | } | 
|  | 115 | rt->_h_errno = 0; | 
|  | 116 | rt->_serial = 0; | 
|  | 117 | pthread_setspecific( _res_key, rt ); | 
|  | 118 | } | 
|  | 119 | /* Check the serial value for any chanes to net.* properties. */ | 
|  | 120 | if (rt->_pi == NULL) { | 
|  | 121 | rt->_pi = (struct prop_info*) __system_property_find("net.change"); | 
|  | 122 | } | 
|  | 123 | if (rt->_pi == NULL || rt->_serial == rt->_pi->serial) { | 
|  | 124 | return rt; | 
|  | 125 | } | 
|  | 126 | rt->_serial = rt->_pi->serial; | 
|  | 127 | /* Reload from system properties. */ | 
|  | 128 | if ( res_ninit( rt->_nres ) < 0 ) { | 
|  | 129 | free(rt); | 
|  | 130 | rt = NULL; | 
|  | 131 | pthread_setspecific( _res_key, rt ); | 
|  | 132 | } | 
|  | 133 | _resolv_cache_reset(rt->_serial); | 
|  | 134 | return rt; | 
|  | 135 | } | 
|  | 136 |  | 
|  | 137 | struct __res_state _nres; | 
|  | 138 |  | 
|  | 139 | #if 0 | 
|  | 140 | struct resolv_cache* | 
|  | 141 | __get_res_cache(void) | 
|  | 142 | { | 
|  | 143 | _res_thread*  rt = _res_thread_get(); | 
|  | 144 |  | 
|  | 145 | if (!rt) | 
|  | 146 | return NULL; | 
|  | 147 |  | 
|  | 148 | if (!rt->_cache) { | 
|  | 149 | rt->_cache = _resolv_cache_create(); | 
|  | 150 | } | 
|  | 151 | return rt->_cache; | 
|  | 152 | } | 
|  | 153 | #endif | 
|  | 154 |  | 
|  | 155 | int* | 
|  | 156 | __get_h_errno(void) | 
|  | 157 | { | 
|  | 158 | _res_thread*  rt    = _res_thread_get(); | 
|  | 159 | static int    panic = NETDB_INTERNAL; | 
|  | 160 |  | 
|  | 161 | return rt ? &rt->_h_errno : &panic; | 
|  | 162 | } | 
|  | 163 |  | 
|  | 164 | res_state | 
|  | 165 | __res_get_state(void) | 
|  | 166 | { | 
|  | 167 | _res_thread*  rt = _res_thread_get(); | 
|  | 168 |  | 
|  | 169 | return rt ? rt->_nres : NULL; | 
|  | 170 | } | 
|  | 171 |  | 
|  | 172 | void | 
|  | 173 | __res_put_state(res_state res) | 
|  | 174 | { | 
|  | 175 | /* nothing to do */ | 
|  | 176 | res=res; | 
|  | 177 | } | 
|  | 178 |  | 
|  | 179 | res_static | 
|  | 180 | __res_get_static(void) | 
|  | 181 | { | 
|  | 182 | _res_thread*  rt = _res_thread_get(); | 
|  | 183 |  | 
|  | 184 | return rt ? rt->_rstatic : NULL; | 
|  | 185 | } |