]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_utilities/lib/ip++.h
Security-57031.1.35.tar.gz
[apple/security.git] / Security / libsecurity_utilities / lib / ip++.h
diff --git a/Security/libsecurity_utilities/lib/ip++.h b/Security/libsecurity_utilities/lib/ip++.h
new file mode 100644 (file)
index 0000000..306c4ab
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2000-2001,2003-2004,2011,2014 Apple Inc. All Rights Reserved.
+ * 
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+
+//
+// ip++ - C++ layer for IP socket and address management
+//
+// Key to comments:
+//     HBO = host byte order, NBO = network byte order
+//
+// Rules for byte ordering: C++ objects store addresses and ports in NBO.
+// Struct in_addr arguments are in NBO. Integer type arguments are in HBO.
+// Stick with the conversion methods and you win. Cast around and you lose.
+//
+// @@@ Which namespace should we be in?
+//
+#ifndef _H_IPPLUSPLUS
+#define _H_IPPLUSPLUS
+
+#include "unix++.h"
+#include "timeflow.h"
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/un.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <fcntl.h>
+#include <cstdio>
+#include <cstdarg>
+#include <map>
+
+using namespace UnixPlusPlus;
+
+
+namespace Security {
+namespace IPPlusPlus {
+
+class Host;
+
+
+//
+// For now, ports are simply a short unsigned integer type, in HBO.
+//
+typedef UInt16 IPPort;
+
+
+//
+// An IP host address.
+//
+class IPAddress : public in_addr {
+public:
+    IPAddress()                                                { s_addr = htonl(INADDR_ANY); }
+    IPAddress(const struct in_addr &addr) { s_addr = addr.s_addr; }
+    explicit IPAddress(UInt32 addr)    { s_addr = htonl(addr); }
+    IPAddress(const char *s);          // ONLY dotted-quad form - use hosts.h for name resolution
+    
+    operator UInt32 () const           { return ntohl(s_addr); }
+    operator string () const;          // "n.n.n.n" (no name resolution)
+    
+public:
+    bool operator == (const IPAddress &other) const    { return s_addr == other.s_addr; }
+    bool operator != (const IPAddress &other) const    { return s_addr != other.s_addr; }
+    bool operator < (const IPAddress &other) const     { return s_addr < other.s_addr; }
+    
+    operator bool () const                     { return s_addr != htonl(INADDR_ANY); }
+    bool operator ! () const           { return s_addr == htonl(INADDR_ANY); }
+    
+public:
+    static const IPAddress &any;
+};
+
+
+//
+// An IP "socket address", i.e. a combined host address and port.
+//
+class IPSockAddress : public sockaddr_in {
+public:
+    IPSockAddress();
+    IPSockAddress(const struct sockaddr_in &sockaddr)  { *(sockaddr_in *)this = sockaddr; }
+    IPSockAddress(const IPAddress &addr, IPPort port);
+    
+    IPAddress address() const          { return sin_addr; }
+    void address(IPAddress addr)       { sin_addr = addr; }
+    IPPort port() const                                { return ntohs(sin_port); }
+    void port(IPPort p)                                { sin_port = htons(p); }
+    
+    operator string () const;          // "n.n.n.n:p" (no name resolution)
+
+    // automatically convert to struct sockaddr * for use in system calls
+    operator struct sockaddr * ()
+    { return reinterpret_cast<struct sockaddr *>(this); }
+    operator const struct sockaddr * () const
+    { return reinterpret_cast<const struct sockaddr *>(this); }
+    
+    // conveniences
+    IPSockAddress defaults(const IPSockAddress &defaultAddr) const;
+    IPSockAddress defaults(const IPAddress &defaultAddr, IPPort defaultPort = 0) const;
+    IPSockAddress defaults(IPPort defaultPort) const;
+};
+
+
+//
+// UNIX Domain Socket addresses, for those who care.
+// An "UNAddress", such as it were, is simply a string.
+//
+class UNSockAddress : public sockaddr_un {
+public:
+       UNSockAddress();
+       UNSockAddress(const char *path);
+       UNSockAddress(const std::string &path);
+       
+       string path() const;
+       operator string () const                { return path(); }
+
+    // automatically convert to struct sockaddr * for use in system calls
+    operator struct sockaddr * ()
+    { return reinterpret_cast<struct sockaddr *>(this); }
+    operator const struct sockaddr * () const
+    { return reinterpret_cast<const struct sockaddr *>(this); }
+};
+
+
+//
+// An IP socket.
+// This inherits all functionality of a FileDesc, so I/O is fun and easy.
+// Socket is "passive"; it doesn't own any resources and does nothing on destruction.
+// On the upside, you can assign Sockets freely.
+// If you want self-managing sockets that clean up after themselves,
+// use the subclasses below.
+//
+class Socket : public FileDesc {
+public:
+    Socket() { }
+       explicit Socket(int domain, int type, int protocol = 0);
+    explicit Socket(int type);
+    
+    Socket &operator = (int fd)                                { setFd(fd); return *this; }
+    
+    // basic open (socket system call)
+       void open(int domain, int type, int protocol = 0);
+       void open(int type)                                             { open(AF_INET, type, 0); }
+    
+    // standard socket operations
+    void bind(const IPSockAddress &addr);      // to this socket address
+    void bind(const IPAddress &addr = IPAddress::any, IPPort port = 0);
+       void bind(const UNSockAddress &addr);   // to this UNIX domain socket
+    void listen(int backlog = 1);
+    void accept(Socket &s);
+    void accept(Socket &s, IPSockAddress &peer);
+    void accept(Socket &s, UNSockAddress &peer);
+       bool connect(const struct sockaddr *peer);
+    bool connect(const IPSockAddress &peer);
+    bool connect(const IPAddress &addr, IPPort port);
+       bool connect(const UNSockAddress &peer);
+    void connect(const Host &host, IPPort port);       // any address of this host
+    void shutdown(int type);
+    enum { shutdownRead = 0, shutdownWrite = 1, shutdownBoth = 2 };
+    
+    // get endpoint addresses
+    IPSockAddress localAddress() const;
+    IPSockAddress peerAddress() const;
+    
+    // socket options
+    void setOption(const void *value, int length, int name, int level = SOL_SOCKET) const;
+    void getOption(void *value, socklen_t &length, int name, int level = SOL_SOCKET) const;
+    
+    template <class T> void setOption(const T &value, int name, int level = SOL_SOCKET) const
+    { setOption(&value, sizeof(value), name, level); }
+    
+    template <class T> T getOption(int name, int level = SOL_SOCKET) const
+    {
+        T value; socklen_t length = sizeof(value);
+        getOption(&value, length, name, level);
+        assert(length == sizeof(value));
+        return value;
+    }
+    
+    // some specific useful options
+    int type() const           { return getOption<int>(SO_TYPE); }
+    int error() const          { return getOption<int>(SO_ERROR); }
+    
+public:
+#if defined(SOMAXCONN)
+    static const int listenMaxQueue = SOMAXCONN;
+#else
+    static const int listenMaxQueue = 5;       // the traditional BSD UNIX value
+#endif
+
+protected:
+    void prepare(int fdFlags, int domain, int type, int protocol = 0);
+};
+
+
+//
+// A TCPClientSocket is a self-connecting TCP socket that connects (actively) to a server.
+// Since TCP, once established, is symmetric, it can also be used for the server side
+// of a TCP pipe. You can think of it as the least complex embodiment of a TCP connection.
+//
+class TCPClientSocket : public Socket {
+    NOCOPY(TCPClientSocket)
+public:
+    TCPClientSocket() { }
+    ~TCPClientSocket();        // closes connection
+    
+#if BUG_GCC
+    void open(int type, int protocol = 0)      { Socket::open(type, protocol); }
+#else
+    using Socket::open;
+#endif
+    
+    void open(const IPSockAddress &peer, int fdFlags = 0);
+    void open(const IPAddress &addr, IPPort port, int fdFlags = 0);
+    void open(const Host &host, IPPort port, int fdFlags = 0);
+
+    TCPClientSocket(const IPSockAddress &peer, int fdFlags = 0)
+    { open(peer, fdFlags); }
+    TCPClientSocket(const IPAddress &addr, IPPort port, int fdFlags = 0)
+    { open(addr, port, fdFlags); }
+    TCPClientSocket(const Host &host, IPPort port, int fdFlags = 0)
+    { open(host, port, fdFlags); }
+    
+protected:     // for serverSocket/clientSocket footsy play
+    void setFd(int fd)                 { Socket::setFd(fd); }
+    
+private:
+    TCPClientSocket(int sockfd);
+};
+
+
+//
+// A TCPServerSocket is a self-initializing listener socket for incoming TCP requests
+// (usually to a server). Its function operator yields the next incoming connection request
+// as a TCPClientSocket (see above). For one-shot receivers, the receive() method will
+// create the client and close the listener atomically (which is sometimes faster).
+//
+class TCPServerSocket : public Socket {
+    NOCOPY(TCPServerSocket)
+public:
+    TCPServerSocket() { }
+    ~TCPServerSocket();        // closes listener; existing connections unaffected
+    
+    void open(const IPSockAddress &local, int depth = 1);
+    void open(IPPort port = 0, int depth = 1)
+    { open(IPSockAddress(IPAddress::any, port), depth); }
+
+    TCPServerSocket(const IPSockAddress &local, int depth = 1) { open(local, depth); }
+    TCPServerSocket(IPPort port, int depth = 1)                                        { open(port, depth); }
+    
+    void operator () (TCPClientSocket &newClient);     // retrieve next connection
+    void receive(TCPClientSocket &client);                     // accept once, then close listener
+};
+
+
+}      // end namespace IPPlusPlus
+}      // end namespace Security
+
+
+#endif //_H_IPPLUSPLUS