1/*++ 2/* NAME 3/* sock_addr 3 4/* SUMMARY 5/* sockaddr utilities 6/* SYNOPSIS 7/* #include <sock_addr.h> 8/* 9/* int sock_addr_cmp_addr(sa, sb) 10/* const struct sockaddr *sa; 11/* const struct sockaddr *sb; 12/* 13/* int sock_addr_cmp_port(sa, sb) 14/* const struct sockaddr *sa; 15/* const struct sockaddr *sb; 16/* 17/* int SOCK_ADDR_EQ_ADDR(sa, sb) 18/* const struct sockaddr *sa; 19/* const struct sockaddr *sb; 20/* 21/* int SOCK_ADDR_EQ_PORT(sa, sb) 22/* const struct sockaddr *sa; 23/* const struct sockaddr *sb; 24/* 25/* int sock_addr_in_loopback(sa) 26/* const struct sockaddr *sa; 27/* AUXILIARY MACROS 28/* struct sockaddr *SOCK_ADDR_PTR(ptr) 29/* unsigned char SOCK_ADDR_FAMILY(ptr) 30/* unsigned char SOCK_ADDR_LEN(ptr) 31/* unsigned short SOCK_ADDR_PORT(ptr) 32/* unsigned short *SOCK_ADDR_PORTP(ptr) 33/* 34/* struct sockaddr_in *SOCK_ADDR_IN_PTR(ptr) 35/* unsigned char SOCK_ADDR_IN_FAMILY(ptr) 36/* unsigned short SOCK_ADDR_IN_PORT(ptr) 37/* struct in_addr SOCK_ADDR_IN_ADDR(ptr) 38/* struct in_addr IN_ADDR(ptr) 39/* 40/* struct sockaddr_in6 *SOCK_ADDR_IN6_PTR(ptr) 41/* unsigned char SOCK_ADDR_IN6_FAMILY(ptr) 42/* unsigned short SOCK_ADDR_IN6_PORT(ptr) 43/* struct in6_addr SOCK_ADDR_IN6_ADDR(ptr) 44/* struct in6_addr IN6_ADDR(ptr) 45/* DESCRIPTION 46/* These utilities take protocol-independent address structures 47/* and perform protocol-dependent operations on structure members. 48/* Some of the macros described here are called unsafe, 49/* because they evaluate one or more arguments multiple times. 50/* 51/* sock_addr_cmp_addr() or sock_addr_cmp_port() compare the 52/* address family and network address or port fields for 53/* equality, and return indication of the difference between 54/* their arguments: < 0 if the first argument is "smaller", 55/* 0 for equality, and > 0 if the first argument is "larger". 56/* 57/* The unsafe macros SOCK_ADDR_EQ_ADDR() or SOCK_ADDR_EQ_PORT() 58/* compare compare the address family and network address or 59/* port fields for equality, and return non-zero when their 60/* arguments differ. 61/* 62/* sock_addr_in_loopback() determines if the argument specifies 63/* a loopback address. 64/* 65/* The SOCK_ADDR_PTR() macro casts a generic pointer to (struct 66/* sockaddr *). The name is upper case for consistency not 67/* safety. SOCK_ADDR_FAMILY() and SOCK_ADDR_LEN() return the 68/* address family and length of the real structure that hides 69/* inside a generic sockaddr structure. On systems where struct 70/* sockaddr has no sa_len member, SOCK_ADDR_LEN() cannot be 71/* used as lvalue. SOCK_ADDR_PORT() returns the IPv4 or IPv6 72/* port number, in network byte order; it must not be used as 73/* lvalue. SOCK_ADDR_PORTP() returns a pointer to the same. 74/* 75/* The macros SOCK_ADDR_IN{,6}_{PTR,FAMILY,PORT,ADDR}() cast 76/* a generic pointer to a specific socket address structure 77/* pointer, or access a specific socket address structure 78/* member. These can be used as lvalues. 79/* 80/* The unsafe INADDR() and IN6_ADDR() macros dereference a 81/* generic pointer to a specific address structure. 82/* DIAGNOSTICS 83/* Panic: unsupported address family. 84/* LICENSE 85/* .ad 86/* .fi 87/* The Secure Mailer license must be distributed with this software. 88/* AUTHOR(S) 89/* Wietse Venema 90/* IBM T.J. Watson Research 91/* P.O. Box 704 92/* Yorktown Heights, NY 10598, USA 93/*--*/ 94 95/* System library. */ 96 97#include <sys_defs.h> 98#include <sys/socket.h> 99#include <netinet/in.h> 100#include <string.h> 101 102/* Utility library. */ 103 104#include <msg.h> 105#include <sock_addr.h> 106 107/* sock_addr_cmp_addr - compare addresses for equality */ 108 109int sock_addr_cmp_addr(const struct sockaddr * sa, 110 const struct sockaddr * sb) 111{ 112 if (sa->sa_family != sb->sa_family) 113 return (sa->sa_family - sb->sa_family); 114 115 /* 116 * With IPv6 address structures, assume a non-hostile implementation that 117 * stores the address as a contiguous sequence of bits. Any holes in the 118 * sequence would invalidate the use of memcmp(). 119 */ 120 if (sa->sa_family == AF_INET) { 121 return (SOCK_ADDR_IN_ADDR(sa).s_addr - SOCK_ADDR_IN_ADDR(sb).s_addr); 122#ifdef HAS_IPV6 123 } else if (sa->sa_family == AF_INET6) { 124 return (memcmp((char *) &(SOCK_ADDR_IN6_ADDR(sa)), 125 (char *) &(SOCK_ADDR_IN6_ADDR(sb)), 126 sizeof(SOCK_ADDR_IN6_ADDR(sa)))); 127#endif 128 } else { 129 msg_panic("sock_addr_cmp_addr: unsupported address family %d", 130 sa->sa_family); 131 } 132} 133 134/* sock_addr_cmp_port - compare ports for equality */ 135 136int sock_addr_cmp_port(const struct sockaddr * sa, 137 const struct sockaddr * sb) 138{ 139 if (sa->sa_family != sb->sa_family) 140 return (sa->sa_family - sb->sa_family); 141 142 if (sa->sa_family == AF_INET) { 143 return (SOCK_ADDR_IN_PORT(sa) - SOCK_ADDR_IN_PORT(sb)); 144#ifdef HAS_IPV6 145 } else if (sa->sa_family == AF_INET6) { 146 return (SOCK_ADDR_IN6_PORT(sa) - SOCK_ADDR_IN6_PORT(sb)); 147#endif 148 } else { 149 msg_panic("sock_addr_cmp_port: unsupported address family %d", 150 sa->sa_family); 151 } 152} 153 154/* sock_addr_in_loopback - determine if address is loopback */ 155 156int sock_addr_in_loopback(const struct sockaddr * sa) 157{ 158 unsigned long inaddr; 159 160 if (sa->sa_family == AF_INET) { 161 inaddr = ntohl(SOCK_ADDR_IN_ADDR(sa).s_addr); 162 return (IN_CLASSA(inaddr) 163 && ((inaddr & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT) 164 == IN_LOOPBACKNET); 165#ifdef HAS_IPV6 166 } else if (sa->sa_family == AF_INET6) { 167 return (IN6_IS_ADDR_LOOPBACK(&SOCK_ADDR_IN6_ADDR(sa))); 168#endif 169 } else { 170 msg_panic("sock_addr_in_loopback: unsupported address family %d", 171 sa->sa_family); 172 } 173} 174