Leaked source code of windows server 2003
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.

659 lines
15 KiB

  1. /*++
  2. Copyright (c) 1992-1997 Microsoft Corporation
  3. Module Name:
  4. network.c
  5. Abstract:
  6. Contains routines for manipulating transport structures.
  7. Environment:
  8. User Mode - Win32
  9. Revision History:
  10. 10-Feb-1997 DonRyan
  11. Rewrote to implement SNMPv2 support.
  12. --*/
  13. ///////////////////////////////////////////////////////////////////////////////
  14. // //
  15. // Include files //
  16. // //
  17. ///////////////////////////////////////////////////////////////////////////////
  18. #include "globals.h"
  19. #include "network.h"
  20. #include "varbinds.h"
  21. #include "query.h"
  22. ///////////////////////////////////////////////////////////////////////////////
  23. // //
  24. // Public procedures //
  25. // //
  26. ///////////////////////////////////////////////////////////////////////////////
  27. BOOL
  28. IsValidSockAddr(
  29. struct sockaddr *pAddress
  30. )
  31. /*++
  32. Routine Description:
  33. Verifies if an IP or IPX address is valid.
  34. An IP address is valid if it is AF_INET and it is not 0.0.0.0
  35. An IPX address is valid if is AF_IPX and the node-number is not null: xxxxxx.000000000000
  36. Arguments:
  37. pAddress - pointer to a generic network address to be tested
  38. Return Values:
  39. Returns true if the address is valid.
  40. --*/
  41. {
  42. if (pAddress == NULL)
  43. return FALSE;
  44. if (pAddress->sa_family == AF_INET)
  45. {
  46. return (((struct sockaddr_in *)pAddress)->sin_addr.s_addr != 0);
  47. }
  48. else if (pAddress->sa_family == AF_IPX)
  49. {
  50. char zeroBuff[6] = {0, 0, 0, 0, 0, 0};
  51. return memcmp(((struct sockaddr_ipx *)pAddress)->sa_nodenum,
  52. zeroBuff,
  53. sizeof(zeroBuff)) != 0;
  54. }
  55. // the address is neither IP nor IPX hence it is definitely an invalid address
  56. return FALSE;
  57. }
  58. BOOL
  59. AllocNLE(
  60. PNETWORK_LIST_ENTRY * ppNLE
  61. )
  62. /*++
  63. Routine Description:
  64. Allocates transport structure and initializes.
  65. Arguments:
  66. ppNLE - pointer to receive pointer to list entry.
  67. Return Values:
  68. Returns true if successful.
  69. --*/
  70. {
  71. BOOL fOk = FALSE;
  72. PNETWORK_LIST_ENTRY pNLE;
  73. // attempt to allocate structure
  74. pNLE = AgentMemAlloc(sizeof(NETWORK_LIST_ENTRY));
  75. // validate pointer
  76. if (pNLE != NULL) {
  77. // allocate buffer to be used for io
  78. pNLE->Buffer.buf = AgentMemAlloc(NLEBUFLEN);
  79. // validate pointer
  80. if (pNLE->Buffer.buf != NULL) {
  81. // initialize socket to socket
  82. pNLE->Socket = INVALID_SOCKET;
  83. // initialize buffer length
  84. pNLE->Buffer.len = NLEBUFLEN;
  85. // initialize subagent query list
  86. InitializeListHead(&pNLE->Queries);
  87. // initialize variable bindings list
  88. InitializeListHead(&pNLE->Bindings);
  89. // success
  90. fOk = TRUE;
  91. } else {
  92. SNMPDBG((
  93. SNMP_LOG_ERROR,
  94. "SNMP: SVC: could not allocate network io buffer.\n"
  95. ));
  96. // release
  97. FreeNLE(pNLE);
  98. // re-init
  99. pNLE = NULL;
  100. }
  101. } else {
  102. SNMPDBG((
  103. SNMP_LOG_ERROR,
  104. "SNMP: SVC: could not allocate network entry.\n"
  105. ));
  106. }
  107. // transfer
  108. *ppNLE = pNLE;
  109. return fOk;
  110. }
  111. BOOL
  112. FreeNLE(
  113. PNETWORK_LIST_ENTRY pNLE
  114. )
  115. /*++
  116. Routine Description:
  117. Releases transport structure.
  118. Arguments:
  119. pNLE - pointer to transport structure.
  120. Return Values:
  121. Returns true if successful.
  122. --*/
  123. {
  124. // validate pointer
  125. if (pNLE != NULL) {
  126. // check to see if socket valid
  127. if (pNLE->Socket != INVALID_SOCKET) {
  128. // release socket
  129. closesocket(pNLE->Socket);
  130. }
  131. // release pdu
  132. UnloadPdu(pNLE);
  133. // release query list
  134. UnloadQueries(pNLE);
  135. // release bindings list
  136. UnloadVarBinds(pNLE);
  137. // release network buffer
  138. AgentMemFree(pNLE->Buffer.buf);
  139. // release memory
  140. AgentMemFree(pNLE);
  141. }
  142. return TRUE;
  143. }
  144. BOOL
  145. LoadIncomingTransports(
  146. )
  147. /*++
  148. Routine Description:
  149. Creates entries for each incoming interface.
  150. Arguments:
  151. None.
  152. Return Values:
  153. Returns true if successful.
  154. --*/
  155. {
  156. BOOL fUdpOk = FALSE;
  157. BOOL fIpxOk = FALSE;
  158. PNETWORK_LIST_ENTRY pNLE = NULL;
  159. INT nStatus;
  160. // allocate tcpip
  161. if (AllocNLE(&pNLE)) {
  162. struct servent * pServEnt;
  163. struct sockaddr_in * pSockAddr;
  164. // initialize sockaddr structure size
  165. pNLE->SockAddrLen = sizeof(struct sockaddr_in);
  166. // obtain pointer to sockaddr structure
  167. pSockAddr = (struct sockaddr_in *)&pNLE->SockAddr;
  168. // attempt to get server information
  169. pServEnt = getservbyname("snmp","udp");
  170. // initialize address structure
  171. pSockAddr->sin_family = AF_INET;
  172. pSockAddr->sin_addr.s_addr = INADDR_ANY;
  173. pSockAddr->sin_port = (pServEnt != NULL)
  174. ? (SHORT)pServEnt->s_port
  175. : htons(DEFAULT_SNMP_PORT_UDP)
  176. ;
  177. // allocate tpcip socket
  178. pNLE->Socket = WSASocket(
  179. AF_INET,
  180. SOCK_DGRAM,
  181. 0,
  182. NULL,
  183. 0,
  184. WSA_FLAG_OVERLAPPED
  185. );
  186. // validate socket
  187. if (pNLE->Socket != INVALID_SOCKET) {
  188. // BUG# 553100 SNMP Agent should not respond to requests to a
  189. // subnet broadcast address
  190. DWORD dwOption = 0;
  191. nStatus = setsockopt(pNLE->Socket,
  192. IPPROTO_IP,
  193. IP_RECEIVE_BROADCAST,
  194. (PCHAR)&dwOption,
  195. sizeof(dwOption)
  196. );
  197. if (nStatus == SOCKET_ERROR) {
  198. SNMPDBG((
  199. SNMP_LOG_WARNING,
  200. "SNMP: SVC: ignore error %d, setsockopt with IP_RECEIVE_BROADCAST on socket %p.\n",
  201. WSAGetLastError(),
  202. pNLE->Socket
  203. ));
  204. }
  205. // attempt to bind
  206. nStatus = bind(pNLE->Socket,
  207. &pNLE->SockAddr,
  208. pNLE->SockAddrLen
  209. );
  210. // validate return code
  211. if (nStatus != SOCKET_ERROR) {
  212. SNMPDBG((
  213. SNMP_LOG_TRACE,
  214. "SNMP: SVC: successfully bound to udp port %d.\n",
  215. ntohs(pSockAddr->sin_port)
  216. ));
  217. // insert transport into list of incoming
  218. InsertTailList(&g_IncomingTransports, &pNLE->Link);
  219. // success
  220. fUdpOk = TRUE;
  221. } else {
  222. SNMPDBG((
  223. SNMP_LOG_ERROR,
  224. "SNMP: SVC: error %d binding to udp port %d.\n",
  225. WSAGetLastError(),
  226. ntohs(pSockAddr->sin_port)
  227. ));
  228. }
  229. } else {
  230. SNMPDBG((
  231. SNMP_LOG_WARNING,
  232. "SNMP: SVC: error %d creating udp socket.\n",
  233. WSAGetLastError()
  234. ));
  235. }
  236. if (!fUdpOk) {
  237. // release
  238. FreeNLE(pNLE);
  239. }
  240. }
  241. // allocate ipx
  242. if (AllocNLE(&pNLE)) {
  243. struct sockaddr_ipx * pSockAddr;
  244. // initialize sockaddr structure size
  245. pNLE->SockAddrLen = sizeof(struct sockaddr_ipx);
  246. // obtain pointer to sockaddr structure
  247. pSockAddr = (struct sockaddr_ipx *)&pNLE->SockAddr;
  248. // initialize address structure
  249. pSockAddr->sa_family = AF_IPX;
  250. pSockAddr->sa_socket = htons(DEFAULT_SNMP_PORT_IPX);
  251. // allocate ipx socket
  252. pNLE->Socket = WSASocket(
  253. AF_IPX,
  254. SOCK_DGRAM,
  255. NSPROTO_IPX,
  256. NULL,
  257. 0,
  258. WSA_FLAG_OVERLAPPED
  259. );
  260. // validate socket
  261. if (pNLE->Socket != INVALID_SOCKET) {
  262. // attempt to bind
  263. nStatus = bind(pNLE->Socket,
  264. &pNLE->SockAddr,
  265. pNLE->SockAddrLen
  266. );
  267. // validate return code
  268. if (nStatus != SOCKET_ERROR) {
  269. SNMPDBG((
  270. SNMP_LOG_TRACE,
  271. "SNMP: SVC: successfully bound to ipx port %d.\n",
  272. ntohs(pSockAddr->sa_socket)
  273. ));
  274. // insert transport into list of incoming
  275. InsertTailList(&g_IncomingTransports, &pNLE->Link);
  276. // success
  277. fIpxOk = TRUE;
  278. } else {
  279. SNMPDBG((
  280. SNMP_LOG_ERROR,
  281. "SNMP: SVC: error %d binding to ipx port %d.\n",
  282. WSAGetLastError(),
  283. ntohs(pSockAddr->sa_socket)
  284. ));
  285. }
  286. } else {
  287. SNMPDBG((
  288. SNMP_LOG_WARNING,
  289. "SNMP: SVC: error %d creating ipx socket.\n",
  290. WSAGetLastError()
  291. ));
  292. }
  293. if (!fIpxOk) {
  294. // release
  295. FreeNLE(pNLE);
  296. }
  297. }
  298. // need one transport min
  299. return (fUdpOk || fIpxOk);
  300. }
  301. BOOL
  302. UnloadTransport(
  303. PNETWORK_LIST_ENTRY pNLE
  304. )
  305. {
  306. // make sure the parameter is valid, otherwise the macro below AVs
  307. if (pNLE == NULL)
  308. return FALSE;
  309. // remove the entry from the list
  310. RemoveEntryList(&(pNLE->Link));
  311. // release the memory
  312. FreeNLE(pNLE);
  313. return TRUE;
  314. }
  315. BOOL
  316. UnloadIncomingTransports(
  317. )
  318. /*++
  319. Routine Description:
  320. Destroys entries for each outgoing interface.
  321. Arguments:
  322. None.
  323. Return Values:
  324. Returns true if successful.
  325. --*/
  326. {
  327. PLIST_ENTRY pLE;
  328. PNETWORK_LIST_ENTRY pNLE;
  329. // process entries until empty
  330. while (!IsListEmpty(&g_IncomingTransports)) {
  331. // extract next entry from head
  332. pLE = RemoveHeadList(&g_IncomingTransports);
  333. // retrieve pointer to mib region structure
  334. pNLE = CONTAINING_RECORD(pLE, NETWORK_LIST_ENTRY, Link);
  335. // release
  336. FreeNLE(pNLE);
  337. }
  338. return TRUE;
  339. }
  340. BOOL
  341. LoadOutgoingTransports(
  342. )
  343. /*++
  344. Routine Description:
  345. Creates entries for each outgoing interface.
  346. Arguments:
  347. None.
  348. Return Values:
  349. Returns true if successful.
  350. --*/
  351. {
  352. BOOL fUdpOk = FALSE;
  353. BOOL fIpxOk = FALSE;
  354. PNETWORK_LIST_ENTRY pNLE = NULL;
  355. // allocate tcpip
  356. if (AllocNLE(&pNLE)) {
  357. // allocate tpcip socket
  358. pNLE->Socket = WSASocket(
  359. AF_INET,
  360. SOCK_DGRAM,
  361. 0,
  362. NULL,
  363. 0,
  364. WSA_FLAG_OVERLAPPED
  365. );
  366. // validate socket
  367. if (pNLE->Socket != INVALID_SOCKET) {
  368. pNLE->SockAddr.sa_family = AF_INET;
  369. // insert transport into list of incoming
  370. InsertTailList(&g_OutgoingTransports, &pNLE->Link);
  371. // success
  372. fUdpOk = TRUE;
  373. } else {
  374. SNMPDBG((
  375. SNMP_LOG_WARNING,
  376. "SNMP: SVC: error %d creating udp socket.\n",
  377. WSAGetLastError()
  378. ));
  379. // release
  380. FreeNLE(pNLE);
  381. }
  382. }
  383. // allocate ipx
  384. if (AllocNLE(&pNLE)) {
  385. // allocate ipx socket
  386. pNLE->Socket = WSASocket(
  387. AF_IPX,
  388. SOCK_DGRAM,
  389. NSPROTO_IPX,
  390. NULL,
  391. 0,
  392. WSA_FLAG_OVERLAPPED
  393. );
  394. // validate socket
  395. if (pNLE->Socket != INVALID_SOCKET) {
  396. pNLE->SockAddr.sa_family = AF_IPX;
  397. // insert transport into list of incoming
  398. InsertTailList(&g_OutgoingTransports, &pNLE->Link);
  399. // success
  400. fIpxOk = TRUE;
  401. } else {
  402. SNMPDBG((
  403. SNMP_LOG_WARNING,
  404. "SNMP: SVC: error %d creating ipx socket.\n",
  405. WSAGetLastError()
  406. ));
  407. // release
  408. FreeNLE(pNLE);
  409. }
  410. }
  411. // need one transport min
  412. return (fUdpOk || fIpxOk);
  413. }
  414. BOOL
  415. UnloadOutgoingTransports(
  416. )
  417. /*++
  418. Routine Description:
  419. Destroys entries for each outgoing interface.
  420. Arguments:
  421. None.
  422. Return Values:
  423. Returns true if successful.
  424. --*/
  425. {
  426. PLIST_ENTRY pLE;
  427. PNETWORK_LIST_ENTRY pNLE;
  428. // process entries until empty
  429. while (!IsListEmpty(&g_OutgoingTransports)) {
  430. // extract next entry from head
  431. pLE = RemoveHeadList(&g_OutgoingTransports);
  432. // retrieve pointer to mib region structure
  433. pNLE = CONTAINING_RECORD(pLE, NETWORK_LIST_ENTRY, Link);
  434. // release
  435. FreeNLE(pNLE);
  436. }
  437. return TRUE;
  438. }
  439. BOOL
  440. UnloadPdu(
  441. PNETWORK_LIST_ENTRY pNLE
  442. )
  443. /*++
  444. Routine Description:
  445. Releases resources allocated in pdu structure.
  446. Arguments:
  447. pNLE - pointer to network list entry.
  448. Return Values:
  449. Returns true if successful.
  450. --*/
  451. {
  452. // release community string
  453. SnmpUtilOctetsFree(&pNLE->Community);
  454. // release varbinds in pdu
  455. SnmpUtilVarBindListFree(&pNLE->Pdu.Vbl);
  456. return TRUE;
  457. }