]>
Commit | Line | Data |
---|---|---|
eb5d44eb | 1 | /* |
2 | * IS-IS Rout(e)ing protocol - isis_tlv.c | |
3 | * IS-IS TLV related routines | |
4 | * | |
5 | * Copyright (C) 2001,2002 Sampo Saaristo | |
6 | * Tampere University of Technology | |
7 | * Institute of Communications Engineering | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or modify it | |
10 | * under the terms of the GNU General Public Licenseas published by the Free | |
11 | * Software Foundation; either version 2 of the License, or (at your option) | |
12 | * any later version. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful,but WITHOUT | |
15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
17 | * more details. | |
18 | ||
19 | * You should have received a copy of the GNU General Public License along | |
20 | * with this program; if not, write to the Free Software Foundation, Inc., | |
21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
22 | */ | |
23 | ||
24 | #include <zebra.h> | |
eb5d44eb | 25 | |
26 | #include "log.h" | |
27 | #include "linklist.h" | |
28 | #include "stream.h" | |
29 | #include "memory.h" | |
30 | #include "prefix.h" | |
31 | #include "vty.h" | |
32 | #include "if.h" | |
33 | ||
34 | #include "isisd/dict.h" | |
35 | #include "isisd/isis_constants.h" | |
36 | #include "isisd/isis_common.h" | |
37 | #include "isisd/isis_flags.h" | |
38 | #include "isisd/isis_circuit.h" | |
39 | #include "isisd/isis_tlv.h" | |
40 | #include "isisd/isisd.h" | |
41 | #include "isisd/isis_dynhn.h" | |
42 | #include "isisd/isis_misc.h" | |
43 | #include "isisd/isis_pdu.h" | |
44 | #include "isisd/isis_lsp.h" | |
45 | ||
eb5d44eb | 46 | void |
47 | free_tlv (void *val) | |
48 | { | |
f390d2c7 | 49 | XFREE (MTYPE_ISIS_TLV, val); |
50 | ||
51 | return; | |
eb5d44eb | 52 | } |
53 | ||
54 | /* | |
55 | * Called after parsing of a PDU. There shouldn't be any tlv's left, so this | |
56 | * is only a caution to avoid memory leaks | |
57 | */ | |
f390d2c7 | 58 | void |
eb5d44eb | 59 | free_tlvs (struct tlvs *tlvs) |
60 | { | |
f390d2c7 | 61 | if (tlvs->area_addrs) |
aac372f4 | 62 | list_delete (tlvs->area_addrs); |
f390d2c7 | 63 | if (tlvs->is_neighs) |
aac372f4 | 64 | list_delete (tlvs->is_neighs); |
f390d2c7 | 65 | if (tlvs->te_is_neighs) |
aac372f4 | 66 | list_delete (tlvs->te_is_neighs); |
f390d2c7 | 67 | if (tlvs->es_neighs) |
aac372f4 | 68 | list_delete (tlvs->es_neighs); |
f390d2c7 | 69 | if (tlvs->lsp_entries) |
aac372f4 | 70 | list_delete (tlvs->lsp_entries); |
f390d2c7 | 71 | if (tlvs->prefix_neighs) |
aac372f4 | 72 | list_delete (tlvs->prefix_neighs); |
3f045a08 JB |
73 | if (tlvs->lan_neighs) |
74 | list_delete (tlvs->lan_neighs); | |
f390d2c7 | 75 | if (tlvs->ipv4_addrs) |
aac372f4 | 76 | list_delete (tlvs->ipv4_addrs); |
f390d2c7 | 77 | if (tlvs->ipv4_int_reachs) |
aac372f4 | 78 | list_delete (tlvs->ipv4_int_reachs); |
f390d2c7 | 79 | if (tlvs->ipv4_ext_reachs) |
aac372f4 | 80 | list_delete (tlvs->ipv4_ext_reachs); |
f390d2c7 | 81 | if (tlvs->te_ipv4_reachs) |
aac372f4 | 82 | list_delete (tlvs->te_ipv4_reachs); |
eb5d44eb | 83 | #ifdef HAVE_IPV6 |
f390d2c7 | 84 | if (tlvs->ipv6_addrs) |
aac372f4 | 85 | list_delete (tlvs->ipv6_addrs); |
f390d2c7 | 86 | if (tlvs->ipv6_reachs) |
aac372f4 | 87 | list_delete (tlvs->ipv6_reachs); |
eb5d44eb | 88 | #endif /* HAVE_IPV6 */ |
3f045a08 JB |
89 | |
90 | memset (tlvs, 0, sizeof (struct tlvs)); | |
91 | ||
eb5d44eb | 92 | return; |
93 | } | |
94 | ||
95 | /* | |
96 | * Parses the tlvs found in the variant length part of the PDU. | |
97 | * Caller tells with flags in "expected" which TLV's it is interested in. | |
98 | */ | |
f390d2c7 | 99 | int |
100 | parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected, | |
3f045a08 | 101 | u_int32_t * found, struct tlvs *tlvs, u_int32_t *auth_tlv_offset) |
eb5d44eb | 102 | { |
f390d2c7 | 103 | u_char type, length; |
104 | struct lan_neigh *lan_nei; | |
105 | struct area_addr *area_addr; | |
106 | struct is_neigh *is_nei; | |
107 | struct te_is_neigh *te_is_nei; | |
108 | struct es_neigh *es_nei; | |
109 | struct lsp_entry *lsp_entry; | |
110 | struct in_addr *ipv4_addr; | |
111 | struct ipv4_reachability *ipv4_reach; | |
112 | struct te_ipv4_reachability *te_ipv4_reach; | |
eb5d44eb | 113 | #ifdef HAVE_IPV6 |
f390d2c7 | 114 | struct in6_addr *ipv6_addr; |
115 | struct ipv6_reachability *ipv6_reach; | |
116 | int prefix_octets; | |
eb5d44eb | 117 | #endif /* HAVE_IPV6 */ |
f390d2c7 | 118 | int value_len, retval = ISIS_OK; |
f02a0992 | 119 | u_char *start = stream, *pnt = stream, *endpnt; |
eb5d44eb | 120 | |
121 | *found = 0; | |
122 | memset (tlvs, 0, sizeof (struct tlvs)); | |
f390d2c7 | 123 | |
124 | while (pnt < stream + size - 2) | |
125 | { | |
126 | type = *pnt; | |
127 | length = *(pnt + 1); | |
128 | pnt += 2; | |
129 | value_len = 0; | |
130 | if (pnt + length > stream + size) | |
131 | { | |
132 | zlog_warn ("ISIS-TLV (%s): TLV (type %d, length %d) exceeds packet " | |
133 | "boundaries", areatag, type, length); | |
134 | retval = ISIS_WARNING; | |
135 | break; | |
136 | } | |
137 | switch (type) | |
138 | { | |
139 | case AREA_ADDRESSES: | |
140 | /* +-------+-------+-------+-------+-------+-------+-------+-------+ | |
141 | * | Address Length | | |
142 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | |
143 | * | Area Address | | |
144 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | |
145 | * : : | |
146 | */ | |
147 | *found |= TLVFLAG_AREA_ADDRS; | |
eb5d44eb | 148 | #ifdef EXTREME_TLV_DEBUG |
529d65b3 | 149 | zlog_debug ("TLV Area Adresses len %d", length); |
eb5d44eb | 150 | #endif /* EXTREME_TLV_DEBUG */ |
f390d2c7 | 151 | if (*expected & TLVFLAG_AREA_ADDRS) |
152 | { | |
153 | while (length > value_len) | |
154 | { | |
155 | area_addr = (struct area_addr *) pnt; | |
156 | value_len += area_addr->addr_len + 1; | |
157 | pnt += area_addr->addr_len + 1; | |
158 | if (!tlvs->area_addrs) | |
159 | tlvs->area_addrs = list_new (); | |
160 | listnode_add (tlvs->area_addrs, area_addr); | |
161 | } | |
162 | } | |
163 | else | |
164 | { | |
165 | pnt += length; | |
166 | } | |
167 | break; | |
168 | ||
169 | case IS_NEIGHBOURS: | |
170 | *found |= TLVFLAG_IS_NEIGHS; | |
eb5d44eb | 171 | #ifdef EXTREME_TLV_DEBUG |
529d65b3 | 172 | zlog_debug ("ISIS-TLV (%s): IS Neighbours length %d", |
173 | areatag, length); | |
eb5d44eb | 174 | #endif /* EXTREME_TLV_DEBUG */ |
f390d2c7 | 175 | if (TLVFLAG_IS_NEIGHS & *expected) |
176 | { | |
177 | /* +-------+-------+-------+-------+-------+-------+-------+-------+ | |
178 | * | Virtual Flag | | |
179 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | |
180 | */ | |
f390d2c7 | 181 | pnt++; |
182 | value_len++; | |
183 | /* +-------+-------+-------+-------+-------+-------+-------+-------+ | |
184 | * | 0 | I/E | Default Metric | | |
185 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | |
186 | * | S | I/E | Delay Metric | | |
187 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | |
188 | * | S | I/E | Expense Metric | | |
189 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | |
190 | * | S | I/E | Error Metric | | |
191 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | |
192 | * | Neighbour ID | | |
193 | * +---------------------------------------------------------------+ | |
194 | * : : | |
195 | */ | |
196 | while (length > value_len) | |
197 | { | |
198 | is_nei = (struct is_neigh *) pnt; | |
199 | value_len += 4 + ISIS_SYS_ID_LEN + 1; | |
200 | pnt += 4 + ISIS_SYS_ID_LEN + 1; | |
201 | if (!tlvs->is_neighs) | |
202 | tlvs->is_neighs = list_new (); | |
203 | listnode_add (tlvs->is_neighs, is_nei); | |
204 | } | |
205 | } | |
206 | else | |
207 | { | |
208 | pnt += length; | |
209 | } | |
210 | break; | |
211 | ||
212 | case TE_IS_NEIGHBOURS: | |
213 | /* +-------+-------+-------+-------+-------+-------+-------+-------+ | |
214 | * | Neighbour ID | 7 | |
215 | * +---------------------------------------------------------------+ | |
216 | * | TE Metric | 3 | |
217 | * +---------------------------------------------------------------+ | |
218 | * | SubTLVs Length | 1 | |
219 | * +---------------------------------------------------------------+ | |
220 | * : : | |
221 | */ | |
222 | *found |= TLVFLAG_TE_IS_NEIGHS; | |
eb5d44eb | 223 | #ifdef EXTREME_TLV_DEBUG |
529d65b3 | 224 | zlog_debug ("ISIS-TLV (%s): Extended IS Neighbours length %d", |
f390d2c7 | 225 | areatag, length); |
eb5d44eb | 226 | #endif /* EXTREME_TLV_DEBUG */ |
f390d2c7 | 227 | if (TLVFLAG_TE_IS_NEIGHS & *expected) |
228 | { | |
229 | while (length > value_len) | |
230 | { | |
231 | te_is_nei = (struct te_is_neigh *) pnt; | |
232 | value_len += 11; | |
233 | pnt += 11; | |
234 | /* FIXME - subtlvs are handled here, for now we skip */ | |
235 | value_len += te_is_nei->sub_tlvs_length; | |
236 | pnt += te_is_nei->sub_tlvs_length; | |
237 | ||
238 | if (!tlvs->te_is_neighs) | |
239 | tlvs->te_is_neighs = list_new (); | |
240 | listnode_add (tlvs->te_is_neighs, te_is_nei); | |
241 | } | |
242 | } | |
243 | else | |
244 | { | |
245 | pnt += length; | |
246 | } | |
247 | break; | |
248 | ||
249 | case ES_NEIGHBOURS: | |
250 | /* +-------+-------+-------+-------+-------+-------+-------+-------+ | |
251 | * | 0 | I/E | Default Metric | | |
252 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | |
253 | * | S | I/E | Delay Metric | | |
254 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | |
255 | * | S | I/E | Expense Metric | | |
256 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | |
257 | * | S | I/E | Error Metric | | |
258 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | |
259 | * | Neighbour ID | | |
260 | * +---------------------------------------------------------------+ | |
261 | * | Neighbour ID | | |
262 | * +---------------------------------------------------------------+ | |
263 | * : : | |
264 | */ | |
eb5d44eb | 265 | #ifdef EXTREME_TLV_DEBUG |
529d65b3 | 266 | zlog_debug ("ISIS-TLV (%s): ES Neighbours length %d", |
f390d2c7 | 267 | areatag, length); |
eb5d44eb | 268 | #endif /* EXTREME_TLV_DEBUG */ |
f390d2c7 | 269 | *found |= TLVFLAG_ES_NEIGHS; |
270 | if (*expected & TLVFLAG_ES_NEIGHS) | |
271 | { | |
272 | es_nei = (struct es_neigh *) pnt; | |
273 | value_len += 4; | |
274 | pnt += 4; | |
275 | while (length > value_len) | |
276 | { | |
277 | /* FIXME FIXME FIXME - add to the list */ | |
278 | /* sys_id->id = pnt; */ | |
279 | value_len += ISIS_SYS_ID_LEN; | |
280 | pnt += ISIS_SYS_ID_LEN; | |
281 | /* if (!es_nei->neigh_ids) es_nei->neigh_ids = sysid; */ | |
282 | } | |
283 | if (!tlvs->es_neighs) | |
284 | tlvs->es_neighs = list_new (); | |
285 | listnode_add (tlvs->es_neighs, es_nei); | |
286 | } | |
287 | else | |
288 | { | |
289 | pnt += length; | |
290 | } | |
291 | break; | |
292 | ||
293 | case LAN_NEIGHBOURS: | |
294 | /* +-------+-------+-------+-------+-------+-------+-------+-------+ | |
295 | * | LAN Address | | |
296 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | |
297 | * : : | |
298 | */ | |
299 | *found |= TLVFLAG_LAN_NEIGHS; | |
eb5d44eb | 300 | #ifdef EXTREME_TLV_DEBUG |
529d65b3 | 301 | zlog_debug ("ISIS-TLV (%s): LAN Neigbours length %d", |
302 | areatag, length); | |
eb5d44eb | 303 | #endif /* EXTREME_TLV_DEBUG */ |
f390d2c7 | 304 | if (TLVFLAG_LAN_NEIGHS & *expected) |
305 | { | |
306 | while (length > value_len) | |
307 | { | |
308 | lan_nei = (struct lan_neigh *) pnt; | |
309 | if (!tlvs->lan_neighs) | |
310 | tlvs->lan_neighs = list_new (); | |
311 | listnode_add (tlvs->lan_neighs, lan_nei); | |
312 | value_len += ETH_ALEN; | |
313 | pnt += ETH_ALEN; | |
314 | } | |
315 | } | |
316 | else | |
317 | { | |
318 | pnt += length; | |
319 | } | |
320 | break; | |
321 | ||
322 | case PADDING: | |
eb5d44eb | 323 | #ifdef EXTREME_TLV_DEBUG |
529d65b3 | 324 | zlog_debug ("TLV padding %d", length); |
eb5d44eb | 325 | #endif /* EXTREME_TLV_DEBUG */ |
f390d2c7 | 326 | pnt += length; |
327 | break; | |
328 | ||
329 | case LSP_ENTRIES: | |
330 | /* +-------+-------+-------+-------+-------+-------+-------+-------+ | |
331 | * | Remaining Lifetime | 2 | |
332 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | |
333 | * | LSP ID | id+2 | |
334 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | |
335 | Content-type: text/html ]>