Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | /* |
2 | * $Id: libnet_build_ospf.c,v 1.21 2005/11/29 22:01:00 carlosc Exp $ | |
3 | * | |
4 | * libnet | |
5 | * libnet_build_ospf.c - OSPF packet assembler | |
6 | * | |
7 | * Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com> | |
8 | * All rights reserved. | |
9 | * | |
10 | * Copyright (c) 1999, 2000 Andrew Reiter <areiter@bindview.com> | |
11 | * Bindview Development | |
12 | * | |
13 | * Redistribution and use in source and binary forms, with or without | |
14 | * modification, are permitted provided that the following conditions | |
15 | * are met: | |
16 | * 1. Redistributions of source code must retain the above copyright | |
17 | * notice, this list of conditions and the following disclaimer. | |
18 | * 2. Redistributions in binary form must reproduce the above copyright | |
19 | * notice, this list of conditions and the following disclaimer in the | |
20 | * documentation and/or other materials provided with the distribution. | |
21 | * | |
22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
32 | * SUCH DAMAGE. | |
33 | * | |
34 | */ | |
35 | ||
36 | #if (HAVE_CONFIG_H) | |
37 | #include "../include/config.h" | |
38 | #endif | |
39 | #if (!(_WIN32) || (__CYGWIN__)) | |
40 | #include "../include/libnet.h" | |
41 | #else | |
42 | #include "../include/win32/libnet.h" | |
43 | #endif | |
44 | ||
45 | libnet_ptag_t | |
46 | libnet_build_ospfv2(u_int16_t len, u_int8_t type, u_int32_t rtr_id, | |
47 | u_int32_t area_id, u_int16_t sum, u_int16_t autype, u_int8_t *payload, | |
48 | u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag) | |
49 | { | |
50 | u_int32_t n, h; | |
51 | libnet_pblock_t *p; | |
52 | struct libnet_ospf_hdr ospf_hdr; | |
53 | ||
54 | if (l == NULL) | |
55 | { | |
56 | return (-1); | |
57 | } | |
58 | ||
59 | n = LIBNET_OSPF_H + payload_s; | |
60 | h = LIBNET_OSPF_H + payload_s + len; | |
61 | ||
62 | /* | |
63 | * Find the existing protocol block if a ptag is specified, or create | |
64 | * a new one. | |
65 | */ | |
66 | p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_OSPF_H); | |
67 | if (p == NULL) | |
68 | { | |
69 | return (-1); | |
70 | } | |
71 | ||
72 | memset(&ospf_hdr, 0, sizeof(ospf_hdr)); | |
73 | ospf_hdr.ospf_v = 2; /* OSPF version 2 */ | |
74 | ospf_hdr.ospf_type = type; /* Type of pkt */ | |
75 | ospf_hdr.ospf_len = htons(h); /* Pkt len */ | |
76 | ospf_hdr.ospf_rtr_id.s_addr = htonl(rtr_id); /* Router ID */ | |
77 | ospf_hdr.ospf_area_id.s_addr = htonl(area_id); /* Area ID */ | |
78 | ospf_hdr.ospf_sum = (sum ? htons(sum) : 0); | |
79 | ospf_hdr.ospf_auth_type = htons(autype); /* Type of auth */ | |
80 | ||
81 | n = libnet_pblock_append(l, p, (u_int8_t *)&ospf_hdr, LIBNET_OSPF_H); | |
82 | if (n == -1) | |
83 | { | |
84 | goto bad; | |
85 | } | |
86 | ||
87 | if ((payload && !payload_s) || (!payload && payload_s)) | |
88 | { | |
89 | snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, | |
90 | "%s(): payload inconsistency\n", __func__); | |
91 | goto bad; | |
92 | } | |
93 | ||
94 | if (payload && payload_s) | |
95 | { | |
96 | n = libnet_pblock_append(l, p, payload, payload_s); | |
97 | if (n == -1) | |
98 | { | |
99 | goto bad; | |
100 | } | |
101 | } | |
102 | ||
103 | if (sum == 0) | |
104 | { | |
105 | /* | |
106 | * If checksum is zero, by default libnet will compute a checksum | |
107 | * for the user. The programmer can override this by calling | |
108 | * libnet_toggle_checksum(l, ptag, 1); | |
109 | */ | |
110 | libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM); | |
111 | } | |
112 | return (ptag ? ptag : libnet_pblock_update(l, p, h, LIBNET_PBLOCK_OSPF_H)); | |
113 | bad: | |
114 | libnet_pblock_delete(l, p); | |
115 | return (-1); | |
116 | } | |
117 | ||
118 | ||
119 | libnet_ptag_t | |
120 | libnet_build_ospfv2_hello(u_int32_t netmask, u_int16_t interval, u_int8_t opts, | |
121 | u_int8_t priority, u_int32_t dead_int, u_int32_t des_rtr, u_int32_t bkup_rtr, | |
122 | u_int32_t neighbor, u_int8_t *payload, u_int32_t payload_s, libnet_t *l, | |
123 | libnet_ptag_t ptag) | |
124 | { | |
125 | u_int32_t n, h; | |
126 | libnet_pblock_t *p; | |
127 | struct libnet_ospf_hello_hdr hello_hdr; | |
128 | ||
129 | if (l == NULL) | |
130 | { | |
131 | return (-1); | |
132 | } | |
133 | ||
134 | n = LIBNET_OSPF_HELLO_H + payload_s; | |
135 | h = 0; | |
136 | ||
137 | /* | |
138 | * Find the existing protocol block if a ptag is specified, or create | |
139 | * a new one. | |
140 | */ | |
141 | p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_OSPF_HELLO_H); | |
142 | if (p == NULL) | |
143 | { | |
144 | return (-1); | |
145 | } | |
146 | ||
147 | memset(&hello_hdr, 0, sizeof(hello_hdr)); | |
148 | hello_hdr.hello_nmask.s_addr = htonl(netmask); /* Netmask */ | |
149 | hello_hdr.hello_intrvl = htons(interval); /* # seconds since last packet sent */ | |
150 | hello_hdr.hello_opts = opts; /* OSPF_* options */ | |
151 | hello_hdr.hello_rtr_pri = priority; /* If 0, can't be backup */ | |
152 | hello_hdr.hello_dead_intvl = htonl(dead_int); /* Time til router is deemed down */ | |
153 | hello_hdr.hello_des_rtr.s_addr = htonl(des_rtr); /* Networks designated router */ | |
154 | hello_hdr.hello_bkup_rtr.s_addr = htonl(bkup_rtr); /* Networks backup router */ | |
155 | hello_hdr.hello_nbr.s_addr = htonl(neighbor); | |
156 | ||
157 | n = libnet_pblock_append(l, p, (u_int8_t *)&hello_hdr, LIBNET_OSPF_HELLO_H); | |
158 | if (n == -1) | |
159 | { | |
160 | goto bad; | |
161 | } | |
162 | ||
163 | if ((payload && !payload_s) || (!payload && payload_s)) | |
164 | { | |
165 | snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, | |
166 | "%s(): payload inconsistency\n", __func__); | |
167 | goto bad; | |
168 | } | |
169 | ||
170 | if (payload && payload_s) | |
171 | { | |
172 | n = libnet_pblock_append(l, p, payload, payload_s); | |
173 | if (n == -1) | |
174 | { | |
175 | goto bad; | |
176 | } | |
177 | } | |
178 | ||
179 | return (ptag ? ptag : libnet_pblock_update(l, p, h, | |
180 | LIBNET_PBLOCK_OSPF_HELLO_H)); | |
181 | bad: | |
182 | libnet_pblock_delete(l, p); | |
183 | return (-1); | |
184 | } | |
185 | ||
186 | ||
187 | libnet_ptag_t | |
188 | libnet_build_ospfv2_dbd(u_int16_t dgram_len, u_int8_t opts, u_int8_t type, | |
189 | u_int32_t seqnum, u_int8_t *payload, u_int32_t payload_s, libnet_t *l, | |
190 | libnet_ptag_t ptag) | |
191 | { | |
192 | u_int32_t n, h; | |
193 | libnet_pblock_t *p; | |
194 | struct libnet_dbd_hdr dbd_hdr; | |
195 | ||
196 | if (l == NULL) | |
197 | { | |
198 | return (-1); | |
199 | } | |
200 | ||
201 | n = LIBNET_OSPF_DBD_H + payload_s; | |
202 | h = 0; | |
203 | ||
204 | /* | |
205 | * Find the existing protocol block if a ptag is specified, or create | |
206 | * a new one. | |
207 | */ | |
208 | p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_OSPF_DBD_H); | |
209 | if (p == NULL) | |
210 | { | |
211 | return (-1); | |
212 | } | |
213 | ||
214 | memset(&dbd_hdr, 0, sizeof(dbd_hdr)); | |
215 | dbd_hdr.dbd_mtu_len = htons(dgram_len); /* Max length of IP packet IF can use */ | |
216 | dbd_hdr.dbd_opts = opts; /* OSPF_* options */ | |
217 | dbd_hdr.dbd_type = type; /* Type of exchange occuring */ | |
218 | dbd_hdr.dbd_seq = htonl(seqnum); /* DBD sequence number */ | |
219 | ||
220 | n = libnet_pblock_append(l, p, (u_int8_t *)&dbd_hdr, LIBNET_OSPF_DBD_H); | |
221 | if (n == -1) | |
222 | { | |
223 | goto bad; | |
224 | } | |
225 | ||
226 | if ((payload && !payload_s) || (!payload && payload_s)) | |
227 | { | |
228 | snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, | |
229 | "%s(): payload inconsistency\n", __func__); | |
230 | goto bad; | |
231 | } | |
232 | ||
233 | if (payload && payload_s) | |
234 | { | |
235 | n = libnet_pblock_append(l, p, payload, payload_s); | |
236 | if (n == -1) | |
237 | { | |
238 | goto bad; | |
239 | } | |
240 | } | |
241 | ||
242 | return (ptag ? ptag : libnet_pblock_update(l, p, h, | |
243 | LIBNET_PBLOCK_OSPF_DBD_H)); | |
244 | bad: | |
245 | libnet_pblock_delete(l, p); | |
246 | return (-1); | |
247 | } | |
248 | ||
249 | ||
250 | libnet_ptag_t | |
251 | libnet_build_ospfv2_lsr(u_int32_t type, u_int lsid, u_int32_t advrtr, | |
252 | u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag) | |
253 | { | |
254 | u_int32_t n, h; | |
255 | libnet_pblock_t *p; | |
256 | struct libnet_lsr_hdr lsr_hdr; | |
257 | ||
258 | if (l == NULL) | |
259 | { | |
260 | return (-1); | |
261 | } | |
262 | ||
263 | n = LIBNET_OSPF_LSR_H + payload_s; | |
264 | h = 0; | |
265 | ||
266 | /* | |
267 | * Find the existing protocol block if a ptag is specified, or create | |
268 | * a new one. | |
269 | */ | |
270 | p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_OSPF_LSR_H); | |
271 | if (p == NULL) | |
272 | { | |
273 | return (-1); | |
274 | } | |
275 | ||
276 | memset(&lsr_hdr, 0, sizeof(lsr_hdr)); | |
277 | lsr_hdr.lsr_type = htonl(type); /* Type of LS being requested */ | |
278 | lsr_hdr.lsr_lsid = htonl(lsid); /* Link State ID */ | |
279 | lsr_hdr.lsr_adrtr.s_addr = htonl(advrtr); /* Advertising router */ | |
280 | ||
281 | n = libnet_pblock_append(l, p, (u_int8_t *)&lsr_hdr, LIBNET_OSPF_LSR_H); | |
282 | if (n == -1) | |
283 | { | |
284 | goto bad; | |
285 | } | |
286 | ||
287 | if ((payload && !payload_s) || (!payload && payload_s)) | |
288 | { | |
289 | snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, | |
290 | "%s(): payload inconsistency\n", __func__); | |
291 | goto bad; | |
292 | } | |
293 | ||
294 | if (payload && payload_s) | |
295 | { | |
296 | n = libnet_pblock_append(l, p, payload, payload_s); | |
297 | if (n == -1) | |
298 | { | |
299 | goto bad; | |
300 | } | |
301 | } | |
302 | ||
303 | return (ptag ? ptag : libnet_pblock_update(l, p, h, | |
304 | LIBNET_PBLOCK_OSPF_LSR_H)); | |
305 | bad: | |
306 | libnet_pblock_delete(l, p); | |
307 | return (-1); | |
308 | } | |
309 | ||
310 | ||
311 | libnet_ptag_t | |
312 | libnet_build_ospfv2_lsu(u_int32_t num, u_int8_t *payload, u_int32_t payload_s, | |
313 | libnet_t *l, libnet_ptag_t ptag) | |
314 | { | |
315 | u_int32_t n, h; | |
316 | libnet_pblock_t *p; | |
317 | struct libnet_lsu_hdr lh_hdr; | |
318 | ||
319 | if (l == NULL) | |
320 | { | |
321 | return (-1); | |
322 | } | |
323 | ||
324 | n = LIBNET_OSPF_LSU_H + payload_s; | |
325 | h = 0; | |
326 | ||
327 | /* | |
328 | * Find the existing protocol block if a ptag is specified, or create | |
329 | * a new one. | |
330 | */ | |
331 | p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_OSPF_LSU_H); | |
332 | if (p == NULL) | |
333 | { | |
334 | return (-1); | |
335 | } | |
336 | ||
337 | memset(&lh_hdr, 0, sizeof(lh_hdr)); | |
338 | lh_hdr.lsu_num = htonl(num); /* Number of LSAs that will be bcasted */ | |
339 | ||
340 | n = libnet_pblock_append(l, p, (u_int8_t *)&lh_hdr, LIBNET_OSPF_LSU_H); | |
341 | if (n == -1) | |
342 | { | |
343 | goto bad; | |
344 | } | |
345 | ||
346 | if ((payload && !payload_s) || (!payload && payload_s)) | |
347 | { | |
348 | snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, | |
349 | "%s(): payload inconsistency\n", __func__); | |
350 | goto bad; | |
351 | } | |
352 | ||
353 | if (payload && payload_s) | |
354 | { | |
355 | n = libnet_pblock_append(l, p, payload, payload_s); | |
356 | if (n == -1) | |
357 | { | |
358 | goto bad; | |
359 | } | |
360 | } | |
361 | ||
362 | return (ptag ? ptag : libnet_pblock_update(l, p, h, | |
363 | LIBNET_PBLOCK_OSPF_LSU_H)); | |
364 | bad: | |
365 | libnet_pblock_delete(l, p); | |
366 | return (-1); | |
367 | } | |
368 | ||
369 | ||
370 | libnet_ptag_t | |
371 | libnet_build_ospfv2_lsa(u_int16_t age, u_int8_t opts, u_int8_t type, u_int lsid, | |
372 | u_int32_t advrtr, u_int32_t seqnum, u_int16_t sum, u_int16_t len, | |
373 | u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag) | |
374 | { | |
375 | u_int32_t n, h; | |
376 | libnet_pblock_t *p; | |
377 | struct libnet_lsa_hdr lsa_hdr; | |
378 | ||
379 | if (l == NULL) | |
380 | { | |
381 | return (-1); | |
382 | } | |
383 | ||
384 | n = LIBNET_OSPF_LSA_H + payload_s; | |
385 | h = len + payload_s; | |
386 | ||
387 | /* | |
388 | * Find the existing protocol block if a ptag is specified, or create | |
389 | * a new one. | |
390 | */ | |
391 | p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_OSPF_LSA_H); | |
392 | if (p == NULL) | |
393 | { | |
394 | return (-1); | |
395 | } | |
396 | ||
397 | memset(&lsa_hdr, 0, sizeof(lsa_hdr)); | |
398 | lsa_hdr.lsa_age = htons(age); | |
399 | lsa_hdr.lsa_opts = opts; | |
400 | lsa_hdr.lsa_type = type; | |
401 | lsa_hdr.lsa_id = htonl(lsid); | |
402 | lsa_hdr.lsa_adv.s_addr = htonl(advrtr); | |
403 | lsa_hdr.lsa_seq = htonl(seqnum); | |
404 | lsa_hdr.lsa_sum = (sum ? htons(sum) : 0); | |
405 | lsa_hdr.lsa_len = htons(h); | |
406 | ||
407 | n = libnet_pblock_append(l, p, (u_int8_t *)&lsa_hdr, LIBNET_OSPF_LSA_H); | |
408 | if (n == -1) | |
409 | { | |
410 | goto bad; | |
411 | } | |
412 | ||
413 | if ((payload && !payload_s) || (!payload && payload_s)) | |
414 | { | |
415 | snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, | |
416 | "%s(): payload inconsistency\n", __func__); | |
417 | goto bad; | |
418 | } | |
419 | ||
420 | if (payload && payload_s) | |
421 | { | |
422 | n = libnet_pblock_append(l, p, payload, payload_s); | |
423 | if (n == -1) | |
424 | { | |
425 | goto bad; | |
426 | } | |
427 | } | |
428 | ||
429 | if (sum == 0) | |
430 | { | |
431 | /* | |
432 | * If checksum is zero, by default libnet will compute a checksum | |
433 | * for the user. The programmer can override this by calling | |
434 | * libnet_toggle_checksum(l, ptag, 1); | |
435 | */ | |
436 | libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM); | |
437 | } | |
438 | return (ptag ? ptag : libnet_pblock_update(l, p, h, | |
439 | LIBNET_PBLOCK_OSPF_LSA_H)); | |
440 | bad: | |
441 | libnet_pblock_delete(l, p); | |
442 | return (-1); | |
443 | } | |
444 | ||
445 | ||
446 | libnet_ptag_t | |
447 | libnet_build_ospfv2_lsa_rtr(u_int16_t flags, u_int16_t num, u_int32_t id, | |
448 | u_int32_t data, u_int8_t type, u_int8_t tos, u_int16_t metric, | |
449 | u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag) | |
450 | { | |
451 | u_int32_t n, h; | |
452 | libnet_pblock_t *p; | |
453 | struct libnet_rtr_lsa_hdr rtr_lsa_hdr; | |
454 | ||
455 | if (l == NULL) | |
456 | { | |
457 | return (-1); | |
458 | } | |
459 | ||
460 | n = LIBNET_OSPF_LS_RTR_H + payload_s; | |
461 | h = 0; | |
462 | ||
463 | /* | |
464 | * Find the existing protocol block if a ptag is specified, or create | |
465 | * a new one. | |
466 | */ | |
467 | p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_LS_RTR_H); | |
468 | if (p == NULL) | |
469 | { | |
470 | return (-1); | |
471 | } | |
472 | ||
473 | memset(&rtr_lsa_hdr, 0, sizeof(rtr_lsa_hdr)); | |
474 | rtr_lsa_hdr.rtr_flags = htons(flags); | |
475 | rtr_lsa_hdr.rtr_num = htons(num); | |
476 | rtr_lsa_hdr.rtr_link_id = htonl(id); | |
477 | rtr_lsa_hdr.rtr_link_data = htonl(data); | |
478 | rtr_lsa_hdr.rtr_type = type; | |
479 | rtr_lsa_hdr.rtr_tos_num = tos; | |
480 | rtr_lsa_hdr.rtr_metric = htons(metric); | |
481 | ||
482 | n = libnet_pblock_append(l, p, (u_int8_t *)&rtr_lsa_hdr, | |
483 | LIBNET_OSPF_LS_RTR_H); | |
484 | if (n == -1) | |
485 | { | |
486 | goto bad; | |
487 | } | |
488 | ||
489 | if ((payload && !payload_s) || (!payload && payload_s)) | |
490 | { | |
491 | snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, | |
492 | "%s(): payload inconsistency\n", __func__); | |
493 | goto bad; | |
494 | } | |
495 | ||
496 | if (payload && payload_s) | |
497 | { | |
498 | n = libnet_pblock_append(l, p, payload, payload_s); | |
499 | if (n == -1) | |
500 | { | |
501 | goto bad; | |
502 | } | |
503 | } | |
504 | ||
505 | return (ptag ? ptag : libnet_pblock_update(l, p, h, | |
506 | LIBNET_PBLOCK_LS_RTR_H)); | |
507 | bad: | |
508 | libnet_pblock_delete(l, p); | |
509 | return (-1); | |
510 | } | |
511 | ||
512 | ||
513 | libnet_ptag_t | |
514 | libnet_build_ospfv2_lsa_net(u_int32_t nmask, u_int32_t rtrid, | |
515 | u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag) | |
516 | { | |
517 | u_int32_t n, h; | |
518 | libnet_pblock_t *p; | |
519 | struct libnet_net_lsa_hdr net_lsa_hdr; | |
520 | ||
521 | if (l == NULL) | |
522 | { | |
523 | return (-1); | |
524 | } | |
525 | ||
526 | n = LIBNET_OSPF_LS_NET_H + payload_s; | |
527 | h = 0; | |
528 | ||
529 | /* | |
530 | * Find the existing protocol block if a ptag is specified, or create | |
531 | * a new one. | |
532 | */ | |
533 | p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_LS_NET_H); | |
534 | if (p == NULL) | |
535 | { | |
536 | return (-1); | |
537 | } | |
538 | ||
539 | memset(&net_lsa_hdr, 0, sizeof(net_lsa_hdr)); | |
540 | net_lsa_hdr.net_nmask.s_addr = htonl(nmask); | |
541 | net_lsa_hdr.net_rtr_id = htonl(rtrid); | |
542 | ||
543 | n = libnet_pblock_append(l, p, (u_int8_t *)&net_lsa_hdr, | |
544 | LIBNET_OSPF_LS_NET_H); | |
545 | if (n == -1) | |
546 | { | |
547 | goto bad; | |
548 | } | |
549 | ||
550 | if ((payload && !payload_s) || (!payload && payload_s)) | |
551 | { | |
552 | snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, | |
553 | "%s(): payload inconsistency\n", __func__); | |
554 | goto bad; | |
555 | } | |
556 | ||
557 | if (payload && payload_s) | |
558 | { | |
559 | n = libnet_pblock_append(l, p, payload, payload_s); | |
560 | if (n == -1) | |
561 | { | |
562 | goto bad; | |
563 | } | |
564 | } | |
565 | ||
566 | return (ptag ? ptag : libnet_pblock_update(l, p, h, | |
567 | LIBNET_PBLOCK_LS_NET_H)); | |
568 | bad: | |
569 | libnet_pblock_delete(l, p); | |
570 | return (-1); | |
571 | } | |
572 | ||
573 | ||
574 | libnet_ptag_t | |
575 | libnet_build_ospfv2_lsa_sum(u_int32_t nmask, u_int32_t metric, u_int tos, | |
576 | u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag) | |
577 | { | |
578 | u_int32_t n, h; | |
579 | libnet_pblock_t *p; | |
580 | struct libnet_sum_lsa_hdr sum_lsa_hdr; | |
581 | ||
582 | if (l == NULL) | |
583 | { | |
584 | return (-1); | |
585 | } | |
586 | ||
587 | n = LIBNET_OSPF_LS_SUM_H + payload_s; | |
588 | h = 0; | |
589 | ||
590 | /* | |
591 | * Find the existing protocol block if a ptag is specified, or create | |
592 | * a new one. | |
593 | */ | |
594 | p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_LS_SUM_H); | |
595 | if (p == NULL) | |
596 | { | |
597 | return (-1); | |
598 | } | |
599 | ||
600 | memset(&sum_lsa_hdr, 0, sizeof(sum_lsa_hdr)); | |
601 | sum_lsa_hdr.sum_nmask.s_addr = htonl(nmask); | |
602 | sum_lsa_hdr.sum_metric = htonl(metric); | |
603 | sum_lsa_hdr.sum_tos_metric = htonl(tos); | |
604 | ||
605 | n = libnet_pblock_append(l, p, (u_int8_t *)&sum_lsa_hdr, | |
606 | LIBNET_OSPF_LS_SUM_H); | |
607 | if (n == -1) | |
608 | { | |
609 | goto bad; | |
610 | } | |
611 | ||
612 | if ((payload && !payload_s) || (!payload && payload_s)) | |
613 | { | |
614 | snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, | |
615 | "%s(): payload inconsistency\n", __func__); | |
616 | goto bad; | |
617 | } | |
618 | ||
619 | if (payload && payload_s) | |
620 | { | |
621 | n = libnet_pblock_append(l, p, payload, payload_s); | |
622 | if (n == -1) | |
623 | { | |
624 | goto bad; | |
625 | } | |
626 | } | |
627 | ||
628 | return (ptag ? ptag : libnet_pblock_update(l, p, h, | |
629 | LIBNET_PBLOCK_LS_SUM_H)); | |
630 | bad: | |
631 | libnet_pblock_delete(l, p); | |
632 | return (-1); | |
633 | } | |
634 | ||
635 | ||
636 | libnet_ptag_t | |
637 | libnet_build_ospfv2_lsa_as(u_int32_t nmask, u_int metric, u_int32_t fwdaddr, | |
638 | u_int32_t tag, u_int8_t *payload, u_int32_t payload_s, libnet_t *l, | |
639 | libnet_ptag_t ptag) | |
640 | { | |
641 | u_int32_t n, h; | |
642 | libnet_pblock_t *p; | |
643 | struct libnet_as_lsa_hdr as_lsa_hdr; | |
644 | ||
645 | if (l == NULL) | |
646 | { | |
647 | return (-1); | |
648 | } | |
649 | ||
650 | n = LIBNET_OSPF_LS_AS_EXT_H + payload_s; | |
651 | h = 0; | |
652 | ||
653 | /* | |
654 | * Find the existing protocol block if a ptag is specified, or create | |
655 | * a new one. | |
656 | */ | |
657 | p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_LS_AS_EXT_H); | |
658 | if (p == NULL) | |
659 | { | |
660 | return (-1); | |
661 | } | |
662 | ||
663 | memset(&as_lsa_hdr, 0, sizeof(as_lsa_hdr)); | |
664 | as_lsa_hdr.as_nmask.s_addr = htonl(nmask); | |
665 | as_lsa_hdr.as_metric = htonl(metric); | |
666 | as_lsa_hdr.as_fwd_addr.s_addr = htonl(fwdaddr); | |
667 | as_lsa_hdr.as_rte_tag = htonl(tag); | |
668 | ||
669 | n = libnet_pblock_append(l, p, (u_int8_t *)&as_lsa_hdr, | |
670 | LIBNET_OSPF_LS_AS_EXT_H); | |
671 | if (n == -1) | |
672 | { | |
673 | goto bad; | |
674 | } | |
675 | ||
676 | if ((payload && !payload_s) || (!payload && payload_s)) | |
677 | { | |
678 | snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, | |
679 | "%s(): payload inconsistency\n", __func__); | |
680 | goto bad; | |
681 | } | |
682 | ||
683 | if (payload && payload_s) | |
684 | { | |
685 | n = libnet_pblock_append(l, p, payload, payload_s); | |
686 | if (n == -1) | |
687 | { | |
688 | goto bad; | |
689 | } | |
690 | } | |
691 | ||
692 | return (ptag ? ptag : libnet_pblock_update(l, p, h, | |
693 | LIBNET_PBLOCK_LS_AS_EXT_H)); | |
694 | bad: | |
695 | libnet_pblock_delete(l, p); | |
696 | return (-1); | |
697 | } | |
698 | ||
699 | /* EOF */ |