updated on Sat Jan 14 12:12:45 UTC 2012
[aur-mirror.git] / netlink-notify / netlink-notify.c
blob19195a28395e312d8da3d6eabebe3df06145683d
1 /*
2 * (C) 2011 by Christian Hesse <mail@eworm.de>
4 * This software may be used and distributed according to the terms
5 * of the GNU General Public License, incorporated herein by reference.
6 */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <string.h>
13 #include <libnotify/notify.h>
15 #include <libmnl/libmnl.h>
16 #include <linux/if.h>
17 #include <linux/if_link.h>
18 #include <linux/rtnetlink.h>
20 #define NOTIFICATION_TIMEOUT 10000
22 #define NOTIFICATION_TEXT "Interface %s is %s."
23 #define NOTIFICATION_TEXT_DEBUG "%s: Interface %s (index %d) is %s.\n"
25 unsigned int netlinksize = 0;
26 NotifyNotification ** netlinkref;
27 char * program;
29 static int data_attr_cb(const struct nlattr * attr, void * data) {
30 const struct nlattr ** tb = data;
31 int type = mnl_attr_get_type(attr);
33 if (mnl_attr_type_valid(attr, IFLA_MAX) < 0)
34 return MNL_CB_OK;
36 switch(type) {
37 case IFLA_MTU:
38 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
39 fprintf(stderr, "%s: Invalid netlink attribute.\n", program);
40 return MNL_CB_ERROR;
42 break;
43 case IFLA_IFNAME:
44 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) {
45 fprintf(stderr, "%s: Invalid netlink attribute.\n", program);
46 return MNL_CB_ERROR;
48 break;
50 tb[type] = attr;
51 return MNL_CB_OK;
54 static int data_cb(const struct nlmsghdr * nlh, void * data) {
55 struct nlattr * tb[IFLA_MAX + 1] = {};
56 struct ifinfomsg * ifm = mnl_nlmsg_get_payload(nlh);
58 char * notification = NULL;
59 char * interface = NULL;
60 NotifyNotification * netlink;
61 unsigned int i;
63 gboolean res = FALSE;
64 GError * error = NULL;
66 mnl_attr_parse(nlh, sizeof(* ifm), data_attr_cb, tb);
68 interface = (char *) mnl_attr_get_str(tb[IFLA_IFNAME]);
69 notification = (char *) malloc(strlen(interface) + strlen(NOTIFICATION_TEXT));
70 sprintf(notification, NOTIFICATION_TEXT, interface, (ifm->ifi_flags & IFF_RUNNING ? "up" : "down"));
71 printf(NOTIFICATION_TEXT_DEBUG, program, interface, ifm->ifi_index, (ifm->ifi_flags & IFF_RUNNING ? "up" : "down"));
73 if (netlinksize < ifm->ifi_index) {
74 netlinkref = realloc(netlinkref, (ifm->ifi_index + 1) * sizeof(size_t));
75 for(i = netlinksize; i < ifm->ifi_index; i++) {
76 netlinkref[i + 1] = NULL;
78 netlinksize = ifm->ifi_index;
81 if (netlinkref[ifm->ifi_index] == NULL) {
82 netlink = notify_notification_new("Netlink", notification, (ifm->ifi_flags & IFF_RUNNING ? "network-transmit-receive" : "network-error"));
83 netlinkref[ifm->ifi_index] = netlink;
84 } else {
85 netlink = netlinkref[ifm->ifi_index];
86 notify_notification_update(netlink, "Netlink", notification, (ifm->ifi_flags & IFF_RUNNING ? "network-transmit-receive" : "network-error"));
89 notify_notification_set_timeout(netlink, NOTIFICATION_TIMEOUT);
90 notify_notification_set_category(netlink, "Netlink");
91 notify_notification_set_urgency (netlink, NOTIFY_URGENCY_NORMAL);
93 while(!notify_notification_show(netlink, &error)) {
94 g_printerr("%s: Error \"%s\" while trying to show notification. Trying to reconnect.\n", program, error->message);
95 g_error_free(error);
96 error = NULL;
98 notify_uninit();
99 if(!notify_init("Udev-Net-Notification")) {
100 fprintf(stderr, "%s: Can't create notify.\n", program);
101 exit(EXIT_FAILURE);
105 free(notification);
107 return MNL_CB_OK;
110 int main(int argc, char ** argv) {
111 struct mnl_socket * nl;
112 char buf[MNL_SOCKET_BUFFER_SIZE];
113 int ret;
115 program = argv[0];
117 printf("%s: %s v%s (compiled: %s)\n", argv[0], PROGNAME, VERSION, DATE);
119 if(!notify_init("Netlink-Notification")) {
120 fprintf(stderr, "%s: Can't create notify.\n", argv[0]);
121 exit(EXIT_FAILURE);
124 nl = mnl_socket_open(NETLINK_ROUTE);
125 if (!nl) {
126 fprintf(stderr, "%s: Can't create netlink socket.\n", argv[0]);
127 exit(EXIT_FAILURE);
130 if (mnl_socket_bind(nl, RTMGRP_LINK, MNL_SOCKET_AUTOPID) < 0) {
131 fprintf(stderr, "%s: Can't bind netlink socket.\n", argv[0]);
132 exit(EXIT_FAILURE);
135 ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
136 while (ret > 0) {
137 ret = mnl_cb_run(buf, ret, 0, 0, data_cb, NULL);
138 if (ret <= 0)
139 break;
140 ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
142 if (ret == -1) {
143 fprintf(stderr, "%s: An error occured reading from netlink socket.\n", argv[0]);
144 exit(EXIT_FAILURE);
147 mnl_socket_close(nl);
149 return 0;