diff options
author | mrm <mrm@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1997-08-22 01:58:01 +0000 |
---|---|---|
committer | mrm <mrm@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1997-08-22 01:58:01 +0000 |
commit | a5eb53e73c47454dc1dee71201812f41ac520ae2 (patch) | |
tree | 23790f507cc0d624252032b2dcc16a9241b5c5e7 /ASNMP | |
parent | c3d425e310f8a2cdd1de255c3d6bbe8d04acc95e (diff) | |
download | ATCD-a5eb53e73c47454dc1dee71201812f41ac520ae2.tar.gz |
Added DecNet and AppleTalk Address classes per the
CISCO-TC.my /CISCO-PING-MIB.my descriptions
Diffstat (limited to 'ASNMP')
-rw-r--r-- | ASNMP/asnmp/address.cpp | 455 | ||||
-rw-r--r-- | ASNMP/asnmp/address.h | 129 |
2 files changed, 528 insertions, 56 deletions
diff --git a/ASNMP/asnmp/address.cpp b/ASNMP/asnmp/address.cpp index ef2041bb33d..0722138f2fc 100644 --- a/ASNMP/asnmp/address.cpp +++ b/ASNMP/asnmp/address.cpp @@ -950,20 +950,20 @@ NetbiosAddress::NetbiosAddress( const char *inaddr, nb_service svc) int NetbiosAddress::parse_address(const char *address) { if (ACE_OS::strlen(address) > NETBIOSLEN) - return 0; // invalid + return FALSE; // invalid if (ACE_OS::strncmp(address, "IBM", 3) == 0) - return 0; // invalid + return FALSE; // invalid // addresses are free form but this check may need to be expose to user // //if (address[15] < nb_workstation || address[15] > nb_server) - // return 0; //invalid service type + // return FALSE; //invalid service type ACE_OS::memset(address_buffer, 0, NETBIOSLEN); ACE_OS::memcpy(address_buffer, address, NETBIOSLEN); - return 1; // valid + return TRUE; // valid } NetbiosAddress::NetbiosAddress( const NetbiosAddress& nbaddr) @@ -1007,6 +1007,11 @@ char *NetbiosAddress::to_string() { return (char *)output_buffer; } + +void NetbiosAddress::to_octet(OctetStr& octet) const +{ + octet.set_data( smival.value.string.ptr, smival.value.string.len); +} NetbiosAddress& NetbiosAddress::operator=( const NetbiosAddress &val) { @@ -1415,6 +1420,11 @@ addr_type IpxAddress::get_type() const return type_ipx; } +void IpxAddress::to_octet(OctetStr& octet) const +{ + octet.set_data( smival.value.string.ptr, smival.value.string.len); +} + //======================================================================== //======== IpxSockAddress Implementation ================================= @@ -1898,6 +1908,11 @@ unsigned int MacAddress::hashFunction() const + (((address_buffer[4] << 8) + address_buffer[5]) * HASH2)); } +void MacAddress::to_octet(OctetStr& octet) const +{ + octet.set_data( smival.value.string.ptr, smival.value.string.len); +} + //======================================================================== //========== Generic Address Implementation ============================== //======================================================================== @@ -1911,34 +1926,29 @@ SmiUINT32 GenAddress::get_syntax() return sNMP_SYNTAX_NULL; } -//-----------[ constructor with a string argument ]---------------------- -GenAddress::GenAddress( const char *addr) -{ - if (ACE_OS::strlen(addr) == 0) { - // initialize SMI info - // BOK: this is generally not used for GenAddress, - // but we need this to be a replica of the real address' - // smival info so that operator=SnmpSyntax will work. - smival.syntax = sNMP_SYNTAX_NULL; // to be overridden - smival.value.string.len = 0; // to be overridden - smival.value.string.ptr = address_buffer; // constant - - valid_flag = FALSE; - address = 0; - format_output(); - return; - } +void GenAddress::init_smi() +{ + smival.syntax = sNMP_SYNTAX_NULL; // to be overridden + smival.value.string.len = 0; // to be overridden + smival.value.string.ptr = address_buffer; // constant +} +//-----------[ constructor with a string argument ]---------------------- +GenAddress::GenAddress( const char *addr): address(0) +{ + valid_flag = FALSE; // initialize SMI info // BOK: smival is generally not used for GenAddress, but // we need this to be a replica of the real address' // smival info so that <class>::operator=SnmpSyntax // will work. - smival.syntax = sNMP_SYNTAX_NULL; // to be overridden - smival.value.string.len = 0; // to be overridden - smival.value.string.ptr = address_buffer; // constant + init_smi(); + + if (addr && ACE_OS::strlen(addr) == 0) { + format_output(); + return; + } - address = 0; parse_address(addr); // Copy real address smival info into GenAddr smival @@ -1957,20 +1967,17 @@ GenAddress::GenAddress( const char *addr) } //-----------[ constructor with an Address argument ]-------------------- -GenAddress::GenAddress( const Address &addr) +GenAddress::GenAddress( const Address &addr): address(0) { + valid_flag = FALSE; + // initialize SMI info // BOK: this is generally not used for GenAddress, // but we need this to be a replica of the real address' // smival info so that operator=SnmpSyntax will work. - smival.syntax = sNMP_SYNTAX_NULL; // to be overridden - smival.value.string.len = 0; // to be overridden - smival.value.string.ptr = address_buffer; // constant - - valid_flag = FALSE; + init_smi(); // make sure that the object is valid if (!addr.valid()) { - address = 0; format_output(); return; } @@ -1997,21 +2004,18 @@ GenAddress::GenAddress( const Address &addr) } //-----------------[ constructor with another GenAddress object ]------------- -GenAddress::GenAddress( const GenAddress &addr) +GenAddress::GenAddress( const GenAddress &addr): address(0) { + valid_flag = FALSE; // initialize SMI info // BOK: this is generally not used for GenAddress, // but we need this to be a replica of the real address' // smival info so that operator=SnmpSyntax will work. - smival.syntax = sNMP_SYNTAX_OCTETS; - smival.value.string.len = 0; - smival.value.string.ptr = address_buffer; + init_smi(); - valid_flag = FALSE; // make sure that the object is valid if (!addr.valid_flag) { - address = 0; format_output(); return; } @@ -2035,13 +2039,13 @@ GenAddress::GenAddress( const GenAddress &addr) } format_output(); -}; +} //----------[ destructor ] ------------------------------------------------ GenAddress::~GenAddress() { if ( address != 0) - delete address; + delete address; } //----------[ create a new instance of this Value ]------------------------ @@ -2062,8 +2066,10 @@ GenAddress& GenAddress::operator=( const GenAddress &addr) delete address; address = 0; } + if (addr.address) address = (Address *)(addr.address)->clone(); + if (address) valid_flag = address->valid(); @@ -2099,8 +2105,7 @@ SnmpSyntax& GenAddress::operator=( SnmpSyntax &val) address = 0; } - if (val.valid()) - { + if (val.valid()) { switch ( val.get_syntax() ) { //-----[ ip address case ]------------- // BOK: this case shouldn't be needed since there is an explicit @@ -2119,11 +2124,13 @@ SnmpSyntax& GenAddress::operator=( SnmpSyntax &val) //-----[ mac address case ]------------ // BOK: This is here only to support GenAddr = primitive OctetStr. // The explicit GenAddr=Address assignment will handle the cases - // GenAddr = [UdpAdd|IpxAddr|IpxSock|MacAddr]. + // GenAddr = [UdpAdd|IpxAddr|IpxSock|MacAddr|DecNetAddr|NetbiosAddr|AppleTlk]. // Note, using the heuristic of octet str len to determine type of // address to create is not accurate when address lengths are equal // (e.g., UDPIPV4LEN == MACLEN). It gets worse if we add AppleTalk or - // OSI which use variable length addresses! + // OSI which use variable length addresses! assume AppleTalk as used in IOS Mibs + // is defined in CISCO-TC.my as fixed length of 3 octets + case sNMP_SYNTAX_OCTETS: { unsigned long val_len; @@ -2144,7 +2151,17 @@ SnmpSyntax& GenAddress::operator=( SnmpSyntax &val) else if (val_len == MACLEN) { ACE_NEW_RETURN(address, MacAddress, *this); } - if (address){ + else if (val_len == APPLETKLEN) { + ACE_NEW_RETURN(address, AppleTalkAddress, *this); + } + else if (val_len == DECNETLEN) { + ACE_NEW_RETURN(address, DecNetAddress, *this); + } + else if (val_len == NETBIOSLEN) { + ACE_NEW_RETURN(address, DecNetAddress, *this); + } + + if (address) { *address = val; valid_flag = address->valid(); } @@ -2173,6 +2190,7 @@ SnmpSyntax& GenAddress::operator=( SnmpSyntax &val) // redefined parse address for macs +// TODO: Add netbios, appletalk, and decnet addresses here int GenAddress::parse_address( const char *addr) { if ( address != 0) @@ -2188,8 +2206,7 @@ int GenAddress::parse_address( const char *addr) // ipxsock address ACE_NEW_RETURN(address, IpxSockAddress( addr), -1); valid_flag = address->valid(); - if ( valid_flag && ((IpxSockAddress*)address)->get_socket()) - { + if ( valid_flag && ((IpxSockAddress*)address)->get_socket()) { format_output(); return TRUE; // ok its an ipxsock address } @@ -2199,8 +2216,7 @@ int GenAddress::parse_address( const char *addr) // ipx address ACE_NEW_RETURN(address, IpxAddress( addr), -1); valid_flag = address->valid(); - if ( valid_flag) - { + if ( valid_flag) { format_output(); return TRUE; // ok its an ipx address } @@ -2212,14 +2228,14 @@ int GenAddress::parse_address( const char *addr) //class will get demoted to ip/ipx. The only proper way to do this is //to parse the strings ourselves. - // udp address + // udp address ACE_NEW_RETURN(address, UdpAddress( addr), -1); valid_flag = address->valid(); - if ( valid_flag && ((UdpAddress*)address)->get_port()) - { + if ( valid_flag && ((UdpAddress*)address)->get_port()) { format_output(); return TRUE; // ok its a udp address } + // otherwise delete it and try another delete address; @@ -2237,11 +2253,41 @@ int GenAddress::parse_address( const char *addr) // mac address ACE_NEW_RETURN(address, MacAddress( addr), -1); valid_flag = address->valid(); - if ( valid_flag) - { + if ( valid_flag) { format_output(); return TRUE; // ok, its a mac } + + // guess by length of argument the type of address + switch (ACE_OS::strlen(addr)) { + case NETBIOSLEN: + ACE_NEW_RETURN(address, NetbiosAddress( addr), -1); + valid_flag = address->valid(); + if ( valid_flag) { + format_output(); + return TRUE; // ok, its a mac + } + break; + + case APPLETKLEN: + ACE_NEW_RETURN(address, AppleTalkAddress( addr), -1); + valid_flag = address->valid(); + if ( valid_flag) { + format_output(); + return TRUE; // ok, its a mac + } + break; + + case DECNETLEN: + ACE_NEW_RETURN(address, DecNetAddress( addr), -1); + valid_flag = address->valid(); + if ( valid_flag) { + format_output(); + return TRUE; // ok, its a mac + } + break; + + } // otherwise its invalid delete address; address = 0; @@ -2281,3 +2327,304 @@ addr_type GenAddress::get_type() const return address->get_type(); } +// call the particular type class here +void GenAddress::to_octet(OctetStr& octet) const +{ + if (!valid()) + return; + + address->to_octet(octet); +} + +//------------------------------------------------------------------------ +//---------[ DecNet Address Class ]--------------------------------------- +//------------------------------------------------------------------------ + +DecNetAddress::DecNetAddress( const char *inaddr): Address() +{ + if (ACE_OS::strlen(inaddr) == 0) { + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = DECNETLEN; + smival.value.string.ptr = address_buffer; + + valid_flag=FALSE; + DecNetAddress::format_output(); + return; + } + + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = DECNETLEN; + smival.value.string.ptr = address_buffer; + + valid_flag = parse_address( (char *) inaddr); + DecNetAddress::format_output(); +} +DecNetAddress::DecNetAddress( const DecNetAddress& decaddr) +{ +} + +DecNetAddress::DecNetAddress( const GenAddress& genaddr) +{ + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = DECNETLEN; + smival.value.string.ptr = address_buffer; + + valid_flag = FALSE; + // allow use of an ipx or ipxsock address + if ( (genaddr.get_type() == type_decnet) ) { + valid_flag = genaddr.valid(); + if ( valid_flag) { + // copy in the Ipx address data + DecNetAddress temp_ipx( (const char *) genaddr); + *this = temp_ipx; + } + } + DecNetAddress::format_output(); +} + +DecNetAddress::~DecNetAddress() +{ +} + +char *DecNetAddress::to_string() +{ + return (char *)output_buffer; +} + +DecNetAddress& DecNetAddress::operator=( const DecNetAddress &decaddr) +{ + // protect against assignment from itself + if ( this == &decaddr ) + return *this; + valid_flag = decaddr.valid_flag; + if (valid_flag) + ACE_OS::memcpy(address_buffer, decaddr.address_buffer, DECNETLEN); + format_output(); + return *this; +} + +void DecNetAddress::to_octet(OctetStr& octet) const +{ + octet.set_data( smival.value.string.ptr, smival.value.string.len); +} + +DecNetAddress::operator const char *() const +{ + return (char *)output_buffer; +} + +SmiUINT32 DecNetAddress::get_syntax() +{ + return sNMP_SYNTAX_OCTETS; +} + +SnmpSyntax& DecNetAddress::operator=( SnmpSyntax &val) +{ + // protect against assignment from itself + if ( this == &val ) + return *this; + + valid_flag = 0; // will get set TRUE if really valid + + if (val.valid()) { + if (((DecNetAddress &)val).smival.value.string.len ==DECNETLEN) { + ACE_OS::memcpy(address_buffer, + ((DecNetAddress &)val).smival.value.string.ptr, DECNETLEN); + valid_flag = 1; + } + } + DecNetAddress::format_output(); + return *this; +} + +SnmpSyntax *DecNetAddress::clone() const +{ + return (SnmpSyntax *) new DecNetAddress(*this); +} + +addr_type DecNetAddress::get_type() const +{ + return type_decnet; +} + +void DecNetAddress::format_output() +{ + // if valid format else null it + if ( valid_flag) + ACE_OS::sprintf( (char *) output_buffer,"%d.%d",address_buffer[0], + address_buffer[1]); + else + output_buffer[0] = 0; +} + +int DecNetAddress::parse_address( const char *address) +{ + if (ACE_OS::strlen(address) > DECNETLEN) + return FALSE; // invalid + + ACE_OS::memset(address_buffer, 0, DECNETLEN); + ACE_OS::memcpy(address_buffer, address, DECNETLEN); + + return TRUE; // valid +} + + +//------------------------------------------------------------------------ +//---------[ AppleTalk Address Class ]------------------------------------ +//------------------------------------------------------------------------ + +AppleTalkAddress::AppleTalkAddress( const char *inaddr): Address() +{ + if (ACE_OS::strlen(inaddr) == 0) { + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = APPLETKLEN; + smival.value.string.ptr = address_buffer; + + valid_flag=FALSE; + AppleTalkAddress::format_output(); + return; + } + + // always initialize SMI info + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = APPLETKLEN; + smival.value.string.ptr = address_buffer; + + valid_flag = parse_address( (char *) inaddr); + AppleTalkAddress::format_output(); +} +AppleTalkAddress::AppleTalkAddress( const AppleTalkAddress& decaddr) +{ +} + +AppleTalkAddress::AppleTalkAddress( const GenAddress& genaddr) +{ + smival.syntax = sNMP_SYNTAX_OCTETS; + smival.value.string.len = APPLETKLEN; + smival.value.string.ptr = address_buffer; + + valid_flag = FALSE; + // allow use of an ipx or ipxsock address + if ( (genaddr.get_type() == type_atk) ) { + valid_flag = genaddr.valid(); + if ( valid_flag) { + // copy in the Ipx address data + AppleTalkAddress temp_ipx( (const char *) genaddr); + *this = temp_ipx; + } + } + AppleTalkAddress::format_output(); +} + +AppleTalkAddress::~AppleTalkAddress() +{ +} + +char *AppleTalkAddress::to_string() +{ + return (char *)output_buffer; +} + +AppleTalkAddress& AppleTalkAddress::operator=( const AppleTalkAddress &ataddr) +{ + // protect against assignment from itself + if ( this == &ataddr ) + return *this; + valid_flag = ataddr.valid_flag; + if (valid_flag) + ACE_OS::memcpy(address_buffer, ataddr.address_buffer, APPLETKLEN); + format_output(); + return *this; +} + +void AppleTalkAddress::to_octet(OctetStr& octet) const +{ + octet.set_data( smival.value.string.ptr, smival.value.string.len); +} + +AppleTalkAddress::operator const char *() const +{ + return (char *)output_buffer; +} + +SmiUINT32 AppleTalkAddress::get_syntax() +{ + return sNMP_SYNTAX_OCTETS; +} + +SnmpSyntax& AppleTalkAddress::operator=( SnmpSyntax &val) +{ + // protect against assignment from itself + if ( this == &val ) + return *this; + + valid_flag = 0; // will get set TRUE if really valid + + if (val.valid()) { + if (((AppleTalkAddress &)val).smival.value.string.len ==APPLETKLEN) { + ACE_OS::memcpy(address_buffer, + ((AppleTalkAddress &)val).smival.value.string.ptr,APPLETKLEN); + valid_flag = 1; + } + } + AppleTalkAddress::format_output(); + return *this; +} + +SnmpSyntax *AppleTalkAddress::clone() const +{ + return (SnmpSyntax *) new AppleTalkAddress(*this); +} + +addr_type AppleTalkAddress::get_type() const +{ + return type_atk; +} + +void AppleTalkAddress::format_output() +{ + // if valid format else null it + if ( valid_flag) + ACE_OS::sprintf( (char *) output_buffer,"%d.%d.%d",address_buffer[0], + address_buffer[1]), address_buffer[3]; + else + output_buffer[0] = 0; +} + +int AppleTalkAddress::parse_address( const char *address) +{ + if (ACE_OS::strlen(address) > APPLETKLEN) + return FALSE; // invalid + + ACE_OS::memset(address_buffer, 0, APPLETKLEN); + ACE_OS::memcpy(address_buffer, address, APPLETKLEN); + + return TRUE; // valid +} + +char AppleTalkAddress::get_host_address() const +{ + return address_buffer[2]; +} + +void AppleTalkAddress::set_host_address(const char host) +{ + address_buffer[2] = host; +} + +short AppleTalkAddress::get_net_address() const +{ + short net; + ACE_OS::memcpy(&net, address_buffer, APPLETKLEN - 1); + return net; +} + +void AppleTalkAddress::set_net_address(const short atknet) +{ + ACE_OS::memcpy(address_buffer, &atknet, APPLETKLEN -1); +} + + diff --git a/ASNMP/asnmp/address.h b/ASNMP/asnmp/address.h index dd1a1818f5f..498deb07910 100644 --- a/ASNMP/asnmp/address.h +++ b/ASNMP/asnmp/address.h @@ -46,9 +46,11 @@ enum address_lengths { UDPIPV4LEN=6, IPV6LEN=16, UDPIPV6LEN=18, - NETBIOSLEN=16, IPXLEN=10, IPXSOCKLEN=12, + NETBIOSLEN=16, + APPLETKLEN=3, + DECNETLEN=2, MACLEN=6, HASH0=19, HASH1=13, @@ -64,6 +66,8 @@ enum addr_type { type_ipxsock, type_mac, type_nb, + type_atk, + type_decnet, type_e164, type_sip, // IPv6 type_invalid @@ -140,6 +144,9 @@ public: virtual int valid() const; // verify the is the address object constructed ok + virtual void to_octet(OctetStr& octet) const = 0; + // return a suitable buffer to contain the address + virtual SmiUINT32 get_syntax() = 0; // (pure virtual) syntax type @@ -244,7 +251,7 @@ public: int is_private() const; // per RFC 1597, private addresses are:: 10, 172.16, and 192.168.0 - void to_octet(OctetStr& octet) const; + virtual void to_octet(OctetStr& octet) const; // convert address into octet string format in network byte order protected: @@ -394,6 +401,8 @@ public: unsigned int hashFunction() const; // return a hash key + virtual void to_octet(OctetStr& octet) const; + // return byte array of the mac address protected: char output_buffer[MAX_DISPLAY_SZ]; @@ -452,6 +461,9 @@ public: SnmpSyntax *clone() const; // create a new instance of this Value + virtual void to_octet(OctetStr& octet) const; + // output byte buffer containing netbios name + protected: void InitNBAddr(const char *inaddr); char output_buffer[MAX_DISPLAY_SZ]; @@ -463,6 +475,110 @@ protected: }; //------------------------------------------------------------------------ +//---------[ DecNet Address Class ]--------------------------------------- +//------------------------------------------------------------------------ +class ACE_Export DecNetAddress : public Address + // = TITLE + // Defines the member functions for the concrete class DecNetAddress. + // DecNet Phase ? address consists of two octets (CISCO-TC.my) +{ + public: + DecNetAddress( const char *inaddr = ""); + // default constructor with string arg + + DecNetAddress( const DecNetAddress& decaddr); + // copy constructor + + DecNetAddress( const GenAddress& genaddr); + // construct with a GenAddress + + ~DecNetAddress(); + + virtual char *to_string(); + + DecNetAddress& operator=( const DecNetAddress &decaddr); + + virtual void to_octet(OctetStr& octet) const; + // convert address into octet string format 2 bytes of decnet address + + virtual operator const char *() const; + // const char * operator overloaded for streaming output + + virtual SmiUINT32 get_syntax(); + // syntax type + + SnmpSyntax& operator=( SnmpSyntax &val); + // copy an instance of this Value + + SnmpSyntax *clone() const; + // create a new instance of this Value + + protected: + virtual int parse_address( const char *inaddr); + virtual addr_type get_type() const; + virtual void format_output(); + char output_buffer[MAX_DISPLAY_SZ]; +}; + +//------------------------------------------------------------------------ +//---------[ AppleTalk Address Class ]------------------------------------ +//------------------------------------------------------------------------ +class ACE_Export AppleTalkAddress : public Address + // = TITLE + // Defines the member functions for the concrete class DecNetAddress. + // DecNet Phase ? address consists of two octets (CISCO-TC.my) +{ + public: + AppleTalkAddress( const char *inaddr = ""); + // default constructor with string arg + + AppleTalkAddress( const AppleTalkAddress& atkaddr); + // copy constructor + + AppleTalkAddress( const GenAddress& genaddr); + // construct with a GenAddress + + ~AppleTalkAddress(); + + virtual char *to_string(); + + AppleTalkAddress& operator=( const AppleTalkAddress &atkaddr); + + virtual void to_octet(OctetStr& octet) const; + // convert address into octet string format 3 bytes of atk address + + char get_host_address() const; + // get the host part of the address + + void set_host_address(const char); + // set the host part of the address + + short get_net_address() const; + // get the 2 byte atk network address + + void set_net_address(const short atknet); + // set the host 2 byte atk network address + + virtual operator const char *() const; + // const char * operator overloaded for streaming output + + virtual SmiUINT32 get_syntax(); + // syntax type + + SnmpSyntax& operator=( SnmpSyntax &val); + // copy an instance of this Value + + SnmpSyntax *clone() const; + // create a new instance of this Value + + private: + virtual int parse_address( const char *inaddr); + virtual addr_type get_type() const; + virtual void format_output(); + char output_buffer[MAX_DISPLAY_SZ]; +}; + +//------------------------------------------------------------------------ //---------[ IPX Address Class ]------------------------------------------ //------------------------------------------------------------------------ class ACE_Export IpxAddress : public Address @@ -507,6 +623,9 @@ public: virtual addr_type get_type() const; // return the type + virtual void to_octet(OctetStr& octet) const; + // return byte sequence containing ipx address + protected: char separator; // ipx format separator {:,/} @@ -630,6 +749,9 @@ public: virtual addr_type get_type() const; // return the type + virtual void to_octet(OctetStr& octet) const; + // return the address as a octet sequence + protected: Address *address; // pointer to a a concrete address @@ -642,6 +764,9 @@ protected: virtual void format_output(); // format output for a generic address + + void init_smi(); + // initialize smi data structure }; #endif //_ADDRESS |