/*++ Copyright (c) 2000 Microsoft Corporation Module Name: ipsend.c Abstract: IP datagram transmission related functions Revision History: 05/22/2000 davidx Created it. --*/ #include "precomp.h" // // Default type-of-service value for outgoing datagrams // BYTE cfgDefaultTos = 0; // // Default time-to-live value for outgoing datagrams // BYTE cfgDefaultTtl = 64; // // Identifier to be assigned to the next outgoing IP datagram // WORD IpNextDgramId; NTSTATUS IpSendPacket( Packet* pkt, IPADDR dstaddr, IfInfo* ifp, RTE** cachedRte ) /*++ Routine Description: Send out an IP datagram to the specified destination address Arguments: pkt - Specifies the datagram to be sent dstaddr - Specifies the destination address ifp - Points to the outgoing interface, optional cachedRte - Address of a cached route entry pointer Return Value: Status code --*/ { RTE* rte; RUNS_AT_DISPATCH_LEVEL // The IP header must be completely filled out ASSERT(pkt->data == (BYTE*) GETPKTIPHDR(pkt)); // Find a route and cache it if ((rte = *cachedRte) == NULL || IsRteOrphaned(rte)) { // release the orphaned route entry if (rte) { IpReleaseCachedRTE(rte); } *cachedRte = rte = IpFindRTE(dstaddr, ifp); if (!rte) { XnetCompletePacket(pkt, NETERR_UNREACHABLE); return NETERR_UNREACHABLE; } RteAddRef(rte); } pkt->nexthop = IsRteLocal(rte) ? dstaddr : rte->nexthop; ifp = rte->ifp; if (pkt->datalen > ifp->mtu) { XnetCompletePacket(pkt, NETERR_MSGSIZE); return NETERR_MSGSIZE; } // // Queue up the packet for transmission // We use a very crude priority mechanism here: // - normal packets are added to the end of the queue // - retransmitted packets are added to the front of the queue // if (pkt->pktflags & PKTFLAG_REXMIT) { PktQInsertHead(&ifp->sendq, pkt); } else { PktQInsertTail(&ifp->sendq, pkt); } ifp->StartOutput(ifp); return NETERR_OK; } VOID IpSendPacketInternal( Packet* pkt, IPADDR srcaddr, IPADDR dstaddr, BYTE protocol, IfInfo* ifp ) /*++ Routine Description: Send an IP datagram out on the specified interface. This is called by internal clients such as ICMP and DHCP. Arguments: pkt - Specifies the datagram to be sent srcaddr - Specifies the source address dstaddr - Specifies the destination address protocol - Specifies the protocol number ifp - Points to the outgoing interface Return Value: NONE Note: We assume the pkt->iphdr field points to where the IP header starts. --*/ { RTE* rte = NULL; IpHeader* iphdr; UINT iphdrlen; KIRQL irql; // // Fix up the IP header // iphdr = GETPKTIPHDR(pkt); ASSERT((BYTE*) iphdr < pkt->data); iphdrlen = pkt->data - (BYTE*) iphdr; pkt->data -= iphdrlen; pkt->datalen += iphdrlen; FILL_IPHEADER( iphdr, iphdrlen, cfgDefaultTos, pkt->datalen, 0, cfgDefaultTtl, protocol, srcaddr, dstaddr); irql = RaiseToDpc(); IpSendPacket(pkt, dstaddr, ifp, &rte); if (rte) { IpReleaseCachedRTE(rte); } LowerFromDpc(irql); }