00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "src/common/shared.hpp"
00012 #include "src/memory/memset.hpp"
00013 #include "src/memory/align.hpp"
00014 #include "src/memory/heap.hpp"
00015 #include "src/net/net.hpp"
00016 #include "src/net/arp.hpp"
00017 #include "src/net/ip.hpp"
00018 #include "src/arch/x86/rtc.hpp"
00019 #include "src/thread/timer.hpp"
00020 #include "src/collection/option.hpp"
00021 #include "src/collection/avlmap.hpp"
00022 #include "src/collection/list.hpp"
00023 #include "src/collection/tuple.hpp"
00024
00028 #define DUMP_IP_PACKET_INFO 1
00029
00032 namespace Net {
00033 namespace IP {
00034
00035 struct ip_address my_ip_address() {
00036 return ip_address(0x03000006);
00037 }
00038
00039 struct netmask_t my_netmask() {
00040 return netmask_t(0xffffff00);
00041 }
00042
00043 using namespace Collection;
00044
00045 int ip_outbound_cmp(struct Tuple2<struct ip_address, struct netbuf* > a, struct Tuple2<struct ip_address, struct netbuf*> b) {
00046 if (a._1.ip > b._1.ip)
00047 return 1;
00048 if (a._1.ip < b._1.ip)
00049 return -1;
00050
00051 return pointer_cmp<struct netbuf> (a._2, b._2);
00052 }
00053
00054 struct AvlTree<struct Tuple2<struct ip_address, struct netbuf*>, ip_outbound_cmp> *ip_outbound;
00055 struct IPC::Lock::lock_t ip_outbound_lock(const_cast<char*>("ip_outbound"));
00056
00057 void init() {
00058 ip_outbound= new AvlTree<struct Tuple2<struct ip_address, struct netbuf*>, ip_outbound_cmp>();
00059 }
00060
00061
00062 void ip_onNewArpEntry(struct Net::Arp::arp_entry arp) {
00063 ip_outbound_lock.lock();
00064 struct Option<struct Tuple2<struct ip_address,struct netbuf*> > opt;
00065 struct Tuple2<struct ip_address, struct netbuf*> templ = Tuple2<struct ip_address, struct netbuf*>(arp.ip_addr, null);
00066
00067
00068 println(opt);
00069 while ( (opt = ip_outbound->find(templ)).isNone() == false) {
00070 struct Tuple2<struct ip_address, struct netbuf*> v= opt.get();
00071 ip_outbound->remove(v);
00072 println(v);
00073 }
00074 ip_outbound_lock.ulock();
00075 }
00076
00077 void ip_transmit(struct netif *nif, struct ip_address ip_addr, uint8 tos, uint8 prot, struct pbuf *pb) {
00078 assert(sizeof(struct ip_header)==20);
00079 testif(pb);
00080 if (pb->ip_data_off < sizeof(struct ip_header)) {
00081 complain("no space for ip header in packet buffer");
00082 return ;
00083 }
00084 struct ip_header *ip;
00085 pb->ip_off=pb->ip_data_off - sizeof(struct ip_header);
00086 ip=reinterpret_cast<struct ip_header*>(&pb->data[pb->ip_off]);
00087 ip->version=4;
00088 ip->hdr_len=sizeof(struct ip_header)/sizeof(uint32);
00089 ip->tos=tos;
00090 ip->len=htons(pb->end - pb->ip_off);
00091 static uint16 ip_iden=0;
00092 ip->iden= htons(ip_iden++);
00093 ip->flags=0;
00094 ip->offset=htons(0);
00095 ip->ttl=32;
00096 ip->prot=prot;
00097 ip->checksum=0;
00098 ip->source_ip=nif->ip_addr;
00099 ip->target_ip=ip_addr;
00100
00101 ip->checksum= count_checksum16(reinterpret_cast<uint16*>(ip), sizeof(struct ip_header)/sizeof(uint16));
00102 struct Option<struct ethernet_address> eth_addr = Net::Arp::arp_get_ether(ip_addr);
00103 if (eth_addr.isNone()) {
00104 ip_outbound_lock.lock();
00105 Thread::Timer::avltree_insert_with_timer(DEF_SECOND*30,
00106 ip_outbound,
00107 Tuple2<struct ip_address, struct netbuf*>(
00108 ip_addr,
00109 new netbuf(pb->end - pb->ip_off, &pb->data[pb->ip_off], null, nif)
00110 )
00111 );
00112 ip_outbound_lock.ulock();
00113 } else {
00115 eth_transmit(nif, eth_addr.get(), 0x0800, new netbuf(pb->end-pb->ip_off, &pb->data[pb->ip_off], null, nif));
00116 }
00117 }
00118 }
00119 }
00120
00121
00122