1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/base/address_list.h" 6 7 #include <stdlib.h> 8 9 #include "base/logging.h" 10 #include "net/base/net_util.h" 11 #include "net/base/sys_addrinfo.h" 12 13 namespace net { 14 15 namespace { 16 17 char* do_strdup(const char* src) { 18 #if defined(OS_WIN) 19 return _strdup(src); 20 #else 21 return strdup(src); 22 #endif 23 } 24 25 // Assign the port for all addresses in the list. 26 void SetPortRecursive(struct addrinfo* info, int port) { 27 uint16* port_field = GetPortFieldFromAddrinfo(info); 28 if (port_field) 29 *port_field = htons(port); 30 31 // Assign recursively. 32 if (info->ai_next) 33 SetPortRecursive(info->ai_next, port); 34 } 35 36 } // namespace 37 38 struct AddressList::Data : public base::RefCountedThreadSafe<Data> { 39 Data(struct addrinfo* ai, bool is_system_created); 40 struct addrinfo* head; 41 42 // Indicates which free function to use for |head|. 43 bool is_system_created; 44 45 private: 46 friend class base::RefCountedThreadSafe<Data>; 47 48 ~Data(); 49 }; 50 51 AddressList::AddressList() { 52 } 53 54 AddressList::AddressList(const IPAddressNumber& address, int port, 55 bool canonicalize_name) { 56 struct addrinfo* ai = new addrinfo; 57 memset(ai, 0, sizeof(addrinfo)); 58 ai->ai_socktype = SOCK_STREAM; 59 60 switch (address.size()) { 61 case 4: { 62 ai->ai_family = AF_INET; 63 const size_t sockaddr_in_size = sizeof(struct sockaddr_in); 64 ai->ai_addrlen = sockaddr_in_size; 65 66 struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>( 67 new char[sockaddr_in_size]); 68 memset(addr, 0, sockaddr_in_size); 69 addr->sin_family = AF_INET; 70 memcpy(&addr->sin_addr, &address[0], 4); 71 ai->ai_addr = reinterpret_cast<struct sockaddr*>(addr); 72 break; 73 } 74 case 16: { 75 ai->ai_family = AF_INET6; 76 const size_t sockaddr_in6_size = sizeof(struct sockaddr_in6); 77 ai->ai_addrlen = sockaddr_in6_size; 78 79 struct sockaddr_in6* addr6 = reinterpret_cast<struct sockaddr_in6*>( 80 new char[sockaddr_in6_size]); 81 memset(addr6, 0, sockaddr_in6_size); 82 addr6->sin6_family = AF_INET6; 83 memcpy(&addr6->sin6_addr, &address[0], 16); 84 ai->ai_addr = reinterpret_cast<struct sockaddr*>(addr6); 85 break; 86 } 87 default: { 88 NOTREACHED() << "Bad IP address"; 89 break; 90 } 91 } 92 93 if (canonicalize_name) { 94 std::string name = NetAddressToString(ai); 95 ai->ai_canonname = do_strdup(name.c_str()); 96 } 97 data_ = new Data(ai, false /*is_system_created*/); 98 SetPort(port); 99 } 100 101 AddressList::AddressList(const AddressList& addresslist) 102 : data_(addresslist.data_) { 103 } 104 105 AddressList::~AddressList() { 106 } 107 108 AddressList& AddressList::operator=(const AddressList& addresslist) { 109 data_ = addresslist.data_; 110 return *this; 111 } 112 113 void AddressList::Adopt(struct addrinfo* head) { 114 data_ = new Data(head, true /*is_system_created*/); 115 } 116 117 void AddressList::Copy(const struct addrinfo* head, bool recursive) { 118 data_ = new Data(CreateCopyOfAddrinfo(head, recursive), 119 false /*is_system_created*/); 120 } 121 122 void AddressList::Append(const struct addrinfo* head) { 123 DCHECK(head); 124 struct addrinfo* new_head; 125 if (data_->is_system_created) { 126 new_head = CreateCopyOfAddrinfo(data_->head, true); 127 data_ = new Data(new_head, false /*is_system_created*/); 128 } else { 129 new_head = data_->head; 130 } 131 // Find the end of current linked list and append new data there. 132 struct addrinfo* copy_ptr = new_head; 133 while (copy_ptr->ai_next) 134 copy_ptr = copy_ptr->ai_next; 135 copy_ptr->ai_next = CreateCopyOfAddrinfo(head, true); 136 137 // Only the head of the list should have a canonname. Strip any 138 // canonical name in the appended data. 139 copy_ptr = copy_ptr->ai_next; 140 while (copy_ptr) { 141 if (copy_ptr->ai_canonname) { 142 free(copy_ptr->ai_canonname); 143 copy_ptr->ai_canonname = NULL; 144 } 145 copy_ptr = copy_ptr->ai_next; 146 } 147 } 148 149 void AddressList::SetPort(int port) { 150 SetPortRecursive(data_->head, port); 151 } 152 153 int AddressList::GetPort() const { 154 return GetPortFromAddrinfo(data_->head); 155 } 156 157 void AddressList::SetFrom(const AddressList& src, int port) { 158 if (src.GetPort() == port) { 159 // We can reference the data from |src| directly. 160 *this = src; 161 } else { 162 // Otherwise we need to make a copy in order to change the port number. 163 Copy(src.head(), true); 164 SetPort(port); 165 } 166 } 167 168 bool AddressList::GetCanonicalName(std::string* canonical_name) const { 169 DCHECK(canonical_name); 170 if (!data_ || !data_->head->ai_canonname) 171 return false; 172 canonical_name->assign(data_->head->ai_canonname); 173 return true; 174 } 175 176 void AddressList::Reset() { 177 data_ = NULL; 178 } 179 180 const struct addrinfo* AddressList::head() const { 181 if (!data_) 182 return NULL; 183 return data_->head; 184 } 185 186 AddressList::AddressList(Data* data) : data_(data) {} 187 188 // static 189 AddressList* AddressList::CreateAddressListFromSockaddr( 190 const struct sockaddr* address, 191 socklen_t address_length, 192 int socket_type, 193 int protocol) { 194 // Do sanity checking on socket_type and protocol. 195 DCHECK(socket_type == SOCK_DGRAM || socket_type == SOCK_STREAM); 196 DCHECK(protocol == IPPROTO_TCP || protocol == IPPROTO_UDP); 197 198 struct addrinfo* ai = new addrinfo; 199 memset(ai, 0, sizeof(addrinfo)); 200 switch (address_length) { 201 case sizeof(struct sockaddr_in): 202 { 203 const struct sockaddr_in* sin = 204 reinterpret_cast<const struct sockaddr_in*>(address); 205 ai->ai_family = sin->sin_family; 206 DCHECK_EQ(AF_INET, ai->ai_family); 207 } 208 break; 209 case sizeof(struct sockaddr_in6): 210 { 211 const struct sockaddr_in6* sin6 = 212 reinterpret_cast<const struct sockaddr_in6*>(address); 213 ai->ai_family = sin6->sin6_family; 214 DCHECK_EQ(AF_INET6, ai->ai_family); 215 } 216 break; 217 default: 218 NOTREACHED() << "Bad IP address"; 219 break; 220 } 221 ai->ai_socktype = socket_type; 222 ai->ai_protocol = protocol; 223 ai->ai_addrlen = address_length; 224 ai->ai_addr = reinterpret_cast<struct sockaddr*>(new char[address_length]); 225 memcpy(ai->ai_addr, address, address_length); 226 return new AddressList(new Data(ai, false /*is_system_created*/)); 227 } 228 229 230 AddressList::Data::Data(struct addrinfo* ai, bool is_system_created) 231 : head(ai), is_system_created(is_system_created) { 232 DCHECK(head); 233 } 234 235 AddressList::Data::~Data() { 236 // Call either freeaddrinfo(head), or FreeCopyOfAddrinfo(head), depending on 237 // who created the data. 238 if (is_system_created) 239 freeaddrinfo(head); 240 else 241 FreeCopyOfAddrinfo(head); 242 } 243 244 } // namespace net 245