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