[NTOS:KE/x64] Handle NMI vs swapgs race condition
[reactos.git] / sdk / lib / drivers / ip / transport / tcp / if.c
1
2 #include "precomp.h"
3
4 #include "lwip/pbuf.h"
5 #include "lwip/netifapi.h"
6 #include "lwip/ip.h"
7 #include "lwip/api.h"
8 #include "lwip/tcpip.h"
9
10 err_t
11 TCPSendDataCallback(struct netif *netif, struct pbuf *p, struct ip_addr *dest)
12 {
13 NDIS_STATUS NdisStatus;
14 PNEIGHBOR_CACHE_ENTRY NCE;
15 IP_PACKET Packet;
16 IP_ADDRESS RemoteAddress, LocalAddress;
17 PIPv4_HEADER Header;
18 ULONG Length;
19 ULONG TotalLength;
20
21 /* The caller frees the pbuf struct */
22
23 if (((*(u8_t*)p->payload) & 0xF0) == 0x40)
24 {
25 Header = p->payload;
26
27 LocalAddress.Type = IP_ADDRESS_V4;
28 LocalAddress.Address.IPv4Address = Header->SrcAddr;
29
30 RemoteAddress.Type = IP_ADDRESS_V4;
31 RemoteAddress.Address.IPv4Address = Header->DstAddr;
32 }
33 else
34 {
35 return ERR_IF;
36 }
37
38 IPInitializePacket(&Packet, LocalAddress.Type);
39
40 if (!(NCE = RouteGetRouteToDestination(&RemoteAddress)))
41 {
42 return ERR_RTE;
43 }
44
45 NdisStatus = AllocatePacketWithBuffer(&Packet.NdisPacket, NULL, p->tot_len);
46 if (NdisStatus != NDIS_STATUS_SUCCESS)
47 {
48 return ERR_MEM;
49 }
50
51 GetDataPtr(Packet.NdisPacket, 0, (PCHAR*)&Packet.Header, &Packet.TotalSize);
52 Packet.MappedHeader = TRUE;
53
54 ASSERT(Packet.TotalSize == p->tot_len);
55
56 TotalLength = p->tot_len;
57 Length = 0;
58 while (Length < TotalLength)
59 {
60 ASSERT(p->len <= TotalLength - Length);
61 ASSERT(p->tot_len == TotalLength - Length);
62 RtlCopyMemory((PCHAR)Packet.Header + Length, p->payload, p->len);
63 Length += p->len;
64 p = p->next;
65 }
66 ASSERT(Length == TotalLength);
67
68 Packet.HeaderSize = sizeof(IPv4_HEADER);
69 Packet.TotalSize = TotalLength;
70 Packet.SrcAddr = LocalAddress;
71 Packet.DstAddr = RemoteAddress;
72
73 NdisStatus = IPSendDatagram(&Packet, NCE);
74 if (!NT_SUCCESS(NdisStatus))
75 return ERR_RTE;
76
77 return 0;
78 }
79
80 VOID
81 TCPUpdateInterfaceLinkStatus(PIP_INTERFACE IF)
82 {
83 #if 0
84 ULONG OperationalStatus;
85
86 GetInterfaceConnectionStatus(IF, &OperationalStatus);
87
88 if (OperationalStatus == MIB_IF_OPER_STATUS_OPERATIONAL)
89 netif_set_link_up(IF->TCPContext);
90 else
91 netif_set_link_down(IF->TCPContext);
92 #endif
93 }
94
95 err_t
96 TCPInterfaceInit(struct netif *netif)
97 {
98 PIP_INTERFACE IF = netif->state;
99
100 netif->hwaddr_len = IF->AddressLength;
101 RtlCopyMemory(netif->hwaddr, IF->Address, netif->hwaddr_len);
102
103 netif->output = TCPSendDataCallback;
104 netif->mtu = IF->MTU;
105
106 netif->name[0] = 'e';
107 netif->name[1] = 'n';
108
109 netif->flags |= NETIF_FLAG_BROADCAST;
110
111 TCPUpdateInterfaceLinkStatus(IF);
112
113 TCPUpdateInterfaceIPInformation(IF);
114
115 return 0;
116 }
117
118 VOID
119 TCPRegisterInterface(PIP_INTERFACE IF)
120 {
121 struct ip_addr ipaddr;
122 struct ip_addr netmask;
123 struct ip_addr gw;
124
125 gw.addr = 0;
126 ipaddr.addr = 0;
127 netmask.addr = 0;
128
129 IF->TCPContext = netif_add(IF->TCPContext,
130 &ipaddr,
131 &netmask,
132 &gw,
133 IF,
134 TCPInterfaceInit,
135 tcpip_input);
136 }
137
138 VOID
139 TCPUnregisterInterface(PIP_INTERFACE IF)
140 {
141 netif_remove(IF->TCPContext);
142 }
143
144 VOID
145 TCPUpdateInterfaceIPInformation(PIP_INTERFACE IF)
146 {
147 struct ip_addr ipaddr;
148 struct ip_addr netmask;
149 struct ip_addr gw;
150
151 gw.addr = 0;
152
153 GetInterfaceIPv4Address(IF,
154 ADE_UNICAST,
155 (PULONG)&ipaddr.addr);
156
157 GetInterfaceIPv4Address(IF,
158 ADE_ADDRMASK,
159 (PULONG)&netmask.addr);
160
161 netif_set_addr(IF->TCPContext, &ipaddr, &netmask, &gw);
162
163 if (ipaddr.addr != 0)
164 {
165 netif_set_up(IF->TCPContext);
166 netif_set_default(IF->TCPContext);
167 }
168 else
169 {
170 netif_set_down(IF->TCPContext);
171 }
172 }