commit 5183b61688db0d13504e748f7d05efe3f135bad5 Author: Thierry FOURNIER Date: Fri Aug 23 15:15:33 2013 +0200 FEAT: Define protocol volatile into nest/proto.c and nest/protocol.h diff --git a/configure.in b/configure.in index 46a6ecd..946fe95 100644 --- a/configure.in +++ b/configure.in @@ -43,11 +43,11 @@ AC_SUBST(srcdir_rel_mf) if test "$enable_ipv6" = yes ; then ip=ipv6 SUFFIX6=6 - all_protocols=bgp,ospf,pipe,radv,rip,static + all_protocols=bgp,ospf,pipe,radv,rip,static,volatile else ip=ipv4 SUFFIX6="" - all_protocols=bgp,ospf,pipe,rip,static + all_protocols=bgp,ospf,pipe,rip,static,volatile fi if test "$with_protocols" = all ; then diff --git a/nest/proto.c b/nest/proto.c index 4a154d5..f4a477f 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -578,6 +578,9 @@ protos_build(void) #ifdef CONFIG_BGP proto_build(&proto_bgp); #endif +#ifdef CONFIG_VOLATILE + proto_build(&proto_volatile); +#endif proto_pool = rp_new(&root_pool, "Protocols"); proto_flush_event = ev_new(proto_pool); proto_flush_event->hook = proto_flush_all; diff --git a/nest/protocol.h b/nest/protocol.h index f95905a..f83976c 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -72,7 +72,7 @@ void protos_dump_all(void); extern struct protocol proto_device, proto_radv, proto_rip, proto_static, - proto_ospf, proto_pipe, proto_bgp; + proto_ospf, proto_pipe, proto_bgp, proto_volatile; /* * Routing Protocol Instance diff --git a/proto/Doc b/proto/Doc index 16b084f..cb16a43 100644 --- a/proto/Doc +++ b/proto/Doc @@ -5,4 +5,5 @@ C pipe C rip C radv C static +C volatile S ../nest/rt-dev.c diff --git a/proto/volatile/Doc b/proto/volatile/Doc new file mode 100644 index 0000000..2d34a68 --- /dev/null +++ b/proto/volatile/Doc @@ -0,0 +1 @@ +S volatile.c diff --git a/proto/volatile/Makefile b/proto/volatile/Makefile new file mode 100644 index 0000000..8388e27 --- /dev/null +++ b/proto/volatile/Makefile @@ -0,0 +1,6 @@ +source=volatile.c +root-rel=../../ +dir-name=proto/volatile + +include ../../Rules + diff --git a/proto/volatile/config.Y b/proto/volatile/config.Y new file mode 100644 index 0000000..f107c9c --- /dev/null +++ b/proto/volatile/config.Y @@ -0,0 +1,75 @@ +/* + * BIRD -- Static Protocol Configuration + * + * (c) 2013--2013 Thierry FOURNIER + * + * Can be freely distributed and used under the terms of the GNU GPL. + */ + +CF_HDR + +#include "proto/volatile/volatile.h" + +CF_DEFINES + +#define VOLATILE_CFG ((struct volatile_config *) this_proto) + +CF_DECLS + +%type prefix_autocorrect + +CF_KEYWORDS(VOLATILE, SET, DEL, CLEAR, GATEWAY) +CF_KEYWORDS(MULTIPATH, WEIGHT) + +CF_GRAMMAR + +CF_ADDTO(proto, volatile_proto '}') + +volatile_proto_start: proto_start VOLATILE { + this_proto = proto_config_new(&proto_volatile, sizeof(struct volatile_config)); + } + ; + +volatile_proto: + volatile_proto_start proto_name '{' + | volatile_proto GATEWAY ipa ';' { + VOLATILE_CFG->gateway = $3; + VOLATILE_CFG->use_gateway = 1; + } + ; + +prefix_autocorrect: + ipa pxlen { + $$.addr = $1; + $$.len = $2; + ip_addr mask = ipa_mkmask($2); + $$.addr = ipa_and($$.addr, mask); + } + ; + + +CF_CLI_HELP(CONFIGURE VOLATILE, {set|del|clear}, [[Configure volatile routes]]) + +CF_CLI(CONFIGURE VOLATILE SET, optsym prefix_autocorrect, + /, + [[Add or set volatile routes]]) +{ volatile_configure_set(proto_get_named($4, &proto_volatile), $5); } ; + +CF_CLI(CONFIGURE VOLATILE DEL, optsym prefix_autocorrect, + /, + [[Delete volatile routes]]) +{ volatile_configure_del(proto_get_named($4, &proto_volatile), $5); } ; + +CF_CLI(CONFIGURE VOLATILE CLEAR, optsym, + , + [[Clear volatile routes]]) +{ volatile_configure_clear(proto_get_named($4, &proto_volatile)); } ; + +CF_CLI(SHOW VOLATILE, optsym, + , + [[Show volatile routes]]) +{ volatile_show(proto_get_named($3, &proto_volatile)); } ; + +CF_CODE + +CF_END diff --git a/proto/volatile/volatile.c b/proto/volatile/volatile.c new file mode 100644 index 0000000..80518b9 --- /dev/null +++ b/proto/volatile/volatile.c @@ -0,0 +1,195 @@ +/* + * BIRD -- Volatile Route Generator + * + * (c) 2013--2013 Thierry FOURNIER + * + * Can be freely distributed and used under the terms of the GNU GPL. + */ + +/** + * DOC: Volatile + * + * The volatile protocol take routes from the cli. These routes are annouced + * to the peers. These routes cannot be exists on the host or cannot correspond + * to any ip address on any interface. + * + * This type of announce is useful for services using transparent binding. + * The transparent binding is used tipically with proxy for proxifying HTTP + * connections. The user add route announcement and the destination is rerouted + * to the transparent proxy. + */ + +#include "nest/bird.h" +#include "nest/iface.h" +#include "nest/protocol.h" +#include "nest/route.h" +#include "nest/cli.h" +#include "conf/conf.h" +#include "lib/string.h" +#include "lib/alloca.h" + +#include "volatile.h" + +struct iface any = { + .name = "auto" +}; + +static void +volatile_install(struct volatile_proto *p, ip_addr net, unsigned int masklen) +{ + struct network *network; + struct rta route_attr_lookup; + struct rta *route_attr; + struct rte *route; + struct neighbor *neigh; + struct iface *iface; + + /* find neighbor for the gateway */ + if (p->cf->use_gateway) { + neigh = neigh_find(&p->p, &p->cf->gateway, NEF_STICKY); + if (!neigh || !neigh->iface) { + log(L_INFO "Cannot find neighbor for the gateway %I", p->cf->gateway); + return; + } + iface = neigh->iface; + } + + else + iface = &any; + + /* prepare route attrinutes lookup */ + bzero(&route_attr_lookup, sizeof(struct rta)); + route_attr_lookup.proto = &p->p; + route_attr_lookup.scope = SCOPE_UNIVERSE; + route_attr_lookup.cast = RTC_UNICAST; + route_attr_lookup.iface = iface; + if (p->cf->use_gateway) { + route_attr_lookup.gw = p->cf->gateway; + route_attr_lookup.source = RTS_STATIC; + route_attr_lookup.dest = RTD_ROUTER; + } + else { + route_attr_lookup.source = RTS_DEVICE; + route_attr_lookup.dest = RTD_DEVICE; + } + + /* lookup or add route attribute entry. This call never fail */ + route_attr = rta_lookup(&route_attr_lookup); + + /* get network entry into the table. This function never fail */ + network = net_get(p->p.table, net, masklen); + + /* get temporary route, and set attributes */ + route = rte_get_temp(route_attr); + route->net = network; + route->pflags = 0; + + /* update the route */ + rte_update(p->p.table, network, &p->p, &p->p, route); +} + +static void +volatile_remove(struct volatile_proto *p, ip_addr net, unsigned int masklen) +{ + struct network *network; + + /* lookup for network entry. if found remove it */ + network = net_find(p->p.table, net, masklen); + if (network) + rte_update(p->p.table, network, &p->p, &p->p, NULL); +} + +/* this function initialize configuration structs */ +static struct proto * +volatile_init(struct proto_config *C) +{ + struct volatile_config *c = (struct volatile_config *) C; + struct proto *P = proto_new(C, sizeof(struct volatile_proto)); + struct volatile_proto *p = (struct volatile_proto *) P; + + p->cf = c; + return P; +} + +struct protocol proto_volatile = { + name: "Volatile", + template: "volatile%d", + init: volatile_init, +}; + +/* this fucntion install new route */ +void +volatile_configure_set(struct proto *P, struct prefix net) +{ + struct volatile_proto *p = (struct volatile_proto *) P; + + volatile_install(p, net.addr, net.len); + cli_msg(0, ""); +} + +/* this fucntion delete known route */ +void +volatile_configure_del(struct proto *P, struct prefix net) +{ + struct volatile_proto *p = (struct volatile_proto *) P; + + volatile_remove(p, net.addr, net.len); + cli_msg(0, ""); +} + +/* this cli function delete all route with restarting protocol */ +void +volatile_configure_clear(struct proto *P) +{ + proto_cmd_restart(P, 0, 0); + cli_msg(0, ""); +} + +void +volatile_show(struct proto *P) +{ + struct volatile_proto *p = (struct volatile_proto *) P; + struct rte *route; + struct rta *attrs; + struct network *network; + + FIB_WALK(&p->p.table->fib, fn) { + network = (struct network *)fn; + for (route = network->routes; + route; + route = route->next) { + + if (route->attrs->proto != P) + continue; + + network = route->net; + attrs = route->attrs; + + if (!network) { + cli_msg(-1009, "???"); + continue; + } + + switch (attrs->dest) { + + case RTD_ROUTER: + cli_msg(-1009, "%I/%2d via %I dev %s", + network->n.prefix, network->n.pxlen, attrs->gw, + attrs->iface ? attrs->iface->name : "???"); + break; + + case RTD_DEVICE: + cli_msg(-1009, "%I/%2d dev auto", + network->n.prefix, network->n.pxlen); + break; + + default: + cli_msg(-1009, "%I/%2d ???", + network->n.prefix, network->n.pxlen); + break; + } + } + } FIB_WALK_END; + + cli_msg(0, ""); +} diff --git a/proto/volatile/volatile.h b/proto/volatile/volatile.h new file mode 100644 index 0000000..fd43873 --- /dev/null +++ b/proto/volatile/volatile.h @@ -0,0 +1,46 @@ +/* + * BIRD -- Volatile Route Generator + * + * (c) 2013--2013 Thierry FOURNIER + * + * Can be freely distributed and used under the terms of the GNU GPL. + */ + +#ifndef _BIRD_VOLATILE_H_ +#define _BIRD_VOLATILE_H_ + +struct volatile_config { + struct proto_config c; + int use_gateway; + ip_addr gateway; +}; + +struct volatile_proto { + struct proto p; + struct volatile_config *cf; /* Shortcut to volatile configuration */ +}; + +void volatile_init_config(struct volatile_config *); + +struct volatile_route { + node n; + struct volatile_route *chain; /* Next for the same neighbor */ + ip_addr net; /* Network we route */ + int masklen; /* Mask length */ + int dest; /* Destination type (RTD_*) */ + ip_addr via; /* Destination router */ + struct neighbor *neigh; + byte *if_name; /* Name for RTD_DEVICE routes */ + struct volatile_route *mp_next; /* Nexthops for RTD_MULTIPATH routes */ + int installed; /* Installed in master table */ +}; + +/* Dummy nodes (parts of multipath route) abuses masklen field for weight + and if_name field for a ptr to the master (RTD_MULTIPATH) node. */ + +void volatile_configure_set(struct proto *P, struct prefix net); +void volatile_configure_del(struct proto *P, struct prefix net); +void volatile_configure_clear(struct proto *P); +void volatile_show(struct proto *P); + +#endif