1 /* Operations on network stuff.
2 Copyright (C) 2018-2019 Free Software Foundation, Inc.
4 This file is part of GDB.
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.
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.
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/>. */
19 #include "common-defs.h"
24 #if _WIN32_WINNT < 0x0501
26 # define _WIN32_WINNT 0x0501
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
33 #include <sys/socket.h>
34 #include <netinet/tcp.h>
37 /* See common/netstuff.h. */
39 scoped_free_addrinfo::~scoped_free_addrinfo ()
44 /* See common/netstuff.h. */
46 parsed_connection_spec
47 parse_connection_spec_without_prefix (std::string spec
, struct addrinfo
*hint
)
49 parsed_connection_spec ret
;
50 size_t last_colon_pos
= 0;
51 /* We're dealing with IPv6 if:
53 - ai_family is AF_INET6, or
54 - ai_family is not AF_INET, and
56 - the number of ':' on spec is greater than 1. */
57 bool is_ipv6
= (hint
->ai_family
== AF_INET6
58 || (hint
->ai_family
!= AF_INET
60 || std::count (spec
.begin (),
61 spec
.end (), ':') > 1)));
67 /* IPv6 addresses can be written as '[ADDR]:PORT', and we
68 support this notation. */
69 size_t close_bracket_pos
= spec
.find_first_of (']');
71 if (close_bracket_pos
== std::string::npos
)
72 error (_("Missing close bracket in hostname '%s'"),
75 hint
->ai_family
= AF_INET6
;
77 const char c
= spec
[close_bracket_pos
+ 1];
80 last_colon_pos
= std::string::npos
;
82 error (_("Invalid cruft after close bracket in '%s'"),
85 /* Erase both '[' and ']'. */
87 spec
.erase (close_bracket_pos
- 1, 1);
89 else if (spec
.find_first_of (']') != std::string::npos
)
90 error (_("Missing open bracket in hostname '%s'"),
94 if (last_colon_pos
== 0)
95 last_colon_pos
= spec
.find_last_of (':');
97 /* The length of the hostname part. */
100 if (last_colon_pos
!= std::string::npos
)
102 /* The user has provided a port. */
103 host_len
= last_colon_pos
;
104 ret
.port_str
= spec
.substr (last_colon_pos
+ 1);
107 host_len
= spec
.size ();
109 ret
.host_str
= spec
.substr (0, host_len
);
111 /* Default hostname is localhost. */
112 if (ret
.host_str
.empty ())
113 ret
.host_str
= "localhost";
118 /* See common/netstuff.h. */
120 parsed_connection_spec
121 parse_connection_spec (const char *spec
, struct addrinfo
*hint
)
123 /* Struct to hold the association between valid prefixes, their
124 family and socktype. */
130 /* The 'ai_family'. */
133 /* The 'ai_socktype'. */
136 static const struct host_prefix prefixes
[] =
138 { "udp:", AF_UNSPEC
, SOCK_DGRAM
},
139 { "tcp:", AF_UNSPEC
, SOCK_STREAM
},
140 { "udp4:", AF_INET
, SOCK_DGRAM
},
141 { "tcp4:", AF_INET
, SOCK_STREAM
},
142 { "udp6:", AF_INET6
, SOCK_DGRAM
},
143 { "tcp6:", AF_INET6
, SOCK_STREAM
},
146 for (const host_prefix prefix
: prefixes
)
147 if (startswith (spec
, prefix
.prefix
))
149 spec
+= strlen (prefix
.prefix
);
150 hint
->ai_family
= prefix
.family
;
151 hint
->ai_socktype
= prefix
.socktype
;
153 = hint
->ai_socktype
== SOCK_DGRAM
? IPPROTO_UDP
: IPPROTO_TCP
;
157 return parse_connection_spec_without_prefix (spec
, hint
);