Do not reopen temporary files
[deliverable/binutils-gdb.git] / gdb / common / netstuff.c
CommitLineData
c7ab0aef
SDJ
1/* Operations on network stuff.
2 Copyright (C) 2018 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18
19#include "common-defs.h"
20#include "netstuff.h"
21#include <algorithm>
22
23#ifdef USE_WIN32API
24#include <winsock2.h>
25#include <wspiapi.h>
26#else
27#include <netinet/in.h>
28#include <arpa/inet.h>
29#include <netdb.h>
30#include <sys/socket.h>
31#include <netinet/tcp.h>
32#endif
33
34/* See common/netstuff.h. */
35
36scoped_free_addrinfo::~scoped_free_addrinfo ()
37{
38 freeaddrinfo (m_res);
39}
40
41/* See common/netstuff.h. */
42
43parsed_connection_spec
44parse_connection_spec_without_prefix (std::string spec, struct addrinfo *hint)
45{
46 parsed_connection_spec ret;
47 size_t last_colon_pos = 0;
48 /* We're dealing with IPv6 if:
49
50 - ai_family is AF_INET6, or
51 - ai_family is not AF_INET, and
52 - spec[0] is '[', or
53 - the number of ':' on spec is greater than 1. */
54 bool is_ipv6 = (hint->ai_family == AF_INET6
55 || (hint->ai_family != AF_INET
56 && (spec[0] == '['
57 || std::count (spec.begin (),
58 spec.end (), ':') > 1)));
f19c7ff8 59 bool is_unix = hint->ai_family == AF_UNIX;
c7ab0aef
SDJ
60
61 if (is_ipv6)
62 {
63 if (spec[0] == '[')
64 {
65 /* IPv6 addresses can be written as '[ADDR]:PORT', and we
66 support this notation. */
67 size_t close_bracket_pos = spec.find_first_of (']');
68
69 if (close_bracket_pos == std::string::npos)
70 error (_("Missing close bracket in hostname '%s'"),
71 spec.c_str ());
72
73 hint->ai_family = AF_INET6;
74
75 const char c = spec[close_bracket_pos + 1];
76
77 if (c == '\0')
78 last_colon_pos = std::string::npos;
79 else if (c != ':')
80 error (_("Invalid cruft after close bracket in '%s'"),
81 spec.c_str ());
82
83 /* Erase both '[' and ']'. */
84 spec.erase (0, 1);
85 spec.erase (close_bracket_pos - 1, 1);
86 }
87 else if (spec.find_first_of (']') != std::string::npos)
88 error (_("Missing open bracket in hostname '%s'"),
89 spec.c_str ());
90 }
91
92 if (last_colon_pos == 0)
93 last_colon_pos = spec.find_last_of (':');
94
95 /* The length of the hostname part. */
96 size_t host_len;
97
98 if (last_colon_pos != std::string::npos)
99 {
100 /* The user has provided a port. */
101 host_len = last_colon_pos;
102 ret.port_str = spec.substr (last_colon_pos + 1);
103 }
104 else
105 host_len = spec.size ();
106
107 ret.host_str = spec.substr (0, host_len);
108
109 /* Default hostname is localhost. */
110 if (ret.host_str.empty ())
111 ret.host_str = "localhost";
112
f19c7ff8
JD
113 if (is_unix && ret.host_str != "localhost")
114 error (_("The host name must be empty or 'localhost' for a unix domain socket."));
115
116 if (is_unix && ret.port_str.empty ())
117 error (_("A path name must be specified for a unix domain socket."));
118
c7ab0aef
SDJ
119 return ret;
120}
121
122/* See common/netstuff.h. */
123
124parsed_connection_spec
125parse_connection_spec (const char *spec, struct addrinfo *hint)
126{
127 /* Struct to hold the association between valid prefixes, their
128 family and socktype. */
129 struct host_prefix
130 {
131 /* The prefix. */
132 const char *prefix;
133
134 /* The 'ai_family'. */
135 int family;
136
137 /* The 'ai_socktype'. */
138 int socktype;
139 };
140 static const struct host_prefix prefixes[] =
141 {
142 { "udp:", AF_UNSPEC, SOCK_DGRAM },
143 { "tcp:", AF_UNSPEC, SOCK_STREAM },
144 { "udp4:", AF_INET, SOCK_DGRAM },
145 { "tcp4:", AF_INET, SOCK_STREAM },
146 { "udp6:", AF_INET6, SOCK_DGRAM },
147 { "tcp6:", AF_INET6, SOCK_STREAM },
f19c7ff8 148 { "unix:", AF_LOCAL, SOCK_STREAM },
c7ab0aef
SDJ
149 };
150
151 for (const host_prefix prefix : prefixes)
152 if (startswith (spec, prefix.prefix))
153 {
154 spec += strlen (prefix.prefix);
155 hint->ai_family = prefix.family;
156 hint->ai_socktype = prefix.socktype;
157 hint->ai_protocol
158 = hint->ai_socktype == SOCK_DGRAM ? IPPROTO_UDP : IPPROTO_TCP;
159 break;
160 }
161
162 return parse_connection_spec_without_prefix (spec, hint);
163}
This page took 0.052638 seconds and 4 git commands to generate.