1 /*
2 * Cisco router) simulation platform.
3 * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4 *
5 * Network Input/Output Abstraction Layer.
6 */
7
8 #include "dynamips_common.h"
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <stdarg.h>
14 #include <unistd.h>
15 #include <errno.h>
16 #include <signal.h>
17 #include <fcntl.h>
18 #include <ctype.h>
19 #include <time.h>
20 #include <sys/time.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <sys/ioctl.h>
24 #include <sys/socket.h>
25 #include <sys/un.h>
26 #include <sys/wait.h>
27 #include <netinet/in.h>
28 #include <arpa/inet.h>
29 #include <netdb.h>
30 #include <pthread.h>
31
32 #ifdef __linux__
33 #include <net/if.h>
34 #include <linux/if_tun.h>
35 #endif
36
37 #include "registry.h"
38 #include "net.h"
39 #include "net_io.h"
40 #include "net_io_filter.h"
41 #include "ptask.h"
42
43 /* Free a NetIO descriptor */
44 static int netio_free(void *data,void *arg);
45
46 /* NIO RX listener */
47 static pthread_mutex_t netio_rxl_mutex = PTHREAD_MUTEX_INITIALIZER;
48 static pthread_mutex_t netio_rxq_mutex = PTHREAD_MUTEX_INITIALIZER;
49 static struct netio_rx_listener *netio_rxl_list = NULL;
50 static struct netio_rx_listener *netio_rxl_add_list = NULL;
51 static netio_desc_t *netio_rxl_remove_list = NULL;
52 static pthread_t netio_rxl_thread;
53 static pthread_cond_t netio_rxl_cond;
54
55 #define NETIO_RXL_LOCK() pthread_mutex_lock(&netio_rxl_mutex);
56 #define NETIO_RXL_UNLOCK() pthread_mutex_unlock(&netio_rxl_mutex);
57
58 #define NETIO_RXQ_LOCK() pthread_mutex_lock(&netio_rxq_mutex);
59 #define NETIO_RXQ_UNLOCK() pthread_mutex_unlock(&netio_rxq_mutex);
60
61 /* NetIO type */
62 typedef struct {
63 char *name;
64 char *desc;
65 }netio_type_t;
66
67 /* NETIO types (must follow the enum definition) */
68 static netio_type_t netio_types[NETIO_TYPE_MAX] = {
69 { "unix" , "UNIX local sockets" },
70 { "vde" , "Virtual Distributed Ethernet / UML switch" },
71 { "tap" , "Linux/FreeBSD TAP device" },
72 { "udp" , "UDP sockets" },
73 { "udp_auto" , "Auto UDP sockets" },
74 { "tcp_cli" , "TCP client" },
75 { "tcp_ser" , "TCP server" },
76 #ifdef LINUX_ETH
77 { "linux_eth" , "Linux Ethernet device" },
78 #endif
79 #ifdef GEN_ETH
80 { "gen_eth" , "Generic Ethernet device (PCAP)" },
81 #endif
82 { "fifo" , "FIFO (intra-hypervisor)" },
83 { "null" , "Null device" },
84 };
85
86 /* Get NETIO type given a description */
netio_get_type(char * type)87 int netio_get_type(char *type)
88 {
89 int i;
90
91 for(i=0;i<NETIO_TYPE_MAX;i++)
92 if (!strcmp(type,netio_types[i].name))
93 return(i);
94
95 return(-1);
96 }
97
98 /* Show the NETIO types */
netio_show_types(void)99 void netio_show_types(void)
100 {
101 int i;
102
103 printf("Available NETIO types:\n");
104
105 for(i=0;i<NETIO_TYPE_MAX;i++)
106 printf(" * %-10s : %s\n",netio_types[i].name,netio_types[i].desc);
107
108 printf("\n");
109 }
110
111 /*
112 * =========================================================================
113 * Generic functions (abstraction layer)
114 * =========================================================================
115 */
116
117 /* Acquire a reference to NIO from registry (increment reference count) */
netio_acquire(char * name)118 netio_desc_t *netio_acquire(char *name)
119 {
120 return(registry_find(name,OBJ_TYPE_NIO));
121 }
122
123 /* Release an NIO (decrement reference count) */
netio_release(char * name)124 int netio_release(char *name)
125 {
126 return(registry_unref(name,OBJ_TYPE_NIO));
127 }
128
129 /* Record an NIO in registry */
netio_record(netio_desc_t * nio)130 static int netio_record(netio_desc_t *nio)
131 {
132 return(registry_add(nio->name,OBJ_TYPE_NIO,nio));
133 }
134
135 /* Create a new NetIO descriptor */
netio_create(char * name)136 static netio_desc_t *netio_create(char *name)
137 {
138 netio_desc_t *nio;
139
140 if (!(nio = malloc(sizeof(*nio))))
141 return NULL;
142
143 /* setup as a NULL descriptor */
144 memset(nio,0,sizeof(*nio));
145 nio->type = NETIO_TYPE_NULL;
146
147 /* save name for registry */
148 if (!(nio->name = strdup(name))) {
149 free(nio);
150 return NULL;
151 }
152
153 return nio;
154 }
155
156 /* Delete a NetIO descriptor */
netio_delete(char * name)157 int netio_delete(char *name)
158 {
159 return(registry_delete_if_unused(name,OBJ_TYPE_NIO,netio_free,NULL));
160 }
161
162 /* Delete all NetIO descriptors */
netio_delete_all(void)163 int netio_delete_all(void)
164 {
165 return(registry_delete_type(OBJ_TYPE_NIO,netio_free,NULL));
166 }
167
168 /* Save the configuration of a NetIO descriptor */
netio_save_config(netio_desc_t * nio,FILE * fd)169 void netio_save_config(netio_desc_t *nio,FILE *fd)
170 {
171 if (nio->save_cfg)
172 nio->save_cfg(nio,fd);
173 }
174
175 /* Save configurations of all NetIO descriptors */
netio_reg_save_config(registry_entry_t * entry,void * opt,int * err)176 static void netio_reg_save_config(registry_entry_t *entry,void *opt,int *err)
177 {
178 netio_save_config((netio_desc_t *)entry->data,(FILE *)opt);
179 }
180
netio_save_config_all(FILE * fd)181 void netio_save_config_all(FILE *fd)
182 {
183 registry_foreach_type(OBJ_TYPE_NIO,netio_reg_save_config,fd,NULL);
184 fprintf(fd,"\n");
185 }
186
187 /* Send a packet through a NetIO descriptor */
netio_send(netio_desc_t * nio,void * pkt,size_t len)188 ssize_t netio_send(netio_desc_t *nio,void *pkt,size_t len)
189 {
190 int res;
191
192 if (!nio)
193 return(-1);
194
195 if (nio->debug) {
196 printf("NIO %s: sending a packet of %lu bytes:\n",nio->name,(u_long)len);
197 mem_dump(stdout,pkt,len);
198 }
199
200 /* Apply the TX filter */
201 if (nio->tx_filter != NULL) {
202 res = nio->tx_filter->pkt_handler(nio,pkt,len,nio->tx_filter_data);
203
204 if (res <= 0)
205 return(-1);
206 }
207
208 /* Apply the bidirectional filter */
209 if (nio->both_filter != NULL) {
210 res = nio->both_filter->pkt_handler(nio,pkt,len,nio->both_filter_data);
211
212 if (res == NETIO_FILTER_ACTION_DROP)
213 return(-1);
214 }
215
216 /* Update output statistics */
217 nio->stats_pkts_out++;
218 nio->stats_bytes_out += len;
219
220 netio_update_bw_stat(nio,len);
221
222 return(nio->send(nio->dptr,pkt,len));
223 }
224
225 /* Receive a packet through a NetIO descriptor */
netio_recv(netio_desc_t * nio,void * pkt,size_t max_len)226 ssize_t netio_recv(netio_desc_t *nio,void *pkt,size_t max_len)
227 {
228 ssize_t len;
229 int res;
230
231 if (!nio)
232 return(-1);
233
234 /* Receive the packet */
235 if ((len = nio->recv(nio->dptr,pkt,max_len)) <= 0)
236 return(-1);
237
238 if (nio->debug) {
239 printf("NIO %s: receiving a packet of %ld bytes:\n",nio->name,(long)len);
240 mem_dump(stdout,pkt,len);
241 }
242
243 /* Apply the RX filter */
244 if (nio->rx_filter != NULL) {
245 res = nio->rx_filter->pkt_handler(nio,pkt,len,nio->rx_filter_data);
246
247 if (res == NETIO_FILTER_ACTION_DROP)
248 return(-1);
249 }
250
251 /* Apply the bidirectional filter */
252 if (nio->both_filter != NULL) {
253 res = nio->both_filter->pkt_handler(nio,pkt,len,nio->both_filter_data);
254
255 if (res == NETIO_FILTER_ACTION_DROP)
256 return(-1);
257 }
258
259 /* Update input statistics */
260 nio->stats_pkts_in++;
261 nio->stats_bytes_in += len;
262 return(len);
263 }
264
265 /* Get a NetIO FD */
netio_get_fd(netio_desc_t * nio)266 int netio_get_fd(netio_desc_t *nio)
267 {
268 int fd = -1;
269
270 switch(nio->type) {
271 case NETIO_TYPE_UNIX:
272 fd = nio->u.nud.fd;
273 break;
274 case NETIO_TYPE_VDE:
275 fd = nio->u.nvd.data_fd;
276 break;
277 case NETIO_TYPE_TAP:
278 fd = nio->u.ntd.fd;
279 break;
280 case NETIO_TYPE_TCP_CLI:
281 case NETIO_TYPE_TCP_SER:
282 case NETIO_TYPE_UDP:
283 case NETIO_TYPE_UDP_AUTO:
284 fd = nio->u.nid.fd;
285 break;
286 #ifdef LINUX_ETH
287 case NETIO_TYPE_LINUX_ETH:
288 fd = nio->u.nled.fd;
289 break;
290 #endif
291 }
292
293 return(fd);
294 }
295
296 /*
297 * =========================================================================
298 * UNIX sockets
299 * =========================================================================
300 */
301
302 /* Create an UNIX socket */
netio_unix_create_socket(netio_unix_desc_t * nud)303 static int netio_unix_create_socket(netio_unix_desc_t *nud)
304 {
305 struct sockaddr_un local_sock;
306
307 if ((nud->fd = socket(AF_UNIX,SOCK_DGRAM,0)) == -1) {
308 perror("netio_unix: socket");
309 return(-1);
310 }
311
312 memset(&local_sock,0,sizeof(local_sock));
313 local_sock.sun_family = AF_UNIX;
314 strcpy(local_sock.sun_path,nud->local_filename);
315
316 if (bind(nud->fd,(struct sockaddr *)&local_sock,sizeof(local_sock)) == -1) {
317 perror("netio_unix: bind");
318 return(-1);
319 }
320
321 return(nud->fd);
322 }
323
324 /* Free a NetIO unix descriptor */
netio_unix_free(netio_unix_desc_t * nud)325 static void netio_unix_free(netio_unix_desc_t *nud)
326 {
327 if (nud->fd != -1)
328 close(nud->fd);
329
330 if (nud->local_filename) {
331 unlink(nud->local_filename);
332 free(nud->local_filename);
333 }
334 }
335
336 /* Allocate a new NetIO UNIX descriptor */
netio_unix_create(netio_unix_desc_t * nud,char * local,char * remote)337 static int netio_unix_create(netio_unix_desc_t *nud,char *local,char *remote)
338 {
339 memset(nud,0,sizeof(*nud));
340 nud->fd = -1;
341
342 /* check lengths */
343 if ((strlen(local) >= sizeof(nud->remote_sock.sun_path)) ||
344 (strlen(remote) >= sizeof(nud->remote_sock.sun_path)))
345 goto nomem_error;
346
347 if (!(nud->local_filename = strdup(local)))
348 goto nomem_error;
349
350 if (netio_unix_create_socket(nud) == -1)
351 return(-1);
352
353 /* prepare the remote info */
354 nud->remote_sock.sun_family = AF_UNIX;
355 strcpy(nud->remote_sock.sun_path,remote);
356 return(0);
357
358 nomem_error:
359 fprintf(stderr,"netio_unix_create: "
360 "invalid file size or insufficient memory\n");
361 return(-1);
362 }
363
364 /* Send a packet to an UNIX socket */
netio_unix_send(netio_unix_desc_t * nud,void * pkt,size_t pkt_len)365 static ssize_t netio_unix_send(netio_unix_desc_t *nud,void *pkt,size_t pkt_len)
366 {
367 return(sendto(nud->fd,pkt,pkt_len,0,
368 (struct sockaddr *)&nud->remote_sock,
369 sizeof(nud->remote_sock)));
370 }
371
372 /* Receive a packet from an UNIX socket */
netio_unix_recv(netio_unix_desc_t * nud,void * pkt,size_t max_len)373 static ssize_t netio_unix_recv(netio_unix_desc_t *nud,void *pkt,size_t max_len)
374 {
375 return(recvfrom(nud->fd,pkt,max_len,0,NULL,NULL));
376 }
377
378 /* Save the NIO configuration */
netio_unix_save_cfg(netio_desc_t * nio,FILE * fd)379 static void netio_unix_save_cfg(netio_desc_t *nio,FILE *fd)
380 {
381 netio_unix_desc_t *nud = nio->dptr;
382 fprintf(fd,"nio create_unix %s %s %s\n",
383 nio->name,nud->local_filename,nud->remote_sock.sun_path);
384 }
385
386 /* Create a new NetIO descriptor with UNIX method */
netio_desc_create_unix(char * nio_name,char * local,char * remote)387 netio_desc_t *netio_desc_create_unix(char *nio_name,char *local,char *remote)
388 {
389 netio_desc_t *nio;
390
391 if (!(nio = netio_create(nio_name)))
392 return NULL;
393
394 if (netio_unix_create(&nio->u.nud,local,remote) == -1) {
395 netio_free(nio,NULL);
396 return NULL;
397 }
398
399 nio->type = NETIO_TYPE_UNIX;
400 nio->send = (void *)netio_unix_send;
401 nio->recv = (void *)netio_unix_recv;
402 nio->free = (void *)netio_unix_free;
403 nio->save_cfg = netio_unix_save_cfg;
404 nio->dptr = &nio->u.nud;
405
406 if (netio_record(nio) == -1) {
407 netio_free(nio,NULL);
408 return NULL;
409 }
410
411 return nio;
412 }
413
414 /*
415 * =========================================================================
416 * VDE (Virtual Distributed Ethernet) interface
417 * =========================================================================
418 */
419
420 /* Free a NetIO VDE descriptor */
netio_vde_free(netio_vde_desc_t * nvd)421 static void netio_vde_free(netio_vde_desc_t *nvd)
422 {
423 if (nvd->data_fd != -1)
424 close(nvd->data_fd);
425
426 if (nvd->ctrl_fd != -1)
427 close(nvd->ctrl_fd);
428
429 if (nvd->local_filename) {
430 unlink(nvd->local_filename);
431 free(nvd->local_filename);
432 }
433 }
434
435 /* Create a new NetIO VDE descriptor */
netio_vde_create(netio_vde_desc_t * nvd,char * control,char * local)436 static int netio_vde_create(netio_vde_desc_t *nvd,char *control,char *local)
437 {
438 struct sockaddr_un ctrl_sock,tst;
439 struct vde_request_v3 req;
440 ssize_t len;
441 int res;
442
443 memset(nvd,0,sizeof(*nvd));
444 nvd->ctrl_fd = nvd->data_fd = -1;
445
446 if ((strlen(control) >= sizeof(ctrl_sock.sun_path)) ||
447 (strlen(local) >= sizeof(nvd->remote_sock.sun_path))) {
448 fprintf(stderr,"netio_vde_create: bad filenames specified\n");
449 return(-1);
450 }
451
452 /* Copy the local filename */
453 if (!(nvd->local_filename = strdup(local))) {
454 fprintf(stderr,"netio_vde_create: insufficient memory\n");
455 return(-1);
456 }
457
458 /* Connect to the VDE switch controller */
459 nvd->ctrl_fd = socket(AF_UNIX,SOCK_STREAM,0);
460 if (nvd->ctrl_fd < 0) {
461 perror("netio_vde_create: socket(control)");
462 return(-1);
463 }
464
465 memset(&ctrl_sock,0,sizeof(ctrl_sock));
466 ctrl_sock.sun_family = AF_UNIX;
467 strcpy(ctrl_sock.sun_path,control);
468
469 res = connect(nvd->ctrl_fd,(struct sockaddr *)&ctrl_sock,
470 sizeof(ctrl_sock));
471
472 if (res < 0) {
473 perror("netio_vde_create: connect(control)");
474 return(-1);
475 }
476
477 tst.sun_family = AF_UNIX;
478 strcpy(tst.sun_path,local);
479
480 /* Create the data connection */
481 nvd->data_fd = socket(AF_UNIX,SOCK_DGRAM,0);
482 if (nvd->data_fd < 0) {
483 perror("netio_vde_create: socket(data)");
484 return(-1);
485 }
486
487 if (bind(nvd->data_fd,(struct sockaddr *)&tst,sizeof(tst))<0) {
488 perror("netio_vde_create: bind(data)");
489 return(-1);
490 }
491
492 /* Now, process to registration */
493 memset(&req,0,sizeof(req));
494 req.sock.sun_family = AF_UNIX;
495 strcpy(req.sock.sun_path,local);
496 req.magic = VDE_SWITCH_MAGIC;
497 req.version = VDE_SWITCH_VERSION;
498 req.type = VDE_REQ_NEW_CONTROL;
499
500 len = write(nvd->ctrl_fd,&req,sizeof(req));
501 if (len != sizeof(req)) {
502 perror("netio_vde_create: write(req)");
503 return(-1);
504 }
505
506 /* Read the remote socket descriptor */
507 len = read(nvd->ctrl_fd,&nvd->remote_sock,sizeof(nvd->remote_sock));
508 if (len != sizeof(nvd->remote_sock)) {
509 perror("netio_vde_create: read(req)");
510 return(-1);
511 }
512
513 return(0);
514 }
515
516 /* Send a packet to a VDE data socket */
netio_vde_send(netio_vde_desc_t * nvd,void * pkt,size_t pkt_len)517 static ssize_t netio_vde_send(netio_vde_desc_t *nvd,void *pkt,size_t pkt_len)
518 {
519 return(sendto(nvd->data_fd,pkt,pkt_len,0,
520 (struct sockaddr *)&nvd->remote_sock,
521 sizeof(nvd->remote_sock)));
522 }
523
524 /* Receive a packet from a VDE socket */
netio_vde_recv(netio_vde_desc_t * nvd,void * pkt,size_t max_len)525 static ssize_t netio_vde_recv(netio_vde_desc_t *nvd,void *pkt,size_t max_len)
526 {
527 return(recvfrom(nvd->data_fd,pkt,max_len,0,NULL,NULL));
528 }
529
530 /* Save the NIO configuration */
netio_vde_save_cfg(netio_desc_t * nio,FILE * fd)531 static void netio_vde_save_cfg(netio_desc_t *nio,FILE *fd)
532 {
533 netio_vde_desc_t *nvd = nio->dptr;
534 fprintf(fd,"nio create_vde %s %s %s\n",
535 nio->name,nvd->remote_sock.sun_path,nvd->local_filename);
536 }
537
538 /* Create a new NetIO descriptor with VDE method */
netio_desc_create_vde(char * nio_name,char * control,char * local)539 netio_desc_t *netio_desc_create_vde(char *nio_name,char *control,char *local)
540 {
541 netio_vde_desc_t *nvd;
542 netio_desc_t *nio;
543
544 if (!(nio = netio_create(nio_name)))
545 return NULL;
546
547 nvd = &nio->u.nvd;
548
549 if (netio_vde_create(nvd,control,local) == -1) {
550 netio_free(nio,NULL);
551 return NULL;
552 }
553
554 nio->type = NETIO_TYPE_VDE;
555 nio->send = (void *)netio_vde_send;
556 nio->recv = (void *)netio_vde_recv;
557 nio->free = (void *)netio_vde_free;
558 nio->save_cfg = netio_vde_save_cfg;
559 nio->dptr = &nio->u.nvd;
560
561 if (netio_record(nio) == -1) {
562 netio_free(nio,NULL);
563 return NULL;
564 }
565
566 return nio;
567 }
568
569 /*
570 * =========================================================================
571 * TAP devices
572 * =========================================================================
573 */
574
575 /* Free a NetIO TAP descriptor */
netio_tap_free(netio_tap_desc_t * ntd)576 static void netio_tap_free(netio_tap_desc_t *ntd)
577 {
578 if (ntd->fd != -1)
579 close(ntd->fd);
580 }
581
582 /* Open a TAP device */
netio_tap_open(char * tap_devname)583 static int netio_tap_open(char *tap_devname)
584 {
585 #ifdef __linux__
586 struct ifreq ifr;
587 int fd,err;
588
589 if ((fd = open("/dev/net/tun",O_RDWR)) < 0)
590 return(-1);
591
592 memset(&ifr,0,sizeof(ifr));
593
594 /* Flags: IFF_TUN - TUN device (no Ethernet headers)
595 * IFF_TAP - TAP device
596 *
597 * IFF_NO_PI - Do not provide packet information
598 */
599 ifr.ifr_flags = IFF_TAP|IFF_NO_PI;
600 if (*tap_devname)
601 strncpy(ifr.ifr_name,tap_devname,IFNAMSIZ);
602
603 if ((err = ioctl(fd,TUNSETIFF,(void *)&ifr)) < 0) {
604 close(fd);
605 return err;
606 }
607
608 strcpy(tap_devname,ifr.ifr_name);
609 return(fd);
610 #else
611 int i,fd = -1;
612 char tap_fullname[NETIO_DEV_MAXLEN];
613
614 if (*tap_devname) {
615 snprintf(tap_fullname,NETIO_DEV_MAXLEN,"/dev/%s",tap_devname);
616 fd = open(tap_fullname,O_RDWR);
617 } else {
618 for(i=0;i<16;i++) {
619 snprintf(tap_devname,NETIO_DEV_MAXLEN,"/dev/tap%d",i);
620
621 if ((fd = open(tap_devname,O_RDWR)) >= 0)
622 break;
623 }
624 }
625
626 return(fd);
627 #endif
628 }
629
630 /* Allocate a new NetIO TAP descriptor */
netio_tap_create(netio_tap_desc_t * ntd,char * tap_name)631 static int netio_tap_create(netio_tap_desc_t *ntd,char *tap_name)
632 {
633 if (strlen(tap_name) >= NETIO_DEV_MAXLEN) {
634 fprintf(stderr,"netio_tap_create: bad TAP device string specified.\n");
635 return(-1);
636 }
637
638 memset(ntd,0,sizeof(*ntd));
639 strcpy(ntd->filename,tap_name);
640 ntd->fd = netio_tap_open(ntd->filename);
641
642 if (ntd->fd == -1) {
643 fprintf(stderr,"netio_tap_create: unable to open TAP device %s (%s)\n",
644 tap_name,strerror(errno));
645 return(-1);
646 }
647
648 return(0);
649 }
650
651 /* Send a packet to a TAP device */
netio_tap_send(netio_tap_desc_t * ntd,void * pkt,size_t pkt_len)652 static ssize_t netio_tap_send(netio_tap_desc_t *ntd,void *pkt,size_t pkt_len)
653 {
654 return(write(ntd->fd,pkt,pkt_len));
655 }
656
657 /* Receive a packet through a TAP device */
netio_tap_recv(netio_tap_desc_t * ntd,void * pkt,size_t max_len)658 static ssize_t netio_tap_recv(netio_tap_desc_t *ntd,void *pkt,size_t max_len)
659 {
660 return(read(ntd->fd,pkt,max_len));
661 }
662
663 /* Save the NIO configuration */
netio_tap_save_cfg(netio_desc_t * nio,FILE * fd)664 static void netio_tap_save_cfg(netio_desc_t *nio,FILE *fd)
665 {
666 netio_tap_desc_t *ntd = nio->dptr;
667 fprintf(fd,"nio create_tap %s %s\n",nio->name,ntd->filename);
668 }
669
670 /* Create a new NetIO descriptor with TAP method */
netio_desc_create_tap(char * nio_name,char * tap_name)671 netio_desc_t *netio_desc_create_tap(char *nio_name,char *tap_name)
672 {
673 netio_tap_desc_t *ntd;
674 netio_desc_t *nio;
675
676 if (!(nio = netio_create(nio_name)))
677 return NULL;
678
679 ntd = &nio->u.ntd;
680
681 if (netio_tap_create(ntd,tap_name) == -1) {
682 netio_free(nio,NULL);
683 return NULL;
684 }
685
686 nio->type = NETIO_TYPE_TAP;
687 nio->send = (void *)netio_tap_send;
688 nio->recv = (void *)netio_tap_recv;
689 nio->free = (void *)netio_tap_free;
690 nio->save_cfg = netio_tap_save_cfg;
691 nio->dptr = &nio->u.ntd;
692
693 if (netio_record(nio) == -1) {
694 netio_free(nio,NULL);
695 return NULL;
696 }
697
698 return nio;
699 }
700
701 /*
702 * =========================================================================
703 * TCP sockets
704 * =========================================================================
705 */
706
707 /* Free a NetIO TCP descriptor */
netio_tcp_free(netio_inet_desc_t * nid)708 static void netio_tcp_free(netio_inet_desc_t *nid)
709 {
710 if (nid->fd != -1)
711 close(nid->fd);
712 }
713
714 /*
715 * very simple protocol to send packets over tcp
716 * 32 bits in network format - size of packet, then packet itself and so on.
717 */
netio_tcp_send(netio_inet_desc_t * nid,void * pkt,size_t pkt_len)718 static ssize_t netio_tcp_send(netio_inet_desc_t *nid,void *pkt,size_t pkt_len)
719 {
720 u_long l = htonl(pkt_len);
721
722 if (write(nid->fd,&l,sizeof(l)) == -1)
723 return(-1);
724
725 return(write(nid->fd,pkt,pkt_len));
726 }
727
netio_tcp_recv(netio_inet_desc_t * nid,void * pkt,size_t max_len)728 static ssize_t netio_tcp_recv(netio_inet_desc_t *nid,void *pkt,size_t max_len)
729 {
730 u_long l;
731
732 if (read(nid->fd,&l,sizeof(l)) != sizeof(l))
733 return(-1);
734
735 if (ntohl(l) > max_len)
736 return(-1);
737
738 return(read(nid->fd,pkt,ntohl(l)));
739 }
740
netio_tcp_cli_create(netio_inet_desc_t * nid,char * host,char * port)741 static int netio_tcp_cli_create(netio_inet_desc_t *nid,char *host,char *port)
742 {
743 struct sockaddr_in serv;
744 struct servent *sp;
745 struct hostent *hp;
746
747 if ((nid->fd = socket(PF_INET,SOCK_STREAM,0)) < 0) {
748 perror("netio_tcp_cli_create: socket");
749 return(-1);
750 }
751
752 memset(&serv,0,sizeof(serv));
753 serv.sin_family = AF_INET;
754
755 if (atoi(port) == 0) {
756 if (!(sp = getservbyname(port,"tcp"))) {
757 fprintf(stderr,"netio_tcp_cli_create: port %s is neither "
758 "number not service %s\n",port,strerror(errno));
759 close(nid->fd);
760 return(-1);
761 }
762 serv.sin_port = sp->s_port;
763 } else
764 serv.sin_port = htons(atoi(port));
765
766 if (inet_addr(host) == INADDR_NONE) {
767 if (!(hp = gethostbyname(host))) {
768 fprintf(stderr,"netio_tcp_cli_create: no host %s\n",host);
769 close(nid->fd);
770 return(-1);
771 }
772 serv.sin_addr.s_addr = *hp->h_addr;
773 } else
774 serv.sin_addr.s_addr = inet_addr(host);
775
776 if (connect(nid->fd,(struct sockaddr *)&serv,sizeof(serv)) < 0) {
777 fprintf(stderr,"netio_tcp_cli_create: connect to %s:%s failed %s\n",
778 host,port,strerror(errno));
779 close(nid->fd);
780 return(-1);
781 }
782 return(0);
783 }
784
785 /* Create a new NetIO descriptor with TCP_CLI method */
netio_desc_create_tcp_cli(char * nio_name,char * host,char * port)786 netio_desc_t *netio_desc_create_tcp_cli(char *nio_name,char *host,char *port)
787 {
788 netio_desc_t *nio;
789
790 if (!(nio = netio_create(nio_name)))
791 return NULL;
792
793 if (netio_tcp_cli_create(&nio->u.nid,host,port) < 0) {
794 netio_free(nio,NULL);
795 return NULL;
796 }
797
798 nio->type = NETIO_TYPE_TCP_CLI;
799 nio->send = (void *)netio_tcp_send;
800 nio->recv = (void *)netio_tcp_recv;
801 nio->free = (void *)netio_tcp_free;
802 nio->dptr = &nio->u.nid;
803
804 if (netio_record(nio) == -1) {
805 netio_free(nio,NULL);
806 return NULL;
807 }
808
809 return nio;
810 }
811
netio_tcp_ser_create(netio_inet_desc_t * nid,char * port)812 static int netio_tcp_ser_create(netio_inet_desc_t *nid,char *port)
813 {
814 struct sockaddr_in serv;
815 struct servent *sp;
816 int sock_fd;
817
818 if ((sock_fd = socket(PF_INET,SOCK_STREAM,0)) < 0) {
819 perror("netio_tcp_cli_create: socket\n");
820 return(-1);
821 }
822
823 memset(&serv,0,sizeof(serv));
824 serv.sin_family = AF_INET;
825 serv.sin_addr.s_addr = htonl(INADDR_ANY);
826
827 if (atoi(port) == 0) {
828 if (!(sp = getservbyname(port,"tcp"))) {
829 fprintf(stderr,"netio_tcp_ser_create: port %s is neither "
830 "number not service %s\n",port,strerror(errno));
831 close(sock_fd);
832 return(-1);
833 }
834 serv.sin_port = sp->s_port;
835 } else
836 serv.sin_port = htons(atoi(port));
837
838 if (bind(sock_fd,(struct sockaddr *)&serv,sizeof(serv)) < 0) {
839 fprintf(stderr,"netio_tcp_ser_create: bind %s failed %s\n",
840 port,strerror(errno));
841 close(sock_fd);
842 return(-1);
843 }
844
845 if (listen(sock_fd,1) < 0) {
846 fprintf(stderr,"netio_tcp_ser_create: listen %s failed %s\n",
847 port,strerror(errno));
848 close(sock_fd);
849 return(-1);
850 }
851
852 fprintf(stderr,"Waiting connection on port %s...\n",port);
853
854 if ((nid->fd = accept(sock_fd,NULL,NULL)) < 0) {
855 fprintf(stderr,"netio_tcp_ser_create: accept %s failed %s\n",
856 port,strerror(errno));
857 close(sock_fd);
858 return(-1);
859 }
860
861 fprintf(stderr,"Connected\n");
862
863 close(sock_fd);
864 return(0);
865 }
866
867 /* Create a new NetIO descriptor with TCP_SER method */
netio_desc_create_tcp_ser(char * nio_name,char * port)868 netio_desc_t *netio_desc_create_tcp_ser(char *nio_name,char *port)
869 {
870 netio_desc_t *nio;
871
872 if (!(nio = netio_create(nio_name)))
873 return NULL;
874
875 if (netio_tcp_ser_create(&nio->u.nid,port) == -1) {
876 netio_free(nio,NULL);
877 return NULL;
878 }
879
880 nio->type = NETIO_TYPE_TCP_SER;
881 nio->send = (void *)netio_tcp_send;
882 nio->recv = (void *)netio_tcp_recv;
883 nio->free = (void *)netio_tcp_free;
884 nio->dptr = &nio->u.nid;
885
886 if (netio_record(nio) == -1) {
887 netio_free(nio,NULL);
888 return NULL;
889 }
890
891 return nio;
892 }
893
894 /*
895 * =========================================================================
896 * UDP sockets
897 * =========================================================================
898 */
899
900 /* Free a NetIO UDP descriptor */
netio_udp_free(netio_inet_desc_t * nid)901 static void netio_udp_free(netio_inet_desc_t *nid)
902 {
903 if (nid->remote_host) {
904 free(nid->remote_host);
905 nid->remote_host = NULL;
906 }
907
908 if (nid->fd != -1)
909 close(nid->fd);
910 }
911
912 /* Send a packet to an UDP socket */
netio_udp_send(netio_inet_desc_t * nid,void * pkt,size_t pkt_len)913 static ssize_t netio_udp_send(netio_inet_desc_t *nid,void *pkt,size_t pkt_len)
914 {
915 return(send(nid->fd,pkt,pkt_len,0));
916 }
917
918 /* Receive a packet from an UDP socket */
netio_udp_recv(netio_inet_desc_t * nid,void * pkt,size_t max_len)919 static ssize_t netio_udp_recv(netio_inet_desc_t *nid,void *pkt,size_t max_len)
920 {
921 return(recvfrom(nid->fd,pkt,max_len,0,NULL,NULL));
922 }
923
924 /* Save the NIO configuration */
netio_udp_save_cfg(netio_desc_t * nio,FILE * fd)925 static void netio_udp_save_cfg(netio_desc_t *nio,FILE *fd)
926 {
927 netio_inet_desc_t *nid = nio->dptr;
928 fprintf(fd,"nio create_udp %s %d %s %d\n",
929 nio->name,nid->local_port,nid->remote_host,nid->remote_port);
930 }
931
932 /* Create a new NetIO descriptor with UDP method */
netio_desc_create_udp(char * nio_name,int local_port,char * remote_host,int remote_port)933 netio_desc_t *netio_desc_create_udp(char *nio_name,int local_port,
934 char *remote_host,int remote_port)
935 {
936 netio_inet_desc_t *nid;
937 netio_desc_t *nio;
938
939 if (!(nio = netio_create(nio_name)))
940 return NULL;
941
942 nid = &nio->u.nid;
943 nid->local_port = local_port;
944 nid->remote_port = remote_port;
945
946 if (!(nid->remote_host = strdup(remote_host))) {
947 fprintf(stderr,"netio_desc_create_udp: insufficient memory\n");
948 goto error;
949 }
950
951 if ((nid->fd = udp_connect(local_port,remote_host,remote_port)) < 0) {
952 fprintf(stderr,"netio_desc_create_udp: unable to connect to %s:%d\n",
953 remote_host,remote_port);
954 goto error;
955 }
956
957 nio->type = NETIO_TYPE_UDP;
958 nio->send = (void *)netio_udp_send;
959 nio->recv = (void *)netio_udp_recv;
960 nio->free = (void *)netio_udp_free;
961 nio->save_cfg = netio_udp_save_cfg;
962 nio->dptr = &nio->u.nid;
963
964 if (netio_record(nio) == -1)
965 goto error;
966
967 return nio;
968
969 error:
970 netio_free(nio,NULL);
971 return NULL;
972 }
973
974 /*
975 * =========================================================================
976 * UDP sockets with auto allocation
977 * =========================================================================
978 */
979
980 /* Get local port */
netio_udp_auto_get_local_port(netio_desc_t * nio)981 int netio_udp_auto_get_local_port(netio_desc_t *nio)
982 {
983 if (nio->type != NETIO_TYPE_UDP_AUTO)
984 return(-1);
985
986 return(nio->u.nid.local_port);
987 }
988
989 /* Connect to a remote host/port */
netio_udp_auto_connect(netio_desc_t * nio,char * host,int port)990 int netio_udp_auto_connect(netio_desc_t *nio,char *host,int port)
991 {
992 netio_inet_desc_t *nid = nio->dptr;
993
994 /* NIO already connected */
995 if (nid->remote_host != NULL)
996 return(-1);
997
998 if (!(nid->remote_host = strdup(host))) {
999 fprintf(stderr,"netio_desc_create_udp_auto: insufficient memory\n");
1000 return(-1);
1001 }
1002
1003 nid->remote_port = port;
1004
1005 if (ip_connect_fd(nid->fd,nid->remote_host,nid->remote_port) < 0) {
1006 free(nid->remote_host);
1007 nid->remote_host = NULL;
1008 return(-1);
1009 }
1010
1011 return(0);
1012 }
1013
1014 /* Create a new NetIO descriptor with auto UDP method */
netio_desc_create_udp_auto(char * nio_name,char * local_addr,int port_start,int port_end)1015 netio_desc_t *netio_desc_create_udp_auto(char *nio_name,char *local_addr,
1016 int port_start,int port_end)
1017 {
1018 netio_inet_desc_t *nid;
1019 netio_desc_t *nio;
1020
1021 if (!(nio = netio_create(nio_name)))
1022 return NULL;
1023
1024 nid = &nio->u.nid;
1025 nid->local_port = -1;
1026 nid->remote_host = NULL;
1027 nid->remote_port = -1;
1028
1029 if ((nid->fd = udp_listen_range(local_addr,port_start,port_end,
1030 &nid->local_port)) < 0)
1031 {
1032 fprintf(stderr,
1033 "netio_desc_create_udp_auto: unable to create socket "
1034 "(addr=%s,port_start=%d,port_end=%d)\n",
1035 local_addr,port_start,port_end);
1036 goto error;
1037 }
1038
1039 nio->type = NETIO_TYPE_UDP_AUTO;
1040 nio->send = (void *)netio_udp_send;
1041 nio->recv = (void *)netio_udp_recv;
1042 nio->free = (void *)netio_udp_free;
1043 nio->save_cfg = netio_udp_save_cfg;
1044 nio->dptr = &nio->u.nid;
1045
1046 if (netio_record(nio) == -1)
1047 goto error;
1048
1049 return nio;
1050
1051 error:
1052 netio_free(nio,NULL);
1053 return NULL;
1054 }
1055
1056 /*
1057 * =========================================================================
1058 * Linux RAW Ethernet driver
1059 * =========================================================================
1060 */
1061 #ifdef LINUX_ETH
1062 /* Free a NetIO raw ethernet descriptor */
netio_lnxeth_free(netio_lnxeth_desc_t * nled)1063 static void netio_lnxeth_free(netio_lnxeth_desc_t *nled)
1064 {
1065 if (nled->fd != -1)
1066 close(nled->fd);
1067 }
1068
1069 /* Send a packet to a raw Ethernet socket */
netio_lnxeth_send(netio_lnxeth_desc_t * nled,void * pkt,size_t pkt_len)1070 static ssize_t netio_lnxeth_send(netio_lnxeth_desc_t *nled,
1071 void *pkt,size_t pkt_len)
1072 {
1073 return(lnx_eth_send(nled->fd,nled->dev_id,pkt,pkt_len));
1074 }
1075
1076 /* Receive a packet from an raw Ethernet socket */
netio_lnxeth_recv(netio_lnxeth_desc_t * nled,void * pkt,size_t max_len)1077 static ssize_t netio_lnxeth_recv(netio_lnxeth_desc_t *nled,
1078 void *pkt,size_t max_len)
1079 {
1080 return(lnx_eth_recv(nled->fd,pkt,max_len));
1081 }
1082
1083 /* Save the NIO configuration */
netio_lnxeth_save_cfg(netio_desc_t * nio,FILE * fd)1084 static void netio_lnxeth_save_cfg(netio_desc_t *nio,FILE *fd)
1085 {
1086 netio_lnxeth_desc_t *nled = nio->dptr;
1087 fprintf(fd,"nio create_linux_eth %s %s\n",nio->name,nled->dev_name);
1088 }
1089
1090 /* Create a new NetIO descriptor with raw Ethernet method */
netio_desc_create_lnxeth(char * nio_name,char * dev_name)1091 netio_desc_t *netio_desc_create_lnxeth(char *nio_name,char *dev_name)
1092 {
1093 netio_lnxeth_desc_t *nled;
1094 netio_desc_t *nio;
1095
1096 if (!(nio = netio_create(nio_name)))
1097 return NULL;
1098
1099 nled = &nio->u.nled;
1100
1101 if (strlen(dev_name) >= NETIO_DEV_MAXLEN) {
1102 fprintf(stderr,"netio_desc_create_lnxeth: bad Ethernet device string "
1103 "specified.\n");
1104 netio_free(nio,NULL);
1105 return NULL;
1106 }
1107
1108 strcpy(nled->dev_name,dev_name);
1109
1110 nled->fd = lnx_eth_init_socket(dev_name);
1111 nled->dev_id = lnx_eth_get_dev_index(dev_name);
1112
1113 if (nled->fd < 0) {
1114 netio_free(nio,NULL);
1115 return NULL;
1116 }
1117
1118 nio->type = NETIO_TYPE_LINUX_ETH;
1119 nio->send = (void *)netio_lnxeth_send;
1120 nio->recv = (void *)netio_lnxeth_recv;
1121 nio->free = (void *)netio_lnxeth_free;
1122 nio->save_cfg = netio_lnxeth_save_cfg;
1123 nio->dptr = &nio->u.nled;
1124
1125 if (netio_record(nio) == -1) {
1126 netio_free(nio,NULL);
1127 return NULL;
1128 }
1129
1130 return nio;
1131 }
1132 #endif /* LINUX_ETH */
1133
1134 /*
1135 * =========================================================================
1136 * Generic RAW Ethernet driver
1137 * =========================================================================
1138 */
1139 #ifdef GEN_ETH
1140 /* Free a NetIO raw ethernet descriptor */
netio_geneth_free(netio_geneth_desc_t * nged)1141 static void netio_geneth_free(netio_geneth_desc_t *nged)
1142 {
1143 gen_eth_close(nged->pcap_dev);
1144 }
1145
1146 /* Send a packet to an Ethernet device */
netio_geneth_send(netio_geneth_desc_t * nged,void * pkt,size_t pkt_len)1147 static ssize_t netio_geneth_send(netio_geneth_desc_t *nged,
1148 void *pkt,size_t pkt_len)
1149 {
1150 return(gen_eth_send(nged->pcap_dev,pkt,pkt_len));
1151 }
1152
1153 /* Receive a packet from an Ethernet device */
netio_geneth_recv(netio_geneth_desc_t * nged,void * pkt,size_t max_len)1154 static ssize_t netio_geneth_recv(netio_geneth_desc_t *nged,
1155 void *pkt,size_t max_len)
1156 {
1157 return(gen_eth_recv(nged->pcap_dev,pkt,max_len));
1158 }
1159
1160 /* Save the NIO configuration */
netio_geneth_save_cfg(netio_desc_t * nio,FILE * fd)1161 static void netio_geneth_save_cfg(netio_desc_t *nio,FILE *fd)
1162 {
1163 netio_geneth_desc_t *nged = nio->dptr;
1164 fprintf(fd,"nio create_gen_eth %s %s\n",nio->name,nged->dev_name);
1165 }
1166
1167 /* Create a new NetIO descriptor with generic raw Ethernet method */
netio_desc_create_geneth(char * nio_name,char * dev_name)1168 netio_desc_t *netio_desc_create_geneth(char *nio_name,char *dev_name)
1169 {
1170 netio_geneth_desc_t *nged;
1171 netio_desc_t *nio;
1172
1173 if (!(nio = netio_create(nio_name)))
1174 return NULL;
1175
1176 nged = &nio->u.nged;
1177
1178 if (strlen(dev_name) >= NETIO_DEV_MAXLEN) {
1179 fprintf(stderr,"netio_desc_create_geneth: bad Ethernet device string "
1180 "specified.\n");
1181 netio_free(nio,NULL);
1182 return NULL;
1183 }
1184
1185 strcpy(nged->dev_name,dev_name);
1186
1187 if (!(nged->pcap_dev = gen_eth_init(dev_name))) {
1188 netio_free(nio,NULL);
1189 return NULL;
1190 }
1191
1192 nio->type = NETIO_TYPE_GEN_ETH;
1193 nio->send = (void *)netio_geneth_send;
1194 nio->recv = (void *)netio_geneth_recv;
1195 nio->free = (void *)netio_geneth_free;
1196 nio->save_cfg = netio_geneth_save_cfg;
1197 nio->dptr = &nio->u.nged;
1198
1199 if (netio_record(nio) == -1) {
1200 netio_free(nio,NULL);
1201 return NULL;
1202 }
1203
1204 return nio;
1205 }
1206 #endif /* GEN_ETH */
1207
1208 /*
1209 * =========================================================================
1210 * FIFO Driver (intra-hypervisor communications)
1211 * =========================================================================
1212 */
1213
1214 /* Extract the first packet of the FIFO */
netio_fifo_extract_pkt(netio_fifo_desc_t * nfd)1215 static netio_fifo_pkt_t *netio_fifo_extract_pkt(netio_fifo_desc_t *nfd)
1216 {
1217 netio_fifo_pkt_t *p;
1218
1219 if (!(p = nfd->head))
1220 return NULL;
1221
1222 nfd->pkt_count--;
1223 nfd->head = p->next;
1224
1225 if (!nfd->head)
1226 nfd->last = NULL;
1227
1228 return p;
1229 }
1230
1231 /* Insert a packet into the FIFO (in tail) */
netio_fifo_insert_pkt(netio_fifo_desc_t * nfd,netio_fifo_pkt_t * p)1232 static void netio_fifo_insert_pkt(netio_fifo_desc_t *nfd,netio_fifo_pkt_t *p)
1233 {
1234 pthread_mutex_lock(&nfd->lock);
1235
1236 nfd->pkt_count++;
1237 p->next = NULL;
1238
1239 if (nfd->last) {
1240 nfd->last->next = p;
1241 } else {
1242 nfd->head = p;
1243 }
1244
1245 nfd->last = p;
1246 pthread_mutex_unlock(&nfd->lock);
1247 }
1248
1249 /* Free the packet list */
netio_fifo_free_pkt_list(netio_fifo_desc_t * nfd)1250 static void netio_fifo_free_pkt_list(netio_fifo_desc_t *nfd)
1251 {
1252 netio_fifo_pkt_t *p,*next;
1253
1254 for(p=nfd->head;p;p=next) {
1255 next = p->next;
1256 free(p);
1257 }
1258
1259 nfd->head = nfd->last = NULL;
1260 nfd->pkt_count = 0;
1261 }
1262
1263 /* Establish a cross-connect between two FIFO NetIO */
netio_fifo_crossconnect(netio_desc_t * a,netio_desc_t * b)1264 int netio_fifo_crossconnect(netio_desc_t *a,netio_desc_t *b)
1265 {
1266 netio_fifo_desc_t *pa,*pb;
1267
1268 if ((a->type != NETIO_TYPE_FIFO) || (b->type != NETIO_TYPE_FIFO))
1269 return(-1);
1270
1271 pa = &a->u.nfd;
1272 pb = &b->u.nfd;
1273
1274 /* A => B */
1275 pthread_mutex_lock(&pa->endpoint_lock);
1276 pthread_mutex_lock(&pa->lock);
1277 pa->endpoint = pb;
1278 netio_fifo_free_pkt_list(pa);
1279 pthread_mutex_unlock(&pa->lock);
1280 pthread_mutex_unlock(&pa->endpoint_lock);
1281
1282 /* B => A */
1283 pthread_mutex_lock(&pb->endpoint_lock);
1284 pthread_mutex_lock(&pb->lock);
1285 pb->endpoint = pa;
1286 netio_fifo_free_pkt_list(pb);
1287 pthread_mutex_unlock(&pb->lock);
1288 pthread_mutex_unlock(&pb->endpoint_lock);
1289 return(0);
1290 }
1291
1292 /* Unbind an endpoint */
netio_fifo_unbind_endpoint(netio_fifo_desc_t * nfd)1293 static void netio_fifo_unbind_endpoint(netio_fifo_desc_t *nfd)
1294 {
1295 pthread_mutex_lock(&nfd->endpoint_lock);
1296 nfd->endpoint = NULL;
1297 pthread_mutex_unlock(&nfd->endpoint_lock);
1298 }
1299
1300 /* Free a NetIO FIFO descriptor */
netio_fifo_free(netio_fifo_desc_t * nfd)1301 static void netio_fifo_free(netio_fifo_desc_t *nfd)
1302 {
1303 if (nfd->endpoint)
1304 netio_fifo_unbind_endpoint(nfd->endpoint);
1305
1306 netio_fifo_free_pkt_list(nfd);
1307 pthread_mutex_destroy(&nfd->lock);
1308 pthread_cond_destroy(&nfd->cond);
1309 }
1310
1311 /* Send a packet (to the endpoint FIFO) */
netio_fifo_send(netio_fifo_desc_t * nfd,void * pkt,size_t pkt_len)1312 static ssize_t netio_fifo_send(netio_fifo_desc_t *nfd,void *pkt,size_t pkt_len)
1313 {
1314 netio_fifo_pkt_t *p;
1315 size_t len;
1316
1317 pthread_mutex_lock(&nfd->endpoint_lock);
1318
1319 /* The cross-connect must have been established before */
1320 if (!nfd->endpoint)
1321 goto error;
1322
1323 /* Allocate a a new packet and insert it into the endpoint FIFO */
1324 len = sizeof(netio_fifo_pkt_t) + pkt_len;
1325 if (!(p = malloc(len)))
1326 goto error;
1327
1328 memcpy(p->pkt,pkt,pkt_len);
1329 p->pkt_len = pkt_len;
1330 netio_fifo_insert_pkt(nfd->endpoint,p);
1331 pthread_cond_signal(&nfd->endpoint->cond);
1332 pthread_mutex_unlock(&nfd->endpoint_lock);
1333 return(pkt_len);
1334
1335 error:
1336 pthread_mutex_unlock(&nfd->endpoint_lock);
1337 return(-1);
1338 }
1339
1340 /* Read a packet from the local FIFO queue */
netio_fifo_recv(netio_fifo_desc_t * nfd,void * pkt,size_t max_len)1341 static ssize_t netio_fifo_recv(netio_fifo_desc_t *nfd,void *pkt,size_t max_len)
1342 {
1343 struct timespec ts;
1344 m_tmcnt_t expire;
1345 netio_fifo_pkt_t *p;
1346 size_t len = -1;
1347
1348 /* Wait for the endpoint to signal a new arriving packet */
1349 expire = m_gettime_usec() + 50000;
1350 ts.tv_sec = expire / 1000000;
1351 ts.tv_nsec = (expire % 1000000) * 1000;
1352
1353 pthread_mutex_lock(&nfd->lock);
1354 pthread_cond_timedwait(&nfd->cond,&nfd->lock,&ts);
1355
1356 /* Extract a packet from the list */
1357 p = netio_fifo_extract_pkt(nfd);
1358 pthread_mutex_unlock(&nfd->lock);
1359
1360 if (p) {
1361 len = m_min(p->pkt_len,max_len);
1362 memcpy(pkt,p->pkt,len);
1363 free(p);
1364 }
1365
1366 return(len);
1367 }
1368
1369 /* Create a new NetIO descriptor with FIFO method */
netio_desc_create_fifo(char * nio_name)1370 netio_desc_t *netio_desc_create_fifo(char *nio_name)
1371 {
1372 netio_fifo_desc_t *nfd;
1373 netio_desc_t *nio;
1374
1375 if (!(nio = netio_create(nio_name)))
1376 return NULL;
1377
1378 nfd = &nio->u.nfd;
1379 pthread_mutex_init(&nfd->lock,NULL);
1380 pthread_mutex_init(&nfd->endpoint_lock,NULL);
1381 pthread_cond_init(&nfd->cond,NULL);
1382
1383 nio->type = NETIO_TYPE_FIFO;
1384 nio->send = (void *)netio_fifo_send;
1385 nio->recv = (void *)netio_fifo_recv;
1386 nio->free = (void *)netio_fifo_free;
1387 nio->dptr = nfd;
1388
1389 if (netio_record(nio) == -1) {
1390 netio_free(nio,NULL);
1391 return NULL;
1392 }
1393
1394 return nio;
1395 }
1396
1397 /*
1398 * =========================================================================
1399 * NULL Driver (does nothing, used for debugging)
1400 * =========================================================================
1401 */
netio_null_send(void * null_ptr,void * pkt,size_t pkt_len)1402 static ssize_t netio_null_send(void *null_ptr,void *pkt,size_t pkt_len)
1403 {
1404 return(pkt_len);
1405 }
1406
netio_null_recv(void * null_ptr,void * pkt,size_t max_len)1407 static ssize_t netio_null_recv(void *null_ptr,void *pkt,size_t max_len)
1408 {
1409 usleep(200000);
1410 return(-1);
1411 }
1412
netio_null_save_cfg(netio_desc_t * nio,FILE * fd)1413 static void netio_null_save_cfg(netio_desc_t *nio,FILE *fd)
1414 {
1415 fprintf(fd,"nio create_null %s\n",nio->name);
1416 }
1417
1418 /* Create a new NetIO descriptor with NULL method */
netio_desc_create_null(char * nio_name)1419 netio_desc_t *netio_desc_create_null(char *nio_name)
1420 {
1421 netio_desc_t *nio;
1422
1423 if (!(nio = netio_create(nio_name)))
1424 return NULL;
1425
1426 nio->type = NETIO_TYPE_NULL;
1427 nio->send = (void *)netio_null_send;
1428 nio->recv = (void *)netio_null_recv;
1429 nio->save_cfg = netio_null_save_cfg;
1430 nio->dptr = NULL;
1431
1432 if (netio_record(nio) == -1) {
1433 netio_free(nio,NULL);
1434 return NULL;
1435 }
1436
1437 return nio;
1438 }
1439
1440 /* Free a NetIO descriptor */
netio_free(void * data,void * arg)1441 static int netio_free(void *data,void *arg)
1442 {
1443 netio_desc_t *nio = data;
1444
1445 if (nio) {
1446 netio_filter_unbind(nio,NETIO_FILTER_DIR_RX);
1447 netio_filter_unbind(nio,NETIO_FILTER_DIR_TX);
1448 netio_filter_unbind(nio,NETIO_FILTER_DIR_BOTH);
1449
1450 if (nio->free != NULL)
1451 nio->free(nio->dptr);
1452
1453 free(nio->name);
1454 free(nio);
1455 }
1456
1457 return(TRUE);
1458 }
1459
1460 /* Reset NIO statistics */
netio_reset_stats(netio_desc_t * nio)1461 void netio_reset_stats(netio_desc_t *nio)
1462 {
1463 nio->stats_pkts_in = nio->stats_pkts_out = 0;
1464 nio->stats_bytes_in = nio->stats_bytes_out = 0;
1465 }
1466
1467 /* Indicate if a NetIO can transmit a packet */
netio_can_transmit(netio_desc_t * nio)1468 int netio_can_transmit(netio_desc_t *nio)
1469 {
1470 u_int bw_current;
1471
1472 /* No bandwidth constraint applied, can always transmit */
1473 if (!nio->bandwidth)
1474 return(TRUE);
1475
1476 /* Check that we verify the bandwidth constraint */
1477 bw_current = nio->bw_cnt_total * 8 * 1000;
1478 bw_current /= 1024 * NETIO_BW_SAMPLE_ITV * NETIO_BW_SAMPLES;
1479
1480 return(bw_current < nio->bandwidth);
1481 }
1482
1483 /* Update bandwidth counter */
netio_update_bw_stat(netio_desc_t * nio,m_uint64_t bytes)1484 void netio_update_bw_stat(netio_desc_t *nio,m_uint64_t bytes)
1485 {
1486 nio->bw_cnt[nio->bw_pos] += bytes;
1487 nio->bw_cnt_total += bytes;
1488 }
1489
1490 /* Reset NIO bandwidth counter */
netio_clear_bw_stat(netio_desc_t * nio)1491 void netio_clear_bw_stat(netio_desc_t *nio)
1492 {
1493 if (++nio->bw_ptask_cnt == (NETIO_BW_SAMPLE_ITV / ptask_sleep_time)) {
1494 nio->bw_ptask_cnt = 0;
1495
1496 if (++nio->bw_pos == NETIO_BW_SAMPLES)
1497 nio->bw_pos = 0;
1498
1499 nio->bw_cnt_total -= nio->bw_cnt[nio->bw_pos];
1500 nio->bw_cnt[nio->bw_pos] = 0;
1501 }
1502 }
1503
1504 /* Set the bandwidth constraint */
netio_set_bandwidth(netio_desc_t * nio,u_int bandwidth)1505 void netio_set_bandwidth(netio_desc_t *nio,u_int bandwidth)
1506 {
1507 nio->bandwidth = bandwidth;
1508 }
1509
1510 /*
1511 * =========================================================================
1512 * RX Listeners
1513 * =========================================================================
1514 */
1515
1516 /* Find a RX listener */
netio_rxl_find(netio_desc_t * nio)1517 static inline struct netio_rx_listener *netio_rxl_find(netio_desc_t *nio)
1518 {
1519 struct netio_rx_listener *rxl;
1520
1521 for(rxl=netio_rxl_list;rxl;rxl=rxl->next)
1522 if (rxl->nio == nio)
1523 return rxl;
1524
1525 return NULL;
1526 }
1527
1528 /* Remove a NIO from the listener list */
netio_rxl_remove_internal(netio_desc_t * nio)1529 static int netio_rxl_remove_internal(netio_desc_t *nio)
1530 {
1531 struct netio_rx_listener *rxl;
1532 int res = -1;
1533
1534 if ((rxl = netio_rxl_find(nio))) {
1535 /* we suppress this NIO only when the ref count hits 0 */
1536 rxl->ref_count--;
1537
1538 if (!rxl->ref_count) {
1539 /* remove this listener from the double linked list */
1540 if (rxl->next)
1541 rxl->next->prev = rxl->prev;
1542
1543 if (rxl->prev)
1544 rxl->prev->next = rxl->next;
1545 else
1546 netio_rxl_list = rxl->next;
1547
1548 /* if this is non-FD NIO, wait for thread to terminate */
1549 if (netio_get_fd(rxl->nio) == -1) {
1550 rxl->running = FALSE;
1551 pthread_join(rxl->spec_thread,NULL);
1552 }
1553
1554 free(rxl);
1555 }
1556
1557 res = 0;
1558 }
1559
1560 return(res);
1561 }
1562
1563 /* Add a RXL listener to the listener list */
netio_rxl_add_internal(struct netio_rx_listener * rxl)1564 static void netio_rxl_add_internal(struct netio_rx_listener *rxl)
1565 {
1566 struct netio_rx_listener *tmp;
1567
1568 if ((tmp = netio_rxl_find(rxl->nio))) {
1569 tmp->ref_count++;
1570 free(rxl);
1571 } else {
1572 rxl->prev = NULL;
1573 rxl->next = netio_rxl_list;
1574 if (rxl->next) rxl->next->prev = rxl;
1575 netio_rxl_list = rxl;
1576 }
1577 }
1578
1579 /* RX Listener dedicated thread (for non-FD NIO) */
netio_rxl_spec_thread(void * arg)1580 static void *netio_rxl_spec_thread(void *arg)
1581 {
1582 struct netio_rx_listener *rxl = arg;
1583 netio_desc_t *nio = rxl->nio;
1584 ssize_t pkt_len;
1585
1586 while(rxl->running) {
1587 pkt_len = netio_recv(nio,nio->rx_pkt,sizeof(nio->rx_pkt));
1588
1589 if (pkt_len > 0)
1590 rxl->rx_handler(nio,nio->rx_pkt,pkt_len,rxl->arg1,rxl->arg2);
1591 }
1592
1593 return NULL;
1594 }
1595
1596 /* RX Listener General Thread */
netio_rxl_gen_thread(void * arg)1597 void *netio_rxl_gen_thread(void *arg)
1598 {
1599 struct netio_rx_listener *rxl;
1600 ssize_t pkt_len;
1601 netio_desc_t *nio;
1602 struct timeval tv;
1603 int fd,fd_max,res;
1604 fd_set rfds;
1605
1606 for(;;) {
1607 NETIO_RXL_LOCK();
1608
1609 NETIO_RXQ_LOCK();
1610 /* Add the new waiting NIO to the active list */
1611 while(netio_rxl_add_list != NULL) {
1612 rxl = netio_rxl_add_list;
1613 netio_rxl_add_list = netio_rxl_add_list->next;
1614 netio_rxl_add_internal(rxl);
1615 }
1616
1617 /* Delete the NIO present in the remove list */
1618 while(netio_rxl_remove_list != NULL) {
1619 nio = netio_rxl_remove_list;
1620 netio_rxl_remove_list = netio_rxl_remove_list->rxl_next;
1621 netio_rxl_remove_internal(nio);
1622 }
1623
1624 pthread_cond_broadcast(&netio_rxl_cond);
1625 NETIO_RXQ_UNLOCK();
1626
1627 /* Build the FD set */
1628 FD_ZERO(&rfds);
1629 fd_max = -1;
1630 for(rxl=netio_rxl_list;rxl;rxl=rxl->next) {
1631 if ((fd = netio_get_fd(rxl->nio)) == -1)
1632 continue;
1633
1634 if (fd > fd_max) fd_max = fd;
1635 FD_SET(fd,&rfds);
1636 }
1637 NETIO_RXL_UNLOCK();
1638
1639 /* Wait for incoming packets */
1640 tv.tv_sec = 0;
1641 tv.tv_usec = 20 * 1000; /* 200 ms */
1642 res = select(fd_max+1,&rfds,NULL,NULL,&tv);
1643
1644 if (res == -1) {
1645 if (errno != EINTR)
1646 perror("netio_rxl_thread: select");
1647 continue;
1648 }
1649
1650 /* Examine active FDs and call user handlers */
1651 NETIO_RXL_LOCK();
1652
1653 for(rxl=netio_rxl_list;rxl;rxl=rxl->next) {
1654 nio = rxl->nio;
1655
1656 if ((fd = netio_get_fd(nio)) == -1)
1657 continue;
1658
1659 if (FD_ISSET(fd,&rfds)) {
1660 pkt_len = netio_recv(nio,nio->rx_pkt,sizeof(nio->rx_pkt));
1661
1662 if (pkt_len > 0)
1663 rxl->rx_handler(nio,nio->rx_pkt,pkt_len,rxl->arg1,rxl->arg2);
1664 }
1665 }
1666
1667 NETIO_RXL_UNLOCK();
1668 }
1669
1670 return NULL;
1671 }
1672
1673 /* Add a RX listener in the listener list */
netio_rxl_add(netio_desc_t * nio,netio_rx_handler_t rx_handler,void * arg1,void * arg2)1674 int netio_rxl_add(netio_desc_t *nio,netio_rx_handler_t rx_handler,
1675 void *arg1,void *arg2)
1676 {
1677 struct netio_rx_listener *rxl;
1678
1679 NETIO_RXQ_LOCK();
1680
1681 if (!(rxl = malloc(sizeof(*rxl)))) {
1682 NETIO_RXQ_UNLOCK();
1683 fprintf(stderr,"netio_rxl_add: unable to create structure.\n");
1684 return(-1);
1685 }
1686
1687 memset(rxl,0,sizeof(*rxl));
1688 rxl->nio = nio;
1689 rxl->ref_count = 1;
1690 rxl->rx_handler = rx_handler;
1691 rxl->arg1 = arg1;
1692 rxl->arg2 = arg2;
1693 rxl->running = TRUE;
1694
1695 if ((netio_get_fd(rxl->nio) == -1) &&
1696 pthread_create(&rxl->spec_thread,NULL,netio_rxl_spec_thread,rxl))
1697 {
1698 NETIO_RXQ_UNLOCK();
1699 fprintf(stderr,"netio_rxl_add: unable to create specific thread.\n");
1700 free(rxl);
1701 return(-1);
1702 }
1703
1704 rxl->next = netio_rxl_add_list;
1705 netio_rxl_add_list = rxl;
1706
1707 pthread_cond_wait(&netio_rxl_cond,&netio_rxq_mutex);
1708 NETIO_RXQ_UNLOCK();
1709 return(0);
1710 }
1711
1712 /* Remove a NIO from the listener list */
netio_rxl_remove(netio_desc_t * nio)1713 int netio_rxl_remove(netio_desc_t *nio)
1714 {
1715 NETIO_RXQ_LOCK();
1716 nio->rxl_next = netio_rxl_remove_list;
1717 netio_rxl_remove_list = nio;
1718 pthread_cond_wait(&netio_rxl_cond,&netio_rxq_mutex);
1719 NETIO_RXQ_UNLOCK();
1720 return(0);
1721 }
1722
1723 /* Initialize the RXL thread */
netio_rxl_init(void)1724 int netio_rxl_init(void)
1725 {
1726 pthread_cond_init(&netio_rxl_cond,NULL);
1727
1728 if (pthread_create(&netio_rxl_thread,NULL,netio_rxl_gen_thread,NULL)) {
1729 perror("netio_rxl_init: pthread_create");
1730 return(-1);
1731 }
1732
1733 return(0);
1734 }
1735