summaryrefslogtreecommitdiff
path: root/usr.sbin/bgpd/rde_rib.c
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2004-01-10 22:25:43 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2004-01-10 22:25:43 +0000
commit574bd409f2c24cd362fe27ec7e43afb8befca78a (patch)
treed9200f77c57d86ce7163ae2cbab8efd7b0f9f5da /usr.sbin/bgpd/rde_rib.c
parentceb96ca370f38e31423d047d24ebd2644c732c16 (diff)
Implement as path prepends. At least one prepend is needed for ebgp
neighbors. Fix a bug in the update generation. If no path attributes are available e.g. a packet with only withdraws we need to set (and write) the bgp path attribute field to zero. With this change we are able to send valid updates to our neighbors with one exception: the nexthop field which needs to be changed for ebgp neighbors. OK henning@
Diffstat (limited to 'usr.sbin/bgpd/rde_rib.c')
-rw-r--r--usr.sbin/bgpd/rde_rib.c78
1 files changed, 77 insertions, 1 deletions
diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c
index 097d18e02e6..f4712ffef3b 100644
--- a/usr.sbin/bgpd/rde_rib.c
+++ b/usr.sbin/bgpd/rde_rib.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_rib.c,v 1.15 2004/01/10 16:20:29 claudio Exp $ */
+/* $OpenBSD: rde_rib.c,v 1.16 2004/01/10 22:25:42 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -297,6 +297,82 @@ aspath_create(void *data, u_int16_t len)
return aspath;
}
+int
+aspath_write(void *p, u_int16_t len, struct aspath *aspath, u_int16_t myAS,
+ int prepend)
+{
+ u_char *b = p;
+ int tot_len, as_len, size, wpos = 0;
+ u_int16_t tmp;
+ u_int8_t type, attr_flag = ATTR_WELL_KNOWN;
+
+ if (prepend > 255)
+ /* lunatic prepends need to be blocked in the parser */
+ return (-1);
+
+ /* first calculate new size */
+ type = aspath->data[0];
+ size = aspath->data[1];
+ if (prepend == 0)
+ as_len = aspath->hdr.len;
+ else if (type == AS_SET || size + prepend > 255)
+ /* need to attach a new AS_SEQUENCE */
+ as_len = 2 + prepend * 2 + aspath->hdr.len;
+ else
+ as_len = prepend * 2 + aspath->hdr.len;
+
+ /* check buffer size */
+ tot_len = 2 + as_len;
+ if (as_len > 255) {
+ attr_flag |= ATTR_EXTLEN;
+ tot_len += 2;
+ } else
+ tot_len += 1;
+
+ if (tot_len > len)
+ return (-1);
+
+ /* header */
+ b[wpos++] = attr_flag;
+ b[wpos++] = ATTR_ASPATH;
+ if (as_len > 0xff) {
+ tmp = as_len;
+ tmp = htons(tmp);
+ memcpy(b, &tmp, 2);
+ wpos += 2;
+ } else
+ b[wpos++] = (u_char)(as_len & 0xff);
+
+ /* first prepends */
+ myAS = htons(myAS);
+ if (type == AS_SET) {
+ b[wpos++] = AS_SEQUENCE;
+ b[wpos++] = prepend;
+ for (; prepend > 0; prepend--) {
+ memcpy(b + wpos, &myAS, 2);
+ wpos += 2;
+ }
+ memcpy(b + wpos, aspath->data, aspath->hdr.len);
+ } else {
+ if (size + prepend > 255) {
+ b[wpos++] = AS_SEQUENCE;
+ b[wpos++] = size + prepend - 255;
+ for (; prepend + size > 255; prepend--) {
+ memcpy(b + wpos, &myAS, 2);
+ wpos += 2;
+ }
+ }
+ b[wpos++] = AS_SEQUENCE;
+ b[wpos++] = size + prepend;
+ for (; prepend > 0; prepend--) {
+ memcpy(b + wpos, &myAS, 2);
+ wpos += 2;
+ }
+ memcpy(b + wpos, aspath->data + 2, aspath->hdr.len - 2);
+ }
+ return (tot_len);
+}
+
void
aspath_destroy(struct aspath *aspath)
{