]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_utilities/lib/ip++.h
Security-57337.20.44.tar.gz
[apple/security.git] / OSX / libsecurity_utilities / lib / ip++.h
1 /*
2 * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 //
26 // ip++ - C++ layer for IP socket and address management
27 //
28 // Key to comments:
29 // HBO = host byte order, NBO = network byte order
30 //
31 // Rules for byte ordering: C++ objects store addresses and ports in NBO.
32 // Struct in_addr arguments are in NBO. Integer type arguments are in HBO.
33 // Stick with the conversion methods and you win. Cast around and you lose.
34 //
35 // @@@ Which namespace should we be in?
36 //
37 #ifndef _H_IPPLUSPLUS
38 #define _H_IPPLUSPLUS
39
40 #include "unix++.h"
41 #include "timeflow.h"
42 #include <sys/types.h>
43 #include <sys/ioctl.h>
44 #include <sys/un.h>
45 #include <sys/socket.h>
46 #include <netinet/in.h>
47 #include <fcntl.h>
48 #include <cstdio>
49 #include <cstdarg>
50 #include <map>
51
52 using namespace UnixPlusPlus;
53
54
55 namespace Security {
56 namespace IPPlusPlus {
57
58 class Host;
59
60
61 //
62 // For now, ports are simply a short unsigned integer type, in HBO.
63 //
64 typedef UInt16 IPPort;
65
66
67 //
68 // An IP host address.
69 //
70 class IPAddress : public in_addr {
71 public:
72 IPAddress() { s_addr = htonl(INADDR_ANY); }
73 IPAddress(const struct in_addr &addr) { s_addr = addr.s_addr; }
74 explicit IPAddress(UInt32 addr) { s_addr = htonl(addr); }
75 IPAddress(const char *s); // ONLY dotted-quad form - use hosts.h for name resolution
76
77 operator UInt32 () const { return ntohl(s_addr); }
78 operator string () const; // "n.n.n.n" (no name resolution)
79
80 public:
81 bool operator == (const IPAddress &other) const { return s_addr == other.s_addr; }
82 bool operator != (const IPAddress &other) const { return s_addr != other.s_addr; }
83 bool operator < (const IPAddress &other) const { return s_addr < other.s_addr; }
84
85 operator bool () const { return s_addr != htonl(INADDR_ANY); }
86 bool operator ! () const { return s_addr == htonl(INADDR_ANY); }
87
88 public:
89 static const IPAddress &any;
90 };
91
92
93 //
94 // An IP "socket address", i.e. a combined host address and port.
95 //
96 class IPSockAddress : public sockaddr_in {
97 public:
98 IPSockAddress();
99 IPSockAddress(const struct sockaddr_in &sockaddr) { *(sockaddr_in *)this = sockaddr; }
100 IPSockAddress(const IPAddress &addr, IPPort port);
101
102 IPAddress address() const { return sin_addr; }
103 void address(IPAddress addr) { sin_addr = addr; }
104 IPPort port() const { return ntohs(sin_port); }
105 void port(IPPort p) { sin_port = htons(p); }
106
107 operator string () const; // "n.n.n.n:p" (no name resolution)
108
109 // automatically convert to struct sockaddr * for use in system calls
110 operator struct sockaddr * ()
111 { return reinterpret_cast<struct sockaddr *>(this); }
112 operator const struct sockaddr * () const
113 { return reinterpret_cast<const struct sockaddr *>(this); }
114
115 // conveniences
116 IPSockAddress defaults(const IPSockAddress &defaultAddr) const;
117 IPSockAddress defaults(const IPAddress &defaultAddr, IPPort defaultPort = 0) const;
118 IPSockAddress defaults(IPPort defaultPort) const;
119 };
120
121
122 //
123 // UNIX Domain Socket addresses, for those who care.
124 // An "UNAddress", such as it were, is simply a string.
125 //
126 class UNSockAddress : public sockaddr_un {
127 public:
128 UNSockAddress();
129 UNSockAddress(const char *path);
130 UNSockAddress(const std::string &path);
131
132 string path() const;
133 operator string () const { return path(); }
134
135 // automatically convert to struct sockaddr * for use in system calls
136 operator struct sockaddr * ()
137 { return reinterpret_cast<struct sockaddr *>(this); }
138 operator const struct sockaddr * () const
139 { return reinterpret_cast<const struct sockaddr *>(this); }
140 };
141
142
143 //
144 // An IP socket.
145 // This inherits all functionality of a FileDesc, so I/O is fun and easy.
146 // Socket is "passive"; it doesn't own any resources and does nothing on destruction.
147 // On the upside, you can assign Sockets freely.
148 // If you want self-managing sockets that clean up after themselves,
149 // use the subclasses below.
150 //
151 class Socket : public FileDesc {
152 public:
153 Socket() { }
154 explicit Socket(int domain, int type, int protocol = 0);
155 explicit Socket(int type);
156
157 Socket &operator = (int fd) { setFd(fd); return *this; }
158
159 // basic open (socket system call)
160 void open(int domain, int type, int protocol = 0);
161 void open(int type) { open(AF_INET, type, 0); }
162
163 // standard socket operations
164 void bind(const IPSockAddress &addr); // to this socket address
165 void bind(const IPAddress &addr = IPAddress::any, IPPort port = 0);
166 void bind(const UNSockAddress &addr); // to this UNIX domain socket
167 void listen(int backlog = 1);
168 void accept(Socket &s);
169 void accept(Socket &s, IPSockAddress &peer);
170 void accept(Socket &s, UNSockAddress &peer);
171 bool connect(const struct sockaddr *peer);
172 bool connect(const IPSockAddress &peer);
173 bool connect(const IPAddress &addr, IPPort port);
174 bool connect(const UNSockAddress &peer);
175 void connect(const Host &host, IPPort port); // any address of this host
176 void shutdown(int type);
177 enum { shutdownRead = 0, shutdownWrite = 1, shutdownBoth = 2 };
178
179 // get endpoint addresses
180 IPSockAddress localAddress() const;
181 IPSockAddress peerAddress() const;
182
183 // socket options
184 void setOption(const void *value, int length, int name, int level = SOL_SOCKET) const;
185 void getOption(void *value, socklen_t &length, int name, int level = SOL_SOCKET) const;
186
187 template <class T> void setOption(const T &value, int name, int level = SOL_SOCKET) const
188 { setOption(&value, sizeof(value), name, level); }
189
190 template <class T> T getOption(int name, int level = SOL_SOCKET) const
191 {
192 T value; socklen_t length = sizeof(value);
193 getOption(&value, length, name, level);
194 assert(length == sizeof(value));
195 return value;
196 }
197
198 // some specific useful options
199 int type() const { return getOption<int>(SO_TYPE); }
200 int error() const { return getOption<int>(SO_ERROR); }
201
202 public:
203 #if defined(SOMAXCONN)
204 static const int listenMaxQueue = SOMAXCONN;
205 #else
206 static const int listenMaxQueue = 5; // the traditional BSD UNIX value
207 #endif
208
209 protected:
210 void prepare(int fdFlags, int domain, int type, int protocol = 0);
211 };
212
213
214 //
215 // A TCPClientSocket is a self-connecting TCP socket that connects (actively) to a server.
216 // Since TCP, once established, is symmetric, it can also be used for the server side
217 // of a TCP pipe. You can think of it as the least complex embodiment of a TCP connection.
218 //
219 class TCPClientSocket : public Socket {
220 NOCOPY(TCPClientSocket)
221 public:
222 TCPClientSocket() { }
223 ~TCPClientSocket(); // closes connection
224
225 #if BUG_GCC
226 void open(int type, int protocol = 0) { Socket::open(type, protocol); }
227 #else
228 using Socket::open;
229 #endif
230
231 void open(const IPSockAddress &peer, int fdFlags = 0);
232 void open(const IPAddress &addr, IPPort port, int fdFlags = 0);
233 void open(const Host &host, IPPort port, int fdFlags = 0);
234
235 TCPClientSocket(const IPSockAddress &peer, int fdFlags = 0)
236 { open(peer, fdFlags); }
237 TCPClientSocket(const IPAddress &addr, IPPort port, int fdFlags = 0)
238 { open(addr, port, fdFlags); }
239 TCPClientSocket(const Host &host, IPPort port, int fdFlags = 0)
240 { open(host, port, fdFlags); }
241
242 protected: // for serverSocket/clientSocket footsy play
243 void setFd(int fd) { Socket::setFd(fd); }
244
245 private:
246 TCPClientSocket(int sockfd);
247 };
248
249
250 //
251 // A TCPServerSocket is a self-initializing listener socket for incoming TCP requests
252 // (usually to a server). Its function operator yields the next incoming connection request
253 // as a TCPClientSocket (see above). For one-shot receivers, the receive() method will
254 // create the client and close the listener atomically (which is sometimes faster).
255 //
256 class TCPServerSocket : public Socket {
257 NOCOPY(TCPServerSocket)
258 public:
259 TCPServerSocket() { }
260 ~TCPServerSocket(); // closes listener; existing connections unaffected
261
262 void open(const IPSockAddress &local, int depth = 1);
263 void open(IPPort port = 0, int depth = 1)
264 { open(IPSockAddress(IPAddress::any, port), depth); }
265
266 TCPServerSocket(const IPSockAddress &local, int depth = 1) { open(local, depth); }
267 TCPServerSocket(IPPort port, int depth = 1) { open(port, depth); }
268
269 void operator () (TCPClientSocket &newClient); // retrieve next connection
270 void receive(TCPClientSocket &client); // accept once, then close listener
271 };
272
273
274 } // end namespace IPPlusPlus
275 } // end namespace Security
276
277
278 #endif //_H_IPPLUSPLUS