1 /* BGP FlowSpec Utilities
3 * Copyright (C) 2017 ChinaTelecom SDN Group
4 * Copyright (C) 2018 6WIND
6 * FRRouting is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * FRRouting is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 #include "bgp_flowspec_util.h"
26 static void hex2bin(uint8_t *hex
, int *bin
)
31 while (remainder
>= 1 && i
< 8) {
32 bin
[7-i
] = remainder
% 2;
33 remainder
= remainder
/ 2;
40 static int hexstr2num(uint8_t *hexstr
, int len
)
45 for (i
= 0; i
< len
; i
++)
46 num
= hexstr
[i
] + 16*16*num
;
52 * handle the flowspec address src/dst or generic address NLRI
53 * return number of bytes analysed ( >= 0).
55 int bgp_flowspec_ip_address(enum bgp_flowspec_util_nlri_t type
,
58 void *result
, int *error
)
60 char *display
= (char *)result
; /* for return_string */
61 struct prefix
*prefix
= (struct prefix
*)result
;
63 struct prefix prefix_local
;
67 memset(&prefix_local
, 0, sizeof(struct prefix
));
68 /* read the prefix length */
69 prefix_local
.prefixlen
= nlri_ptr
[offset
];
70 psize
= PSIZE(prefix_local
.prefixlen
);
72 /* TODO Flowspec IPv6 Support */
73 prefix_local
.family
= AF_INET
;
74 /* Prefix length check. */
75 if (prefix_local
.prefixlen
> prefix_blen(&prefix_local
) * 8)
77 /* When packet overflow occur return immediately. */
78 if (psize
+ offset
> max_len
)
80 /* Defensive coding, double-check
81 * the psize fits in a struct prefix
83 if (psize
> (ssize_t
)sizeof(prefix_local
.u
))
85 memcpy(&prefix_local
.u
.prefix
, &nlri_ptr
[offset
], psize
);
88 case BGP_FLOWSPEC_RETURN_STRING
:
89 prefix2str(&prefix_local
, display
,
90 BGP_FLOWSPEC_STRING_DISPLAY_MAX
);
92 case BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE
:
93 PREFIX_COPY_IPV4(prefix
, &prefix_local
)
95 case BGP_FLOWSPEC_VALIDATE_ONLY
:
103 * handle the flowspec operator NLRI
104 * return number of bytes analysed
105 * if there is an error, the passed error param is used to give error:
106 * -1 if decoding error,
108 int bgp_flowspec_op_decode(enum bgp_flowspec_util_nlri_t type
,
111 void *result
, int *error
)
114 int len
, value
, value_size
;
116 char *ptr
= (char *)result
; /* for return_string */
121 hex2bin(&nlri_ptr
[offset
], op
);
124 value_size
= 1 << len
;
125 value
= hexstr2num(&nlri_ptr
[offset
], value_size
);
126 /* can not be < and > at the same time */
127 if (op
[5] == 1 && op
[6] == 1)
129 /* if first element, AND bit can not be set */
130 if (op
[1] == 1 && loop
== 0)
133 case BGP_FLOWSPEC_RETURN_STRING
:
135 ptr
+= sprintf(ptr
, ", ");
137 ptr
+= sprintf(ptr
, "<");
139 ptr
+= sprintf(ptr
, ">");
141 ptr
+= sprintf(ptr
, "=");
142 ptr
+= sprintf(ptr
, " %d ", value
);
144 case BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE
:
145 /* TODO : FS OPAQUE */
147 case BGP_FLOWSPEC_VALIDATE_ONLY
:
152 offset
+= value_size
;
154 } while (op
[0] == 0 && offset
< max_len
- 1);
155 if (offset
> max_len
)
157 /* use error parameter to count the number of entries */
165 * handle the flowspec tcpflags field
166 * return number of bytes analysed
167 * if there is an error, the passed error param is used to give error:
168 * -1 if decoding error,
170 int bgp_flowspec_tcpflags_decode(enum bgp_flowspec_util_nlri_t type
,
173 void *result
, int *error
)
176 int len
, value_size
, loop
= 0, value
;
177 char *ptr
= (char *)result
; /* for return_string */
182 hex2bin(&nlri_ptr
[offset
], op
);
183 /* if first element, AND bit can not be set */
184 if (op
[1] == 1 && loop
== 0)
187 len
= 2 * op
[2] + op
[3];
188 value_size
= 1 << len
;
189 value
= hexstr2num(&nlri_ptr
[offset
], value_size
);
191 case BGP_FLOWSPEC_RETURN_STRING
:
192 if (op
[1] == 1 && loop
!= 0)
193 ptr
+= sprintf(ptr
, ", and ");
194 else if (op
[1] == 0 && loop
!= 0)
195 ptr
+= sprintf(ptr
, ", or ");
196 ptr
+= sprintf(ptr
, "tcp flags is ");
198 ptr
+= sprintf(ptr
, "not ");
200 ptr
+= sprintf(ptr
, "exactly match ");
201 ptr
+= sprintf(ptr
, "%d", value
);
203 case BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE
:
204 /* TODO : FS OPAQUE */
206 case BGP_FLOWSPEC_VALIDATE_ONLY
:
211 offset
+= value_size
;
213 } while (op
[0] == 0 && offset
< max_len
- 1);
214 if (offset
> max_len
)
216 /* use error parameter to count the number of entries */
223 * handle the flowspec fragment type field
224 * return error (returned values are invalid) or number of bytes analysed
225 * -1 if error in decoding
226 * >= 0 : number of bytes analysed (ok).
228 int bgp_flowspec_fragment_type_decode(enum bgp_flowspec_util_nlri_t type
,
231 void *result
, int *error
)
234 int len
, value
, value_size
, loop
= 0;
235 char *ptr
= (char *)result
; /* for return_string */
240 hex2bin(&nlri_ptr
[offset
], op
);
242 len
= 2 * op
[2] + op
[3];
243 value_size
= 1 << len
;
244 value
= hexstr2num(&nlri_ptr
[offset
], value_size
);
245 if (value
!= 1 && value
!= 2 && value
!= 4 && value
!= 8)
247 offset
+= value_size
;
248 /* TODO : as per RFC5574 : first Fragment bits are Reserved
249 * does that mean that it is not possible
250 * to handle multiple occurences ?
251 * as of today, we only grab the first TCP fragment
259 case BGP_FLOWSPEC_RETURN_STRING
:
262 ptr
+= sprintf(ptr
, "dont-fragment");
265 ptr
+= sprintf(ptr
, "is-fragment");
268 ptr
+= sprintf(ptr
, "first-fragment");
271 ptr
+= sprintf(ptr
, "last-fragment");
277 case BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE
:
278 /* TODO : FS OPAQUE */
280 case BGP_FLOWSPEC_VALIDATE_ONLY
:
286 } while (op
[0] == 0 && offset
< max_len
- 1);
287 if (offset
> max_len
)