11d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich/* lookup_table.c --
21d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * Copyright 2009 Red Hat Inc., Durham, North Carolina.
31d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * All Rights Reserved.
41d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich *
51d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * This library is free software; you can redistribute it and/or
61d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * modify it under the terms of the GNU Lesser General Public
71d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * License as published by the Free Software Foundation; either
81d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * version 2.1 of the License, or (at your option) any later version.
91d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich *
101d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * This library is distributed in the hope that it will be useful,
111d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * but WITHOUT ANY WARRANTY; without even the implied warranty of
121d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
131d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * Lesser General Public License for more details.
141d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich *
151d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * You should have received a copy of the GNU Lesser General Public
161d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * License along with this library; if not, write to the Free Software
171d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
181d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich *
191d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * Authors:
201d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich *      Steve Grubb <sgrubb@redhat.com>
211d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich */
221d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
231d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include "config.h"
241d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <stddef.h>
251d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <linux/capability.h>
261d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <strings.h>
271d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
281d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
291d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifndef CAP_LAST_CAP
301d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define CAP_LAST_CAP CAP_AUDIT_CONTROL
311d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
321d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#undef cap_valid
331d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define cap_valid(x) ((x) <= CAP_LAST_CAP)
341d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
351d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
361d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstruct transtab {
371d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich    int   value;
381d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich    int   offset;
391d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich};
401d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
411d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define MSGSTRFIELD(line) MSGSTRFIELD1(line)
421d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define MSGSTRFIELD1(line) str##line
431d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
441d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
451d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich/* To create the following tables in a DSO-friendly way we split them in
461d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich   two separate variables: a long string which is created by concatenating
471d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich   all strings referenced in the table and the table itself, which uses
481d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich   offsets instead of string pointers.  To do this without increasing
491d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich   the maintenance burden we use a lot of preprocessor magic.  All the
501d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich   maintainer has to do is to add a new entry to the included file and
511d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich   recompile.  */
521d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
531d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic const union captab_msgstr_t {
541d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich    struct {
551d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define _S(n, s) char MSGSTRFIELD(__LINE__)[sizeof (s)];
561d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include "captab.h"
571d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#undef _S
581d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich    };
591d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich    char str[0];
601d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich} captab_msgstr = { {
611d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define _S(n, s) s,
621d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include "captab.h"
631d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#undef _S
641d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich} };
651d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic const struct transtab captab[] = {
661d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define _S(n, s) { n, offsetof(union captab_msgstr_t,  \
671d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich                               MSGSTRFIELD(__LINE__)) },
681d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include "captab.h"
691d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#undef _S
701d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich};
711d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define CAP_NG_CAPABILITY_NAMES (sizeof(captab)/sizeof(captab[0]))
721d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
731d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
741d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
751d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
761d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic int capng_lookup_name(const struct transtab *table,
771d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		const char *tabstr, size_t length, const char *name)
781d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
791d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	size_t i;
801d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
811d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	for (i = 0; i < length; i++) {
821d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (!strcasecmp(tabstr + table[i].offset, name))
831d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			return table[i].value;
841d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
851d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return -1;
861d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
871d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
881d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic const char *capng_lookup_number(const struct transtab *table,
891d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich                                       const char *tabstr, size_t length,
901d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich                                       int number)
911d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
921d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	size_t i;
931d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
941d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	for (i = 0; i < length; i++) {
951d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (table[i].value == number)
961d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			return tabstr + table[i].offset;
971d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
981d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return NULL;
991d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
1001d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
1011d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichint capng_name_to_capability(const char *name)
1021d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
1031d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return capng_lookup_name(captab, captab_msgstr.str,
1041d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich                                 CAP_NG_CAPABILITY_NAMES, name);
1051d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
1061d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
1071d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichconst char *capng_capability_to_name(unsigned int capability)
1081d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
1091d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (!cap_valid(capability))
1101d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return NULL;
1111d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
1121d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return capng_lookup_number(captab, captab_msgstr.str,
1131d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich                                   CAP_NG_CAPABILITY_NAMES, capability);
1141d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
1151d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
116