]> andersk Git - moira.git/blame_incremental - server/qsetup.pc
Allow hostname to start with a digit in hostname_check, but disallow it
[moira.git] / server / qsetup.pc
... / ...
CommitLineData
1/* $Id$
2 *
3 * Query setup routines
4 *
5 * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
6 * For copying and distribution information, please see the file
7 * <mit-copyright.h>.
8 */
9
10#include <mit-copyright.h>
11#include "mr_server.h"
12#include "query.h"
13#include "qrtn.h"
14
15#include <arpa/inet.h>
16#include <netinet/in.h>
17
18#include <ctype.h>
19#include <stdlib.h>
20#include <string.h>
21
22EXEC SQL INCLUDE sqlca;
23
24RCSID("$Header$");
25
26extern char *whoami;
27extern int dbms_errno, mr_errcode;
28
29EXEC SQL BEGIN DECLARE SECTION;
30extern char stmt_buf[];
31EXEC SQL END DECLARE SECTION;
32
33EXEC SQL WHENEVER SQLERROR DO dbmserr();
34
35
36int prefetch_value(struct query *q, char **argv, client *cl);
37int check_nfs(int mach_idx, char *name, char *access);
38
39/* Setup Routines */
40
41/* Setup routine for add_user
42 *
43 * Inputs: argv[0] - login
44 * argv[1] - uid
45 *
46 * Description:
47 *
48 * - if argv[1] == UNIQUE_UID then set argv[1] = next(uid)
49 * - if argv[0] == UNIQUE_LOGIN then set argv[0] = "#<uid>"
50 */
51
52int setup_ausr(struct query *q, char *argv[], client *cl)
53{
54 int row, err;
55 EXEC SQL BEGIN DECLARE SECTION;
56 int nuid;
57 EXEC SQL END DECLARE SECTION;
58
59 if (!strcmp(q->shortname, "uusr") || !strcmp(q->shortname, "uuac"))
60 row = 2;
61 else
62 row = 1;
63
64 if (strlen(argv[row + 2]) + strlen(argv[row + 3]) +
65 strlen(argv[row + 4]) + 2 > USERS_FULLNAME_SIZE)
66 return MR_ARG_TOO_LONG;
67
68 if (!strcmp(argv[row], UNIQUE_UID) || atoi(argv[row]) == -1)
69 {
70 if ((err = set_next_object_id("unix_uid", USERS_TABLE, 1)))
71 return err;
72 EXEC SQL SELECT value INTO :nuid FROM numvalues WHERE name = 'unix_uid';
73 if (sqlca.sqlerrd[2] != 1)
74 return MR_INTERNAL;
75 sprintf(argv[row], "%d", nuid);
76 }
77
78 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[row]) == -1)
79 sprintf(argv[0], "#%s", argv[row]);
80
81 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
82 return mr_errcode;
83
84 return MR_SUCCESS;
85}
86
87
88/* setup_dusr - verify that the user is no longer being referenced
89 * and may safely be deleted.
90 */
91
92int setup_dusr(struct query *q, char *argv[], client *cl)
93{
94 EXEC SQL BEGIN DECLARE SECTION;
95 int flag, id, cnt;
96 EXEC SQL END DECLARE SECTION;
97
98 id = *(int *)argv[0];
99
100 /* For now, only allow users to be deleted if their status is 0 */
101 EXEC SQL SELECT status INTO :flag FROM users WHERE users_id = :id;
102 if (flag != 0 && flag != 4)
103 return MR_IN_USE;
104
105 EXEC SQL DELETE FROM quota WHERE entity_id = :id AND type = 'USER';
106 EXEC SQL DELETE FROM krbmap WHERE users_id = :id;
107 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
108 WHERE member_id = :id AND member_type = 'USER';
109 if (cnt > 0)
110 return MR_IN_USE;
111 EXEC SQL SELECT COUNT(label) INTO :cnt FROM filesys
112 WHERE owner = :id;
113 if (cnt > 0)
114 return MR_IN_USE;
115 EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
116 WHERE acl_id = :id AND acl_type = 'USER';
117 if (cnt > 0)
118 return MR_IN_USE;
119 EXEC SQL SELECT COUNT(name) INTO :cnt FROM servers
120 WHERE acl_id = :id AND acl_type = 'USER';
121 if (cnt > 0)
122 return MR_IN_USE;
123 EXEC SQL SELECT COUNT(acl_id) INTO :cnt FROM hostaccess
124 WHERE acl_id = :id AND acl_type = 'USER';
125 if (cnt > 0)
126 return MR_IN_USE;
127 if (dbms_errno)
128 return mr_errcode;
129 return MR_SUCCESS;
130}
131
132
133/* setup_spop: verify that there is already a valid POP machine_id in the
134 * pop_id field. Also take care of keeping track of the post office usage.
135 */
136int setup_spop(struct query *q, char *argv[], client *cl)
137{
138 EXEC SQL BEGIN DECLARE SECTION;
139 int id, mid;
140 char type[USERS_POTYPE_SIZE];
141 EXEC SQL END DECLARE SECTION;
142
143 id = *(int *)argv[0];
144 EXEC SQL SELECT potype, pop_id INTO :type, :mid FROM users
145 WHERE users_id = :id;
146 if (sqlca.sqlerrd[2] == 0)
147 return MR_MACHINE;
148 EXEC SQL SELECT mach_id INTO :mid FROM machine
149 WHERE mach_id = :mid;
150 if (sqlca.sqlerrd[2] == 0)
151 return MR_MACHINE;
152 if (strcmp(strtrim(type), "POP"))
153 set_pop_usage(mid, 1);
154 return MR_SUCCESS;
155}
156
157
158/* setup_dpob: Take care of keeping track of the post office usage.
159 */
160int setup_dpob(struct query *q, char *argv[], client *cl)
161{
162 EXEC SQL BEGIN DECLARE SECTION;
163 int id, user;
164 char type[USERS_POTYPE_SIZE];
165 EXEC SQL END DECLARE SECTION;
166
167 user = *(int *)argv[0];
168 EXEC SQL SELECT potype, pop_id INTO :type, :id FROM users
169 WHERE users_id = :user;
170 if (dbms_errno)
171 return mr_errcode;
172
173 if (!strcmp(strtrim(type), "POP"))
174 set_pop_usage(id, -1);
175 return MR_SUCCESS;
176}
177
178
179/* setup_dmac - verify that the machine is no longer being referenced
180 * and may safely be deleted.
181 */
182
183int setup_dmac(struct query *q, char *argv[], client *cl)
184{
185 EXEC SQL BEGIN DECLARE SECTION;
186 int flag, id, cnt;
187 EXEC SQL END DECLARE SECTION;
188
189 id = *(int *)argv[0];
190
191 EXEC SQL SELECT status INTO :flag FROM machine
192 WHERE mach_id = :id;
193 if (flag != 3)
194 return MR_IN_USE;
195 EXEC SQL SELECT COUNT(login) INTO :cnt FROM users
196 WHERE potype = 'POP' AND pop_id = :id;
197 if (cnt > 0)
198 return MR_IN_USE;
199 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM serverhosts
200 WHERE mach_id = :id;
201 if (cnt > 0)
202 return MR_IN_USE;
203 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM nfsphys
204 WHERE mach_id = :id;
205 if (cnt > 0)
206 return MR_IN_USE;
207 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM hostaccess
208 WHERE mach_id = :id;
209 if (cnt > 0)
210 return MR_IN_USE;
211 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM printcap
212 WHERE mach_id = :id;
213 if (cnt > 0)
214 return MR_IN_USE;
215 EXEC SQL SELECT COUNT(quotaserver) INTO :cnt FROM printcap
216 WHERE quotaserver = :id;
217 if (cnt > 0)
218 return MR_IN_USE;
219 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM palladium
220 WHERE mach_id = :id;
221 if (cnt > 0)
222 return MR_IN_USE;
223 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM hostalias
224 WHERE mach_id = :id;
225 if (cnt > 0)
226 return MR_IN_USE;
227
228 EXEC SQL DELETE FROM mcmap WHERE mach_id = :id;
229 if (dbms_errno)
230 return mr_errcode;
231 return MR_SUCCESS;
232}
233
234
235/* setup_dsnt - verify that the subnet is no longer being referenced
236 * and may safely be deleted.
237 */
238
239int setup_dsnt(struct query *q, char *argv[], client *cl)
240{
241 EXEC SQL BEGIN DECLARE SECTION;
242 int id, cnt = 0;
243 EXEC SQL END DECLARE SECTION;
244
245 id = *(int *)argv[0];
246 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM machine
247 WHERE snet_id = :id;
248 if (cnt > 0)
249 return MR_IN_USE;
250 return MR_SUCCESS;
251}
252
253
254/* setup_dclu - verify that the cluster is no longer being referenced
255 * and may safely be deleted.
256 */
257
258int setup_dclu(struct query *q, char *argv[], client *cl)
259{
260 EXEC SQL BEGIN DECLARE SECTION;
261 int id, cnt;
262 EXEC SQL END DECLARE SECTION;
263
264 id = *(int *)argv[0];
265 EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM mcmap
266 WHERE clu_id = :id;
267 if (cnt > 0)
268 return MR_IN_USE;
269 EXEC SQL SELECT COUNT(clu_id) INTO :cnt FROM svc
270 WHERE clu_id = :id;
271 if (cnt > 0)
272 return MR_IN_USE;
273 if (dbms_errno)
274 return mr_errcode;
275 return MR_SUCCESS;
276}
277
278
279/* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
280 * a new gid and put it in argv[6]. Otherwise if argv[6] is UNIQUE_ID but
281 * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
282 * a -1 there. Remember that this is also used for ulis, with the indexes
283 * at 6 & 7. Also check that the list name does not contain uppercase
284 * characters, control characters, @, or :.
285 */
286
287static int badlistchars[] = {
288 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
289 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
290 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
291 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* 0 - ? */
292 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
293 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, /* P - _ */
294 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
295 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
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,
299 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
300 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
301 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
302 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
303 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
304};
305
306int setup_alis(struct query *q, char *argv[], client *cl)
307{
308 EXEC SQL BEGIN DECLARE SECTION;
309 int ngid;
310 EXEC SQL END DECLARE SECTION;
311 unsigned char *p;
312 int idx, err;
313
314 if (!strcmp(q->shortname, "alis"))
315 idx = 0;
316 else if (!strcmp(q->shortname, "ulis"))
317 idx = 1;
318
319 if (idx == 1)
320 {
321 EXEC SQL BEGIN DECLARE SECTION;
322 int lid = *(int *)argv[0];
323 EXEC SQL END DECLARE SECTION;
324
325 if (acl_access_check(lid, cl))
326 return MR_PERM;
327 }
328
329 for (p = (unsigned char *) argv[idx]; *p; p++)
330 {
331 if (badlistchars[*p])
332 return MR_BAD_CHAR;
333 }
334
335 if (!strcmp(argv[6 + idx], UNIQUE_GID) || atoi(argv[6 + idx]) == -1)
336 {
337 if (atoi(argv[5 + idx]))
338 {
339 if ((err = set_next_object_id("gid", LIST_TABLE, 1)))
340 return err;
341 EXEC SQL SELECT value INTO :ngid FROM numvalues
342 WHERE name = 'gid';
343 if (dbms_errno)
344 return mr_errcode;
345 sprintf(argv[6 + idx], "%d", ngid);
346 }
347 else
348 strcpy(argv[6 + idx], "-1");
349 }
350
351 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
352 return mr_errcode;
353
354 return MR_SUCCESS;
355}
356
357
358/* setup_dlis - verify that the list is no longer being referenced
359 * and may safely be deleted.
360 */
361
362int setup_dlis(struct query *q, char *argv[], client *cl)
363{
364 int id;
365 EXEC SQL BEGIN DECLARE SECTION;
366 int cnt;
367 EXEC SQL END DECLARE SECTION;
368
369 id = *(int *)argv[0];
370
371 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
372 WHERE member_id = :id AND member_type = 'LIST';
373 if (cnt > 0)
374 return MR_IN_USE;
375
376 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
377 WHERE member_id = :id AND member_type = 'LIST';
378 if (cnt > 0)
379 return MR_IN_USE;
380
381 EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
382 WHERE list_id = :id;
383 if (cnt > 0)
384 return MR_IN_USE;
385
386 EXEC SQL SELECT COUNT(label) INTO :cnt FROM filesys WHERE owners = :id;
387 if (cnt > 0)
388 return MR_IN_USE;
389
390 EXEC SQL SELECT COUNT(tag) INTO :cnt FROM capacls WHERE list_id = :id;
391 if (cnt > 0)
392 return MR_IN_USE;
393
394 EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
395 WHERE acl_id = :id AND acl_type = 'LIST' AND list_id != :id;
396 if (cnt > 0)
397 return MR_IN_USE;
398
399 EXEC SQL SELECT COUNT(name) INTO :cnt FROM servers
400 WHERE acl_id = :id AND acl_type = 'LIST';
401 if (cnt > 0)
402 return MR_IN_USE;
403
404 EXEC SQL SELECT COUNT(entity_id) INTO :cnt FROM quota
405 WHERE entity_id = :id AND type = 'GROUP';
406 if (cnt > 0)
407 return MR_IN_USE;
408
409 EXEC SQL SELECT COUNT(acl_id) INTO :cnt FROM hostaccess
410 WHERE acl_id = :id AND acl_type = 'LIST';
411 if (cnt > 0)
412 return MR_IN_USE;
413
414 EXEC SQL SELECT COUNT(class) INTO :cnt FROM zephyr z
415 WHERE z.xmt_type = 'LIST' AND z.xmt_id = :id
416 OR z.sub_type = 'LIST' AND z.sub_id = :id
417 OR z.iws_type = 'LIST' AND z.iws_id = :id
418 OR z.iui_type = 'LIST' AND z.iui_id = :id;
419 if (cnt > 0)
420 return MR_IN_USE;
421
422 return MR_SUCCESS;
423}
424
425
426/* setup_dsin - verify that the service is no longer being referenced
427 * and may safely be deleted.
428 */
429
430int setup_dsin(struct query *q, char *argv[], client *cl)
431{
432 EXEC SQL BEGIN DECLARE SECTION;
433 int ec, cnt;
434 char *svrname;
435 EXEC SQL END DECLARE SECTION;
436
437 svrname = argv[0];
438 EXEC SQL SELECT COUNT(service) INTO :cnt FROM serverhosts
439 WHERE service = UPPER(:svrname);
440 if (cnt > 0)
441 return MR_IN_USE;
442
443 EXEC SQL SELECT inprogress INTO :ec FROM servers
444 WHERE name = UPPER(:svrname);
445 if (dbms_errno)
446 return mr_errcode;
447 if (ec)
448 return MR_IN_USE;
449
450 return MR_SUCCESS;
451}
452
453
454/* setup_dshi - verify that the service-host is no longer being referenced
455 * and may safely be deleted.
456 */
457
458int setup_dshi(struct query *q, char *argv[], client *cl)
459{
460 EXEC SQL BEGIN DECLARE SECTION;
461 int id, ec;
462 char *svrname;
463 EXEC SQL END DECLARE SECTION;
464
465 svrname = argv[0];
466 id = *(int *)argv[1];
467
468 EXEC SQL SELECT inprogress INTO :ec FROM serverhosts
469 WHERE service = UPPER(:svrname) AND mach_id = :id;
470 if (dbms_errno)
471 return mr_errcode;
472 if (ec)
473 return MR_IN_USE;
474
475 return MR_SUCCESS;
476}
477
478
479/**
480 ** setup_add_filesys - verify existance of referenced file systems
481 **
482 ** Inputs: Add
483 ** argv[1] - type
484 ** argv[2] - mach_id
485 ** argv[3] - name
486 ** argv[5] - rwaccess
487 **
488 ** Description:
489 ** - for type = RVD:
490 ** * allow anything
491 ** - for type = NFS:
492 ** * extract directory prefix from name
493 ** * verify mach_id/dir in nfsphys
494 ** * verify rwaccess in {r, w, R, W}
495 **
496 ** Side effect: sets variable _var_phys_id to the ID of the physical
497 ** filesystem (nfsphys_id for NFS, 0 for RVD)
498 **
499 ** Errors:
500 ** MR_NFS - specified directory not exported
501 ** MR_FILESYS_ACCESS - invalid filesys access
502 **
503 **/
504
505EXEC SQL BEGIN DECLARE SECTION;
506int _var_phys_id;
507EXEC SQL END DECLARE SECTION;
508
509int setup_afil(struct query *q, char *argv[], client *cl)
510{
511 char *type, *name;
512 int mach_id;
513 EXEC SQL BEGIN DECLARE SECTION;
514 int ok;
515 char ftype[FILESYS_TYPE_SIZE + 10], *rwaccess;
516 EXEC SQL END DECLARE SECTION;
517
518 type = argv[1];
519 mach_id = *(int *)argv[2];
520 name = argv[3];
521 rwaccess = argv[5];
522 _var_phys_id = 0;
523
524 sprintf(ftype, "fs_access_%s", type);
525 EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
526 WHERE name = :ftype AND type = 'TYPE' and trans = :rwaccess;
527 if (dbms_errno)
528 return mr_errcode;
529 if (ok == 0)
530 return MR_FILESYS_ACCESS;
531
532 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
533 return mr_errcode;
534
535 if (!strcmp(type, "NFS"))
536 return check_nfs(mach_id, name, rwaccess);
537
538 return MR_SUCCESS;
539}
540
541
542/* Verify the arguments, depending on the FStype. Also, if this is an
543 * NFS filesystem, then update any quotas for that filesystem to reflect
544 * the new phys_id.
545 */
546
547int setup_ufil(struct query *q, char *argv[], client *cl)
548{
549 int mach_id, status;
550 char *type, *name;
551 EXEC SQL BEGIN DECLARE SECTION;
552 int fid, total, who, ok;
553 char *entity, ftype[FILESYS_TYPE_SIZE + 10], *access;
554 short int total_null;
555 EXEC SQL END DECLARE SECTION;
556
557 _var_phys_id = 0;
558 type = argv[2];
559 mach_id = *(int *)argv[3];
560 name = argv[4];
561 access = argv[6];
562 fid = *(int *)argv[0];
563 who = cl->client_id;
564 entity = cl->entity;
565
566 sprintf(ftype, "fs_access_%s", type);
567 EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
568 WHERE name = :ftype AND type = 'TYPE' AND trans = :access;
569 if (dbms_errno)
570 return mr_errcode;
571 if (ok == 0)
572 return MR_FILESYS_ACCESS;
573
574 EXEC SQL SELECT type INTO :ftype FROM filesys
575 WHERE filsys_id = :fid;
576 if (dbms_errno)
577 return mr_errcode;
578
579 if (!strcmp(type, "NFS"))
580 {
581 status = check_nfs(mach_id, name, access);
582 EXEC SQL UPDATE quota SET phys_id = :_var_phys_id
583 WHERE filsys_id = :fid;
584 if (dbms_errno)
585 return mr_errcode;
586 return status;
587 }
588 else if (!strcmp(type, "AFS") && strcmp(strtrim(ftype), "AFS")
589 && strcmp(strtrim(ftype), "ERR"))
590 {
591 total = 0;
592 EXEC SQL DELETE FROM quota
593 WHERE type = 'ANY' AND filsys_id = :fid;
594 EXEC SQL SELECT SUM (quota) INTO :total:total_null FROM quota
595 WHERE filsys_id = :fid AND phys_id != 0;
596 if (dbms_errno)
597 return mr_errcode;
598 if (!total_null && (total != 0))
599 {
600 EXEC SQL INSERT INTO quota (quota, filsys_id, phys_id, entity_id,
601 type, modtime, modby, modwith)
602 VALUES (:total, :fid, 0, 0, 'ANY', SYSDATE, :who, :entity);
603 if (dbms_errno)
604 return mr_errcode;
605 }
606 }
607 else
608 {
609 EXEC SQL UPDATE quota SET phys_id = 0 WHERE filsys_id = :fid;
610 if (dbms_errno)
611 return mr_errcode;
612 }
613 return MR_SUCCESS;
614}
615
616
617/* Find the NFS physical partition that the named directory is on.
618 * This is done by comparing the dir against the mount point of the
619 * partition. To make sure we get the correct match when there is
620 * more than one, we sort the query in reverse order by dir name.
621 */
622
623int check_nfs(int mach_id, char *name, char *access)
624{
625 EXEC SQL BEGIN DECLARE SECTION;
626 char dir[NFSPHYS_DIR_SIZE];
627 int mid = mach_id;
628 EXEC SQL END DECLARE SECTION;
629 int status;
630 char *cp1;
631 char *cp2;
632
633 status = MR_NFS;
634 EXEC SQL DECLARE csr101 CURSOR FOR
635 SELECT nfsphys_id, dir FROM nfsphys
636 WHERE mach_id = :mid
637 ORDER BY 2 DESC;
638 if (dbms_errno)
639 return mr_errcode;
640 EXEC SQL OPEN csr101;
641 if (dbms_errno)
642 return mr_errcode;
643 while (1)
644 {
645 EXEC SQL FETCH csr101 INTO :_var_phys_id, :dir;
646 if (sqlca.sqlcode)
647 break;
648 cp1 = name;
649 cp2 = strtrim(dir);
650 while (*cp2)
651 {
652 if (*cp1++ != *cp2)
653 break;
654 cp2++;
655 }
656 if (!*cp2)
657 {
658 status = MR_SUCCESS;
659 break;
660 }
661 }
662 EXEC SQL CLOSE csr101;
663 if (dbms_errno)
664 return mr_errcode;
665 return status;
666}
667
668
669/* setup_dfil: free any quota records and fsgroup info associated with
670 * a filesystem when it is deleted. Also adjust the allocation numbers.
671 */
672
673int setup_dfil(struct query *q, char **argv, client *cl)
674{
675 EXEC SQL BEGIN DECLARE SECTION;
676 int id, total, phys_id;
677 short int none;
678 EXEC SQL END DECLARE SECTION;
679
680 id = *(int *)argv[0];
681 EXEC SQL SELECT SUM (quota) INTO :total:none FROM quota
682 WHERE filsys_id = :id;
683
684 if (none)
685 total = 0;
686
687 /** What if there are multiple phys_id's per f/s? (bad data) **/
688 EXEC SQL SELECT phys_id INTO :phys_id FROM filesys
689 WHERE filsys_id = :id;
690 EXEC SQL UPDATE nfsphys SET allocated = allocated - :total
691 WHERE nfsphys_id = :phys_id;
692
693 if (!none)
694 EXEC SQL DELETE FROM quota WHERE filsys_id = :id;
695 EXEC SQL DELETE FROM fsgroup WHERE filsys_id = :id;
696 EXEC SQL DELETE FROM fsgroup WHERE group_id = :id;
697 if (dbms_errno)
698 return mr_errcode;
699 return MR_SUCCESS;
700}
701
702
703/* setup_dnfp: check to see that the nfs physical partition does not have
704 * any filesystems assigned to it before allowing it to be deleted.
705 */
706
707int setup_dnfp(struct query *q, char **argv, client *cl)
708{
709 EXEC SQL BEGIN DECLARE SECTION;
710 int id, cnt;
711 char *dir;
712 EXEC SQL END DECLARE SECTION;
713
714 id = *(int *)argv[0];
715 dir = argv[1];
716 EXEC SQL SELECT count(fs.rowid) INTO :cnt FROM filesys fs, nfsphys np
717 WHERE fs.mach_id = :id AND fs.phys_id = np.nfsphys_id
718 AND np.mach_id = :id AND np.dir = :dir;
719 if (cnt > 0)
720 return MR_IN_USE;
721 if (dbms_errno)
722 return mr_errcode;
723 return MR_SUCCESS;
724}
725
726
727/* setup_dqot: Remove allocation from nfsphys before deleting quota.
728 * argv[0] = filsys_id
729 * argv[1] = type if "update_quota" or "delete_quota"
730 * argv[2 or 1] = users_id or list_id
731 */
732
733int setup_dqot(struct query *q, char **argv, client *cl)
734{
735 EXEC SQL BEGIN DECLARE SECTION;
736 int quota, fs, id, physid;
737 char *qtype;
738 EXEC SQL END DECLARE SECTION;
739
740 fs = *(int *)argv[0];
741 if (!strcmp(q->name, "update_quota") || !strcmp(q->name, "delete_quota"))
742 {
743 qtype = argv[1];
744 id = *(int *)argv[2];
745 }
746 else
747 {
748 qtype = "USER";
749 id = *(int *)argv[1];
750 }
751
752 EXEC SQL SELECT quota INTO :quota FROM quota
753 WHERE type = :qtype AND entity_id = :id AND filsys_id = :fs;
754 EXEC SQL SELECT phys_id INTO :physid FROM filesys
755 WHERE filsys_id = :fs;
756 EXEC SQL UPDATE nfsphys SET allocated = allocated - :quota
757 WHERE nfsphys_id = :physid;
758
759 if (dbms_errno)
760 return mr_errcode;
761 return MR_SUCCESS;
762}
763
764
765/* prefetch_value():
766 * This routine fetches an appropriate value from the numvalues table.
767 * It is a little hack to get around the fact that SQL doesn't let you
768 * do something like INSERT INTO table (foo) VALUES (other_table.bar).
769 *
770 * It is called from the query table as (*v->pre_rtn)(q, Argv, cl) or
771 * from within a setup_...() routine with the appropriate arguments.
772 *
773 * Correct functioning of this routine may depend on the assumption
774 * that this query is an APPEND.
775 */
776
777int prefetch_value(struct query *q, char **argv, client *cl)
778{
779 EXEC SQL BEGIN DECLARE SECTION;
780 char *name = q->validate->object_id;
781 int value;
782 EXEC SQL END DECLARE SECTION;
783 int status, limit, argc;
784
785 /* set next object id, limiting it if necessary */
786 if (!strcmp(name, "unix_uid") || !strcmp(name, "gid"))
787 limit = 1; /* So far as I know, this isn't needed. Just CMA. */
788 else
789 limit = 0;
790 if ((status = set_next_object_id(name, q->rtable, limit)) != MR_SUCCESS)
791 return status;
792
793 /* fetch object id */
794 EXEC SQL SELECT value INTO :value FROM numvalues WHERE name = :name;
795 if (dbms_errno)
796 return mr_errcode;
797 if (sqlca.sqlerrd[2] != 1)
798 return MR_INTERNAL;
799
800 argc = q->argc + q->vcnt; /* end of Argv for APPENDs */
801 sprintf(argv[argc], "%d", value);
802
803 return MR_SUCCESS;
804}
805
806/* prefetch_filesys():
807 * Fetches the phys_id from filesys based on the filsys_id in argv[0].
808 * Appends the filsys_id and the phys_id to the argv so they can be
809 * referenced in an INSERT into a table other than filesys. Also
810 * see comments at prefetch_value().
811 *
812 * Assumes the existence of a row where filsys_id = argv[0], since a
813 * filesys label has already been resolved to a filsys_id.
814 */
815int prefetch_filesys(struct query *q, char **argv, client *cl)
816{
817 EXEC SQL BEGIN DECLARE SECTION;
818 int fid, phid;
819 EXEC SQL END DECLARE SECTION;
820 int argc;
821
822 fid = *(int *)argv[0];
823 EXEC SQL SELECT phys_id INTO :phid FROM filesys WHERE filsys_id = :fid;
824 if (dbms_errno)
825 return mr_errcode;
826
827 argc = q->argc + q->vcnt;
828 sprintf(argv[argc++], "%d", phid);
829 sprintf(argv[argc], "%d", fid);
830
831 return MR_SUCCESS;
832}
833
834
835/* setup_ahst():
836 */
837
838int setup_ahst(struct query *q, char **argv, client *cl)
839{
840 EXEC SQL BEGIN DECLARE SECTION;
841 char *name, oldname[MACHINE_NAME_SIZE], vendor[MACHINE_VENDOR_SIZE];
842 char model[MACHINE_MODEL_SIZE], os[MACHINE_OS_SIZE];
843 int value, id, ssaddr, smask, shigh, slow, cnt;
844 unsigned int saddr, mask, high, low;
845 EXEC SQL END DECLARE SECTION;
846 int row;
847 struct in_addr addr;
848
849 id = *(int *)argv[0];
850
851 if (!strcmp(q->shortname, "uhst"))
852 {
853 row = 1;
854 EXEC SQL SELECT name, vendor, model, os
855 INTO :oldname, :vendor, :model, :os
856 FROM machine WHERE mach_id = :id;
857 }
858 else
859 row = 0;
860
861 /* Sanity check name, vendor, model, and os. */
862 if ((row == 0 || strcasecmp(argv[1], oldname)) &&
863 !hostname_check(argv[row]))
864 return MR_BAD_CHAR;
865 if ((row == 0 || strcasecmp(argv[2], vendor)) &&
866 !hostinfo_check(argv[row + 1]))
867 return MR_BAD_CHAR;
868 if ((row == 0 || strcasecmp(argv[3], model)) &&
869 !hostinfo_check(argv[row + 2]))
870 return MR_BAD_CHAR;
871 if ((row == 0 || strcasecmp(argv[4], os)) &&
872 !hostinfo_check(argv[row + 3]))
873 return MR_BAD_CHAR;
874
875 /* check for duplicate name */
876 name = argv[row];
877 EXEC SQL SELECT count(mach_id) INTO :cnt FROM hostalias
878 WHERE name = UPPER(:name);
879 if (dbms_errno)
880 return mr_errcode;
881 if (cnt != 0)
882 return MR_EXISTS;
883
884 /* check address */
885 if (!strcmp(argv[9 + row], "unassigned"))
886 value = -1;
887 else if (!strcmp(argv[9 + row], "unique"))
888 {
889 if (*(int *)argv[8 + row] == 0)
890 value = -1;
891 else
892 value = -2;
893 }
894 else
895 {
896 value = ntohl(inet_addr(argv[9 + row]));
897 if (value == -1)
898 return MR_ADDRESS;
899 }
900 if (value == 0)
901 return MR_ADDRESS;
902 if (value != -1)
903 {
904 /*
905 * an address or unique was specified.
906 */
907 id = *(int *)argv[8 + row];
908 EXEC SQL SELECT saddr, mask, high, low INTO :ssaddr, :smask,
909 :shigh, :slow FROM subnet WHERE snet_id = :id;
910 if (dbms_errno)
911 return mr_errcode;
912 saddr = (unsigned) ssaddr;
913 mask = (unsigned) smask;
914 high = (unsigned) shigh;
915 low = (unsigned) slow;
916 if (value != -2)
917 {
918 /*
919 * someone specified an IP address for the host record
920 */
921 if ((value & mask) != saddr || value < low || value > high)
922 return MR_ADDRESS;
923 /*
924 * run the address argument through inet_addr(). This
925 * has the effect that any out of bounds host addrs will
926 * be converted to a valid host addr. We do this now
927 * so that the uniqueness check works. We should also
928 * link in an inet_addr() that returns an error for
929 * this case.
930 */
931 addr.s_addr = inet_addr(argv[9 + row]);
932 name = inet_ntoa(addr);
933 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
934 WHERE address = :name;
935 if (dbms_errno)
936 return mr_errcode;
937 if (cnt > 0)
938 {
939 /*
940 * make IP address is unique. If this a modify request
941 * (row == 1), then we expect one record to exist.
942 */
943 if (row == 0 || (row == 1 && cnt > 1))
944 return MR_ADDRESS;
945 if (row == 1 && cnt == 1)
946 {
947 EXEC SQL SELECT mach_id INTO :id FROM machine
948 WHERE address = :name;
949 if (id != *(int *)argv[0])
950 return MR_ADDRESS;
951 }
952 }
953 }
954 else
955 {
956 /*
957 * a "unique" address was specified. Walk through the
958 * range specified in the network record, return
959 * error if no room left.
960 */
961 for (id = low; id <= high; id++)
962 {
963 if (((id & 0xff) == 0) || ((id & 0xff) == 255))
964 continue;
965 addr.s_addr = htonl(id);
966 name = inet_ntoa(addr);
967 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
968 WHERE address = :name;
969 if (dbms_errno)
970 return mr_errcode;
971 if (cnt == 0)
972 break;
973 }
974 if (cnt != 0)
975 return MR_NO_ID;
976 else
977 value = htonl(id);
978 }
979 /*
980 * we have an address in value. Convert it to a string and store it.
981 */
982 addr.s_addr = htonl(value);
983 strcpy(argv[9 + row], inet_ntoa(addr));
984 }
985 else
986 strcpy(argv[9 + row], "unassigned");
987
988 /* status checking */
989 value = atoi(argv[7 + row]);
990 if (row == 0 && !(value == 1 || value == 0))
991 return MR_TYPE;
992 if (row == 1)
993 {
994 id = *(int *)argv[0];
995 EXEC SQL SELECT status INTO :cnt FROM machine WHERE mach_id = :id;
996 if (dbms_errno)
997 return mr_errcode;
998 if (value != cnt)
999 {
1000 EXEC SQL UPDATE machine SET statuschange = SYSDATE
1001 WHERE mach_id = :id;
1002 }
1003 }
1004
1005 /*
1006 * If this is an update_host query, we're done.
1007 */
1008 if (row == 1)
1009 return MR_SUCCESS;
1010
1011 /*
1012 * For an add_host query, allocate and fill in a new machine id,
1013 * and then insert the creator id.
1014 */
1015 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
1016 return mr_errcode;
1017
1018 sprintf(argv[q->argc + q->vcnt + 1], "%d", cl->client_id);
1019 return MR_SUCCESS;
1020}
1021
1022
1023/* setup_ahal():
1024 */
1025
1026int setup_ahal(struct query *q, char **argv, client *cl)
1027{
1028 EXEC SQL BEGIN DECLARE SECTION;
1029 char *name;
1030 int cnt;
1031 EXEC SQL END DECLARE SECTION;
1032 char *p;
1033
1034 name = argv[0];
1035 if (!hostname_check(argv[0]))
1036 return MR_BAD_CHAR;
1037
1038 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine WHERE
1039 name = UPPER(:name);
1040 if (dbms_errno)
1041 return mr_errcode;
1042 if (cnt > 0)
1043 return MR_EXISTS;
1044
1045 return MR_SUCCESS;
1046}
1047
1048/* hostname_check()
1049 * validate the rfc1035/rfc1123-ness of a hostname
1050 */
1051
1052int hostname_check(char *name)
1053{
1054 char *p;
1055 int count;
1056
1057 /* Sanity check name: must contain only letters, numerals, and
1058 * hyphen, and not start or end with a hyphen. Also make sure no
1059 * label (the thing the .s seperate) is longer than 63 characters.
1060 */
1061
1062 for (p = name, count = 0; *p; p++)
1063 {
1064 count++;
1065 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
1066 (*p == '-' && p[1] == '.'))
1067 return 0;
1068 if (*p == '.')
1069 count = 0;
1070 if (count == 64)
1071 return 0;
1072 }
1073 if (*(p - 1) == '-')
1074 return 0;
1075 return 1;
1076}
1077
1078int hostinfo_check(char *info)
1079{
1080 char *p;
1081
1082 if (!*info)
1083 return 1;
1084
1085 /* Sanity check host hostinfo: must start with a letter, contain
1086 * only letters, numerals, and hyphen, and not end with a hyphen.
1087 */
1088
1089 if (!isalpha(*info))
1090 return 0;
1091 for (p = info; *p; p++)
1092 {
1093 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
1094 (*p == '-' && p[1] == '.'))
1095 return 0;
1096 }
1097 if (!isalnum(*(p - 1)))
1098 return 1;
1099}
This page took 1.126965 seconds and 5 git commands to generate.