1/*++ 2/* NAME 3/* own_inet_addr 3 4/* SUMMARY 5/* determine if IP address belongs to this mail system instance 6/* SYNOPSIS 7/* #include <own_inet_addr.h> 8/* 9/* int own_inet_addr(addr) 10/* struct sockaddr *addr; 11/* 12/* INET_ADDR_LIST *own_inet_addr_list() 13/* 14/* INET_ADDR_LIST *own_inet_mask_list() 15/* 16/* int proxy_inet_addr(addr) 17/* struct in_addr *addr; 18/* 19/* INET_ADDR_LIST *proxy_inet_addr_list() 20/* DESCRIPTION 21/* own_inet_addr() determines if the specified IP address belongs 22/* to this mail system instance, i.e. if this mail system instance 23/* is supposed to be listening on this specific IP address. 24/* 25/* own_inet_addr_list() returns the list of all addresses that 26/* belong to this mail system instance. 27/* 28/* own_inet_mask_list() returns the list of all corresponding 29/* netmasks. 30/* 31/* proxy_inet_addr() determines if the specified IP address is 32/* listed with the proxy_interfaces configuration parameter. 33/* 34/* proxy_inet_addr_list() returns the list of all addresses that 35/* belong to proxy network interfaces. 36/* LICENSE 37/* .ad 38/* .fi 39/* The Secure Mailer license must be distributed with this software. 40/* AUTHOR(S) 41/* Wietse Venema 42/* IBM T.J. Watson Research 43/* P.O. Box 704 44/* Yorktown Heights, NY 10598, USA 45/*--*/ 46 47/* System library. */ 48 49#include <sys_defs.h> 50#include <string.h> 51 52/* Utility library. */ 53 54#include <msg.h> 55#include <mymalloc.h> 56#include <inet_addr_list.h> 57#include <inet_addr_local.h> 58#include <inet_addr_host.h> 59#include <stringops.h> 60#include <myaddrinfo.h> 61#include <sock_addr.h> 62#include <inet_proto.h> 63 64/* Global library. */ 65 66#include <mail_params.h> 67#include <own_inet_addr.h> 68 69/* Application-specific. */ 70 71static INET_ADDR_LIST saved_addr_list; 72static INET_ADDR_LIST saved_mask_list; 73static INET_ADDR_LIST saved_proxy_list; 74 75/* own_inet_addr_init - initialize my own address list */ 76 77static void own_inet_addr_init(INET_ADDR_LIST *addr_list, 78 INET_ADDR_LIST *mask_list) 79{ 80 INET_ADDR_LIST local_addrs; 81 INET_ADDR_LIST local_masks; 82 char *hosts; 83 char *host; 84 const char *sep = " \t,"; 85 char *bufp; 86 int nvirtual; 87 int nlocal; 88 MAI_HOSTADDR_STR hostaddr; 89 struct sockaddr_storage *sa; 90 struct sockaddr_storage *ma; 91 92 inet_addr_list_init(addr_list); 93 inet_addr_list_init(mask_list); 94 95 /* 96 * Avoid run-time errors when all network protocols are disabled. We 97 * can't look up interface information, and we can't convert explicit 98 * names or addresses. 99 */ 100 if (inet_proto_info()->ai_family_list[0] == 0) { 101 if (msg_verbose) 102 msg_info("skipping %s setting - " 103 "all network protocols are disabled", 104 VAR_INET_INTERFACES); 105 return; 106 } 107 108 /* 109 * If we are listening on all interfaces (default), ask the system what 110 * the interfaces are. 111 */ 112 if (strcmp(var_inet_interfaces, INET_INTERFACES_ALL) == 0) { 113 if (inet_addr_local(addr_list, mask_list, 114 inet_proto_info()->ai_family_list) == 0) 115 msg_fatal("could not find any active network interfaces"); 116 } 117 118 /* 119 * Select all loopback interfaces from the system's available interface 120 * list. 121 */ 122 else if (strcmp(var_inet_interfaces, INET_INTERFACES_LOCAL) == 0) { 123 inet_addr_list_init(&local_addrs); 124 inet_addr_list_init(&local_masks); 125 if (inet_addr_local(&local_addrs, &local_masks, 126 inet_proto_info()->ai_family_list) == 0) 127 msg_fatal("could not find any active network interfaces"); 128 for (sa = local_addrs.addrs, ma = local_masks.addrs; 129 sa < local_addrs.addrs + local_addrs.used; sa++, ma++) { 130 if (sock_addr_in_loopback(SOCK_ADDR_PTR(sa))) { 131 inet_addr_list_append(addr_list, SOCK_ADDR_PTR(sa)); 132 inet_addr_list_append(mask_list, SOCK_ADDR_PTR(ma)); 133 } 134 } 135 inet_addr_list_free(&local_addrs); 136 inet_addr_list_free(&local_masks); 137 } 138 139 /* 140 * If we are supposed to be listening only on specific interface 141 * addresses (virtual hosting), look up the addresses of those 142 * interfaces. 143 */ 144 else { 145 bufp = hosts = mystrdup(var_inet_interfaces); 146 while ((host = mystrtok(&bufp, sep)) != 0) 147 if (inet_addr_host(addr_list, host) == 0) 148 msg_fatal("config variable %s: host not found: %s", 149 VAR_INET_INTERFACES, host); 150 myfree(hosts); 151 152 /* 153 * Weed out duplicate IP addresses. Duplicates happen when the same 154 * IP address is listed under multiple hostnames. If we don't weed 155 * out duplicates, Postfix can suddenly stop working after the DNS is 156 * changed. 157 */ 158 inet_addr_list_uniq(addr_list); 159 160#ifdef __APPLE_OS_X_SERVER__ 161 /* remove IPv6 scoped addresses */ 162 inet_addr_list_clean(addr_list); 163#endif 164 165 /* 166 * Find out the netmask for each virtual interface, by looking it up 167 * among all the local interfaces. 168 */ 169 inet_addr_list_init(&local_addrs); 170 inet_addr_list_init(&local_masks); 171 if (inet_addr_local(&local_addrs, &local_masks, 172 inet_proto_info()->ai_family_list) == 0) 173 msg_fatal("could not find any active network interfaces"); 174 for (nvirtual = 0; nvirtual < addr_list->used; nvirtual++) { 175 for (nlocal = 0; /* see below */ ; nlocal++) { 176 if (nlocal >= local_addrs.used) { 177 SOCKADDR_TO_HOSTADDR( 178 SOCK_ADDR_PTR(addr_list->addrs + nvirtual), 179 SOCK_ADDR_LEN(addr_list->addrs + nvirtual), 180 &hostaddr, (MAI_SERVPORT_STR *) 0, 0); 181 msg_fatal("parameter %s: no local interface found for %s", 182 VAR_INET_INTERFACES, hostaddr.buf); 183 } 184 if (SOCK_ADDR_EQ_ADDR(addr_list->addrs + nvirtual, 185 local_addrs.addrs + nlocal)) { 186 inet_addr_list_append(mask_list, 187 SOCK_ADDR_PTR(local_masks.addrs + nlocal)); 188 break; 189 } 190 } 191 } 192 inet_addr_list_free(&local_addrs); 193 inet_addr_list_free(&local_masks); 194 } 195} 196 197/* own_inet_addr - is this my own internet address */ 198 199int own_inet_addr(struct sockaddr * addr) 200{ 201 int i; 202 203 if (saved_addr_list.used == 0) 204 own_inet_addr_init(&saved_addr_list, &saved_mask_list); 205 206 for (i = 0; i < saved_addr_list.used; i++) 207 if (SOCK_ADDR_EQ_ADDR(addr, saved_addr_list.addrs + i)) 208 return (1); 209 return (0); 210} 211 212/* own_inet_addr_list - return list of addresses */ 213 214INET_ADDR_LIST *own_inet_addr_list(void) 215{ 216 if (saved_addr_list.used == 0) 217 own_inet_addr_init(&saved_addr_list, &saved_mask_list); 218 219 return (&saved_addr_list); 220} 221 222/* own_inet_mask_list - return list of addresses */ 223 224INET_ADDR_LIST *own_inet_mask_list(void) 225{ 226 if (saved_addr_list.used == 0) 227 own_inet_addr_init(&saved_addr_list, &saved_mask_list); 228 229 return (&saved_mask_list); 230} 231 232/* proxy_inet_addr_init - initialize my proxy interface list */ 233 234static void proxy_inet_addr_init(INET_ADDR_LIST *addr_list) 235{ 236 char *hosts; 237 char *host; 238 const char *sep = " \t,"; 239 char *bufp; 240 241 /* 242 * Parse the proxy_interfaces parameter, and expand any symbolic 243 * hostnames into IP addresses. 244 */ 245 inet_addr_list_init(addr_list); 246 bufp = hosts = mystrdup(var_proxy_interfaces); 247 while ((host = mystrtok(&bufp, sep)) != 0) 248 if (inet_addr_host(addr_list, host) == 0) 249 msg_fatal("config variable %s: host not found: %s", 250 VAR_PROXY_INTERFACES, host); 251 myfree(hosts); 252 253 /* 254 * Weed out duplicate IP addresses. 255 */ 256 inet_addr_list_uniq(addr_list); 257} 258 259/* proxy_inet_addr - is this my proxy internet address */ 260 261int proxy_inet_addr(struct sockaddr * addr) 262{ 263 int i; 264 265 if (*var_proxy_interfaces == 0) 266 return (0); 267 268 if (saved_proxy_list.used == 0) 269 proxy_inet_addr_init(&saved_proxy_list); 270 271 for (i = 0; i < saved_proxy_list.used; i++) 272 if (SOCK_ADDR_EQ_ADDR(addr, saved_proxy_list.addrs + i)) 273 return (1); 274 return (0); 275} 276 277/* proxy_inet_addr_list - return list of addresses */ 278 279INET_ADDR_LIST *proxy_inet_addr_list(void) 280{ 281 if (*var_proxy_interfaces != 0 && saved_proxy_list.used == 0) 282 proxy_inet_addr_init(&saved_proxy_list); 283 284 return (&saved_proxy_list); 285} 286 287#ifdef TEST 288#include <inet_proto.h> 289 290static void inet_addr_list_print(INET_ADDR_LIST *list) 291{ 292 MAI_HOSTADDR_STR hostaddr; 293 struct sockaddr_storage *sa; 294 295 for (sa = list->addrs; sa < list->addrs + list->used; sa++) { 296 SOCKADDR_TO_HOSTADDR(SOCK_ADDR_PTR(sa), SOCK_ADDR_LEN(sa), 297 &hostaddr, (MAI_SERVPORT_STR *) 0, 0); 298 msg_info("%s", hostaddr.buf); 299 } 300} 301 302char *var_inet_interfaces; 303 304int main(int argc, char **argv) 305{ 306 INET_PROTO_INFO *proto_info; 307 INET_ADDR_LIST *list; 308 309 if (argc != 3) 310 msg_fatal("usage: %s protocols interface_list (e.g. \"all all\")", 311 argv[0]); 312 msg_verbose = 10; 313 proto_info = inet_proto_init(argv[0], argv[1]); 314 var_inet_interfaces = argv[2]; 315 list = own_inet_addr_list(); 316 inet_addr_list_print(list); 317 return (0); 318} 319 320#endif 321