Multiple tap/grab support for kvde_switch
[vde.git] / vde-2 / src / kvde_switch / datasock.c
blobb9b3ab2365d39150fb5de59cccd29cd349534369
1 /* Copyright 2005 Renzo Davoli - VDE-2
2 * --pidfile/-p and cleanup management by Mattia Belletti (C) 2004.
3 * Licensed under the GPLv2
4 * Modified by Ludovico Gardenghi 2005
5 * -g option (group management) by Daniel P. Berrange
6 * dir permission patch by Alessio Caprari 2006
7 */
9 #include <stdio.h>
10 #include <fcntl.h>
11 #include <errno.h>
12 #include <string.h>
13 #include <unistd.h>
14 #include <syslog.h>
15 #include <stdlib.h>
16 #include <stdint.h>
17 #include <libgen.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <sys/ioctl.h>
21 #include <sys/socket.h>
22 #include <sys/types.h>
23 #include <sys/un.h>
24 #include <net/if.h>
25 #include <stdarg.h>
26 #include <limits.h>
27 #include <grp.h>
28 #define _GNU_SOURCE
29 #include <getopt.h>
31 #include <config.h>
32 #include <vde.h>
33 #include <vdecommon.h>
35 #include "../vde_switch/switch.h"
36 #include "sockutils.h"
37 #include "consmgmt.h"
39 #include <af_ipn.h>
41 static struct swmodule swmi;
42 static unsigned int ctl_type;
43 static int mode = 0700;
45 static char real_ctl_socket[PATH_MAX];
46 static char *ctl_socket = real_ctl_socket;
47 static gid_t grp_owner = -1;
49 #define MODULENAME "kernel module interface"
51 static void handle_input(unsigned char type,int fd,int revents,int *arg)
53 /*here OOB messages will be delivered for debug options */
56 static void cleanup(unsigned char type,int fd,int arg)
58 unlink(ctl_socket);
61 static struct option long_options[] = {
62 {"sock", 1, 0, 's'},
63 {"vdesock", 1, 0, 's'},
64 {"unix", 1, 0, 's'},
65 {"mod", 1, 0, 'm'},
66 {"group", 1, 0, 'g'},
67 {"tap", 1, 0, 't'},
68 {"grab", 1, 0, 'G'},
72 #define Nlong_options (sizeof(long_options)/sizeof(struct option));
74 static void usage(void)
76 printf(
77 "(opts from datasock module)\n"
78 " -s, --sock SOCK control directory pathname\n"
79 " -s, --vdesock SOCK Same as --sock SOCK\n"
80 " -s, --unix SOCK Same as --sock SOCK\n"
81 " -m, --mod MODE Standard access mode for comm sockets (octal)\n"
82 " -g, --group GROUP Group owner for comm sockets\n"
83 " -t, --tap TAP Enable routing through TAP tap interface\n"
84 " -G, --grab INT Enable routing grabbing an existing interface\n");
87 struct extinterface {
88 char type;
89 char *name;
90 struct extinterface *next;
93 static struct extinterface *extifhead;
94 static struct extinterface **extiftail=&extifhead;
96 static void addextinterface(char type,char *name)
98 struct extinterface *new=malloc(sizeof (struct extinterface));
99 if (new) {
100 new->type=type;
101 new->name=strdup(name);
102 new->next=NULL;
103 *extiftail=new;
104 extiftail=&(new->next);
108 static void runextinterfaces(struct sockaddr_un *sun)
110 struct extinterface *iface,*oldiface;
111 struct ifreq ifr;
112 for (iface=extifhead;iface != NULL;iface=oldiface)
114 int kvdefd;
115 memset(&ifr, 0, sizeof(ifr));
116 strncpy(ifr.ifr_name,iface->name,IFNAMSIZ);
117 if (iface->type == 't')
118 ifr.ifr_flags=IPN_NODEFLAG_TAP;
119 else
120 ifr.ifr_flags=IPN_NODEFLAG_GRAB;
121 // printf("ioctl\n");
122 kvdefd = socket(AF_IPN,SOCK_RAW,IPN_VDESWITCH);
123 if (kvdefd < 0) {
124 kvdefd = socket(AF_IPN_STOLEN,SOCK_RAW,IPN_VDESWITCH);
125 if (kvdefd < 0) {
126 printlog(LOG_ERR,"kvde_switch grab/tap error socket");
127 exit(-1);
130 if(bind(kvdefd, (struct sockaddr *) sun, sizeof(*sun)) < 0) {
131 printlog(LOG_ERR,"cannot bind socket grab/tap");
132 exit(-1);
134 if (ioctl(kvdefd, IPN_CONN_NETDEV, (void *) &ifr) < 0) {
135 printlog(LOG_ERR, "%s interface %s error: %s", iface->name,
136 (iface->type == 't')?"tap":"grab",strerror(errno));
137 exit(-1);
139 free(iface->name);
140 oldiface=iface->next;
141 free(iface);
143 extifhead=NULL;
146 static int parseopt(int c, char *optarg)
148 int outc=0;
149 struct group *grp;
150 switch (c) {
151 case 's':
152 /* This should returns NULL as the path probably does not exist */
153 vde_realpath(optarg, ctl_socket);
154 break;
155 case 'm':
156 sscanf(optarg,"%o",&mode);
157 break;
158 case 'g':
159 if (!(grp = getgrnam(optarg))) {
160 printlog(LOG_ERR, "No such group '%s'", optarg);
161 exit(1);
163 grp_owner=grp->gr_gid;
164 break;
165 case 't':
166 case 'G':
167 addextinterface(c,optarg);
168 break;
169 default:
170 outc=c;
172 return outc;
175 int check_kernel_support(void) {
177 int kvdefd = socket(AF_IPN,SOCK_RAW,IPN_VDESWITCH);
178 if (kvdefd < 0) {
179 kvdefd = socket(AF_IPN_STOLEN,SOCK_RAW,IPN_VDESWITCH);
180 if (kvdefd < 0) {
181 printlog(LOG_ERR,"kvde_switch requires ipn and kvde_switch kernel modules loaded");
182 return(-1);
185 close(kvdefd);
186 return 0;
189 static void init(void)
191 int kvdefd;
192 struct sockaddr_un sun;
193 int family = AF_IPN;
194 kvdefd = socket(AF_IPN,SOCK_RAW,IPN_VDESWITCH);
195 if (kvdefd < 0) {
196 family=AF_IPN_STOLEN;
197 kvdefd = socket(AF_IPN_STOLEN,SOCK_RAW,IPN_VDESWITCH);
198 if (kvdefd < 0) {
199 printlog(LOG_ERR,"kvde_switch requires ipn and kvde_switch kernel modules loaded");
200 exit(-1);
203 sun.sun_family = family;
204 snprintf(sun.sun_path,sizeof(sun.sun_path),"%s",ctl_socket);
205 if(bind(kvdefd, (struct sockaddr *) &sun, sizeof(sun)) < 0) {
206 printlog(LOG_ERR,"cannot bind socket %s",ctl_socket);
207 exit(-1);
209 if(chmod(ctl_socket, mode) <0) {
210 printlog(LOG_ERR, "chmod: %s", strerror(errno));
211 exit(1);
213 if(chown(ctl_socket,-1,grp_owner) < 0) {
214 printlog(LOG_ERR, "chown: %s", strerror(errno));
215 exit(1);
217 runextinterfaces(&sun);
218 add_fd(kvdefd,ctl_type,-1);
221 static int showinfo(FILE *fd)
223 printoutc(fd,"ctl dir %s",ctl_socket);
224 printoutc(fd,"std mode 0%03o",mode);
225 return 0;
228 static struct comlist cl[]={
229 {"ds","============","DATA SOCKET MENU",NULL,NOARG},
230 {"ds/showinfo","","show ds info",showinfo,NOARG|WITHFILE},
234 static void delep (int fd, void* data, void *descr)
236 if (fd>=0) remove_fd(fd);
237 if (data) free(data);
238 if (descr) free(descr);
242 void start_datasock(void)
244 strcpy(ctl_socket,(geteuid()==0)?VDESTDSOCK:VDETMPSOCK);
245 swmi.swmnopts=Nlong_options;
246 swmi.swmopts=long_options;
247 swmi.usage=usage;
248 swmi.parseopt=parseopt;
249 swmi.init=init;
250 swmi.handle_input=handle_input;
251 swmi.cleanup=cleanup;
252 ADDCL(cl);
253 add_swm(&swmi);