]> andersk Git - moira.git/blame - server/qsetup.pc
Allow hostname to start with a digit in hostname_check, but disallow it
[moira.git] / server / qsetup.pc
CommitLineData
7ac48069 1/* $Id$
73cf66ba 2 *
7ac48069 3 * Query setup routines
73cf66ba 4 *
7ac48069 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>.
73cf66ba 8 */
9
73cf66ba 10#include <mit-copyright.h>
73cf66ba 11#include "mr_server.h"
03c05291 12#include "query.h"
7ac48069 13#include "qrtn.h"
14
03c05291 15#include <arpa/inet.h>
7ac48069 16#include <netinet/in.h>
17
18#include <ctype.h>
19#include <stdlib.h>
20#include <string.h>
21
73cf66ba 22EXEC SQL INCLUDE sqlca;
73cf66ba 23
7ac48069 24RCSID("$Header$");
25
26extern char *whoami;
03c05291 27extern int dbms_errno, mr_errcode;
73cf66ba 28
29EXEC SQL BEGIN DECLARE SECTION;
30extern char stmt_buf[];
31EXEC SQL END DECLARE SECTION;
32
03c05291 33EXEC SQL WHENEVER SQLERROR DO dbmserr();
34
73cf66ba 35
03c05291 36int prefetch_value(struct query *q, char **argv, client *cl);
37int check_nfs(int mach_idx, char *name, char *access);
73cf66ba 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
5eaef520 52int setup_ausr(struct query *q, char *argv[], client *cl)
73cf66ba 53{
5eaef520 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;
cca8e7ef 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
5eaef520 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);
73cf66ba 76 }
77
5eaef520 78 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[row]) == -1)
79 sprintf(argv[0], "#%s", argv[row]);
73cf66ba 80
5eaef520 81 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
82 return mr_errcode;
73cf66ba 83
5eaef520 84 return MR_SUCCESS;
73cf66ba 85}
86
87
88/* setup_dusr - verify that the user is no longer being referenced
89 * and may safely be deleted.
90 */
91
7ac48069 92int setup_dusr(struct query *q, char *argv[], client *cl)
73cf66ba 93{
5eaef520 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;
73cf66ba 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 */
7ac48069 136int setup_spop(struct query *q, char *argv[], client *cl)
73cf66ba 137{
5eaef520 138 EXEC SQL BEGIN DECLARE SECTION;
139 int id, mid;
e688520a 140 char type[USERS_POTYPE_SIZE];
5eaef520 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;
7ac48069 146 if (sqlca.sqlerrd[2] == 0)
5eaef520 147 return MR_MACHINE;
148 EXEC SQL SELECT mach_id INTO :mid FROM machine
149 WHERE mach_id = :mid;
7ac48069 150 if (sqlca.sqlerrd[2] == 0)
5eaef520 151 return MR_MACHINE;
152 if (strcmp(strtrim(type), "POP"))
153 set_pop_usage(mid, 1);
154 return MR_SUCCESS;
73cf66ba 155}
156
157
158/* setup_dpob: Take care of keeping track of the post office usage.
159 */
7ac48069 160int setup_dpob(struct query *q, char *argv[], client *cl)
73cf66ba 161{
5eaef520 162 EXEC SQL BEGIN DECLARE SECTION;
163 int id, user;
e688520a 164 char type[USERS_POTYPE_SIZE];
5eaef520 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;
73cf66ba 176}
177
178
179/* setup_dmac - verify that the machine is no longer being referenced
180 * and may safely be deleted.
181 */
182
7ac48069 183int setup_dmac(struct query *q, char *argv[], client *cl)
73cf66ba 184{
5eaef520 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;
73cf66ba 232}
233
234
235/* setup_dsnt - verify that the subnet is no longer being referenced
236 * and may safely be deleted.
237 */
238
7ac48069 239int setup_dsnt(struct query *q, char *argv[], client *cl)
73cf66ba 240{
5eaef520 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;
73cf66ba 251}
252
253
254/* setup_dclu - verify that the cluster is no longer being referenced
255 * and may safely be deleted.
256 */
257
7ac48069 258int setup_dclu(struct query *q, char *argv[], client *cl)
73cf66ba 259{
5eaef520 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;
73cf66ba 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[] = {
5eaef520 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,
73cf66ba 304};
305
5eaef520 306int setup_alis(struct query *q, char *argv[], client *cl)
73cf66ba 307{
5eaef520 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
5a22fdf5 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
5eaef520 329 for (p = (unsigned char *) argv[idx]; *p; p++)
330 {
73cf66ba 331 if (badlistchars[*p])
5eaef520 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);
73cf66ba 346 }
5eaef520 347 else
348 strcpy(argv[6 + idx], "-1");
73cf66ba 349 }
350
5eaef520 351 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
352 return mr_errcode;
73cf66ba 353
5eaef520 354 return MR_SUCCESS;
73cf66ba 355}
356
357
358/* setup_dlis - verify that the list is no longer being referenced
359 * and may safely be deleted.
360 */
361
7ac48069 362int setup_dlis(struct query *q, char *argv[], client *cl)
73cf66ba 363{
5eaef520 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;
73cf66ba 423}
424
425
426/* setup_dsin - verify that the service is no longer being referenced
427 * and may safely be deleted.
428 */
429
7ac48069 430int setup_dsin(struct query *q, char *argv[], client *cl)
73cf66ba 431{
5eaef520 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;
73cf66ba 451}
452
453
454/* setup_dshi - verify that the service-host is no longer being referenced
455 * and may safely be deleted.
456 */
457
7ac48069 458int setup_dshi(struct query *q, char *argv[], client *cl)
73cf66ba 459{
5eaef520 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;
73cf66ba 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
03c05291 486 ** argv[5] - rwaccess
73cf66ba 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
03c05291 494 ** * verify rwaccess in {r, w, R, W}
73cf66ba 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
5eaef520 509int setup_afil(struct query *q, char *argv[], client *cl)
73cf66ba 510{
5eaef520 511 char *type, *name;
512 int mach_id;
513 EXEC SQL BEGIN DECLARE SECTION;
514 int ok;
e688520a 515 char ftype[FILESYS_TYPE_SIZE + 10], *rwaccess;
5eaef520 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;
73cf66ba 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
5eaef520 547int setup_ufil(struct query *q, char *argv[], client *cl)
73cf66ba 548{
5eaef520 549 int mach_id, status;
550 char *type, *name;
551 EXEC SQL BEGIN DECLARE SECTION;
552 int fid, total, who, ok;
e688520a 553 char *entity, ftype[FILESYS_TYPE_SIZE + 10], *access;
5eaef520 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;
73cf66ba 605 }
73cf66ba 606 }
5eaef520 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;
73cf66ba 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
5eaef520 623int check_nfs(int mach_id, char *name, char *access)
73cf66ba 624{
5eaef520 625 EXEC SQL BEGIN DECLARE SECTION;
e688520a 626 char dir[NFSPHYS_DIR_SIZE];
5eaef520 627 int mid = mach_id;
628 EXEC SQL END DECLARE SECTION;
44d12d58 629 int status;
630 char *cp1;
631 char *cp2;
5eaef520 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)
73cf66ba 653 break;
5eaef520 654 cp2++;
655 }
656 if (!*cp2)
657 {
658 status = MR_SUCCESS;
659 break;
73cf66ba 660 }
661 }
5eaef520 662 EXEC SQL CLOSE csr101;
663 if (dbms_errno)
664 return mr_errcode;
665 return status;
73cf66ba 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
5eaef520 673int setup_dfil(struct query *q, char **argv, client *cl)
73cf66ba 674{
5eaef520 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;
73cf66ba 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
5eaef520 707int setup_dnfp(struct query *q, char **argv, client *cl)
73cf66ba 708{
5eaef520 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;
73cf66ba 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
5eaef520 733int setup_dqot(struct query *q, char **argv, client *cl)
73cf66ba 734{
5eaef520 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];
73cf66ba 750 }
751
5eaef520 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;
73cf66ba 758
5eaef520 759 if (dbms_errno)
760 return mr_errcode;
761 return MR_SUCCESS;
73cf66ba 762}
763
764
7f426981 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 *
5eaef520 770 * It is called from the query table as (*v->pre_rtn)(q, Argv, cl) or
7f426981 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
5eaef520 777int prefetch_value(struct query *q, char **argv, client *cl)
7f426981 778{
5eaef520 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;
7f426981 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 */
5eaef520 815int prefetch_filesys(struct query *q, char **argv, client *cl)
7f426981 816{
5eaef520 817 EXEC SQL BEGIN DECLARE SECTION;
818 int fid, phid;
819 EXEC SQL END DECLARE SECTION;
820 int argc;
7f426981 821
5eaef520 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;
7f426981 826
5eaef520 827 argc = q->argc + q->vcnt;
828 sprintf(argv[argc++], "%d", phid);
829 sprintf(argv[argc], "%d", fid);
7f426981 830
5eaef520 831 return MR_SUCCESS;
7f426981 832}
833
834
835/* setup_ahst():
836 */
837
5eaef520 838int setup_ahst(struct query *q, char **argv, client *cl)
7f426981 839{
5eaef520 840 EXEC SQL BEGIN DECLARE SECTION;
e688520a 841 char *name, oldname[MACHINE_NAME_SIZE], vendor[MACHINE_VENDOR_SIZE];
db9491c6 842 char model[MACHINE_MODEL_SIZE], os[MACHINE_OS_SIZE];
ff98438b 843 int value, id, ssaddr, smask, shigh, slow, cnt;
844 unsigned int saddr, mask, high, low;
5eaef520 845 EXEC SQL END DECLARE SECTION;
846 int row;
847 struct in_addr addr;
5eaef520 848
fde09f2c 849 id = *(int *)argv[0];
850
5eaef520 851 if (!strcmp(q->shortname, "uhst"))
85330553 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 }
5eaef520 858 else
859 row = 0;
860
9e252e6f 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;
8ca3e341 874
5eaef520 875 /* check for duplicate name */
876 name = argv[row];
877 EXEC SQL SELECT count(mach_id) INTO :cnt FROM hostalias
ad06a10e 878 WHERE name = UPPER(:name);
5eaef520 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;
5482f508 899 }
5eaef520 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];
ff98438b 908 EXEC SQL SELECT saddr, mask, high, low INTO :ssaddr, :smask,
909 :shigh, :slow FROM subnet WHERE snet_id = :id;
5eaef520 910 if (dbms_errno)
911 return mr_errcode;
ff98438b 912 saddr = (unsigned) ssaddr;
913 mask = (unsigned) smask;
914 high = (unsigned) shigh;
915 low = (unsigned) slow;
5eaef520 916 if (value != -2)
917 {
918 /*
919 * someone specified an IP address for the host record
920 */
082466aa 921 if ((value & mask) != saddr || value < low || value > high)
5eaef520 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 */
7ac48069 943 if (row == 0 || (row == 1 && cnt > 1))
5eaef520 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;
7f426981 951 }
952 }
5eaef520 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);
7ac48069 966 name = inet_ntoa(addr);
5eaef520 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;
7f426981 973 }
5eaef520 974 if (cnt != 0)
6715bac2 975 return MR_NO_ID;
5eaef520 976 else
977 value = htonl(id);
7f426981 978 }
5eaef520 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));
7f426981 984 }
5eaef520 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;
7f426981 1002 }
1003 }
1004
5eaef520 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;
7f426981 1020}
1021
1022
1023/* setup_ahal():
1024 */
1025
5eaef520 1026int setup_ahal(struct query *q, char **argv, client *cl)
7f426981 1027{
5eaef520 1028 EXEC SQL BEGIN DECLARE SECTION;
1029 char *name;
1030 int cnt;
1031 EXEC SQL END DECLARE SECTION;
1032 char *p;
1033
84f3d463 1034 name = argv[0];
1035 if (!hostname_check(argv[0]))
5eaef520 1036 return MR_BAD_CHAR;
7f426981 1037
5eaef520 1038 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine WHERE
ad06a10e 1039 name = UPPER(:name);
5eaef520 1040 if (dbms_errno)
1041 return mr_errcode;
1042 if (cnt > 0)
1043 return MR_EXISTS;
7f426981 1044
5eaef520 1045 return MR_SUCCESS;
7f426981 1046}
84f3d463 1047
1048/* hostname_check()
9e252e6f 1049 * validate the rfc1035/rfc1123-ness of a hostname
84f3d463 1050 */
1051
1052int hostname_check(char *name)
1053{
1054 char *p;
1055 int count;
1056
9e252e6f 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.
84f3d463 1060 */
1061
9e252e6f 1062 for (p = name, count = 0; *p; p++)
84f3d463 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}
9e252e6f 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 0.232783 seconds and 5 git commands to generate.