/src/samba/librpc/ndr/ndr_table.c
Line | Count | Source |
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 | | NTSTATUS ndr_table_register(const struct ndr_interface_table *table) |
35 | 0 | { |
36 | 0 | struct ndr_interface_list *l; |
37 | |
|
38 | 0 | for (l = ndr_interfaces; l; l = l->next) { |
39 | | /* |
40 | | * If no GUID is supplied, use the name to determine |
41 | | * uniqueness. |
42 | | */ |
43 | 0 | if (GUID_all_zero(&table->syntax_id.uuid)) { |
44 | 0 | if (strcmp(table->name, |
45 | 0 | l->table->name) != 0) { |
46 | 0 | continue; |
47 | 0 | } |
48 | 0 | DBG_ERR("Attempt to register interface %s which has the " |
49 | 0 | "same name as already registered interface\n", |
50 | 0 | table->name); |
51 | 0 | } else { |
52 | 0 | if (!GUID_equal(&table->syntax_id.uuid, |
53 | 0 | &l->table->syntax_id.uuid)) { |
54 | 0 | continue; |
55 | 0 | } |
56 | 0 | DBG_ERR("Attempt to register interface %s which has the " |
57 | 0 | "same UUID as already registered interface %s\n", |
58 | 0 | table->name, l->table->name); |
59 | 0 | } |
60 | 0 | return NT_STATUS_OBJECT_NAME_COLLISION; |
61 | 0 | } |
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 | 0 | l = talloc(NULL, struct ndr_interface_list); |
74 | 0 | l->table = table; |
75 | |
|
76 | 0 | DLIST_ADD(ndr_interfaces, l); |
77 | |
|
78 | 0 | return NT_STATUS_OK; |
79 | 0 | } |
80 | | |
81 | | /* |
82 | | find the pipe name for a local IDL interface |
83 | | */ |
84 | | const char *ndr_interface_name(const struct GUID *uuid, uint32_t if_version) |
85 | 0 | { |
86 | 0 | const struct ndr_interface_list *l; |
87 | 0 | for (l=ndr_table_list();l;l=l->next) { |
88 | 0 | if (GUID_equal(&l->table->syntax_id.uuid, uuid) && |
89 | 0 | l->table->syntax_id.if_version == if_version) { |
90 | 0 | return l->table->name; |
91 | 0 | } |
92 | 0 | } |
93 | 0 | return "UNKNOWN"; |
94 | 0 | } |
95 | | |
96 | | /* |
97 | | find the number of calls defined by local IDL |
98 | | */ |
99 | | int ndr_interface_num_calls(const struct GUID *uuid, uint32_t if_version) |
100 | 0 | { |
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 | 0 | } |
107 | 0 | } |
108 | 0 | return -1; |
109 | 0 | } |
110 | | |
111 | | |
112 | | /* |
113 | | find a dcerpc interface by name |
114 | | */ |
115 | | const struct ndr_interface_table *ndr_table_by_name(const char *name) |
116 | 0 | { |
117 | 0 | const struct ndr_interface_list *l; |
118 | 0 | for (l=ndr_table_list();l;l=l->next) { |
119 | 0 | if (strcasecmp(l->table->name, name) == 0) { |
120 | 0 | return l->table; |
121 | 0 | } |
122 | 0 | } |
123 | 0 | return NULL; |
124 | 0 | } |
125 | | |
126 | | /* |
127 | | find a dcerpc interface by syntax |
128 | | */ |
129 | | const struct ndr_interface_table *ndr_table_by_syntax(const struct ndr_syntax_id *syntax) |
130 | 0 | { |
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 | 0 | } |
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 | 0 | } |
140 | 0 | } |
141 | 0 | return NULL; |
142 | 0 | } |
143 | | |
144 | | /* |
145 | | find a dcerpc interface by uuid |
146 | | */ |
147 | | const struct ndr_interface_table *ndr_table_by_uuid(const struct GUID *uuid) |
148 | 0 | { |
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 | 0 | } |
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 | 0 | } |
158 | 0 | } |
159 | 0 | return NULL; |
160 | 0 | } |
161 | | |
162 | | /* |
163 | | return the list of registered dcerpc_pipes |
164 | | */ |
165 | | const struct ndr_interface_list *ndr_table_list(void) |
166 | 0 | { |
167 | 0 | ndr_table_init(); |
168 | 0 | return ndr_interfaces; |
169 | 0 | } |
170 | | |
171 | | |
172 | | NTSTATUS ndr_table_init(void) |
173 | 0 | { |
174 | 0 | static bool initialized = false; |
175 | |
|
176 | 0 | if (initialized) return NT_STATUS_OK; |
177 | 0 | initialized = true; |
178 | |
|
179 | 0 | ndr_table_register_builtin_tables(); |
180 | |
|
181 | 0 | return NT_STATUS_OK; |
182 | 0 | } |