2 * Copyright (C) 2012-2014 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
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>.
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
16 #include "ietf_attr_op_status.h"
18 #include <pa_tnc/pa_tnc_msg.h>
19 #include <bio/bio_writer.h>
20 #include <bio/bio_reader.h>
21 #include <utils/debug.h>
25 typedef struct private_ietf_attr_op_status_t private_ietf_attr_op_status_t
;
27 ENUM(op_status_names
, OP_STATUS_UNKNOWN
, OP_STATUS_OPERATIONAL
,
34 ENUM(op_result_names
, OP_RESULT_UNKNOWN
, OP_RESULT_UNSUCCESSFUL
,
42 * PA-TNC Operational Status type (see section 4.2.5 of RFC 5792)
45 * 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
46 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47 * | Status | Result | Reserved |
48 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51 * | Last Use (continued) |
52 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53 * | Last Use (continued) |
54 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55 * | Last Use (continued) |
56 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57 * | Last Use (continued) |
58 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61 #define OP_STATUS_SIZE 24
64 * Private data of an ietf_attr_op_status_t object.
66 struct private_ietf_attr_op_status_t
{
69 * Public members of ietf_attr_op_status_t
71 ietf_attr_op_status_t
public;
74 * Vendor-specific attribute type
79 * Length of attribute value
84 * Attribute value or segment
114 METHOD(pa_tnc_attr_t
, get_type
, pen_type_t
,
115 private_ietf_attr_op_status_t
*this)
120 METHOD(pa_tnc_attr_t
, get_value
, chunk_t
,
121 private_ietf_attr_op_status_t
*this)
126 METHOD(pa_tnc_attr_t
, get_noskip_flag
, bool,
127 private_ietf_attr_op_status_t
*this)
129 return this->noskip_flag
;
132 METHOD(pa_tnc_attr_t
, set_noskip_flag
,void,
133 private_ietf_attr_op_status_t
*this, bool noskip
)
135 this->noskip_flag
= noskip
;
138 METHOD(pa_tnc_attr_t
, build
, void,
139 private_ietf_attr_op_status_t
*this)
141 bio_writer_t
*writer
;
150 /* Conversion from time_t to RFC 3339 ASCII string */
151 gmtime_r(&this->last_use
, &t
);
152 snprintf(last_use
, 21, "%04d-%02d-%02dT%02d:%02d:%02dZ", 1900 + t
.tm_year
,
153 t
.tm_mon
+ 1, t
.tm_mday
, t
.tm_hour
, t
.tm_min
, t
.tm_sec
);
155 writer
= bio_writer_create(OP_STATUS_SIZE
);
156 writer
->write_uint8 (writer
, this->status
);
157 writer
->write_uint8 (writer
, this->result
);
158 writer
->write_uint16(writer
, 0x0000);
159 writer
->write_data (writer
, chunk_create(last_use
, 20));
161 this->value
= writer
->extract_buf(writer
);
162 this->length
= this->value
.len
;
163 writer
->destroy(writer
);
166 METHOD(pa_tnc_attr_t
, process
, status_t
,
167 private_ietf_attr_op_status_t
*this, u_int32_t
*offset
)
169 bio_reader_t
*reader
;
176 if (this->value
.len
< this->length
)
180 if (this->value
.len
!= OP_STATUS_SIZE
)
182 DBG1(DBG_TNC
, "incorrect size for IETF operational status");
185 reader
= bio_reader_create(this->value
);
186 reader
->read_uint8 (reader
, &this->status
);
187 reader
->read_uint8 (reader
, &this->result
);
188 reader
->read_uint16(reader
, &reserved
);
189 reader
->read_data (reader
, 20, &last_use
);
190 reader
->destroy(reader
);
192 if (this->status
> OP_STATUS_ROOF
)
194 DBG1(DBG_TNC
, "invalid status value %c for IETF operational status",
201 if (this->result
> OP_RESULT_ROOF
)
203 DBG1(DBG_TNC
, "invalid result value %c for IETF operational status",
210 /* Conversion from RFC 3339 ASCII string to time_t */
211 if (sscanf(last_use
.ptr
, "%4d-%2d-%2dT%2d:%2d:%2dZ", &t
.tm_year
, &t
.tm_mon
,
212 &t
.tm_mday
, &t
.tm_hour
, &t
.tm_min
, &t
.tm_sec
) != 6)
214 DBG1(DBG_TNC
, "invalid last_use time format in IETF operational status");
220 this->last_use
= mktime(&t
) - timezone
;
225 METHOD(pa_tnc_attr_t
, get_ref
, pa_tnc_attr_t
*,
226 private_ietf_attr_op_status_t
*this)
229 return &this->public.pa_tnc_attribute
;
232 METHOD(pa_tnc_attr_t
, destroy
, void,
233 private_ietf_attr_op_status_t
*this)
235 if (ref_put(&this->ref
))
237 free(this->value
.ptr
);
242 METHOD(ietf_attr_op_status_t
, get_status
, u_int8_t
,
243 private_ietf_attr_op_status_t
*this)
248 METHOD(ietf_attr_op_status_t
, get_result
, u_int8_t
,
249 private_ietf_attr_op_status_t
*this)
254 METHOD(ietf_attr_op_status_t
, get_last_use
, time_t,
255 private_ietf_attr_op_status_t
*this)
257 return this->last_use
;
261 * Described in header.
263 pa_tnc_attr_t
*ietf_attr_op_status_create(u_int8_t status
, u_int8_t result
,
266 private_ietf_attr_op_status_t
*this;
270 .pa_tnc_attribute
= {
271 .get_type
= _get_type
,
272 .get_value
= _get_value
,
273 .get_noskip_flag
= _get_noskip_flag
,
274 .set_noskip_flag
= _set_noskip_flag
,
280 .get_status
= _get_status
,
281 .get_result
= _get_result
,
282 .get_last_use
= _get_last_use
,
284 .type
= { PEN_IETF
, IETF_ATTR_OPERATIONAL_STATUS
},
287 .last_use
= last_use
,
291 return &this->public.pa_tnc_attribute
;
295 * Described in header.
297 pa_tnc_attr_t
*ietf_attr_op_status_create_from_data(size_t length
, chunk_t data
)
299 private_ietf_attr_op_status_t
*this;
303 .pa_tnc_attribute
= {
304 .get_type
= _get_type
,
305 .get_value
= _get_value
,
306 .get_noskip_flag
= _get_noskip_flag
,
307 .set_noskip_flag
= _set_noskip_flag
,
313 .get_status
= _get_status
,
314 .get_result
= _get_result
,
315 .get_last_use
= _get_last_use
,
317 .type
= { PEN_IETF
, IETF_ATTR_OPERATIONAL_STATUS
},
318 .value
= chunk_clone(data
),
322 return &this->public.pa_tnc_attribute
;