Mailing List Archive

[PATCH 2/2] lib: move and complete RD library to rd.[ch] files
Move rd structure handling routines into a common file. This API
is used by BGP daemons when handling SAFI MPLS and SAFI ENCAP address
sub families. This could also to be used as library for other daemons.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
---
bgpd/bgp_encap.c | 2 +-
bgpd/bgp_mplsvpn.c | 144 +-------------------------------------------
bgpd/bgp_mplsvpn.h | 26 --------
bgpd/bgp_route.c | 1 +
bgpd/bgp_vty.c | 1 +
bgpd/bgpd.c | 1 +
bgpd/bgpd.h | 4 ++
lib/Makefile.am | 4 +-
lib/rd.c | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/rd.h | 59 ++++++++++++++++++
10 files changed, 243 insertions(+), 172 deletions(-)
create mode 100644 lib/rd.c
create mode 100644 lib/rd.h

diff --git a/bgpd/bgp_encap.c b/bgpd/bgp_encap.c
index 8361d3f55a49..bc58ade161c7 100644
--- a/bgpd/bgp_encap.c
+++ b/bgpd/bgp_encap.c
@@ -35,13 +35,13 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "memory.h"
#include "stream.h"
#include "filter.h"
+#include "rd.h"

#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_ecommunity.h"
-#include "bgpd/bgp_mplsvpn.h"
#include "bgpd/bgp_vty.h"
#include "bgpd/bgp_encap.h"

diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 392a239f19c8..9a910cf3715b 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -26,6 +26,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "memory.h"
#include "stream.h"
#include "filter.h"
+#include "rd.h"

#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
@@ -35,16 +36,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_mplsvpn.h"
#include "bgpd/bgp_packet.h"

-u_int16_t
-decode_rd_type (u_char *pnt)
-{
- u_int16_t v;
-
- v = ((u_int16_t) *pnt++ << 8);
- v |= (u_int16_t) *pnt;
- return v;
-}
-
u_int32_t
decode_label (u_char *pnt)
{
@@ -56,43 +47,6 @@ decode_label (u_char *pnt)
return l;
}

-/* type == RD_TYPE_AS */
-void
-decode_rd_as (u_char *pnt, struct rd_as *rd_as)
-{
- rd_as->as = (u_int16_t) *pnt++ << 8;
- rd_as->as |= (u_int16_t) *pnt++;
-
- rd_as->val = ((u_int32_t) *pnt++ << 24);
- rd_as->val |= ((u_int32_t) *pnt++ << 16);
- rd_as->val |= ((u_int32_t) *pnt++ << 8);
- rd_as->val |= (u_int32_t) *pnt;
-}
-
-/* type == RD_TYPE_AS4 */
-void
-decode_rd_as4 (u_char *pnt, struct rd_as *rd_as)
-{
- rd_as->as = (u_int32_t) *pnt++ << 24;
- rd_as->as |= (u_int32_t) *pnt++ << 16;
- rd_as->as |= (u_int32_t) *pnt++ << 8;
- rd_as->as |= (u_int32_t) *pnt++;
-
- rd_as->val = ((u_int16_t) *pnt++ << 8);
- rd_as->val |= (u_int16_t) *pnt;
-}
-
-/* type == RD_TYPE_IP */
-void
-decode_rd_ip (u_char *pnt, struct rd_ip *rd_ip)
-{
- memcpy (&rd_ip->ip, pnt, 4);
- pnt += 4;
-
- rd_ip->val = ((u_int16_t) *pnt++ << 8);
- rd_ip->val |= (u_int16_t) *pnt;
-}
-
int
bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr,
struct bgp_nlri *packet)
@@ -226,66 +180,6 @@ bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr,
}

int
-str2prefix_rd (const char *str, struct prefix_rd *prd)
-{
- int ret; /* ret of called functions */
- int lret; /* local ret, of this func */
- char *p;
- char *p2;
- struct stream *s = NULL;
- char *half = NULL;
- struct in_addr addr;
-
- s = stream_new (8);
-
- prd->family = AF_UNSPEC;
- prd->prefixlen = 64;
-
- lret = 0;
- p = strchr (str, ':');
- if (! p)
- goto out;
-
- if (! all_digit (p + 1))
- goto out;
-
- half = XMALLOC (MTYPE_TMP, (p - str) + 1);
- memcpy (half, str, (p - str));
- half[p - str] = '\0';
-
- p2 = strchr (str, '.');
-
- if (! p2)
- {
- if (! all_digit (half))
- goto out;
-
- stream_putw (s, RD_TYPE_AS);
- stream_putw (s, atoi (half));
- stream_putl (s, atol (p + 1));
- }
- else
- {
- ret = inet_aton (half, &addr);
- if (! ret)
- goto out;
-
- stream_putw (s, RD_TYPE_IP);
- stream_put_in_addr (s, &addr);
- stream_putw (s, atol (p + 1));
- }
- memcpy (prd->val, s->data, 8);
- lret = 1;
-
-out:
- if (s)
- stream_free (s);
- if (half)
- XFREE(MTYPE_TMP, half);
- return lret;
-}
-
-int
str2tag (const char *str, u_char *tag)
{
unsigned long l;
@@ -310,42 +204,6 @@ str2tag (const char *str, u_char *tag)
return 1;
}

-char *
-prefix_rd2str (struct prefix_rd *prd, char *buf, size_t size)
-{
- u_char *pnt;
- u_int16_t type;
- struct rd_as rd_as;
- struct rd_ip rd_ip;
-
- if (size < RD_ADDRSTRLEN)
- return NULL;
-
- pnt = prd->val;
-
- type = decode_rd_type (pnt);
-
- if (type == RD_TYPE_AS)
- {
- decode_rd_as (pnt + 2, &rd_as);
- snprintf (buf, size, "%u:%d", rd_as.as, rd_as.val);
- return buf;
- }
- else if (type == RD_TYPE_AS4)
- {
- decode_rd_as4 (pnt + 2, &rd_as);
- snprintf (buf, size, "%u:%d", rd_as.as, rd_as.val);
- return buf;
- }
- else if (type == RD_TYPE_IP)
- {
- decode_rd_ip (pnt + 2, &rd_ip);
- snprintf (buf, size, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
- return buf;
- }
- return NULL;
-}
-
/* For testing purpose, static route of MPLS-VPN. */
DEFUN (vpnv4_network,
vpnv4_network_cmd,
diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h
index 3fbbd335405b..488308127294 100644
--- a/bgpd/bgp_mplsvpn.h
+++ b/bgpd/bgp_mplsvpn.h
@@ -21,36 +21,10 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#ifndef _QUAGGA_BGP_MPLSVPN_H
#define _QUAGGA_BGP_MPLSVPN_H

-#define RD_TYPE_AS 0
-#define RD_TYPE_IP 1
-#define RD_TYPE_AS4 2
-
-#define RD_ADDRSTRLEN 28
-
-struct rd_as
-{
- u_int16_t type;
- as_t as;
- u_int32_t val;
-};
-
-struct rd_ip
-{
- u_int16_t type;
- struct in_addr ip;
- u_int16_t val;
-};
-
-extern u_int16_t decode_rd_type (u_char *);
extern void bgp_mplsvpn_init (void);
extern int bgp_nlri_parse_vpn (struct peer *, struct attr *, struct bgp_nlri *);
extern u_int32_t decode_label (u_char *);
extern void encode_label(u_int32_t, u_char *);
-extern void decode_rd_as (u_char *, struct rd_as *);
-extern void decode_rd_as4 (u_char *, struct rd_as *);
-extern void decode_rd_ip (u_char *, struct rd_ip *);
-extern int str2prefix_rd (const char *, struct prefix_rd *);
extern int str2tag (const char *, u_char *);
-extern char *prefix_rd2str (struct prefix_rd *, char *, size_t);

#endif /* _QUAGGA_BGP_MPLSVPN_H */
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 4cb6c141bcdc..cf705509c55b 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -34,6 +34,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "plist.h"
#include "thread.h"
#include "workqueue.h"
+#include "rd.h"

#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 7af4e81a87b1..e5a618e5425a 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -31,6 +31,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "memory.h"
#include "hash.h"
#include "filter.h"
+#include "rd.h"

#include "bgpd/bgpd.h"
#include "bgpd/bgp_advertise.h"
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 018a59941101..50359603841a 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -37,6 +37,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "linklist.h"
#include "workqueue.h"
#include "table.h"
+#include "rd.h"

#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 0058b581377b..b625cd345a0a 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -25,7 +25,11 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "sockunion.h"

/* Typedef BGP specific types. */
+#ifndef AS_T
+#define AS_T
typedef u_int32_t as_t;
+#endif
+
typedef u_int16_t as16_t; /* we may still encounter 16 Bit asnums */
typedef u_int16_t bgp_size_t;

diff --git a/lib/Makefile.am b/lib/Makefile.am
index be8495f140e4..9a0bfdb9751f 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -14,7 +14,7 @@ libzebra_la_SOURCES = \
filter.c routemap.c distribute.c stream.c str.c log.c plist.c \
zclient.c sockopt.c smux.c agentx.c snmp.c md5.c if_rmap.c keychain.c privs.c \
sigevent.c pqueue.c jhash.c memtypes.c workqueue.c vrf.c \
- event_counter.c nexthop.c
+ event_counter.c nexthop.c rd.c

BUILT_SOURCES = memtypes.h route_types.h gitversion.h

@@ -30,7 +30,7 @@ pkginclude_HEADERS = \
plist.h zclient.h sockopt.h smux.h md5.h if_rmap.h keychain.h \
privs.h sigevent.h pqueue.h jhash.h zassert.h memtypes.h \
workqueue.h route_types.h libospf.h vrf.h fifo.h event_counter.h \
- nexthop.h
+ nexthop.h rd.h

noinst_HEADERS = \
plist_int.h
diff --git a/lib/rd.c b/lib/rd.c
new file mode 100644
index 000000000000..45b6afa221ae
--- /dev/null
+++ b/lib/rd.c
@@ -0,0 +1,173 @@
+/* MPLS-VPN
+ Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING. If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#include <zebra.h>
+
+#include "command.h"
+#include "prefix.h"
+#include "log.h"
+#include "memory.h"
+#include "stream.h"
+#include "rd.h"
+
+int
+str2prefix_rd (const char *str, struct prefix_rd *prd)
+{
+ int ret; /* ret of called functions */
+ int lret; /* local ret, of this func */
+ char *p;
+ char *p2;
+ struct stream *s = NULL;
+ char *half = NULL;
+ struct in_addr addr;
+
+ s = stream_new (8);
+
+ prd->family = AF_UNSPEC;
+ prd->prefixlen = 64;
+
+ lret = 0;
+ p = strchr (str, ':');
+ if (! p)
+ goto out;
+
+ if (! all_digit (p + 1))
+ goto out;
+
+ half = XMALLOC (MTYPE_TMP, (p - str) + 1);
+ memcpy (half, str, (p - str));
+ half[p - str] = '\0';
+
+ p2 = strchr (str, '.');
+
+ if (! p2)
+ {
+ if (! all_digit (half))
+ goto out;
+
+ stream_putw (s, RD_TYPE_AS);
+ stream_putw (s, atoi (half));
+ stream_putl (s, atol (p + 1));
+ }
+ else
+ {
+ ret = inet_aton (half, &addr);
+ if (! ret)
+ goto out;
+
+ stream_putw (s, RD_TYPE_IP);
+ stream_put_in_addr (s, &addr);
+ stream_putw (s, atol (p + 1));
+ }
+ memcpy (prd->val, s->data, 8);
+ lret = 1;
+
+out:
+ if (s)
+ stream_free (s);
+ if (half)
+ XFREE(MTYPE_TMP, half);
+ return lret;
+}
+
+u_int16_t
+decode_rd_type (u_char *pnt)
+{
+ u_int16_t v;
+
+ v = ((u_int16_t) *pnt++ << 8);
+ v |= (u_int16_t) *pnt;
+
+ return v;
+}
+
+/* type == RD_TYPE_AS */
+void
+decode_rd_as (u_char *pnt, struct rd_as *rd_as)
+{
+ rd_as->as = (u_int16_t) *pnt++ << 8;
+ rd_as->as |= (u_int16_t) *pnt++;
+
+ rd_as->val = ((u_int32_t) *pnt++ << 24);
+ rd_as->val |= ((u_int32_t) *pnt++ << 16);
+ rd_as->val |= ((u_int32_t) *pnt++ << 8);
+ rd_as->val |= (u_int32_t) *pnt;
+}
+
+/* type == RD_TYPE_AS4 */
+void
+decode_rd_as4 (u_char *pnt, struct rd_as *rd_as)
+{
+ rd_as->as = (u_int32_t) *pnt++ << 24;
+ rd_as->as |= (u_int32_t) *pnt++ << 16;
+ rd_as->as |= (u_int32_t) *pnt++ << 8;
+ rd_as->as |= (u_int32_t) *pnt++;
+
+ rd_as->val = ((u_int16_t) *pnt++ << 8);
+ rd_as->val |= (u_int16_t) *pnt;
+}
+
+/* type == RD_TYPE_IP */
+void
+decode_rd_ip (u_char *pnt, struct rd_ip *rd_ip)
+{
+ memcpy (&rd_ip->ip, pnt, 4);
+ pnt += 4;
+
+ rd_ip->val = ((u_int16_t) *pnt++ << 8);
+ rd_ip->val |= (u_int16_t) *pnt;
+}
+
+char *
+prefix_rd2str (struct prefix_rd *prd, char *buf, size_t size)
+{
+ u_char *pnt;
+ u_int16_t type;
+ struct rd_as rd_as;
+ struct rd_ip rd_ip;
+
+ if (size < RD_ADDRSTRLEN)
+ return NULL;
+
+ pnt = prd->val;
+
+ type = decode_rd_type (pnt);
+
+ if (type == RD_TYPE_AS)
+ {
+ decode_rd_as (pnt + 2, &rd_as);
+ snprintf (buf, size, "%u:%d", rd_as.as, rd_as.val);
+ return buf;
+ }
+ else if (type == RD_TYPE_AS4)
+ {
+ decode_rd_as4 (pnt + 2, &rd_as);
+ snprintf (buf, size, "%u:%d", rd_as.as, rd_as.val);
+ return buf;
+ }
+ else if (type == RD_TYPE_IP)
+ {
+ decode_rd_ip (pnt + 2, &rd_ip);
+ snprintf (buf, size, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
+ return buf;
+ }
+
+ return NULL;
+}
diff --git a/lib/rd.h b/lib/rd.h
new file mode 100644
index 000000000000..c04d754e8fa2
--- /dev/null
+++ b/lib/rd.h
@@ -0,0 +1,59 @@
+/*
+ * Route Distinguisher Structure
+ * Copyright (C) 2016 6WIND
+ *
+ * This file is part of Quagga.
+ *
+ * GNU Quagga is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Quagga is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Quagga; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_RD_H
+#define _ZEBRA_RD_H
+
+#ifndef AS_T
+#define AS_T
+typedef u_int32_t as_t;
+#endif
+
+struct rd_as
+{
+ u_int16_t type;
+ as_t as;
+ u_int32_t val;
+};
+
+struct rd_ip
+{
+ u_int16_t type;
+ struct in_addr ip;
+ u_int16_t val;
+};
+
+#define RD_TYPE_AS 0
+#define RD_TYPE_IP 1
+#define RD_TYPE_AS4 2
+
+/* Maximum route distinguisher string length */
+#define RD_ADDRSTRLEN 28
+
+extern u_int16_t decode_rd_type (u_char *pnt);
+extern void decode_rd_as (u_char *pnt, struct rd_as *rd_as);
+extern void decode_rd_as4 (u_char *pnt, struct rd_as *rd_as);
+extern void decode_rd_ip (u_char *pnt, struct rd_ip *rd_ip);
+extern int str2prefix_rd (const char *, struct prefix_rd *);
+extern char *prefix_rd2str (struct prefix_rd *, char *, size_t);
+#endif /* _BGP_RD_H */
+
--
2.1.4


_______________________________________________
Quagga-dev mailing list
Quagga-dev@lists.quagga.net
https://lists.quagga.net/mailman/listinfo/quagga-dev
Re: [PATCH 2/2] lib: move and complete RD library to rd.[ch] files [ In reply to ]
On Wed, 12 Oct 2016, Philippe Guibert wrote:

> +u_int16_t
> +decode_rd_type (u_char *pnt)
> +{
> + u_int16_t v;
> +
> + v = ((u_int16_t) *pnt++ << 8);
> + v |= (u_int16_t) *pnt;
> +
> + return v;
> +}
> +
> +/* type == RD_TYPE_AS */
> +void
> +decode_rd_as (u_char *pnt, struct rd_as *rd_as)
> +{
> + rd_as->as = (u_int16_t) *pnt++ << 8;
> + rd_as->as |= (u_int16_t) *pnt++;
> +
> + rd_as->val = ((u_int32_t) *pnt++ << 24);
> + rd_as->val |= ((u_int32_t) *pnt++ << 16);
> + rd_as->val |= ((u_int32_t) *pnt++ << 8);
> + rd_as->val |= (u_int32_t) *pnt;
> +}
> +
> +/* type == RD_TYPE_AS4 */
> +void
> +decode_rd_as4 (u_char *pnt, struct rd_as *rd_as)
> +{
> + rd_as->as = (u_int32_t) *pnt++ << 24;
> + rd_as->as |= (u_int32_t) *pnt++ << 16;
> + rd_as->as |= (u_int32_t) *pnt++ << 8;
> + rd_as->as |= (u_int32_t) *pnt++;
> +
> + rd_as->val = ((u_int16_t) *pnt++ << 8);
> + rd_as->val |= (u_int16_t) *pnt;
> +}
> +
> +/* type == RD_TYPE_IP */
> +void
> +decode_rd_ip (u_char *pnt, struct rd_ip *rd_ip)
> +{
> + memcpy (&rd_ip->ip, pnt, 4);
> + pnt += 4;
> +
> + rd_ip->val = ((u_int16_t) *pnt++ << 8);
> + rd_ip->val |= (u_int16_t) *pnt;
> +}

> +
> +char *
> +prefix_rd2str (struct prefix_rd *prd, char *buf, size_t size)
> +{

So, one of my nits with the original submission was the bare pointer
parsing. It needs to go via lib/stream. Whatever nits one can find in
the aesthetics of lib/stream and its available exception handling at the
moment being confined to a very blunt instrument (be nice to have an
error 'absorbing' interface, with passive reporting of errors, too),
lib/stream does a great job at turning overflow bugs into DoS bugs. As
long as it is used, of course.

And it really should be used, and we need to get picky about requiring
it be used in new submissions, as well as hunting down and updating
existing code that isn't.

As you're the lucky one touching it next, could you do the honours?

(prefix_rd2str doesn't have to go through lib/stream, assuming all
constructions of prefix_rd did).

regards,
--
Paul Jakma | paul@jakma.org | @pjakma | Key ID: 0xD86BF79464A2FF6A
Fortune:
I have a simple rule in life: If I don't understand something, it must be bad.

- Linus Torvalds

_______________________________________________
Quagga-dev mailing list
Quagga-dev@lists.quagga.net
https://lists.quagga.net/mailman/listinfo/quagga-dev