Line data Source code
1 : /* 2 : Unix SMB/CIFS implementation. 3 : 4 : dcerpc utility functions 5 : 6 : Copyright (C) Andrew Tridgell 2003 7 : Copyright (C) Jelmer Vernooij 2004 8 : 9 : This program is free software; you can redistribute it and/or modify 10 : it under the terms of the GNU General Public License as published by 11 : the Free Software Foundation; either version 3 of the License, or 12 : (at your option) any later version. 13 : 14 : This program is distributed in the hope that it will be useful, 15 : but WITHOUT ANY WARRANTY; without even the implied warranty of 16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 : GNU General Public License for more details. 18 : 19 : You should have received a copy of the GNU General Public License 20 : along with this program. If not, see <http://www.gnu.org/licenses/>. 21 : */ 22 : 23 : #include "includes.h" 24 : #include "../lib/util/dlinklist.h" 25 : #include "librpc/ndr/libndr.h" 26 : #include "librpc/ndr/ndr_table.h" 27 : #undef strcasecmp 28 : 29 : static struct ndr_interface_list *ndr_interfaces; 30 : 31 : /* 32 : register a ndr interface table 33 : */ 34 290196 : NTSTATUS ndr_table_register(const struct ndr_interface_table *table) 35 : { 36 17496 : struct ndr_interface_list *l; 37 : 38 15815682 : for (l = ndr_interfaces; l; l = l->next) { 39 : /* 40 : * If no GUID is supplied, use the name to determine 41 : * uniqueness. 42 : */ 43 15525486 : if (GUID_all_zero(&table->syntax_id.uuid)) { 44 14413068 : if (strcmp(table->name, 45 7206534 : l->table->name) != 0) { 46 15023934 : continue; 47 : } 48 0 : DBG_ERR("Attempt to register interface %s which has the " 49 : "same name as already registered interface\n", 50 : table->name); 51 : } else { 52 8318952 : if (!GUID_equal(&table->syntax_id.uuid, 53 8318952 : &l->table->syntax_id.uuid)) { 54 8318952 : continue; 55 : } 56 0 : DBG_ERR("Attempt to register interface %s which has the " 57 : "same UUID as already registered interface %s\n", 58 : table->name, l->table->name); 59 : } 60 0 : return NT_STATUS_OBJECT_NAME_COLLISION; 61 : } 62 : 63 : /* 64 : * This is a singleton instance guaranteed 65 : * by the above check to be only added once 66 : * into the list so we can allocate off the NULL 67 : * context. We never want this to be freed 68 : * until process shutdown. If needed we could 69 : * add a deregister function that walks and 70 : * frees the list. 71 : */ 72 : 73 290196 : l = talloc(NULL, struct ndr_interface_list); 74 290196 : l->table = table; 75 : 76 290196 : DLIST_ADD(ndr_interfaces, l); 77 : 78 290196 : return NT_STATUS_OK; 79 : } 80 : 81 : /* 82 : find the pipe name for a local IDL interface 83 : */ 84 382 : const char *ndr_interface_name(const struct GUID *uuid, uint32_t if_version) 85 : { 86 0 : const struct ndr_interface_list *l; 87 36859 : for (l=ndr_table_list();l;l=l->next) { 88 36856 : if (GUID_equal(&l->table->syntax_id.uuid, uuid) && 89 379 : l->table->syntax_id.if_version == if_version) { 90 379 : return l->table->name; 91 : } 92 : } 93 3 : return "UNKNOWN"; 94 : } 95 : 96 : /* 97 : find the number of calls defined by local IDL 98 : */ 99 0 : int ndr_interface_num_calls(const struct GUID *uuid, uint32_t if_version) 100 : { 101 0 : const struct ndr_interface_list *l; 102 0 : for (l=ndr_table_list();l;l=l->next){ 103 0 : if (GUID_equal(&l->table->syntax_id.uuid, uuid) && 104 0 : l->table->syntax_id.if_version == if_version) { 105 0 : return l->table->num_calls; 106 : } 107 : } 108 0 : return -1; 109 : } 110 : 111 : 112 : /* 113 : find a dcerpc interface by name 114 : */ 115 37 : const struct ndr_interface_table *ndr_table_by_name(const char *name) 116 : { 117 35 : const struct ndr_interface_list *l; 118 1917 : for (l=ndr_table_list();l;l=l->next) { 119 1917 : if (strcasecmp(l->table->name, name) == 0) { 120 37 : return l->table; 121 : } 122 : } 123 0 : return NULL; 124 : } 125 : 126 : /* 127 : find a dcerpc interface by syntax 128 : */ 129 0 : const struct ndr_interface_table *ndr_table_by_syntax(const struct ndr_syntax_id *syntax) 130 : { 131 0 : const struct ndr_interface_list *l; 132 0 : if (GUID_all_zero(&syntax->uuid)) { 133 : /* These are not unique */ 134 0 : return NULL; 135 : } 136 0 : for (l=ndr_table_list();l;l=l->next) { 137 0 : if (ndr_syntax_id_equal(&l->table->syntax_id, syntax)) { 138 0 : return l->table; 139 : } 140 : } 141 0 : return NULL; 142 : } 143 : 144 : /* 145 : find a dcerpc interface by uuid 146 : */ 147 0 : const struct ndr_interface_table *ndr_table_by_uuid(const struct GUID *uuid) 148 : { 149 0 : const struct ndr_interface_list *l; 150 0 : if (GUID_all_zero(uuid)) { 151 : /* These are not unique */ 152 0 : return NULL; 153 : } 154 0 : for (l=ndr_table_list();l;l=l->next) { 155 0 : if (GUID_equal(&l->table->syntax_id.uuid, uuid)) { 156 0 : return l->table; 157 : } 158 : } 159 0 : return NULL; 160 : } 161 : 162 : /* 163 : return the list of registered dcerpc_pipes 164 : */ 165 658 : const struct ndr_interface_list *ndr_table_list(void) 166 : { 167 658 : ndr_table_init(); 168 658 : return ndr_interfaces; 169 : } 170 : 171 : 172 3113 : NTSTATUS ndr_table_init(void) 173 : { 174 197 : static bool initialized = false; 175 : 176 3113 : if (initialized) return NT_STATUS_OK; 177 2687 : initialized = true; 178 : 179 2687 : ndr_table_register_builtin_tables(); 180 : 181 2687 : return NT_STATUS_OK; 182 : }