]> git.saurik.com Git - apple/security.git/blame - cdsa/cdsa_utilities/ip++.h
Security-30.1.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / ip++.h
CommitLineData
bac41a7b
A
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
45using namespace UnixPlusPlus;
46
47
48namespace Security {
49namespace IPPlusPlus {
50
51class Host;
52
53
54//
55// For now, ports are simply a short unsigned integer type, in HBO.
56//
57typedef uint16 IPPort;
58
59
60//
61// An IP host address.
62//
63class IPAddress : public in_addr {
64public:
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
73public:
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
81public:
82 static const IPAddress &any;
83};
84
85
86//
87// An IP "socket address", i.e. a combined host address and port.
88//
89class IPSockAddress : public sockaddr_in {
90public:
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//
123class Socket : public FileDesc {
124public:
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
168public:
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
175protected:
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//
185class TCPClientSocket : public Socket {
186 NOCOPY(TCPClientSocket)
187public:
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
208protected: // for serverSocket/clientSocket footsy play
209 void setFd(int fd) { Socket::setFd(fd); }
210
211private:
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//
222class TCPServerSocket : public Socket {
223 NOCOPY(TCPServerSocket)
224public:
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