README: command syntax fix. web.c html constant return for 404 was wrong.
[vde.git] / vde / port.c
blob33c8c8ddebc8811cb51f629278b2e69edf2fe923
1 /* Copyright 2003 Renzo Davoli
2 * Based on the code of uml_switch Copyright 2002 Yon Uriarte and Jeff Dike
3 * Licensed under the GPL
4 */
6 #include <config.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <errno.h>
11 #include <syslog.h>
12 #include <sys/socket.h>
13 #include <sys/un.h>
15 #include <switch.h>
16 #include <hash.h>
17 #include <port.h>
19 /* a full ethernet 802.3 frame */
20 struct packet {
21 struct {
22 unsigned char dest[ETH_ALEN];
23 unsigned char src[ETH_ALEN];
24 unsigned char proto[2];
25 } header;
26 unsigned char data[1500];
30 // for dedugging if needed
32 void packet_dump (struct packet *p)
34 register int i;
35 printf ("packet dump dst");
36 for (i=0;i<ETH_ALEN;i++)
37 printf(":%02x",p->header.dest[i]);
38 printf(" src");
39 for (i=0;i<ETH_ALEN;i++)
40 printf(":%02x",p->header.src[i]);
41 printf(" proto");
42 for (i=0;i<2;i++)
43 printf(":%02x",p->header.proto[i]);
44 printf("\n");
48 /* descriptor of a port group */
49 struct portgroup {
50 /* identifier of the port group */
51 int ident;
52 /* number of ports which reference this descriptor */
53 int counter;
56 struct port {
57 int control;
58 /* tap case: NULL; data case: pointer to sock_data */
59 void *data;
60 int data_len;
61 /* pointer to a structure containing group description; reference counting
62 * allows to share the same structure, and know at the same time how many
63 * ports are grouped together */
64 struct portgroup *pg;
65 void (*sender)(int fd, void *packet, int len, void *data);
69 #define IS_BROADCAST(addr) ((addr[0] & 1) == 1)
71 void close_port(int i, int fd)
73 struct port *port=(struct port *)(g_fdsdata[i]);
75 if(port == NULL){
76 printlog(LOG_WARNING, "No port associated with descriptor %d", fd);
77 return;
79 else if(port->control != fd){
80 printlog(LOG_WARNING, "file descriptor mismatch %d %d", port->control, fd);
81 return;
84 if (port->pg != NULL) {
85 if (--port->pg->counter == 0) {
86 free(port->pg);
87 port->pg=NULL;
88 hash_delete_port(port);
89 } else {
91 struct port *p;
92 register int i;
94 p=NULL;
96 for(i=g_minfds ; i<g_nfds ; i++) {
97 p=(struct port *)(g_fdsdata[i]);
98 if(port != NULL && port != p && port->pg == p->pg) break;
100 if (p == NULL) {
101 printlog(LOG_WARNING,"portgroup inconsistency");
102 } else
104 hash_reassign(port,p);
108 else {
110 hash_delete_port(port);
113 #ifdef INFO
114 printlog(LOG_INFO,"Disconnect %d",port->control);
115 #endif
116 free(port);
119 static void update_src(struct port *port, struct packet *p)
121 struct port *last;
123 /* We don't like broadcast source addresses */
124 if(IS_BROADCAST(p->header.src)) return;
126 last = find_in_hash(p->header.src);
128 if(last == NULL || (port != last && (port->pg == NULL ||
129 port->pg != last->pg))){
130 /* old value differs from actual input port - this can happen in two ways:
131 * or the address is simply unknown (probably been forgot by the ARP cache,
132 * or just connected), or it belongs to an unkown port group / different
133 * port group */
135 #ifdef INFO
136 printlog(LOG_INFO," Addr: %02x:%02x:%02x:%02x:%02x:%02x New port %d",
137 p->header.src[0], p->header.src[1], p->header.src[2],
138 p->header.src[3], p->header.src[4], p->header.src[5],
139 port->control);
140 #endif
142 /* there was an entry for this address, but we felt compelled to add a new
143 * one, so at least remove the old one before */
144 if(last != NULL){
145 #ifdef INFO
146 printlog(LOG_INFO," old port %d", last->control);
147 #endif
148 delete_hash(p->header.src);
151 /* add the new ARP entry */
152 insert_into_hash(p->header.src, port);
154 update_entry_time(p->header.src);
157 static void send_dst(struct port *port, struct packet *packet, int len,
158 int hub)
160 struct port *target, *p;
161 register int i;
163 target = find_in_hash(packet->header.dest);
164 /*fprintf(stderr,"%02x:%02x:%02x:%02x:%02x:%02x -> %02x:%02x:%02x:%02x:%02x:%02x %p\n",
165 packet->header.src[0], packet->header.src[1],
166 packet->header.src[2], packet->header.src[3],
167 packet->header.src[4], packet->header.src[5],
168 packet->header.dest[0], packet->header.dest[1],
169 packet->header.dest[2], packet->header.dest[3],
170 packet->header.dest[4], packet->header.dest[5],
171 target);*/
172 if((target == NULL) || IS_BROADCAST(packet->header.dest) || hub){
173 #ifdef INFO
174 if((target == NULL) && !IS_BROADCAST(packet->header.dest)){
175 if(port == NULL)
176 printlog(LOG_WARNING,"unknown Addr: %02x:%02x:%02x:%02x:%02x:%02x from port UNKNOWN",
177 packet->header.dest[0], packet->header.dest[1],
178 packet->header.dest[2], packet->header.dest[3],
179 packet->header.dest[4], packet->header.dest[5]);
180 else
181 printlog(LOG_WARNING,"unknown Addr: %02x:%02x:%02x:%02x:%02x:%02x from port %d",
182 packet->header.dest[0], packet->header.dest[1],
183 packet->header.dest[2], packet->header.dest[3],
184 packet->header.dest[4], packet->header.dest[5], port->control);
186 #endif
188 /* no cache or broadcast/multicast == all ports */
189 for(i=g_minfds ; i<g_nfds ; i++) {
190 p=(struct port *)(g_fdsdata[i]);
191 if (p != NULL && ((p->pg == NULL && p != port) ||
192 p->pg != port->pg))
193 (*p->sender)(p->control, packet, len, p->data);
196 else {
197 if (target->pg == NULL)
198 (*target->sender)(target->control, packet, len, target->data);
199 else if (target->pg != port->pg) {
200 if (target->pg->counter == 1)
201 (*target->sender)(target->control, packet, len, target->data);
202 else {
203 for(i=g_minfds ; i<g_nfds ; i++) {
204 p=(struct port *)(g_fdsdata[i]);
205 if (p != NULL && p->pg == target->pg)
206 (*p->sender)(p->control, packet, len, p->data);
213 #define BPDUADDR {0x01,0x80,0xc2,0x00,0x00,0x00}
214 static unsigned char bpduaddrp[]=BPDUADDR;
215 #define ISBPDU(P) (memcmp((P)->header.dest,bpduaddrp,ETH_ALEN)==0)
217 /* we have received a packet of data; take the packet 'packet' of size 'len'
218 * and send it to port 'p', acting as a hub if asked for. if p is NULL, then we
219 * assume that data comes from no known source (this should not happen) */
220 static void handle_direct_data (struct port *p, int hub, struct packet *packet, int len)
222 /* if we have an incoming port (we should) */
223 if(p != NULL) update_src(p, packet);
224 #ifdef INFO
225 else {
226 printlog(LOG_WARNING,"Unknown connection for packet, shouldn't happen.");
228 #endif
229 /* throw away FSP packets: VDE1 is unable to manage FSP, run VDE2 instead
230 * ;-) */
231 if (!ISBPDU(packet))
232 send_dst(p, packet, len, hub);
236 void handle_tap_data(int i, int fd, int hub)
238 struct packet packet;
239 int len;
240 struct port *port;
242 len = read(fd, &packet, sizeof(packet));
243 if(len < 0){
244 if(errno != EAGAIN) printlog(LOG_WARNING,"Reading tap data %s",strerror(errno));
245 return;
247 port=(struct port *)(g_fdsdata[i]);
248 handle_direct_data(port, hub, &packet, len);
251 /* initialize a port structure with control=fd, given data+data_len and sender
252 * function; add it to the port group given by identifier portgroup iff != 0,
253 * and then add it to the g_fdsdata array at index i. */
254 int setup_port(int i, int fd, void (*sender)(int fd, void *packet, int len,
255 void *data), void *data, int data_len, int portgroup)
257 struct port *port;
259 port = malloc(sizeof(struct port));
260 if(port == NULL){
261 printlog(LOG_WARNING,"malloc %s",strerror(errno));
262 return(-1);
264 g_fdsdata[i]=port;
265 port->control = fd;
266 port->data = data;
267 port->data_len = data_len;
268 port->sender = sender;
269 port->pg = NULL;
270 if (portgroup != 0)
272 // search for other port on the same group
273 struct port *p=NULL;
274 for(i=g_minfds ; i<g_nfds ; i++) {
275 if (g_fdsdata != NULL) {
276 p=(struct port *)(g_fdsdata[i]);
277 if (p->pg != NULL && p->pg->ident == portgroup) {
278 port->pg=p->pg;
279 port->pg->counter++;
280 break;
284 /* enlarge the structure if needed */
285 if (port->pg == NULL)
287 port->pg=malloc(sizeof(struct portgroup));
288 if(port->pg == NULL){
289 printlog(LOG_WARNING,"malloc %s",strerror(errno));
290 return(-1);
292 port->pg->ident=portgroup;
293 port->pg->counter=1;
296 #ifdef INFO
297 printlog(LOG_INFO,"New connection %d",fd);
298 #endif
299 return(0);
302 struct sock_data {
303 /* fd from which data is read */
304 int fd;
305 /* source address of read data */
306 struct sockaddr_un sock;
309 static void send_sock(int fd, void *packet, int len, void *data)
311 struct sock_data *mine = data;
312 int err;
314 //do {
315 err = sendto(mine->fd, packet, len, 0, (struct sockaddr *) &mine->sock,
316 sizeof(mine->sock));
317 //} while (err == -1 && errno == EAGAIN);
318 if(err != len)
319 printlog(LOG_WARNING, "send_sock sending to fd %d %s", mine->fd, strerror(errno));
322 //static int match_sock(int port_fd, int data_fd, void *port_data,
323 //int port_data_len, void *data)
325 //struct sock_data *mine = data;
326 //struct sock_data *port = port_data;
328 //if(port_data_len != sizeof(*mine)) return(0);
329 //return(!memcmp(&port->sock, &mine->sock, sizeof(mine->sock)));
332 /* handle data reception from data socket fd. hub is 1 if we act as hubs, 0
333 * otherwise */
334 int handle_sock_data(int fd, int hub)
336 struct packet packet;
337 struct sock_data data;
338 int len, socklen = sizeof(data.sock);
339 struct port *p;
340 register int i;
341 struct sock_data *mine;
342 struct sock_data *port;
344 len = recvfrom(fd, &packet, sizeof(packet), 0,
345 (struct sockaddr *) &data.sock, &socklen);
346 if(len <= 0){
347 if(len < 0 && errno != EAGAIN) printlog(LOG_WARNING,"handle_sock_data %s",strerror(errno));
348 if (len == 0) return 1;
349 /* EGAIN case: receive would block, so tell everything's alright, and it
350 * will be managed in the next select again */
351 else return 0;
353 data.fd = fd;
355 /* goes through all ports, and look if it already knows about the one from
356 * which we received some data */
357 p=NULL;
358 for(i=g_minfds ; i<g_nfds ; i++) {
359 if (g_fdsdata[i] != NULL) {
360 p=(struct port *)(g_fdsdata[i]);
361 mine=&data;
362 port=p->data;
363 //if(match_sock(p->control, fd, p->data, p->data_len, &data)) break;
364 if(p->data_len == sizeof(struct sock_data) &&
365 !(memcmp(&(port->sock), &mine->sock, sizeof(mine->sock)))) break;
368 handle_direct_data(p,hub,&packet,len);
369 return 0;
372 int handle_sock_direct_data(int i, int fd, int hub)
374 struct packet packet;
375 struct sock_data data;
376 struct port *port;
377 int len, socklen = sizeof(data.sock);
379 len = recvfrom(fd, &packet, sizeof(packet), 0,
380 (struct sockaddr *) &data.sock, &socklen);
381 if(len <= 0){
382 if(len < 0 && errno != EAGAIN) printlog(LOG_WARNING,"handle_sock_direct_data %s",strerror(errno));
383 if (len == 0) return 1;
384 else return 0;
386 data.fd = fd;
388 port=(struct port *)(g_fdsdata[i]);
389 handle_direct_data(port, hub, &packet, len);
390 return 0;
393 int setup_sock_port(int i, int fd, struct sockaddr_un *name, int data_fd, int portgroup)
395 struct sock_data *data;
397 data = malloc(sizeof(*data));
398 if(data == NULL){
399 printlog(LOG_WARNING,"setup_sock_port %s",strerror(errno));
400 return(-1);
402 *data = ((struct sock_data) { fd : data_fd,
403 sock : *name });
404 return(setup_port(i, fd, send_sock, data, sizeof(*data), portgroup));