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

📄 ftpportmapper.cc

📁 COPE the first practical network coding scheme which is developped on click
💻 CC
字号:
/* * ftpportmapper.{cc,hh} -- IPMapper for FTP PORT commands * Eddie Kohler * * Copyright (c) 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 "ftpportmapper.hh"#include <clicknet/ip.h>#include <clicknet/tcp.h>#include <click/router.hh>#include <click/elemfilter.hh>#include <click/confparse.hh>#include <click/error.hh>CLICK_DECLSFTPPortMapper::FTPPortMapper()  : Element(1, 1), _pattern(0){}FTPPortMapper::~FTPPortMapper(){}intFTPPortMapper::configure(Vector<String> &conf, ErrorHandler *errh){  if (conf.size() != 3)    return errh->error("wrong number of arguments; expected `FTPPortMapper(element, pattern)'");  // get control packet rewriter  Element *e = cp_element(conf[0], this, errh);  if (!e)    return -1;  _control_rewriter = (TCPRewriter *)e->cast("TCPRewriter");  if (!_control_rewriter)    return errh->error("first argument must be a TCPRewriter-like element");  // get data packet rewriter  e = cp_element(conf[1], this, errh);  if (!e)    return -1;  _data_rewriter = (IPRw *)e->cast("IPRw");  if (!_data_rewriter)    return errh->error("second argument must be an IPRewriter-like element");  _pattern = 0;  if (IPRw::Pattern::parse_with_ports(conf[2], &_pattern, &_forward_port,				      &_reverse_port, this, errh) < 0)    return -1;  _pattern->use();  if (_data_rewriter->notify_pattern(_pattern, errh) < 0)    return -1;    if (_forward_port >= _data_rewriter->noutputs()      || _reverse_port >= _data_rewriter->noutputs())    return errh->error("port out of range for `%s'", _data_rewriter->declaration().cc());  else    return 0;}intFTPPortMapper::initialize(ErrorHandler *errh){  // make sure that _control_rewriter is downstream  CastElementFilter filter("TCPRewriter");  Vector<Element *> elts;  router()->downstream_elements(this, 0, &filter, elts);  filter.filter(elts);  for (int i = 0; i < elts.size(); i++)    if (elts[i] == _control_rewriter)      goto found_control_rewriter;  errh->warning("control packet rewriter `%s' is not downstream", _control_rewriter->declaration().cc()); found_control_rewriter:  return 0;}voidFTPPortMapper::cleanup(CleanupStage){  if (_pattern)    _pattern->unuse();}Packet *FTPPortMapper::simple_action(Packet *p){  const click_ip *iph = p->ip_header();  assert(iph->ip_p == IP_PROTO_TCP);  const click_tcp *tcph = p->tcp_header();  unsigned data_offset = p->transport_header_offset() + (tcph->th_off<<2);  const unsigned char *data = p->data() + data_offset;  unsigned len = p->length() - data_offset;  if (len < 4      || (data[0] != 'P' && data[0] != 'p')      || (data[1] != 'O' && data[1] != 'o')      || (data[2] != 'R' && data[2] != 'r')      || (data[3] != 'T' && data[3] != 't')      || data[4] != ' ')    return p;    // parse the PORT command  unsigned pos = 5;  while (pos < len && data[pos] == ' ')    pos++;  unsigned port_arg_offset = pos;  // followed by 6 decimal numbers separated by commas  unsigned nums[6];  nums[0] = nums[1] = nums[2] = nums[3] = nums[4] = nums[5] = 0;  int which_num = 0;  while (pos < len && which_num < 6) {    if (data[pos] >= '0' && data[pos] <= '9')      nums[which_num] = (nums[which_num] * 10) + data[pos] - '0';    else if (data[pos] == ',')      which_num++;    else      break;    pos++;  }  // check that the command was complete and the numbers are ok  if (which_num != 5 || pos >= len || (data[pos] != '\r' && data[pos] != '\n'))    return p;  for (int i = 0; i < 6; i++)    if (nums[i] >= 256)      return p;  // OK; create the IP address and port number  IPAddress src_data_addr(htonl((nums[0]<<24) | (nums[1]<<16) | (nums[2]<<8) | nums[3]));  unsigned src_data_port = htons((nums[4]<<8) | nums[5]);  // add mapping from specified port to destination  unsigned dst_data_port = htons(ntohs(tcph->th_dport) - 1);  IPFlowID flow(src_data_addr, src_data_port,		IPAddress(iph->ip_dst), dst_data_port);  // check for existing mapping  IPRw::Mapping *forward = _data_rewriter->get_mapping(IP_PROTO_TCP, flow);  if (!forward) {    // create new mapping    forward = _data_rewriter->apply_pattern(_pattern, IP_PROTO_TCP, flow,					    _forward_port, _reverse_port);    if (!forward)      return p;  }  // rewrite PORT command to reflect mapping  IPFlowID new_flow = forward->flow_id();  unsigned new_saddr = ntohl(new_flow.saddr().addr());  unsigned new_sport = ntohs(new_flow.sport());  char buf[30];  unsigned buflen;  buflen = sprintf(buf, "%d,%d,%d,%d,%d,%d", (new_saddr>>24)&255, (new_saddr>>16)&255,	  (new_saddr>>8)&255, new_saddr&255, (new_sport>>8)&255, new_sport&255);  //click_chatter("%s", buf);  WritablePacket *wp;  unsigned port_arg_len = pos - port_arg_offset;  if (port_arg_len < buflen) {    wp = p->put(buflen - port_arg_len);  } else {    wp = p->uniqueify();    wp->take(port_arg_len - buflen);  }  memmove(wp->data() + data_offset + port_arg_offset + buflen,	  wp->data() + data_offset + port_arg_offset + port_arg_len,	  len - pos);  memcpy(wp->data() + data_offset + port_arg_offset,	 buf,	 buflen);  // set IP length field, incrementally update IP checksum according to RFC1624  // new_sum = ~(~old_sum + ~old_halfword + new_halfword)  click_ip *wp_iph = wp->ip_header();  unsigned short old_ip_hw = ((unsigned short *)wp_iph)[1];  wp_iph->ip_len = htons(wp->length() - wp->ip_header_offset());  unsigned short new_ip_hw = ((unsigned short *)wp_iph)[1];  unsigned ip_sum =    (~wp_iph->ip_sum & 0xFFFF) + (~old_ip_hw & 0xFFFF) + new_ip_hw;  while (ip_sum >> 16)		// XXX necessary?    ip_sum = (ip_sum & 0xFFFF) + (ip_sum >> 16);  wp_iph->ip_sum = ~ip_sum;  // set TCP checksum  // XXX should check old TCP checksum first!!!  click_tcp *wp_tcph = wp->tcp_header();  // update sequence numbers in old mapping  IPFlowID p_flow(p);  if (TCPRewriter::TCPMapping *p_mapping = _control_rewriter->get_mapping(IP_PROTO_TCP, p_flow)) {    tcp_seq_t interesting_seqno = ntohl(wp_tcph->th_seq) + len;    p_mapping->update_seqno_delta(interesting_seqno, buflen - port_arg_len);  } else    click_chatter("%{element}: control packet with no mapping", this);  wp_tcph->th_sum = 0;  unsigned wp_tcp_len = wp->length() - wp->transport_header_offset();  unsigned csum = click_in_cksum((unsigned char *)wp_tcph, wp_tcp_len);  wp_tcph->th_sum = click_in_cksum_pseudohdr(csum, wp_iph, wp_tcp_len);    return wp;}CLICK_ENDDECLSELEMENT_REQUIRES(TCPRewriter)EXPORT_ELEMENT(FTPPortMapper)

⌨️ 快捷键说明

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