Termlib: fixed endian bug while reading terminfo file
[senf.git] / senf / Socket / Protocols / INet / INet4Address.cc
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief INet4Address non-inline non-template implementation */
30
31 #include "INet4Address.hh"
32 //#include "INet4Address.ih"
33
34 // Custom includes
35 #include <arpa/inet.h>
36 #include <netdb.h>
37 #include <sys/socket.h>
38 #include <boost/lexical_cast.hpp>
39 #if defined(_REENTRANT) && !defined(__GLIBC__)
40 #include <boost/thread/mutex.hpp>
41 #endif
42
43 //#include "INet4Address.mpp"
44 #define prefix_
45 //-/////////////////////////////////////////////////////////////////////////////////////////////////
46
47 //-/////////////////////////////////////////////////////////////////////////////////////////////////
48 // senf::INet4Address::INet4Address
49
50 prefix_ senf::INet4Address::INet4Address(address_type value)
51 {
52     iref() = htonl(value);
53 }
54
55 prefix_ senf::INet4Address senf::INet4Address::from_string(std::string const & s)
56 {
57     struct in_addr ina;
58     if (::inet_pton(AF_INET,s.c_str(),&ina) > 0)
59         return INet4Address::from_inaddr(ina.s_addr);
60
61     if  (s.empty())
62         throw AddressSyntaxException() << ": empty string";
63
64     int herr (0);
65
66     // If available, we use the reentrant GNU variant. This has the additional advantage, that we
67     // can explicitly ask for IPv4 addresses
68
69 #   ifdef __GLIBC__
70
71     struct hostent entbuf;
72     char buffer[4096];
73     struct hostent * ent (0);
74     ::gethostbyname2_r(s.c_str(), AF_INET, &entbuf, buffer, sizeof(buffer), &ent, &herr);
75
76 #   else // ! __GLIBC__
77
78 #   ifdef _REENTRANT
79     static boost::mutex mutex;
80     boost::mutex::scoped_lock lock(mutex);
81 #   endif
82     struct hostent * ent (::gethostbyname(s.c_str()));
83     herr = h_errno;
84
85 #   endif // __GLIBC__
86
87     if (!ent)
88         throw UnknownHostnameException(s);
89     if (ent->h_addrtype != AF_INET)
90         throw UnknownHostnameException(s);
91
92     // We are only interested in the first address ...
93     return INet4Address::from_inaddr(
94         reinterpret_cast<in_addr*>(*(ent->h_addr_list))->s_addr);
95 }
96
97 prefix_ bool senf::INet4Address::local()
98     const
99 {
100     address_type l (address());
101     return
102         (l & 0xFF000000u) == 0x0A000000u ||
103         (l & 0xFFF00000u) == 0xAC100000u ||
104         (l & 0xFFFF0000u) == 0xA9FE0000u ||
105         (l & 0xFFFF0000u) == 0xC0A80000u;
106 }
107
108 prefix_ bool senf::INet4Address::loopback()
109     const
110 {
111     return (address() & 0xFF000000u) == 0x7F000000u;
112 }
113
114 prefix_ bool senf::INet4Address::multicast()
115     const
116 {
117     return (address() & 0xF0000000u) == 0xE0000000u;
118 }
119
120 prefix_ senf::INet4Address::address_type senf::INet4Address::address()
121     const
122 {
123     return ntohl(iref());
124 }
125
126 senf::INet4Address const senf::INet4Address::None;
127 senf::INet4Address const senf::INet4Address::Loopback (0x7F000001u);
128 senf::INet4Address const senf::INet4Address::Broadcast (0xFFFFFFFFu);
129
130 //-/////////////////////////////////////////////////////////////////////////////////////////////////
131 // senf::INet4Network
132
133 prefix_ senf::INet4Network::INet4Network(std::string const & s)
134 {
135     std::string::size_type i (s.find('/'));
136     if (i == std::string::npos)
137         throw AddressSyntaxException(s);
138     try {
139         prefix_len_ = prefix_len_checked(boost::lexical_cast<unsigned>(std::string(s,i+1)));
140     } catch (boost::bad_lexical_cast const &) {
141         throw AddressSyntaxException(s);
142     }
143     address_ = INet4Address(INet4Address::from_string(std::string(s, 0, i)).address() & mask());
144 }
145
146 //-/////////////////////////////////////////////////////////////////////////////////////////////////
147 // namespace members
148
149 prefix_ std::ostream & senf::operator<<(std::ostream & os, INet4Address const & addr)
150 {
151     ::in_addr ina;
152     char buffer[16];
153     ina.s_addr = addr.inaddr();
154     ::inet_ntop(AF_INET,&ina,buffer,16);
155     buffer[15] = 0;
156     os << buffer;
157     return os;
158 }
159
160 prefix_ std::istream & senf::operator>>(std::istream & is, INet4Address & addr)
161 {
162     std::string s;
163     if (!(is >> s))
164         return is;
165     try {
166         addr = INet4Address::from_string(s);
167     }
168     catch (AddressException &) {
169         is.setstate(std::ios::failbit);
170     }
171     return is;
172 }
173
174 prefix_ std::istream & senf::operator>>(std::istream & is, INet4Network & addr)
175 {
176     std::string s;
177     if (!(is >> s))
178         return is;
179     try {
180         addr = INet4Network(s);
181     }
182     catch (AddressException &) {
183         is.setstate(std::ios::failbit);
184     }
185     return is;
186 }
187
188 //-/////////////////////////////////////////////////////////////////////////////////////////////////
189 #undef prefix_
190 //#include "INet4Address.mpp"
191
192 \f
193 // Local Variables:
194 // mode: c++
195 // fill-column: 100
196 // comment-column: 40
197 // c-file-style: "senf"
198 // indent-tabs-mode: nil
199 // ispell-local-dictionary: "american"
200 // compile-command: "scons -u test"
201 // End: