int main(int argc, char **argv) { INET_ADDR_LIST list; INET_PROTO_INFO *proto_info; proto_info = inet_proto_init(argv[0], INET_PROTO_NAME_ALL); inet_addr_list_init(&list); while (--argc && *++argv) if (inet_addr_host(&list, *argv) == 0) msg_fatal("host not found: %s", *argv); msg_info("list before sort/uniq"); inet_addr_list_print(&list); inet_addr_list_uniq(&list); msg_info("list after sort/uniq"); inet_addr_list_print(&list); inet_addr_list_free(&list); return (0); }
static void proxy_inet_addr_init(INET_ADDR_LIST *addr_list) { char *hosts; char *host; const char *sep = " \t,"; char *bufp; /* * Parse the proxy_interfaces parameter, and expand any symbolic * hostnames into IP addresses. */ inet_addr_list_init(addr_list); bufp = hosts = mystrdup(var_proxy_interfaces); while ((host = mystrtok(&bufp, sep)) != 0) if (inet_addr_host(addr_list, host) == 0) msg_fatal("config variable %s: host not found: %s", VAR_PROXY_INTERFACES, host); myfree(hosts); /* * Weed out duplicate IP addresses. */ inet_addr_list_uniq(addr_list); }
static void own_inet_addr_init(INET_ADDR_LIST *addr_list, INET_ADDR_LIST *mask_list) { INET_ADDR_LIST local_addrs; INET_ADDR_LIST local_masks; char *hosts; char *host; const char *sep = " \t,"; char *bufp; int nvirtual; int nlocal; MAI_HOSTADDR_STR hostaddr; struct sockaddr_storage *sa; struct sockaddr_storage *ma; inet_addr_list_init(addr_list); inet_addr_list_init(mask_list); /* * If we are listening on all interfaces (default), ask the system what * the interfaces are. */ if (strcmp(var_inet_interfaces, INET_INTERFACES_ALL) == 0) { if (inet_addr_local(addr_list, mask_list, inet_proto_info()->ai_family_list) == 0) msg_fatal("could not find any active network interfaces"); } /* * Select all loopback interfaces from the system's available interface * list. */ else if (strcmp(var_inet_interfaces, INET_INTERFACES_LOCAL) == 0) { inet_addr_list_init(&local_addrs); inet_addr_list_init(&local_masks); if (inet_addr_local(&local_addrs, &local_masks, inet_proto_info()->ai_family_list) == 0) msg_fatal("could not find any active network interfaces"); for (sa = local_addrs.addrs, ma = local_masks.addrs; sa < local_addrs.addrs + local_addrs.used; sa++, ma++) { if (sock_addr_in_loopback(SOCK_ADDR_PTR(sa))) { inet_addr_list_append(addr_list, SOCK_ADDR_PTR(sa)); inet_addr_list_append(mask_list, SOCK_ADDR_PTR(ma)); } } inet_addr_list_free(&local_addrs); inet_addr_list_free(&local_masks); } /* * If we are supposed to be listening only on specific interface * addresses (virtual hosting), look up the addresses of those * interfaces. */ else { bufp = hosts = mystrdup(var_inet_interfaces); while ((host = mystrtok(&bufp, sep)) != 0) if (inet_addr_host(addr_list, host) == 0) msg_fatal("config variable %s: host not found: %s", VAR_INET_INTERFACES, host); myfree(hosts); /* * Weed out duplicate IP addresses. Duplicates happen when the same * IP address is listed under multiple hostnames. If we don't weed * out duplicates, Postfix can suddenly stop working after the DNS is * changed. */ inet_addr_list_uniq(addr_list); /* * Find out the netmask for each virtual interface, by looking it up * among all the local interfaces. */ inet_addr_list_init(&local_addrs); inet_addr_list_init(&local_masks); if (inet_addr_local(&local_addrs, &local_masks, inet_proto_info()->ai_family_list) == 0) msg_fatal("could not find any active network interfaces"); for (nvirtual = 0; nvirtual < addr_list->used; nvirtual++) { for (nlocal = 0; /* see below */ ; nlocal++) { if (nlocal >= local_addrs.used) { SOCKADDR_TO_HOSTADDR( SOCK_ADDR_PTR(addr_list->addrs + nvirtual), SOCK_ADDR_LEN(addr_list->addrs + nvirtual), &hostaddr, (MAI_SERVPORT_STR *) 0, 0); msg_fatal("parameter %s: no local interface found for %s", VAR_INET_INTERFACES, hostaddr.buf); } if (SOCK_ADDR_EQ_ADDR(addr_list->addrs + nvirtual, local_addrs.addrs + nlocal)) { inet_addr_list_append(mask_list, SOCK_ADDR_PTR(local_masks.addrs + nlocal)); break; } } } inet_addr_list_free(&local_addrs); inet_addr_list_free(&local_masks); } }
MASTER_SERV *get_master_ent() { VSTRING *buf = vstring_alloc(100); VSTRING *junk = vstring_alloc(100); MASTER_SERV *serv; char *cp; char *name; char *host = 0; char *port = 0; char *transport; int private; int unprivileged; /* passed on to child */ int chroot; /* passed on to child */ char *command; int n; char *bufp; char *atmp; const char *parse_err; static char *saved_interfaces = 0; char *err; if (master_fp == 0) msg_panic("get_master_ent: config file not open"); if (master_disable == 0) msg_panic("get_master_ent: no service disable list"); /* * XXX We cannot change the inet_interfaces setting for a running master * process. Listening sockets are inherited by child processes so that * closing and reopening those sockets in the master does not work. * * Another problem is that library routines still cache results that are * based on the old inet_interfaces setting. It is too much trouble to * recompute everything. * * In order to keep our data structures consistent we ignore changes in * inet_interfaces settings, and issue a warning instead. */ if (saved_interfaces == 0) saved_interfaces = mystrdup(var_inet_interfaces); /* * Skip blank lines and comment lines. */ for (;;) { if (readllines(buf, master_fp, &master_line_last, &master_line) == 0) { vstring_free(buf); vstring_free(junk); return (0); } bufp = vstring_str(buf); if ((cp = mystrtok(&bufp, master_blanks)) == 0) continue; name = cp; transport = get_str_ent(&bufp, "transport type", (char *) 0); vstring_sprintf(junk, "%s/%s", name, transport); if (match_service_match(master_disable, vstring_str(junk)) == 0) break; } /* * Parse one logical line from the configuration file. Initialize service * structure members in order. */ serv = (MASTER_SERV *) mymalloc(sizeof(MASTER_SERV)); serv->next = 0; /* * Flags member. */ serv->flags = 0; /* * All servers busy warning timer. */ serv->busy_warn_time = 0; /* * Service name. Syntax is transport-specific. */ serv->ext_name = mystrdup(name); /* * Transport type: inet (wild-card listen or virtual) or unix. */ #define STR_SAME !strcmp if (STR_SAME(transport, MASTER_XPORT_NAME_INET)) { if (!STR_SAME(saved_interfaces, var_inet_interfaces)) { msg_warn("service %s: ignoring %s change", serv->ext_name, VAR_INET_INTERFACES); msg_warn("to change %s, stop and start Postfix", VAR_INET_INTERFACES); } serv->type = MASTER_SERV_TYPE_INET; atmp = mystrdup(name); if ((parse_err = host_port(atmp, &host, "", &port, (char *) 0)) != 0) fatal_with_context("%s in \"%s\"", parse_err, name); if (*host) { serv->flags |= MASTER_FLAG_INETHOST;/* host:port */ MASTER_INET_ADDRLIST(serv) = (INET_ADDR_LIST *) mymalloc(sizeof(*MASTER_INET_ADDRLIST(serv))); inet_addr_list_init(MASTER_INET_ADDRLIST(serv)); if (inet_addr_host(MASTER_INET_ADDRLIST(serv), host) == 0) fatal_with_context("bad hostname or network address: %s", name); inet_addr_list_uniq(MASTER_INET_ADDRLIST(serv)); serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used; } else { MASTER_INET_ADDRLIST(serv) = strcasecmp(saved_interfaces, INET_INTERFACES_ALL) ? own_inet_addr_list() : /* virtual */ wildcard_inet_addr_list(); /* wild-card */ inet_addr_list_uniq(MASTER_INET_ADDRLIST(serv)); serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used; } MASTER_INET_PORT(serv) = mystrdup(port); for (n = 0; /* see below */ ; n++) { if (n >= MASTER_INET_ADDRLIST(serv)->used) { serv->flags |= MASTER_FLAG_LOCAL_ONLY; break; } if (!sock_addr_in_loopback(SOCK_ADDR_PTR(MASTER_INET_ADDRLIST(serv)->addrs + n))) break; } } else if (STR_SAME(transport, MASTER_XPORT_NAME_UNIX)) { serv->type = MASTER_SERV_TYPE_UNIX; serv->listen_fd_count = 1; serv->flags |= MASTER_FLAG_LOCAL_ONLY; } else if (STR_SAME(transport, MASTER_XPORT_NAME_UXDG)) { serv->type = MASTER_SERV_TYPE_UXDG; serv->listen_fd_count = 1; serv->flags |= MASTER_FLAG_LOCAL_ONLY; } else if (STR_SAME(transport, MASTER_XPORT_NAME_FIFO)) { serv->type = MASTER_SERV_TYPE_FIFO; serv->listen_fd_count = 1; serv->flags |= MASTER_FLAG_LOCAL_ONLY; #ifdef MASTER_SERV_TYPE_PASS } else if (STR_SAME(transport, MASTER_XPORT_NAME_PASS)) { serv->type = MASTER_SERV_TYPE_PASS; serv->listen_fd_count = 1; /* If this is a connection screener, remote clients are likely. */ #endif } else { fatal_with_context("bad transport type: %s", transport); } /* * Service class: public or private. */ private = get_bool_ent(&bufp, "private", "y");