📄 icmp6error.cc
字号:
/* * icmp6error.{cc,hh} -- element constructs ICMP6 error packets * Peilei Fan, Frederik Scholaert * * Copyright (c) 1999-2000 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 <clicknet/icmp6.h>#include <clicknet/ip6.h>#include <clicknet/ip.h>#include "icmp6error.hh"#include <click/ip6address.hh>#include <click/confparse.hh>#include <click/error.hh>#include <click/glue.hh>#include <click/packet_anno.hh>CLICK_DECLSICMP6Error::ICMP6Error(){ _code = _type = -1;}ICMP6Error::~ICMP6Error(){}intICMP6Error::configure(Vector<String> &conf, ErrorHandler *errh){ if (cp_va_kparse(conf, this, errh, "SRC", cpkP+cpkM, cpIP6Address, &_src_ip, "TYPE", cpkP+cpkM, cpInteger, &_type, "CODE", cpkP+cpkM, cpInteger, &_code, cpEnd) < 0) return -1; return 0;}boolICMP6Error::is_error_type(int type){ return (type == ICMP6_UNREACH || type == ICMP6_PKTTOOBIG || type == ICMP6_TIMXCEED || type == ICMP6_PARAMPROB);}boolICMP6Error::is_redirect_type(int type){ return (type == ICMP6_REDIRECT);}intICMP6Error::initialize(ErrorHandler *errh){ if (_type < 0 || _code < 0 || (_src_ip == IP6Address())) return errh->error("not configured -a"); if (!is_error_type(_type) && !is_redirect_type(_type)) return errh->error("ICMP6 type %d is not an error or redirect type", _type); return 0;}/* * Is an IP6 address unicast? * check if they are not multicast address (prefix is ff) * Can't detect directed broadcast here! */boolICMP6Error::unicast(const IP6Address &aa){ const unsigned char *a = aa.data(); if (a[0]== 0xff) return(0); return(1);}/* * Is a source IP6 address valid * */boolICMP6Error::valid_source(const IP6Address &aa){ //unsigned int a = aa.s_addr; //unsigned int ha = ntohl(a); //unsigned net = (ha >> 24) & 0xff; /* broadcast or multicast */ if(unicast(aa) == 0) return(0); /* local net or host: */// if(net == 0)// return(0); /* I don't know how to detect directed broadcast. */ /* ::1 */ if(aa == IP6Address("::1")) return(0); return(1);}/* * Does a packet contain a source route option? * currently, let's say no option for this */boolICMP6Error::has_route_opt(const click_ip6 *){ return(0);}Packet *ICMP6Error::simple_action(Packet *p){ WritablePacket *q = 0; const click_ip6 *ipp = p->ip6_header(); click_ip6 *nip; click_icmp6 *icp; unsigned xlen; if (!p->has_network_header()) goto out; /* These "don'ts" are from RFC1885 2.4.e: */ /* Don't reply to ICMP6 error messages. */ if(ipp->ip6_nxt == IP_PROTO_ICMP6) { icp = (click_icmp6 *) ((char *)ipp); if( is_error_type(icp->icmp6_type)) goto out; } /* Don't respond to packets with IPv6 broadcast destinations. */ if(unicast(IP6Address(ipp->ip6_dst)) == 0) goto out; /* Don't respond to e.g. Ethernet broadcasts or multicasts. */ if (p->packet_type_anno() == Packet::BROADCAST || p->packet_type_anno() == Packet::MULTICAST) goto out; /* send back as much of invoding packet as will fit without the ICMPv6 packet exceeding 576 octets , ICMP6 header is 8 octets*/ xlen = p->length(); if (xlen > 568) xlen = 568; if (_type != ICMP6_REDIRECT) q = Packet::make(sizeof(struct click_ip6) + sizeof(struct click_icmp6) + xlen); else q = Packet::make(sizeof(struct click_ip6) + sizeof(struct click_icmp6_redirect) + xlen); // guaranteed that packet data is aligned memset(q->data(), '\0', q->length()); //set ip6 header nip = (click_ip6 *) q->data(); nip->ip6_flow = 0; nip->ip6_v = 6; nip->ip6_plen = htons(q->length()-40); nip->ip6_nxt = IP_PROTO_ICMP6; /* next header */ nip->ip6_hlim = 0xff; //what hop limit shoud I set? nip->ip6_src = _src_ip; nip->ip6_dst = ipp->ip6_src; //set icmp6 Message icp = (click_icmp6 *) (nip + 1); icp->icmp6_type = _type; icp->icmp6_code = _code; if(_type == ICMP6_PKTTOOBIG && _code == 0){ /* Set the mtu value. */ ((click_icmp6_pkttoobig *)icp)->icmp6_mtusize = 1500; } if(_type == 4 && _code == 0){ /* Set the Parameter Problem pointer. */ ((click_icmp6_paramprob *) icp)->icmp6_pointer = ICMP_PARAMPROB_ANNO(p); //the pointer should be 4 bytes, however, there's no space in Anno structure //temporarily use the same as the ICMP parameter pointer, will be dealt later } if (_type == ICMP6_REDIRECT && _code == 0) { click_icmp6_redirect *icpr = (click_icmp6_redirect *) (nip + 1); icpr->icmp6_target = DST_IP6_ANNO(p); icpr->icmp6_dst = ipp->ip6_dst; memcpy((void *)(icpr + 1), p->data(), xlen); } else memcpy((void *)(icp + 1), p->data(), xlen); icp->icmp6_cksum = htons(in6_fast_cksum(&nip->ip6_src, &nip->ip6_dst, nip->ip6_plen, nip->ip6_nxt, 0, (unsigned char *)icp, nip->ip6_plen)); SET_DST_IP6_ANNO(q, IP6Address(nip->ip6_dst)); SET_FIX_IP_SRC_ANNO(q, 1); // fix_ip_src: shared flag with IPv4 q->set_ip6_header(nip, sizeof(click_ip6)); out: p->kill(); return(q);}CLICK_ENDDECLSEXPORT_ELEMENT(ICMP6Error)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -