kvde_switch datasock udpdated to latest ipn version
[vde.git] / vde-2 / src / kvde_switch / datasock.c
blob4750bb1f83b38ffe942d5a33ab5ddd29558ea1e3
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(int kvdefd)
110 struct extinterface *iface,*oldiface;
111 struct ifreq ifr;
112 for (iface=extifhead;iface != NULL;iface=oldiface)
114 memset(&ifr, 0, sizeof(ifr));
115 strncpy(ifr.ifr_name,iface->name,IFNAMSIZ);
116 if (iface->type == 't')
117 ifr.ifr_flags=IPN_NODEFLAG_TAP;
118 else
119 ifr.ifr_flags=IPN_NODEFLAG_GRAB;
120 // printf("ioctl\n");
121 if (ioctl(kvdefd, IPN_CONN_NETDEV, (void *) &ifr) < 0) {
122 printlog(LOG_ERR, "%s interface %s error: %s", iface->name,
123 (iface->type == 't')?"tap":"grab",strerror(errno));
124 exit(-1);
126 free(iface->name);
127 oldiface=iface->next;
128 free(iface);
130 extifhead=NULL;
133 static int parseopt(int c, char *optarg)
135 int outc=0;
136 struct group *grp;
137 switch (c) {
138 case 's':
139 /* This should returns NULL as the path probably does not exist */
140 vde_realpath(optarg, ctl_socket);
141 break;
142 case 'm':
143 sscanf(optarg,"%o",&mode);
144 break;
145 case 'g':
146 if (!(grp = getgrnam(optarg))) {
147 printlog(LOG_ERR, "No such group '%s'", optarg);
148 exit(1);
150 grp_owner=grp->gr_gid;
151 break;
152 case 't':
153 case 'G':
154 addextinterface(c,optarg);
155 break;
156 default:
157 outc=c;
159 return outc;
162 int check_kernel_support(void) {
164 int kvdefd = socket(AF_IPN,SOCK_RAW,IPN_VDESWITCH);
165 if (kvdefd < 0) {
166 kvdefd = socket(AF_IPN_STOLEN,SOCK_RAW,IPN_VDESWITCH);
167 if (kvdefd < 0) {
168 printlog(LOG_ERR,"kvde_switch requires ipn and kvde_switch kernel modules loaded");
169 return(-1);
172 close(kvdefd);
173 return 0;
176 static void init(void)
178 int kvdefd;
179 struct sockaddr_un sun;
180 int family = AF_IPN;
181 kvdefd = socket(AF_IPN,SOCK_RAW,IPN_VDESWITCH);
182 if (kvdefd < 0) {
183 family=AF_IPN_STOLEN;
184 kvdefd = socket(AF_IPN_STOLEN,SOCK_RAW,IPN_VDESWITCH);
185 if (kvdefd < 0) {
186 printlog(LOG_ERR,"kvde_switch requires ipn and kvde_switch kernel modules loaded");
187 exit(-1);
190 sun.sun_family = family;
191 snprintf(sun.sun_path,sizeof(sun.sun_path),"%s",ctl_socket);
192 if(bind(kvdefd, (struct sockaddr *) &sun, sizeof(sun)) < 0) {
193 printlog(LOG_ERR,"cannot bind socket %s",ctl_socket);
194 exit(-1);
196 if(chmod(ctl_socket, mode) <0) {
197 printlog(LOG_ERR, "chmod: %s", strerror(errno));
198 exit(1);
200 if(chown(ctl_socket,-1,grp_owner) < 0) {
201 printlog(LOG_ERR, "chown: %s", strerror(errno));
202 exit(1);
204 runextinterfaces(kvdefd);
205 add_fd(kvdefd,ctl_type,-1);
208 static int showinfo(FILE *fd)
210 printoutc(fd,"ctl dir %s",ctl_socket);
211 printoutc(fd,"std mode 0%03o",mode);
212 return 0;
215 static struct comlist cl[]={
216 {"ds","============","DATA SOCKET MENU",NULL,NOARG},
217 {"ds/showinfo","","show ds info",showinfo,NOARG|WITHFILE},
221 static void delep (int fd, void* data, void *descr)
223 if (fd>=0) remove_fd(fd);
224 if (data) free(data);
225 if (descr) free(descr);
229 void start_datasock(void)
231 strcpy(ctl_socket,(geteuid()==0)?VDESTDSOCK:VDETMPSOCK);
232 swmi.swmnopts=Nlong_options;
233 swmi.swmopts=long_options;
234 swmi.usage=usage;
235 swmi.parseopt=parseopt;
236 swmi.init=init;
237 swmi.handle_input=handle_input;
238 swmi.cleanup=cleanup;
239 ADDCL(cl);
240 add_swm(&swmi);