1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/address_list.h"
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <stdlib.h>
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_util.h"
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/sys_addrinfo.h"
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net {
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace {
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochchar* do_strdup(const char* src) {
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN)
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return _strdup(src);
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return strdup(src);
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Assign the port for all addresses in the list.
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SetPortRecursive(struct addrinfo* info, int port) {
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  uint16* port_field = GetPortFieldFromAddrinfo(info);
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (port_field)
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *port_field = htons(port);
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Assign recursively.
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (info->ai_next)
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SetPortRecursive(info->ai_next, port);
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstruct AddressList::Data : public base::RefCountedThreadSafe<Data> {
393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Data(struct addrinfo* ai, bool is_system_created);
403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  struct addrinfo* head;
413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Indicates which free function to use for |head|.
433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool is_system_created;
443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick private:
463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  friend class base::RefCountedThreadSafe<Data>;
473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ~Data();
493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick};
503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
513345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickAddressList::AddressList() {
523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
543345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickAddressList::AddressList(const IPAddressNumber& address, int port,
553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                         bool canonicalize_name) {
563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  struct addrinfo* ai = new addrinfo;
573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  memset(ai, 0, sizeof(addrinfo));
583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ai->ai_socktype = SOCK_STREAM;
593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  switch (address.size()) {
613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case 4: {
623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ai->ai_family = AF_INET;
633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      const size_t sockaddr_in_size = sizeof(struct sockaddr_in);
643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ai->ai_addrlen = sockaddr_in_size;
653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(
673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          new char[sockaddr_in_size]);
683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      memset(addr, 0, sockaddr_in_size);
693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      addr->sin_family = AF_INET;
703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      memcpy(&addr->sin_addr, &address[0], 4);
713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ai->ai_addr = reinterpret_cast<struct sockaddr*>(addr);
723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case 16: {
753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ai->ai_family = AF_INET6;
763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      const size_t sockaddr_in6_size = sizeof(struct sockaddr_in6);
773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ai->ai_addrlen = sockaddr_in6_size;
783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      struct sockaddr_in6* addr6 = reinterpret_cast<struct sockaddr_in6*>(
803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          new char[sockaddr_in6_size]);
813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      memset(addr6, 0, sockaddr_in6_size);
823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      addr6->sin6_family = AF_INET6;
833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      memcpy(&addr6->sin6_addr, &address[0], 16);
843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ai->ai_addr = reinterpret_cast<struct sockaddr*>(addr6);
853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    default: {
883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NOTREACHED() << "Bad IP address";
893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (canonicalize_name) {
943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    std::string name = NetAddressToString(ai);
953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ai->ai_canonname = do_strdup(name.c_str());
963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  data_ = new Data(ai, false /*is_system_created*/);
983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SetPort(port);
993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
10172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenAddressList::AddressList(const AddressList& addresslist)
10272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    : data_(addresslist.data_) {
10372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
10472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
10572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenAddressList::~AddressList() {
10672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
10772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
10872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenAddressList& AddressList::operator=(const AddressList& addresslist) {
10972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  data_ = addresslist.data_;
11072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return *this;
11172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid AddressList::Adopt(struct addrinfo* head) {
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_ = new Data(head, true /*is_system_created*/);
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AddressList::Copy(const struct addrinfo* head, bool recursive) {
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  data_ = new Data(CreateCopyOfAddrinfo(head, recursive),
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   false /*is_system_created*/);
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AddressList::Append(const struct addrinfo* head) {
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(head);
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct addrinfo* new_head;
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (data_->is_system_created) {
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    new_head = CreateCopyOfAddrinfo(data_->head, true);
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_ = new Data(new_head, false /*is_system_created*/);
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    new_head = data_->head;
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Find the end of current linked list and append new data there.
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct addrinfo* copy_ptr = new_head;
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (copy_ptr->ai_next)
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    copy_ptr = copy_ptr->ai_next;
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  copy_ptr->ai_next = CreateCopyOfAddrinfo(head, true);
136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Only the head of the list should have a canonname.  Strip any
138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // canonical name in the appended data.
139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  copy_ptr = copy_ptr->ai_next;
140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  while (copy_ptr) {
141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (copy_ptr->ai_canonname) {
142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      free(copy_ptr->ai_canonname);
143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      copy_ptr->ai_canonname = NULL;
144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    copy_ptr = copy_ptr->ai_next;
146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid AddressList::SetPort(int port) {
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SetPortRecursive(data_->head, port);
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint AddressList::GetPort() const {
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return GetPortFromAddrinfo(data_->head);
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid AddressList::SetFrom(const AddressList& src, int port) {
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (src.GetPort() == port) {
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // We can reference the data from |src| directly.
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    *this = src;
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Otherwise we need to make a copy in order to change the port number.
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Copy(src.head(), true);
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SetPort(port);
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
16872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool AddressList::GetCanonicalName(std::string* canonical_name) const {
16972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(canonical_name);
17072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!data_ || !data_->head->ai_canonname)
17172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
17272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  canonical_name->assign(data_->head->ai_canonname);
17372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return true;
17472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
17572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid AddressList::Reset() {
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_ = NULL;
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst struct addrinfo* AddressList::head() const {
181dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!data_)
182dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return NULL;
1833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return data_->head;
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1863345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickAddressList::AddressList(Data* data) : data_(data) {}
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
188dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// static
189dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenAddressList* AddressList::CreateAddressListFromSockaddr(
190dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const struct sockaddr* address,
191dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    socklen_t address_length,
192dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    int socket_type,
193dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    int protocol) {
194dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Do sanity checking on socket_type and protocol.
195dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(socket_type == SOCK_DGRAM || socket_type == SOCK_STREAM);
196dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(protocol == IPPROTO_TCP || protocol == IPPROTO_UDP);
197dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
198dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  struct addrinfo* ai = new addrinfo;
199dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  memset(ai, 0, sizeof(addrinfo));
200dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  switch (address_length) {
201dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case sizeof(struct sockaddr_in):
202dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      {
203dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        const struct sockaddr_in* sin =
204dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            reinterpret_cast<const struct sockaddr_in*>(address);
205dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        ai->ai_family = sin->sin_family;
206dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        DCHECK_EQ(AF_INET, ai->ai_family);
207dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
208dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      break;
209dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case sizeof(struct sockaddr_in6):
210dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      {
211dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        const struct sockaddr_in6* sin6 =
212dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            reinterpret_cast<const struct sockaddr_in6*>(address);
213dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        ai->ai_family = sin6->sin6_family;
214dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        DCHECK_EQ(AF_INET6, ai->ai_family);
215dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
216dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      break;
217dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    default:
218dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      NOTREACHED() << "Bad IP address";
219dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      break;
220dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
221dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ai->ai_socktype = socket_type;
222dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ai->ai_protocol = protocol;
223dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ai->ai_addrlen = address_length;
224dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ai->ai_addr = reinterpret_cast<struct sockaddr*>(new char[address_length]);
225dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  memcpy(ai->ai_addr, address, address_length);
226dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return new AddressList(new Data(ai, false /*is_system_created*/));
227dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
228dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
229dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAddressList::Data::Data(struct addrinfo* ai, bool is_system_created)
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : head(ai), is_system_created(is_system_created) {
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(head);
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottAddressList::Data::~Data() {
236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Call either freeaddrinfo(head), or FreeCopyOfAddrinfo(head), depending on
237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // who created the data.
238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (is_system_created)
239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    freeaddrinfo(head);
240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  else
241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    FreeCopyOfAddrinfo(head);
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace net
245