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.
13 #include <libnotify/notify.h>
15 #include <libmnl/libmnl.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
;
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)
38 if (mnl_attr_validate(attr
, MNL_TYPE_U32
) < 0) {
39 fprintf(stderr
, "%s: Invalid netlink attribute.\n", program
);
44 if (mnl_attr_validate(attr
, MNL_TYPE_STRING
) < 0) {
45 fprintf(stderr
, "%s: Invalid netlink attribute.\n", program
);
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
;
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
;
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
);
99 if(!notify_init("Udev-Net-Notification")) {
100 fprintf(stderr
, "%s: Can't create notify.\n", program
);
110 int main(int argc
, char ** argv
) {
111 struct mnl_socket
* nl
;
112 char buf
[MNL_SOCKET_BUFFER_SIZE
];
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]);
124 nl
= mnl_socket_open(NETLINK_ROUTE
);
126 fprintf(stderr
, "%s: Can't create netlink socket.\n", argv
[0]);
130 if (mnl_socket_bind(nl
, RTMGRP_LINK
, MNL_SOCKET_AUTOPID
) < 0) {
131 fprintf(stderr
, "%s: Can't bind netlink socket.\n", argv
[0]);
135 ret
= mnl_socket_recvfrom(nl
, buf
, sizeof(buf
));
137 ret
= mnl_cb_run(buf
, ret
, 0, 0, data_cb
, NULL
);
140 ret
= mnl_socket_recvfrom(nl
, buf
, sizeof(buf
));
143 fprintf(stderr
, "%s: An error occured reading from netlink socket.\n", argv
[0]);
147 mnl_socket_close(nl
);