nl.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <errno.h>
  5. #include <asm/types.h>
  6. #include <sys/types.h>
  7. #include <sys/socket.h>
  8. #include <linux/netlink.h>
  9. #include <sys/select.h>
  10. #include <sys/time.h>
  11. #include <unistd.h>
  12. #include "nl.h"
  13. nl_fds_t * nl_init(void)
  14. {
  15. struct sockaddr_nl nl_addr;
  16. nl_fds_t *nl_fds;
  17. nl_fds = malloc(sizeof(*nl_fds) * NL_FDS_LEN);
  18. if (!nl_fds)
  19. return NULL;
  20. memset(&nl_addr, 0, sizeof(nl_addr));
  21. nl_addr.nl_family = AF_NETLINK;
  22. nl_addr.nl_pad = 0;
  23. nl_addr.nl_pid = 0; /* Let kernel to assign id */
  24. nl_addr.nl_groups = -1; /* Listen all multicast */
  25. /* NETLINK_KOBJECT_UEVENT for PCI events */
  26. if ((nl_fds[0] = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)) < 0) {
  27. fprintf(stderr, "Error: Can't create socket for NETLINK_KOBJECT_UEVENT.\n");
  28. return NULL;
  29. }
  30. if (bind(nl_fds[0], (void *)&nl_addr, sizeof(nl_addr))) {
  31. fprintf(stderr, "Error: Can't bind NETLINK_KOBJECT_UEVENT.\n");
  32. return NULL;
  33. }
  34. printf("KOBJECT=%d\n", nl_fds[0]);
  35. /* NETLINK_ROUTER for network events like interface up/down */
  36. if ((nl_fds[1] = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) {
  37. fprintf(stderr, "Error: Can't create socket for NETLINK_ROUTER\n");
  38. return NULL;
  39. }
  40. if (bind(nl_fds[1], (void *)&nl_addr, sizeof(nl_addr))) {
  41. fprintf(stderr, "Error: Can't bind NETLINK_ROUTER\n");
  42. return NULL;
  43. }
  44. printf("ROUTE=%d\n", nl_fds[1]);
  45. return nl_fds;
  46. }
  47. void nl_close(nl_fds_t *nl_fds)
  48. {
  49. int i;
  50. if (!nl_fds)
  51. return;
  52. for (i = 0; i < NL_FDS_LEN; i++) {
  53. if (nl_fds[i] >= 0)
  54. close(nl_fds[i]);
  55. }
  56. free(nl_fds);
  57. }
  58. int nl_poll(nl_fds_t *nl_fds, int timeout)
  59. {
  60. fd_set fd_set;
  61. char buf[10];
  62. int n;
  63. int i;
  64. int nfds = 0;
  65. struct timeval tv;
  66. if (!nl_fds)
  67. return -1;
  68. /* Initialize the set of active sockets. */
  69. FD_ZERO(&fd_set);
  70. for (i = 0; i < NL_FDS_LEN; i++) {
  71. FD_SET(nl_fds[i], &fd_set);
  72. if (nl_fds[i] > nfds)
  73. nfds = nl_fds[i];
  74. }
  75. nfds++;
  76. /* Wait up to five seconds. */
  77. tv.tv_sec = timeout;
  78. tv.tv_usec = 0;
  79. n = select(nfds, &fd_set, NULL, NULL, &tv);
  80. printf("NETLINK: n=%d\n", n);
  81. if (n < 0) {
  82. if (EINTR == errno)
  83. return -2;
  84. return -1;
  85. }
  86. if (0 == n)
  87. return n;
  88. /* Service all the sockets with input pending. */
  89. for (i = 0; i < NL_FDS_LEN; i++) {
  90. if (!FD_ISSET(nl_fds[i], &fd_set))
  91. continue;
  92. printf("RECV %d %d\n", i, nl_fds[i]);
  93. /* Read all messages. We don't need a message content. */
  94. while (recv(nl_fds[i], buf, sizeof(buf), MSG_DONTWAIT) > 0);
  95. }
  96. return n;
  97. }