aes.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*****************************************************************
  2. ******************************************************************
  3. *** ***
  4. *** (C)Copyright 2012, American Megatrends Inc. ***
  5. *** ***
  6. *** All Rights Reserved ***
  7. *** ***
  8. *** 5555 Oakbrook Parkway, Norcross, GA 30093, USA ***
  9. *** ***
  10. *** Phone 770.246.8600 ***
  11. *** ***
  12. ******************************************************************
  13. ******************************************************************
  14. ******************************************************************
  15. *
  16. * Filename: aes.c
  17. *
  18. * Descriptions: Code that connects to AES engine and sends any
  19. * new SEL event generated
  20. *
  21. *
  22. * Author: Manish Tomar (manisht@ami.com)
  23. *
  24. ******************************************************************/
  25. #include <sys/types.h>
  26. #include <sys/un.h>
  27. #include <sys/socket.h>
  28. #include <errno.h>
  29. #include <unistd.h>
  30. #include <fcntl.h>
  31. #include <poll.h>
  32. #include <string.h>
  33. #include <stdio.h>
  34. #include "aes.h"
  35. #include "featuredef.h"
  36. #define AES_PATH "/tmp/aesevents"
  37. #define MAX_TRIES 3
  38. static int _g_tries = 0;
  39. static int _connect()
  40. {
  41. int sock = -1, ret;
  42. int flags;
  43. int optval = -1;
  44. socklen_t optlen = sizeof(optval);
  45. char *errstr, errbuf[128];
  46. struct sockaddr_un addr;
  47. struct pollfd pfd = { 0 };
  48. //errno = 0;
  49. // create socket
  50. addr.sun_family = AF_UNIX;
  51. strncpy(addr.sun_path, AES_PATH, sizeof(addr.sun_path));
  52. sock = socket(AF_UNIX, SOCK_STREAM, 0);
  53. if (sock == -1) {
  54. errstr = "error creating Unix Socket";
  55. goto error;
  56. }
  57. // set non-block
  58. flags = fcntl(sock, F_GETFL, 0);
  59. fcntl(sock, F_SETFL, flags | O_NONBLOCK);
  60. // connect it
  61. if (0 == connect(sock, (struct sockaddr *)&addr, sizeof(addr))) {
  62. return sock;
  63. }
  64. // connection failed. wait if in progress
  65. if (errno != EINPROGRESS) {
  66. errstr = "Connect failed";
  67. goto error;
  68. }
  69. // Wait for max of 5 milliseconds
  70. pfd.fd = sock;
  71. pfd.events = POLLOUT;
  72. if (-1 == (ret = poll(&pfd, 1, 5))) {
  73. errstr = "Error polling";
  74. goto error;
  75. }
  76. if (ret == 0) {
  77. errstr = "poll timed out";
  78. goto error;
  79. }
  80. if (ret != 1) {
  81. errstr = "unexpected poll return";
  82. goto error;
  83. }
  84. if (!(pfd.revents & POLLOUT)) {
  85. errstr = "unexected event on fd";
  86. goto error;
  87. }
  88. if (-1 == getsockopt(sock, SOL_SOCKET, SO_ERROR, &optval, &optlen)) {
  89. errstr = "error from getsockopt";
  90. goto error;
  91. }
  92. if (optval != 0) {
  93. errstr = "error connecting to aes";
  94. goto error;
  95. }
  96. return sock;
  97. error:
  98. memset(errbuf, 0, sizeof(errbuf));
  99. strerror_r(errno, errbuf, sizeof(errbuf));
  100. fprintf(stderr, "%s: %s\n", errstr, errbuf);
  101. if (sock != -1)
  102. close(sock);
  103. return -1;
  104. }
  105. int AES_SendEvent(SELEventRecord_T *event)
  106. {
  107. static int sock = -1; // UDS connected socket
  108. static int enabled = -1;
  109. ssize_t sent;
  110. // check if AES is enabled in stack
  111. if (enabled == -1) {
  112. enabled = IsFeatureEnabled("CONFIG_SPX_FEATURE_AUTOMATION_ENGINE");
  113. }
  114. if (!enabled)
  115. return 0;
  116. resend:
  117. if (sock == -1) {
  118. // First time called. Make UDS connection with small timeout
  119. if (_g_tries > MAX_TRIES) {
  120. fprintf(stderr, "AES connection attempts exceeded max tries\n");
  121. return -1;
  122. }
  123. sock = _connect();
  124. if (sock == -1) {
  125. _g_tries++;
  126. return -1;
  127. }
  128. }
  129. // Send the event using existing socket connection
  130. if (sizeof(*event) != (sent = send(sock, event, sizeof(*event), MSG_NOSIGNAL))) {
  131. if (sent == -1) {
  132. if (errno == ECONNRESET || errno == EPIPE) {
  133. // Could happen if aes engine is restarted
  134. sock = -1;
  135. _g_tries = 0;
  136. goto resend;
  137. }
  138. char buf[128];
  139. strerror_r(errno, buf, sizeof(buf));
  140. fprintf(stderr, "AES: Error sending data: %s\n", buf);
  141. }
  142. else {
  143. fprintf(stderr, "AES: Partial data sent. UNHANDLED AND UNEXPECTED\n");
  144. }
  145. // setting sock to -1 to reconnect next time
  146. // TODO: But this event will not be sent. May need to change to reconnect and send this event
  147. return (sock = -1);
  148. }
  149. return 0;
  150. }