Certificate API

This commit is contained in:
Adam Ierymenko 2020-07-02 22:22:31 -07:00
parent 727aa8e71f
commit 899f0c9749
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
7 changed files with 254 additions and 35 deletions

View file

@ -81,8 +81,8 @@ Commands:
verify <identity> <file> <sig> Verify a signature verify <identity> <file> <sig> Verify a signature
certificate <command> [args] - Certificate commands certificate <command> [args] - Certificate commands
newid Create a new unique subject ID newid Create a new unique subject ID
newcsr <settings> Create a new CSR (signing request) newcsr <settings path> Create a new CSR (signing request)
sign <crl path> <identity path> Sign a CRL and create a certificate sign <csr path> <identity path> Sign a CSR to create a certificate
verify <certificate> Verify a certificate verify <certificate> Verify a certificate
show List certificate for current node show List certificate for current node
import <certificate> [<trust>] Import certificate into this node import <certificate> [<trust>] Import certificate into this node

View file

@ -251,16 +251,16 @@ Vector< uint8_t > Certificate::encode(const bool omitSignature) const
return enc; return enc;
} }
bool Certificate::decode(const Vector< uint8_t > &data) bool Certificate::decode(const void *const data, const unsigned int len)
{ {
char tmp[256], tmp2[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1]; char tmp[256], tmp2[ZT_CERTIFICATE_MAX_STRING_LENGTH + 1];
m_clear();
Dictionary d; Dictionary d;
if (!d.decode(data.data(), (unsigned int)data.size())) if (!d.decode(data, len))
return false; return false;
m_clear();
this->flags = d.getUI("f"); this->flags = d.getUI("f");
this->timestamp = (int64_t)d.getUI("t"); this->timestamp = (int64_t)d.getUI("t");
this->validity[0] = (int64_t)d.getUI("v#0"); this->validity[0] = (int64_t)d.getUI("v#0");
@ -384,6 +384,15 @@ bool Certificate::decode(const Vector< uint8_t > &data)
return true; return true;
} }
Vector< uint8_t > Certificate::encodeCSR()
{
Vector< uint8_t > enc;
Dictionary d;
m_encodeSubject(this->subject, d, false);
d.encode(enc);
return enc;
}
bool Certificate::sign(const Identity &issuer) bool Certificate::sign(const Identity &issuer)
{ {
Vector< uint8_t > enc(encode(true)); Vector< uint8_t > enc(encode(true));
@ -417,7 +426,7 @@ ZT_CertificateError Certificate::verify() const
if ( if (
(this->subject.uniqueIdProofSignatureSize != ZT_ECC384_SIGNATURE_SIZE) || (this->subject.uniqueIdProofSignatureSize != ZT_ECC384_SIGNATURE_SIZE) ||
(this->subject.uniqueIdSize != (ZT_ECC384_PUBLIC_KEY_SIZE + 1)) || (this->subject.uniqueIdSize != (ZT_ECC384_PUBLIC_KEY_SIZE + 1)) ||
(this->subject.uniqueId[0] != ZT_CERTIFICATE_UNIQUE_ID_PUBLIC_KEY_TYPE_NIST_P_384)) (this->subject.uniqueId[0] != ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384))
return ZT_CERTIFICATE_ERROR_INVALID_UNIQUE_ID_PROOF; return ZT_CERTIFICATE_ERROR_INVALID_UNIQUE_ID_PROOF;
Dictionary tmp; Dictionary tmp;
m_encodeSubject(this->subject, tmp, true); m_encodeSubject(this->subject, tmp, true);
@ -462,11 +471,11 @@ ZT_CertificateError Certificate::verify() const
return ZT_CERTIFICATE_ERROR_NONE; return ZT_CERTIFICATE_ERROR_NONE;
} }
bool Certificate::setSubjectUniqueId(const uint8_t uniqueId[ZT_CERTIFICATE_UNIQUE_ID_SIZE_TYPE_NIST_P_384], const uint8_t uniqueIdPrivate[ZT_CERTIFICATE_UNIQUE_ID_PRIVATE_KEY_SIZE_TYPE_NIST_P_384]) bool Certificate::setSubjectUniqueId(const uint8_t uniqueId[ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE], const uint8_t uniqueIdPrivate[ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE])
{ {
m_subjectUniqueId.assign(uniqueId, uniqueId + ZT_CERTIFICATE_UNIQUE_ID_SIZE_TYPE_NIST_P_384); m_subjectUniqueId.assign(uniqueId, uniqueId + ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE);
this->subject.uniqueId = m_subjectUniqueId.data(); this->subject.uniqueId = m_subjectUniqueId.data();
this->subject.uniqueIdSize = ZT_CERTIFICATE_UNIQUE_ID_SIZE_TYPE_NIST_P_384; this->subject.uniqueIdSize = ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE;
Dictionary d; Dictionary d;
m_encodeSubject(this->subject, d, true); m_encodeSubject(this->subject, d, true);
@ -567,3 +576,103 @@ void Certificate::m_encodeSubject(const ZT_Certificate_Subject &s, Dictionary &d
} }
} // namespace ZeroTier } // namespace ZeroTier
extern "C" {
int ZT_Certificate_newSubjectUniqueId(
enum ZT_CertificateUniqueIdType type,
void *uniqueId,
int *uniqueIdSize,
void *uniqueIdPrivate,
int *uniqueIdPrivateSize)
{
switch(type) {
case ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384:
if ((*uniqueIdSize < ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE) || (*uniqueIdPrivateSize < ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE))
return ZT_RESULT_ERROR_BAD_PARAMETER;
*uniqueIdSize = ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE;
*uniqueIdPrivateSize = ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE;
ZeroTier::Certificate::createSubjectUniqueId(reinterpret_cast<uint8_t *>(uniqueId), reinterpret_cast<uint8_t *>(uniqueIdPrivate));
return ZT_RESULT_OK;
}
return ZT_RESULT_ERROR_BAD_PARAMETER;
}
int ZT_Certificate_newCSR(
const ZT_Certificate_Subject *subject,
const void *uniqueId,
int uniqueIdSize,
const void *uniqueIdPrivate,
int uniqueIdPrivateSize,
void *csr,
int *csrSize)
{
ZeroTier::Certificate c;
ZeroTier::Utils::copy< sizeof(ZT_Certificate_Subject) >(&(c.subject), subject);
if ((uniqueId) && (uniqueIdSize > 0) && (uniqueIdPrivate) && (uniqueIdPrivateSize > 0)) {
if ((reinterpret_cast<const uint8_t *>(uniqueId)[0] != ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384) || (uniqueIdSize != ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE) || (uniqueIdPrivateSize != ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE))
return ZT_RESULT_ERROR_BAD_PARAMETER;
if (!c.setSubjectUniqueId(reinterpret_cast<const uint8_t *>(uniqueId), reinterpret_cast<const uint8_t *>(uniqueIdPrivate)))
return ZT_RESULT_ERROR_INVALID_CREDENTIAL;
}
ZeroTier::Vector< uint8_t > csrV(c.encodeCSR());
if ((int)csrV.size() > *csrSize)
return ZT_RESULT_ERROR_BAD_PARAMETER;
ZeroTier::Utils::copy(csr, csrV.data(), (unsigned int)csrV.size());
*csrSize = (int)csrV.size();
return ZT_RESULT_OK;
}
int ZT_Certificate_sign(
const ZT_Certificate *cert,
const ZT_Identity *signer,
void *signedCert,
int *signedCertSize)
{
ZeroTier::Certificate c(*cert);
if (!c.sign(*reinterpret_cast<const ZeroTier::Identity *>(signer)))
return ZT_RESULT_ERROR_BAD_PARAMETER;
ZeroTier::Vector< uint8_t > enc(c.encode());
if ((int)enc.size() > *signedCertSize)
return ZT_RESULT_ERROR_BAD_PARAMETER;
ZeroTier::Utils::copy(signedCert, enc.data(), (unsigned int)enc.size());
*signedCertSize = (int)enc.size();
return ZT_RESULT_OK;
}
enum ZT_CertificateError ZT_Certificate_decode(
ZT_Certificate **decodedCert,
const void *cert,
int certSize,
int verify)
{
try {
if (!decodedCert)
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
*decodedCert = nullptr;
ZeroTier::Certificate *const c = new ZeroTier::Certificate();
if (!c->decode(cert, certSize)) {
delete c;
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
}
if (verify) {
ZT_CertificateError err = c->verify();
if (err != ZT_CERTIFICATE_ERROR_NONE) {
delete c;
return err;
}
}
*decodedCert = c;
return ZT_CERTIFICATE_ERROR_NONE;
} catch ( ... ) {
return ZT_CERTIFICATE_ERROR_INVALID_FORMAT;
}
}
ZT_SDK_API void ZT_Certificate_delete(ZT_Certificate *cert)
{
if (cert)
delete reinterpret_cast<ZeroTier::Certificate *>(cert);
}
}

View file

@ -129,9 +129,17 @@ public:
* Decode this certificate from marshaled bytes. * Decode this certificate from marshaled bytes.
* *
* @param data Marshalled certificate * @param data Marshalled certificate
* @param len Length of marshalled certificate
* @return True if input is valid and was unmarshalled (signature is NOT checked) * @return True if input is valid and was unmarshalled (signature is NOT checked)
*/ */
bool decode(const Vector< uint8_t > &data); bool decode(const void *data, unsigned int len);
/**
* Encode only the subject portion of this certificate as a CSR
*
* @return Encoded CSR
*/
Vector< uint8_t > encodeCSR();
/** /**
* Sign this certificate (and also fill in serialNo). * Sign this certificate (and also fill in serialNo).
@ -160,7 +168,7 @@ public:
* @param uniqueIdPrivate Private key associated with unique ID to prove ownership of it * @param uniqueIdPrivate Private key associated with unique ID to prove ownership of it
* @return True if successful * @return True if successful
*/ */
bool setSubjectUniqueId(const uint8_t uniqueId[ZT_CERTIFICATE_UNIQUE_ID_SIZE_TYPE_NIST_P_384], const uint8_t uniqueIdPrivate[ZT_CERTIFICATE_UNIQUE_ID_PRIVATE_KEY_SIZE_TYPE_NIST_P_384]); bool setSubjectUniqueId(const uint8_t uniqueId[ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE], const uint8_t uniqueIdPrivate[ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE]);
/** /**
* Create a subject unique ID and corresponding private key required for use * Create a subject unique ID and corresponding private key required for use
@ -168,9 +176,9 @@ public:
* @param uniqueId Buffer to receive unique ID * @param uniqueId Buffer to receive unique ID
* @param uniqueIdPrivate Buffer to receive private key * @param uniqueIdPrivate Buffer to receive private key
*/ */
static ZT_INLINE void createSubjectUniqueId(uint8_t uniqueId[ZT_CERTIFICATE_UNIQUE_ID_SIZE_TYPE_NIST_P_384], uint8_t uniqueIdPrivate[ZT_CERTIFICATE_UNIQUE_ID_PRIVATE_KEY_SIZE_TYPE_NIST_P_384]) static ZT_INLINE void createSubjectUniqueId(uint8_t uniqueId[ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE], uint8_t uniqueIdPrivate[ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE])
{ {
uniqueId[0] = ZT_CERTIFICATE_UNIQUE_ID_PUBLIC_KEY_TYPE_NIST_P_384; uniqueId[0] = ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384;
ECC384GenerateKey(uniqueId + 1, uniqueIdPrivate); ECC384GenerateKey(uniqueId + 1, uniqueIdPrivate);
} }

View file

@ -1107,9 +1107,9 @@ extern "C" const char *ZTT_crypto()
ZT_T_PRINTF("OK" ZT_EOL_S); ZT_T_PRINTF("OK" ZT_EOL_S);
ZT_T_PRINTF(" Create subject unique ID... "); ZT_T_PRINTF(" Create subject unique ID... ");
uint8_t uniqueId[ZT_CERTIFICATE_UNIQUE_ID_SIZE_TYPE_NIST_P_384], uniqueIdPrivate[ZT_CERTIFICATE_UNIQUE_ID_PRIVATE_KEY_SIZE_TYPE_NIST_P_384]; uint8_t uniqueId[ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE], uniqueIdPrivate[ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE];
Certificate::createSubjectUniqueId(uniqueId, uniqueIdPrivate); Certificate::createSubjectUniqueId(uniqueId, uniqueIdPrivate);
Utils::b32e(uniqueId, ZT_CERTIFICATE_UNIQUE_ID_SIZE_TYPE_NIST_P_384, tmp, sizeof(tmp)); Utils::b32e(uniqueId, ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE, tmp, sizeof(tmp));
ZT_T_PRINTF("OK %s" ZT_EOL_S, tmp); ZT_T_PRINTF("OK %s" ZT_EOL_S, tmp);
ZT_T_PRINTF(" Create and sign certificate... "); ZT_T_PRINTF(" Create and sign certificate... ");
@ -1148,7 +1148,7 @@ extern "C" const char *ZTT_crypto()
ZT_T_PRINTF(" Test certificate decode from marshaled format... "); ZT_T_PRINTF(" Test certificate decode from marshaled format... ");
SharedPtr<Certificate> cert2(new Certificate()); SharedPtr<Certificate> cert2(new Certificate());
if (!cert2->decode(enc)) { if (!cert2->decode(enc.data(), (unsigned int)enc.size())) {
ZT_T_PRINTF("FAILED (decode)" ZT_EOL_S); ZT_T_PRINTF("FAILED (decode)" ZT_EOL_S);
return "Certificate decode"; return "Certificate decode";
} }

View file

@ -34,7 +34,8 @@ Topology::Topology(const RuntimeEnvironment *renv, void *tPtr, const int64_t now
if (serialNo.size() == ZT_SHA384_DIGEST_SIZE) { if (serialNo.size() == ZT_SHA384_DIGEST_SIZE) {
Utils::copy< 48 >(id, serialNo.data()); Utils::copy< 48 >(id, serialNo.data());
Certificate cert; Certificate cert;
if (cert.decode(RR->node->stateObjectGet(tPtr, ZT_STATE_OBJECT_CERT, id))) Vector< uint8_t > enc(RR->node->stateObjectGet(tPtr, ZT_STATE_OBJECT_CERT, id));
if (cert.decode(enc.data(), (unsigned int)enc.size()))
addCertificate(tPtr, cert, now, (unsigned int)d.getUI(Dictionary::arraySubscript(tmp, "c$.lt", idx)), false, false, false); addCertificate(tPtr, cert, now, (unsigned int)d.getUI(Dictionary::arraySubscript(tmp, "c$.lt", idx)), false, false, false);
} }
} }

View file

@ -38,7 +38,7 @@ extern "C" {
/* This symbol may be defined to anything we need to put in front of API function prototypes. */ /* This symbol may be defined to anything we need to put in front of API function prototypes. */
#ifndef ZT_SDK_API #ifndef ZT_SDK_API
#define ZT_SDK_API #define ZT_SDK_API extern
#endif #endif
/* ---------------------------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------------------------- */
@ -308,20 +308,26 @@ typedef struct
*/ */
#define ZT_CERTIFICATE_LOCAL_TRUST_FLAG_ZEROTIER_ROOT_SET 0x0002U #define ZT_CERTIFICATE_LOCAL_TRUST_FLAG_ZEROTIER_ROOT_SET 0x0002U
/**
* Public key type for NIST P-384 public keys used as subject unique IDs.
*/
#define ZT_CERTIFICATE_UNIQUE_ID_PUBLIC_KEY_TYPE_NIST_P_384 1
/** /**
* Size of a unique ID of the given key type (with type prefix byte) * Size of a unique ID of the given key type (with type prefix byte)
*/ */
#define ZT_CERTIFICATE_UNIQUE_ID_SIZE_TYPE_NIST_P_384 50 #define ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE 50
/** /**
* Size of the private key corresponding to a unique ID of the given type. * Size of the private key corresponding to a unique ID of the given type.
*/ */
#define ZT_CERTIFICATE_UNIQUE_ID_PRIVATE_KEY_SIZE_TYPE_NIST_P_384 48 #define ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE 48
/**
* Unique ID types supported for certificate subject unique IDs
*/
enum ZT_CertificateUniqueIdType
{
/**
* Public key type for NIST P-384 public keys used as subject unique IDs.
*/
ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384 = 1
};
/** /**
* Errors returned by functions that verify or handle certificates. * Errors returned by functions that verify or handle certificates.
@ -2620,7 +2626,10 @@ ZT_SDK_API ZT_Locator *ZT_Locator_fromString(const char *str);
* @param bufSize Size of buffer in bytes (needs to be at least 2048 bytes in size) * @param bufSize Size of buffer in bytes (needs to be at least 2048 bytes in size)
* @return Number of bytes stored to buf or -1 on error such as buffer too small * @return Number of bytes stored to buf or -1 on error such as buffer too small
*/ */
ZT_SDK_API int ZT_Locator_marshal(const ZT_Locator *loc,void *buf,unsigned int bufSize); ZT_SDK_API int ZT_Locator_marshal(
const ZT_Locator *loc,
void *buf,
unsigned int bufSize);
/** /**
* Get this locator in string format * Get this locator in string format
@ -2669,7 +2678,9 @@ ZT_SDK_API unsigned int ZT_Locator_endpointCount(const ZT_Locator *loc);
* @param ep Endpoint number from 0 to 1 - endpointCount() * @param ep Endpoint number from 0 to 1 - endpointCount()
* @return Endpoint or NULL if out of bounds * @return Endpoint or NULL if out of bounds
*/ */
ZT_SDK_API const ZT_Endpoint *ZT_Locator_endpoint(const ZT_Locator *loc,const unsigned int ep); ZT_SDK_API const ZT_Endpoint *ZT_Locator_endpoint(
const ZT_Locator *loc,
const unsigned int ep);
/** /**
* Verify this locator's signature * Verify this locator's signature
@ -2677,7 +2688,9 @@ ZT_SDK_API const ZT_Endpoint *ZT_Locator_endpoint(const ZT_Locator *loc,const un
* @param signer Signing identity * @param signer Signing identity
* @return Non-zero if locator is valid * @return Non-zero if locator is valid
*/ */
ZT_SDK_API int ZT_Locator_verify(const ZT_Locator *loc,const ZT_Identity *signer); ZT_SDK_API int ZT_Locator_verify(
const ZT_Locator *loc,
const ZT_Identity *signer);
/** /**
* Delete a locator * Delete a locator
@ -2704,6 +2717,97 @@ ZT_SDK_API void ZT_version(
/* ---------------------------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------------------------- */
/**
* Create a new certificate subject unique ID and private key
*
* A unique ID is really a public/private key pair.
*
* @param type Unique ID type (key pair algorithm)
* @param uniqueId Unique ID buffer
* @param uniqueIdSize Value/result: size of buffer
* @param uniqueIdPrivate Unique ID private key buffer
* @param uniqueIdPrivateSize Value/result: size of buffer
* @return OK (0) or error
*/
ZT_SDK_API int ZT_Certificate_newSubjectUniqueId(
enum ZT_CertificateUniqueIdType type,
void *uniqueId,
int *uniqueIdSize,
void *uniqueIdPrivate,
int *uniqueIdPrivateSize);
/**
* Create a new certificate signing request (CSR)
*
* A CSR is effectively just an encoded certificate subject.
* If both uniqueId and uniqueIdPrivate are specified, the subject
* will be signed with a unique ID. Otherwise these fields are not
* set. If a unique ID and unique ID signature are present in the
* supplied subject, these will be ignored.
*
* @param subject Subject filled in with fields for CSR
* @param uniqueId Unique ID or NULL if none
* @param uniqueIdSize Size of unique ID
* @param uniqueIdPrivate Unique ID private key or NULL if none
* @param uniqueIdPrivateSize Size of unique ID private key
* @param csr Buffer to hold CSR (recommended size: 16384 bytes)
* @param csrSize Value/result: size of buffer
* @return OK (0) or error
*/
ZT_SDK_API int ZT_Certificate_newCSR(
const ZT_Certificate_Subject *subject,
const void *uniqueId,
int uniqueIdSize,
const void *uniqueIdPrivate,
int uniqueIdPrivateSize,
void *csr,
int *csrSize);
/**
* Sign a CSR to generate a complete certificate
*
* @param cert Certificate to sign
* @param signer Signer identity (must contain secret key)
* @param signedCert Signed certificate buffer (recommended size: 16384 bytes)
* @param signedCertSize Value/result: size of buffer
* @return OK (0) or error
*/
ZT_SDK_API int ZT_Certificate_sign(
const ZT_Certificate *cert,
const ZT_Identity *signer,
void *signedCert,
int *signedCertSize);
/**
* Decode a certificate or CSR
*
* A CSR is just the encoded subject part of a certificate. Decoding a CSR
* results in a certificate whose subject is filled in but nothing else.
*
* If no error occurs and the pointer at decodedCert is set to non-NULL,
* the returned certificate must be freed with ZT_Certificate_delete().
*
* @param decodedCert Result parameter: target pointer is set to certificate
* @param cert Certificate or CSR data
* @param certSize Size of data
* @param verify If non-zero, verify signatures and structure
* @return Certificate error, if any
*/
ZT_SDK_API enum ZT_CertificateError ZT_Certificate_decode(
ZT_Certificate **decodedCert,
const void *cert,
int certSize,
int verify);
/**
* Free a certificate created with ZT_Certificate_decode()
*
* @param cert Certificate to free
*/
ZT_SDK_API void ZT_Certificate_delete(ZT_Certificate *cert);
/* ---------------------------------------------------------------------------------------------------------------- */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -11,7 +11,9 @@
*/ */
/****/ /****/
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x06010000 #define _WIN32_WINNT 0x06010000
#endif
#include "GoGlue.h" #include "GoGlue.h"
@ -22,11 +24,11 @@
#include "../core/MAC.hpp" #include "../core/MAC.hpp"
#include "../core/Address.hpp" #include "../core/Address.hpp"
#include "../core/Containers.hpp" #include "../core/Containers.hpp"
#include "../core/Certificate.hpp"
#include "../osdep/OSUtils.hpp" #include "../osdep/OSUtils.hpp"
#include "../osdep/EthernetTap.hpp" #include "../osdep/EthernetTap.hpp"
#ifndef __WINDOWS__ #ifndef __WINDOWS__
#include <unistd.h> #include <unistd.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
@ -35,16 +37,11 @@
#include <ifaddrs.h> #include <ifaddrs.h>
#include <net/if.h> #include <net/if.h>
#include <netinet/in.h> #include <netinet/in.h>
#ifdef __BSD__ #ifdef __BSD__
#include <netinet6/in6_var.h> #include <netinet6/in6_var.h>
#endif #endif
#include <arpa/inet.h> #include <arpa/inet.h>
#include <errno.h> #include <errno.h>
#ifdef __LINUX__ #ifdef __LINUX__
#ifndef IPV6_DONTFRAG #ifndef IPV6_DONTFRAG
#define IPV6_DONTFRAG 62 #define IPV6_DONTFRAG 62