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