2 /* $Id: idmapd.c,v 1.5 2003/11/05 14:58:58 rees Exp $ */
6 * the regents of the university of michigan
9 * permission is granted to use, copy, create derivative works and redistribute
10 * this software and such derivative works for any purpose, so long as the name
11 * of the university of michigan is not used in any advertising or publicity
12 * pertaining to the use or distribution of this software without specific,
13 * written prior authorization. if the above copyright notice or any other
14 * identification of the university of michigan is included in any copy of any
15 * portion of this software, then the disclaimer below must also be included.
17 * this software is provided as is, without representation from the university
18 * of michigan as to its fitness for any purpose, and without warranty by the
19 * university of michigan of any kind, either express or implied, including
20 * without limitation the implied warranties of merchantability and fitness for
21 * a particular purpose. the regents of the university of michigan shall not be
22 * liable for any damages, including special, indirect, incidental, or
23 * consequential damages, with respect to any claim arising out of or in
24 * connection with the use of the software, even if it has been or is hereafter
25 * advised of the possibility of such damages.
28 /* XXX ignores the domain of received names. */
30 #include <sys/types.h>
31 #include <sys/ioctl.h>
32 #include <sys/syscall.h>
33 #include <sys/errno.h>
36 #include <sys/queue.h>
38 #include <nfs4client/nfs4_dev.h>
39 #include <nfs4client/nfs4_idmap.h>
50 #define DEV_PATH "/dev/nfs4"
52 #define DOMAIN "@FreeBSD.org"
53 #define BADUSER "nobody"
54 #define BADGROUP "nogroup"
59 struct nfs4dev_msg msg;
60 TAILQ_ENTRY(idmap_e) next;
64 char *domain = DOMAIN;
66 TAILQ_HEAD(, idmap_e) upcall_q;
68 #define add_idmap_e(E) do { \
70 TAILQ_INSERT_TAIL(&upcall_q, E, next); \
73 #define remove_idmap_e(E) do { \
74 assert(E != NULL && !TAILQ_EMPTY(&upcall_q)); \
75 E = TAILQ_FIRST(&upcall_q); \
76 TAILQ_REMOVE(&upcall_q, E, next); \
79 #define get_idmap_e(E) do { \
80 if ((E = (struct idmap_e *) malloc(sizeof(struct idmap_e))) == NULL) {\
81 fprintf(stderr, "get_idmap_e(): error in malloc\n");\
84 #define put_idmap_e(E) free(E)
88 validateascii(char *string, u_int32_t len)
92 for (i = 0; i < len; i++) {
93 if (string[i] == '\0')
99 if (string[i] != '\0')
105 idmap_prune_domain(struct idmap_msg * m)
116 if (validateascii(m->id_name, len) < 0) {
117 fprintf(stderr, "msg has invalid ascii\n");
121 for (i=0; i < len && m->id_name[i] != '@' ; i++);
123 ret = (char *)malloc(i+1);
127 bcopy(m->id_name, ret, i);
134 idmap_add_domain(struct idmap_msg * m, char * name)
138 if (m == NULL || name == NULL)
143 nlen = len + strlen(domain);
145 if (nlen > IDMAP_MAXNAMELEN)
148 bcopy(name, &m->id_name[0], len);
149 bcopy(domain, &m->id_name[len], strlen(domain));
151 m->id_name[nlen] = '\0';
152 m->id_namelen = nlen;
158 idmap_name(struct idmap_msg * m, char *name)
160 if (m == NULL || name == NULL || m->id_namelen != 0)
163 if (idmap_add_domain(m, name))
170 idmap_id(struct idmap_msg * m, ident_t id)
172 if (m == NULL || m->id_namelen == 0) {
173 fprintf(stderr, "idmap_id: bad msg\n");
179 m->id_id.uid = id.uid;
182 m->id_id.gid = id.gid;
193 idmap_service(struct idmap_e * e)
195 struct idmap_msg * m;
202 fprintf(stderr, "bad entry\n");
206 if (e->msg.msg_vers != NFS4DEV_VERSION) {
207 fprintf(stderr, "kernel/userland version mismatch! %d/%d\n",
208 e->msg.msg_vers, NFS4DEV_VERSION);
212 if (e->msg.msg_type != NFS4DEV_TYPE_IDMAP) {
213 fprintf(stderr, "bad type!\n");
217 if (e->msg.msg_len != sizeof(struct idmap_msg)) {
218 fprintf(stderr, "bad message length: %zu/%zu\n", e->msg.msg_len,
219 sizeof(struct idmap_msg));
224 printf("servicing msg xid: %x\n", e->msg.msg_xid);
227 m = (struct idmap_msg *)e->msg.msg_data;
229 if (m->id_namelen != 0 && m->id_namelen != strlen(m->id_name)) {
230 fprintf(stderr, "bad name length in idmap_msg\n");
234 switch (m->id_type) {
236 if (m->id_namelen == 0) {
238 pwd = getpwuid(m->id_id.uid);
241 fprintf(stderr, "unknown uid %d!\n",
242 (uint32_t)m->id_id.uid);
247 if (idmap_name(m, name))
252 name = idmap_prune_domain(m);
256 pwd = getpwnam(name);
259 fprintf(stderr, "unknown username %s!\n", name);
261 id.uid = (uid_t)BADUID;
263 id.uid = pwd->pw_uid;
272 if (m->id_namelen == 0) {
274 grp = getgrgid(m->id_id.gid);
277 fprintf(stderr, "unknown gid %d!\n",
278 (uint32_t)m->id_id.gid);
283 if (idmap_name(m, name))
287 name = idmap_prune_domain(m);
291 grp = getgrnam(name);
294 fprintf(stderr, "unknown groupname %s!\n", name);
296 id.gid = (gid_t)BADGID;
298 id.gid = grp->gr_gid;
307 fprintf(stderr, "bad idmap type: %d\n", m->id_type);
316 main(int argc, char ** argv)
319 struct idmap_e * entry;
320 fd_set read_fds, write_fds;
324 while ((ch = getopt(argc, argv, "d:v")) != -1) {
333 fprintf(stderr, "usage: %s [-v] [-d domain]\n", argv[0]);
340 TAILQ_INIT(&upcall_q);
342 fd = open(DEV_PATH, O_RDWR, S_IRUSR | S_IWUSR);
354 struct timeval timo = {1, 0};
359 FD_SET(fd, &read_fds);
360 FD_SET(fd, &write_fds);
362 ret = select(maxfd+1, &read_fds, &write_fds, NULL, &timo);
363 } while (ret < 0 && errno == EINTR);
372 if (FD_ISSET(fd, &read_fds)) {
376 error = ioctl(fd, NFS4DEVIOCGET, &entry->msg);
380 perror("get ioctl:");
385 switch (entry->msg.msg_type ) {
386 case NFS4DEV_TYPE_IDMAP:
387 if (idmap_service(entry))
388 entry->msg.msg_error = EIO;
391 fprintf(stderr, "unknown nfs4dev_msg type\n");
392 entry->msg.msg_error = EIO;
400 if (FD_ISSET(fd, &write_fds)) {
401 while (!TAILQ_EMPTY(&upcall_q)) {
402 remove_idmap_e(entry);
404 error = ioctl(fd, NFS4DEVIOCPUT, &entry->msg);