1 1.18 joerg /* $NetBSD: mkalias.c,v 1.18 2011/08/30 21:10:28 joerg Exp $ */ 2 1.1 lukem 3 1.1 lukem /* 4 1.1 lukem * Copyright (c) 1997 Mats O Jansson <moj (at) stacken.kth.se> 5 1.1 lukem * All rights reserved. 6 1.1 lukem * 7 1.1 lukem * Redistribution and use in source and binary forms, with or without 8 1.1 lukem * modification, are permitted provided that the following conditions 9 1.1 lukem * are met: 10 1.1 lukem * 1. Redistributions of source code must retain the above copyright 11 1.1 lukem * notice, this list of conditions and the following disclaimer. 12 1.1 lukem * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 lukem * notice, this list of conditions and the following disclaimer in the 14 1.1 lukem * documentation and/or other materials provided with the distribution. 15 1.1 lukem * 16 1.1 lukem * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 17 1.1 lukem * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 1.1 lukem * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 1.1 lukem * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 1.1 lukem * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 1.1 lukem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 1.1 lukem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 1.1 lukem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 1.1 lukem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 1.1 lukem * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 1.1 lukem * SUCH DAMAGE. 27 1.1 lukem */ 28 1.1 lukem 29 1.2 lukem #include <sys/cdefs.h> 30 1.4 lukem #ifndef lint 31 1.18 joerg __RCSID("$NetBSD: mkalias.c,v 1.18 2011/08/30 21:10:28 joerg Exp $"); 32 1.1 lukem #endif 33 1.1 lukem 34 1.2 lukem #include <sys/types.h> 35 1.2 lukem #include <sys/param.h> 36 1.2 lukem #include <netinet/in.h> 37 1.2 lukem #include <arpa/nameser.h> 38 1.2 lukem 39 1.1 lukem #include <ctype.h> 40 1.2 lukem #include <err.h> 41 1.1 lukem #include <netdb.h> 42 1.2 lukem #include <resolv.h> 43 1.1 lukem #include <stdio.h> 44 1.6 kleink #include <stdlib.h> 45 1.1 lukem #include <string.h> 46 1.7 kleink #include <time.h> 47 1.1 lukem #include <unistd.h> 48 1.2 lukem 49 1.2 lukem #include <rpc/rpc.h> 50 1.2 lukem 51 1.5 lukem #include "protos.h" 52 1.1 lukem #include "ypdb.h" 53 1.1 lukem #include "ypdef.h" 54 1.1 lukem 55 1.18 joerg static void capitalize(char *, int); 56 1.18 joerg static int check_host(char *, char *, int, int, int); 57 1.18 joerg static void split_address(char *, int, char *, char *); 58 1.18 joerg __dead static void usage(void); 59 1.2 lukem 60 1.18 joerg static void 61 1.10 wiz split_address(char *address, int len, char *user, char *host) 62 1.1 lukem { 63 1.2 lukem char *c, *s, *r; 64 1.1 lukem int i = 0; 65 1.1 lukem 66 1.2 lukem if ((strchr(address, '@')) != NULL) { 67 1.1 lukem 68 1.1 lukem s = user; 69 1.1 lukem 70 1.1 lukem for(c = address; i < len; i++) { 71 1.1 lukem if (*c == '@') { 72 1.1 lukem *s = '\0'; 73 1.1 lukem s = host; 74 1.2 lukem } else 75 1.1 lukem *s++ = *c; 76 1.1 lukem c++; 77 1.1 lukem } 78 1.1 lukem *s = '\0'; 79 1.1 lukem } 80 1.1 lukem 81 1.2 lukem if ((r = strrchr(address, '!')) != NULL) { 82 1.1 lukem 83 1.1 lukem s = host; 84 1.1 lukem 85 1.1 lukem for(c = address; i < len; i++) { 86 1.1 lukem if (c == r) { 87 1.1 lukem *s = '\0'; 88 1.1 lukem s = user; 89 1.2 lukem } else 90 1.1 lukem *s++ = *c; 91 1.1 lukem c++; 92 1.1 lukem } 93 1.1 lukem *s = '\0'; 94 1.1 lukem } 95 1.1 lukem } 96 1.1 lukem 97 1.18 joerg static int 98 1.10 wiz check_host(char *address, char *host, int dflag, int uflag, int Eflag) 99 1.1 lukem { 100 1.14 mrg u_char answer[PACKETSZ]; 101 1.1 lukem int status; 102 1.1 lukem 103 1.2 lukem if ((dflag && strchr(address, '@')) || 104 1.2 lukem (uflag && strchr(address, '!'))) 105 1.2 lukem return(0); 106 1.1 lukem 107 1.1 lukem if ((_res.options & RES_INIT) == 0) 108 1.1 lukem res_init(); 109 1.1 lukem 110 1.1 lukem status = res_search(host, C_IN, T_AAAA, answer, sizeof(answer)); 111 1.1 lukem 112 1.1 lukem if (status == -1) 113 1.1 lukem status = res_search(host, C_IN, T_A, answer, sizeof(answer)); 114 1.1 lukem 115 1.1 lukem if ((status == -1) && Eflag) 116 1.1 lukem status = res_search(host, C_IN, T_MX, answer, sizeof(answer)); 117 1.1 lukem 118 1.1 lukem return(status == -1); 119 1.1 lukem } 120 1.1 lukem 121 1.18 joerg static void 122 1.10 wiz capitalize(char *name, int len) 123 1.1 lukem { 124 1.1 lukem char last = ' '; 125 1.1 lukem char *c; 126 1.1 lukem int i = 0; 127 1.1 lukem 128 1.1 lukem for(c = name; i < len; i++) { 129 1.1 lukem if (*c == '.') last = '.'; 130 1.1 lukem c++; 131 1.1 lukem } 132 1.1 lukem 133 1.1 lukem i = 0; 134 1.1 lukem if (last == '.') { 135 1.1 lukem for(c = name; i < len; i++) { 136 1.2 lukem if (last == '.') 137 1.12 dsl *c = toupper((unsigned char)*c); 138 1.1 lukem last = *c++; 139 1.1 lukem } 140 1.1 lukem } 141 1.1 lukem } 142 1.1 lukem 143 1.1 lukem int 144 1.10 wiz main(int argc, char *argv[]) 145 1.1 lukem { 146 1.1 lukem int eflag = 0; 147 1.1 lukem int dflag = 0; 148 1.1 lukem int nflag = 0; 149 1.1 lukem int sflag = 0; 150 1.1 lukem int uflag = 0; 151 1.1 lukem int vflag = 0; 152 1.1 lukem int Eflag = 0; 153 1.1 lukem int ch; 154 1.1 lukem char *input = NULL; 155 1.1 lukem char *output = NULL; 156 1.1 lukem DBM *db; 157 1.2 lukem datum key, val; 158 1.1 lukem char *slash; 159 1.1 lukem DBM *new_db = NULL; 160 1.15 lukem static const char template[] = "ypdbXXXXXX"; 161 1.15 lukem char db_mapname[MAXPATHLEN], db_outfile[MAXPATHLEN]; 162 1.1 lukem int status; 163 1.2 lukem char user[4096], host[4096]; /* XXX: DB bsize = 4096 in ypdb.c */ 164 1.1 lukem char datestr[11]; 165 1.1 lukem char myname[MAXHOSTNAMELEN]; 166 1.1 lukem 167 1.2 lukem while ((ch = getopt(argc, argv, "Edensuv")) != -1) { 168 1.2 lukem switch(ch) { 169 1.2 lukem case 'd': 170 1.2 lukem dflag++; /* Don't check DNS hostname */ 171 1.2 lukem break; 172 1.2 lukem 173 1.2 lukem case 'e': 174 1.2 lukem eflag++; /* Check hostname */ 175 1.2 lukem break; 176 1.2 lukem 177 1.2 lukem case 'E': 178 1.2 lukem eflag++; /* Check hostname */ 179 1.2 lukem Eflag++; /* .. even check MX records */ 180 1.2 lukem break; 181 1.2 lukem 182 1.2 lukem case 'n': 183 1.2 lukem nflag++; /* Capitalize name parts */ 184 1.2 lukem break; 185 1.2 lukem 186 1.2 lukem case 's': 187 1.2 lukem sflag++; /* Don't know... */ 188 1.2 lukem break; 189 1.2 lukem 190 1.2 lukem case 'u': 191 1.2 lukem uflag++; /* Don't check UUCP hostname */ 192 1.2 lukem break; 193 1.2 lukem 194 1.2 lukem case 'v': 195 1.2 lukem vflag++; /* Verbose */ 196 1.2 lukem break; 197 1.2 lukem 198 1.2 lukem default: 199 1.2 lukem usage(); 200 1.2 lukem } 201 1.1 lukem } 202 1.1 lukem 203 1.2 lukem if (optind == argc) 204 1.2 lukem usage(); 205 1.2 lukem 206 1.2 lukem input = argv[optind++]; 207 1.2 lukem if (optind < argc) 208 1.2 lukem output = argv[optind++]; 209 1.2 lukem if (optind < argc) 210 1.2 lukem usage(); 211 1.1 lukem 212 1.15 lukem db = ypdb_open(input); 213 1.2 lukem if (db == NULL) 214 1.3 lukem err(1, "Unable to open input database `%s'", input); 215 1.1 lukem 216 1.1 lukem if (output != NULL) { 217 1.13 lukem if (strlen(output) + strlen(YPDB_SUFFIX) > 218 1.13 lukem (sizeof(db_outfile) + 1)) 219 1.2 lukem warnx("file name `%s' too long", output); 220 1.1 lukem snprintf(db_outfile, sizeof(db_outfile), 221 1.1 lukem "%s%s", output, YPDB_SUFFIX); 222 1.1 lukem 223 1.1 lukem slash = strrchr(output, '/'); 224 1.1 lukem if (slash != NULL) 225 1.1 lukem slash[1] = 0; /* truncate to dir */ 226 1.1 lukem else 227 1.1 lukem *output = 0; /* elminate */ 228 1.1 lukem 229 1.1 lukem /* note: output is now directory where map goes ! */ 230 1.1 lukem 231 1.15 lukem if (strlen(output) + strlen(template) + strlen(YPDB_SUFFIX) > 232 1.13 lukem (sizeof(db_mapname) - 1)) 233 1.3 lukem errx(1, "Directory name `%s' too long", output); 234 1.1 lukem 235 1.15 lukem snprintf(db_mapname, sizeof(db_mapname), "%s%s", 236 1.15 lukem output, template); 237 1.1 lukem 238 1.15 lukem new_db = ypdb_mktemp(db_mapname); 239 1.2 lukem if (new_db == NULL) 240 1.3 lukem err(1, "Unable to open output database `%s'", 241 1.2 lukem db_outfile); 242 1.1 lukem } 243 1.1 lukem 244 1.1 lukem for (key = ypdb_firstkey(db); 245 1.1 lukem key.dptr != NULL; 246 1.1 lukem key = ypdb_nextkey(db)) { 247 1.1 lukem 248 1.2 lukem val = ypdb_fetch(db, key); 249 1.1 lukem 250 1.2 lukem if (val.dptr == NULL) 251 1.2 lukem continue; /* No value */ 252 1.1 lukem if ((*key.dptr == '@') && (key.dsize == 1)) 253 1.1 lukem continue; /* Sendmail token */ 254 1.1 lukem if (strncmp(key.dptr, "YP_", 3)==0) /* YP token */ 255 1.1 lukem continue; 256 1.2 lukem if (strchr(val.dptr, ',')) /* List... */ 257 1.2 lukem continue; 258 1.2 lukem if (strchr(val.dptr, '|')) /* Pipe... */ 259 1.2 lukem continue; 260 1.1 lukem 261 1.2 lukem if (!((strchr(val.dptr, '@')) || 262 1.2 lukem (strchr(val.dptr, '!')))) 263 1.2 lukem continue; /* Skip local users */ 264 1.1 lukem 265 1.2 lukem split_address(val.dptr, val.dsize, user, host); 266 1.1 lukem 267 1.1 lukem if (eflag && check_host(val.dptr, host, dflag, uflag, Eflag)) { 268 1.2 lukem printf("Invalid host %s in %*.*s:%*.*s\n", host, 269 1.1 lukem key.dsize, key.dsize, key.dptr, 270 1.1 lukem val.dsize, val.dsize, val.dptr); 271 1.1 lukem continue; 272 1.1 lukem } 273 1.1 lukem 274 1.2 lukem if (nflag) 275 1.2 lukem capitalize(key.dptr, key.dsize); 276 1.1 lukem 277 1.1 lukem if (new_db != NULL) { 278 1.1 lukem status = ypdb_store(new_db, val, key, YPDB_INSERT); 279 1.1 lukem if (status != 0) { 280 1.1 lukem printf("%s: problem storing %*.*s %*.*s\n", 281 1.9 cgd getprogname(), 282 1.1 lukem val.dsize, val.dsize, val.dptr, 283 1.1 lukem key.dsize, key.dsize, key.dptr); 284 1.1 lukem } 285 1.1 lukem } 286 1.1 lukem 287 1.1 lukem if (vflag) { 288 1.1 lukem printf("%*.*s --> %*.*s\n", 289 1.1 lukem val.dsize, val.dsize, val.dptr, 290 1.1 lukem key.dsize, key.dsize, key.dptr); 291 1.1 lukem } 292 1.1 lukem 293 1.1 lukem } 294 1.1 lukem 295 1.1 lukem if (new_db != NULL) { 296 1.11 itojun snprintf(datestr, sizeof(datestr), "%010d", (int)time(NULL)); 297 1.16 lukem key.dptr = __UNCONST(YP_LAST_KEY); 298 1.1 lukem key.dsize = strlen(YP_LAST_KEY); 299 1.1 lukem val.dptr = datestr; 300 1.1 lukem val.dsize = strlen(datestr); 301 1.1 lukem status = ypdb_store(new_db, key, val, YPDB_INSERT); 302 1.2 lukem if (status != 0) 303 1.2 lukem warnx("problem storing %*.*s %*.*s", 304 1.1 lukem key.dsize, key.dsize, key.dptr, 305 1.1 lukem val.dsize, val.dsize, val.dptr); 306 1.1 lukem } 307 1.1 lukem 308 1.1 lukem if (new_db != NULL) { 309 1.5 lukem localhostname(myname, sizeof(myname) - 1); 310 1.16 lukem key.dptr = __UNCONST(YP_MASTER_KEY); 311 1.1 lukem key.dsize = strlen(YP_MASTER_KEY); 312 1.1 lukem val.dptr = myname; 313 1.1 lukem val.dsize = strlen(myname); 314 1.1 lukem status = ypdb_store(new_db, key, val, YPDB_INSERT); 315 1.2 lukem if (status != 0) 316 1.2 lukem warnx("problem storing %*.*s %*.*s", 317 1.1 lukem key.dsize, key.dsize, key.dptr, 318 1.1 lukem val.dsize, val.dsize, val.dptr); 319 1.1 lukem } 320 1.1 lukem 321 1.1 lukem ypdb_close(db); 322 1.1 lukem 323 1.1 lukem if (new_db != NULL) { 324 1.1 lukem ypdb_close(new_db); 325 1.2 lukem if (rename(db_mapname, db_outfile) < 0) 326 1.2 lukem err(1, "rename `%s' to `%s' failed", db_mapname, 327 1.1 lukem db_outfile); 328 1.1 lukem } 329 1.1 lukem 330 1.2 lukem exit(0); 331 1.2 lukem } 332 1.2 lukem 333 1.18 joerg static void 334 1.10 wiz usage(void) 335 1.2 lukem { 336 1.2 lukem fprintf(stderr, 337 1.2 lukem "usage: %s [-e|-E [-d] [-u]] [-n] [-v] input [output]\n", 338 1.9 cgd getprogname()); 339 1.2 lukem exit(1); 340 1.1 lukem } 341