/********************************************************************* * Function: void IP_RxHandler( NET_PKT *sbfr ) * * PreCondition: None * Input: sbfr - packet buffer * Output: None * Side Effects: None * Overview: Process new IP packet received by local NIC * Note: ********************************************************************/ void IP_RxHandler( NET_PKT *sbfr, BYTE * srcMAC ) { IP_HEADER *ipHdr; WORD len, optionsLen; BYTE ihl; // If this packet is not for us then discard it. // we may get these packets only in promiscous mode if( sbfr->PktType == PKT_NON_LOCAL ) { goto IP_DropPkt; } ipHdr = (IP_HEADER*)sbfr->pNetworkLayer; ihl = ipHdr->IHL_Version & 0x0F; if( (ihl < IP_IHLEN) || ((ipHdr->IHL_Version & 0xF0) != IPv4) ) { goto IP_DropPkt; } // Calculate options length in this header, if there is any. // IHL is in terms of numbers of 32-bit DWORDs; i.e. actual // length is 4 times IHL. optionsLen = (ihl * 4) - sizeof(IP_HEADER); if( optionsLen > MAX_OPTIONS_LEN ) { goto IP_DropPkt; } if( checksum16( (BYTE*)ipHdr, ihl * 4 ) != 0xFFFF ) // must be FFFF { goto IP_DropPkt; } len = swaps( ipHdr->TotalLength ); if( (sbfr->PktLen < len) || (len < (ihl * 4) ) ) { goto IP_DropPkt; } ipHdr->TotalLength=sbfr->PktLen = len; //adjust pktlen to not exceed totallength IP_DeliverLocalPkt( sbfr ); return; ////////////////////////////////// IP_DropPkt: DeAllocateBuffer(sbfr); return; }
void _Network::tick() { static unsigned short tx_to=0; static unsigned short rx_to=0; struct ethernet_packet rx; unsigned short len; unsigned short i; ENC28J60 *iface; struct arp_packet *arp; struct ip_packet *ip; struct icmp_packet *icmp; struct udp_packet *udp; struct tcp_packet *tcp; char temp[100]; unsigned long spa,tpa; unsigned char *ipdata; unsigned short ipdlen; unsigned short ipdoff; TCPClient *cli; TCPServer *svr; TCPClient *est; if(rx_to>0) { rx_to--; if(rx_to==0) { digitalWrite(PIN_LED1,LOW); } } if(tx_to>0) { tx_to--; if(tx_to==0) { digitalWrite(PIN_LED2,LOW); } } for(i=0; i<MAX_INTERFACES; i++) { if(this->interfaces[i]!=NULL) { iface = this->interfaces[i]; len = iface->packetReceive(1500,(unsigned char *)&rx); if(len>0) { iface->rx_packets++; // Handle the incoming packet digitalWrite(PIN_LED1,HIGH); rx_to = 10; switch(ntohs(rx.header.ether_type)) { case ETHERTYPE_ARP: arp = (struct arp_packet *)rx.payload; spa = arp->spa[0]<<24 | arp->spa[1]<<16 | arp->spa[2]<<8 | arp->spa[3]; tpa = arp->tpa[0]<<24 | arp->tpa[1]<<16 | arp->tpa[2]<<8 | arp->tpa[3]; if(tpa == iface->ip) { this->addOrUpdateARP(arp->sha,spa,i); if(ntohs(arp->op) == ARP_OP_REQUEST) { // Someone is looking for us. memcpy(arp->tha,arp->sha,6); memcpy(arp->tpa,arp->spa,4); memcpy(arp->sha,iface->mac,6); arp->spa[3] = iface->ip & 0xFF; arp->spa[2] = iface->ip>>8 & 0xFF; arp->spa[1] = iface->ip>>16 & 0xFF; arp->spa[0] = iface->ip>>24 & 0xFF; memcpy(rx.header.ether_dhost,rx.header.ether_shost,6); memcpy(rx.header.ether_shost,iface->mac,6); arp->op = htons(ARP_OP_REPLY); iface->queueTX((unsigned char *)&rx,len); } } break; case ETHERTYPE_IP: ip = (struct ip_packet *)rx.payload; ipdoff = ip->ihl << 2; ipdlen = ntohs(ip->tot_len) - ipdoff; ipdata = (unsigned char *)(&rx.payload)+ipdoff; switch(ip->protocol) { case IPPROTO_ICMP: icmp = (struct icmp_packet *)ipdata; switch(icmp->type) { case ICMP_ECHO: icmp->type = ICMP_ECHOREPLY; memcpy(rx.header.ether_dhost,rx.header.ether_shost,6); memcpy(rx.header.ether_shost,iface->mac,6); memcpy(ip->daddr,ip->saddr,4); ip->saddr[3] = iface->ip & 0xFF; ip->saddr[2] = iface->ip>>8 & 0xFF; ip->saddr[1] = iface->ip>>16 & 0xFF; ip->saddr[0] = iface->ip>>24 & 0xFF; icmp->checksum = 0; icmp->checksum = htons(checksum16(ipdata,ipdlen,CS_IP)); iface->queueTX((unsigned char *)&rx,len); break; } break; case IPPROTO_UDP: udp = (struct udp_packet *)ipdata; for(i=0; i<MAX_PORTS; i++) { if(this->udp_ports[i] != NULL) { if(this->udp_ports[i]->port == ntohs(udp->destPort)) { this->udp_ports[i]->addPacket(len,&rx); } } } break; case IPPROTO_TCP: tcp = (struct tcp_packet *)ipdata; for(i=0; i<MAX_PORTS; i++) { if(this->tcp_clients[i]!=NULL) { if(this->tcp_clients[i]->socketMatch(ntohs(tcp->destPort), ntohs(tcp->sourcePort), quad2ip(ip->saddr[0],ip->saddr[1],ip->saddr[2],ip->saddr[3]))==1) { cli = this->tcp_clients[i]; cli->handleIncomingPacket(ip); } } if(this->tcp_servers[i]!=NULL) { // Packet coming in to a listening socket if((this->tcp_servers[i]->localPort == ntohs(tcp->destPort)) && (this->tcp_servers[i]->state == TCP_LISTEN)) { svr = this->tcp_servers[i]; // Try and match it with an existing connection cli = NULL; for(i=0; i<MAX_TCP_CONNECTIONS; i++) { if(svr->connections[i].state!=TCP_CLOSED) { if(svr->connections[i].socketMatch(ntohs(tcp->destPort), ntohs(tcp->sourcePort), quad2ip(ip->saddr[0],ip->saddr[1],ip->saddr[2],ip->saddr[3]))==1) { cli = &svr->connections[i]; cli->handleIncomingPacket(ip); } } } // Not an existing connections. If it's a SYN then start a connection up if(cli==NULL) { if(tcp->syn==1 && tcp->ack==0) { est = svr->getFreeConnection(); if(est!=NULL) { est->localPort = svr->localPort; est->peerPort = ntohs(tcp->sourcePort); est->peerAddress = quad2ip(ip->saddr[0],ip->saddr[1],ip->saddr[2],ip->saddr[3]); est->tx_mss=1440; est->irs = ntohl(tcp->sequence); est->rx_nxt = est->irs+1; est->iss = rand(); est->tx_nxt = est->iss; est->sendSynAck(); est->state=TCP_ESTABLISHED; } } } } } } break; default: break; } break; default: break; }
short UDP::send(unsigned long peerAddress, unsigned short peerPort, unsigned char *data, unsigned short len) { short interface; struct ethernet_packet eth; unsigned long ipAddress = peerAddress; short rv; struct ip_packet *ip; unsigned char *ipdata; struct udp_packet *udp; unsigned char *udpdata; interface = Network.getInterfaceByIP(peerAddress); if(interface<0) { interface = Network.getDefaultInterface(); } if(interface<0) { return -ENROUTE; } memset((char *)ð,0,sizeof(struct ethernet_packet)); eth.header.ether_type=htons(ETHERTYPE_IP); memcpy(eth.header.ether_shost,Network.interfaces[interface]->mac,6); rv = Network.getARP(ipAddress,(unsigned char *)eth.header.ether_dhost,interface); if(rv < 0) { return -ENARP; } ip = (struct ip_packet *)(ð.payload); ip->protocol = IPPROTO_UDP; ip->ttl = 64; ip->tos = 0; ip->id = htons(Network.interfaces[interface]->id()); ip->flags = 0b010; ip->frag_off = 0; ip->frag_offh = 0; ip->saddr[3] = Network.interfaces[interface]->ip & 0xFF; ip->saddr[2] = Network.interfaces[interface]->ip>>8 & 0xFF; ip->saddr[1] = Network.interfaces[interface]->ip>>16 & 0xFF; ip->saddr[0] = Network.interfaces[interface]->ip>>24 & 0xFF; ip->daddr[3] = ipAddress & 0xFF; ip->daddr[2] = ipAddress>>8 & 0xFF; ip->daddr[1] = ipAddress>>16 & 0xFF; ip->daddr[0] = ipAddress>>24 & 0xFF; ip->version = 4; ip->ihl = 5; ip->tot_len = htons(sizeof(struct udp_packet) + 20 + len); ip->check = 0; ipdata = (unsigned char *)ip + 20; udp = (struct udp_packet *)ipdata; udp->sourcePort = htons(this->port); udp->destPort = htons(peerPort); udp->checksum = 0; udp->length = htons(len+sizeof(udp_packet)); udpdata = (unsigned char *)udp+sizeof(struct udp_packet); memcpy(udpdata,data,len); udp->checksum = htons(checksum16((unsigned char *)&ip->saddr[0],len+16,1)); ip->check = htons(checksum16((unsigned char *)ip,20,CS_IP)); Network.interfaces[interface]->queueTX((unsigned char *)ð,sizeof(struct ether_header)+20+sizeof(struct udp_packet)+len); return len; }
void upload(char *filename, char *path, char *ip, int opt, unsigned short start, unsigned short exec) { int ret, size, p, n, k, i, j; char fullpath[256]; // don't exceed this, the cpc wouldn't be able |cd it anyway FILE *fd; SOCKET sd; unsigned char *buf; fd = fopen(filename, "rb"); if ( fd == NULL ) { printf("file %s not found\n", filename); return; } #ifndef __WIN32__ if (!is_regular_file(filename)) { printf("file %s is not a regular file\n", filename); fclose(fd); return; } #endif fseek(fd, 0, SEEK_END); size = ftell(fd); fseek(fd, 0, SEEK_SET); buf = malloc(size+0x80); if ( buf == NULL ) { printf("Not enough memory!\n"); fclose(fd); return; } if ( opt != 0 ) { _cpchead *cpcheader = (_cpchead *)buf; memset(cpcheader, 0, 0x80); // set up cleaned filename and extionsion formatfn(cpcheader->filename, filename); getExtension(cpcheader->extension, filename); // add more file types here... and more paramters.... switch (opt) { case 1: cpcheader->addr = 0x172; // protext uses this cpcheader->type = 10; cpcheader->size = size; cpcheader->size2 = size; cpcheader->checksum = checksum16(buf, 66); break; default: case 2: // binary header cpcheader->addr = start; cpcheader->exec = exec; cpcheader->type = 2; cpcheader->size = size; cpcheader->size2 = size; cpcheader->checksum = checksum16(buf, 66); break; } fread(&buf[0x80], size, 1, fd); size+=0x80; } else fread(buf, size, 1, fd); fclose(fd); ret = httpConnect(ip); if ( ret >= 0 ) { sd = ret; // connect socket p = pathPos(filename, strlen(filename)); // strip any PC path from filename sprintf(fullpath, "%s/%s", path, &filename[p]); k = strlen(fullpath); n = 0; while ( n < k ) // remove leading / from path { if ( fullpath[n] != '/' ) break; n++; } // remove duplicate /'s k = strlen(fullpath); j = 0; for (i=n; i < (k+1); i++) { if ( (fullpath[i] == '/') && (fullpath[i+1] == '/') ) i++; fullpath[j++] = fullpath[i]; } if ( httpSend(sd, fullpath, buf, size, "upfile", "/upload.html", ip) >= 0 ) ret = httpResponse(sd); httpClose(sd); if ( ret == 200 ) printf("Upload OK!\r\n"); else printf("Upload error code. %i\r\n", ret); } else printf("Connect to %s failed\n", ip); free(buf); }