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