/* $Id$ * * This generates the dhcpd.conf.print and associated files. * * Copyright (C) 1992-1998 by the Massachusetts Institute of Technology. * For copying and distribution information, please see the file * . */ #include #include #include #include #include #include #include #include #include "util.h" #define MACHINE_CHWADDR_SIZE 18 EXEC SQL INCLUDE sqlca; RCSID("$Header$"); char *whoami = "dhcp.gen"; char *db = "moira/moira"; void hwcolonify(char *from, char *to); void sqlerr(void); int main(int argc, char **argv) { EXEC SQL BEGIN DECLARE SECTION; char name[MACHINE_NAME_SIZE], hwaddr[MACHINE_HWADDR_SIZE]; char chwaddr[MACHINE_CHWADDR_SIZE]; char ohwaddr[MACHINE_HWADDR_SIZE], hwtype[PRINTERS_HWTYPE_SIZE]; char addr[MACHINE_ADDRESS_SIZE], location[PRINTERS_LOCATION_SIZE]; char contact[PRINTERS_CONTACT_SIZE], logaddr[MACHINE_ADDRESS_SIZE]; char modtime[PRINTERS_MODTIME_SIZE], type[PRINTERS_TYPE_SIZE]; char *unixtime_fmt = UNIXTIME_FMT; char host[MACHINE_ADDRESS_SIZE], types[SERVERHOSTS_VALUE3_SIZE]; int mid, alcount; EXEC SQL END DECLARE SECTION; char shortname[MACHINE_NAME_SIZE], net[MACHINE_ADDRESS_SIZE]; char filename[MAXPATHLEN]; struct { char types[SERVERHOSTS_VALUE3_SIZE]; char host[MACHINE_ADDRESS_SIZE]; } *allowlist; char *p, *q; int i, allows, typelen; TARFILE *tf; FILE *out; time_t now = time(NULL); EXEC SQL CONNECT :db; EXEC SQL WHENEVER SQLERROR DO sqlerr(); if (argc != 2) { fprintf(stderr, "usage: %s [outfile]\n", argv[0]); exit(MR_ARGS); } /* Get print spoolers for allow lists. */ EXEC SQL SELECT COUNT(service) INTO :alcount FROM serverhosts sh, machine m WHERE (sh.service = 'PRINT' OR sh.service = 'CUPS-PRINT') AND sh.mach_id = m.mach_id AND m.status = 1 AND m.address != 'unassigned'; allowlist = malloc(alcount * sizeof(*allowlist)); EXEC SQL DECLARE csr_spool CURSOR FOR SELECT m.address, sh.value3 FROM machine m, serverhosts sh WHERE m.mach_id = sh.mach_id AND (sh.service = 'PRINT' OR sh.service = 'CUPS-PRINT') AND m.status = 1 AND m.address != 'unassigned'; EXEC SQL OPEN csr_spool; for (i = 0; i < alcount; i++) { EXEC SQL FETCH csr_spool INTO :host, :types; if (sqlca.sqlcode) sqlerr(); strcpy(allowlist[i].host, strtrim(host)); strcpy(allowlist[i].types, strtrim(types)); } EXEC SQL CLOSE csr_spool; /* Now build the tar file. */ tf = tarfile_open(argv[1]); /* Build dhcpd.conf.print */ out = tarfile_start(tf, "/var/boot/dhcpd.conf.print", 0755, 0, 0, "root", "root", now); ohwaddr[0] = '\0'; EXEC SQL DECLARE csr_boot CURSOR FOR SELECT LOWER(m.name), m.hwaddr, m.address, m2.address, pr.location, pr.contact, pr.hwtype FROM printers pr, machine m, machine m2 WHERE pr.type != 'ALIAS' AND pr.mach_id != 0 AND pr.mach_id = m.mach_id AND pr.loghost = m2.mach_id ORDER BY m.hwaddr; EXEC SQL OPEN csr_boot; while (1) { EXEC SQL FETCH csr_boot INTO :name, :hwaddr, :addr, :logaddr, :location, :contact, :hwtype; if (sqlca.sqlcode) break; strtrim(hwaddr); if (!*hwaddr || !strcasecmp(hwaddr, "unknown")) continue; if (!strcmp(hwaddr, ohwaddr)) { fprintf(stderr, "Ignoring duplicate hwaddr %s\n", hwaddr); continue; } strcpy(ohwaddr, hwaddr); hwcolonify(hwaddr, chwaddr); strtrim(name); strtrim(addr); strtrim(logaddr); strtrim(location); strtrim(contact); strtrim(hwtype); strcpy(shortname, name); if ((p = strchr(shortname, '.'))) *p = '\0'; if ((p = strchr(addr, '.')) && (q = strchr(++p, '.'))) { strncpy(net, p, q - p); net[q - p] = '\0'; } else continue; fprintf(out, "# %s: %s\n# contact: %s\nhost %s {\n\t" "hardware ethernet %s;\n\tfixed-address %s;\n", shortname, location, contact, name, chwaddr, addr); if (strlen(logaddr) != 0) fprintf(out, "\toption log-servers %s;\n", logaddr); if (!strncmp(hwtype, "HP", 2)) fprintf(out, "\toption option-144 \"/hp/%s\";\n", shortname); fprintf(out, "}\n\n"); } EXEC SQL CLOSE csr_boot; tarfile_end(tf); /* Now generate /var/boot/hp/ files */ EXEC SQL DECLARE csr_boot2 CURSOR FOR SELECT LOWER(m.name), m.hwaddr, m2.address, m3.address, pr.type, pr.location, pr.contact, TO_CHAR(pr.modtime, :unixtime_fmt) FROM printers pr, machine m, machine m2, machine m3 WHERE pr.hwtype LIKE 'HP%' AND pr.mach_id != 0 AND pr.mach_id = m.mach_id AND pr.rm = m2.mach_id AND pr.loghost = m3.mach_id AND pr.type != 'ALIAS'; EXEC SQL OPEN csr_boot2; while (1) { EXEC SQL FETCH csr_boot2 INTO :name, :hwaddr, :addr, :logaddr, :type, :location, :contact, :modtime; if (sqlca.sqlcode) break; strtrim(hwaddr); if (!*hwaddr || !strcasecmp(hwaddr, "unknown")) continue; strtrim(name); strtrim(addr); strtrim(logaddr); strtrim(type); strtrim(location); strtrim(contact); strcpy(shortname, name); if ((p = strchr(shortname, '.'))) *p = '\0'; /* We create it as foo.new so dhcp.sh can append the passwords * and other data and rename it. */ sprintf(filename, "/var/boot/hp/%s.new", shortname); out = tarfile_start(tf, filename, 0755, 0, 0, "root", "root", unixtime(modtime)); fprintf(out, "name: %s\nlocation: %s\ncontact: %s\n\n", shortname, *location ? location : "unknown", *contact ? contact : "unknown"); if (*logaddr) fprintf(out, "trap-dest: %s\nallow: %s\n", logaddr, logaddr); fprintf(out, "allow: %s\n", addr); typelen = strlen(type); for (i = allows = 0; i < alcount && allows < 9; i++) { char *p; /* Don't list the spoolhost twice. */ if (!strcmp(allowlist[i].host, addr)) continue; p = strstr(allowlist[i].types, type); if (!p) continue; /* Make sure the match was real, and not just because one type * is a substring of another type. */ if (p != allowlist[i].types && *(p - 1) != ',' && *(p - 1) != ' ') continue; p += typelen; if (*p && *p != ',' && *p != ' ') continue; fprintf(out, "allow: %s\n", allowlist[i].host); allows++; } /* Rest of data is same for all printers and is appended from a * a file on the boot server. */ tarfile_end(tf); } tarfile_close(tf); exit(MR_SUCCESS); } void hwcolonify(char *from, char *to) { int f = 0, t = 0; int mod = 2; for (f = 0 ; f < MACHINE_HWADDR_SIZE - 1 ; ) { to[t++] = from[f++]; if (f % mod == 0) to[t++] = ':'; } if (f % mod == 0) t--; to[t] = '\0'; } void sqlerr(void) { db_error(sqlca.sqlcode); }