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

📄 ip6ndsolicitor.cc

📁 Click is a modular router toolkit. To use it you ll need to know how to compile and install the sof
💻 CC
字号:
/* * ip6ndsolicitor.{cc,hh} -- Neighborhood Solicitation element * Peilei Fan * * Copyright (c) 1999-2001 Massachusetts Institute of Technology * * 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 "ip6ndsolicitor.hh"#include <clicknet/ether.h>#include <click/etheraddress.hh>#include <click/ip6address.hh>#include <click/confparse.hh>#include <click/straccum.hh>#include <click/bitvector.hh>#include <click/error.hh>#include <click/glue.hh>CLICK_DECLSIP6NDSolicitor::IP6NDSolicitor(): _expire_timer(expire_hook, this){    // input 0: IP6 packets    // input 1: ether/N.Advertisement responses    // output 0: ether/IP6 and ether/N.Solicitation queries  for (int i = 0; i < NMAP; i++)    _map[i] = 0;}IP6NDSolicitor::~IP6NDSolicitor(){}intIP6NDSolicitor::configure(Vector<String> &conf, ErrorHandler *errh){  return cp_va_kparse(conf, this, errh,		      "IP", cpkP+cpkM, cpIP6Address, &_my_ip6,		      "ETH", cpkP+cpkM, cpEthernetAddress, &_my_en,		      cpEnd);}intIP6NDSolicitor::initialize(ErrorHandler *){  _expire_timer.initialize(this);  _expire_timer.schedule_after_msec(EXPIRE_TIMEOUT_MS);  _arp_queries = 0;  _pkts_killed = 0;  return 0;}voidIP6NDSolicitor::cleanup(CleanupStage){  for (int i = 0; i < NMAP; i++) {    for (NDEntry *t = _map[i]; t; ) {      NDEntry *n = t->next;      if (t->p)	t->p->kill();      delete t;      t = n;    }    _map[i] = 0;  }}voidIP6NDSolicitor::take_state(Element *e, ErrorHandler *){  IP6NDSolicitor *arpq = (IP6NDSolicitor *)e->cast("IP6NDSolicitor");  if (!arpq || _my_ip6 != arpq->_my_ip6 || _my_en != arpq->_my_en)    return;  NDEntry *save[NMAP];  memcpy(save, _map, sizeof(NDEntry *) * NMAP);  memcpy(_map, arpq->_map, sizeof(NDEntry *) * NMAP);  memcpy(arpq->_map, save, sizeof(NDEntry *) * NMAP);}voidIP6NDSolicitor::expire_hook(Timer *, void *thunk){  IP6NDSolicitor *arpq = (IP6NDSolicitor *)thunk;  click_jiffies_t jiff = click_jiffies();  for (int i = 0; i < NMAP; i++) {    NDEntry *prev = 0;    while (1) {      NDEntry *e = (prev ? prev->next : arpq->_map[i]);      if (!e)	break;      if (e->ok) {	int gap = jiff - e->last_response_jiffies;	if (gap > 120*CLICK_HZ) {	  // delete entry from map	  if (prev) prev->next = e->next;	  else arpq->_map[i] = e->next;	  if (e->p)	    e->p->kill();	  delete e;	  continue;		// don't change prev	} else if (gap > 60*CLICK_HZ)	  e->polling = 1;      }      prev = e;    }  }  arpq->_expire_timer.schedule_after_msec(EXPIRE_TIMEOUT_MS);}voidIP6NDSolicitor::send_query_for(const u_char want_ip6[16]){  click_ether *e;  click_ip6 *ip6;  click_nd_sol *ea;  WritablePacket *q = Packet::make(sizeof(*e) + sizeof(*ip6) + sizeof(*ea));  if (q == 0) {    click_chatter("in ndsol: cannot make packet!");    assert(0);  }  memset(q->data(), '\0', q->length());  e = (click_ether *) q->data();  ip6=(click_ip6 *)(e+1);  ea = (click_nd_sol *) (ip6 + 1);  // set ethernet header  // dst add is a multicast add: first two octets : 0x3333,  // last four octets is the lst four octets of DST IP6Address  // which is the solicited-node multicast address: "ff02::1:ff00:0" +  // 24 bits from targest ip6 address  e->ether_dhost[0] = 0x33;  e->ether_dhost[1] = 0x33;  e->ether_dhost[2] = 0xff;  e->ether_dhost[3] = want_ip6[13];  e->ether_dhost[4] = want_ip6[14];  e->ether_dhost[5] = want_ip6[15];  memcpy(e->ether_shost, _my_en.data(), 6);  e->ether_type = htons(ETHERTYPE_IP6);  // set ip6 header  ip6->ip6_flow = 0;		// set flow to 0 (includes version)  ip6->ip6_v = 6;		// then set version to 6  ip6->ip6_plen=htons(sizeof(click_nd_sol));  ip6->ip6_nxt=0x3a; //i.e. protocal: icmp6 message  ip6->ip6_hlim=0xff; //indicate no router has processed it  ip6->ip6_src = _my_ip6;  unsigned char  dst2[16];  dst2[0]=0xff;  dst2[1]=0x02;  for (int i=2; i<11; i++) {    dst2[i]=0;  }  dst2[11]=1;  dst2[12]=0xff;  dst2[13]=want_ip6[13];  dst2[14]=want_ip6[14];  dst2[15]=want_ip6[15];  ip6->ip6_dst = IP6Address(dst2);  //set ICMP6 - Neighborhood Solicitation Message  ea->type = 0x87;  ea->code =0;  ea->reserved = htonl(0);  memcpy(ea->nd_tpa, want_ip6, 16);  ea->option_type = 0x1;  ea->option_length = 0x1;  memcpy(ea->nd_sha, _my_en.data(), 6);  ea->checksum = htons(in6_fast_cksum(&ip6->ip6_src, &ip6->ip6_dst, ip6->ip6_plen, ip6->ip6_nxt, 0, (unsigned char *)(ip6+1), htons(sizeof(click_nd_sol))));  _arp_queries++;  output(noutputs()-1).push(q);}/* * If the packet's IP6 address is in the table, add an ethernet header * and push it out. * Otherwise push out a query packet. * May save the packet in the NDEntry table for later sending. * May call p->kill(). */voidIP6NDSolicitor::handle_ip6(Packet *p){  IP6Address ipa = DST_IP6_ANNO(p);  int bucket = (ipa.data()[0] + ipa.data()[15]) % NMAP;  NDEntry *ae = _map[bucket];  while (ae && ae->ip6 != ipa)    ae = ae->next;  if (ae) {    if (ae->polling) {      send_query_for(ae->ip6.data());      ae->polling = 0;    }    //find the match IP address, send to output 0    if (ae->ok) {      Packet *q = p->push(sizeof(click_ether));      click_ether *e = (click_ether *)q->data();      memcpy(e->ether_shost, _my_en.data(), 6);      memcpy(e->ether_dhost, ae->en.data(), 6);      e->ether_type = htons(ETHERTYPE_IP6);      output(0).push(q);    } else {      if (ae->p) {        ae->p->kill();	_pkts_killed++;      }      ae->p = p;      send_query_for(DST_IP6_ANNO(p).data());    }  } else {    NDEntry *ae = new NDEntry;    ae->ip6 = ipa;    ae->ok = ae->polling = 0;    ae->p = p;    ae->next = _map[bucket];    _map[bucket] = ae;    send_query_for(DST_IP6_ANNO(p).data());  }}/* * Got an Neighborhood Advertisement (response to N. Solicitation Message) * Update our NDEntry table. * If there was a packet waiting to be sent, return it. */voidIP6NDSolicitor::handle_response(Packet *p){  if (p->length() < sizeof(click_ether) + sizeof(click_ip6) + sizeof(click_nd_sol))    return;  click_ether *ethh = (click_ether *) p->data();  click_ip6 *ip6h = (click_ip6 *)(ethh+1);  click_nd_adv * eah = (click_nd_adv*)(ip6h+1);  IP6Address ipa = IP6Address(eah->nd_tpa);  EtherAddress ena = EtherAddress(eah->nd_tha);    if (ntohs(ethh->ether_type) == ETHERTYPE_IP6	&& eah->type == ND_ADV) {//        && !ena.is_group()) {     int bucket = (ipa.data()[0] + ipa.data()[15]) % NMAP;      NDEntry *ae = _map[bucket];      while (ae && ae->ip6 != ipa)        ae = ae->next;      if (!ae)        return;      if (ae->ok && ae->en != ena)        click_chatter("IP6NDSolicitor overwriting an entry");      ae->en = ena;      ae->ok = 1;      ae->polling = 0;      ae->last_response_jiffies = click_jiffies();      Packet *cached_packet = ae->p;      ae->p = 0;      if (cached_packet){        handle_ip6(cached_packet);}    }}voidIP6NDSolicitor::push(int port, Packet *p){   if (port == 0){     handle_ip6(p); }  else {    handle_response(p);    p->kill();  }}StringIP6NDSolicitor::read_table(Element *e, void *){    IP6NDSolicitor *q = (IP6NDSolicitor *)e;    StringAccum sa;    for (int i = 0; i < NMAP; i++)	for (NDEntry *e = q->_map[i]; e; e = e->next)	    sa << e->ip6 << ' ' << (e->ok ? 1 : 0) << ' ' << e->en << '\n';    return sa.take_string();}static StringIP6NDSolicitor_read_stats(Element *e, void *){  IP6NDSolicitor *q = (IP6NDSolicitor *)e;  return    String(q->_pkts_killed) + " packets killed\n" +    String(q->_arp_queries) + " ND Solicitation Message sent\n";}voidIP6NDSolicitor::add_handlers(){  add_read_handler("table", read_table, (void *)0);  add_read_handler("stats", IP6NDSolicitor_read_stats, (void *)0);}CLICK_ENDDECLSELEMENT_REQUIRES(ip6)EXPORT_ELEMENT(IP6NDSolicitor)

⌨️ 快捷键说明

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