/************************************************************ ** $Id: mx.c,v 0.5 2003/12/29 16:45:38 bcx Exp bcx $ ** ** Copyright Bryan Costales and Perforce Software, Inc. 2003 ** ** This code is "open source" as defined by version 1.9 of ** the Open Source Definition from: ** ** http://www.opensource.org/docs/definition.php. ** ** Entry points defined in this file: ** ** getmx(): ** Look up MX records for the passed host, and then ** look up the IP addresses of each found host. *************************************************************/ # define EXTERN extern #include "slow.h" char ** getmx(char *host, char **list) { char buf[BUFSIZ]; char *cp; HEADER *hp; QBUF qbuf; int len; int acnt, qdcnt; u_short pref; /* not used */ u_short type; /* not used */ u_long ttl; /* not used */ struct hostent *hostp; char **p, **pp; unsigned char *ep, *up; struct in_addr in; # if HAVE_GETIPNODEBYNAME int err; # endif extern int h_errno; errno = 0; if (host == NULL || *host == '\0') return NULL; (void)strcpy(buf, host); /* * Make sure host ends in a dot to short circuit lookups */ cp = buf + strlen(buf) - 1; if (*cp != '.') *(++cp) = '.'; *(++cp) = '\0'; /* * Make sure host does not begin with a dot. */ cp = buf; if (*cp == '.') ++cp; /* * The trailing dot above speeds up the lookup. */ (void)res_init(); len = res_query(cp, C_IN, T_MX, (u_char *) &qbuf, sizeof(qbuf)); if (len < 0) { (void) fprintf(stderr, "%s: %s(%d): %s: %s\n", Prog, __FILE__, __LINE__, cp, hstrerror(h_errno)); exit(h_errno); } hp = (HEADER *)&qbuf; up = (u_char *)&qbuf + HFIXEDSZ; ep = (u_char *)&qbuf + len; for (qdcnt = ntohs(hp->qdcount); qdcnt--; up += len + QFIXEDSZ) { if ((len = dn_skipname(up, ep)) < 0) { (void) fprintf(stderr, "%s: %s(%d): %s: %s\n", Prog, __FILE__, __LINE__, host, hstrerror(h_errno)); exit(h_errno); } } acnt = ntohs(hp->ancount); while (--acnt >= 0 && up < ep) { if ((len = dn_expand((u_char *)&qbuf, ep, up, (RES_UNC_T) buf, BUFSIZ-1)) < 0) { break; } up += len; GETSHORT(type, up); up += INT16SZ; GETLONG(ttl, up); GETSHORT(len, up); if (type != T_MX) { up += len; continue; } GETSHORT(pref, up); if ((len = dn_expand((u_char *)&qbuf, ep, up, (RES_UNC_T) buf, BUFSIZ-1)) < 0) { break; } up += len; if (is_in_list(buf, list) == FALSE) list = push_list(buf, list, FALSE); # if HAVE_GETIPNODEBYNAME hostp = getipnodebyname(buf, AF_INET, AI_DEFAULT , &err); if (hostp == NULL) continue; if (hostp->h_aliases == NULL) { freehostent(hostp); continue; } # else /* * Okay to fall back to gethostbyname() here * because we are not muti-threading yet. */ hostp = gethostbyname(buf); if (hostp == NULL) { continue; } if (hostp->h_addr_list == NULL) { continue; } # endif for (p = hostp->h_addr_list; *p != 0; p++) { (void) memcpy(&in.s_addr, *p, sizeof (in.s_addr)); (void) sprintf(buf, "%s", inet_ntoa(in)); if (is_in_list(buf, list) == FALSE) list = push_list(buf, list, FALSE); for (pp = hostp->h_aliases; *pp != 0; pp++) { sprintf(buf, "%s", *pp); if (is_in_list(buf, list) == FALSE) list = push_list(buf, list, FALSE); } } # if HAVE_GETIPNODEBYNAME freehostent(hostp); # endif } return list; } /* ** RBL_LOOKUP -- lookup an IP address at an RBL server ** */ int rbl_lookup(char *server, char *ip, int log) { char buf[BUFSIZ]; char **iplist; int ipcnt; char **p; struct hostent *hostp; # if HAVE_GETIPNODEBYNAME int err; # endif extern int h_errno; errno = 0; if (ip == NULL || *ip == '\0') return EINVAL; if (server == NULL || *server == '\0') return EINVAL; iplist = mkargv(ip, '.', log); if (iplist == NULL) return errno; ipcnt = 0; for (p = iplist; *p != NULL; ++p) ++ipcnt; if (ipcnt < 4) return EINVAL; sprintf(buf, "%s.%s.%s.%s.%s", iplist[3], iplist[2], iplist[1], iplist[0], server); # if HAVE_GETIPNODEBYNAME hostp = getipnodebyname(buf, AF_INET, AI_DEFAULT , &err); if (hostp != NULL) { freehostent(hostp); return 0; } return -(err); # else /* * Okay to fall through to here because we don't * need to access the contents of hostp. We only * care if it is NULL or not. Hence, gethostbyname * is thread-save here. */ hostp = gethostbyname(buf); if (hostp == NULL) return -(h_errno); return 0; # endif } PRIMARY_KEY * aliasips(PRIMARY_KEY *list, int *n, PRIMARY_KEY ip) { struct hostent *hp; char *host; char **p; PRIMARY_KEY nip; # if HAVE_GETIPNODEBYADDR int err; # else struct in_addr in; char ipbuf[MAXHOSTNAMELEN]; # endif if (list == NULL) { list = try_alloc(__FILE__, __LINE__, sizeof(PRIMARY_KEY) * 2, TRUE); list[0] = ip; list[1] = NULL; *n = 1; } if (AddIPAliases == FALSE) return list; if (ip == 0) return list; # if HAVE_GETIPNODEBYADDR && HAVE_GETIPNODEBYNAME /* * perform IP aliasing here. */ hp = getipnodebyaddr(&ip, INADDRSZ, AF_INET, &err); # else (void) memcpy(&in.s_addr, ((char *)(&ip)), sizeof(in.s_addr)); (void) sprintf(ipbuf, "%s", inet_ntoa(in)); hp = gethostbyaddr(ipbuf, strlen(ipbuf), AF_INET); # endif if (hp == NULL) return list; if (hp->h_name == NULL) { # if HAVE_GETIPNODEBYADDR && HAVE_GETIPNODEBYNAME freehostent(hp); # endif return list; } host = try_strdup(__FILE__, __LINE__, hp->h_name, TRUE); # if HAVE_GETIPNODEBYADDR && HAVE_GETIPNODEBYNAME freehostent(hp); hp = getipnodebyname(host, AF_INET, AI_DEFAULT , &err); # else hp = gethostbyname(host); # endif (void)free(host); if (hp == NULL) return list; if (hp->h_aliases == NULL) { # if HAVE_GETIPNODEBYADDR && HAVE_GETIPNODEBYNAME freehostent(hp); # endif return list; } for (p = hp->h_aliases; *p != NULL; p++) { nip = inet_network(*p); if ((int)nip == -1) continue; list = try_realloc(__FILE__, __LINE__, list, sizeof(PRIMARY_KEY) * (*n + 2), TRUE); list[*n] = nip; ++(*n); list[*n] = NULL; } # if HAVE_GETIPNODEBYADDR && HAVE_GETIPNODEBYNAME freehostent(hp); # endif return list; }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#5 | 4222 | bryan_costales |
Massive rewrite to speed up the database writes. Using a single database now with duplicate keys where the keys are the IP numbers. Added a purge command and removed the garbage command. Fixed some leaking memory bugs and properly closed the database in a few places were it was not properly closed. Updated the docs to reflect this and bumped both the database version and release number. Running on a FreeBSD 3.x machine and a Solaris 9 machine. |
||
#4 | 4052 | bryan_costales |
Implimented: whitelisting AddMXHost for MX servers that lie Converted to thread safe DNS routines garbage collection RunAsUser and RunAsGroup for root startups rebuild the database summarize by IP number Finished all documentation. Moved release from alpha to beta |
||
#3 | 3998 | bryan_costales |
Brought the whole distribution up to V0.9 Added a huge abount of documentation. Added slowedit find Created startup scripts to launch for testing Fixed numerous bugs. Fixed a few portablity issues. Installed hooks for whitelisting and IP aliases. |
||
#2 | 3957 | bryan_costales |
Added rbl lookup support and testing for same. Folded in support for smfi_stop(). Added lots of slowedit commands Fixed a serious bug in MX lookups. Added to documentation. |
||
#1 | 3838 | bryan_costales |
This is pre-release 0.5 (rcs numbering) which includes: The milter source files and Makefile A regressive testing subdirectory with Makefile and /bin/sh scripts. A patches subdirectory with a patch file for V8.13 sendmail All have been compiled and tested on a 64bit Sun Solaris 9 machine. |