[efi] Include installed protocol list in unknown handle names
[ipxe.git] / src / net / oncrpc / oncrpc_iob.c
1 /*
2 * Copyright (C) 2013 Marin Hannache <ipxe@mareo.fr>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 */
19
20 #include <stdint.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <assert.h>
25 #include <errno.h>
26 #include <byteswap.h>
27 #include <ipxe/socket.h>
28 #include <ipxe/tcpip.h>
29 #include <ipxe/in.h>
30 #include <ipxe/iobuf.h>
31 #include <ipxe/xfer.h>
32 #include <ipxe/open.h>
33 #include <ipxe/uri.h>
34 #include <ipxe/features.h>
35 #include <ipxe/oncrpc.h>
36 #include <ipxe/oncrpc_iob.h>
37
38 /** @file
39 *
40 * SUN ONC RPC protocol
41 *
42 */
43
44 size_t oncrpc_iob_add_fields ( struct io_buffer *io_buf,
45 const struct oncrpc_field fields[] ) {
46 size_t i;
47 size_t s = 0;
48
49 struct oncrpc_field f;
50
51 if ( ! io_buf )
52 return 0;
53
54 for ( i = 0; fields[i].type != oncrpc_none; i++ ) {
55 f = fields[i];
56 switch ( f.type ) {
57 case oncrpc_int32:
58 s += oncrpc_iob_add_int ( io_buf, f.value.int32 );
59 break;
60
61 case oncrpc_int64:
62 s += oncrpc_iob_add_int64 ( io_buf, f.value.int64 );
63 break;
64
65 case oncrpc_str:
66 s += oncrpc_iob_add_string ( io_buf, f.value.str );
67 break;
68
69 case oncrpc_array:
70 s += oncrpc_iob_add_array ( io_buf,
71 f.value.array.length,
72 f.value.array.ptr );
73 break;
74
75 case oncrpc_intarray:
76 s += oncrpc_iob_add_intarray ( io_buf,
77 f.value.intarray.length,
78 f.value.intarray.ptr );
79 break;
80
81 case oncrpc_cred:
82 s += oncrpc_iob_add_cred ( io_buf, f.value.cred);
83 break;
84
85 default:
86 return s;
87 }
88 }
89
90 return s;
91 }
92
93 /**
94 * Add an array of bytes to the end of an I/O buffer
95 *
96 * @v io_buf I/O buffer
97 * @v val String
98 * @ret size Size of the data written
99 *
100 * In the ONC RPC protocol, every data is four byte paded, we add padding when
101 * necessary by using oncrpc_align()
102 */
103 size_t oncrpc_iob_add_array ( struct io_buffer *io_buf, size_t length,
104 const void *data ) {
105 size_t padding = oncrpc_align ( length ) - length;
106
107 oncrpc_iob_add_int ( io_buf, length );
108 memcpy ( iob_put ( io_buf, length ), data, length );
109 memset ( iob_put ( io_buf, padding ), 0, padding );
110
111 return length + padding + sizeof ( uint32_t );
112 }
113
114 /**
115 * Add an int array to the end of an I/O buffer
116 *
117 * @v io_buf I/O buffer
118 * @v length Length od the array
119 * @v val Int array
120 * @ret size Size of the data written
121 */
122 size_t oncrpc_iob_add_intarray ( struct io_buffer *io_buf, size_t length,
123 const uint32_t *array ) {
124 size_t i;
125
126 oncrpc_iob_add_int ( io_buf, length );
127
128 for ( i = 0; i < length; ++i )
129 oncrpc_iob_add_int ( io_buf, array[i] );
130
131 return ( ( length + 1 ) * sizeof ( uint32_t ) );
132 }
133
134 /**
135 * Add credential information to the end of an I/O buffer
136 *
137 * @v io_buf I/O buffer
138 * @v cred Credential information
139 * @ret size Size of the data written
140 */
141 size_t oncrpc_iob_add_cred ( struct io_buffer *io_buf,
142 const struct oncrpc_cred *cred ) {
143 struct oncrpc_cred_sys *syscred;
144 size_t s;
145
146 struct oncrpc_field credfields[] = {
147 ONCRPC_FIELD ( int32, cred->flavor ),
148 ONCRPC_FIELD ( int32, cred->length ),
149 ONCRPC_FIELD_END,
150 };
151
152 if ( ! io_buf || ! cred )
153 return 0;
154
155 s = oncrpc_iob_add_fields ( io_buf, credfields);
156
157 switch ( cred->flavor ) {
158 case ONCRPC_AUTH_NONE:
159 break;
160
161 case ONCRPC_AUTH_SYS:
162 syscred = container_of ( cred, struct oncrpc_cred_sys,
163 credential );
164
165 struct oncrpc_field syscredfields[] = {
166 ONCRPC_FIELD ( int32, syscred->stamp ),
167 ONCRPC_FIELD ( str, syscred->hostname ),
168 ONCRPC_FIELD ( int32, syscred->uid ),
169 ONCRPC_FIELD ( int32, syscred->gid ),
170 ONCRPC_SUBFIELD ( intarray, syscred->aux_gid_len,
171 syscred->aux_gid ),
172 ONCRPC_FIELD_END,
173 };
174
175 s += oncrpc_iob_add_fields ( io_buf, syscredfields );
176 break;
177 }
178
179 return s;
180 }
181
182 /**
183 * Get credential information from the beginning of an I/O buffer
184 *
185 * @v io_buf I/O buffer
186 * @v cred Struct where the information will be saved
187 * @ret size Size of the data read
188 */
189 size_t oncrpc_iob_get_cred ( struct io_buffer *io_buf,
190 struct oncrpc_cred *cred ) {
191 if ( cred == NULL )
192 return * ( uint32_t * ) io_buf->data;
193
194 cred->flavor = oncrpc_iob_get_int ( io_buf );
195 cred->length = oncrpc_iob_get_int ( io_buf );
196
197 iob_pull ( io_buf, cred->length );
198
199 return ( 2 * sizeof ( uint32_t ) + cred->length );
200 }