1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 2002-2012 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Eclipse Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.eclipse.org/org/documents/epl-v10.html *
11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * Aman Shaikh <ashaikh@research.att.com> *
18 * *
19 ***********************************************************************/
20 /*****************************************************
21 * File name : ospf_lsag_lsa.c
22 * Objective : Defines functions for parsing LSAG LSA logs.
23 *****************************************************/
24
25 #include "./include.h"
26
27 #define MAGIC_NAME "ospf"
28 #define MAGIC_TYPE "lsag_lsa"
29 #define MAGIC_VERSION 20090701L
30
31 /* Structure to keep track of the parsing state. */
32 typedef struct _lsag_lsa_state_t {
33 ospf_lsa_can_t lsa_can; /* Canonical LSA object */
34
35 /* Parameters to store LSAG LSA being read/processed */
36 uint8_t *lsag_lsap; /* Pointer to current LSAG LSA record
37 being read and processed */
38 uint32_t lsag_lsa_max_len;
39 /* Length of space allocated to
40 '*lsag_lsap' (in bytes ) */
41 uint32_t lsag_lsa_len;
42 /* Length of actual LSA stored in
43 '*lsag_lsap' (in bytes). Must be
44 <= lsag_lsa_max_len. */
45 } lsag_lsa_state_t;
46
47 /*
48 * Size of initial space allocated to 'lsag_lsap' above.
49 * This is just an initial value. The size of 'lsag_lsap'
50 * can be increased later if needed.
51 */
52 #define INIT_LSA_MAX_LEN 10000
53
54 /*
55 * identf for 'lsag_lsa_format'.
56 * Determines if a file contains LSA logs given 'buff_p' holding
57 * first 'size' bytes.
58 */
59 static int identf_lsag_lsa_file(Dssfile_t *fp, void *buff_p, size_t size,
60 Dssdisc_t *disc);
61
62 /*
63 * openf for 'lsag_lsa_format'.
64 * Allocates space for reading LSAG LSA records.
65 */
66 static int open_lsag_lsa_file(Dssfile_t *fp, Dssdisc_t *disc);
67
68 /*
69 * closef for 'lsag_lsa_format'.
70 * Frees space for reading LSAG LSA records.
71 */
72 static int close_lsag_lsa_file(Dssfile_t *fp, Dssdisc_t *disc);
73
74 /*
75 * readf for 'lsag_lsa_format'.
76 * Reads an LSAG LSA record into an 'ospf_lsa_can_t' object.
77 * Returns NULL if can't read further.
78 */
79 static int read_lsag_lsa_rec(Dssfile_t *fp, Dssrecord_t *rp, Dssdisc_t *disc);
80
81 #define FORMAT_NAME "lsag"
82
83 /*
84 * Type object for file types containing LSAG lsa logs.
85 */
86 Dssformat_t lsag_lsa_format = {
87 FORMAT_NAME, /* name */
88 "OSPF LSAG LSA format", /* description */
89 CXH,
90 identf_lsag_lsa_file, /* identf */
91 open_lsag_lsa_file, /* openf */
92 read_lsag_lsa_rec, /* readf */
93 NULL, /* writef */
94 NULL, /* seekf */
95 close_lsag_lsa_file, /* closef */
96 NULL, /* savef */
97 NULL, /* dropf */
98 /* private stuff */
99 OSPF_LSAG_LSA_NEXT /* next */
100 };
101
102 static int
identf_lsag_lsa_file(Dssfile_t * fp,void * data_p,size_t size,Dssdisc_t * disc)103 identf_lsag_lsa_file(Dssfile_t *fp, void *data_p, size_t size,
104 Dssdisc_t *disc) {
105 Magicid_t *mp = (Magicid_t *)data_p;
106 Magicid_data_t version, m_size;
107
108 ASSERT(fp);
109 ASSERT(mp);
110 ASSERT(disc);
111 #if 0
112 sfprintf(sfstderr,
113 "identf_lsag_lsa_file() file: %s sizeof(Magicid_t): %d\n",
114 fp->path, sizeof(Magicid_t));
115 #endif
116
117 /*
118 * Check the first record.
119 * Make sure that the record contains appropriate magic header.
120 */
121 if (size < sizeof(*mp)) {
122 if (disc->errorf && (fp->dss->flags & DSS_DEBUG)) {
123 (*disc->errorf)(NULL, disc, 2, "%s: not enough bytes for magic hdr",
124 FORMAT_NAME);
125 }
126 return 0;
127 }
128 if (!streq(mp->name, MAGIC_NAME)) {
129 if (disc->errorf && (fp->dss->flags & DSS_DEBUG)) {
130 (*disc->errorf)(NULL, disc, 2, "%s: magic name \"%-.*s\" does not match expected \"%s\"", FORMAT_NAME, strlen(MAGIC_NAME), mp->name, MAGIC_NAME);
131 }
132 return 0;
133 }
134 if (!streq(mp->type, MAGIC_TYPE)) {
135 if (disc->errorf && (fp->dss->flags & DSS_DEBUG)) {
136 (*disc->errorf)(NULL, disc, 2, "%s: magic type \"%-.*s\" does not match expected \"%s\"", FORMAT_NAME, strlen(MAGIC_TYPE), mp->type, MAGIC_TYPE);
137 }
138 return 0;
139 }
140 version = ntohl(mp->version);
141 switch (version) {
142 case MAGIC_VERSION:
143 m_size = ntohl(mp->size);
144 #if 0
145 sfprintf(sfstderr, "identf_lsag_lsa_file() m_size: %u\n", m_size);
146 #endif
147 if (m_size < (LSA_HDR_LEN + sizeof(areaid_t))) {
148 if (disc->errorf) {
149 (*disc->errorf)(NULL, disc, 2,
150 "%s: size of file records less than LSA_HDR_LEN + sizeof(area_id)",
151 FORMAT_NAME);
152 }
153 return -1;
154 } /* End of if (m_size) */
155 break;
156
157 default:
158 if (disc->errorf) {
159 (*disc->errorf)(NULL, disc, 2, "%s: version in file is incorrect",
160 FORMAT_NAME);
161 }
162 return -1;
163 } /* End of switch (version) */
164
165 #if 0
166 sfprintf(sfstderr, "identf_lsag_lsa_file() returnig 1...\n");
167 #endif
168 if (disc->errorf && (fp->dss->flags & DSS_DEBUG))
169 (*disc->errorf)(NULL, disc, 2, "%s: format \"%s\" type \"%s %s\" version %lu", fp->path, FORMAT_NAME, MAGIC_NAME, MAGIC_TYPE, MAGIC_VERSION);
170 return 1;
171 }
172
173 static int
open_lsag_lsa_file(Dssfile_t * fp,Dssdisc_t * disc)174 open_lsag_lsa_file(Dssfile_t *fp, Dssdisc_t *disc) {
175 lsag_lsa_state_t *state_p;
176 ospf_lsa_can_t *lsa_can_p;
177 Magicid_t magic_hdr;
178
179 ASSERT(fp);
180 ASSERT(disc);
181 #if 0
182 sfprintf(sfstderr, "open_lsag_lsa_file() file: %s\n", fp->path);
183 #endif
184 if (fp->flags & DSS_FILE_WRITE) {
185 } else {
186
187 /*
188 * Reread the magic header to get the file pointer to advance
189 * to the first LSA record.
190 */
191 if (sfread(fp->io, &magic_hdr, sizeof(Magicid_t)) !=
192 sizeof(Magicid_t)) {
193 if (disc->errorf) {
194 (*disc->errorf)(NULL, disc, ERROR_SYSTEM|2,
195 "%s: header read error",
196 fp->format->name);
197 }
198 return -1;
199 }
200
201 /* Create 'lsag_lsa_state_t' object and store it in 'fp->data'. */
202 MD_CALLOC(fp->data, void *, 1, sizeof(lsag_lsa_state_t));
203 ASSERT(fp->data);
204 state_p = (lsag_lsa_state_t *)(fp->data);
205
206 /*
207 * Allocate space to store an LSA in '*state_p'.
208 * This space can be increased later on if needed.
209 */
210 MD_CALLOC(state_p->lsag_lsap, uint8_t *, INIT_LSA_MAX_LEN,
211 sizeof(uint8_t));
212 ASSERT(state_p->lsag_lsap);
213 state_p->lsag_lsa_max_len = INIT_LSA_MAX_LEN;
214 state_p->lsag_lsa_len = 0;
215
216 /* Initialize canonical LSA in 'state_p' */
217 lsa_can_p = &(state_p->lsa_can);
218 init_lsa_can(lsa_can_p);
219 } /* End of if writing or reading */
220 #if 0
221 sfprintf(sfstderr, "open_lsag_lsa_file() returning 0\n");
222 #endif
223 return 0;
224 }
225
226 static int
close_lsag_lsa_file(Dssfile_t * fp,Dssdisc_t * disc)227 close_lsag_lsa_file(Dssfile_t *fp, Dssdisc_t *disc) {
228 lsag_lsa_state_t *state_p;
229
230 ASSERT(fp);
231 ASSERT(disc);
232 #if 0
233 sfprintf(sfstderr, "close_lsag_lsa_file() file: %s\n", fp->path);
234 #endif
235 state_p = (lsag_lsa_state_t *)(fp->data);
236 if (!state_p) {
237 return -1;
238 }
239
240 /* Free space allocated to store LSA inside fp->data. */
241 if (state_p->lsag_lsap) {
242 MD_FREE(state_p->lsag_lsap);
243 }
244
245 /*
246 * Free space allocated to store LSA data in the canonical LSA
247 * inside fp->data.
248 */
249 free_lsa_can_data(&(state_p->lsa_can));
250
251 /* Now free 'state_p' */
252 MD_FREE(state_p);
253 fp->data = NULL;
254
255 return 0;
256 }
257
258 static int
read_lsag_lsa_rec(Dssfile_t * fp,Dssrecord_t * rp,Dssdisc_t * disc)259 read_lsag_lsa_rec(Dssfile_t *fp, Dssrecord_t *rp, Dssdisc_t *disc) {
260
261 #define PRE_LSA_PARAMS_SIZE (3 * sizeof(uint32_t))
262
263 lsag_lsa_state_t *state_p;
264 ospf_lsa_can_t *lsa_can_p;
265 ospf_lsa_t *lsap;
266 uint32_t lsa_len, lsa_data_len, bytes_left, bytes_read;
267 uint8_t buff[PRE_LSA_PARAMS_SIZE], *buff_p;
268
269 /* sfprintf(sfstderr, "read_lsag_lsa_rec() FILE: %s LINE: %d\n",
270 __FILE__, __LINE__); */
271 ASSERT(fp);
272 ASSERT(rp);
273 ASSERT(disc);
274 state_p = (lsag_lsa_state_t *)(fp->data);
275 ASSERT(state_p);
276 lsa_can_p = &(state_p->lsa_can);
277
278 /*
279 * Read pre-LSA parameters (e.g., time-stamp and area-id),
280 * and store them in '*lsa_can_p'.
281 */
282 bytes_read = sfread(fp->io, buff, PRE_LSA_PARAMS_SIZE);
283 if (bytes_read != PRE_LSA_PARAMS_SIZE) {
284 return 0;
285 }
286 buff_p = buff;
287 bytes_left = PRE_LSA_PARAMS_SIZE;
288 EXTRACT_DATA_TYPE_FROM_NO_BUFF(uint32_t, buff_p, 0, lsa_can_p->sec,
289 bytes_left);
290 #if 0
291 sfprintf(sfstderr,
292 "read_lsag_lsa_rec() sec: %d\n", lsa_can_p->sec);
293 #endif
294 EXTRACT_DATA_TYPE_FROM_NO_BUFF(uint32_t, buff_p, 0, lsa_can_p->micro_sec,
295 bytes_left);
296 EXTRACT_DATA_TYPE_FROM_NO_BUFF(uint32_t, buff_p, 0, lsa_can_p->lsu_areaid,
297 bytes_left);
298
299 /* Read LSA header */
300 if (LSA_HDR_LEN > (state_p->lsag_lsa_max_len)) {
301 MD_REALLOC(state_p->lsag_lsap, state_p->lsag_lsap, uint8_t *,
302 LSA_HDR_LEN);
303 ASSERT(state_p->lsag_lsap);
304 state_p->lsag_lsa_max_len = LSA_HDR_LEN;
305 }
306 lsap = (ospf_lsa_t *)(state_p->lsag_lsap);
307 if (sfread(fp->io, lsap, LSA_HDR_LEN) != LSA_HDR_LEN) {
308 return 0;
309 }
310 lsa_can_p->lsa_id = NTOH_LSA_ID(lsap->lsa_id_f);
311 lsa_can_p->lsa_advrt = NTOH_LSA_ADVRT(lsap->lsa_advrt_f);
312 lsa_can_p->lsa_seq = NTOH_LSA_SEQ(lsap->lsa_seq_f);
313 lsa_can_p->lsa_age = NTOH_LSA_AGE(lsap->lsa_age_f);
314 lsa_can_p->lsa_cksum = NTOH_LSA_CKSUM(lsap->lsa_cksum_f);
315 lsa_len = lsa_can_p->lsa_len = NTOH_LSA_LEN(lsap->lsa_len_f);
316 lsa_can_p->lsa_options = NTOH_LSA_OPTIONS(lsap->lsa_options_f);
317 lsa_can_p->lsa_type = NTOH_LSA_TYPE(lsap->lsa_type_f);
318 #if 0
319 sfprintf(sfstderr,
320 "read_lsag_lsa_rec() LSA(%d %s %s) with seq: 0x%x len: %d\n",
321 lsa_can_p->lsa_type,
322 ipaddr_to_dotted_decimal(lsa_can_p->lsa_id),
323 rtid_to_dotted_decimal(lsa_can_p->lsa_advrt),
324 lsa_can_p->lsa_seq,
325 lsa_can_p->lsa_len);
326 #endif
327
328 /* Read LSA data as is */
329 lsa_data_len = lsa_len - LSA_HDR_LEN;
330 calloc_lsa_can_data(lsa_can_p, lsa_data_len);
331 if (sfread(fp->io, lsa_can_p->lsa_data_p, lsa_data_len) !=
332 lsa_data_len) {
333 return 0;
334 }
335
336 rp->data = lsa_can_p;
337 rp->size = sizeof(*lsa_can_p);
338 return 1;
339
340 #undef PRE_LSA_PARAMS_SIZE
341
342 }
343