5 * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
6 * For copying and distribution information, please see the file
10 #include <mit-copyright.h>
11 #include "mr_server.h"
15 #include <arpa/inet.h>
16 #include <netinet/in.h>
22 EXEC SQL INCLUDE sqlca;
27 extern int dbms_errno, mr_errcode;
29 EXEC SQL BEGIN DECLARE SECTION;
30 extern char stmt_buf[];
31 EXEC SQL END DECLARE SECTION;
33 EXEC SQL WHENEVER SQLERROR DO dbmserr();
36 int prefetch_value(struct query *q, char **argv, client *cl);
37 int check_nfs(int mach_idx, char *name, char *access);
41 /* Setup routine for add_user
43 * Inputs: argv[0] - login
48 * - if argv[1] == UNIQUE_UID then set argv[1] = next(uid)
49 * - if argv[0] == UNIQUE_LOGIN then set argv[0] = "#<uid>"
52 int setup_ausr(struct query *q, char *argv[], client *cl)
55 EXEC SQL BEGIN DECLARE SECTION;
57 EXEC SQL END DECLARE SECTION;
59 if (!strcmp(q->shortname, "uusr") || !strcmp(q->shortname, "uuac"))
63 if (!strcmp(argv[row], UNIQUE_UID) || atoi(argv[row]) == -1)
65 if ((err = set_next_object_id("unix_uid", USERS_TABLE, 1)))
67 EXEC SQL SELECT value INTO :nuid FROM numvalues WHERE name = 'unix_uid';
68 if (sqlca.sqlerrd[2] != 1)
70 sprintf(argv[row], "%d", nuid);
73 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[row]) == -1)
74 sprintf(argv[0], "#%s", argv[row]);
76 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
83 /* setup_dusr - verify that the user is no longer being referenced
84 * and may safely be deleted.
87 int setup_dusr(struct query *q, char *argv[], client *cl)
89 EXEC SQL BEGIN DECLARE SECTION;
91 EXEC SQL END DECLARE SECTION;
95 /* For now, only allow users to be deleted if their status is 0 */
96 EXEC SQL SELECT status INTO :flag FROM users WHERE users_id = :id;
97 if (flag != 0 && flag != 4)
100 EXEC SQL DELETE FROM quota WHERE entity_id = :id AND type = 'USER';
101 EXEC SQL DELETE FROM krbmap WHERE users_id = :id;
102 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
103 WHERE member_id = :id AND member_type = 'USER';
106 EXEC SQL SELECT COUNT(label) INTO :cnt FROM filesys
110 EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
111 WHERE acl_id = :id AND acl_type = 'USER';
114 EXEC SQL SELECT COUNT(name) INTO :cnt FROM servers
115 WHERE acl_id = :id AND acl_type = 'USER';
118 EXEC SQL SELECT COUNT(acl_id) INTO :cnt FROM hostaccess
119 WHERE acl_id = :id AND acl_type = 'USER';
128 /* setup_spop: verify that there is already a valid POP machine_id in the
129 * pop_id field. Also take care of keeping track of the post office usage.
131 int setup_spop(struct query *q, char *argv[], client *cl)
133 EXEC SQL BEGIN DECLARE SECTION;
135 char type[USERS_POTYPE_SIZE];
136 EXEC SQL END DECLARE SECTION;
138 id = *(int *)argv[0];
139 EXEC SQL SELECT potype, pop_id INTO :type, :mid FROM users
140 WHERE users_id = :id;
141 if (sqlca.sqlerrd[2] == 0)
143 EXEC SQL SELECT mach_id INTO :mid FROM machine
144 WHERE mach_id = :mid;
145 if (sqlca.sqlerrd[2] == 0)
147 if (strcmp(strtrim(type), "POP"))
148 set_pop_usage(mid, 1);
153 /* setup_dpob: Take care of keeping track of the post office usage.
155 int setup_dpob(struct query *q, char *argv[], client *cl)
157 EXEC SQL BEGIN DECLARE SECTION;
159 char type[USERS_POTYPE_SIZE];
160 EXEC SQL END DECLARE SECTION;
162 user = *(int *)argv[0];
163 EXEC SQL SELECT potype, pop_id INTO :type, :id FROM users
164 WHERE users_id = :user;
168 if (!strcmp(strtrim(type), "POP"))
169 set_pop_usage(id, -1);
174 /* setup_dmac - verify that the machine is no longer being referenced
175 * and may safely be deleted.
178 int setup_dmac(struct query *q, char *argv[], client *cl)
180 EXEC SQL BEGIN DECLARE SECTION;
182 EXEC SQL END DECLARE SECTION;
184 id = *(int *)argv[0];
186 EXEC SQL SELECT status INTO :flag FROM machine
190 EXEC SQL SELECT COUNT(login) INTO :cnt FROM users
191 WHERE potype = 'POP' AND pop_id = :id;
194 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM serverhosts
198 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM nfsphys
202 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM hostaccess
206 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM printcap
210 EXEC SQL SELECT COUNT(quotaserver) INTO :cnt FROM printcap
211 WHERE quotaserver = :id;
214 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM palladium
218 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM hostalias
223 EXEC SQL DELETE FROM mcmap WHERE mach_id = :id;
230 /* setup_dsnt - verify that the subnet is no longer being referenced
231 * and may safely be deleted.
234 int setup_dsnt(struct query *q, char *argv[], client *cl)
236 EXEC SQL BEGIN DECLARE SECTION;
238 EXEC SQL END DECLARE SECTION;
240 id = *(int *)argv[0];
241 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM machine
249 /* setup_dclu - verify that the cluster is no longer being referenced
250 * and may safely be deleted.
253 int setup_dclu(struct query *q, char *argv[], client *cl)
255 EXEC SQL BEGIN DECLARE SECTION;
257 EXEC SQL END DECLARE SECTION;
259 id = *(int *)argv[0];
260 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM mcmap
264 EXEC SQL SELECT COUNT(clu_id) INTO :cnt FROM svc
274 /* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
275 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
276 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
277 * a -1 there. Remember that this is also used for ulis, with the indexes
278 * at 6 & 7. Also check that the list name does not contain uppercase
279 * characters, control characters, @, or :.
282 static int badlistchars[] = {
283 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
284 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
285 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
286 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* 0 - ? */
287 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
288 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, /* P - _ */
289 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
290 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
291 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
292 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
293 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
294 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
295 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
296 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
297 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
298 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
301 int setup_alis(struct query *q, char *argv[], client *cl)
303 EXEC SQL BEGIN DECLARE SECTION;
305 EXEC SQL END DECLARE SECTION;
309 if (!strcmp(q->shortname, "alis"))
311 else if (!strcmp(q->shortname, "ulis"))
316 EXEC SQL BEGIN DECLARE SECTION;
317 int lid = *(int *)argv[0];
318 EXEC SQL END DECLARE SECTION;
320 if (acl_access_check(lid, cl))
324 for (p = (unsigned char *) argv[idx]; *p; p++)
326 if (badlistchars[*p])
330 if (!strcmp(argv[6 + idx], UNIQUE_GID) || atoi(argv[6 + idx]) == -1)
332 if (atoi(argv[5 + idx]))
334 if ((err = set_next_object_id("gid", LIST_TABLE, 1)))
336 EXEC SQL SELECT value INTO :ngid FROM numvalues
340 sprintf(argv[6 + idx], "%d", ngid);
343 strcpy(argv[6 + idx], "-1");
346 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
353 /* setup_dlis - verify that the list is no longer being referenced
354 * and may safely be deleted.
357 int setup_dlis(struct query *q, char *argv[], client *cl)
360 EXEC SQL BEGIN DECLARE SECTION;
362 EXEC SQL END DECLARE SECTION;
364 id = *(int *)argv[0];
366 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
367 WHERE member_id = :id AND member_type = 'LIST';
371 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
372 WHERE member_id = :id AND member_type = 'LIST';
376 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
381 EXEC SQL SELECT COUNT(label) INTO :cnt FROM filesys WHERE owners = :id;
385 EXEC SQL SELECT COUNT(tag) INTO :cnt FROM capacls WHERE list_id = :id;
389 EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
390 WHERE acl_id = :id AND acl_type = 'LIST' AND list_id != :id;
394 EXEC SQL SELECT COUNT(name) INTO :cnt FROM servers
395 WHERE acl_id = :id AND acl_type = 'LIST';
399 EXEC SQL SELECT COUNT(entity_id) INTO :cnt FROM quota
400 WHERE entity_id = :id AND type = 'GROUP';
404 EXEC SQL SELECT COUNT(acl_id) INTO :cnt FROM hostaccess
405 WHERE acl_id = :id AND acl_type = 'LIST';
409 EXEC SQL SELECT COUNT(class) INTO :cnt FROM zephyr z
410 WHERE z.xmt_type = 'LIST' AND z.xmt_id = :id
411 OR z.sub_type = 'LIST' AND z.sub_id = :id
412 OR z.iws_type = 'LIST' AND z.iws_id = :id
413 OR z.iui_type = 'LIST' AND z.iui_id = :id;
421 /* setup_dsin - verify that the service is no longer being referenced
422 * and may safely be deleted.
425 int setup_dsin(struct query *q, char *argv[], client *cl)
427 EXEC SQL BEGIN DECLARE SECTION;
430 EXEC SQL END DECLARE SECTION;
433 EXEC SQL SELECT COUNT(service) INTO :cnt FROM serverhosts
434 WHERE service = UPPER(:svrname);
438 EXEC SQL SELECT inprogress INTO :ec FROM servers
439 WHERE name = UPPER(:svrname);
449 /* setup_dshi - verify that the service-host is no longer being referenced
450 * and may safely be deleted.
453 int setup_dshi(struct query *q, char *argv[], client *cl)
455 EXEC SQL BEGIN DECLARE SECTION;
458 EXEC SQL END DECLARE SECTION;
461 id = *(int *)argv[1];
463 EXEC SQL SELECT inprogress INTO :ec FROM serverhosts
464 WHERE service = UPPER(:svrname) AND mach_id = :id;
475 ** setup_add_filesys - verify existance of referenced file systems
481 ** argv[5] - rwaccess
487 ** * extract directory prefix from name
488 ** * verify mach_id/dir in nfsphys
489 ** * verify rwaccess in {r, w, R, W}
491 ** Side effect: sets variable _var_phys_id to the ID of the physical
492 ** filesystem (nfsphys_id for NFS, 0 for RVD)
495 ** MR_NFS - specified directory not exported
496 ** MR_FILESYS_ACCESS - invalid filesys access
500 EXEC SQL BEGIN DECLARE SECTION;
502 EXEC SQL END DECLARE SECTION;
504 int setup_afil(struct query *q, char *argv[], client *cl)
508 EXEC SQL BEGIN DECLARE SECTION;
510 char ftype[FILESYS_TYPE_SIZE + 10], *rwaccess;
511 EXEC SQL END DECLARE SECTION;
514 mach_id = *(int *)argv[2];
519 sprintf(ftype, "fs_access_%s", type);
520 EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
521 WHERE name = :ftype AND type = 'TYPE' and trans = :rwaccess;
525 return MR_FILESYS_ACCESS;
527 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
530 if (!strcmp(type, "NFS"))
531 return check_nfs(mach_id, name, rwaccess);
537 /* Verify the arguments, depending on the FStype. Also, if this is an
538 * NFS filesystem, then update any quotas for that filesystem to reflect
542 int setup_ufil(struct query *q, char *argv[], client *cl)
546 EXEC SQL BEGIN DECLARE SECTION;
547 int fid, total, who, ok;
548 char *entity, ftype[FILESYS_TYPE_SIZE + 10], *access;
549 short int total_null;
550 EXEC SQL END DECLARE SECTION;
554 mach_id = *(int *)argv[3];
557 fid = *(int *)argv[0];
561 sprintf(ftype, "fs_access_%s", type);
562 EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
563 WHERE name = :ftype AND type = 'TYPE' AND trans = :access;
567 return MR_FILESYS_ACCESS;
569 EXEC SQL SELECT type INTO :ftype FROM filesys
570 WHERE filsys_id = :fid;
574 if (!strcmp(type, "NFS"))
576 status = check_nfs(mach_id, name, access);
577 EXEC SQL UPDATE quota SET phys_id = :_var_phys_id
578 WHERE filsys_id = :fid;
583 else if (!strcmp(type, "AFS") && strcmp(strtrim(ftype), "AFS")
584 && strcmp(strtrim(ftype), "ERR"))
587 EXEC SQL DELETE FROM quota
588 WHERE type = 'ANY' AND filsys_id = :fid;
589 EXEC SQL SELECT SUM (quota) INTO :total:total_null FROM quota
590 WHERE filsys_id = :fid AND phys_id != 0;
593 if (!total_null && (total != 0))
595 EXEC SQL INSERT INTO quota (quota, filsys_id, phys_id, entity_id,
596 type, modtime, modby, modwith)
597 VALUES (:total, :fid, 0, 0, 'ANY', SYSDATE, :who, :entity);
604 EXEC SQL UPDATE quota SET phys_id = 0 WHERE filsys_id = :fid;
612 /* Find the NFS physical partition that the named directory is on.
613 * This is done by comparing the dir against the mount point of the
614 * partition. To make sure we get the correct match when there is
615 * more than one, we sort the query in reverse order by dir name.
618 int check_nfs(int mach_id, char *name, char *access)
620 EXEC SQL BEGIN DECLARE SECTION;
621 char dir[NFSPHYS_DIR_SIZE];
623 EXEC SQL END DECLARE SECTION;
629 EXEC SQL DECLARE csr101 CURSOR FOR
630 SELECT nfsphys_id, dir FROM nfsphys
635 EXEC SQL OPEN csr101;
640 EXEC SQL FETCH csr101 INTO :_var_phys_id, :dir;
657 EXEC SQL CLOSE csr101;
664 /* setup_dfil: free any quota records and fsgroup info associated with
665 * a filesystem when it is deleted. Also adjust the allocation numbers.
668 int setup_dfil(struct query *q, char **argv, client *cl)
670 EXEC SQL BEGIN DECLARE SECTION;
671 int id, total, phys_id;
673 EXEC SQL END DECLARE SECTION;
675 id = *(int *)argv[0];
676 EXEC SQL SELECT SUM (quota) INTO :total:none FROM quota
677 WHERE filsys_id = :id;
682 /** What if there are multiple phys_id's per f/s? (bad data) **/
683 EXEC SQL SELECT phys_id INTO :phys_id FROM filesys
684 WHERE filsys_id = :id;
685 EXEC SQL UPDATE nfsphys SET allocated = allocated - :total
686 WHERE nfsphys_id = :phys_id;
689 EXEC SQL DELETE FROM quota WHERE filsys_id = :id;
690 EXEC SQL DELETE FROM fsgroup WHERE filsys_id = :id;
691 EXEC SQL DELETE FROM fsgroup WHERE group_id = :id;
698 /* setup_dnfp: check to see that the nfs physical partition does not have
699 * any filesystems assigned to it before allowing it to be deleted.
702 int setup_dnfp(struct query *q, char **argv, client *cl)
704 EXEC SQL BEGIN DECLARE SECTION;
707 EXEC SQL END DECLARE SECTION;
709 id = *(int *)argv[0];
711 EXEC SQL SELECT count(fs.rowid) INTO :cnt FROM filesys fs, nfsphys np
712 WHERE fs.mach_id = :id AND fs.phys_id = np.nfsphys_id
713 AND np.mach_id = :id AND np.dir = :dir;
722 /* setup_dqot: Remove allocation from nfsphys before deleting quota.
723 * argv[0] = filsys_id
724 * argv[1] = type if "update_quota" or "delete_quota"
725 * argv[2 or 1] = users_id or list_id
728 int setup_dqot(struct query *q, char **argv, client *cl)
730 EXEC SQL BEGIN DECLARE SECTION;
731 int quota, fs, id, physid;
733 EXEC SQL END DECLARE SECTION;
735 fs = *(int *)argv[0];
736 if (!strcmp(q->name, "update_quota") || !strcmp(q->name, "delete_quota"))
739 id = *(int *)argv[2];
744 id = *(int *)argv[1];
747 EXEC SQL SELECT quota INTO :quota FROM quota
748 WHERE type = :qtype AND entity_id = :id AND filsys_id = :fs;
749 EXEC SQL SELECT phys_id INTO :physid FROM filesys
750 WHERE filsys_id = :fs;
751 EXEC SQL UPDATE nfsphys SET allocated = allocated - :quota
752 WHERE nfsphys_id = :physid;
761 * This routine fetches an appropriate value from the numvalues table.
762 * It is a little hack to get around the fact that SQL doesn't let you
763 * do something like INSERT INTO table (foo) VALUES (other_table.bar).
765 * It is called from the query table as (*v->pre_rtn)(q, Argv, cl) or
766 * from within a setup_...() routine with the appropriate arguments.
768 * Correct functioning of this routine may depend on the assumption
769 * that this query is an APPEND.
772 int prefetch_value(struct query *q, char **argv, client *cl)
774 EXEC SQL BEGIN DECLARE SECTION;
775 char *name = q->validate->object_id;
777 EXEC SQL END DECLARE SECTION;
778 int status, limit, argc;
780 /* set next object id, limiting it if necessary */
781 if (!strcmp(name, "unix_uid") || !strcmp(name, "gid"))
782 limit = 1; /* So far as I know, this isn't needed. Just CMA. */
785 if ((status = set_next_object_id(name, q->rtable, limit)) != MR_SUCCESS)
788 /* fetch object id */
789 EXEC SQL SELECT value INTO :value FROM numvalues WHERE name = :name;
792 if (sqlca.sqlerrd[2] != 1)
795 argc = q->argc + q->vcnt; /* end of Argv for APPENDs */
796 sprintf(argv[argc], "%d", value);
801 /* prefetch_filesys():
802 * Fetches the phys_id from filesys based on the filsys_id in argv[0].
803 * Appends the filsys_id and the phys_id to the argv so they can be
804 * referenced in an INSERT into a table other than filesys. Also
805 * see comments at prefetch_value().
807 * Assumes the existence of a row where filsys_id = argv[0], since a
808 * filesys label has already been resolved to a filsys_id.
810 int prefetch_filesys(struct query *q, char **argv, client *cl)
812 EXEC SQL BEGIN DECLARE SECTION;
814 EXEC SQL END DECLARE SECTION;
817 fid = *(int *)argv[0];
818 EXEC SQL SELECT phys_id INTO :phid FROM filesys WHERE filsys_id = :fid;
822 argc = q->argc + q->vcnt;
823 sprintf(argv[argc++], "%d", phid);
824 sprintf(argv[argc], "%d", fid);
833 int setup_ahst(struct query *q, char **argv, client *cl)
835 EXEC SQL BEGIN DECLARE SECTION;
836 char *name, oldname[MACHINE_NAME_SIZE], vendor[MACHINE_VENDOR_SIZE];
837 char model[MACHINE_MODEL_SIZE], os[MACHINE_OS_SIZE];
838 int value, id, ssaddr, smask, shigh, slow, cnt;
839 unsigned int saddr, mask, high, low;
840 EXEC SQL END DECLARE SECTION;
844 id = *(int *)argv[0];
846 if (!strcmp(q->shortname, "uhst"))
849 EXEC SQL SELECT name, vendor, model, os
850 INTO :oldname, :vendor, :model, :os
851 FROM machine WHERE mach_id = :id;
856 /* sanity check name: must start with a letter, contain only
857 * letters, numerals, and hyphen, and not end with a hyphen.
859 if (row == 0 || strcasecmp(argv[1], oldname))
867 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
868 (*p == '-' && p[1] == '.'))
875 /* sanity check host vendor: must start with a letter, contain only
876 * letters, numerals, and hyphen, and end with an alphanumeric.
878 if (*argv[row + 1] && (row == 0 || strcasecmp(argv[2], vendor)))
880 char *p = argv[row + 1];
886 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
887 (*p == '-' && p[1] == '.'))
890 if (!isalnum(*(p - 1)))
894 /* sanity check host type: must start with a letter, contain only
895 * letters, numerals, and hyphen, and end with an alphanumeric.
897 if (*argv[row + 2] && (row == 0 || strcasecmp(argv[3], model)))
899 char *p = argv[row + 2];
905 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
906 (*p == '-' && p[1] == '.'))
909 if (!isalnum(*(p - 1)))
913 /* sanity check host os: must start with a letter, contain only
914 * letters, numerals, and hyphen, and end with an hyphen alphanumeric.
916 if (*argv[row + 3] && (row == 0 || strcasecmp(argv[4], os)))
918 char *p = argv[row + 3];
924 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
925 (*p == '-' && p[1] == '.'))
928 if (!isalnum(*(p - 1)))
932 /* check for duplicate name */
934 EXEC SQL SELECT count(mach_id) INTO :cnt FROM hostalias
935 WHERE name = UPPER(:name);
942 if (!strcmp(argv[9 + row], "unassigned"))
944 else if (!strcmp(argv[9 + row], "unique"))
946 if (*(int *)argv[8 + row] == 0)
953 value = ntohl(inet_addr(argv[9 + row]));
962 * an address or unique was specified.
964 id = *(int *)argv[8 + row];
965 EXEC SQL SELECT saddr, mask, high, low INTO :ssaddr, :smask,
966 :shigh, :slow FROM subnet WHERE snet_id = :id;
969 saddr = (unsigned) ssaddr;
970 mask = (unsigned) smask;
971 high = (unsigned) shigh;
972 low = (unsigned) slow;
976 * someone specified an IP address for the host record
978 if ((value & mask) != saddr || value < low || value > high)
981 * run the address argument through inet_addr(). This
982 * has the effect that any out of bounds host addrs will
983 * be converted to a valid host addr. We do this now
984 * so that the uniqueness check works. We should also
985 * link in an inet_addr() that returns an error for
988 addr.s_addr = inet_addr(argv[9 + row]);
989 name = inet_ntoa(addr);
990 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
991 WHERE address = :name;
997 * make IP address is unique. If this a modify request
998 * (row == 1), then we expect one record to exist.
1000 if (row == 0 || (row == 1 && cnt > 1))
1002 if (row == 1 && cnt == 1)
1004 EXEC SQL SELECT mach_id INTO :id FROM machine
1005 WHERE address = :name;
1006 if (id != *(int *)argv[0])
1014 * a "unique" address was specified. Walk through the
1015 * range specified in the network record, return
1016 * error if no room left.
1018 for (id = low; id <= high; id++)
1020 if (((id & 0xff) == 0) || ((id & 0xff) == 255))
1022 addr.s_addr = htonl(id);
1023 name = inet_ntoa(addr);
1024 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
1025 WHERE address = :name;
1037 * we have an address in value. Convert it to a string and store it.
1039 addr.s_addr = htonl(value);
1040 strcpy(argv[9 + row], inet_ntoa(addr));
1043 strcpy(argv[9 + row], "unassigned");
1045 /* status checking */
1046 value = atoi(argv[7 + row]);
1047 if (row == 0 && !(value == 1 || value == 0))
1051 id = *(int *)argv[0];
1052 EXEC SQL SELECT status INTO :cnt FROM machine WHERE mach_id = :id;
1057 EXEC SQL UPDATE machine SET statuschange = SYSDATE
1058 WHERE mach_id = :id;
1063 * If this is an update_host query, we're done.
1069 * For an add_host query, allocate and fill in a new machine id,
1070 * and then insert the creator id.
1072 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
1075 sprintf(argv[q->argc + q->vcnt + 1], "%d", cl->client_id);
1083 int setup_ahal(struct query *q, char **argv, client *cl)
1085 EXEC SQL BEGIN DECLARE SECTION;
1088 EXEC SQL END DECLARE SECTION;
1096 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
1097 (*p == '-' && p[1] == '.'))
1100 if (*(p - 1) == '-')
1103 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine WHERE
1104 name = UPPER(:name);