Line data Source code
1 : // Snap Websites Server -- inet helper functions
2 : // Copyright (c) 2011-2019 Made to Order Software Corp. All Rights Reserved
3 : //
4 : // This program is free software; you can redistribute it and/or modify
5 : // it under the terms of the GNU General Public License as published by
6 : // the Free Software Foundation; either version 2 of the License, or
7 : // (at your option) any later version.
8 : //
9 : // This program is distributed in the hope that it will be useful,
10 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : // GNU General Public License for more details.
13 : //
14 : // You should have received a copy of the GNU General Public License
15 : // along with this program; if not, write to the Free Software
16 : // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 :
18 :
19 : // self
20 : //
21 : #include "snapwebsites/inet_helpers.h"
22 :
23 :
24 : // C++ lib
25 : //
26 : #include <iostream>
27 :
28 :
29 : // last include
30 : //
31 : #include <snapdev/poison.h>
32 :
33 :
34 :
35 : namespace snap
36 : {
37 : namespace snap_inet
38 : {
39 :
40 :
41 :
42 :
43 : /** \brief Convert a string to a in6_addr structure.
44 : *
45 : * This function is similar to inet_pton() only it always converts
46 : * the address to an IPv6 address. The input may be an IPv4 address
47 : * or an IPv6 address.
48 : *
49 : * If the input is neither an IPv4 nor an IPv6 address, the function
50 : * returns 0 and sets errno to EAFNOSUPPORT.
51 : *
52 : * \note
53 : * The function clears the IP address in dst if an error occurs.
54 : * In other words you end up with "IN6ADDR_ANY".
55 : *
56 : * \note
57 : * An IPv4 in an IPv6 address is just preceded by "::ffff:". So
58 : * in most cases you do not need such.
59 : *
60 : * \warning
61 : * IPv4 embedded in an IPv6 address should not be used over the wire.
62 : * In most cases this function is used to save IP address in binary
63 : * in one format rather than having to know which format the address
64 : * was being saved as (i.e. the row or column key of some data in
65 : * Cassandra.)
66 : *
67 : * \param[in] src The string representing an IP address.
68 : * \param[out] dst A pointer to a in6_addr buffer.
69 : *
70 : * \return 0 on error and errno set to EAFNOSUPPORT, otherwise 1
71 : * and dst set to a valid IPv6 address.
72 : */
73 0 : int inet_pton_v6(char const * src, struct in6_addr * dst)
74 : {
75 0 : int const r6(inet_pton(AF_INET6, src, dst));
76 0 : if(r6 != 1)
77 : {
78 : // try again with IPv4
79 : struct in_addr addr;
80 0 : int const r4(inet_pton(AF_INET, src, &addr));
81 0 : if(r4 != 1)
82 : {
83 : // reset the address, it is not good
84 0 : for(size_t i(0); i < sizeof(in6_addr); ++i)
85 : {
86 0 : reinterpret_cast<char *>(dst)[i] = 0;
87 : }
88 0 : return 0;
89 : }
90 :
91 : // convert an IPv4 to an IPv6... (i.e. embedding)
92 0 : std::string ipv6("::ffff:");
93 0 : ipv6 += src;
94 0 : int const r46(inet_pton(AF_INET6, ipv6.c_str(), dst));
95 0 : if(r46 != 1)
96 : {
97 : // somehow it worked as IPv4, but not IPv6?!?
98 0 : for(size_t i(0); i < sizeof(in6_addr); ++i)
99 : {
100 0 : reinterpret_cast<char *>(dst)[i] = 0;
101 : }
102 0 : errno = EAFNOSUPPORT;
103 0 : return 0;
104 : }
105 : }
106 :
107 : // it work, user has result in 'dst'
108 0 : return 1;
109 : }
110 :
111 :
112 : } // snap_inet namespace
113 6 : } // snap namespace
114 : // vim: ts=4 sw=4 et
|