1// Copyright 2013 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/dns/mdns_client.h"
6
7#include "net/base/net_errors.h"
8#include "net/dns/dns_protocol.h"
9#include "net/dns/mdns_client_impl.h"
10
11namespace net {
12
13namespace {
14
15const char kMDnsMulticastGroupIPv4[] = "224.0.0.251";
16const char kMDnsMulticastGroupIPv6[] = "FF02::FB";
17
18IPEndPoint GetMDnsIPEndPoint(const char* address) {
19  IPAddressNumber multicast_group_number;
20  bool success = ParseIPLiteralToNumber(address,
21                                        &multicast_group_number);
22  DCHECK(success);
23  return IPEndPoint(multicast_group_number,
24                    dns_protocol::kDefaultPortMulticast);
25}
26
27int Bind(const IPEndPoint& multicast_addr,
28         uint32 interface_index,
29         DatagramServerSocket* socket) {
30  IPAddressNumber address_any(multicast_addr.address().size());
31  IPEndPoint bind_endpoint(address_any, multicast_addr.port());
32
33  socket->AllowAddressReuse();
34  socket->SetMulticastInterface(interface_index);
35
36  int rv = socket->Listen(bind_endpoint);
37  if (rv < OK)
38    return rv;
39
40  return socket->JoinGroup(multicast_addr.address());
41}
42
43}  // namespace
44
45// static
46scoped_ptr<MDnsSocketFactory> MDnsSocketFactory::CreateDefault() {
47  return scoped_ptr<MDnsSocketFactory>(new MDnsSocketFactoryImpl);
48}
49
50// static
51scoped_ptr<MDnsClient> MDnsClient::CreateDefault() {
52  return scoped_ptr<MDnsClient>(new MDnsClientImpl());
53}
54
55IPEndPoint GetMDnsIPEndPoint(AddressFamily address_family) {
56  switch (address_family) {
57    case ADDRESS_FAMILY_IPV4:
58      return GetMDnsIPEndPoint(kMDnsMulticastGroupIPv4);
59    case ADDRESS_FAMILY_IPV6:
60      return GetMDnsIPEndPoint(kMDnsMulticastGroupIPv6);
61    default:
62      NOTREACHED();
63      return IPEndPoint();
64  }
65}
66
67InterfaceIndexFamilyList GetMDnsInterfacesToBind() {
68  NetworkInterfaceList network_list;
69  InterfaceIndexFamilyList interfaces;
70  if (!GetNetworkList(&network_list, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES))
71    return interfaces;
72  for (size_t i = 0; i < network_list.size(); ++i) {
73    AddressFamily family = GetAddressFamily(network_list[i].address);
74    if (family == ADDRESS_FAMILY_IPV4 || family == ADDRESS_FAMILY_IPV6) {
75      interfaces.push_back(
76          std::make_pair(network_list[i].interface_index, family));
77    }
78  }
79  std::sort(interfaces.begin(), interfaces.end());
80  // Interfaces could have multiple addresses. Filter out duplicate entries.
81  interfaces.erase(std::unique(interfaces.begin(), interfaces.end()),
82                   interfaces.end());
83  return interfaces;
84}
85
86scoped_ptr<DatagramServerSocket> CreateAndBindMDnsSocket(
87    AddressFamily address_family,
88    uint32 interface_index) {
89  scoped_ptr<DatagramServerSocket> socket(
90      new UDPServerSocket(NULL, NetLog::Source()));
91
92  IPEndPoint multicast_addr = GetMDnsIPEndPoint(address_family);
93  int rv = Bind(multicast_addr, interface_index, socket.get());
94  if (rv != OK) {
95    socket.reset();
96    VLOG(1) << "Bind failed, endpoint=" << multicast_addr.ToStringWithoutPort()
97            << ", error=" << rv;
98  }
99  return socket.PassAs<DatagramServerSocket>();
100}
101
102}  // namespace net
103