Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

416 lines
9.2 KiB

  1. //=============================================================================
  2. // Copyright (c) 1998 Microsoft Corporation
  3. // File Name: packet.c
  4. // Abstract:
  5. //
  6. // Author: K.S.Lokesh (lokeshs@) 1-1-98
  7. //=============================================================================
  8. #include "pchdvmrp.h"
  9. #pragma hdrstop
  10. VOID
  11. ProcessDvmrpProbe(
  12. PIF_TABLE_ENTRY pite,
  13. UCHAR *Packet,
  14. ULONG PacketSize,
  15. IPADDR SrcAddr
  16. );
  17. VOID
  18. ProcessDvmrpReport(
  19. PIF_TABLE_ENTRY pite,
  20. UCHAR *Packet,
  21. ULONG PacketSize,
  22. IPADDR SrcAddr
  23. );
  24. VOID
  25. ProcessDvmrpPrune(
  26. PIF_TABLE_ENTRY pite,
  27. UCHAR *Packet,
  28. ULONG PacketSize,
  29. IPADDR SrcAddr
  30. );
  31. VOID
  32. ProcessDvmrpGraft(
  33. PIF_TABLE_ENTRY pite,
  34. UCHAR *Packet,
  35. ULONG PacketSize,
  36. IPADDR SrcAddr
  37. );
  38. VOID
  39. ProcessDvmrpGraftAck(
  40. PIF_TABLE_ENTRY pite,
  41. UCHAR *Packet,
  42. ULONG PacketSize,
  43. IPADDR SrcAddr
  44. );
  45. //-----------------------------------------------------------------------------
  46. // _JoinMulticastGroup
  47. //-----------------------------------------------------------------------------
  48. DWORD
  49. JoinMulticastGroup (
  50. SOCKET Sock,
  51. DWORD Group,
  52. DWORD IfIndex,
  53. IPADDR IpAddr
  54. )
  55. {
  56. struct ip_mreq imOption;
  57. DWORD Error = NO_ERROR;
  58. DWORD Retval;
  59. LPSTR lpszGroup = "tobefilled";
  60. LPSTR lpszAddr = "tobefilled";
  61. imOption.imr_multiaddr.s_addr = Group;
  62. imOption.imr_interface.s_addr = IpAddr;
  63. Retval = setsockopt(Sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
  64. (PBYTE)&imOption, sizeof(imOption));
  65. if (Retval == SOCKET_ERROR) {
  66. Error = WSAGetLastError();
  67. Trace4(ERR,
  68. "error %d joining multicast group(%d.%d.%d.%d) on interface "
  69. "(%d) %d.%d.%d.%d",
  70. Error, PRINT_IPADDR(Group), IfIndex, PRINT_IPADDR(IpAddr));
  71. Logerr2(JOIN_GROUP_FAILED, "%s,%s", lpszGroup, lpszAddr, Error);
  72. }
  73. return Error;
  74. }
  75. //-----------------------------------------------------------------------------
  76. // _PostAsyncRecv
  77. //-----------------------------------------------------------------------------
  78. DWORD
  79. PostAsyncRecv(
  80. PIF_TABLE_ENTRY pite
  81. )
  82. {
  83. DWORD Error = NO_ERROR;
  84. PASYNC_SOCKET_DATA pSocketData = pite->pSocketData;
  85. pSocketData->Flags = 0;
  86. pSocketData->FromLen = sizeof(SOCKADDR);
  87. Error = WSARecvFrom(pite->Socket, &pSocketData->WsaBuf, 1,
  88. &pSocketData->NumBytesReceived, &pSocketData->Flags,
  89. (SOCKADDR FAR *)&pSocketData->SrcAddress,
  90. &pSocketData->FromLen, &pSocketData->Overlapped, NULL);
  91. if (Error!=SOCKET_ERROR) {
  92. Trace0(RECEIVE, "the WSAReceiveFrom returned immediately\n");
  93. }
  94. else {
  95. Error = WSAGetLastError();
  96. if (Error!=WSA_IO_PENDING) {
  97. Trace1(RECEIVE,
  98. "WSARecvFrom returned in PostAsyncRecv() with error code:%0x",
  99. Error);
  100. Logerr0(RECVFROM_FAILED, Error);
  101. }
  102. else
  103. Trace0(RECEIVE, "WSARecvFrom() returned WSA_IO_PENDING in ???");
  104. }
  105. return Error;
  106. }
  107. //-----------------------------------------------------------------------------
  108. // _McastSetTtl
  109. // set the ttl value for multicast data. the default ttl for multicast is 1.
  110. //-----------------------------------------------------------------------------
  111. DWORD
  112. McastSetTtl(
  113. SOCKET sock,
  114. UCHAR ttl
  115. )
  116. {
  117. INT dwTtl = ttl;
  118. DWORD Error=NO_ERROR;
  119. Error = setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL,
  120. (char *)&dwTtl, sizeof(dwTtl));
  121. if (Error != 0) {
  122. Error = WSAGetLastError();
  123. Trace1(ERR, "error:%d: unable to set ttl value", Error);
  124. return Error;
  125. }
  126. return Error;
  127. }
  128. //-----------------------------------------------------------------------------
  129. // _ProcessAsyncReceivePacket
  130. //-----------------------------------------------------------------------------
  131. VOID
  132. ProcessAsyncReceivePacket(
  133. DWORD ErrorCode,
  134. DWORD NumBytesRecv,
  135. LPOVERLAPPED pOverlapped
  136. )
  137. {
  138. PASYNC_SOCKET_DATA pSocketData;
  139. DWORD IfIndex, Error;
  140. IPADDR SrcAddr, DstnAddr;
  141. CHAR SrcAddrString[20];
  142. DWORD PacketSize, IpHdrLen;
  143. UCHAR *pPacket;
  144. LPBYTE Buffer;
  145. DVMRP_HEADER UNALIGNED *pDvmrpHdr;
  146. PIF_TABLE_ENTRY pite = NULL;
  147. PIP_HEADER pIpHdr;
  148. UCHAR PacketType;
  149. //
  150. // kslksl
  151. // How to get pite?
  152. //
  153. IfIndex = pite->IfIndex;
  154. //
  155. // if the IO completed due to socket being closed, check if the
  156. // refcount is down to 0, in which case safely delete the pite entry
  157. //
  158. if ( (ErrorCode != NO_ERROR) || (NumBytesRecv == 0)) {
  159. //
  160. // kslksl
  161. //
  162. if (InterlockedDecrement(&pite->RefCount) == 0)
  163. DVMRP_FREE(pite);
  164. return;
  165. }
  166. pSocketData = CONTAINING_RECORD(pOverlapped, ASYNC_SOCKET_DATA,
  167. Overlapped);
  168. //
  169. // get interface read lock
  170. //
  171. ACQUIRE_IF_LOCK_SHARED(pite->IfIndex, "ProcessAsyncReceivePacket");
  172. BEGIN_BREAKOUT_BLOCK1 {
  173. // if interface is not active, then free pite if required and return
  174. if (!IS_IF_ACTIVATED(pite)) {
  175. if (InterlockedDecrement(&pite->RefCount) == 0) {
  176. DVMRP_FREE(pite);
  177. }
  178. Trace1(RECEIVE,
  179. "Received packet on inactive interface:%d", IfIndex);
  180. Error = ERROR_CAN_NOT_COMPLETE;
  181. GOTO_END_BLOCK1;
  182. }
  183. // set source addr of packet
  184. SrcAddr = pSocketData->SrcAddress.sin_addr.s_addr;
  185. lstrcpy(SrcAddrString, INET_NTOA(SrcAddr));
  186. // check that the packet has min length
  187. if (NumBytesRecv < MIN_PACKET_SIZE) {
  188. LPSTR lpszAddr = "<tbd>";
  189. Trace2(RECEIVE,
  190. "Received very short packet of length:%d from:%s",
  191. IfIndex, SrcAddrString);
  192. Logwarn2(PACKET_TOO_SMALL, lpszAddr, SrcAddrString, NO_ERROR);
  193. Error = ERROR_CAN_NOT_COMPLETE;
  194. GOTO_END_BLOCK1;
  195. }
  196. //
  197. // set packet ptr, IpHdr ptr, dwNumBytes, DstnMcastAddr
  198. //
  199. Buffer = pSocketData->WsaBuf.buf;
  200. IpHdrLen = (Buffer[0]&0x0F)*4;
  201. pIpHdr = (PIP_HEADER)Buffer;
  202. pPacket = &Buffer[IpHdrLen];
  203. PacketSize = NumBytesRecv - IpHdrLen;
  204. DstnAddr = (ULONG)pIpHdr->Dstn.s_addr;
  205. pDvmrpHdr = (DVMRP_HEADER UNALIGNED *) pPacket;
  206. //
  207. // verify that the packet has igmp type
  208. //
  209. if (pIpHdr->Protocol!=0x2) {
  210. Trace4(RECEIVE,
  211. "Packet received with IpDstnAddr(%d.%d.%d.%d) from (%s) on "
  212. "interface:%d is not of Igmp type(%d)",
  213. PRINT_IPADDR(pIpHdr->Dstn.s_addr),
  214. SrcAddrString, pite->IfIndex, pIpHdr->Protocol
  215. );
  216. Error = ERROR_CAN_NOT_COMPLETE;
  217. GOTO_END_BLOCK1;
  218. }
  219. //
  220. // verify that the packet has dvmrp type field
  221. //
  222. if ( pDvmrpHdr->Vertype != 0x13) {
  223. Error = ERROR_CAN_NOT_COMPLETE;
  224. GOTO_END_BLOCK1;
  225. }
  226. #if 0
  227. // kslksl
  228. //
  229. // Verify Igmp checksum
  230. //
  231. if (xsum(pDvmrpHdr, sizeof(DVMRP_HEADER)) != 0xffff) {
  232. Trace0(RECEIVE, "Wrong checksum packet received");
  233. GOTO_END_BLOCK1
  234. }
  235. #endif
  236. //
  237. // verify that the packet has correct code
  238. //
  239. PacketType = pDvmrpHdr->Code;
  240. switch (PacketType) {
  241. case DVMRP_PROBE:
  242. {
  243. ProcessDvmrpProbe(pite, pPacket, PacketSize, SrcAddr);
  244. break;
  245. }
  246. case DVMRP_REPORT:
  247. {
  248. ProcessDvmrpReport(pite, pPacket, PacketSize, SrcAddr);
  249. break;
  250. }
  251. case DVMRP_PRUNE:
  252. {
  253. ProcessDvmrpPrune(pite, pPacket, PacketSize, SrcAddr);
  254. break;
  255. }
  256. case DVMRP_GRAFT:
  257. {
  258. ProcessDvmrpGraft(pite, pPacket, PacketSize, SrcAddr);
  259. break;
  260. }
  261. case DVMRP_GRAFT_ACK:
  262. {
  263. ProcessDvmrpGraftAck(pite, pPacket, PacketSize, SrcAddr);
  264. break;
  265. }
  266. }
  267. } END_BREAKOUT_BLOCK1;
  268. PostAsyncRecv(pite);
  269. }//end ProcessAsyncReceive
  270. VOID
  271. ProcessDvmrpProbe(
  272. PIF_TABLE_ENTRY pite,
  273. UCHAR *Packet,
  274. ULONG PacketSize,
  275. IPADDR SrcAddr
  276. )
  277. {
  278. }
  279. VOID
  280. ProcessDvmrpReport(
  281. PIF_TABLE_ENTRY pite,
  282. UCHAR *Packet,
  283. ULONG PacketSize,
  284. IPADDR SrcAddr
  285. )
  286. {
  287. }
  288. VOID
  289. ProcessDvmrpPrune(
  290. PIF_TABLE_ENTRY pite,
  291. UCHAR *Packet,
  292. ULONG PacketSize,
  293. IPADDR SrcAddr
  294. )
  295. {
  296. }
  297. VOID
  298. ProcessDvmrpGraft(
  299. PIF_TABLE_ENTRY pite,
  300. UCHAR *Packet,
  301. ULONG PacketSize,
  302. IPADDR SrcAddr
  303. )
  304. {
  305. }
  306. VOID
  307. ProcessDvmrpGraftAck(
  308. PIF_TABLE_ENTRY pite,
  309. UCHAR *Packet,
  310. ULONG PacketSize,
  311. IPADDR SrcAddr
  312. )
  313. {
  314. }