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

📄 kerneltun.cc

📁 Click is a modular router toolkit. To use it you ll need to know how to compile and install the sof
💻 CC
📖 第 1 页 / 共 2 页
字号:
	ifr.ifr_mtu = _mtu_out;	if (ioctl(s, SIOCSIFMTU, &ifr) != 0)	    errh->warning("could not set interface MTU: %s", strerror(errno));    }#endif#if defined(SIOCGIFFLAGS) && defined(SIOCSIFFLAGS)    if (ioctl(s, SIOCGIFFLAGS, &ifr) != 0) {	errh->error("SIOCGIFFLAGS failed: %s", strerror(errno));	goto out;    }    if (_tap)	ifr.ifr_flags = (addr ? ifr.ifr_flags & ~IFF_NOARP : ifr.ifr_flags | IFF_NOARP);    ifr.ifr_flags = (addr ? ifr.ifr_flags | IFF_UP | IFF_PROMISC : ifr.ifr_flags & ~IFF_UP & ~IFF_PROMISC);    if (ioctl(s, SIOCSIFFLAGS, &ifr) != 0) {	errh->error("SIOCSIFFLAGS failed: %s", strerror(errno));	goto out;    }#else# error "Lacking SIOCGIFFLAGS and/or SIOCSIFFLAGS"#endif out:    close(s);    return (errh->nerrors() == before ? 0 : -1);}intKernelTun::setup_tun(ErrorHandler *errh){// #if defined(__OpenBSD__)  && !defined(TUNSIFMODE)//     /* see OpenBSD bug: http://cvs.openbsd.org/cgi-bin/wwwgnats.pl/full/782 */// #define       TUNSIFMODE      _IOW('t', 88, int)// #endif#if defined(TUNSIFMODE) || defined(__FreeBSD__)    if (!_tap) {	int mode = IFF_BROADCAST;	if (ioctl(_fd, TUNSIFMODE, &mode) != 0)	    return errh->error("TUNSIFMODE failed: %s", strerror(errno));    }#endif#if defined(__OpenBSD__)    if (!_tap) {	struct tuninfo ti;	memset(&ti, 0, sizeof(struct tuninfo));	if (ioctl(_fd, TUNGIFINFO, &ti) != 0)	    return errh->error("TUNGIFINFO failed: %s", strerror(errno));	ti.flags &= IFF_BROADCAST;	if (ioctl(_fd, TUNSIFINFO, &ti) != 0)	    return errh->error("TUNSIFINFO failed: %s", strerror(errno));    }#endif#if defined(TUNSIFHEAD) || defined(__FreeBSD__)    // Each read/write prefixed with a 32-bit address family,    // just as in OpenBSD.    if (!_tap && _type == BSD_TUN) {	int yes = 1;	if (ioctl(_fd, TUNSIFHEAD, &yes) != 0)	    return errh->error("TUNSIFHEAD failed: %s", strerror(errno));    }#endif    // set addresses and MTU    if (updown(_near, _mask, errh) < 0)	return -1;    if (_gw) {	String cmd = "/sbin/route -n add default ";#if defined(__linux__)	cmd += "gw " + _gw.unparse();#else	cmd += _gw.unparse();#endif	if (system(cmd.c_str()) != 0)	    return errh->error("%s: %s", cmd.c_str(), strerror(errno));    }    // calculate maximum packet size needed to receive data from    // tun/tap.    if (_tap) {	if (_type == LINUX_UNIVERSAL)	    _mtu_in = _mtu_out + 18;	else if (_type == LINUX_ETHERTAP)	    _mtu_in = _mtu_out + 16;	else	    _mtu_in = _mtu_out + 14;    } else if (_type == LINUX_UNIVERSAL)	_mtu_in = _mtu_out + 4;    else if (_type == BSD_TUN)	_mtu_in = _mtu_out + 4;    else if (_type == BSD_TAP || _type == NETBSD_TAP || _type == NETBSD_TUN)	_mtu_in = _mtu_out;    else if (_type == OSX_TUN)	_mtu_in = _mtu_out + 4; // + 0?    else /* _type == LINUX_ETHERTAP */	_mtu_in = _mtu_out + 16;    return 0;}intKernelTun::initialize(ErrorHandler *errh){    if (alloc_tun(errh) < 0)	return -1;    if (setup_tun(errh) < 0)	return -1;    if (input_is_pull(0)) {	ScheduleInfo::join_scheduler(this, &_task, errh);	_signal = Notifier::upstream_empty_signal(this, 0, &_task);    }    if (_adjust_headroom) {	if (_tap && _type == LINUX_UNIVERSAL)	    _headroom += (4 - (_headroom + 2) % 4) % 4; // default 4/2 alignment	else	    _headroom += (4 - _headroom % 4) % 4; // default 4/0 alignment    }    add_select(_fd, SELECT_READ);    return 0;}voidKernelTun::cleanup(CleanupStage){    if (_fd >= 0) {	if (_type != LINUX_UNIVERSAL && _type != NETBSD_TAP)	    updown(0, ~0, ErrorHandler::default_handler());	close(_fd);	remove_select(_fd, SELECT_READ);    }}voidKernelTun::selected(int fd){    if (fd != _fd)	return;    WritablePacket *p = Packet::make(_headroom, 0, _mtu_in, 0);    if (!p) {	click_chatter("out of memory!");	return;    }    int cc = read(_fd, p->data(), _mtu_in);    if (cc > 0) {	p->take(_mtu_in - cc);	bool ok = false;	if (_tap) {	    if (_type == LINUX_UNIVERSAL)		// 2-byte padding, 2-byte Ethernet type, then Ethernet header		p->pull(4);	    else if (_type == LINUX_ETHERTAP)		// 2-byte padding, then Ethernet header		p->pull(2);	    ok = true;	} else if (_type == LINUX_UNIVERSAL) {	    // 2-byte padding followed by an Ethernet type	    uint16_t etype = *(uint16_t *)(p->data() + 2);	    p->pull(4);	    if (etype != htons(ETHERTYPE_IP) && etype != htons(ETHERTYPE_IP6))		checked_output_push(1, p->clone());	    else		ok = fake_pcap_force_ip(p, FAKE_DLT_RAW);	} else if (_type == BSD_TUN) {	    // 4-byte address family followed by IP header	    int af = ntohl(*(unsigned *)p->data());	    p->pull(4);	    if (af != AF_INET && af != AF_INET6) {		click_chatter("KernelTun(%s): don't know AF %d", _dev_name.c_str(), af);		checked_output_push(1, p->clone());	    } else		ok = fake_pcap_force_ip(p, FAKE_DLT_RAW);	} else if (_type == OSX_TUN || _type == NETBSD_TUN) {	    ok = fake_pcap_force_ip(p, FAKE_DLT_RAW);	} else { /* _type == LINUX_ETHERTAP */	    // 2-byte padding followed by a mostly-useless Ethernet header	    uint16_t etype = *(uint16_t *)(p->data() + 14);	    p->pull(16);	    if (etype != htons(ETHERTYPE_IP) && etype != htons(ETHERTYPE_IP6))		checked_output_push(1, p->clone());	    else		ok = fake_pcap_force_ip(p, FAKE_DLT_RAW);	}	if (ok) {	    p->timestamp_anno().set_now();	    output(0).push(p);	} else	    checked_output_push(1, p);    } else {	if (!_ignore_q_errs || !_printed_read_err || (errno != ENOBUFS)) {	    _printed_read_err = true;	    perror("KernelTun read");	}    }}boolKernelTun::run_task(Task *){    Packet *p = input(0).pull();    if (p)	push(0, p);    else if (!_signal)	return false;    _task.fast_reschedule();    return p != 0;}voidKernelTun::push(int, Packet *p){    const click_ip *iph = 0;    int check_length;    // sanity checks    if (_tap) {	if (p->length() < sizeof(click_ether)) {	    click_chatter("%s(%s): packet too small", class_name(), _dev_name.c_str());	    goto kill;	}	// use network length for MTU	check_length = p->length() - sizeof(click_ether);    } else {	iph = p->ip_header();	// check IP header	if (!p->has_network_header()	    || p->network_length() < (int) sizeof(click_ip)) {	    click_chatter("%s(%s): no network header", class_name(), _dev_name.c_str());	kill:	    p->kill();	    return;	} else if (iph->ip_v != 4 && iph->ip_v != 6) {	    click_chatter("%s(%s): unknown IP version %d", class_name(), _dev_name.c_str(), iph->ip_v);	    goto kill;	}	// strip link headers	p->change_headroom_and_length(p->headroom() + p->network_header_offset(), p->network_length());	check_length = p->length();    }    // check MTU    if (check_length > _mtu_out) {	click_chatter("%s(%s): packet larger than MTU (%d)", class_name(), _dev_name.c_str(), _mtu_out);	goto kill;    }    WritablePacket *q;    if (_tap) {	if (_type == LINUX_UNIVERSAL) {	    // 2-byte padding, 2-byte Ethernet type, then Ethernet header	    uint16_t ethertype = ((const click_ether *) p->data())->ether_type;	    if ((q = p->push(4)))		((uint16_t *) q->data())[1] = ethertype;	    p = q;	} else if (_type == LINUX_ETHERTAP) {	    // 2-byte padding, then Ethernet header	    p = p->push(2);	} else {	    /* existing packet is OK */;	}    } else if (_type == LINUX_UNIVERSAL) {	// 2-byte padding followed by an Ethernet type	uint32_t ethertype = (iph->ip_v == 4 ? htonl(ETHERTYPE_IP) : htonl(ETHERTYPE_IP6));	if ((q = p->push(4)))	    *(uint32_t *)(q->data()) = ethertype;	p = q;    } else if (_type == BSD_TUN) {	uint32_t af = (iph->ip_v == 4 ? htonl(AF_INET) : htonl(AF_INET6));	if ((q = p->push(4)))	    *(uint32_t *)(q->data()) = af;	p = q;    } else if (_type == LINUX_ETHERTAP) {	uint16_t ethertype = (iph->ip_v == 4 ? htons(ETHERTYPE_IP) : htons(ETHERTYPE_IP6));	if ((q = p->push(16))) {	    /* ethertap driver is very picky about what address we use	     * here. e.g. if we have the wrong address, linux might ignore	     * all the packets, or accept udp or icmp, but ignore tcp.	     * aaarrrgh, well this works. -ddc */	    memcpy(q->data(), "\x00\x00\xFE\xFD\x00\x00\x00\x00\xFE\xFD\x00\x00\x00\x00", 14);	    *(uint16_t *)(q->data() + 14) = ethertype;	}	p = q;    } else {	/* existing packet is OK */;    }    if (p) {	int w = write(_fd, p->data(), p->length());	if (w != (int) p->length() && (errno != ENOBUFS || !_ignore_q_errs || !_printed_write_err)) {	    _printed_write_err = true;	    click_chatter("%s(%s): write failed: %s", class_name(), _dev_name.c_str(), strerror(errno));	}	p->kill();    } else	click_chatter("%s(%s): out of memory", class_name(), _dev_name.c_str());}StringKernelTun::print_dev_name(Element *e, void *){    KernelTun *kt = (KernelTun *) e;    return kt->_dev_name;}voidKernelTun::add_handlers(){    if (input_is_pull(0))	add_task_handlers(&_task);    add_read_handler("dev_name", print_dev_name, 0);}CLICK_ENDDECLSELEMENT_REQUIRES(userlevel FakePcap)EXPORT_ELEMENT(KernelTun)

⌨️ 快捷键说明

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