2 * vi:set cin noet sw=4 tw=70:
3 * Copyright 2006, International Business Machines Corporation and others.
6 * This software has been released under the terms of the IBM Public
7 * License. For details, see the LICENSE file in the top-level source
8 * directory or online at http://www.openafs.org/dl/license10.html
12 * Filesystem export operations for Linux
14 #include <afsconfig.h>
15 #include "afs/param.h"
18 #if !defined(AFS_NONFSTRANS) || defined(AFS_AIX_IAUTH_ENV)
19 #include <linux/module.h> /* early to avoid printf->printk mapping */
21 #include "afs/sysincludes.h"
22 #include "afsincludes.h"
23 #include "nfsclient.h"
24 #include <linux/sunrpc/svc.h>
25 #include <linux/sunrpc/svcauth.h>
27 static unsigned long authtab_addr
= 0;
28 #if defined(module_param) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
29 module_param(authtab_addr
, long, 0);
31 MODULE_PARM(authtab_addr
, "l");
33 MODULE_PARM_DESC(authtab_addr
, "Address of the authtab array.");
35 extern struct auth_ops
*authtab
[] __attribute__((weak
));
36 static struct auth_ops
**afs_authtab
;
37 static struct auth_ops
*afs_new_authtab
[RPC_AUTH_MAXFLAVOR
];
38 static struct auth_ops
*afs_orig_authtab
[RPC_AUTH_MAXFLAVOR
];
40 static int whine_memory
= 0;
42 afs_lock_t afs_xnfssrv
;
44 struct nfs_server_thread
{
45 struct nfs_server_thread
*next
; /* next in chain */
46 pid_t pid
; /* pid of this thread */
47 int active
; /* this thread is servicing an RPC */
48 struct sockaddr_in client_addr
; /* latest client of this thread */
50 afs_int32 uid
; /* AFS UID/PAG for this thread */
51 afs_int32 code
; /* What should InitReq return? */
52 int flavor
; /* auth flavor */
53 uid_t client_uid
; /* UID claimed by client */
54 gid_t client_gid
; /* GID claimed by client */
55 gid_t client_g0
, client_g1
; /* groups claimed by client */
58 static struct nfs_server_thread
*nfssrv_list
= 0;
60 static struct nfs_server_thread
*find_nfs_thread(int create
)
62 struct nfs_server_thread
*this;
64 /* Check that this is an nfsd kernel thread */
65 if (current
->files
!= init_task
.files
|| strcmp(current
->comm
, "nfsd"))
68 ObtainWriteLock(&afs_xnfssrv
, 804);
69 for (this = nfssrv_list
; this; this = this->next
)
70 if (this->pid
== current
->pid
)
72 if (!this && create
) {
73 this = afs_osi_Alloc(sizeof(struct nfs_server_thread
));
75 this->next
= nfssrv_list
;
76 this->pid
= current
->pid
;
77 this->client_addrlen
= 0;
79 printk("afs: added nfsd task %d/%d\n",
80 current
->tgid
, current
->pid
);
81 } else if (!whine_memory
) {
83 printk("afs: failed to allocate memory for nfsd task %d/%d\n",
84 current
->tgid
, current
->pid
);
87 ReleaseWriteLock(&afs_xnfssrv
);
92 svcauth_afs_accept(struct svc_rqst
*rqstp
, u32
*authp
)
94 struct nfs_server_thread
*ns
;
95 struct afs_exporter
*outexp
;
97 struct sockaddr_in
*addr
;
100 code
= afs_orig_authtab
[rqstp
->rq_authop
->flavour
]->accept(rqstp
, authp
);
105 ns
= find_nfs_thread(1);
108 /* XXX maybe we should fail this with rpc_system_err? */
111 #if HAVE_LINUX_SVC_ADDR_IN
112 addr
= svc_addr_in(rqstp
);
114 addr
= &rqstp
->rq_addr
;
118 ns
->flavor
= rqstp
->rq_authop
->flavour
;
120 ns
->client_addr
= *addr
;
121 ns
->client_addrlen
= rqstp
->rq_addrlen
;
122 ns
->client_uid
= afs_cr_uid(&rqstp
->rq_cred
);
123 ns
->client_gid
= afs_cr_gid(&rqstp
->rq_cred
);
124 if (afs_cr_group_info(&rqstp
->rq_cred
)->ngroups
> 0)
125 ns
->client_g0
= GROUP_AT(afs_cr_group_info(&rqstp
->rq_cred
), 0);
128 if (afs_cr_group_info(&rqstp
->rq_cred
)->ngroups
> 1)
129 ns
->client_g1
= GROUP_AT(afs_cr_group_info(&rqstp
->rq_cred
), 1);
133 if (addr
->sin_family
!= AF_INET
) {
134 printk("afs: NFS request from non-IPv4 client (family %d len %d)\n",
135 addr
->sin_family
, rqstp
->rq_addrlen
);
140 afs_set_cr_uid(credp
, afs_cr_uid(&rqstp
->rq_cred
));
141 afs_set_cr_gid(credp
, afs_cr_gid(&rqstp
->rq_cred
));
142 get_group_info(afs_cr_group_info(&rqstp
->rq_cred
));
143 afs_set_cr_group_info(credp
, afs_cr_group_info(&rqstp
->rq_cred
));
145 /* avoid creating wildcard entries by mapping anonymous
146 * clients to afs_nobody */
147 if (afs_cr_uid(credp
) == -1)
148 afs_set_cr_uid(credp
, -2);
149 code
= afs_nfsclient_reqhandler(0, &credp
, addr
->sin_addr
.s_addr
,
151 if (!code
&& outexp
) EXP_RELE(outexp
);
152 if (!code
) ns
->code
= 0;
154 printk("afs: svcauth_afs_accept: afs_nfsclient_reqhandler: %d\n", code
);
164 /* This doesn't work, because they helpfully NULL out rqstp->authop
165 * before calling us, so we have no way to tell what the original
169 svcauth_afs_release(struct svc_rqst
*rqstp
)
171 struct nfs_server_thread
*ns
;
174 ns
= find_nfs_thread(0);
175 if (ns
) ns
->active
= 0;
178 return afs_orig_authtab
[rqstp
->rq_authop
->flavour
]->release(rqstp
);
183 int osi_linux_nfs_initreq(struct vrequest
*av
, afs_ucred_t
*cr
, int *code
)
185 struct nfs_server_thread
*ns
;
187 ns
= find_nfs_thread(0);
188 if (!ns
|| !ns
->active
)
193 afs_cr_ruid(cr
) = NFSXLATOR_CRED
;
199 void osi_linux_nfssrv_init(void)
204 AFS_RWLOCK_INIT(&afs_xnfssrv
, "afs_xnfssrv");
206 if (authtab
&& !IS_ERR(authtab
))
207 afs_authtab
= authtab
;
208 else if (authtab_addr
) afs_authtab
= (struct auth_ops
**)authtab_addr
;
210 printk("Warning: Unable to find the address of authtab\n");
211 printk("NFS Translator hooks will not be installed\n");
212 printk("To correct, specify authtab_addr=<authtab>\n");
217 for (i
= 0; i
< RPC_AUTH_MAXFLAVOR
; i
++) {
218 afs_orig_authtab
[i
] = afs_authtab
[i
];
219 if (!afs_orig_authtab
[i
] || afs_orig_authtab
[i
]->flavour
!= i
||
220 !try_module_get(afs_orig_authtab
[i
]->owner
)) {
221 afs_orig_authtab
[i
] = 0;
225 afs_new_authtab
[i
] = afs_osi_Alloc(sizeof(struct auth_ops
));
226 osi_Assert(afs_new_authtab
[i
] != NULL
);
227 *(afs_new_authtab
[i
]) = *(afs_orig_authtab
[i
]);
228 afs_new_authtab
[i
]->owner
= THIS_MODULE
;
229 afs_new_authtab
[i
]->accept
= svcauth_afs_accept
;
230 /* afs_new_authtab[i]->release = svcauth_afs_release; */
231 svc_auth_unregister(i
);
232 svc_auth_register(i
, afs_new_authtab
[i
]);
236 void osi_linux_nfssrv_shutdown(void)
238 struct nfs_server_thread
*next
;
242 for (i
= 0; i
< RPC_AUTH_MAXFLAVOR
; i
++) {
243 if (!afs_orig_authtab
[i
])
245 svc_auth_unregister(i
);
246 svc_auth_register(i
, afs_orig_authtab
[i
]);
247 module_put(afs_orig_authtab
[i
]->owner
);
248 afs_osi_Free(afs_new_authtab
[i
], sizeof(struct auth_ops
));
253 ObtainWriteLock(&afs_xnfssrv
, 805);
254 while (nfssrv_list
) {
255 next
= nfssrv_list
->next
;
256 afs_osi_Free(nfssrv_list
, sizeof(struct nfs_server_thread
));
259 ReleaseWriteLock(&afs_xnfssrv
);
262 #endif /* AFS_NONFSTRANS */