xbox-kernel/private/ntos/xnet/ip/ipsend.c
2020-09-30 17:17:25 +02:00

177 lines
3.4 KiB
C

/*++
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);
}