]>
Commit | Line | Data |
---|---|---|
e1ee0e20 SC |
1 | /* |
2 | * Copyright (C) 2010 Sansar Choinyambuu | |
3 | * HSR Hochschule fuer Technik Rapperswil | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms of the GNU General Public License as published by the | |
7 | * Free Software Foundation; either version 2 of the License, or (at your | |
8 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, but | |
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
12 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
13 | * for more details. | |
14 | */ | |
15 | ||
54eb669d | 16 | #include "pb_reason_string_msg.h" |
e1ee0e20 | 17 | |
7e432eff AS |
18 | #include <bio/bio_writer.h> |
19 | #include <bio/bio_reader.h> | |
f05b4272 | 20 | #include <utils/debug.h> |
e1ee0e20 | 21 | |
54eb669d | 22 | typedef struct private_pb_reason_string_msg_t private_pb_reason_string_msg_t; |
e1ee0e20 SC |
23 | |
24 | /** | |
25 | * PB-Language-Preference message (see section 4.11 of RFC 5793) | |
26 | * | |
27 | * 0 1 2 3 | |
28 | * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | |
29 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
30 | * | Reason String Length | | |
31 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
32 | * | Reason String (Variable Length) | | |
33 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
34 | * | Lang Code Len | Reason String Language Code (Variable Length) | | |
35 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
36 | */ | |
37 | ||
e1ee0e20 | 38 | /** |
97613b3b | 39 | * Private data of a pb_reason_string_msg_t object. |
e1ee0e20 SC |
40 | * |
41 | */ | |
54eb669d | 42 | struct private_pb_reason_string_msg_t { |
e1ee0e20 | 43 | /** |
54eb669d | 44 | * Public pb_reason_string_msg_t interface. |
e1ee0e20 | 45 | */ |
54eb669d | 46 | pb_reason_string_msg_t public; |
e1ee0e20 SC |
47 | |
48 | /** | |
49 | * PB-TNC message type | |
50 | */ | |
51 | pb_tnc_msg_type_t type; | |
375dacca | 52 | |
e1ee0e20 SC |
53 | /** |
54 | * Reason string | |
55 | */ | |
56 | chunk_t reason_string; | |
375dacca | 57 | |
e1ee0e20 SC |
58 | /** |
59 | * Language code | |
60 | */ | |
61 | chunk_t language_code; | |
62 | ||
63 | /** | |
64 | * Encoded message | |
65 | */ | |
66 | chunk_t encoding; | |
67 | }; | |
68 | ||
54eb669d AS |
69 | METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t, |
70 | private_pb_reason_string_msg_t *this) | |
e1ee0e20 SC |
71 | { |
72 | return this->type; | |
73 | } | |
74 | ||
54eb669d AS |
75 | METHOD(pb_tnc_msg_t, get_encoding, chunk_t, |
76 | private_pb_reason_string_msg_t *this) | |
e1ee0e20 SC |
77 | { |
78 | return this->encoding; | |
79 | } | |
375dacca | 80 | |
54eb669d AS |
81 | METHOD(pb_tnc_msg_t, build, void, |
82 | private_pb_reason_string_msg_t *this) | |
e1ee0e20 | 83 | { |
7e432eff | 84 | bio_writer_t *writer; |
e1ee0e20 | 85 | |
3a16bec8 AS |
86 | if (this->encoding.ptr) |
87 | { | |
88 | return; | |
89 | } | |
7e432eff | 90 | writer = bio_writer_create(64); |
54eb669d AS |
91 | writer->write_data32(writer, this->reason_string); |
92 | writer->write_data8 (writer, this->language_code); | |
e1ee0e20 | 93 | |
e1ee0e20 SC |
94 | this->encoding = writer->get_buf(writer); |
95 | this->encoding = chunk_clone(this->encoding); | |
96 | writer->destroy(writer); | |
97 | } | |
98 | ||
54eb669d AS |
99 | METHOD(pb_tnc_msg_t, process, status_t, |
100 | private_pb_reason_string_msg_t *this, u_int32_t *offset) | |
e1ee0e20 | 101 | { |
7e432eff | 102 | bio_reader_t *reader; |
e1ee0e20 | 103 | |
7e432eff | 104 | reader = bio_reader_create(this->encoding); |
a6bf8e91 AS |
105 | if (!reader->read_data32(reader, &this->reason_string)) |
106 | { | |
54eb669d AS |
107 | DBG1(DBG_TNC, "could not parse reason string"); |
108 | reader->destroy(reader); | |
109 | *offset = 0; | |
a6bf8e91 AS |
110 | return FAILED; |
111 | }; | |
e150442b | 112 | this->reason_string = chunk_clone(this->reason_string); |
375dacca | 113 | |
54eb669d AS |
114 | if (this->reason_string.len && |
115 | this->reason_string.ptr[this->reason_string.len-1] == '\0') | |
116 | { | |
117 | DBG1(DBG_TNC, "reason string must not be null terminated"); | |
118 | reader->destroy(reader); | |
119 | *offset = 3 + this->reason_string.len; | |
120 | return FAILED; | |
121 | } | |
122 | ||
a6bf8e91 AS |
123 | if (!reader->read_data8(reader, &this->language_code)) |
124 | { | |
54eb669d AS |
125 | DBG1(DBG_TNC, "could not parse language code"); |
126 | reader->destroy(reader); | |
127 | *offset = 4 + this->reason_string.len; | |
a6bf8e91 AS |
128 | return FAILED; |
129 | }; | |
e150442b | 130 | this->language_code = chunk_clone(this->language_code); |
e1ee0e20 | 131 | reader->destroy(reader); |
54eb669d AS |
132 | |
133 | if (this->language_code.len && | |
134 | this->language_code.ptr[this->language_code.len-1] == '\0') | |
135 | { | |
136 | DBG1(DBG_TNC, "language code must not be null terminated"); | |
137 | *offset = 4 + this->reason_string.len + this->language_code.len; | |
138 | return FAILED; | |
139 | } | |
140 | ||
e1ee0e20 SC |
141 | return SUCCESS; |
142 | } | |
143 | ||
54eb669d AS |
144 | METHOD(pb_tnc_msg_t, destroy, void, |
145 | private_pb_reason_string_msg_t *this) | |
e1ee0e20 SC |
146 | { |
147 | free(this->encoding.ptr); | |
148 | free(this->reason_string.ptr); | |
149 | free(this->language_code.ptr); | |
150 | free(this); | |
151 | } | |
152 | ||
54eb669d AS |
153 | METHOD(pb_reason_string_msg_t, get_reason_string, chunk_t, |
154 | private_pb_reason_string_msg_t *this) | |
e1ee0e20 SC |
155 | { |
156 | return this->reason_string; | |
157 | } | |
158 | ||
54eb669d AS |
159 | METHOD(pb_reason_string_msg_t, get_language_code, chunk_t, |
160 | private_pb_reason_string_msg_t *this) | |
e1ee0e20 SC |
161 | { |
162 | return this->language_code; | |
163 | } | |
164 | ||
165 | /** | |
166 | * See header | |
167 | */ | |
54eb669d | 168 | pb_tnc_msg_t *pb_reason_string_msg_create_from_data(chunk_t data) |
e1ee0e20 | 169 | { |
54eb669d | 170 | private_pb_reason_string_msg_t *this; |
e1ee0e20 SC |
171 | |
172 | INIT(this, | |
173 | .public = { | |
174 | .pb_interface = { | |
175 | .get_type = _get_type, | |
176 | .get_encoding = _get_encoding, | |
177 | .build = _build, | |
178 | .process = _process, | |
179 | .destroy = _destroy, | |
180 | }, | |
e1ee0e20 | 181 | .get_reason_string = _get_reason_string, |
e1ee0e20 SC |
182 | .get_language_code = _get_language_code, |
183 | }, | |
184 | .type = PB_MSG_REASON_STRING, | |
185 | .encoding = chunk_clone(data), | |
186 | ); | |
187 | ||
188 | return &this->public.pb_interface; | |
189 | } | |
190 | ||
191 | /** | |
192 | * See header | |
193 | */ | |
54eb669d AS |
194 | pb_tnc_msg_t *pb_reason_string_msg_create(chunk_t reason_string, |
195 | chunk_t language_code) | |
e1ee0e20 | 196 | { |
54eb669d | 197 | private_pb_reason_string_msg_t *this; |
e1ee0e20 SC |
198 | |
199 | INIT(this, | |
200 | .public = { | |
201 | .pb_interface = { | |
202 | .get_type = _get_type, | |
203 | .get_encoding = _get_encoding, | |
204 | .build = _build, | |
205 | .process = _process, | |
206 | .destroy = _destroy, | |
207 | }, | |
e1ee0e20 | 208 | .get_reason_string = _get_reason_string, |
e1ee0e20 SC |
209 | .get_language_code = _get_language_code, |
210 | }, | |
211 | .type = PB_MSG_REASON_STRING, | |
e150442b AS |
212 | .reason_string = chunk_clone(reason_string), |
213 | .language_code = chunk_clone(language_code), | |
e1ee0e20 SC |
214 | ); |
215 | ||
216 | return &this->public.pb_interface; | |
217 | } |