Whamcloud - gitweb
67287e8e46b351899803f21e02d95427eb0f4208
[fs/lustre-release.git] / lustre / ptlrpc / sec_config.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  */
36
37 #ifndef EXPORT_SYMTAB
38 #define EXPORT_SYMTAB
39 #endif
40 #define DEBUG_SUBSYSTEM S_SEC
41
42 #include <libcfs/libcfs.h>
43 #ifndef __KERNEL__
44 #include <liblustre.h>
45 #include <libcfs/list.h>
46 #else
47 #include <linux/crypto.h>
48 #include <linux/key.h>
49 #endif
50
51 #include <obd.h>
52 #include <obd_class.h>
53 #include <obd_support.h>
54 #include <lustre_net.h>
55 #include <lustre_import.h>
56 #include <lustre_dlm.h>
57 #include <lustre_sec.h>
58
59 #include "ptlrpc_internal.h"
60
61 const char *sptlrpc_part2name(enum lustre_sec_part part)
62 {
63         switch (part) {
64         case LUSTRE_SP_CLI:
65                 return "cli";
66         case LUSTRE_SP_MDT:
67                 return "mdt";
68         case LUSTRE_SP_OST:
69                 return "ost";
70         case LUSTRE_SP_MGS:
71                 return "mgs";
72         case LUSTRE_SP_ANY:
73                 return "any";
74         default:
75                 return "err";
76         }
77 }
78 EXPORT_SYMBOL(sptlrpc_part2name);
79
80 enum lustre_sec_part sptlrpc_target_sec_part(struct obd_device *obd)
81 {
82         const char *type = obd->obd_type->typ_name;
83
84         if (!strcmp(type, LUSTRE_MDT_NAME))
85                 return LUSTRE_SP_MDT;
86         if (!strcmp(type, LUSTRE_OST_NAME))
87                 return LUSTRE_SP_OST;
88         if (!strcmp(type, LUSTRE_MGS_NAME))
89                 return LUSTRE_SP_MGS;
90
91         CERROR("unknown target %p(%s)\n", obd, type);
92         return LUSTRE_SP_ANY;
93 }
94 EXPORT_SYMBOL(sptlrpc_target_sec_part);
95
96 /****************************************
97  * user supplied flavor string parsing  *
98  ****************************************/
99
100 #ifdef HAVE_ADLER
101 #define BULK_HASH_ALG_DEFAULT   BULK_HASH_ALG_ADLER32
102 #else
103 #define BULK_HASH_ALG_DEFAULT   BULK_HASH_ALG_CRC32
104 #endif
105
106 typedef enum {
107         BULK_TYPE_N = 0,
108         BULK_TYPE_I = 1,
109         BULK_TYPE_P = 2
110 } bulk_type_t;
111
112 static void get_default_flavor(struct sptlrpc_flavor *sf)
113 {
114         sf->sf_rpc = SPTLRPC_FLVR_NULL;
115         sf->sf_bulk_ciph = BULK_CIPH_ALG_NULL;
116         sf->sf_bulk_hash = BULK_HASH_ALG_NULL;
117         sf->sf_flags = 0;
118 }
119
120 static void get_flavor_by_rpc(struct sptlrpc_rule *rule, __u16 rpc_flavor)
121 {
122         get_default_flavor(&rule->sr_flvr);
123
124         rule->sr_flvr.sf_rpc = rpc_flavor;
125
126         switch (rpc_flavor) {
127         case SPTLRPC_FLVR_NULL:
128                 break;
129         case SPTLRPC_FLVR_PLAIN:
130         case SPTLRPC_FLVR_KRB5N:
131         case SPTLRPC_FLVR_KRB5A:
132                 rule->sr_flvr.sf_bulk_hash = BULK_HASH_ALG_DEFAULT;
133                 break;
134         case SPTLRPC_FLVR_KRB5P:
135                 rule->sr_flvr.sf_bulk_ciph = BULK_CIPH_ALG_AES128;
136                 /* fall through */
137         case SPTLRPC_FLVR_KRB5I:
138                 rule->sr_flvr.sf_bulk_hash = BULK_HASH_ALG_SHA1;
139                 break;
140         default:
141                 LBUG();
142         }
143 }
144
145 static void get_flavor_by_bulk(struct sptlrpc_rule *rule,
146                                __u16 rpc_flavor, bulk_type_t bulk_type)
147 {
148         switch (bulk_type) {
149         case BULK_TYPE_N:
150                 rule->sr_flvr.sf_bulk_hash = BULK_HASH_ALG_NULL;
151                 rule->sr_flvr.sf_bulk_ciph = BULK_CIPH_ALG_NULL;
152                 break;
153         case BULK_TYPE_I:
154                 switch (rpc_flavor) {
155                 case SPTLRPC_FLVR_PLAIN:
156                 case SPTLRPC_FLVR_KRB5N:
157                 case SPTLRPC_FLVR_KRB5A:
158                         rule->sr_flvr.sf_bulk_hash = BULK_HASH_ALG_DEFAULT;
159                         break;
160                 case SPTLRPC_FLVR_KRB5I:
161                 case SPTLRPC_FLVR_KRB5P:
162                         rule->sr_flvr.sf_bulk_hash = BULK_HASH_ALG_SHA1;
163                         break;
164                 default:
165                         LBUG();
166                 }
167                 rule->sr_flvr.sf_bulk_ciph = BULK_CIPH_ALG_NULL;
168                 break;
169         case BULK_TYPE_P:
170                 rule->sr_flvr.sf_bulk_hash = BULK_HASH_ALG_SHA1;
171                 rule->sr_flvr.sf_bulk_ciph = BULK_CIPH_ALG_AES128;
172                 break;
173         default:
174                 LBUG();
175         }
176 }
177
178 static __u16 __flavors[] = {
179         SPTLRPC_FLVR_NULL,
180         SPTLRPC_FLVR_PLAIN,
181         SPTLRPC_FLVR_KRB5N,
182         SPTLRPC_FLVR_KRB5A,
183         SPTLRPC_FLVR_KRB5I,
184         SPTLRPC_FLVR_KRB5P,
185 };
186
187 #define __nflavors      ARRAY_SIZE(__flavors)
188
189 /*
190  * flavor string format: rpc[-bulk{n|i|p}[:cksum/enc]]
191  * for examples:
192  *  null
193  *  plain-bulki
194  *  krb5p-bulkn
195  *  krb5i-bulkp
196  *  krb5i-bulkp:sha512/arc4
197  */
198 static int parse_flavor(char *str, struct sptlrpc_rule *rule)
199 {
200         const char     *f;
201         char           *bulk, *alg, *enc;
202         char            buf[64];
203         bulk_type_t     bulk_type;
204         __u8            i;
205         ENTRY;
206
207         if (str == NULL || str[0] == '\0') {
208                 rule->sr_flvr.sf_rpc = SPTLRPC_FLVR_INVALID;
209                 goto out;
210         }
211
212         for (i = 0; i < __nflavors; i++) {
213                 f = sptlrpc_rpcflavor2name(__flavors[i]);
214                 if (strncmp(str, f, strlen(f)) == 0)
215                         break;
216         }
217
218         if (i >= __nflavors)
219                 GOTO(invalid, -EINVAL);
220
221         /* prepare local buffer thus we can modify it as we want */
222         strncpy(buf, str, 64);
223         buf[64 - 1] = '\0';
224
225         /* find bulk string */
226         bulk = strchr(buf, '-');
227         if (bulk)
228                 *bulk++ = '\0';
229
230         /* now the first part must equal to rpc flavor name */
231         if (strcmp(buf, f) != 0)
232                 GOTO(invalid, -EINVAL);
233
234         get_flavor_by_rpc(rule, __flavors[i]);
235
236         if (bulk == NULL)
237                 goto out;
238
239         /* find bulk algorithm string */
240         alg = strchr(bulk, ':');
241         if (alg)
242                 *alg++ = '\0';
243
244         /* verify bulk section */
245         if (strcmp(bulk, "bulkn") == 0) {
246                 rule->sr_flvr.sf_bulk_hash = BULK_HASH_ALG_NULL;
247                 rule->sr_flvr.sf_bulk_ciph = BULK_CIPH_ALG_NULL;
248                 bulk_type = BULK_TYPE_N;
249         } else if (strcmp(bulk, "bulki") == 0)
250                 bulk_type = BULK_TYPE_I;
251         else if (strcmp(bulk, "bulkp") == 0)
252                 bulk_type = BULK_TYPE_P;
253         else
254                 GOTO(invalid, -EINVAL);
255
256         /* null flavor don't support bulk i/p */
257         if (__flavors[i] == SPTLRPC_FLVR_NULL && bulk_type != BULK_TYPE_N)
258                 GOTO(invalid, -EINVAL);
259
260         /* plain policy dosen't support bulk p */
261         if (__flavors[i] == SPTLRPC_FLVR_PLAIN && bulk_type == BULK_TYPE_P)
262                 GOTO(invalid, -EINVAL);
263
264         get_flavor_by_bulk(rule, __flavors[i], bulk_type);
265
266         if (alg == NULL)
267                 goto out;
268
269         /* find encryption algorithm string */
270         enc = strchr(alg, '/');
271         if (enc)
272                 *enc++ = '\0';
273
274         /* checksum algorithm */
275         for (i = 0; i < BULK_HASH_ALG_MAX; i++) {
276                 if (strcmp(alg, sptlrpc_get_hash_name(i)) == 0) {
277                         rule->sr_flvr.sf_bulk_hash = i;
278                         break;
279                 }
280         }
281         if (i >= BULK_HASH_ALG_MAX)
282                 GOTO(invalid, -EINVAL);
283
284         /* privacy algorithm */
285         if (enc) {
286                 for (i = 0; i < BULK_CIPH_ALG_MAX; i++) {
287                         if (strcmp(enc, sptlrpc_get_ciph_name(i)) == 0) {
288                                 rule->sr_flvr.sf_bulk_ciph = i;
289                                 break;
290                         }
291                 }
292                 if (i >= BULK_CIPH_ALG_MAX)
293                         GOTO(invalid, -EINVAL);
294         }
295
296         /*
297          * bulk combination sanity checks
298          */
299         if (bulk_type == BULK_TYPE_P &&
300             rule->sr_flvr.sf_bulk_ciph == BULK_CIPH_ALG_NULL)
301                 GOTO(invalid, -EINVAL);
302
303         if (bulk_type == BULK_TYPE_I &&
304             (rule->sr_flvr.sf_bulk_hash == BULK_HASH_ALG_NULL ||
305              rule->sr_flvr.sf_bulk_ciph != BULK_CIPH_ALG_NULL))
306                 GOTO(invalid, -EINVAL);
307
308         if (bulk_type == BULK_TYPE_N &&
309             (rule->sr_flvr.sf_bulk_hash != BULK_HASH_ALG_NULL ||
310              rule->sr_flvr.sf_bulk_ciph != BULK_CIPH_ALG_NULL))
311                 GOTO(invalid, -EINVAL);
312
313 out:
314         return 0;
315 invalid:
316         CERROR("invalid flavor string: %s\n", str);
317         return -EINVAL;
318 }
319
320 /****************************************
321  * configure rules                      *
322  ****************************************/
323
324 static void sptlrpc_rule_init(struct sptlrpc_rule *rule)
325 {
326         rule->sr_netid = LNET_NIDNET(LNET_NID_ANY);
327         rule->sr_from = LUSTRE_SP_ANY;
328         rule->sr_to = LUSTRE_SP_ANY;
329         rule->sr_padding = 0;
330
331         get_default_flavor(&rule->sr_flvr);
332 }
333
334 /*
335  * format: network[.direction]=flavor
336  */
337 int sptlrpc_parse_rule(char *param, struct sptlrpc_rule *rule)
338 {
339         char           *flavor, *dir;
340         int             rc;
341
342         sptlrpc_rule_init(rule);
343
344         flavor = strchr(param, '=');
345         if (flavor == NULL) {
346                 CERROR("invalid param, no '='\n");
347                 RETURN(-EINVAL);
348         }
349         *flavor++ = '\0';
350
351         dir = strchr(param, '.');
352         if (dir)
353                 *dir++ = '\0';
354
355         /* 1.1 network */
356         if (strcmp(param, "default")) {
357                 rule->sr_netid = libcfs_str2net(param);
358                 if (rule->sr_netid == LNET_NIDNET(LNET_NID_ANY)) {
359                         CERROR("invalid network name: %s\n", param);
360                         RETURN(-EINVAL);
361                 }
362         }
363
364         /* 1.2 direction */
365         if (dir) {
366                 if (!strcmp(dir, "mdt2ost")) {
367                         rule->sr_from = LUSTRE_SP_MDT;
368                         rule->sr_to = LUSTRE_SP_OST;
369                 } else if (!strcmp(dir, "mdt2mdt")) {
370                         rule->sr_from = LUSTRE_SP_MDT;
371                         rule->sr_to = LUSTRE_SP_MDT;
372                 } else if (!strcmp(dir, "cli2ost")) {
373                         rule->sr_from = LUSTRE_SP_CLI;
374                         rule->sr_to = LUSTRE_SP_OST;
375                 } else if (!strcmp(dir, "cli2mdt")) {
376                         rule->sr_from = LUSTRE_SP_CLI;
377                         rule->sr_to = LUSTRE_SP_MDT;
378                 } else {
379                         CERROR("invalid rule dir segment: %s\n", dir);
380                         RETURN(-EINVAL);
381                 }
382         }
383
384         /* 2.1 flavor */
385         rc = parse_flavor(flavor, rule);
386         if (rc)
387                 RETURN(-EINVAL);
388
389         RETURN(0);
390 }
391 EXPORT_SYMBOL(sptlrpc_parse_rule);
392
393 void sptlrpc_rule_set_free(struct sptlrpc_rule_set *rset)
394 {
395         LASSERT(rset->srs_nslot ||
396                 (rset->srs_nrule == 0 && rset->srs_rules == NULL));
397
398         if (rset->srs_nslot) {
399                 OBD_FREE(rset->srs_rules,
400                          rset->srs_nslot * sizeof(*rset->srs_rules));
401                 sptlrpc_rule_set_init(rset);
402         }
403 }
404 EXPORT_SYMBOL(sptlrpc_rule_set_free);
405
406 /*
407  * return 0 if the rule set could accomodate one more rule.
408  * if @expand != 0, the rule set might be expanded.
409  */
410 int sptlrpc_rule_set_expand(struct sptlrpc_rule_set *rset, int expand)
411 {
412         struct sptlrpc_rule *rules;
413         int nslot;
414
415         if (rset->srs_nrule < rset->srs_nslot)
416                 return 0; 
417
418         if (expand == 0)
419                 return -E2BIG;
420
421         if (rset->srs_nslot == 0)
422                 nslot = 8;
423         else
424                 nslot = rset->srs_nslot + 8;
425
426         /* better use realloc() if available */
427         OBD_ALLOC(rules, nslot * sizeof(*rset->srs_rules));
428         if (rules == NULL)
429                 return -ENOMEM;
430
431         memcpy(rules, rset->srs_rules,
432                rset->srs_nrule * sizeof(*rset->srs_rules));
433
434         if (rset->srs_rules)
435                 OBD_FREE(rset->srs_rules,
436                          rset->srs_nslot * sizeof(*rset->srs_rules));
437
438         rset->srs_rules = rules;
439         rset->srs_nslot = nslot;
440         return 0;
441 }
442 EXPORT_SYMBOL(sptlrpc_rule_set_expand);
443
444 static inline int rule_spec_dir(struct sptlrpc_rule *rule)
445 {
446         return (rule->sr_from != LUSTRE_SP_ANY ||
447                 rule->sr_to != LUSTRE_SP_ANY);
448 }
449 static inline int rule_spec_net(struct sptlrpc_rule *rule)
450 {
451         return (rule->sr_netid != LNET_NIDNET(LNET_NID_ANY));
452 }
453 static inline int rule_match_dir(struct sptlrpc_rule *r1,
454                                  struct sptlrpc_rule *r2)
455 {
456         return (r1->sr_from == r2->sr_from && r1->sr_to == r2->sr_to);
457 }
458 static inline int rule_match_net(struct sptlrpc_rule *r1,
459                                  struct sptlrpc_rule *r2)
460 {
461         return (r1->sr_netid == r2->sr_netid);
462 }
463
464 /*
465  * merge @rule into @rset.
466  * if @expand != 0 then @rset slots might be expanded.
467  */
468 int sptlrpc_rule_set_merge(struct sptlrpc_rule_set *rset, 
469                            struct sptlrpc_rule *rule,
470                            int expand)
471 {
472         struct sptlrpc_rule      *p = rset->srs_rules;
473         int                       spec_dir, spec_net;
474         int                       rc, n, match = 0;
475
476         spec_net = rule_spec_net(rule);
477         spec_dir = rule_spec_dir(rule);
478
479         for (n = 0; n < rset->srs_nrule; n++) {
480                 p = &rset->srs_rules[n]; 
481
482                 /* test network match, if failed:
483                  * - spec rule: skip rules which is also spec rule match, until
484                  *   we hit a wild rule, which means no more chance
485                  * - wild rule: skip until reach the one which is also wild
486                  *   and matches
487                  */
488                 if (!rule_match_net(p, rule)) {
489                         if (spec_net) {
490                                 if (rule_spec_net(p))
491                                         continue;
492                                 else
493                                         break;
494                         } else {
495                                 continue;
496                         }
497                 }
498
499                 /* test dir match, same logic as net matching */
500                 if (!rule_match_dir(p, rule)) {
501                         if (spec_dir) {
502                                 if (rule_spec_dir(p))
503                                         continue;
504                                 else
505                                         break;
506                         } else {
507                                 continue;
508                         }
509                 }
510
511                 /* find a match */
512                 match = 1;
513                 break;
514         }
515
516         if (match) {
517                 LASSERT(n >= 0 && n < rset->srs_nrule);
518
519                 if (rule->sr_flvr.sf_rpc == SPTLRPC_FLVR_INVALID) {
520                         /* remove this rule */
521                         if (n < rset->srs_nrule - 1)
522                                 memmove(&rset->srs_rules[n],
523                                         &rset->srs_rules[n + 1],
524                                         (rset->srs_nrule - n - 1) *
525                                         sizeof(*rule));
526                         rset->srs_nrule--;
527                 } else {
528                         /* override the rule */
529                         memcpy(&rset->srs_rules[n], rule, sizeof(*rule));
530                 }
531         } else {
532                 LASSERT(n >= 0 && n <= rset->srs_nrule);
533
534                 if (rule->sr_flvr.sf_rpc != SPTLRPC_FLVR_INVALID) {
535                         rc = sptlrpc_rule_set_expand(rset, expand);
536                         if (rc)
537                                 return rc;
538
539                         if (n < rset->srs_nrule)
540                                 memmove(&rset->srs_rules[n + 1],
541                                         &rset->srs_rules[n],
542                                         (rset->srs_nrule - n) * sizeof(*rule));
543                         memcpy(&rset->srs_rules[n], rule, sizeof(*rule));
544                         rset->srs_nrule++;
545                 } else {
546                         CWARN("ignore the unmatched deletion\n");
547                 }
548         }
549
550         return 0;
551 }
552 EXPORT_SYMBOL(sptlrpc_rule_set_merge);
553
554 int sptlrpc_rule_set_from_log(struct sptlrpc_rule_set *rset,
555                               struct sptlrpc_conf_log *log)
556 {
557         LASSERT(rset);
558         LASSERT(log);
559
560         sptlrpc_rule_set_free(rset);
561
562         if (log->scl_nrule == 0)
563                 return 0;
564
565         OBD_ALLOC(rset->srs_rules, log->scl_nrule * sizeof(*log->scl_rules));
566         if (!rset->srs_rules)
567                 return -ENOMEM;
568
569         memcpy(rset->srs_rules, log->scl_rules,
570                log->scl_nrule * sizeof(*log->scl_rules));
571         rset->srs_nslot = rset->srs_nrule = log->scl_nrule;
572         return 0;
573 }
574 EXPORT_SYMBOL(sptlrpc_rule_set_from_log);
575
576 /*
577  * according to NID/from choose a flavor from rule set.
578  */
579 void sptlrpc_rule_set_choose(struct sptlrpc_rule_set *rset,
580                              enum lustre_sec_part from,
581                              lnet_nid_t nid,
582                              struct sptlrpc_flavor *sf)
583 {
584         struct sptlrpc_rule    *r;
585         int                     n;
586
587         for (n = 0; n < rset->srs_nrule; n++) {
588                 r = &rset->srs_rules[n];
589
590                 if (LNET_NIDNET(nid) != LNET_NIDNET(LNET_NID_ANY) &&
591                     r->sr_netid != LNET_NIDNET(LNET_NID_ANY) &&
592                     LNET_NIDNET(nid) != r->sr_netid)
593                         continue;
594
595                 if (from != LUSTRE_SP_ANY && r->sr_from != LUSTRE_SP_ANY &&
596                     from != r->sr_from)
597                         continue;
598
599                 *sf = r->sr_flvr;
600                 return;
601         }
602
603         /* no match found, set as default flavor */
604         get_default_flavor(sf);
605 }
606 EXPORT_SYMBOL(sptlrpc_rule_set_choose);
607
608 void sptlrpc_rule_set_dump(struct sptlrpc_rule_set *rset)
609 {
610         struct sptlrpc_rule *r;
611         int     n;
612
613         for (n = 0; n < rset->srs_nrule; n++) {
614                 r = &rset->srs_rules[n];
615                 CWARN("<%02d> from %x to %x, net %x, rpc %x\n", n,
616                       r->sr_from, r->sr_to, r->sr_netid, r->sr_flvr.sf_rpc);
617         }
618 }
619 EXPORT_SYMBOL(sptlrpc_rule_set_dump);
620
621 /****************************************
622  * sptlrpc config log                   *
623  ****************************************/
624
625 struct sptlrpc_conf_log *sptlrpc_conf_log_alloc(void)
626 {
627         struct sptlrpc_conf_log *log;
628
629         OBD_ALLOC_PTR(log);
630         if (log == NULL)
631                 return ERR_PTR(-ENOMEM);
632
633         log->scl_max = SPTLRPC_CONF_LOG_MAX;
634         return log;
635 }
636 EXPORT_SYMBOL(sptlrpc_conf_log_alloc);
637
638 void sptlrpc_conf_log_free(struct sptlrpc_conf_log *log)
639 {
640         LASSERT(log->scl_max == SPTLRPC_CONF_LOG_MAX);
641         OBD_FREE_PTR(log);
642 }
643 EXPORT_SYMBOL(sptlrpc_conf_log_free);
644
645 static __u32 get_log_rule_flags(enum lustre_sec_part from,
646                                 enum lustre_sec_part to,
647                                 unsigned int fl_udesc)
648 {
649         /* MDT->MDT; MDT->OST */
650         if (from == LUSTRE_SP_MDT)
651                 return PTLRPC_SEC_FL_ROOTONLY;
652         /* CLI->OST */
653         if (from == LUSTRE_SP_CLI && to == LUSTRE_SP_OST)
654                 return PTLRPC_SEC_FL_ROOTONLY | PTLRPC_SEC_FL_BULK;
655         /* CLI->MDT */
656         if (from == LUSTRE_SP_CLI && to == LUSTRE_SP_MDT)
657                 if (fl_udesc)
658                         return PTLRPC_SEC_FL_UDESC;
659
660         return 0;
661 }
662
663 /*
664  * generate config log: merge general and target rules, which
665  * match @from @to
666  */
667 int sptlrpc_conf_log_populate(struct sptlrpc_rule_set *gen,
668                               struct sptlrpc_rule_set *tgt,
669                               enum lustre_sec_part from,
670                               enum lustre_sec_part to,
671                               unsigned int fl_udesc,
672                               struct sptlrpc_conf_log *log)
673 {
674         struct sptlrpc_rule_set *src[2] = { gen, tgt };
675         struct sptlrpc_rule_set  dst;
676         struct sptlrpc_rule     *rule;
677         __u32                    flags;
678         int                      i, n, rc;
679
680         LASSERT(log);
681
682         dst.srs_nslot = log->scl_max;
683         dst.srs_nrule = 0;
684         dst.srs_rules = log->scl_rules;
685
686         /* merge general rules firstly, then target-specific rules */
687         for (i = 0; i < 2; i++) {
688                 if (src[i] == NULL)
689                         continue;
690
691                 for (n = 0; n < src[i]->srs_nrule; n++) {
692                         rule = &src[i]->srs_rules[n];
693
694                         if (from != LUSTRE_SP_ANY &&
695                             rule->sr_from != LUSTRE_SP_ANY &&
696                             rule->sr_from != from)
697                                 continue;
698                         if (to != LUSTRE_SP_ANY &&
699                             rule->sr_to != LUSTRE_SP_ANY &&
700                             rule->sr_to != to)
701                                 continue;
702
703                         rc = sptlrpc_rule_set_merge(&dst, rule, 0);
704                         if (rc) {
705                                 CERROR("can't merge: %d\n", rc);
706                                 return rc;
707                         }
708                 }
709         }
710
711         log->scl_nrule = dst.srs_nrule;
712
713         /* set flags for each rule */
714         flags = get_log_rule_flags(from, to, fl_udesc);
715
716         for (i = 0; i < log->scl_nrule; i++) {
717                 log->scl_rules[i].sr_flvr.sf_flags = flags;
718
719                 /* also clear the from/to fields which don't need to be known
720                  * accordingly. @from == ANY means this log is for target,
721                  * otherwise for client. */
722                 if (from != LUSTRE_SP_ANY)
723                         log->scl_rules[i].sr_from = LUSTRE_SP_ANY;
724                 log->scl_rules[i].sr_to = LUSTRE_SP_ANY;
725         }
726
727         return 0;
728 }
729 EXPORT_SYMBOL(sptlrpc_conf_log_populate);
730
731 /*
732  * extract config log from @lcfg
733  */
734 struct sptlrpc_conf_log *sptlrpc_conf_log_extract(struct lustre_cfg *lcfg)
735 {
736         struct sptlrpc_conf_log *log;
737         struct sptlrpc_rule     *r;
738         int                      i;
739         ENTRY;
740
741         log = lustre_cfg_buf(lcfg, 1);
742         if (log == NULL) {
743                 CERROR("no sptlrpc config data\n");
744                 RETURN(ERR_PTR(-EINVAL));
745         }
746
747         if (lcfg->lcfg_version == __swab32(LUSTRE_CFG_VERSION)) {
748                 __swab32s(&log->scl_max);
749                 __swab32s(&log->scl_nrule);
750         }
751
752         if (LUSTRE_CFG_BUFLEN(lcfg, 1) <
753             log->scl_max * sizeof(log->scl_rules[0])) {
754                 CERROR("mal-formed config log\n");
755                 RETURN(ERR_PTR(-EINVAL));
756         }
757
758         if (lcfg->lcfg_version == __swab32(LUSTRE_CFG_VERSION)) {
759                 for (i = 0; i < log->scl_nrule; i++) {
760                         r = &log->scl_rules[i];
761                         __swab32s(&r->sr_netid);
762                         __swab16s(&r->sr_flvr.sf_rpc);
763                         __swab32s(&r->sr_flvr.sf_flags);
764                 }
765         }
766
767         RETURN(log);
768 }
769 EXPORT_SYMBOL(sptlrpc_conf_log_extract);
770
771 void sptlrpc_conf_log_cleanup(struct sptlrpc_conf_log *log)
772 {
773         log->scl_nrule = 0;
774         memset(log->scl_rules, 0, sizeof(log->scl_rules));
775 }
776 EXPORT_SYMBOL(sptlrpc_conf_log_cleanup);
777
778 void sptlrpc_conf_log_dump(struct sptlrpc_conf_log *log)
779 {
780         struct sptlrpc_rule    *r;
781         int                     n;
782
783         CWARN("max %u, rule# %u part %u\n",
784               log->scl_max, log->scl_nrule, log->scl_part);
785
786         for (n = 0; n < log->scl_nrule; n++) {
787                 r = &log->scl_rules[n];
788                 CWARN("<%02d> %x -> %x, net %x, rpc %x\n", n,
789                       r->sr_from, r->sr_to, r->sr_netid, r->sr_flvr.sf_rpc);
790         }
791 }
792 EXPORT_SYMBOL(sptlrpc_conf_log_dump);
793
794 /*
795  * caller should guarantee that no concurrent calls to this function
796  */
797 #define SEC_ADAPT_DELAY         (10)
798
799 int sptlrpc_cliobd_process_config(struct obd_device *obd,
800                                   struct lustre_cfg *lcfg)
801 {
802         struct sptlrpc_conf_log *log;
803         struct obd_import       *imp;
804         int                      rc;
805
806         log = sptlrpc_conf_log_extract(lcfg);
807         if (IS_ERR(log)) {
808                 CERROR("extract log error: %ld\n", PTR_ERR(log));
809                 return PTR_ERR(log);
810         }
811
812         obd->u.cli.cl_sec_part = log->scl_part;
813
814         rc = sptlrpc_rule_set_from_log(&obd->u.cli.cl_sptlrpc_rset, log);
815         if (rc) {
816                 CERROR("failed create rule set: %d\n", rc);
817                 return rc;
818         }
819
820         imp = obd->u.cli.cl_import;
821         if (imp == NULL)
822                 return 0;
823
824         /* even if imp_sec_expire is already set, we'll override it to a
825          * newer (later) time */
826         spin_lock(&imp->imp_lock);
827         if (imp->imp_sec)
828                 imp->imp_sec_expire = cfs_time_current_sec() + SEC_ADAPT_DELAY;
829         spin_unlock(&imp->imp_lock);
830         return 0;
831 }
832 EXPORT_SYMBOL(sptlrpc_cliobd_process_config);