]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/ip++.h
Security-54.1.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/socket.h>
39 #include <netinet/in.h>
40 #include <fcntl.h>
41 #include <cstdio>
42 #include <cstdarg>
43 #include <map>
44
45 using namespace UnixPlusPlus;
46
47
48 namespace Security {
49 namespace IPPlusPlus {
50
51 class Host;
52
53
54 //
55 // For now, ports are simply a short unsigned integer type, in HBO.
56 //
57 typedef uint16 IPPort;
58
59
60 //
61 // An IP host address.
62 //
63 class IPAddress : public in_addr {
64 public:
65 IPAddress() { s_addr = htonl(INADDR_ANY); }
66 IPAddress(const struct in_addr &addr) { s_addr = addr.s_addr; }
67 explicit IPAddress(uint32 addr) { s_addr = htonl(addr); }
68 IPAddress(const char *s); // ONLY dotted-quad form - use hosts.h for name resolution
69
70 operator uint32 () const { return ntohl(s_addr); }
71 operator string () const; // "n.n.n.n" (no name resolution)
72
73 public:
74 bool operator == (const IPAddress &other) const { return s_addr == other.s_addr; }
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
78 operator bool () const { return s_addr != htonl(INADDR_ANY); }
79 bool operator ! () const { return s_addr == htonl(INADDR_ANY); }
80
81 public:
82 static const IPAddress &any;
83 };
84
85
86 //
87 // An IP "socket address", i.e. a combined host address and port.
88 //
89 class IPSockAddress : public sockaddr_in {
90 public:
91 IPSockAddress();
92 IPSockAddress(const struct sockaddr_in &sockaddr) { *(sockaddr_in *)this = sockaddr; }
93 IPSockAddress(const IPAddress &addr, IPPort port);
94
95 IPAddress address() const { return sin_addr; }
96 void address(IPAddress addr) { sin_addr = addr; }
97 IPPort port() const { return ntohs(sin_port); }
98 void port(IPPort p) { sin_port = htons(p); }
99
100 operator string () const; // "n.n.n.n:p" (no name resolution)
101
102 // automatically convert to struct sockaddr * for use in system calls
103 operator struct sockaddr * ()
104 { return reinterpret_cast<struct sockaddr *>(this); }
105 operator const struct sockaddr * () const
106 { return reinterpret_cast<const struct sockaddr *>(this); }
107
108 // conveniences
109 IPSockAddress defaults(const IPSockAddress &defaultAddr) const;
110 IPSockAddress defaults(const IPAddress &defaultAddr, IPPort defaultPort = 0) const;
111 IPSockAddress defaults(IPPort defaultPort) const;
112 };
113
114
115 //
116 // An IP socket.
117 // This inherits all functionality of a FileDesc, so I/O is fun and easy.
118 // Socket is "passive"; it doesn't own any resources and does nothing on destruction.
119 // On the upside, you can assign Sockets freely.
120 // If you want self-managing sockets that clean up after themselves,
121 // use the subclasses below.
122 //
123 class Socket : public FileDesc {
124 public:
125 Socket() { }
126 explicit Socket(int type, int protocol = 0);
127
128 Socket &operator = (int fd) { setFd(fd); return *this; }
129
130 // basic open (socket system call)
131 void open(int type, int protocol = 0);
132
133 // standard socket operations
134 void bind(const IPSockAddress &addr); // to this socket address
135 void bind(const IPAddress &addr = IPAddress::any, IPPort port = 0);
136 void listen(int backlog = 1);
137 void accept(Socket &s);
138 void accept(Socket &s, IPSockAddress &peer);
139 bool connect(const IPSockAddress &peer);
140 bool connect(const IPAddress &addr, IPPort port);
141 void connect(const Host &host, IPPort port); // any address of this host
142 void shutdown(int type);
143 enum { shutdownRead = 0, shutdownWrite = 1, shutdownBoth = 2 };
144
145 // get endpoint addresses
146 IPSockAddress localAddress() const;
147 IPSockAddress peerAddress() const;
148
149 // socket options
150 void setOption(const void *value, int length, int name, int level = SOL_SOCKET) const;
151 void getOption(void *value, int &length, int name, int level = SOL_SOCKET) const;
152
153 template <class T> void setOption(const T &value, int name, int level = SOL_SOCKET) const
154 { setOption(&value, sizeof(value), name, level); }
155
156 template <class T> T getOption(int name, int level = SOL_SOCKET) const
157 {
158 T value; int length = sizeof(value);
159 getOption(&value, length, name, level);
160 assert(length == sizeof(value));
161 return value;
162 }
163
164 // some specific useful options
165 int type() const { return getOption<int>(SO_TYPE); }
166 int error() const { return getOption<int>(SO_ERROR); }
167
168 public:
169 #if defined(SOMAXCONN)
170 static const int listenMaxQueue = SOMAXCONN;
171 #else
172 static const int listenMaxQueue = 5; // the traditional BSD UNIX value
173 #endif
174
175 protected:
176 void prepare(int fdFlags, int type, int protocol = 0);
177 };
178
179
180 //
181 // A TCPClientSocket is a self-connecting TCP socket that connects (actively) to a server.
182 // Since TCP, once established, is symmetric, it can also be used for the server side
183 // of a TCP pipe. You can think of it as the least complex embodiment of a TCP connection.
184 //
185 class TCPClientSocket : public Socket {
186 NOCOPY(TCPClientSocket)
187 public:
188 TCPClientSocket() { }
189 ~TCPClientSocket(); // closes connection
190
191 #if BUG_GCC
192 void open(int type, int protocol = 0) { Socket::open(type, protocol); }
193 #else
194 using Socket::open;
195 #endif
196
197 void open(const IPSockAddress &peer, int fdFlags = 0);
198 void open(const IPAddress &addr, IPPort port, int fdFlags = 0);
199 void open(const Host &host, IPPort port, int fdFlags = 0);
200
201 TCPClientSocket(const IPSockAddress &peer, int fdFlags = 0)
202 { open(peer, fdFlags); }
203 TCPClientSocket(const IPAddress &addr, IPPort port, int fdFlags = 0)
204 { open(addr, port, fdFlags); }
205 TCPClientSocket(const Host &host, IPPort port, int fdFlags = 0)
206 { open(host, port, fdFlags); }
207
208 protected: // for serverSocket/clientSocket footsy play
209 void setFd(int fd) { Socket::setFd(fd); }
210
211 private:
212 TCPClientSocket(int sockfd);
213 };
214
215
216 //
217 // A TCPServerSocket is a self-initializing listener socket for incoming TCP requests
218 // (usually to a server). Its function operator yields the next incoming connection request
219 // as a TCPClientSocket (see above). For one-shot receivers, the receive() method will
220 // create the client and close the listener atomically (which is sometimes faster).
221 //
222 class TCPServerSocket : public Socket {
223 NOCOPY(TCPServerSocket)
224 public:
225 TCPServerSocket() { }
226 ~TCPServerSocket(); // closes listener; existing connections unaffected
227
228 void open(const IPSockAddress &local, int depth = 1);
229 void open(IPPort port = 0, int depth = 1)
230 { open(IPSockAddress(IPAddress::any, port), depth); }
231
232 TCPServerSocket(const IPSockAddress &local, int depth = 1) { open(local, depth); }
233 TCPServerSocket(IPPort port, int depth = 1) { open(port, depth); }
234
235 void operator () (TCPClientSocket &newClient); // retrieve next connection
236 void receive(TCPClientSocket &client); // accept once, then close listener
237 };
238
239
240 } // end namespace IPPlusPlus
241 } // end namespace Security
242
243
244 #endif //_H_IPPLUSPLUS