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