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