8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / ypcmd / ypxfrd_server.c
blob2f293326db0a6a55dda8d88b6f80149f073d2e9d
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
26 /* Portions Copyright 2005 Juergen Keil */
28 #pragma ident "%Z%%M% %I% %E% SMI"
30 #include <sys/types.h>
31 #include <signal.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <ndbm.h>
36 #include <rpc/rpc.h>
37 #include <rpc/svc.h>
38 #include <netinet/in.h>
39 #include <sys/socket.h>
40 #include <syslog.h>
41 #include "ypxfrd.h"
42 #include "ypsym.h"
43 #include "ypdefs.h"
45 * Because this code hacks into DBM underneath its API it can't use the N2L
46 * shim in it's normal way. It thus includes shim.h instead of shim_hooks.h
47 * and has knowledge of shim internals. While copying the DBM files it does
48 * not lock them. This reflects the behavior of the pre N2L code.
50 #include "shim.h"
51 #include "yptol.h"
53 #if (defined(vax) || defined(i386))
54 #define DOSWAB 1
55 #endif
57 USE_YP_SECURE
59 /* per connection stuff */
60 struct mycon {
61 map_ctrl *map;
62 int lblk;
63 int firstd;
64 datum key;
67 bool_t xdr_myfyl(XDR *xdrs, struct mycon *objp);
68 bool_t xdr_pages(XDR *xdrs, struct mycon *m);
69 bool_t xdr_dirs(XDR *xdrs, struct mycon *m);
71 int mygetdir(char *block, int *no, struct mycon *m);
72 int mygetpage(char *block, int *pageno, struct mycon *m);
74 datum mydbm_topkey(DBM *db, datum okey);
75 datum dbm_do_nextkey();
76 datum shim_dbm_do_nextkey();
78 extern void get_secure_nets(char *);
79 extern int check_secure_net_ti(struct netbuf *, char *);
80 extern int _main(int, char **);
82 int
83 main(int argc, char **argv)
85 int connmaxrec = RPC_MAXDATASIZE;
87 /* load up the securenet file */
88 get_secure_nets(argv[0]);
91 * Set non-blocking mode and maximum record size for
92 * connection oriented RPC transports.
94 if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &connmaxrec)) {
95 syslog(LOG_INFO|LOG_DAEMON,
96 "unable to set maximum RPC record size");
99 /* Initialize file locking etc. */
100 if (!init_lock_system(TRUE))
101 /* An detailed error will already have been logged */
102 exit(-1);
104 return (_main(argc, argv));
108 * In yptol mode we may start a cache update thread within a child process.
109 * It is thus important that child processes do not exit, killing any such
110 * threads, before the thread has completed. They must thus call this version
111 * of the exit() function.
113 void
114 yptol_exit(int status)
116 if (yptol_mode) {
117 thr_join(0, NULL, NULL);
119 exit(status);
122 dbmfyl *
123 getdbm_1_svc(hosereq *argp, struct svc_req *rqstp)
125 static dbmfyl result;
126 char path[MAXNAMLEN + 1];
127 SVCXPRT *xprt;
128 int pid;
129 int res;
130 struct mycon m;
131 char *ypname = "ypxfrd";
132 struct netbuf *nbuf;
133 sa_family_t af;
134 in_port_t port;
136 xprt = rqstp->rq_xprt;
138 signal(SIGPIPE, SIG_IGN);
139 signal(SIGCHLD, SIG_IGN);
142 * Build up path name. If we are working in N2L mode also conv
143 * to the new N2L style mapname.
145 * Do not allow any path as a domain name or map name.
147 if ((strchr(argp->domain, '/') != NULL) ||
148 (strchr(argp->map, '/') != NULL) ||
149 (!ypmkfilename(argp->domain, argp->map, (char *)&path))) {
150 res = GETDBM_ERROR;
151 if (!svc_sendreply(rqstp->rq_xprt, xdr_answer,
152 (caddr_t)&res)) {
153 svcerr_systemerr(rqstp->rq_xprt);
155 return (NULL);
158 pid = fork1();
159 if (pid < 0) {
160 perror("fork");
162 res = GETDBM_ERROR;
163 if (!svc_sendreply(rqstp->rq_xprt, xdr_answer,
164 (caddr_t)&res)) {
165 svcerr_systemerr(rqstp->rq_xprt);
167 return (NULL);
169 if (pid != 0)
170 return (NULL);
172 m.map = (map_ctrl *)shim_dbm_open(path, 0, 0);
173 if (m.map == NULL) {
174 perror(path);
175 res = GETDBM_ERROR;
176 if (!svc_sendreply(rqstp->rq_xprt, xdr_answer,
177 (caddr_t)&res)) {
178 svcerr_systemerr(rqstp->rq_xprt);
180 yptol_exit(0);
181 return (NULL);
184 /* Do the security thing */
185 if ((nbuf = svc_getrpccaller(xprt)) == 0) {
186 res = GETDBM_ERROR;
187 if (!svc_sendreply(xprt, xdr_answer, (caddr_t)&res)) {
188 svcerr_systemerr(xprt);
190 shim_dbm_close((DBM *)m.map);
191 yptol_exit(0);
192 return (NULL);
194 if (!check_secure_net_ti(nbuf, ypname)) {
195 res = GETDBM_ERROR;
196 if (!svc_sendreply(xprt, xdr_answer, (caddr_t)&res)) {
197 svcerr_systemerr(xprt);
199 shim_dbm_close((DBM *)m.map);
200 yptol_exit(1);
201 return (NULL);
204 af = ((struct sockaddr_storage *)nbuf->buf)->ss_family;
205 port = (af == AF_INET6) ?
206 ((struct sockaddr_in6 *)nbuf->buf)->sin6_port :
207 ((struct sockaddr_in *)nbuf->buf)->sin_port;
209 if ((af == AF_INET || af == AF_INET6) &&
210 (ntohs(port) > IPPORT_RESERVED)) {
211 datum key, val;
213 key.dptr = yp_secure;
214 key.dsize = yp_secure_sz;
215 val = shim_dbm_fetch((DBM *)m.map, key);
216 if (val.dptr != NULL) {
217 res = GETDBM_ERROR;
218 if (!svc_sendreply(xprt, xdr_answer, (caddr_t)&res)) {
219 svcerr_systemerr(xprt);
221 shim_dbm_close((DBM *)m.map);
222 yptol_exit(1);
223 return (NULL);
227 /* OK, we're through */
228 m.key = shim_dbm_firstkey((DBM *)m.map);
230 m.lblk = -1;
231 m.firstd = 0;
233 if (!svc_sendreply(rqstp->rq_xprt, xdr_myfyl, (caddr_t)&m)) {
234 svcerr_systemerr(rqstp->rq_xprt);
236 shim_dbm_close((DBM *)m.map);
237 yptol_exit(0);
239 return (&result);
242 bool_t
243 xdr_myfyl(XDR *xdrs, struct mycon *objp)
245 int ans = OK;
247 if (!xdr_answer(xdrs, (answer *) &ans))
248 return (FALSE);
249 if (!xdr_pages(xdrs, objp))
250 return (FALSE);
251 if (!xdr_dirs(xdrs, objp))
252 return (FALSE);
254 return (TRUE);
257 bool_t
258 xdr_pages(XDR *xdrs, struct mycon *m)
260 static struct pag res;
261 bool_t false = FALSE;
262 bool_t true = TRUE;
263 #ifdef DOSWAB
264 short *s;
265 int i;
266 int cnt;
267 #endif
268 res.status = mygetpage(res.pag_u.ok.blkdat, &(res.pag_u.ok.blkno), m);
270 #ifdef DOSWAB
271 if (res.status == OK) {
272 s = (short *)res.pag_u.ok.blkdat;
273 cnt = s[0];
274 for (i = 0; i <= cnt; i++)
275 s[i] = ntohs(s[i]);
277 #endif
279 if (!xdr_pag(xdrs, &res))
280 return (FALSE);
282 while (res.status == OK) {
283 if (!xdr_bool(xdrs, &true))
284 return (FALSE);
285 res.status = mygetpage(res.pag_u.ok.blkdat,
286 &(res.pag_u.ok.blkno), m);
288 #ifdef DOSWAB
289 if (res.status == OK) {
290 s = (short *)res.pag_u.ok.blkdat;
291 cnt = s[0];
292 for (i = 0; i <= cnt; i++)
293 s[i] = ntohs(s[i]);
295 #endif
297 if (!xdr_pag(xdrs, &res))
298 return (FALSE);
301 return (xdr_bool(xdrs, &false));
305 mygetdir(char *block, int *no, struct mycon *m)
307 int status;
308 int len;
310 if (m->firstd == 0) {
311 lseek(m->map->entries->dbm_dirf, 0, 0);
312 m->firstd = 1;
313 } else
314 m->firstd++;
316 len = read(m->map->entries->dbm_dirf, block, DBLKSIZ);
317 *no = (m->firstd) - 1;
318 status = OK;
321 * printf("dir block %d\n", (m->firstd) - 1);
324 if (len < 0) {
325 perror("read directory");
326 status = GETDBM_ERROR;
327 } else if (len == 0) {
328 status = GETDBM_EOF;
330 * printf("dir EOF\n");
333 return (status);
336 bool_t
337 xdr_dirs(XDR *xdrs, struct mycon *m)
339 static struct dir res;
340 bool_t false = FALSE;
341 bool_t true = TRUE;
343 res.status = mygetdir(res.dir_u.ok.blkdat, &(res.dir_u.ok.blkno), m);
345 if (!xdr_dir(xdrs, &res))
346 return (FALSE);
348 while (res.status == OK) {
349 if (!xdr_bool(xdrs, &true))
350 return (FALSE);
351 res.status = mygetdir(res.dir_u.ok.blkdat,
352 &(res.dir_u.ok.blkno), m);
353 if (!xdr_dir(xdrs, &res))
354 return (FALSE);
357 return (xdr_bool(xdrs, &false));
361 mygetpage(char *block, int *pageno, struct mycon *m)
364 for (; m->key.dptr;
365 m->key = shim_dbm_do_nextkey((DBM *)m->map, m->key)) {
367 if (m->map->entries->dbm_pagbno != m->lblk) {
369 * printf("block=%d lblk=%d\n",
370 * m->map->entries->dbm_pagbno,
371 * m->lblk);
373 m->lblk = m->map->entries->dbm_pagbno;
374 *pageno = m->lblk;
375 memmove(block, m->map->entries->dbm_pagbuf, PBLKSIZ);
376 /* advance key on first try */
377 m->key = mydbm_topkey(m->map->entries, m->key);
378 m->key = shim_dbm_do_nextkey((DBM *)m->map, m->key);
379 return (OK);
383 * printf("EOF\n");
385 return (GETDBM_EOF);
388 datum
389 mydbm_topkey(DBM *db, datum okey)
391 datum ans;
392 datum tmp;
393 register char *buf;
394 int n;
395 register short *sp;
396 register short t;
397 datum item;
398 #if defined(_XPG4_2)
399 register size_t m;
400 #else
401 register long m;
402 #endif
403 register char *p1, *p2;
405 buf = db->dbm_pagbuf;
406 sp = (short *)buf;
407 /* find the maximum key in cmpdatum order */
409 if ((unsigned)0 >= sp[0]) {
410 return (okey);
411 } else {
412 ans.dptr = buf + sp[1];
413 ans.dsize = PBLKSIZ - sp[1];
415 for (n = 2; ; n += 2) {
416 if ((unsigned)n >= sp[0]) {
417 if (ans.dptr == NULL) {
418 return (okey);
419 } else {
420 return (ans);
422 } else {
423 t = PBLKSIZ;
424 if (n > 0)
425 t = sp[n];
426 tmp.dptr = buf + sp[n + 1];
427 tmp.dsize = t - sp[n + 1];
430 m = tmp.dsize;
431 if (m != ans.dsize) {
432 if ((m - ans.dsize) < 0)
433 ans = tmp;
434 } else if (m == 0) {
435 } else {
436 p1 = tmp.dptr;
437 p2 = ans.dptr;
439 if (*p1++ != *p2++) {
440 if ((*--p1 - *--p2) < 0)
441 ans = tmp;
442 break;
444 while (--m);