1 /* $NetBSD: own_inet_addr.c,v 1.1.1.1 2009/06/23 10:08:47 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 * If we are listening on all interfaces (default), ask the system what 99 * the interfaces are. 100 */ 101 if (strcmp(var_inet_interfaces, INET_INTERFACES_ALL) == 0) { 102 if (inet_addr_local(addr_list, mask_list, 103 inet_proto_info()->ai_family_list) == 0) 104 msg_fatal("could not find any active network interfaces"); 105 } 106 107 /* 108 * Select all loopback interfaces from the system's available interface 109 * list. 110 */ 111 else if (strcmp(var_inet_interfaces, INET_INTERFACES_LOCAL) == 0) { 112 inet_addr_list_init(&local_addrs); 113 inet_addr_list_init(&local_masks); 114 if (inet_addr_local(&local_addrs, &local_masks, 115 inet_proto_info()->ai_family_list) == 0) 116 msg_fatal("could not find any active network interfaces"); 117 for (sa = local_addrs.addrs, ma = local_masks.addrs; 118 sa < local_addrs.addrs + local_addrs.used; sa++, ma++) { 119 if (sock_addr_in_loopback(SOCK_ADDR_PTR(sa))) { 120 inet_addr_list_append(addr_list, SOCK_ADDR_PTR(sa)); 121 inet_addr_list_append(mask_list, SOCK_ADDR_PTR(ma)); 122 } 123 } 124 inet_addr_list_free(&local_addrs); 125 inet_addr_list_free(&local_masks); 126 } 127 128 /* 129 * If we are supposed to be listening only on specific interface 130 * addresses (virtual hosting), look up the addresses of those 131 * interfaces. 132 */ 133 else { 134 bufp = hosts = mystrdup(var_inet_interfaces); 135 while ((host = mystrtok(&bufp, sep)) != 0) 136 if (inet_addr_host(addr_list, host) == 0) 137 msg_fatal("config variable %s: host not found: %s", 138 VAR_INET_INTERFACES, host); 139 myfree(hosts); 140 141 /* 142 * Weed out duplicate IP addresses. Duplicates happen when the same 143 * IP address is listed under multiple hostnames. If we don't weed 144 * out duplicates, Postfix can suddenly stop working after the DNS is 145 * changed. 146 */ 147 inet_addr_list_uniq(addr_list); 148 149 /* 150 * Find out the netmask for each virtual interface, by looking it up 151 * among all the local interfaces. 152 */ 153 inet_addr_list_init(&local_addrs); 154 inet_addr_list_init(&local_masks); 155 if (inet_addr_local(&local_addrs, &local_masks, 156 inet_proto_info()->ai_family_list) == 0) 157 msg_fatal("could not find any active network interfaces"); 158 for (nvirtual = 0; nvirtual < addr_list->used; nvirtual++) { 159 for (nlocal = 0; /* see below */ ; nlocal++) { 160 if (nlocal >= local_addrs.used) { 161 SOCKADDR_TO_HOSTADDR( 162 SOCK_ADDR_PTR(addr_list->addrs + nvirtual), 163 SOCK_ADDR_LEN(addr_list->addrs + nvirtual), 164 &hostaddr, (MAI_SERVPORT_STR *) 0, 0); 165 msg_fatal("parameter %s: no local interface found for %s", 166 VAR_INET_INTERFACES, hostaddr.buf); 167 } 168 if (SOCK_ADDR_EQ_ADDR(addr_list->addrs + nvirtual, 169 local_addrs.addrs + nlocal)) { 170 inet_addr_list_append(mask_list, 171 SOCK_ADDR_PTR(local_masks.addrs + nlocal)); 172 break; 173 } 174 } 175 } 176 inet_addr_list_free(&local_addrs); 177 inet_addr_list_free(&local_masks); 178 } 179 } 180 181 /* own_inet_addr - is this my own internet address */ 182 183 int own_inet_addr(struct sockaddr * addr) 184 { 185 int i; 186 187 if (saved_addr_list.used == 0) 188 own_inet_addr_init(&saved_addr_list, &saved_mask_list); 189 190 for (i = 0; i < saved_addr_list.used; i++) 191 if (SOCK_ADDR_EQ_ADDR(addr, saved_addr_list.addrs + i)) 192 return (1); 193 return (0); 194 } 195 196 /* own_inet_addr_list - return list of addresses */ 197 198 INET_ADDR_LIST *own_inet_addr_list(void) 199 { 200 if (saved_addr_list.used == 0) 201 own_inet_addr_init(&saved_addr_list, &saved_mask_list); 202 203 return (&saved_addr_list); 204 } 205 206 /* own_inet_mask_list - return list of addresses */ 207 208 INET_ADDR_LIST *own_inet_mask_list(void) 209 { 210 if (saved_addr_list.used == 0) 211 own_inet_addr_init(&saved_addr_list, &saved_mask_list); 212 213 return (&saved_mask_list); 214 } 215 216 /* proxy_inet_addr_init - initialize my proxy interface list */ 217 218 static void proxy_inet_addr_init(INET_ADDR_LIST *addr_list) 219 { 220 char *hosts; 221 char *host; 222 const char *sep = " \t,"; 223 char *bufp; 224 225 /* 226 * Parse the proxy_interfaces parameter, and expand any symbolic 227 * hostnames into IP addresses. 228 */ 229 inet_addr_list_init(addr_list); 230 bufp = hosts = mystrdup(var_proxy_interfaces); 231 while ((host = mystrtok(&bufp, sep)) != 0) 232 if (inet_addr_host(addr_list, host) == 0) 233 msg_fatal("config variable %s: host not found: %s", 234 VAR_PROXY_INTERFACES, host); 235 myfree(hosts); 236 237 /* 238 * Weed out duplicate IP addresses. 239 */ 240 inet_addr_list_uniq(addr_list); 241 } 242 243 /* proxy_inet_addr - is this my proxy internet address */ 244 245 int proxy_inet_addr(struct sockaddr * addr) 246 { 247 int i; 248 249 if (*var_proxy_interfaces == 0) 250 return (0); 251 252 if (saved_proxy_list.used == 0) 253 proxy_inet_addr_init(&saved_proxy_list); 254 255 for (i = 0; i < saved_proxy_list.used; i++) 256 if (SOCK_ADDR_EQ_ADDR(addr, saved_proxy_list.addrs + i)) 257 return (1); 258 return (0); 259 } 260 261 /* proxy_inet_addr_list - return list of addresses */ 262 263 INET_ADDR_LIST *proxy_inet_addr_list(void) 264 { 265 if (*var_proxy_interfaces != 0 && saved_proxy_list.used == 0) 266 proxy_inet_addr_init(&saved_proxy_list); 267 268 return (&saved_proxy_list); 269 } 270 271 #ifdef TEST 272 #include <inet_proto.h> 273 274 static void inet_addr_list_print(INET_ADDR_LIST *list) 275 { 276 MAI_HOSTADDR_STR hostaddr; 277 struct sockaddr_storage *sa; 278 279 for (sa = list->addrs; sa < list->addrs + list->used; sa++) { 280 SOCKADDR_TO_HOSTADDR(SOCK_ADDR_PTR(sa), SOCK_ADDR_LEN(sa), 281 &hostaddr, (MAI_SERVPORT_STR *) 0, 0); 282 msg_info("%s", hostaddr.buf); 283 } 284 } 285 286 char *var_inet_interfaces; 287 288 int main(int argc, char **argv) 289 { 290 INET_PROTO_INFO *proto_info; 291 INET_ADDR_LIST *list; 292 293 if (argc != 3) 294 msg_fatal("usage: %s protocols interface_list (e.g. \"all all\")", 295 argv[0]); 296 msg_verbose = 10; 297 proto_info = inet_proto_init(argv[0], argv[1]); 298 var_inet_interfaces = argv[2]; 299 list = own_inet_addr_list(); 300 inet_addr_list_print(list); 301 return (0); 302 } 303 304 #endif 305