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