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/collection/tuple.hpp"
00017 #include "src/collection/option.hpp"
00018 #include "src/net/arp.hpp"
00019 #include "src/net/ip.hpp"
00020 #include "src/net/icmp.hpp"
00021 #include "src/net/3c556.hpp"
00022 #include "src/arch/x86/rtc.hpp"
00023 #include "src/thread/timer.hpp"
00024 #include "src/collection/avlmap.hpp"
00025 #include "src/collection/list.hpp"
00026
00030 #define DUMP_IP_PACKET_INFO 1
00031 #define DEBUG_IP_CHECKSUM_ALERT 0
00032 #define DEBUG_IP_FRAGMENTED_ALERT 0
00033 #define DEBUG_IP_PROT_ALERT 0
00034
00038
00039 namespace Net {
00040 namespace IP {
00041
00042 struct ip_address my_ip_address() {
00043 return ip_address(0x03000006);
00044 }
00045
00046 struct netmask_t my_netmask() {
00047 return netmask_t(0xffffff00);
00048 }
00049
00050 using namespace Collection;
00051
00053 void onIpReception(struct netbuf *nb) {
00054
00055 struct ip_header *iph;
00056 iph= reinterpret_cast<struct ip_header*>(&nb->data[14]);
00057 if (count_checksum_iph(iph) != iph->checksum) {
00058 #if DEBUG_IP_CHECKSUM_ALERT
00059 println(*nb);
00060 println(*iph);
00061 complain("incorrect checksum: datagram dropped");
00062 #endif
00063 } else {
00064 if ((iph->flags_fo & 2) || ((0x1FFF&ntohs(iph->flags_fo)) != 0)) {
00065 #if DEBUG_IP_FRAGMENTED_ALERT
00066 println(*nb);
00067 println(*iph);
00068 complain("fragmented datagram dropped");
00069 #endif
00070 } else {
00071 switch (iph->prot) {
00072 case 0x01 : Net::ICMP::processDatagram(nb);
00073 break;
00074 default:
00075 #if DEBUG_IP_PROT_ALERT
00076 print(*nb);
00077 print(*iph);
00078 complain("protocol unavaillable");
00079 #endif
00080
00081 break;
00082 }
00083 }
00084 }
00085 netbuf_free(nb);
00086 }
00087
00088 int ip_outbound_cmp(struct Tuple2<struct ip_address, struct netbuf* > a, struct Tuple2<struct ip_address, struct netbuf*> b) {
00089 if (a._1.ip > b._1.ip)
00090 return 1;
00091 if (a._1.ip < b._1.ip)
00092 return -1;
00093
00094 return pointer_cmp<struct netbuf> (a._2, b._2);
00095 }
00096
00097 int ip_outbound_cmp_by_first(struct Tuple2<struct ip_address, struct netbuf* > a, struct Tuple2<struct ip_address, struct netbuf*> b) {
00098 return generic_cmp<uint32>(a._1.ip, b._1.ip);
00099 }
00100
00101 struct AvlTree<struct Tuple2<struct ip_address, struct netbuf*>, ip_outbound_cmp> *ip_outbound;
00102 struct IPC::Lock::lock_t ip_outbound_lock(const_cast<char*>("ip_outbound"));
00103
00104 void init() {
00105 ip_outbound= new AvlTree<struct Tuple2<struct ip_address, struct netbuf*>, ip_outbound_cmp>();
00106 }
00107
00108
00109 void ip_onNewArpEntry(struct Net::Arp::arp_entry arp) {
00110 ip_outbound_lock.lock();
00111 struct Option<struct Tuple2<struct ip_address,struct netbuf*> > opt;
00112 struct Tuple2<struct ip_address, struct netbuf*> templ = Tuple2<struct ip_address, struct netbuf*>(arp.ip_addr, null);
00113
00114 while ( (opt = ip_outbound->findcmp< ip_outbound_cmp_by_first >(templ)).isNone() == false) {
00115 struct Tuple2<struct ip_address, struct netbuf*> v= opt.get();
00116 struct netbuf *nb = v._2;
00117 ip_outbound->remove(v);
00119 eth_transmit(nb->nif, arp.eth_addr, 0x0800, nb);
00120 }
00121 ip_outbound_lock.ulock();
00122 }
00123
00124 uint16 count_checksum_iph(struct ip_header *iph) {
00125 uint16 sv= iph->checksum;
00126 iph->checksum=0;
00127 uint16 ret= count_checksum16(reinterpret_cast<uint16*>(iph), sizeof(struct ip_header));
00128 iph->checksum=sv;
00129 return ret;
00130 }
00131
00132 void ip_transmit(struct ip_address ip_addr, uint8 tos, uint8 prot, struct packet_t *pb) {
00133 struct pbuf *p;
00134 p = reinterpret_cast<struct pbuf*>(kmalloc(sizeof(struct pbuf),"pbuf"));
00135 p->data=pb->buf;
00136 p->ip_data_off=pb->off;
00137 p->len=pb->capacity;
00138 p->end=pb->end;
00139 ip_transmit(ip_addr,tos,prot,p);
00140 }
00141
00142 void ip_transmit(struct ip_address ip_addr, uint8 tos, uint8 prot, struct pbuf *pb) {
00144 struct netif *nif = e3c556_nif;
00145 assert(sizeof(struct ip_header)==20);
00146 testif(pb);
00147 if (pb->ip_data_off < sizeof(struct ip_header)) {
00148 complain("no space for ip header in packet buffer");
00149 return ;
00150 }
00151 struct ip_header *ip;
00152 pb->ip_off=pb->ip_data_off - sizeof(struct ip_header);
00153 ip=reinterpret_cast<struct ip_header*>(&pb->data[pb->ip_off]);
00154 ip->version=4;
00155 ip->hdr_len=sizeof(struct ip_header)/sizeof(uint32);
00156 ip->tos=tos;
00157 ip->len=htons(pb->end - pb->ip_off);
00158 static uint16 ip_iden=0;
00159 ip->iden= htons(ip_iden++);
00160 ip->flags_fo=htons(0);
00161 ip->ttl=32;
00162 ip->prot=prot;
00163 ip->source_ip=nif->ip_addr;
00164 ip->target_ip=ip_addr;
00165
00166
00167 ip->checksum= count_checksum_iph(ip);
00168 struct Option<struct ethernet_address> eth_addr = Net::Arp::arp_get_ether(ip_addr);
00169 if (eth_addr.isNone()) {
00170 ip_outbound_lock.lock();
00171 Thread::Timer::avltree_insert_with_timer(DEF_SECOND*30,
00172 ip_outbound,
00173 Tuple2<struct ip_address, struct netbuf*>(
00174 ip_addr,
00175 new netbuf(pb->end - pb->ip_off, &pb->data[pb->ip_off], null, nif)
00176 )
00177 );
00178 ip_outbound_lock.ulock();
00179 } else {
00181 eth_transmit(nif, eth_addr.get(), 0x0800, new netbuf(pb->end-pb->ip_off, &pb->data[pb->ip_off], null, nif));
00182 }
00183 }
00184 }
00185 }
00186
00187 void print (struct Net::IP::ip_header iph) {
00188 char ltrs[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
00189 prin("(IPv");
00190 putch(ltrs[iph.version]);
00191 prin(": hdrlen=", iph.hdr_len, " tos=", iph.tos, " len=", Net::ntohs(iph.len), " iden=", Net::ntohs(iph.iden),
00192 " flags_fo=", Net::ntohs(iph.flags_fo), " ttl=", iph.ttl, " prot=", iph.prot, " chsum=", Net::ntohs(iph.checksum));
00193 uint16 v= Net::IP::count_checksum_iph(&iph);
00194 if (v==iph.checksum)
00195 prin("(correct)");
00196 else
00197 prin("(should be ", Net::htons(v), ")");
00198 prin(" src=", iph.source_ip, ", target=", iph.target_ip, ")");
00199 }
00200
00201 void print (struct Net::IP::pbuf pb) {
00202 notimpl();
00203 }
00204
00205 void print (struct Net::IP::route_t &route) {
00206 prin("(route_t: target=", route.target, " netmask=", route.netmask, " gateway=", route.gateway, " nif= ", (route.nif==null?"null":route.nif->name), " flags=",route.flags,")");
00207
00208 }
00209
00210