*** db.c.orig Mon Nov 11 12:44:28 1996 --- db.c Mon Feb 17 07:42:48 1997 *************** *** 1,6 **** --- 1,8 ---- /* * Copyright 1988 by Rayan S. Zachariassen, all rights reserved. * This will be free software, but only when it is finished. + * + * 'longestmatch' driver kissg@sztaki.hu 970209 */ /* *************** *** 138,143 **** --- 140,146 ---- /* drivers */ static struct conscell *find_domain __((struct conscell *(*lookupfn)(), struct search_info *sip)); static struct conscell *find_nodot_domain __((struct conscell *(*lookupfn)(), struct search_info *sip)); + static struct conscell *find_longest_match __((struct conscell *(*lookupfn)(), struct search_info *sip)); /* others.. */ static void cacheflush __((struct db_info *dbip)); extern struct conscell *readchunk __((char *file, long offset)); *************** *** 179,184 **** --- 182,189 ---- proto_config.driver = find_nodot_domain; else if (strcmp(optarg, "pathalias") == 0) proto_config.driver = find_domain; + else if (strcmp(optarg, "longestmatch") == 0) + proto_config.driver = find_longest_match; else ++errflg; break; *************** *** 940,945 **** --- 945,1029 ---- } /* + * Searching the longest match. + * + * The lookup sequence for foo.bar.edu is: + * + * foo.bar.edu + * .bar.edu + * .edu + * . + * + * The lookup sequence for 1.2.3.13 is: + * + * 1.2.3.13/32 + * 1.2.3.12/31 + * 1.2.3.12/30 + * 1.2.3.8/29 + * 1.2.3.0/28 + * ... + * 1.0.0.0/8 + * ... + * 0.0.0.0/1 + * 0.0.0.0/0 + */ + + static struct conscell * + find_longest_match(lookupfn, sip) + struct conscell *(*lookupfn)(); + struct search_info *sip; + { + register u_char *cp; + struct conscell *l; + u_char buf[BUFSIZ], *realkey; + unsigned int oct1,oct2,oct3,oct4; + + if (sscanf((char*)(sip->key[0]=='[' ? sip->key+1 : sip->key), + "%3u.%3u.%3u.%3u", + &oct1,&oct2,&oct3,&oct4) == 4) { /* IP address with optional [] */ + unsigned int h_addr,h_mask; + int prefix; + h_addr=(((oct1&255)<<8|oct2&255)<<8|oct3&255)<<8|oct4&255; + sip->key=buf; + for (prefix=32, h_mask=0xffffffffL; + prefix>=0; --prefix, h_mask<<=1) { + sprintf((char*)buf,"%u.%u.%u.%u/%d", + (h_addr&h_mask) >> 24 & 255, + (h_addr&h_mask) >> 16 & 255, + (h_addr&h_mask) >> 8 & 255, + (h_addr&h_mask) & 255, + prefix); + if ((l = (*lookupfn)(sip)) != NULL) + return l; + } + } + else { /* domain name */ + /* check the key as given */ + if ((l = (*lookupfn)(sip)) != NULL) + return l; + realkey = sip->key; + /* iterate over the superdomains of the key */ + for (cp = realkey; *cp;) { + while (*cp && *cp != '.') + ++cp; + while (*cp == '.') + ++cp; + if (*(cp-1) == '.') { + sip->key = cp-1; + if ((l = (*lookupfn)(sip)) != NULL) + return l; + } + } + /* Still failed ? Try to look for "." */ + sip->key = "."; + if ((l = (*lookupfn)(sip)) != NULL) + return l; + } + + return NULL; + } + + /* * This routine is good for looking up foo.bar.edu in e.g. a gateway list. * It is typically used for pathalias database lookup. * *************** *** 949,954 **** --- 1033,1039 ---- * .bar.edu * .edu * .foo.bar.edu + * . */ static struct conscell *