1 /*
2 * $Id: libnet_build_bgp.c,v 1.8 2004/04/13 17:32:28 mike Exp $
3 *
4 * libnet
5 * libnet_build_bgp.c - BGP packet assembler (RFC 1771)
6 *
7 * Copyright (c) 2003 Frederic Raynal <pappy@security-labs.org>
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 */
32
33 #if (HAVE_CONFIG_H)
34 #include "../include/config.h"
35 #endif
36 #if (!(_WIN32) || (__CYGWIN__))
37 #include "../include/libnet.h"
38 #else
39 #include "../include/win32/libnet.h"
40 #endif
41
42 libnet_ptag_t
libnet_build_bgp4_header(uint8_t marker[LIBNET_BGP4_MARKER_SIZE],uint16_t len,uint8_t type,const uint8_t * payload,uint32_t payload_s,libnet_t * l,libnet_ptag_t ptag)43 libnet_build_bgp4_header(uint8_t marker[LIBNET_BGP4_MARKER_SIZE],
44 uint16_t len, uint8_t type, const uint8_t *payload, uint32_t payload_s,
45 libnet_t *l, libnet_ptag_t ptag)
46 {
47 uint32_t n, h;
48 libnet_pblock_t *p;
49 struct libnet_bgp4_header_hdr bgp4_hdr;
50
51 if (l == NULL)
52 {
53 return (-1);
54 }
55
56 n = LIBNET_BGP4_HEADER_H + payload_s; /* size of memory block */
57 h = 0; /* BGP headers have no checksum */
58
59 /*
60 * Find the existing protocol block if a ptag is specified, or create
61 * a new one.
62 */
63 p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_BGP4_HEADER_H);
64 if (p == NULL)
65 {
66 return (-1);
67 }
68
69 memset(&bgp4_hdr, 0, sizeof(bgp4_hdr));
70 memcpy(bgp4_hdr.marker, marker, LIBNET_BGP4_MARKER_SIZE * sizeof(uint8_t));
71 bgp4_hdr.len = htons(len);
72 bgp4_hdr.type = type;
73
74 n = libnet_pblock_append(l, p, (uint8_t *)&bgp4_hdr, LIBNET_BGP4_HEADER_H);
75 if (n == -1)
76 {
77 goto bad;
78 }
79
80 /* boilerplate payload sanity check / append macro */
81 LIBNET_DO_PAYLOAD(l, p);
82
83 return (ptag ? ptag : libnet_pblock_update(l, p, h,
84 LIBNET_PBLOCK_BGP4_HEADER_H));
85 bad:
86 libnet_pblock_delete(l, p);
87 return (-1);
88 }
89
90 libnet_ptag_t
libnet_build_bgp4_open(uint8_t version,uint16_t src_as,uint16_t hold_time,uint32_t bgp_id,uint8_t opt_len,const uint8_t * payload,uint32_t payload_s,libnet_t * l,libnet_ptag_t ptag)91 libnet_build_bgp4_open(uint8_t version, uint16_t src_as, uint16_t hold_time,
92 uint32_t bgp_id, uint8_t opt_len, const uint8_t *payload, uint32_t payload_s,
93 libnet_t *l, libnet_ptag_t ptag)
94 {
95 uint32_t n, h;
96 libnet_pblock_t *p;
97 uint16_t val;
98
99 if (l == NULL)
100 {
101 return (-1);
102 }
103
104 n = LIBNET_BGP4_OPEN_H + payload_s; /* size of memory block */
105 h = 0; /* BGP msg have no checksum */
106
107 /*
108 * Find the existing protocol block if a ptag is specified, or create
109 * a new one.
110 */
111 p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_BGP4_OPEN_H);
112 if (p == NULL)
113 {
114 return (-1);
115 }
116
117 /* for memory alignment reason, we need to append each field separately */
118 n = libnet_pblock_append(l, p, (uint8_t *)&version, sizeof (version));
119 if (n == -1)
120 {
121 goto bad;
122 }
123
124 val = htons(src_as);
125 n = libnet_pblock_append(l, p, (uint8_t *)&val, sizeof(src_as));
126 if (n == -1)
127 {
128 goto bad;
129 }
130
131 val = htons(hold_time);
132 n = libnet_pblock_append(l, p, (uint8_t *)&val, sizeof(hold_time));
133 if (n == -1)
134 {
135 goto bad;
136 }
137
138 n = htonl(bgp_id);
139 n = libnet_pblock_append(l, p, (uint8_t *)&n, sizeof(bgp_id));
140 if (n == -1)
141 {
142 goto bad;
143 }
144
145 n = libnet_pblock_append(l, p, (uint8_t *)&opt_len, sizeof(opt_len));
146 if (n == -1)
147 {
148 goto bad;
149 }
150
151 /* boilerplate payload sanity check / append macro */
152 LIBNET_DO_PAYLOAD(l, p);
153
154 return (ptag ? ptag : libnet_pblock_update(l, p, h,
155 LIBNET_PBLOCK_BGP4_OPEN_H));
156 bad:
157 libnet_pblock_delete(l, p);
158 return (-1);
159 }
160
161 libnet_ptag_t
libnet_build_bgp4_update(uint16_t unfeasible_rt_len,const uint8_t * withdrawn_rt,uint16_t total_path_attr_len,const uint8_t * path_attributes,uint16_t info_len,uint8_t * reachability_info,const uint8_t * payload,uint32_t payload_s,libnet_t * l,libnet_ptag_t ptag)162 libnet_build_bgp4_update(uint16_t unfeasible_rt_len, const uint8_t *withdrawn_rt,
163 uint16_t total_path_attr_len, const uint8_t *path_attributes, uint16_t info_len,
164 uint8_t *reachability_info, const uint8_t *payload, uint32_t payload_s,
165 libnet_t *l, libnet_ptag_t ptag)
166 {
167 uint32_t n, h;
168 libnet_pblock_t *p;
169 uint16_t length;
170
171 if (l == NULL)
172 {
173 return (-1);
174 }
175
176 /* size of memory block */
177 n = LIBNET_BGP4_UPDATE_H + unfeasible_rt_len + total_path_attr_len +
178 info_len + payload_s;
179
180 /* BGP msg have no checksum */
181 h = 0;
182
183 /*
184 * Find the existing protocol block if a ptag is specified, or create
185 * a new one.
186 */
187 p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_BGP4_UPDATE_H);
188 if (p == NULL)
189 {
190 return (-1);
191 }
192
193 /* for memory alignment reason, we need to append each field separately */
194 length = htons(unfeasible_rt_len);
195 n = libnet_pblock_append(l, p, (uint8_t *)&length,
196 sizeof (unfeasible_rt_len));
197 if (n == -1)
198 {
199 goto bad;
200 }
201
202 if (unfeasible_rt_len && withdrawn_rt)
203 {
204 n = libnet_pblock_append(l, p, withdrawn_rt, unfeasible_rt_len);
205 if (n == -1)
206 {
207 goto bad;
208 }
209 }
210
211 length = htons(total_path_attr_len);
212 n = libnet_pblock_append(l, p, (uint8_t *)&length,
213 sizeof (total_path_attr_len));
214 if (n == -1)
215 {
216 goto bad;
217 }
218
219 if (total_path_attr_len && path_attributes)
220 {
221 n = libnet_pblock_append(l, p, path_attributes, total_path_attr_len);
222 if (n == -1)
223 {
224 goto bad;
225 }
226 }
227
228 if (info_len && reachability_info)
229 {
230 n = libnet_pblock_append(l, p, reachability_info, info_len);
231 if (n == -1)
232 {
233 goto bad;
234 }
235 }
236
237 /* boilerplate payload sanity check / append macro */
238 LIBNET_DO_PAYLOAD(l, p);
239
240 return (ptag ? ptag : libnet_pblock_update(l, p, h,
241 LIBNET_PBLOCK_BGP4_UPDATE_H));
242 bad:
243 libnet_pblock_delete(l, p);
244 return (-1);
245 }
246
247 libnet_ptag_t
libnet_build_bgp4_notification(uint8_t err_code,uint8_t err_subcode,const uint8_t * payload,uint32_t payload_s,libnet_t * l,libnet_ptag_t ptag)248 libnet_build_bgp4_notification(uint8_t err_code, uint8_t err_subcode,
249 const uint8_t *payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
250 {
251 uint32_t n, h;
252 libnet_pblock_t *p;
253 struct libnet_bgp4_notification_hdr bgp4_hdr;
254
255 if (l == NULL)
256 {
257 return (-1);
258 }
259
260 n = LIBNET_BGP4_NOTIFICATION_H + + payload_s; /* size of memory block */
261 h = 0;
262
263 /*
264 * Find the existing protocol block if a ptag is specified, or create
265 * a new one.
266 */
267 p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_BGP4_NOTIFICATION_H);
268 if (p == NULL)
269 {
270 return (-1);
271 }
272
273 memset(&bgp4_hdr, 0, sizeof(bgp4_hdr));
274 bgp4_hdr.err_code = err_code;
275 bgp4_hdr.err_subcode = err_subcode;
276
277 n = libnet_pblock_append(l, p, (uint8_t *)&bgp4_hdr,
278 LIBNET_BGP4_NOTIFICATION_H);
279 if (n == -1)
280 {
281 goto bad;
282 }
283
284 /* boilerplate payload sanity check / append macro */
285 LIBNET_DO_PAYLOAD(l, p);
286
287 return (ptag ? ptag : libnet_pblock_update(l, p, h,
288 LIBNET_PBLOCK_BGP4_NOTIFICATION_H));
289 bad:
290 libnet_pblock_delete(l, p);
291 return (-1);
292 }
293
294 /* EOF */
295