1 /*
2  * Cisco router simulation platform.
3  * Copyright (c) 2006 Christophe Fillot (cf@utc.fr)
4  *
5  * Hypervisor NIO bridge routines.
6  */
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <string.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <signal.h>
15 #include <fcntl.h>
16 #include <errno.h>
17 #include <assert.h>
18 #include <stdarg.h>
19 #include <sys/ioctl.h>
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <arpa/inet.h>
23 #include <pthread.h>
24 
25 #include "utils.h"
26 #include "net.h"
27 #include "crc.h"
28 #include "net_io.h"
29 #include "net_io_bridge.h"
30 #include "registry.h"
31 #include "hypervisor.h"
32 
33 /* Create a new NIO bridge */
cmd_create(hypervisor_conn_t * conn,int argc,char * argv[])34 static int cmd_create(hypervisor_conn_t *conn,int argc,char *argv[])
35 {
36    netio_bridge_t *t;
37 
38    if (!(t = netio_bridge_create(argv[0]))) {
39       hypervisor_send_reply(conn,HSC_ERR_CREATE,1,
40                             "unable to create NIO bridge '%s'",
41                             argv[0]);
42       return(-1);
43    }
44 
45    netio_bridge_release(argv[0]);
46    hypervisor_send_reply(conn,HSC_INFO_OK,1,"NIO bridge '%s' created",argv[0]);
47    return(0);
48 }
49 
50 /* Rename a NIO bridge */
cmd_rename(hypervisor_conn_t * conn,int argc,char * argv[])51 static int cmd_rename(hypervisor_conn_t *conn,int argc,char *argv[])
52 {
53    netio_bridge_t *t;
54    char *newname;
55 
56    if (!(t = hypervisor_find_object(conn,argv[0],OBJ_TYPE_NIO_BRIDGE)))
57       return(-1);
58 
59    if (registry_exists(argv[1],OBJ_TYPE_NIO_BRIDGE)) {
60       netio_bridge_release(argv[0]);
61       hypervisor_send_reply(conn,HSC_ERR_RENAME,1,
62                             "unable to rename NIO bridge '%s', '%s' already exists",
63                             argv[0],argv[1]);
64       return(-1);
65    }
66 
67    if(!(newname = strdup(argv[1]))) {
68       netio_bridge_release(argv[0]);
69       hypervisor_send_reply(conn,HSC_ERR_RENAME,1,
70                             "unable to rename NIO bridge '%s', out of memory",
71                             argv[0]);
72       return(-1);
73    }
74 
75    if (registry_rename(argv[0],newname,OBJ_TYPE_NIO_BRIDGE)) {
76       free(newname);
77       netio_bridge_release(argv[0]);
78       hypervisor_send_reply(conn,HSC_ERR_RENAME,1,
79                             "unable to rename NIO bridge '%s'",
80                             argv[0]);
81       return(-1);
82    }
83 
84    free(t->name);
85    t->name = newname;
86 
87    netio_bridge_release(argv[1]);
88    hypervisor_send_reply(conn,HSC_INFO_OK,1,"NIO bridge '%s' renamed to '%s'",argv[0],argv[1]);
89    return(0);
90 }
91 
92 /* Delete an NIO bridge */
cmd_delete(hypervisor_conn_t * conn,int argc,char * argv[])93 static int cmd_delete(hypervisor_conn_t *conn,int argc,char *argv[])
94 {
95    int res;
96 
97    res = netio_bridge_delete(argv[0]);
98 
99    if (res == 1) {
100       hypervisor_send_reply(conn,HSC_INFO_OK,1,"NIO bridge '%s' deleted",
101                             argv[0]);
102    } else {
103       hypervisor_send_reply(conn,HSC_ERR_DELETE,1,
104                             "unable to delete NIO bridge '%s'",argv[0]);
105    }
106 
107    return(res);
108 }
109 
110 /*
111  * Add a NIO to a bridge
112  *
113  * Parameters: <bridge_name> <nio_name>
114  */
cmd_add_nio(hypervisor_conn_t * conn,int argc,char * argv[])115 static int cmd_add_nio(hypervisor_conn_t *conn,int argc,char *argv[])
116 {
117    netio_bridge_t *t;
118 
119    if (!(t = hypervisor_find_object(conn,argv[0],OBJ_TYPE_NIO_BRIDGE)))
120       return(-1);
121 
122    if (netio_bridge_add_netio(t,argv[1]) == -1) {
123       netio_bridge_release(argv[0]);
124       hypervisor_send_reply(conn,HSC_ERR_BINDING,1,
125                             "unable to bind NIO '%s' to bridge '%s'",
126                             argv[1],argv[0]);
127       return(-1);
128    }
129 
130    netio_bridge_release(argv[0]);
131    hypervisor_send_reply(conn,HSC_INFO_OK,1,"NIO '%s' bound.",argv[1]);
132    return(0);
133 }
134 
135 /*
136  * Remove a NIO from a bridge
137  *
138  * Parameters: <bridge_name> <nio_name>
139  */
cmd_remove_nio(hypervisor_conn_t * conn,int argc,char * argv[])140 static int cmd_remove_nio(hypervisor_conn_t *conn,int argc,char *argv[])
141 {
142    netio_bridge_t *t;
143 
144    if (!(t = hypervisor_find_object(conn,argv[0],OBJ_TYPE_NIO_BRIDGE)))
145       return(-1);
146 
147    if (netio_bridge_remove_netio(t,argv[1]) == -1) {
148       netio_bridge_release(argv[0]);
149       hypervisor_send_reply(conn,HSC_ERR_BINDING,1,
150                             "unable to bind NIO '%s' to bridge '%s'",
151                             argv[1],argv[0]);
152       return(-1);
153    }
154 
155    netio_bridge_release(argv[0]);
156    hypervisor_send_reply(conn,HSC_INFO_OK,1,"NIO '%s' unbound.",argv[1]);
157    return(0);
158 }
159 
160 /* Show info about a NIO bridge object */
cmd_show_list(registry_entry_t * entry,void * opt,int * err)161 static void cmd_show_list(registry_entry_t *entry,void *opt,int *err)
162 {
163    hypervisor_conn_t *conn = opt;
164    hypervisor_send_reply(conn,HSC_INFO_MSG,0,"%s",entry->name);
165 }
166 
167 /* Bridge switch List */
cmd_list(hypervisor_conn_t * conn,int argc,char * argv[])168 static int cmd_list(hypervisor_conn_t *conn,int argc,char *argv[])
169 {
170    int err = 0;
171    registry_foreach_type(OBJ_TYPE_NIO_BRIDGE,cmd_show_list,conn,&err);
172    hypervisor_send_reply(conn,HSC_INFO_OK,1,"OK");
173    return(0);
174 }
175 
176 /* NIO bridge commands */
177 static hypervisor_cmd_t nio_bridge_cmd_array[] = {
178    { "create", 1, 1, cmd_create, NULL },
179    { "rename", 2, 2, cmd_rename, NULL },
180    { "delete", 1, 1, cmd_delete, NULL },
181    { "add_nio", 2, 2, cmd_add_nio, NULL },
182    { "remove_nio", 2, 2, cmd_remove_nio, NULL },
183    { "list", 0, 0, cmd_list, NULL },
184    { NULL, -1, -1, NULL, NULL },
185 };
186 
187 /* Hypervisor NIO bridge initialization */
hypervisor_nio_bridge_init(void)188 int hypervisor_nio_bridge_init(void)
189 {
190    hypervisor_module_t *module;
191 
192    module = hypervisor_register_module("nio_bridge",NULL);
193    assert(module != NULL);
194 
195    hypervisor_register_cmd_array(module,nio_bridge_cmd_array);
196    return(0);
197 }
198