⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ipsecroutetable.cc

📁 Click is a modular router toolkit. To use it you ll need to know how to compile and install the sof
💻 CC
字号:
// -*- c-basic-offset: 4 -*-/* * ipsecroutetable.{cc,hh} -- looks up next-hop address in route table and includes support for IPsec ESP tunnels * between a pair of gateways (check push and cp_ipsec_route) * Dimitris Syrivelis * * Copyright (c) 2006 University of Thessaly, Hellas * * This is an extended version of iproutetable * iproutetable.{cc,hh} -- looks up next-hop address in route table * Benjie Chen, Eddie Kohler * * Copyright (c) 2001 Massachusetts Institute of Technology * Copyright (c) 2002 International Computer Science Institute * * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, subject to the conditions listed in the Click LICENSE * file. These conditions include: you must preserve this copyright * notice, and you cannot mention the copyright holders in advertising * related to the Software without their permission.  The Software is * provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This notice is a * summary of the Click LICENSE file; the license in that file is * legally binding. */#include <click/config.h>#include <click/ipaddress.hh>#include <click/confparse.hh>#include <click/error.hh>#include <click/glue.hh>#include <click/straccum.hh>#include <click/router.hh>#include <click/packet_anno.hh>#include "ipsecroutetable.hh"#include "esp.hh"CLICK_DECLS//changed to support IPsec extensionsboolcp_ipsec_route(String s, IPsecRoute *r_store, bool remove_route, Element *context){    IPsecRoute r;    //Data to initialize the SADataTuple    unsigned int replay;    uint8_t  oowin;    SADataTuple * sa_data;    if (!cp_ip_prefix(cp_shift_spacevec(s), &r.addr, &r.mask, true, context))	return false;    r.addr &= r.mask;    String word = cp_shift_spacevec(s);    if (word == "-")	/* null gateway; do nothing */;    else if (cp_ip_address(word, &r.gw, context))	/* do nothing */;    else	goto two_words;    word = cp_shift_spacevec(s);  two_words:    if (cp_integer(word, &r.port) || (!word && remove_route))	//Ipsec extensions parsing	word = cp_shift_spacevec(s);    if (!word) {	//no further arguments found so no ipsec extensions need to be added for this route	r.spi = SPI(0);	r.sa_data = NULL;	//store routing table        *r_store = r;	return true;    }    Vector<String> words;    words.push_back(word);    cp_spacevec(s, words);    String enc_key, auth_key;    if (cp_va_kparse(words, context, ErrorHandler::default_handler(),		     "SPI", cpkP+cpkM, cpUnsigned, &r.spi,		     "ENCRYPT_KEY", cpkP+cpkM, cpString, &enc_key,		     "AUTH_KEY", cpkP+cpkM, cpString, &auth_key,		     "REPLAY", cpkP+cpkM, cpUnsigned, &replay,		     "OOSIZE", cpkP+cpkM, cpUnsigned, &oowin,		     cpEnd) < 0)	return false;    if (enc_key.length() != 16 || auth_key.length() != 16) {	click_chatter("key has bad length");	return false;    }    // Create new Security Association Table entry    sa_data = new SADataTuple(enc_key.data(), auth_key.data(), replay, oowin);    ((IPsecRouteTable*)context)->_sa_table.insert(SPI(r.spi),*sa_data);    //Set Tuple reference in the Routing entry    r.sa_data = sa_data;    //store routing table    *r_store = r;    return true;}//changed to support ipsec extensionsStringAccum&IPsecRoute::unparse(StringAccum& sa, bool tabs) const{    int l = sa.length();    char tab = (tabs ? '\t' : ' ');    sa << addr.unparse_with_mask(mask) << tab;    if (sa.length() < l + 17 && tabs)	sa << '\t';    l = sa.length();    if (gw)	sa << gw << tab;    else	sa << '-' << tab;    if (sa.length() < l + 9 && tabs)	sa << '\t';    if (!real())	sa << "-1";    else	sa << port;    if(spi != 0) {	sa << "  |TUNNELED CONNECTION| \n|SPI| |ENC KEY| |AUTH KEY| ||\n";	sa << " |" <<spi<<"|";	sa << sa_data->unparse_entries().c_str() <<"\n";    }    return sa;}StringIPsecRoute::unparse() const{    StringAccum sa;    sa << *this;    return sa.take_string();}void *IPsecRouteTable::cast(const char *name){    if (strcmp(name, "IPsecRouteTable") == 0)	return (void *)this;    else	return Element::cast(name);}intIPsecRouteTable::configure(Vector<String> &conf, ErrorHandler *errh){    int before = errh->nerrors();    IPsecRoute r;    for (int i = 0; i < conf.size(); i++) {	if (cp_ipsec_route(conf[i], &r, false, this)	    && r.port >= 0 && r.port < noutputs())	    (void) add_route(r, false, 0, errh);	else	    errh->error("argument %d should be 'ADDR/MASK [GATEWAY] OUTPUT'", i+1);    }    return (errh->nerrors() != before ? -1 : 0);}intIPsecRouteTable::add_route(const IPsecRoute&, bool, IPsecRoute*, ErrorHandler *errh){    // by default, cannot add routes    return errh->error("cannot add routes to this routing table");}intIPsecRouteTable::remove_route(const IPsecRoute&, IPsecRoute*, ErrorHandler *errh){    // by default, cannot remove routes    return errh->error("cannot delete routes from this routing table");}intIPsecRouteTable::lookup_route(IPAddress, IPAddress &, unsigned int&, SADataTuple*&) const{    return -1;			// by default, route lookups fail}StringIPsecRouteTable::dump_routes(){    return String();}voidIPsecRouteTable::push(int, Packet *p){    IPAddress gw;    uint32_t spi;    SADataTuple * sa_data;    const click_ip *ip = reinterpret_cast< const click_ip *>(p->data());    int port = lookup_route(p->dst_ip_anno(), gw, spi, sa_data);    if (port >= 0) {	switch(port) {	  case 1: {	   //This packet should be sent over a tunneled connection	   //so set proper annotations with references to Security Data to be used by IPsec modules           if((spi == 0) || (sa_data == NULL)) {	       click_chatter("No Ipsec tunnel for %s. Wrong tunnel setup", p->dst_ip_anno().unparse().c_str());	   }	   SET_IPSEC_SPI_ANNO(p,(uint32_t)spi);	   //ISSUE: This is 32-bit architecture specific passing a pointer to next module through annotations!!	   SET_IPSEC_SA_DATA_REFERENCE_ANNO(p,(uint32_t)sa_data);	   break;	 }	 case 0: {	    //Is this packet an ipsec ESP packet? What if one just needs to communicate with a server            //that runs on this router?	    if(ip->ip_p != 50) {	      /*This not an IPSEC packet and it should be delivered to the host's linux network stack                In a typical setup one would send anything that is directed to port 2 to Linux */                port = 2;            }            // This is an ipsec packet and belongs to a tunneled connection	    // so we set the proper annotation with reference to Security Data Table to be used by IPsec modules            // Careful this enhancement is 32-bit architecture specific!!            struct esp_new * esp =(struct esp_new *)(p->data()+sizeof(click_ip));            sa_data = _sa_table.lookup(SPI(ntohl(esp->esp_spi)));	    if(sa_data == NULL) {		click_chatter("Invalid SPI %d, Dropping packet",ntohl(esp->esp_spi));	p->kill();                return;           }	   SET_IPSEC_SA_DATA_REFERENCE_ANNO(p,(uint32_t)sa_data);	   break;	 }	}; //end of switch	assert(port < noutputs());	if (gw)	    p->set_dst_ip_anno(gw);	output(port).push(p);    } else {	static int complained = 0;	if (++complained <= 5)	    click_chatter("IPsecRouteTable: no route for %s", p->dst_ip_anno().unparse().c_str());	p->kill();    }}intIPsecRouteTable::run_command(int command, const String &str, Vector<IPsecRoute> * old_routes, ErrorHandler *errh){    IPsecRoute route, old_route;    if (!cp_ipsec_route(str, &route, command == CMD_REMOVE, this)	|| route.port < (command == CMD_REMOVE ? -1 : 0)	|| route.port >= noutputs())	return errh->error("expected 'ADDR/MASK [GATEWAY%s'", (command == CMD_REMOVE ? " OUTPUT]" : "] OUTPUT"));    int r, before = errh->nerrors();    if (command == CMD_ADD)	r = add_route(route, false, &old_route, errh);    else if (command == CMD_SET)	r = add_route(route, true, &old_route, errh);    else	r = remove_route(route, &old_route, errh);    // save old route if in a transaction    if (r >= 0 && old_routes) {	if (old_route.port < 0) { // must come from add_route	    old_route = route;	    old_route.extra = CMD_ADD;	} else	    old_route.extra = command;	old_routes->push_back(old_route);    }    // report common errors    if (r == -EEXIST && errh->nerrors() == before)	errh->error("conflict with existing route '%s'", old_route.unparse().c_str());    if (r == -ENOENT && errh->nerrors() == before)	errh->error("route '%s' not found", route.unparse().c_str());    return r;}intIPsecRouteTable::add_route_handler(const String &conf, Element *e, void *thunk, ErrorHandler *errh){    IPsecRouteTable *table = static_cast<IPsecRouteTable *>(e);    return table->run_command((thunk ? CMD_SET : CMD_ADD), conf, 0, errh);}intIPsecRouteTable::remove_route_handler(const String &conf, Element *e, void *, ErrorHandler *errh){    IPsecRouteTable *table = static_cast<IPsecRouteTable *>(e);    return table->run_command(CMD_REMOVE, conf, 0, errh);}intIPsecRouteTable::ctrl_handler(const String &conf_in, Element *e, void *, ErrorHandler *errh){    IPsecRouteTable *table = static_cast<IPsecRouteTable *>(e);    String conf = cp_uncomment(conf_in);    const char* s = conf.begin(), *end = conf.end();    Vector<IPsecRoute> old_routes;    int r = 0;    while (s < end) {	const char* nl = find(s, end, '\n');	String line = conf.substring(s, nl);	String first_word = cp_shift_spacevec(line);	int command;	if (first_word == "add")	    command = CMD_ADD;	else if (first_word == "remove")	    command = CMD_REMOVE;	else if (first_word == "set")	    command = CMD_SET;	else if (!first_word)	    continue;	else {	    r = errh->error("bad command '%#s'", first_word.c_str());	    goto rollback;	}	if ((r = table->run_command(command, line, &old_routes, errh)) < 0)	    goto rollback;	s = nl + 1;    }    return 0;  rollback:    while (old_routes.size()) {	const IPsecRoute& rt = old_routes.back();	if (rt.extra == CMD_REMOVE)	    table->add_route(rt, false, 0, errh);	else if (rt.extra == CMD_ADD)	    table->remove_route(rt, 0, errh);	else	    table->add_route(rt, true, 0, errh);	old_routes.pop_back();    }    return r;}StringIPsecRouteTable::table_handler(Element *e, void *){    IPsecRouteTable *r = static_cast<IPsecRouteTable*>(e);    return r->dump_routes();}intIPsecRouteTable::lookup_handler(int, String& s, Element* e, const Handler*, ErrorHandler* errh){    IPsecRouteTable *table = static_cast<IPsecRouteTable*>(e);    IPAddress a;    if (cp_ip_address(cp_uncomment(s), &a, table)) {	IPAddress gw;	uint32_t spi;	SADataTuple * sa_data;	int port = table->lookup_route(a, gw,spi,sa_data);	if (gw)	    s = String(port) + " " + gw.unparse();	else	    s = String(port);	return 0;    } else	return errh->error("expected IP address, not '%s'", s.c_str());}voidIPsecRouteTable::add_handlers(){    add_write_handler("add", add_route_handler, 0);    add_write_handler("set", add_route_handler, (void*) 1);    add_write_handler("remove", remove_route_handler, 0);    add_write_handler("ctrl", ctrl_handler, 0);    add_read_handler("table", table_handler, 0);    set_handler("lookup", Handler::OP_READ | Handler::READ_PARAM, lookup_handler);}CLICK_ENDDECLSELEMENT_PROVIDES(IPsecRouteTable)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -