int fix_tcp_packet (in_Header *ip, tcp_Header *tcp, int ack_len, int data_len) { static DWORD seq_num = 12345678; /* starting sequence */ tcp_PseudoHeader ph; WORD src_port; tcp->checksum = 0; src_port = tcp->srcPort; tcp->srcPort = tcp->dstPort; tcp->dstPort = src_port; tcp->acknum = intel (intel(tcp->seqnum) + ack_len); tcp->seqnum = intel (seq_num); tcp->offset = sizeof(*tcp) / 4; /* in dwords */ seq_num += data_len; ph.src = ip->source; ph.dst = ip->destination; ph.mbz = 0; ph.protocol = TCP_PROTO; ph.length = intel16 (sizeof(*tcp) + data_len); ph.checksum = CHECKSUM (tcp, sizeof(*tcp) + data_len); ip->length = intel16 (data_len + sizeof(*tcp) + sizeof(*ip)); ip->checksum = 0; ip->checksum = ~CHECKSUM (ip, sizeof(*ip)); tcp->checksum = ~CHECKSUM (&ph, sizeof(ph)); return (sizeof(*ip) + sizeof(*tcp) + data_len); }
/** * Check if ip-source is a (directed) broadcast address. * Some hacker may try to create a broadcast storm. * Also check for null source address (0.0.0.0). * Broadcast destination is already filtered out by icmp_handler(). */ static BOOL icmp_check (const in_Header *ip, int type) { DWORD src, dst; BOOL bcast; src = intel (ip->source); dst = intel (ip->destination); bcast = (~src & ~sin_mask) == 0; if (bcast) { icmp_bogus (ip, type, _LANG(" (broadcast)")); return (FALSE); } if (ip->source == 0UL) { icmp_bogus (ip, type, _LANG(" (network)")); return (FALSE); } if (IN_MULTICAST(dst)) { icmp_bogus (ip, type, _LANG(" (multicast)")); return (FALSE); } if (IN_EXPERIMENTAL(dst)) { icmp_bogus (ip, type, _LANG(" (experimental)")); return (FALSE); } return (TRUE); }
/** * Handle ICMP_REDIRECT messages. */ static void icmp_redirect (const union ICMP_PKT *icmp, const in_Header *ip, const in_Header *orig_ip, int code) { DWORD new_ip = intel (icmp->ip.ipaddr); DWORD old_ip = intel (orig_ip->destination); const char *msg; if (new_ip == old_ip) { /* Possibly because we and router use different netmasks */ } else if ((new_ip ^ my_ip_addr) & sin_mask) /* new host not on subnet */ { char buf[100]; strcpy (buf, ", GW = "); strcat (buf, _inet_ntoa(NULL,new_ip)); icmp_bogus (ip, ICMP_REDIRECT, buf); return; } msg = icmp_redirect_str[code]; icmp_print (1, msg, ip->source); switch (orig_ip->proto) { #if !defined(USE_UDP_ONLY) case TCP_PROTO: if (do_redirect.tcp) /* do it to some socket */ _tcp_cancel (orig_ip, ICMP_REDIRECT, code, msg, &new_ip); break; #endif case UDP_PROTO: if (do_redirect.udp) _udp_cancel (orig_ip, ICMP_REDIRECT, code, msg, &new_ip); break; case ICMP_PROTO: if (do_redirect.icmp) { /* _ip_recursion = TRUE; !! */ _arp_register (new_ip, old_ip); /* _ip_recursion = FALSE; !! */ } break; case IGMP_PROTO: if (do_redirect.igmp) { /* _ip_recursion = TRUE; !! */ _arp_register (new_ip, old_ip); /* _ip_recursion = FALSE; !! */ } break; } }
//-------------------------------------------------------------- void ofShader::checkShaderInfoLog(GLuint shader, GLenum type, ofLogLevel logLevel) { GLsizei infoLength; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLength); if (infoLength > 1) { GLchar* infoBuffer = new GLchar[infoLength]; glGetShaderInfoLog(shader, infoLength, &infoLength, infoBuffer); ofLog(logLevel, "ofShader: %s shader reports:\n%s", nameForType(type).c_str(), infoBuffer); if (shaderSource.find(type) != shaderSource.end()) { // The following regexp should match shader compiler error messages by Nvidia and ATI. // Unfortunately, each vendor's driver formats error messages slightly different. std::regex nvidia_ati("^.*[(:]{1}(\\d+)[:)]{1}.*"); std::regex intel("^[0-9]+:([0-9]+)\\([0-9]+\\):.*$"); std::smatch matches; string infoString = (infoBuffer != nullptr) ? ofTrim(infoBuffer): ""; if (std::regex_search(infoString, matches, intel) || std::regex_search(infoString, matches, nvidia_ati)){ ofBuffer buf = shaderSource[type]; ofBuffer::Line line = buf.getLines().begin(); int offendingLineNumber = ofToInt(matches[1]); ostringstream msg; msg << "ofShader: " + nameForType(type) + ", offending line " << offendingLineNumber << " :"<< endl; for(int i=0; line != buf.getLines().end(); line++, i++ ){ string s = *line; if ( i >= offendingLineNumber -3 && i < offendingLineNumber + 2 ){ msg << "\t" << setw(5) << (i+1) << "\t" << s << endl; } } ofLog(logLevel) << msg.str(); }else{ ofLog(logLevel) << shaderSource[type]; } } delete [] infoBuffer; } }
/* * igmp_report - send a IGMP Report packet * * int igmp_report (DWORD ip) * Where: * ip is the IP address to report. * * Returns: * 0 if unable to send report * 1 report was sent successfully */ int igmp_report (DWORD ip) { struct IGMP_PKT *pkt; IGMP_packet *igmp; eth_address ethaddr; /* get the ethernet addr of the destination */ multi_to_eth ((DWORD)ALL_SYSTEMS, (BYTE*)ðaddr); /* format the packet with the request's hardware address */ pkt = (struct IGMP_PKT*) _eth_formatpacket (ethaddr, IP_TYPE); igmp = &pkt->igmp; ip = intel (ip); /* fill in the igmp packet */ igmp->type = IGMP_REPORT; igmp->version = IGMP_VERSION; igmp->mbz = 0; igmp->address = ip; igmp->checksum = 0; igmp->checksum = ~checksum (igmp,sizeof(*igmp)); return IP_OUTPUT (&pkt->in, 0, ip, IGMP_PROTO, 0, 0, 0, (int)sizeof(*igmp), NULL); }
/* * igmp_handler - handles the incoming IGMP packets * * void igmp_handler (in_Header *ip) * Where: * ip is the IP packet in question * * Returns: None * */ void igmp_handler (const in_Header *ip, BOOL broadcast) { BYTE i; DWORD host; BOOL found = 0; WORD len = in_GetHdrLen (ip); IGMP_packet *igmp = (IGMP_packet*) ((BYTE*)ip + len); DEBUG_RX (NULL, ip); if (len < sizeof(*igmp)) { STAT (igmpstats.igps_rcv_tooshort++); return; } if (checksum(igmp,sizeof(*igmp)) != 0xFFFF) { STAT (igmpstats.igps_rcv_badsum++); return; } host = intel (igmp->address); /* Determine whether this is a report or a query */ switch (igmp->type) { case IGMP_QUERY: STAT (igmpstats.igps_rcv_queries++); for (i = 0; i < IPMULTI_SIZE; i++) if (_ipmulti[i].active && _ipmulti[i].ina != ALL_SYSTEMS && _ipmulti[i].replytime == 0) { _ipmulti[i].replytime = set_timeout (Random(500,1000)); found = 1; } if (!found && !broadcast) STAT (igmpstats.igps_rcv_badqueries++); break; case IGMP_REPORT: STAT (igmpstats.igps_rcv_reports++); for (i = 0; i < IPMULTI_SIZE; i++) if (_ipmulti[i].active && _ipmulti[i].ina == host && host != ALL_SYSTEMS) { _ipmulti[i].replytime = 0; found = 1; STAT (igmpstats.igps_rcv_ourreports++); break; } if (!found && !broadcast) STAT (igmpstats.igps_rcv_badreports++); break; } }
/* * resolve() * convert domain name -> address resolution. * returns 0 if name is unresolvable right now */ longword resolve_fn( char *name, sockfunct_t fn ) // S. Lawson { longword ipaddr; // S. Lawson #define DNSCACHESIZE 4 // cache up to 4 names #define DNSCACHELENGTH 32 // up to 32 characters #define DNSCACHETIMEOUT 120 // for up to 2 minutes static char DNScacheName[DNSCACHESIZE][DNSCACHELENGTH]; static longword DNScacheIP[DNSCACHESIZE]; static longword DNScacheTimeout[DNSCACHESIZE]={0,0,0,0}; static char DNScacheNext=0; int DNScacheScan; if( !name ) return 0L; rip( name ); // S. Lawson - trim for cache scan if ( isaddr( name )) return( aton( name )); // S. Lawson for (DNScacheScan=0 ; DNScacheScan<DNSCACHESIZE ; DNScacheScan++) { if (DNScacheTimeout[DNScacheScan]==0L) continue; if (chk_timeout(DNScacheTimeout[DNScacheScan])) { DNScacheTimeout[DNScacheScan]=0L; continue; } if(!strcmpi(DNScacheName[DNScacheScan],name)) return DNScacheIP[DNScacheScan]; } #ifdef NOTUSED // S. Lawson if( do_ns_lookup(name, DTYPEA, typea_unpacker, &ipaddr) ) return (intel(ipaddr)); else return (0L); #else // S. Lawson if( do_ns_lookup(name, DTYPEA, typea_unpacker, &ipaddr, fn) ) { strncpy(DNScacheName[DNScacheNext], name, DNSCACHELENGTH); DNScacheName[DNScacheNext][DNSCACHELENGTH-1]='\0'; DNScacheIP[DNScacheNext]=intel(ipaddr); DNScacheTimeout[DNScacheNext]=set_timeout(DNSCACHETIMEOUT); if (++DNScacheNext>=DNSCACHESIZE) DNScacheNext=0; return (intel(ipaddr)); } return (0L); #endif // S. Lawson }
static void icmp_print (int dbg_lvl, const char *msg, DWORD src) { if (debug_on < dbg_lvl) return; outs ("\nICMP: "); if (src) { outs ("("); outs (_inet_ntoa(NULL,intel(src))); outs ("): "); } outsnl (_LANG(msg)); }
/** * Handle incoming RARP packets. */ BOOL _rarp_handler (const rarp_Header *rh, BOOL brdcast) { SIO_TRACE (("_rarp_handler")); DEBUG_RX (NULL, rh); if (!brdcast && rh->opcode == RARP_REPLY && rh->protType == IP4_TYPE && !memcmp(rh->dstEthAddr,_eth_addr,sizeof(mac_address))) { my_ip_addr = intel (rh->dstIPAddr); return (TRUE); } return (FALSE); }
/* * _dorarp - Checks global variable _rarptimeout * returns 1 on success and sets ip address */ int _dorarp (void) { DWORD rarptimeout = set_timeout (1000 * _rarptimeout); WORD magictimeout = Random (7000, 14000); outs (_LANG("Configuring through RARP...")); while (1) { DWORD sendtimeout; if (!_rarp_request()) break; sendtimeout = set_timeout (magictimeout); magictimeout += Random (1000, 7000); while (!chk_timeout(sendtimeout)) { const struct rarp_Header *rarp; WORD eth_type; BOOL bcast; if (chk_timeout(rarptimeout)) return (0); WATT_YIELD(); rarp = (rarp_Header*) _eth_arrived (ð_type, &bcast); if (!rarp) continue; DEBUG_RX (NULL, rarp); if (eth_type == RARP_TYPE && !bcast && rarp->opcode == RARP_REPLY && rarp->protType == IP4_TYPE && !memcmp(rarp->dstEthAddr,_eth_addr,sizeof(mac_address))) { my_ip_addr = intel (rarp->dstIPAddr); _eth_free (rarp); return (1); } _eth_free (rarp); } } return (0); }
void DccTransferRecv::sendAck() // slot { //kdDebug() << "sendAck()" << endl; KIO::fileoffset_t pos = intel( m_transferringPosition ); m_recvSocket->enableWrite( false ); m_recvSocket->writeBlock( (char*)&pos, 4 ); if ( m_transferringPosition == (KIO::fileoffset_t)m_fileSize ) { kdDebug() << "DccTransferRecv::sendAck(): Sent final ACK." << endl; m_recvSocket->enableRead( false ); disconnect( m_recvSocket, 0, 0, 0 ); finishTransferLogger(); m_writeCacheHandler->close(); // WriteCacheHandler will send the signal done() } else if ( m_transferringPosition > (KIO::fileoffset_t)m_fileSize ) { kdDebug() << "DccTransferRecv::sendAck(): the remote host sent larger data than expected: " << QString::number( m_transferringPosition ) << endl; failed( i18n( "Transferring error" ) ); } }
static int ping_gateway (DWORD host, void *eth) { struct ping_pkt *pkt; struct icmp_echo *icmp; struct in_Header *ip; int len; pkt = (struct ping_pkt*) _eth_formatpacket (eth, IP4_TYPE); ip = &pkt->in; icmp = &pkt->icmp; len = sizeof (*icmp); icmp_id = (WORD) set_timeout (0); /* "random" id */ icmp->type = ICMP_ECHO; icmp->code = 0; icmp->index = 1; icmp->identifier = icmp_id; icmp->sequence = icmp_seq++; icmp->checksum = 0; icmp->checksum = ~CHECKSUM (icmp, len); return IP4_OUTPUT (ip, 0, intel(host), ICMP_PROTO, 1, (BYTE)_default_tos, 0, len, NULL); }
/** * Handler for incoming ICMP packets. */ void icmp_handler (const in_Header *ip, BOOL broadcast) { union ICMP_PKT *icmp; const in_Header *orig_ip; int type, code; unsigned len; DWORD delta_time; BOOL for_me, i_orig; /* is it for me, did I originate it */ const char *msg; DEBUG_RX (NULL, ip); if (block_icmp) /* application is handling ICMP; not needed */ return; len = in_GetHdrLen (ip); icmp = (union ICMP_PKT*) ((BYTE*)ip + len); len = intel16 (ip->length) - len; for_me = _ip4_is_multihome_addr (intel(ip->destination)); if (!for_me || broadcast) /* drop broadcast pings.. */ return; if (len < sizeof(icmp->info)) { STAT (icmpstats.icps_tooshort++); return; } if (CHECKSUM(icmp,len) != 0xFFFF) { STAT (icmpstats.icps_checksum++); icmp_print (1, _LANG("bad checksum"), ip->source); return; } type = icmp->unused.type; code = icmp->unused.code; orig_ip = &icmp->ip.ip; i_orig = _ip4_is_local_addr (intel(orig_ip->source)); if (type == ICMP_MASKREPLY) { if (!_do_mask_req) return; i_orig = TRUE; } /* !! this needs work */ if (!i_orig && (type != ICMP_ECHOREPLY && type != ICMP_ECHO && type != ICMP_IREQREPLY && type != ICMP_TSTAMP)) { icmp_bogus (ip, type, NULL); return; } switch (type) { case ICMP_ECHOREPLY: /* check if we were waiting for it */ delta_time = set_timeout(0) - icmp->echo.identifier; add_ping (intel(ip->source), delta_time, icmp->echo.index); return; case ICMP_UNREACH: if (code < DIM(icmp_unreach_str)) { UINT len_needed = 8 + in_GetHdrLen (orig_ip); WORD next_mtu = 0; msg = _LANG (icmp_unreach_str[code]); icmp_print (1, msg, ip->source); if (orig_ip->proto == TCP_PROTO || orig_ip->proto == UDP_PROTO) len_needed += 4; /* Need the src/dest port numbers */ if (len >= len_needed) { if (code == ICMP_UNREACH_NEEDFRAG) next_mtu = intel16 (icmp->needfrag.next_mtu); #if !defined(USE_UDP_ONLY) if (orig_ip->proto == TCP_PROTO) _tcp_cancel (orig_ip, ICMP_UNREACH, code, msg, &next_mtu); else #endif if (orig_ip->proto == UDP_PROTO) _udp_cancel (orig_ip, ICMP_UNREACH, code, msg, &next_mtu); /** \todo Handle cancelling raw sockets */ #if defined(USE_BSD_API) && 0 else _raw_cancel (orig_ip, ICMP_UNREACH, code, msg); #endif } else STAT (icmpstats.icps_tooshort++); } else STAT (icmpstats.icps_badcode++); return; case ICMP_SOURCEQUENCH: #if !defined(USE_UDP_ONLY) if (orig_ip->proto == TCP_PROTO) { msg = _LANG (icmp_type_str[type]); icmp_print (1, msg, ip->source); _tcp_cancel (orig_ip, ICMP_SOURCEQUENCH, code, msg, NULL); } #endif return; case ICMP_REDIRECT: if (code < DIM(icmp_redirect_str)) icmp_redirect (icmp, ip, orig_ip, code); else STAT (icmpstats.icps_badcode++); return; case ICMP_ECHO: icmp_print (2, _LANG("PING requested of us"), ip->source); icmp_echo_reply (ip, icmp, len); return; case ICMP_TIMXCEED: if (code >= DIM(icmp_exceed_str)) { STAT (icmpstats.icps_badcode++); return; } if (code == 0) /* "TTL exceeded in transit" */ switch (orig_ip->proto) { #if !defined(USE_UDP_ONLY) case TCP_PROTO: msg = _LANG (icmp_exceed_str[0]); icmp_print (1, msg, ip->source); _tcp_cancel (orig_ip, ICMP_TIMXCEED, code, msg, NULL); break; #endif case UDP_PROTO: msg = _LANG (icmp_exceed_str[0]); icmp_print (1, msg, ip->source); _udp_cancel (orig_ip, ICMP_TIMXCEED, code, msg, NULL); break; } return; case ICMP_PARAMPROB: msg = _LANG (icmp_type_str[ICMP_PARAMPROB]); switch (orig_ip->proto) { #if !defined(USE_UDP_ONLY) case TCP_PROTO: icmp_print (0, msg, ip->source); _tcp_cancel (orig_ip, ICMP_PARAMPROB, code, msg, NULL); break; #endif case UDP_PROTO: icmp_print (0, msg, ip->source); _udp_cancel (orig_ip, ICMP_PARAMPROB, code, msg, NULL); break; } return; case ICMP_ROUTERADVERT: /* todo !! */ msg = _LANG (icmp_type_str[ICMP_ROUTERADVERT]); icmp_print (1, msg, ip->source); return; case ICMP_ROUTERSOLICIT: /* todo !! */ msg = _LANG (icmp_type_str[ICMP_ROUTERSOLICIT]); icmp_print (1, msg, ip->source); return; case ICMP_TSTAMP: msg = _LANG (icmp_type_str[ICMP_TSTAMP]); icmp_print (1, msg, ip->source); /**< \todo send reply? */ return; case ICMP_TSTAMPREPLY: msg = _LANG (icmp_type_str[ICMP_TSTAMPREPLY]); icmp_print (1, msg, ip->source); /**< \todo should store */ return; case ICMP_IREQ: msg = _LANG (icmp_type_str[ICMP_IREQ]); icmp_print (1, msg, ip->source); /**< \todo send reply */ return; case ICMP_IREQREPLY: msg = _LANG (icmp_type_str[ICMP_IREQREPLY]); icmp_print (1, msg, ip->source); /**< \todo send reply upwards */ return; case ICMP_MASKREQ: /* might be sent by us, never answer */ break; case ICMP_MASKREPLY: msg = _LANG (icmp_type_str[ICMP_MASKREPLY]); icmp_print (0, msg, ip->source); if ((icmp->mask.identifier == addr_mask_id) && (icmp->mask.sequence == addr_mask_seq-1) && sin_mask != intel(icmp->mask.mask)) outsnl ("Conflicting net-mask from \"ICMP Addr Mask Reply\"\7"); addr_mask_id = 0; return; } }
/** * _eth_send() does the actual transmission once we are complete with * filling the buffer. Do any last minute patches here, like fix the * size. Send to "loopback" device if it's IP and destination matches * loopback network (127.x.x.x.). * * Return length of network-layer packet (not length of link-layer * packet). */ int _eth_send (WORD len, const void *sock, const char *file, unsigned line) { #if defined(USE_DEBUG) || defined(USE_LOOPBACK) unsigned errline = 0; #endif BOOL send_loopback_to_driver = FALSE; SIO_TRACE (("_eth_send, len %d", len)); if (!_eth_is_init) /* GvB 2002-09, Lets us run without a working eth */ { SOCK_ERRNO (ENETDOWN); return (0); } #if defined(WIN32) /* * Just a test for now; send it to the driver and look what happens.... * They go on the wire and not to the Winsock loopback provider. * No surprise here yet. */ if (loopback_mode & LBACK_MODE_WINSOCK) send_loopback_to_driver = TRUE; #endif if (proto == IP4_TYPE) { /* Sending to loopback device if IPv4. */ const in_Header *ip = (const in_Header*) nw_pkt; if (!send_loopback_to_driver && _ip4_is_loopback_addr(intel(ip->destination))) { #if defined(USE_LOOPBACK) len = send_loopback (*TX_BUF(), FALSE, &errline); #else STAT (ip4stats.ips_odropped++); /* packet dropped (null-device) */ #endif goto debug_tx; } } #if defined(USE_IPV6) else if (proto == IP6_TYPE) { const in6_Header *ip = (const in6_Header*) nw_pkt; if (!send_loopback_to_driver && IN6_IS_ADDR_LOOPBACK(&ip->destination)) { #if defined(USE_LOOPBACK) len = send_loopback (*TX_BUF(), TRUE, &errline); #else STAT (ip6stats.ip6s_odropped++); #endif goto debug_tx; } } #endif /* USE_IPV6 */ #if defined(USE_PPPOE) else if (proto == PPPOE_SESS_TYPE) { pppoe_Packet *pppoe = (pppoe_Packet*) TX_BUF()->eth.data; pppoe->length = intel16 (len+2); len += PPPOE_HDR_SIZE + 2; /* add 2 for protocol */ } #endif /* Store the last Tx CPU timestamp (for debugging). */ #if (DOSX) && !(DOSX & WINWATT) if (_dbugxmit && has_rdtsc) get_rdtsc2 (&_eth_last.tx.tstamp); #endif /* Do the MAC-dependant transmit. `len' on return is total length * of link-layer packet sent. `len' is 0 on failure. The xmit-hook * is used by e.g. libpcap/libnet. */ if (_eth_xmit_hook) len = (*_eth_xmit_hook) (TX_BUF(), len + _pkt_ip_ofs); else len = (*mac_transmit) (TX_BUF(), len + _pkt_ip_ofs); if (len > _pkt_ip_ofs) { _eth_last.tx.size = len; len -= _pkt_ip_ofs; } else { if (debug_on) outs ("Tx failed. "); len = 0; _eth_last.tx.size = 0; } debug_tx: #if defined(NEED_PKT_SPLIT) pkt_split_mac_out (TX_BUF()); #endif #if defined(USE_STATISTICS) if (len > 0) update_out_stat(); #endif #if defined(USE_DEBUG) if (_dbugxmit) (*_dbugxmit) (sock, (const in_Header*)nw_pkt, file, line); if (len == 0) { if (errline && !send_loopback_to_driver) dbug_printf ("** Error in loopback handler, line %u\n", errline); else { const char err[] = "** Transmit fault **\n"; TCP_CONSOLE_MSG (0, ("%s", err)); dbug_printf (err); } } #else ARGSUSED (sock); ARGSUSED (file); ARGSUSED (line); #endif /* Undo hack done in pppoe_mac_format() */ if (proto == PPPOE_SESS_TYPE || _pktdevclass == PDCLASS_ETHER) _pkt_ip_ofs = sizeof(eth_Header); return (len); }
DWORD ntohl (DWORD val) { return intel(val); }
DWORD htonl (DWORD val) { return intel(val); }
/* * Handler for incoming ICMP packets */ void icmp_handler (const in_Header *ip, BOOL broadcast) { union icmp_pkt *icmp; in_Header *orig_ip; int len, type, code; BOOL for_me, i_orig; /* is it for me, did I originate it */ const char *msg; DEBUG_RX (NULL, ip); if (block_icmp) /* application is handling ICMP; not needed */ return; len = in_GetHdrLen (ip); icmp = (union icmp_pkt*) ((BYTE*)ip + len); len = intel16 (ip->length) - len; for_me = (DWORD) (intel(ip->destination) - my_ip_addr) <= multihomes; if (!for_me || broadcast) /* drop broadcast pings.. */ return; if (len < sizeof(icmp->info)) { STAT (icmpstats.icps_tooshort++); return; } if (checksum(icmp,len) != 0xFFFF) { STAT (icmpstats.icps_checksum++); icmp_print (1, _LANG("bad checksum"), ip->source); return; } type = icmp->unused.type; code = icmp->unused.code; orig_ip = &icmp->ip.ip; i_orig = is_local_addr (intel(orig_ip->source)); if (type == ICMP_MASKREPLY) { if (!_domask_req) return; i_orig = TRUE; } /* !! this needs work */ if (!i_orig && (type != ICMP_ECHOREPLY && type != ICMP_ECHO && type != ICMP_IREQREPLY && type != ICMP_TSTAMP)) { icmp_bogus (ip, type, NULL); return; } switch (type) { case ICMP_ECHOREPLY: /* check if we were waiting for it */ STAT (icmpstats.icps_inhist[ICMP_ECHOREPLY]++); ping_hcache = intel (ip->source); ping_tcache = set_timeout (1000) - *(DWORD*)&icmp->echo.identifier; if (ping_tcache > 0x7FFFFFFFL) ping_tcache += 0x1800B0L; ping_number = *(DWORD*)(((BYTE*)&icmp->echo.identifier) + 4); return; case ICMP_UNREACH: STAT (icmpstats.icps_inhist[ICMP_UNREACH]++); if (code < DIM(icmp_unreach_str)) { icmp_print (1, msg = icmp_unreach_str[code], ip->source); #if !defined(USE_UDP_ONLY) if (orig_ip->proto == TCP_PROTO) _tcp_cancel (orig_ip, type, msg, 0); else #endif if (orig_ip->proto == UDP_PROTO) _udp_cancel (orig_ip, type, msg, 0); } else STAT (icmpstats.icps_badcode++); return; case ICMP_SOURCEQUENCH: STAT (icmpstats.icps_inhist[ICMP_SOURCEQUENCH]++); #if !defined(USE_UDP_ONLY) if (orig_ip->proto == TCP_PROTO) { icmp_print (1, _LANG("Source Quench"), ip->source); _tcp_cancel (orig_ip, type, NULL, 0); } #endif return; case ICMP_REDIRECT: STAT (icmpstats.icps_inhist[ICMP_REDIRECT]++); if (code < 4) { DWORD new_gw = intel (icmp->ip.ipaddr); /* Check if new gateway is on our subnet */ if ((new_gw ^ my_ip_addr) & sin_mask) { char buf[100], adr[20]; strcpy (buf, ", GW = "); strcat (buf, _inet_ntoa(adr,new_gw)); icmp_bogus (ip, type, buf); return; } icmp_print (1, msg = icmp_redirect_str[code], ip->source); switch (orig_ip->proto) { #if !defined(USE_UDP_ONLY) case TCP_PROTO: if (do_redirect.tcp) /* do it to some socket */ _tcp_cancel (orig_ip, type, msg, new_gw); break; #endif case UDP_PROTO: if (do_redirect.udp) _udp_cancel (orig_ip, type, msg, new_gw); break; case ICMP_PROTO: if (do_redirect.icmp) { _ip_recursion = 1; _arp_register (new_gw, intel(orig_ip->destination), 0); _ip_recursion = 0; } break; case IGMP_PROTO: if (do_redirect.igmp) { _ip_recursion = 1; _arp_register (new_gw, intel(orig_ip->destination), 0); _ip_recursion = 0; } break; } } else STAT (icmpstats.icps_badcode++); return; case ICMP_ECHO: STAT (icmpstats.icps_inhist[ICMP_ECHO]++); icmp_print (2, _LANG("PING requested of us"), ip->source); { /* Extract eth-address and create Echo reply packet. */ struct _pkt *pkt; union icmp_pkt *newicmp; if (!icmp_chk_src(ip,ICMP_ECHO)) return; pkt = (struct _pkt*) _eth_formatpacket (MAC_SRC(ip), IP_TYPE); newicmp = &pkt->icmp; /* Don't let a huge reassembled ICMP-packet kill us. */ len = min (len, mtu - sizeof(*ip)); memcpy (newicmp, icmp, len); newicmp->echo.type = ICMP_ECHOREPLY; newicmp->echo.code = code; /* Use supplied ip values in case we ever multi-home. * Note that ip values are still in network order. */ icmp_send (pkt, ip->destination, ip->source, len); icmp_print (2, _LANG("PING reply sent"), 0); } return; case ICMP_TIMXCEED: if (code >= DIM(icmp_exceed_str)) { STAT (icmpstats.icps_badcode++); return; } STAT (icmpstats.icps_inhist[ICMP_TIMXCEED]++); if (code != 1) switch (orig_ip->proto) { #if !defined(USE_UDP_ONLY) case TCP_PROTO: icmp_print (1, icmp_exceed_str[code], ip->source); _tcp_cancel (orig_ip, ICMP_TIMXCEED, NULL, 0); break; #endif case UDP_PROTO: icmp_print (1, icmp_exceed_str[code], ip->source); _udp_cancel (orig_ip, ICMP_TIMXCEED, NULL, 0); break; } return; case ICMP_PARAMPROB: STAT (icmpstats.icps_inhist[ICMP_PARAMPROB]++); switch (orig_ip->proto) { #if !defined(USE_UDP_ONLY) case TCP_PROTO: icmp_print (0, _LANG(icmp_type_str[type]), ip->source); _tcp_cancel (orig_ip, type, NULL, 0); break; #endif case UDP_PROTO: icmp_print (0, _LANG(icmp_type_str[type]), ip->source); _udp_cancel (orig_ip, type, NULL, 0); break; } return; case ICMP_ROUTERADVERT: /* todo !! */ STAT (icmpstats.icps_inhist[ICMP_ROUTERADVERT]++); icmp_print (1, _LANG(icmp_type_str[type]), ip->source); return; case ICMP_ROUTERSOLICIT: /* todo !! */ STAT (icmpstats.icps_inhist[ICMP_ROUTERSOLICIT]++); icmp_print (1, _LANG(icmp_type_str[type]), ip->source); return; case ICMP_TSTAMP: STAT (icmpstats.icps_inhist[ICMP_TSTAMP]++); icmp_print (1, _LANG(icmp_type_str[type]), ip->source); /* todo!!, send reply? */ return; case ICMP_TSTAMPREPLY: STAT (icmpstats.icps_inhist[ICMP_TSTAMPREPLY]++); icmp_print (1, _LANG(icmp_type_str[type]), ip->source); /* todo!!, should store */ return; case ICMP_IREQ: STAT (icmpstats.icps_inhist[ICMP_IREQ]++); icmp_print (1, _LANG(icmp_type_str[type]), ip->source); /* todo!!, send reply */ return; case ICMP_IREQREPLY: STAT (icmpstats.icps_inhist[ICMP_IREQREPLY]++); icmp_print (1, _LANG(icmp_type_str[type]), ip->source); /* todo!!, send reply upwards */ return; case ICMP_MASKREQ: STAT (icmpstats.icps_inhist[ICMP_MASKREQ]++); break; case ICMP_MASKREPLY: STAT (icmpstats.icps_inhist[ICMP_MASKREPLY]++); icmp_print (0, _LANG(icmp_type_str[type]), ip->source); if ((icmp->mask.identifier == addr_mask_id) && (icmp->mask.sequence == addr_mask_seq-1) && sin_mask != intel(icmp->mask.mask)) outsnl ("Conflicting net-mask from \"ICMP Addr Mask Reply\"\7"); addr_mask_id = 0; return; } }
int sock_recv_from (sock_type *s, void *hisip, WORD *hisport, void *buffer, unsigned len, int peek) { #if !defined(USE_UDP_ONLY) _tcp_Socket *t; #endif recv_buf *p, *oldest = NULL; recv_data *r = (recv_data*) s->udp.rx_data; long seqnum = LONG_MAX; int i; if (r->recv_sig != RECV_USED) { SOCK_ERRNO (EBADF); /* To differentiate an error from 0-byte probe (also -1) */ return (-1); } switch (s->udp.ip_type) { case UDP_PROTO: p = (recv_buf*) r->recv_bufs; /* find the oldest used UDP buffer. */ for (i = 0; i < r->recv_bufnum; i++, p++) { switch (p->buf_sig) { case RECV_UNUSED: break; case RECV_USED: /* Drop looped packets sent by us (running * under Win32 DOS box using NDIS3PKT or SwsVpkt). */ if ((_eth_ndis3pkt || _eth_SwsVpkt) && !s->tcp.is_ip6 && p->buf_hisip == intel(my_ip_addr)) { p->buf_sig = RECV_UNUSED; continue; } if (p->buf_seqnum < seqnum) /* ignore wraps */ { seqnum = p->buf_seqnum; oldest = p; #if 0 SOCK_DEBUGF (("\nsock_recv_from(): buffer %d, " "seq-num %ld, len %d", i, seqnum, p->buf_len)); #endif } break; default: outsnl (_LANG("ERROR: sock_recv_init data err")); return (0); } } break; #if !defined(USE_UDP_ONLY) case TCP_PROTO: t = &s->tcp; len = min (len, (unsigned)t->rx_datalen); if (len) memcpy (buffer, r->recv_bufs, len); return (len); #endif } if (!oldest) return (0); /* found the oldest UDP packet */ p = oldest; if (p->buf_len < 0) /* a 0-byte probe packet */ len = -1; else { len = min ((unsigned)p->buf_len, len); memcpy (buffer, p->buf_data, len); } #if defined(USE_IPV6) if (s->tcp.is_ip6) { if (hisip) memcpy (hisip, &p->buf_hisip6, sizeof(ip6_address)); } else #endif if (hisip) *(DWORD*)hisip = p->buf_hisip; if (hisport) *hisport = p->buf_hisport; if (!peek) p->buf_sig = RECV_UNUSED; return (len); }