• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *    Copyright (c) 2021, The OpenThread Authors.
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 are met:
7  *    1. Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *    2. Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *    3. Neither the name of the copyright holder nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *    POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "common/dns_utils.hpp"
30 
31 #include <assert.h>
32 
33 #include "common/code_utils.hpp"
34 
NameEndsWithDot(const std::string & aName)35 static bool NameEndsWithDot(const std::string &aName)
36 {
37     return !aName.empty() && aName.back() == '.';
38 }
39 
SplitFullDnsName(const std::string & aName)40 DnsNameInfo SplitFullDnsName(const std::string &aName)
41 {
42     size_t      transportPos;
43     DnsNameInfo nameInfo;
44     std::string fullName = aName;
45 
46     if (!NameEndsWithDot(fullName))
47     {
48         fullName += '.';
49     }
50 
51     transportPos = fullName.rfind("._udp.");
52 
53     if (transportPos == std::string::npos)
54     {
55         transportPos = fullName.rfind("._tcp.");
56     }
57 
58     if (transportPos == std::string::npos)
59     {
60         // host.domain or domain
61         size_t dotPos = fullName.find_first_of('.');
62 
63         assert(dotPos != std::string::npos);
64 
65         // host.domain
66         nameInfo.mHostName = fullName.substr(0, dotPos);
67         nameInfo.mDomain   = fullName.substr(dotPos + 1, fullName.length() - dotPos - 1);
68     }
69     else
70     {
71         // service or service instance
72         size_t dotPos = transportPos > 0 ? fullName.find_last_of('.', transportPos - 1) : std::string::npos;
73 
74         nameInfo.mDomain = fullName.substr(transportPos + 6); // 6 is the length of "._tcp." or "._udp."
75 
76         if (dotPos == std::string::npos)
77         {
78             // service.domain
79             nameInfo.mServiceName = fullName.substr(0, transportPos + 5);
80         }
81         else
82         {
83             // instance.service.domain
84             nameInfo.mInstanceName = fullName.substr(0, dotPos);
85             nameInfo.mServiceName  = fullName.substr(dotPos + 1, transportPos + 4 - dotPos);
86         }
87     }
88 
89     if (!NameEndsWithDot(nameInfo.mDomain))
90     {
91         nameInfo.mDomain += '.';
92     }
93 
94     return nameInfo;
95 }
96 
SplitFullServiceInstanceName(const std::string & aFullName,std::string & aInstanceName,std::string & aType,std::string & aDomain)97 otbrError SplitFullServiceInstanceName(const std::string &aFullName,
98                                        std::string &      aInstanceName,
99                                        std::string &      aType,
100                                        std::string &      aDomain)
101 {
102     otbrError   error    = OTBR_ERROR_NONE;
103     DnsNameInfo nameInfo = SplitFullDnsName(aFullName);
104 
105     VerifyOrExit(nameInfo.IsServiceInstance(), error = OTBR_ERROR_INVALID_ARGS);
106 
107     aInstanceName = std::move(nameInfo.mInstanceName);
108     aType         = std::move(nameInfo.mServiceName);
109     aDomain       = std::move(nameInfo.mDomain);
110 
111 exit:
112     return error;
113 }
114 
SplitFullServiceName(const std::string & aFullName,std::string & aType,std::string & aDomain)115 otbrError SplitFullServiceName(const std::string &aFullName, std::string &aType, std::string &aDomain)
116 {
117     otbrError   error    = OTBR_ERROR_NONE;
118     DnsNameInfo nameInfo = SplitFullDnsName(aFullName);
119 
120     VerifyOrExit(nameInfo.IsService(), error = OTBR_ERROR_INVALID_ARGS);
121 
122     aType   = std::move(nameInfo.mServiceName);
123     aDomain = std::move(nameInfo.mDomain);
124 
125 exit:
126     return error;
127 }
128 
SplitFullHostName(const std::string & aFullName,std::string & aHostName,std::string & aDomain)129 otbrError SplitFullHostName(const std::string &aFullName, std::string &aHostName, std::string &aDomain)
130 {
131     otbrError   error    = OTBR_ERROR_NONE;
132     DnsNameInfo nameInfo = SplitFullDnsName(aFullName);
133 
134     VerifyOrExit(nameInfo.IsHost(), error = OTBR_ERROR_INVALID_ARGS);
135 
136     aHostName = std::move(nameInfo.mHostName);
137     aDomain   = std::move(nameInfo.mDomain);
138 
139 exit:
140     return error;
141 }
142