// -*- mode: C++; tab-width: 8; -*- // vi:ts=8 sw=4 noexpandtab autoindent /** * netprotectaddr.h - Store an IPv4 or IPv6 protects table address and compare it with match strings. * * Copyright 2012 Perforce Software. All rights reserved. * * This file is part of Perforce - the FAST SCM System. */ #include <stdhdrs.h> #include <strbuf.h> #include "netport.h" #include "netportipv6.h" #include "netipaddr.h" #include "netprotectaddr.h" // uncomment to enable address parse/match debugging //#define NPA_DEBUG #ifdef NPA_DEBUG #include "debug.h" #endif /* * Orthodox Canonical Form (OCF) methods */ /** * default ctor */ NetProtectAddr::NetProtectAddr() : m_proxy(PROXY_NONE) , m_addr() , m_prefixlen(NetIPAddr::CIDR_UNSPEC) , m_type(NetProtectAddr::PROT_ADDR_TEXT) { } // default ctor NetProtectAddr::NetProtectAddr( const StrPtr &addr) : m_proxy(PROXY_NONE) , m_addr(addr) , m_prefixlen(NetIPAddr::CIDR_UNSPEC) , m_type(NetProtectAddr::PROT_ADDR_TEXT) { Parse(); } /** * copy ctor */ NetProtectAddr::NetProtectAddr( const NetProtectAddr &rhs) : m_proxy(rhs.m_proxy) , m_addr(rhs.m_addr) , m_prefixlen(rhs.m_prefixlen) , m_type(rhs.m_type) , m_nipa(rhs.m_nipa) { } // copy ctor /** * dtor */ NetProtectAddr::~NetProtectAddr() { } // dtor /** * assignment op */ const NetProtectAddr & NetProtectAddr::operator=( const NetProtectAddr &rhs) { if( this != &rhs ) { m_proxy = rhs.m_proxy; m_addr = rhs.m_addr; m_prefixlen = rhs.m_prefixlen; m_type = rhs.m_type; m_nipa = rhs.m_nipa; } return *this; } // op= /** * op== */ bool NetProtectAddr::operator==( const NetProtectAddr &rhs) const { if( this == &rhs ) { return true; } if( m_proxy != rhs.m_proxy || m_addr != rhs.m_addr || m_prefixlen != rhs.m_prefixlen || m_type != rhs.m_type || m_nipa != rhs.m_nipa ) { return false; } return true; } // op== /** * op!= */ bool NetProtectAddr::operator!=( const NetProtectAddr &rhs) const { return !(*this == rhs); } // op!= /* * Other methods */ /** * Parse a string into its components: * regex: * [proxy-]Address[/[pfxlen]] * BNF: * ProtectEntry ::= OptProxyPrefix Address OptPrefixLen ; * OptProxyPrefix ::= 'proxy-' * | * ; * Address ::= IPv4Address * | IPv6Address * | WildAddress * ; * IPv4Address ::= [0-9]{1,3}.[0-9]{1,3}.[0-9]{0,3}.[0-9]{0,3} ; * IPv6Address ::= // I won't describe IPv6 in a single regex! 8 fields of 16 bits: [0-9a-fA-F]{0,4} ; * WildAddress := * ; // any text string; '*' is special * OptPrefixLen ::= '/' number * | '/' * | * ; */ void NetProtectAddr::Parse() { const char *cp = m_addr.Text(); StrBuf tmpbuf; // used to avoid overlapping src/dst in StrBuf::Set() calls // check for a proxy prefix if( !StrRef("proxy-").XCompareN(m_addr) ) { m_proxy = PROXY_SET; cp += 6; // skip the proxy stuff } else if( *cp == '*' ) { m_proxy = PROXY_OPT; cp++; // skip the optional proxy flag } else { m_proxy = PROXY_NONE; } // check for a netmask (network prefix len in "slash" notation) if( const char *p = strchr(cp, '/') ) { tmpbuf.Set( cp, p - cp ); m_addr.Set( tmpbuf.Text() ); m_prefixlen = StrPtr::Atoi( p + 1 ); // pin cidr values to the allowed range boundaries if( m_prefixlen < NetIPAddr::CIDR_MIN ) m_prefixlen = NetIPAddr::CIDR_MIN; else if( m_prefixlen > NetIPAddr::CIDR_MAX_V6 ) m_prefixlen = NetIPAddr::CIDR_MAX_V6; } else { m_prefixlen = NetIPAddr::CIDR_UNSPEC; tmpbuf.Set( cp ); m_addr.Set( tmpbuf.Text() ); } m_nipa.Set(m_addr, m_prefixlen); if( m_nipa.IsTypeV4() ) { m_type = PROT_ADDR_V4; if( m_prefixlen > NetIPAddr::CIDR_MAX_V4 ) m_prefixlen = NetIPAddr::CIDR_MAX_V4; } else if( m_nipa.IsTypeV6() ) { m_type = PROT_ADDR_V6; if( m_prefixlen > NetIPAddr::CIDR_MAX_V6 ) m_prefixlen = NetIPAddr::CIDR_MAX_V6; } else { // optimize common case if( m_addr == "*" ) m_type = PROT_ADDR_ANY; else m_type = PROT_ADDR_TEXT; m_prefixlen = NetIPAddr::CIDR_UNSPEC; } } bool NetProtectAddr::Match( const NetProtectAddr &rhs ) const { #ifdef NPA_DEBUG StrBuf buf; StrBuf rhsbuf; ToString(buf); rhs.ToString(rhsbuf); p4debug.printf( " NetProtectAddr::Match(%s, %s)\n", buf.Text(), rhsbuf.Text() ); #endif if( !m_nipa.IsTypeValid() ) return false; switch( rhs.m_proxy ) { case PROXY_NONE: if( m_proxy == PROXY_SET ) return false; break; case PROXY_SET: if( m_proxy == PROXY_NONE ) return false; break; case PROXY_OPT: // fall through break; } switch( rhs.m_type ) { case PROT_ADDR_ANY: // short-circuit most common case return true; case PROT_ADDR_V4: case PROT_ADDR_V6: return m_nipa.Match(rhs.m_nipa); case PROT_ADDR_TEXT: return false; // caller must handle [opt wildcard] text, eg, by calling MatchTable::Match() } return false; } /** * Match * Common usage (eg, from dmprotects.cc): * NetProtectAddr npa( myhostaddress ); * while (entry = get next protect table entry) * { * if( npa.Match(entry.host) ) * { * ... * } * } */ bool NetProtectAddr::Match( const StrPtr &cidr ) const { #ifdef NPA_DEBUG StrBuf buf; ToString(buf); p4debug.printf( " NetProtectAddr::Match(\"%s\") against %s\n", buf.Text(), cidr.Text() ); #endif const NetProtectAddr npa( cidr ); return Match(npa); } /* * Debugging -- generate a textual representation of the address type * [static] */ const char * NetProtectAddr::TypeName(ProtAddrType t) { switch( t ) { case PROT_ADDR_V4: return "v4"; case PROT_ADDR_V6: return "v6"; case PROT_ADDR_TEXT: return "txt"; case PROT_ADDR_ANY: return "*"; } // quiet warning c4715: not all control paths return a value return "<unknown>"; } /* * Debugging -- generate a textual representation of the proxy type * [static] */ const char * NetProtectAddr::ProxyName(ProxyType t) { switch( t ) { case PROXY_NONE: return ""; case PROXY_SET: return "proxy-"; case PROXY_OPT: return "*"; } // quiet warning c4715: not all control paths return a value return "<unknown>"; } /* * Debugging -- generate a textual representation of the address type */ const char * NetProtectAddr::TypeName() const { return TypeName(m_type); } /* * Debugging -- generate a textual representation of the proxy type */ const char * NetProtectAddr::ProxyName() const { return ProxyName(m_proxy); } /* * Debugging -- generate a textual representation of this object */ void NetProtectAddr::ToString(StrBuf &buf) const { char numbuf[64]; const char *num = StrBuf::Itoa(m_prefixlen, &numbuf[sizeof(numbuf)-1]); StrBuf nipabuf; m_nipa.ToString(nipabuf); buf.Set( "{" ); buf.Append( ProxyName() ); buf.Append( nipabuf.Text() ); buf.Append( "/" ); buf.Append( num ); buf.Append( "%" ); buf.Append( TypeName() ); buf.Append( "}" ); }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 14945 | Newtopian |
Merging //guest/perforce_software/p4/... to //guest/Newtopian/p4/... |
||
//guest/perforce_software/p4/2014.1/net/netprotectaddr.cc | |||||
#1 | 12188 | Matt Attaway | Move 'main' p4 into a release specific directory in prep for new releases | ||
//guest/perforce_software/p4/net/netprotectaddr.cc | |||||
#1 | 9129 | Matt Attaway | Initial commit of the 2014.1 p4/p4api source code |