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