ia64/xen-unstable
changeset 919:264c48ba4da3
bitkeeper revision 1.582.1.1 (3fafbef8y8bKbMkHy5KldiazAvehBA)
xen_netwatch.c:
new file
Makefile:
New utility for watching network interfaces coming up and going down, and calling a configure script.
xen_netwatch.c:
new file
Makefile:
New utility for watching network interfaces coming up and going down, and calling a configure script.
author | kaf24@scramble.cl.cam.ac.uk |
---|---|
date | Mon Nov 10 16:38:16 2003 +0000 (2003-11-10) |
parents | 3913078b6947 |
children | e2a517ef1be8 fc5ae656dd1e |
files | .rootkeys tools/misc/Makefile tools/misc/xen_netwatch.c |
line diff
1.1 --- a/.rootkeys Mon Nov 10 13:44:15 2003 +0000 1.2 +++ b/.rootkeys Mon Nov 10 16:38:16 2003 +0000 1.3 @@ -190,6 +190,7 @@ 3f870808zS6T6iFhqYPGelroZlVfGQ tools/mis 1.4 3f8bcf29ulZIC9rC4wM70H_q4s6VPg tools/misc/xen_log.c 1.5 3f13d81eQ9Vz-h-6RDGFkNR9CRP95g tools/misc/xen_nat_enable 1.6 3f13d81e6Z6806ihYYUw8GVKNkYnuw tools/misc/xen_nat_enable.README 1.7 +3fafbef1fJFKCcJLq-ffpauvpM10jQ tools/misc/xen_netwatch.c 1.8 3f1668d4F29Jsw0aC0bJEIkOBiagiQ tools/misc/xen_read_console.c 1.9 3f87ba90EUVPQLVOlFG0sW89BCwouQ tools/misc/xen_refresh_dev.c 1.10 3f72f1bdJPsV3JCnBqs9ddL9tr6D2g xen/COPYING
2.1 --- a/tools/misc/Makefile Mon Nov 10 13:44:15 2003 +0000 2.2 +++ b/tools/misc/Makefile Mon Nov 10 16:38:16 2003 +0000 2.3 @@ -1,13 +1,13 @@ 2.4 2.5 -CC = gcc 2.6 -CFLAGS = -Wall -O3 2.7 -CFLAGS += -I../../xen/include -I../../xenolinux-sparse/include -I../internal 2.8 +CC = gcc 2.9 +CFLAGS = -Wall -O3 2.10 +EXTRA_INC = -I../../xen/include -I../../xenolinux-sparse/include -I../internal 2.11 2.12 HDRS = $(wildcard *.h) 2.13 SRCS = $(wildcard *.c) 2.14 OBJS = $(patsubst %.c,%.o,$(SRCS)) 2.15 2.16 -TARGETS = xen_read_console xen_cpuperf xen_refresh_dev 2.17 +TARGETS = xen_read_console xen_cpuperf xen_refresh_dev xen_netwatch 2.18 2.19 INSTALL = $(TARGETS) xen-mkdevnodes xen_nat_enable xen-clone 2.20 2.21 @@ -25,6 +25,9 @@ clean: 2.22 $(RM) *.o $(TARGETS) 2.23 $(MAKE) -C miniterm clean 2.24 2.25 -%: %.c $(HDRS) Makefile 2.26 +xen_netwatch: %: %.c $(HDRS) Makefile 2.27 $(CC) $(CFLAGS) -o $@ $< 2.28 2.29 +%: %.c $(HDRS) Makefile 2.30 + $(CC) $(CFLAGS) $(EXTRA_INC) -o $@ $< 2.31 +
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/tools/misc/xen_netwatch.c Mon Nov 10 16:38:16 2003 +0000 3.3 @@ -0,0 +1,196 @@ 3.4 +/****************************************************************************** 3.5 + * netwatch.c 3.6 + * 3.7 + * Watch for network interfaces needing frobbing. 3.8 + * 3.9 + * Copyright (c) 2003, K A Fraser 3.10 + */ 3.11 + 3.12 +#include <asm/types.h> 3.13 +#include <sys/types.h> 3.14 +#include <sys/socket.h> 3.15 +#include <sys/ioctl.h> 3.16 +#include <sys/resource.h> 3.17 +#include <sys/time.h> 3.18 +#include <sys/un.h> 3.19 +#include <sys/wait.h> 3.20 +#include <linux/netlink.h> 3.21 +#include <linux/rtnetlink.h> 3.22 +#include <linux/if.h> 3.23 + 3.24 +#include <errno.h> 3.25 +#include <signal.h> 3.26 +#include <stdio.h> 3.27 +#include <unistd.h> 3.28 +#include <time.h> 3.29 + 3.30 +#define LOG(_f, _a...) \ 3.31 + do { \ 3.32 + time_t now = time(NULL); \ 3.33 + char *tstr = ctime(&now); \ 3.34 + char *p = strchr(tstr, '\n'); if (p) *p = '\0'; \ 3.35 + fprintf(logfd, "%s: " _f "\n", tstr, ## _a); \ 3.36 + fflush(logfd); \ 3.37 + } while ( 0 ) 3.38 + 3.39 +#define EXIT do { LOG("Exiting."); return 1; } while ( 0 ) 3.40 + 3.41 +static void daemonise(void) 3.42 +{ 3.43 + int i; 3.44 + struct rlimit rlim; 3.45 + 3.46 + /* Close all file handles we inherited from our parent. */ 3.47 + if ( getrlimit(RLIMIT_NOFILE, &rlim) == 0 ) 3.48 + for ( i = 0; i < rlim.rlim_cur; i++ ) 3.49 + close(i); 3.50 + 3.51 + /* Lose the controlling tty. */ 3.52 + setsid(); 3.53 +} 3.54 + 3.55 +void handle_child_death(int dummy) 3.56 +{ 3.57 + (void)waitpid(-1, NULL, WNOHANG); 3.58 +} 3.59 + 3.60 +int main(int argc, char **argv) 3.61 +{ 3.62 + char *logfile = "/var/xen/netwatch"; 3.63 + char *scriptfile = "/etc/xen/netwatch"; 3.64 + FILE *logfd; 3.65 + int nlfd, unixfd, bytes; 3.66 + int last_index = ~0; 3.67 + unsigned int last_flags = ~0; 3.68 + char buffer[8192]; 3.69 + struct sockaddr_nl nladdr; 3.70 + struct nlmsghdr *nlmsg; 3.71 + struct ifinfomsg *ifi; 3.72 + struct ifreq ifr; 3.73 + struct sigaction sigchld; 3.74 + 3.75 + /* Ensure that zombie children are reaped. */ 3.76 + memset(&sigchld, 0, sizeof(sigchld)); 3.77 + sigchld.sa_handler = handle_child_death; 3.78 + sigemptyset(&sigchld.sa_mask); 3.79 + sigchld.sa_flags = SA_NOCLDSTOP | SA_RESTART; 3.80 + (void)sigaction(SIGCHLD, &sigchld, NULL); 3.81 + 3.82 + /* 3.83 + * After child daemonises it can't display errors until it opens the log 3.84 + * file. Since it may be unable to open the log file, we test for that 3.85 + * possibility here. 3.86 + */ 3.87 + if ( (logfd = fopen(logfile, "wb")) == NULL ) 3.88 + { 3.89 + fprintf(stderr, "Could not open log file '%s' (%d)\n", logfile, errno); 3.90 + fprintf(stderr, "Exiting.\n"); 3.91 + return 1; 3.92 + } 3.93 + fclose(logfd); 3.94 + 3.95 + switch ( fork() ) 3.96 + { 3.97 + case 0: 3.98 + daemonise(); 3.99 + break; 3.100 + case -1: 3.101 + fprintf(stderr, "Could not daemonize. (%d)\n", errno); 3.102 + fprintf(stderr, "Exiting.\n"); 3.103 + return 1; 3.104 + default: 3.105 + goto out; 3.106 + } 3.107 + 3.108 + /* Silent error is forgiveable here, as our parent did a test for us. */ 3.109 + if ( (logfd = fopen(logfile, "wb")) == NULL ) 3.110 + return 1; 3.111 + 3.112 + if ( (nlfd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) == -1 ) 3.113 + { 3.114 + LOG("Could not open an rtnetlink socket. (%d)\n", errno); 3.115 + EXIT; 3.116 + } 3.117 + 3.118 + if ( (unixfd = socket(PF_UNIX, SOCK_DGRAM, 0)) == -1 ) 3.119 + { 3.120 + LOG("Could not open UNIX socket. (%d)\n", errno); 3.121 + EXIT; 3.122 + } 3.123 + 3.124 + nladdr.nl_family = AF_NETLINK; 3.125 + nladdr.nl_pid = 0; 3.126 + nladdr.nl_groups = RTMGRP_LINK; 3.127 + if ( bind(nlfd, (struct sockaddr *)&nladdr, sizeof(nladdr)) == -1 ) 3.128 + { 3.129 + LOG("Could not bind to kernel (%d)\n", errno); 3.130 + EXIT; 3.131 + } 3.132 + 3.133 + for ( ; ; ) 3.134 + { 3.135 + memset(buffer, 0, sizeof(buffer)); 3.136 + 3.137 + if ( (bytes = read(nlfd, buffer, sizeof(buffer))) == -1 ) 3.138 + { 3.139 + if ( errno != EINTR ) 3.140 + LOG("Error when reading from socket (%d)", errno); 3.141 + continue; 3.142 + } 3.143 + 3.144 + if ( bytes == 0 ) 3.145 + continue; 3.146 + 3.147 + for ( nlmsg = (struct nlmsghdr *)buffer; 3.148 + !(nlmsg->nlmsg_flags & NLMSG_DONE); 3.149 + nlmsg = NLMSG_NEXT(nlmsg, bytes) ) 3.150 + { 3.151 + /* This termination condition works. NLMSG_DONE doesn't always. */ 3.152 + if ( nlmsg->nlmsg_len == 0 ) 3.153 + break; 3.154 + 3.155 + if ( nlmsg->nlmsg_type != RTM_NEWLINK ) 3.156 + continue; 3.157 + 3.158 + ifi = NLMSG_DATA(nlmsg); 3.159 + 3.160 + ifr.ifr_ifindex = ifi->ifi_index; 3.161 + if ( ioctl(unixfd, SIOCGIFNAME, &ifr) == -1 ) 3.162 + continue; 3.163 + 3.164 + if ( !(ifi->ifi_change & IFF_UP) ) 3.165 + continue; 3.166 + 3.167 + /* Ignore duplicate messages. */ 3.168 + if ( (last_index == ifr.ifr_ifindex) && 3.169 + (last_flags == ifi->ifi_flags) ) 3.170 + continue; 3.171 + last_index = ifr.ifr_ifindex; 3.172 + last_flags = ifi->ifi_flags; 3.173 + 3.174 + LOG("Network %s event for interface %s", 3.175 + (ifi->ifi_flags & IFF_UP) ? "UP" : "DOWN", 3.176 + ifr.ifr_name); 3.177 + 3.178 + switch ( fork() ) 3.179 + { 3.180 + case 0: 3.181 + execl(scriptfile, 3.182 + ifr.ifr_name, 3.183 + (ifi->ifi_flags & IFF_UP) ? "up" : "down"); 3.184 + LOG("Error executing network script '%s %s %s'", 3.185 + scriptfile, ifr.ifr_name, 3.186 + (ifi->ifi_flags & IFF_UP) ? "up" : "down"); 3.187 + return 1; 3.188 + case -1: 3.189 + LOG("Error forking to exec script"); 3.190 + break; 3.191 + default: 3.192 + break; 3.193 + } 3.194 + } 3.195 + } 3.196 + 3.197 + out: 3.198 + return 0; 3.199 +}