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.

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