PageRenderTime 32ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/src/services/ddsi/code/in_socketMisc.c

https://github.com/xrl/opensplice
C | 454 lines | 320 code | 97 blank | 37 comment | 45 complexity | 5cb30c4defe74013f64935f10c439143 MD5 | raw file
  1. /* interface */
  2. #include "in_socketMisc.h"
  3. /* implemenation */
  4. #include <string.h>
  5. #include "os_heap.h"
  6. #include "os_socket.h"
  7. #include "in_commonTypes.h"
  8. /* 44 octets for IPv6 addresses */
  9. #define IN_INTF_MAX_NAME_LEN (INET6_ADDRSTRLEN)
  10. typedef char in_interfaceName[IN_INTF_MAX_NAME_LEN];
  11. #define SD_FLAG_IS_SET(flags, flag) ((((in_uint)(flags) & (in_uint)(flag))) != 0U)
  12. #if 0
  13. #define IN_ADDRESS(ptr) ((size_t)(ptr))
  14. #define IN_POINTER(address) ((char *)(address))
  15. #endif
  16. /* last seen Socket error, only changes are reported in the errorlog */
  17. os_sockErrno inLastSockError = 0;
  18. /* Helper functions */
  19. /* \brief converts to IPv6 address format
  20. *
  21. * Returns 16 octet vector. Using IPv4-mapping to reprensent
  22. * IPv4 addresses with IPv6 (RFC3493)*/
  23. in_addressType
  24. in_getAddressType(
  25. const char *addressString)
  26. {
  27. in_addressType result = IN_ADDRESS_TYPE_UNKNOWN;
  28. OS_STRUCT(in_address) address;
  29. if (strcmp(addressString, INCF_BROADCAST_EXPR) == 0) {
  30. /* broadcast is available for IPv4 only */
  31. result = IN_ADDRESS_TYPE_BROADCAST;
  32. } else {
  33. /* do not care about return value, 0.0.0.0 will succeed in any case */
  34. in_addressInitFromStringWithDefault(&address, addressString, "0.0.0.0");
  35. result = in_addressGetType(&address);
  36. }
  37. /* POST: result of [IN_ADDRESS_TYPE_UNKNOWN, .., IN_ADDRESS_TYPE_MULTICAST] */
  38. return result;
  39. }
  40. /* interfaceInfo */
  41. struct in_interfaceInfo_s {
  42. in_interfaceName name;
  43. os_ushort flags;
  44. struct sockaddr *primaryAddress;
  45. struct sockaddr *broadcastAddress;
  46. };
  47. static in_interfaceInfo
  48. in_interfaceInfoNew(
  49. const in_interfaceName name,
  50. const os_ushort flags,
  51. const struct sockaddr *primaryAddress,
  52. const struct sockaddr *broadcastAddress)
  53. {
  54. in_interfaceInfo result = NULL;
  55. result = (in_interfaceInfo)os_malloc((os_uint)sizeof(*result));
  56. if (result != NULL) {
  57. /* Copy fields */
  58. memcpy(result->name, name, IN_INTF_MAX_NAME_LEN);
  59. result->name[IN_INTF_MAX_NAME_LEN - 1] = '\0';
  60. result->flags = flags;
  61. if (primaryAddress && ((int)primaryAddress->sa_family == AF_INET)) {
  62. /* Only IPv4 for now */
  63. result->primaryAddress = (struct sockaddr *)os_malloc(
  64. (os_uint)sizeof(struct sockaddr_in));
  65. if (result->primaryAddress) {
  66. memcpy(result->primaryAddress, primaryAddress,
  67. (os_uint)sizeof(struct sockaddr_in));
  68. }
  69. /* If interface supports broadcast, fill bc info */
  70. if (broadcastAddress && SD_FLAG_IS_SET(flags, IFF_BROADCAST)) {
  71. result->broadcastAddress = (struct sockaddr *)os_malloc(
  72. (os_uint)sizeof(struct sockaddr_in));
  73. if (result->broadcastAddress) {
  74. memcpy(result->broadcastAddress, broadcastAddress,
  75. (os_uint)sizeof(struct sockaddr_in));
  76. }
  77. } else {
  78. result->broadcastAddress = NULL;
  79. }
  80. } else {
  81. result->primaryAddress = NULL;
  82. result->broadcastAddress = NULL;
  83. }
  84. }
  85. return result;
  86. }
  87. static void
  88. in_interfaceInfoFree(
  89. in_interfaceInfo interfaceInfo)
  90. {
  91. if (interfaceInfo != NULL) {
  92. if (interfaceInfo->primaryAddress) {
  93. os_free(interfaceInfo->primaryAddress);
  94. }
  95. if (interfaceInfo->broadcastAddress) {
  96. os_free(interfaceInfo->broadcastAddress);
  97. }
  98. os_free(interfaceInfo);
  99. }
  100. }
  101. /* ------------------------------- Callbacks -------------------------------- */
  102. static void
  103. in_interfaceWalkCountBC(
  104. os_ifAttributes *intf,
  105. os_socket sockfd,
  106. void *actionArg)
  107. {
  108. unsigned int *count = (unsigned int *)actionArg;
  109. (void)intf;
  110. (void)sockfd;
  111. /* Only interested in broadcast-enabled interfaces for now */
  112. if (SD_FLAG_IS_SET(intf->flags, IFF_BROADCAST)) {
  113. (*count)++;
  114. }
  115. }
  116. static void
  117. in_interfaceWalkFillBC(
  118. os_ifAttributes *intf,
  119. os_socket sockfd,
  120. void *actionArg)
  121. {
  122. in_interfaceInfo **interfaceInfo = (in_interfaceInfo **)actionArg;
  123. if (SD_FLAG_IS_SET(intf->flags, IFF_BROADCAST)) {
  124. **interfaceInfo = in_interfaceInfoNew(intf->name, intf->flags,
  125. &intf->address, &intf->broadcast_address);
  126. /* (*interfaceInfo)++ not allowed by QAC */
  127. *interfaceInfo = &((*interfaceInfo)[1]);
  128. }
  129. }
  130. static void
  131. in_interfaceWalkCountMC(
  132. os_ifAttributes *intf,
  133. os_socket sockfd,
  134. void *actionArg)
  135. {
  136. unsigned int *count = (unsigned int *)actionArg;
  137. (void)intf;
  138. (void)sockfd;
  139. /* Only interested in multicast-enabled interfaces for now */
  140. if (SD_FLAG_IS_SET(intf->flags, IFF_MULTICAST) &&
  141. !SD_FLAG_IS_SET(intf->flags, IFF_LOOPBACK)) {
  142. (*count)++;
  143. }
  144. }
  145. static void
  146. in_interfaceWalkFillMC(
  147. os_ifAttributes *intf,
  148. os_socket sockfd,
  149. void *actionArg)
  150. {
  151. in_interfaceInfo **interfaceInfo = (in_interfaceInfo **)actionArg;
  152. struct sockaddr *broadaddr;
  153. if (SD_FLAG_IS_SET(intf->flags, IFF_MULTICAST) &&
  154. !SD_FLAG_IS_SET(intf->flags, IFF_LOOPBACK)) {
  155. if (SD_FLAG_IS_SET(intf->flags, IFF_BROADCAST)) {
  156. broadaddr = &intf->broadcast_address;
  157. } else {
  158. broadaddr = NULL;
  159. }
  160. **interfaceInfo = in_interfaceInfoNew(intf->name, intf->flags,
  161. &intf->address, broadaddr);
  162. /* (*interfaceInfo)++ not allowed by QAC */
  163. *interfaceInfo = &((*interfaceInfo)[1]);
  164. }
  165. }
  166. static void
  167. in_interfaceWalkCountLoopback(
  168. os_ifAttributes *intf,
  169. os_socket sockfd,
  170. void *actionArg)
  171. {
  172. unsigned int *count = (unsigned int *)actionArg;
  173. /* Only interested in broadcast-enabled interfaces for now */
  174. if (SD_FLAG_IS_SET(intf->flags, IFF_LOOPBACK)) {
  175. (*count)++;
  176. }
  177. }
  178. static void
  179. in_interfaceWalkFillLoopback(
  180. os_ifAttributes *intf,
  181. os_socket sockfd,
  182. void *actionArg)
  183. {
  184. in_interfaceInfo **interfaceInfo = (in_interfaceInfo **)actionArg;
  185. (void)sockfd;
  186. if (SD_FLAG_IS_SET(intf->flags, IFF_LOOPBACK)) {
  187. **interfaceInfo = in_interfaceInfoNew(intf->name, intf->flags,
  188. &intf->address, NULL);
  189. /* (*interfaceInfo)++ not allowed by QAC */
  190. *interfaceInfo = &((*interfaceInfo)[1]);
  191. }
  192. }
  193. /* -------------------------------------------------------------------------- */
  194. /* ------------------- Interface retrieval and walk over -------------------- */
  195. #define MAX_INTERFACES 64
  196. typedef void (*in_interfaceWalkFunc)(
  197. os_ifAttributes *intf,
  198. os_socket sockfd,
  199. void *actionArg);
  200. static void
  201. in_interfaceIPv4Walk(
  202. os_ifAttributes *allInterfaces,
  203. os_uint nofInterfaces,
  204. os_socket sockfd,
  205. const in_interfaceWalkFunc action,
  206. void *actionArg)
  207. {
  208. os_uint currentInterface = 0;
  209. if (action) {
  210. while (currentInterface < nofInterfaces) {
  211. if (SD_FLAG_IS_SET(allInterfaces[currentInterface].flags, IFF_UP)) {
  212. action(&allInterfaces[currentInterface], sockfd, actionArg);
  213. currentInterface++;
  214. }
  215. }
  216. }
  217. }
  218. #undef IN_MAX
  219. os_result
  220. in_interfaceInfoRetrieveAllBC(
  221. in_interfaceInfo **interfaceList /* [nofInterfaces */,
  222. os_uint *nofInterfaces,
  223. os_socket sockfd)
  224. {
  225. os_result result;
  226. os_ifAttributes ifList[MAX_INTERFACES];
  227. os_uint nofIf = 0;
  228. in_interfaceInfo *interfaceHelper;
  229. *interfaceList = NULL;
  230. *nofInterfaces = 0;
  231. result = os_sockQueryInterfaces(&ifList[0], (os_uint)MAX_INTERFACES, &nofIf);
  232. if (result == os_resultSuccess) {
  233. /* Count the number of valid interfaces */
  234. in_interfaceIPv4Walk(ifList, nofIf, sockfd,
  235. in_interfaceWalkCountBC, nofInterfaces);
  236. /* Number of IPv4 addresses known, now fill them */
  237. *interfaceList = (in_interfaceInfo *)os_malloc(
  238. (*nofInterfaces) * (os_uint)sizeof(*interfaceList));
  239. /* Fill the interface info structures */
  240. interfaceHelper = *interfaceList;
  241. in_interfaceIPv4Walk(ifList, nofIf, sockfd,
  242. in_interfaceWalkFillBC, &interfaceHelper);
  243. }
  244. return nofIf;
  245. }
  246. os_result
  247. in_interfaceInfoRetrieveAllMC(
  248. in_interfaceInfo **interfaceList /* [nofInterfaces */,
  249. os_uint *nofInterfaces,
  250. os_socket sockfd)
  251. {
  252. os_result result;
  253. os_ifAttributes ifList[MAX_INTERFACES];
  254. os_uint nofIf;
  255. in_interfaceInfo *interfaceHelper;
  256. *interfaceList = NULL;
  257. *nofInterfaces = 0;
  258. result = os_sockQueryInterfaces(&ifList[0], (os_uint)MAX_INTERFACES, &nofIf);
  259. if (result == os_resultSuccess) {
  260. /* Count the number of valid interfaces */
  261. in_interfaceIPv4Walk(ifList, nofIf, sockfd,
  262. in_interfaceWalkCountMC, nofInterfaces);
  263. /* Number of IPv4 addresses known, now fill them */
  264. *interfaceList = (in_interfaceInfo *)os_malloc(
  265. (*nofInterfaces) * (os_uint)sizeof(*interfaceList));
  266. /* Fill the interface info structures */
  267. interfaceHelper = *interfaceList;
  268. in_interfaceIPv4Walk(ifList, nofIf, sockfd,
  269. in_interfaceWalkFillMC, &interfaceHelper);
  270. }
  271. return nofIf;
  272. }
  273. os_result
  274. in_interfaceInfoRetrieveAllLoopback(
  275. in_interfaceInfo **interfaceList /* [nofInterfaces */,
  276. os_uint *nofInterfaces,
  277. os_socket sockfd)
  278. {
  279. os_result result;
  280. os_ifAttributes ifList[MAX_INTERFACES];
  281. os_uint nofIf;
  282. in_interfaceInfo *interfaceHelper;
  283. *interfaceList = NULL;
  284. *nofInterfaces = 0;
  285. result = os_sockQueryInterfaces(&ifList[0], (os_uint)MAX_INTERFACES, &nofIf);
  286. if (result == os_resultSuccess) {
  287. /* Count the number of valid interfaces */
  288. in_interfaceIPv4Walk(ifList, nofIf, sockfd,
  289. in_interfaceWalkCountLoopback, nofInterfaces);
  290. /* Number of IPv4 addresses known, now fill them */
  291. *interfaceList = (in_interfaceInfo *)os_malloc(
  292. (*nofInterfaces) * (os_uint)sizeof(*interfaceList));
  293. /* Fill the interface info structures */
  294. interfaceHelper = *interfaceList;
  295. in_interfaceIPv4Walk(ifList, nofIf, sockfd,
  296. in_interfaceWalkFillLoopback, &interfaceHelper);
  297. }
  298. return nofIf;
  299. }
  300. /* -------------------------------------------------------------------------- */
  301. /* ---------------------- Interface info members and getters ---------------- */
  302. void
  303. in_interfaceInfoFreeAll(
  304. in_interfaceInfo *interfaceList /* [nofInterfaces */,
  305. os_uint nofInterfaces)
  306. {
  307. os_uint i;
  308. if (interfaceList) {
  309. for (i=0; i<nofInterfaces; i++) {
  310. in_interfaceInfoFree(interfaceList[i]);
  311. }
  312. os_free(interfaceList);
  313. }
  314. }
  315. char *
  316. in_interfaceInfoGetName(
  317. const in_interfaceInfo interfaceInfo)
  318. {
  319. char *result = NULL;
  320. if (interfaceInfo != NULL) {
  321. result = interfaceInfo->name;
  322. }
  323. return result;
  324. }
  325. #if 0
  326. /* Currently not used */
  327. unsigned short
  328. in_interfaceInfoGetFlags(
  329. const in_interfaceInfo interfaceInfo)
  330. {
  331. short result = 0;
  332. if (interface) {
  333. result = interfaceInfo->flags;
  334. }
  335. return result;
  336. }
  337. #endif
  338. struct sockaddr *
  339. in_interfaceInfoGetPrimaryAddress(
  340. const in_interfaceInfo interfaceInfo)
  341. {
  342. struct sockaddr *result = NULL;
  343. if (interfaceInfo != NULL) {
  344. result = interfaceInfo->primaryAddress;
  345. }
  346. return result;
  347. }
  348. struct sockaddr *
  349. in_interfaceInfoGetBroadcastAddress(
  350. const in_interfaceInfo interfaceInfo)
  351. {
  352. struct sockaddr *result = NULL;
  353. if (interfaceInfo != NULL) {
  354. result = interfaceInfo->broadcastAddress;
  355. }
  356. return result;
  357. }