1 /* VDE_ROUTER (C) 2007 Daniele Lacamera
3 * Licensed under the GPLv2
5 * This is a tiny v4 router that can be used to link
6 * together two or more vde switches.
23 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
31 #include <libvdeplug.h>
35 #include <vdecommon.h>
43 #if defined(VDE_FREEBSD) || defined(VDE_DARWIN)
44 #define ICMP_DEST_UNREACH 3
45 #define ICMP_PROT_UNREACH 2
49 * The main structure. Contains: interfaces, routing table,
52 struct vde_router VDEROUTER
;
56 /* This is the default routing policy ( Unlimited fifo )
60 int ufifo_enqueue(struct vde_buff
*vdb
, struct vde_iface
*vif
)
62 struct vde_buff
*qo
= vif
->q_out
;
67 while (qo
->next
!=NULL
){
74 int ufifo_dequeue(struct vde_iface
*vif
){
75 struct vde_buff
*vdb_out
=vif
->q_out
;
76 raw_send(vif
,vdb_out
);
77 vif
->q_out
=vdb_out
->next
;
78 return (vif
->q_out
?1:0);
81 int ufifo_init(struct vde_iface
*vif
, char *args
)
83 vif
->policy_name
= "ufifo";
84 return (strlen(args
) == 0);
87 char *nostats(struct vde_iface
*vif
)
89 return "No Statistics Available.";
93 struct routing_policy unlimited_fifo_routing_policy
={
95 .help
= "Unlimited FIFO (Default)\nUsage: tc set <dev> ufifo\n",
96 .enqueue
= ufifo_enqueue
,
97 .dequeue
= ufifo_dequeue
,
99 .policy_init
= ufifo_init
103 inline struct vde_ethernet_header
*ethhead(struct vde_buff
*vdb
)
105 return (struct vde_ethernet_header
*)(vdb
->data
);
108 inline struct iphdr
*iphead(struct vde_buff
*vdb
)
110 return (struct iphdr
*)(vdb
->data
+ 14);
113 inline void *payload(struct vde_buff
*vdb
)
115 return (uint8_t*)(vdb
->data
+ 14 + sizeof(struct iphdr
));
119 tcpriv(struct vde_iface
*vi
)
121 return (void *)(vi
->tc_priv
);
124 void policy_register(struct routing_policy
*r
)
126 struct routing_policy
*p
= VDEROUTER
.modlist
;
128 VDEROUTER
.modlist
= r
;
131 while (p
->next
!=NULL
){
138 struct routing_policy
*getpolicy(char *name
)
140 struct routing_policy
*p
= VDEROUTER
.modlist
;
141 struct routing_policy
*new;
143 char libname
[300],libname2
[300],libname3
[300];
144 snprintf(libname
,255,"%s.so",name
);
145 snprintf(libname2
,255,"/usr/lib/vde2/vde_l3/%s.so",name
);
146 snprintf(libname3
,255,"/usr/local/lib/vde2/vde_l3/%s.so",name
);
149 if (!strncmp(name
,p
->name
,255))
155 di
= dlopen(libname
,RTLD_LAZY
);
157 di
= dlopen(libname2
,RTLD_LAZY
);
159 di
= dlopen(libname3
,RTLD_LAZY
);
162 fprintf(stderr
,"Error loading module %s: %s\n",libname
,dlerror());
165 new = (struct routing_policy
*) dlsym(di
,"module_routing_policy");
167 policy_register(new);
170 fprintf(stderr
,"Error registering module %s: %s\n",libname
,dlerror());
178 void set_interface_policy (struct vde_iface
*vif
, struct routing_policy
*rp
)
180 vif
->enqueue
= rp
->enqueue
;
181 vif
->dequeue
= rp
->dequeue
;
184 vif
->tc_stats
= rp
->tc_stats
;
186 vif
->tc_stats
= nostats
;
188 vif
->policy_init
= rp
->policy_init
;
193 static const int mgmtmode
=0700;
194 static int max_total_sockets
=0;
196 static char *progname
;
199 /* Small utility functions, to talk to humans.
201 static char *ip2ascii(uint32_t ip
){
202 struct in_addr ia_be
;
203 ia_be
.s_addr
= htonl(ip
);
204 return(strdup(inet_ntoa(ia_be
)));
207 uint8_t *ip2mac(uint32_t ip
)
209 uint8_t *ret
=(uint8_t *) malloc(6);
210 uint32_t bigendian_ip
= htonl(ip
);
213 memcpy(ret
+2,&bigendian_ip
,4);
218 static char *mac2ascii(uint8_t *mac
){
219 char *res
= calloc(1,18);
220 snprintf(res
,18,"%02X:%02X:%02X:%02X:%02X:%02X", mac
[0],mac
[1],mac
[2],mac
[3],mac
[4],mac
[5]);
226 * Get an interface from its id
228 static struct vde_iface
*get_interface(int id
){
229 struct vde_iface
*ifc
= VDEROUTER
.interfaces
;
242 fprintf(stderr
,"Usage: %s [-G default_gw] -v vde_sock1:ipaddess1/netmask1 [-v ...] [-v vde_sockN:ipaddessN/netmaskN]\n",p
);
243 fprintf(stderr
," [-r network/netmask:gateway ] [-r ...] \n");
245 fprintf(stderr
,"Options:\n");
246 fprintf(stderr
,"-v VDESOCK:ADDRESS/NETMASK adds a network interface\n" \
247 "\twith address ADDRESS and netmask NETMASK. \n" \
248 "\tThe interface is connected to the vde socket VDESOCK.\n" \
249 "\t(At least one '-v' argument is required.)\n" \
252 fprintf(stderr
,"-r ADDRESS/NETMASK:GATEWAY adds a static route to the network\n" \
253 "\tADDRESS with netmask NETMASK, through the gateway GATEWAY. \n" \
255 fprintf(stderr
,"-G ADDRESS sets the router default gateway to ADDRESS.\n" \
263 /* physically copy a vde_buff
265 struct vde_buff
*buff_clone( struct vde_buff
*orig
)
267 struct vde_buff
*clone
= (struct vde_buff
*)calloc(1,sizeof(struct vde_buff
));
268 memcpy (clone
,orig
,sizeof(struct vde_buff
));
269 clone
->data
= (char *)calloc(1,orig
->len
);
270 memcpy(clone
->data
,orig
->data
,orig
->len
);
275 * Send a packet directly using the ethernet
277 size_t raw_send(struct vde_iface
*of
,struct vde_buff
*vdb
)
280 fprintf(stderr
,"Sending a %luB packet. VDECONN@%p. Protocol = %d through iface %d.\n",vdb
->len
,&(of
->vdec
),ntohs(*((uint16_t *)(vdb
->data
+12))),of
->id
);
282 return vde_send(of
->vdec
,vdb
->data
,vdb
->len
,0);
286 int ip_input(struct vde_buff
*vdb
);
287 int ip_output(struct vde_buff
*vdb
, uint32_t dst
, uint8_t protocol
);
288 size_t arp_query(struct vde_iface
*oif
, uint32_t tgt
);
289 struct vde_iface
*is_neightbor(uint32_t addr
);
294 int ip_output_ready(struct vde_buff
*vdb
){
295 struct iphdr
*iph
= iphead(vdb
);
296 return ip_output(vdb
,ntohl(iph
->daddr
), iph
->protocol
);
303 static struct vde_iface
*add_iface(struct vde_iface
*new, struct vde_iface
*list
)
308 list
->next
=add_iface(new,list
->next
);
312 static struct vde_route
*add_route(struct vde_route
*new, struct vde_route
*list
)
317 list
->next
=add_route(new,list
->next
);
321 static struct arp_entry
*add_arp_entry(struct arp_entry
*new, struct arp_entry
*list
)
326 list
->next
=add_arp_entry(new,list
->next
);
331 /* Dequeue all pending packets that were
332 * waiting for arp IP/MAC association.
334 static void dequeue_pending(uint32_t addr
)
336 struct vde_buff
*pq
= VDEROUTER
.arp_pending
;
337 struct vde_buff
*tmp
;
338 struct iphdr
*h
=iphead(pq
);
339 if(ntohs(h
->daddr
) == addr
){
340 ip_output(pq
, addr
, h
->protocol
);
341 VDEROUTER
.arp_pending
= pq
->next
;
345 if (h
->daddr
== addr
) {
346 ip_output(pq
->next
,addr
,h
->protocol
);
348 pq
->next
= tmp
->next
;
356 * Get an arp entry from its ip.
358 static struct arp_entry
*get_arp_entry(uint32_t ipaddr
)
360 struct arp_entry
*a
=VDEROUTER
.arp_table
;
362 if (a
->ipaddr
== ipaddr
)
370 /* Prepare a vde_buff to be sent through a local interface
372 int neightbor_send(struct vde_iface
*to
, struct vde_buff
*vdb
)
374 struct arp_entry
*ae
;
375 struct vde_ethernet_header
*he
;
376 struct iphdr
*iph
= iphead(vdb
);
378 ae
= get_arp_entry(iph
->daddr
);
381 memcpy(he
->src
,to
->mac
, 6);
382 memcpy(he
->dst
,ae
->mac
, 6);
383 packets_in
= to
->enqueue(vdb
,to
);
387 // VDEROUTER.arp_pending=enqueue(vdb,VDEROUTER.arp_pending);
388 arp_query(to
, ntohl(iph
->daddr
));
393 /* Prepare a vde_buff to be sent through a gateway
395 int gateway_send(struct vde_buff
*vdb
, uint32_t gw
)
397 struct arp_entry
*ae
;
398 struct vde_ethernet_header
*he
;
399 struct vde_iface
*to
= is_neightbor(gw
);
401 ae
= get_arp_entry(htonl(gw
));
404 memcpy(he
->src
,to
->mac
, 6);
405 memcpy(he
->dst
,ae
->mac
, 6);
406 packets_in
= to
->enqueue(vdb
,to
);
409 memset(he
->dst
, 0, 6);
410 // VDEROUTER.arp_pending=enqueue(vdb,VDEROUTER.arp_pending);
418 * Swap src/dst mac addresses at given mem addresses
420 static void swap_macaddr(uint8_t addr1
[], uint8_t addr2
[])
424 memcpy(addr1
,addr2
,6);
429 * Swap src/dst ip addresses at given mem addresses
431 static void swap_ipaddr(uint32_t *addr1
, uint32_t *addr2
)
434 memcpy(&tmp
,addr1
,4);
435 memcpy(addr1
,addr2
,4);
436 memcpy(addr2
,&tmp
,4);
441 * Allocate a new vde_buff packet of given size
443 static struct vde_buff
*vdebuff_alloc(size_t size
)
445 struct vde_buff
*ret
;
446 struct vde_ethernet_header
*veh
;
449 ret
=(struct vde_buff
*)calloc(1,sizeof(struct vde_buff
));
450 // fprintf(stderr,"ALLOCATING %lu Bytes of memory: ",size);
451 ret
->data
=(char *)calloc(1,size
+1);
452 if(ret
==NULL
|| ret
->data
==NULL
){
453 perror("Out of Memory.\n");
456 // fprintf(stderr,"Done.\n",size);
458 // Set default packet type (IP)
459 veh
->buftype
= htons(PTYPE_IP
);
466 * Gets interface's mac address in a new array
468 static inline char *macaddr(struct vde_iface
*vif
)
470 char *mac
=(char*)calloc(1,ETHERNET_ADDRESS_SIZE
);
471 memcpy(mac
,vif
->mac
,6);
477 size_t vde_router_receive(struct vde_iface i
)
485 int is_arp_pending(struct vde_iface
*of
, uint8_t *mac
){return 0;}
492 * Prepare and send an arp query
494 size_t arp_query(struct vde_iface
*oif
, uint32_t tgt
)
496 struct vde_ethernet_header
*vdeh
;
497 struct arp_header
*ah
;
498 struct vde_buff
*vdb
;
500 /* Allocate 60B buffer for ARP request */
501 vdb
= vdebuff_alloc(60);
503 /* populate eth header */
505 memcpy(vdeh
->dst
, ETH_BCAST
, 6);
506 memcpy(vdeh
->src
, oif
->mac
,6);
507 vdeh
->buftype
= htons(PTYPE_ARP
);
509 /* build arp payload */
510 ah
=(struct arp_header
*)iphead(vdb
);
511 ah
->htype
= htons(HTYPE_ETH
);
512 ah
->ptype
= htons(PTYPE_IP
);
513 ah
->hsize
= ETHERNET_ADDRESS_SIZE
;
514 ah
->psize
= IP_ADDRESS_SIZE
;
515 ah
->opcode
= htons(ARP_REQUEST
);
516 memcpy(ah
->s_mac
, oif
->mac
,6);
517 ah
->s_addr
= htonl(oif
->ipaddr
);
518 memset(ah
->d_mac
,0,6);
519 ah
->d_addr
= htonl(tgt
);
521 return(raw_send(oif
,vdb
));
526 * Reply to given arp request, if needed
528 size_t arp_reply(struct vde_iface
*oif
, struct vde_buff
*vdb
)
530 struct vde_ethernet_header
*vdeh
;
531 struct arp_header
*ah
;
533 swap_macaddr(vdeh
->src
,vdeh
->dst
);
534 memcpy(vdeh
->src
,oif
->mac
,6);
535 ah
=(struct arp_header
*)iphead(vdb
);
536 ah
->opcode
= htons(ARP_REPLY
);
537 swap_macaddr(ah
->s_mac
, ah
->d_mac
);
538 memcpy(ah
->s_mac
, oif
->mac
,6);
539 swap_ipaddr(&(ah
->s_addr
), &(ah
->d_addr
));
541 return(raw_send(oif
,vdb
));
546 /* Internet Protocol */
548 /* get the interface struct from its address
550 struct vde_iface
*get_iface_by_ipaddr(uint32_t addr
)
552 struct vde_iface
*vif
= VDEROUTER
.interfaces
;
554 if(vif
->ipaddr
== addr
)
562 * Gets the interface through which we should be able to reach
563 * the given ip address. If the destination is not a neighbor,
564 * returns a NULL pointer.
566 struct vde_iface
*is_neightbor(uint32_t addr
)
568 struct vde_iface
*vif
= VDEROUTER
.interfaces
;
570 if((vif
->ipaddr
&vif
->nm
) == (addr
&vif
->nm
))
580 * Returns the ip address of the gateway for this destination.
581 * If more than one route matches, the route with the stricter
584 uint32_t get_gateway(uint32_t addr
)
586 struct vde_route
*vdr
= VDEROUTER
.route_table
;
588 uint32_t max_netmask
= 0;
590 if((vdr
->network
& vdr
->nm
) == (addr
& vdr
->nm
) && vdr
->nm
> max_netmask
){
592 max_netmask
= vdr
->nm
;
597 return VDEROUTER
.default_gw
;
601 /* Parse an incoming arp packet */
602 int parse_arp(struct vde_buff
*vdb
)
604 struct arp_header
*ah
;
605 struct vde_iface
*vif
;
606 struct arp_entry
*ae
=(struct arp_entry
*)malloc(sizeof(struct arp_entry
));;
607 ah
= (struct arp_header
*)iphead(vdb
);
608 vif
= get_iface_by_ipaddr(ntohl(ah
->d_addr
));
612 memcpy(ae
->mac
,ah
->s_mac
,6);
613 ae
->ipaddr
=ah
->s_addr
;
615 VDEROUTER
.arp_table
= add_arp_entry(ae
,VDEROUTER
.arp_table
);
616 switch(ntohs(ah
->opcode
)){
621 if(is_arp_pending(vif
,ah
->s_mac
)){
622 dequeue_pending(ntohl(ah
->s_addr
));
633 * Wrapper for neightbor/gateway send
636 int ip_send(struct vde_buff
*vdb
)
638 struct vde_iface
*oif
;
639 struct iphdr
*iph
=iphead(vdb
);
641 oif
= is_neightbor(ntohl(iph
->daddr
));
643 return neightbor_send(oif
,vdb
);
645 gateway
= get_gateway(ntohl(iph
->daddr
));
647 return gateway_send(vdb
,gateway
);
653 * Forward the ip packet to next hop. TTL is decreased,
654 * checksum is set again for coherence, and TTL overdue
655 * packets are not forwarded.
657 int ip_forward(struct vde_buff
*vdb
){
658 struct iphdr
*iph
=iphead(vdb
);
670 int parse_ip(struct vde_buff
*vdb
)
672 struct vde_ethernet_header
*eh
;
673 struct iphdr
*iph
=iphead(vdb
);
674 struct arp_entry
*ae
;
677 if(!get_arp_entry(iph
->saddr
)){
678 ae
=(struct arp_entry
*)malloc(sizeof(struct arp_entry
));;
679 memcpy(ae
->mac
,eh
->src
,6);
680 ae
->ipaddr
= iph
->saddr
;
681 VDEROUTER
.arp_table
= add_arp_entry(ae
,VDEROUTER
.arp_table
);
683 if (get_iface_by_ipaddr(ntohl(iph
->daddr
))){
684 return ip_input(vdb
);
686 return ip_forward(vdb
);
691 * Calculate checksum of a given string
693 uint16_t checksum(uint8_t *buf
, int len
)
695 uint32_t sum
= 0, carry
=0;
697 for(i
=0; i
<len
; i
++){
704 carry
= (sum
&0xFFFF0000) >>16;
705 sum
= (sum
&0x0000FFFF);
706 return (uint16_t) ~(sum
+ carry
) ;
710 * Calculate ip-header checksum. it's a wrapper for checksum();
712 uint16_t ip_checksum(struct iphdr
*iph
)
715 return checksum((uint8_t*)iph
,sizeof(struct iphdr
));
718 #define DEFAULT_TTL 64
721 * Layer 4 protocols should call this to transmit.
723 int ip_output(struct vde_buff
*vdb
, uint32_t dst
, uint8_t protocol
)
725 struct iphdr
*iph
=iphead(vdb
);
726 struct vde_iface
*oif
;
729 iph
->frag_off
=htons(0x4000); // Don't fragment.
730 iph
->tot_len
= htons(vdb
->len
- sizeof(struct vde_ethernet_header
));
732 iph
->protocol
= protocol
;
733 iph
->ttl
= DEFAULT_TTL
;
734 iph
->check
= htons(ip_checksum(iph
));
736 oif
= is_neightbor(dst
);
738 oif
=is_neightbor(get_gateway(dst
));
742 fprintf(stderr
, "Cannot determine the route to %08x",dst
);
748 iph
->saddr
= htonl(oif
->ipaddr
);
749 iph
->daddr
= htonl(dst
);
750 iph
->check
= htons(ip_checksum(iph
));
755 * Send a ICMP_PROTOCOL_UNREACHABLE if so.
758 static int service_unreachable(struct vde_buff
*buf_in
)
760 struct iphdr
*iph_in
;
762 struct vde_buff
*vdb
;
763 static uint16_t ident
=0;
766 vdb
=vdebuff_alloc(sizeof(struct vde_ethernet_header
) +
767 sizeof(struct iphdr
) + 8);
769 ich
=(struct icmp
*)payload(vdb
);
770 ich
->icmp_type
= ICMP_DEST_UNREACH
;
771 ich
->icmp_code
= ICMP_PROT_UNREACH
;
772 ich
->icmp_hun
.ih_idseq
.icd_id
= ident
++;
773 ich
->icmp_hun
.ih_idseq
.icd_seq
= 0;
777 ich
->icmp_cksum
= htons(checksum(payload(vdb
), vdb
->len
- sizeof(struct iphdr
) - 14));
779 iph_in
= iphead(buf_in
);
780 return ip_output(vdb
,ntohl(iph_in
->saddr
),PROTO_ICMP
);
784 /* Parse an incoming icmp packet
786 int parse_icmp(struct vde_buff
*vdb
)
790 ich
= (struct icmp
*) payload(vdb
);
792 if (ich
->icmp_type
== ICMP_ECHO
){
793 swap_ipaddr(&iph
->saddr
,&iph
->daddr
);
794 ich
->icmp_type
= ICMP_ECHOREPLY
;
796 ich
->icmp_cksum
= htons(checksum(payload(vdb
), vdb
->len
- 34));
797 iph
->check
= htons(ip_checksum(iph
));
800 ip_output_ready(vdb
);
806 // Returns if the ip is unicast
807 static uint32_t inline unicast_ip(uint32_t ip
){
808 if ((ip
& 0xE0000000) == 0xE0000000)
815 uint32_t ascii2ip(char *c
){
816 return (ntohl(inet_addr(c
)));
819 //return >0 for valid netmasks.
820 uint32_t valid_nm(uint32_t nm
)
824 for (i
=31; i
>=0; i
--){
832 uint32_t ascii2nm(char *c
){
833 uint32_t res
=ascii2ip(c
);
836 if (sscanf(c
,"%d",&nmval
)<0){
839 while(nmval
>0 && nmval
<32 && (i
>= (32 - nmval
)))
843 return valid_nm(res
);
846 //check if mac address is multicast
848 static int is_multicast_mac(uint8_t *mac
)
850 if((mac
[0]&0x01) && (mac
[2]&0x5E))
855 static void printoutc(int fd
, const char *format
, ...)
858 char outbuf
[MAXCMD
+1];
860 va_start (arg
, format
);
861 vsnprintf(outbuf
,MAXCMD
,format
,arg
);
863 write(fd
,outbuf
,strlen(outbuf
));
866 static int showinfo(int fd
,char *s
)
871 static int help(int fd
,char *s
)
873 printoutc(fd
, "help Display this inline help");
874 printoutc(fd
, "ifconfig [vdN [ADDRESS [netmask NETMASK]]] Display virtual ethernet options/configure virtual ethernet N");
875 printoutc(fd
, "route list Print out the routing table");
876 printoutc(fd
, "route net ADDRESS/NETMASK gw GATEWAY Add static route");
877 printoutc(fd
, "route default gw GATEWAY Add default route");
878 printoutc(fd
, "tc ls Show each interface routing policy");
879 printoutc(fd
, "tc set DEV POLICY ARGS Change interface routing policy");
880 printoutc(fd
, "shutdown: shut the channel down");
881 printoutc(fd
, "logout: log out from this mgmt session");
886 static int route(int fd
,char *s
)
888 int arglen
=strlen(s
);
889 struct vde_iface
*pi
;
890 struct vde_route
*pr
;
897 if(arglen
== 5 && strncmp(s
,"list",4)==0){
898 printoutc(fd
,"Destination\tGateway\t\tGenmask\t\tIface");
899 pi
= VDEROUTER
.interfaces
;
901 printoutc(fd
,"%s\t%s\t\t%s\t\tvd%d",ip2ascii(pi
->ipaddr
&pi
->nm
),ip2ascii(0),ip2ascii(pi
->nm
),pi
->id
);
904 pr
= VDEROUTER
.route_table
;
906 pi
=is_neightbor(pr
->gw
);
908 printoutc(fd
,"%s\t%s\t\t%s\t\tvd%d",ip2ascii(pr
->network
&pr
->nm
),ip2ascii(pr
->gw
),ip2ascii(pr
->nm
),pi
->id
);
911 pi
=is_neightbor(VDEROUTER
.default_gw
);
912 if(VDEROUTER
.default_gw
)
913 printoutc(fd
,"%s\t\t%s\t\t%s\t\tvd%d",ip2ascii(0),ip2ascii(VDEROUTER
.default_gw
),ip2ascii(0),pi
->id
);
916 if(strncmp(s
,"default gw ",11)==0){
917 VDEROUTER
.default_gw
= unicast_ip(ascii2ip(s
+11));
918 if(!VDEROUTER
.default_gw
){
919 printoutc(fd
,"Invalid gateway.");
922 printoutc(fd
,"Default route changed to %s", ip2ascii(VDEROUTER
.default_gw
));
926 if(strncmp(s
,"net ",4)==0){
928 struct vde_route
*new = malloc (sizeof(struct vde_route
));
940 new->network
= unicast_ip(ascii2ip(addr
));
941 new->gw
= unicast_ip(ascii2ip(gw
));
942 new->nm
= ascii2nm(nm
);
944 pr
= VDEROUTER
.route_table
;
946 if(new->network
== pr
->network
&& new->nm
== pr
->nm
){
948 printoutc(fd
,"Route successfully updated.");
953 VDEROUTER
.route_table
= add_route(new, VDEROUTER
.route_table
);
954 printoutc(fd
,"Route successfully added.");
960 printoutc(fd
, "'route' command usage:");
961 printoutc(fd
, "route list Print out the routing table");
962 printoutc(fd
, "route net ADDRESS/NETMASK:GATEWAY Add/change static route");
963 printoutc(fd
, "route default gw GATEWAY Change default route");
974 static int if_display(int fd
, char *iface
){
975 struct vde_iface
*pi
;
978 if(strncmp(iface
,"all",3)==0){
979 pi
=VDEROUTER
.interfaces
;
982 if(strncmp(iface
,"vd",2)!=0){
986 iface_id
= atoi(iface
+2);
987 pi
= get_interface(iface_id
);
989 printoutc(fd
, "Interface %s not found.",iface
);
995 printoutc(fd
, "vd%d\tLink encap: vde HWaddr %s",pi
->id
, mac2ascii(pi
->mac
));
996 printoutc(fd
, "\tinet addr:%s Netmask:%s", ip2ascii(pi
->ipaddr
), ip2ascii(pi
->nm
));
998 if(showone
) return 0;
1006 static int ifconfig(int fd
, char *s
)
1008 int arglen
=strlen(s
)-1;
1009 struct vde_iface
*pi
;
1010 char *addr
,*nmtag
,*nm
=NULL
,*iface
;
1017 if(if_display(fd
,"all") < 0)
1024 addr
=index(iface
,' ');
1026 if(if_display(fd
,iface
)<0)
1033 nmtag
=index(addr
,' ');
1038 nm
=index(nmtag
,' ');
1045 if(strncmp(iface
,"vd",2)!=0){
1049 iface_id
= atoi(iface
+2);
1050 pi
= get_interface(iface_id
);
1052 printoutc(fd
, "Interface %s not found.",iface
);
1056 tmp
= unicast_ip(ascii2ip(addr
));
1060 printoutc(fd
, "IP address for %s successfully changed.",iface
);
1061 if (mode
== IF_CHALL
){
1066 printoutc(fd
, "Netmask for %s successfully changed.",iface
);
1071 printoutc(fd
, "'ifconfig' command usage:");
1072 printoutc(fd
, "ifconfig [vdN [ADDRESS [netmask NETMASK]]]");
1076 static int traffic_control(int fd
, char *s
)
1078 int arglen
=strlen(s
)-1;
1079 struct vde_iface
*pi
;
1080 struct routing_policy
*pp
;
1081 char *iface
, *policy
, *args
;
1089 if (arglen
== 2 && (strncmp(s
,"ls",2)==0)){
1090 pi
= VDEROUTER
.interfaces
;
1092 printoutc(fd
, "vd%d: %s. %s", pi
->id
, pi
->policy_name
, pi
->tc_stats(pi
));
1099 if (arglen
> 4 && (strncmp(s
,"set",3) == 0)){
1101 policy
=index(iface
,' ');
1103 *(policy
++)=(char)0;
1104 if((strncmp(iface
,"vd",2)) || (sscanf(iface
+2,"%d",&ifnum
)<1))
1106 args
=index(policy
,' ');
1113 if(strlen(policy
)<1)
1116 // check interface existstence
1117 pi
= VDEROUTER
.interfaces
;
1118 while (pi
&& pi
->id
!= ifnum
){
1121 printoutc(fd
, "tc: Device vd%d not found.",ifnum
);
1125 // try to get module
1126 pp
=getpolicy(policy
);
1128 printoutc(fd
, "Cannot load rp module %s.so",policy
);
1131 set_interface_policy(pi
, pp
);
1132 if (!pi
->policy_init(pi
,args
)){
1133 printoutc(fd
, "%s: syntax error.\n%s",pp
->name
,pp
->help
);
1138 printoutc(fd
, "vd%d: queuing discipline set to %s.", pi
->id
, pi
->policy_name
);
1143 printoutc(fd
, "'tc' command usage:");
1144 printoutc(fd
, "tc ls Print out the routing policy for each interface");
1145 printoutc(fd
, "tc set <DEV> <policy> <arguments> Change routing policy");
1150 static int logout(int fd
,char *s
)
1155 static int doshutdown(int fd
,char *s
)
1162 static struct comlist
{
1164 int (*fun
)(int fd
,char *arg
);
1166 } commandlist
[] = {
1167 {"help", help
, WITHFD
},
1168 {"showinfo",showinfo
, WITHFD
},
1169 {"ifconfig",ifconfig
, 0},
1171 {"logout",logout
, 0},
1172 {"shutdown",doshutdown
, 0},
1173 {"tc",traffic_control
,0}
1176 #define NCL sizeof(commandlist)/sizeof(struct comlist)
1178 static int handle_cmd(int fd
,char *inbuf
)
1182 while (*inbuf
== ' ' || *inbuf
== '\t' || *inbuf
== '\n') inbuf
++;
1183 if (*inbuf
!= '\0' && *inbuf
!= '#') {
1185 && strncmp(commandlist
[i
].tag
,inbuf
,strlen(commandlist
[i
].tag
))!=0;
1190 inbuf
+= strlen(commandlist
[i
].tag
);
1191 while (*inbuf
== ' ' || *inbuf
== '\t') inbuf
++;
1192 if (commandlist
[i
].type
& WITHFD
)
1193 printoutc(fd
,"0000 DATA END WITH '.'");
1194 rv
=commandlist
[i
].fun(fd
,inbuf
);
1195 if (commandlist
[i
].type
& WITHFD
)
1203 static char header
[]="\nVDE Layer 3 Switch V.%s\n(C) D.Lacamera 2007 - GPLv2\n";
1204 static char prompt
[]="\nVDE-L3$ ";
1206 static int mgmtcommand(int fd
)
1211 n
= read(fd
, buf
, MAXCMD
);
1213 fprintf(stderr
,"%s: read from mgmt %s",progname
,strerror(errno
));
1218 /* Remote end has closed connection. */
1221 if (fd
==STDIN_FILENO
)
1222 outfd
=STDOUT_FILENO
;
1224 rv
=handle_cmd(outfd
,buf
);
1226 write(outfd
,prompt
,strlen(prompt
));
1231 static int delmgmtconn(int i
,struct pollfd
*pfd
,int nfds
)
1235 if (pfd
[i
].fd
== 0) /* close stdin implies exit */
1237 memmove(pfd
+i
,pfd
+i
+1,sizeof (struct pollfd
) * (nfds
-i
-1));
1243 static int openmgmt(char *mgmt
)
1246 struct sockaddr_un sun
;
1249 if((mgmtconnfd
= socket(PF_UNIX
, SOCK_STREAM
, 0)) < 0){
1250 fprintf(stderr
,"%s: mgmt socket: %s",progname
,strerror(errno
));
1253 if(setsockopt(mgmtconnfd
, SOL_SOCKET
, SO_REUSEADDR
, (char *) &one
,
1255 fprintf(stderr
,"%s: mgmt setsockopt: %s",progname
,strerror(errno
));
1258 if(fcntl(mgmtconnfd
, F_SETFL
, O_NONBLOCK
) < 0){
1259 fprintf(stderr
,"%s: Setting O_NONBLOCK on mgmt fd: %s",progname
,strerror(errno
));
1262 sun
.sun_family
= PF_UNIX
;
1263 snprintf(sun
.sun_path
,sizeof(sun
.sun_path
),"%s",mgmt
);
1264 if(bind(mgmtconnfd
, (struct sockaddr
*) &sun
, sizeof(sun
)) < 0){
1265 fprintf(stderr
,"%s: mgmt bind %s",progname
,strerror(errno
));
1268 chmod(sun
.sun_path
,mgmtmode
);
1269 if(listen(mgmtconnfd
, 15) < 0){
1270 fprintf(stderr
,"%s: mgmt listen: %s",progname
,strerror(errno
));
1278 static int newmgmtconn(int fd
,struct pollfd
*pfd
,int nfds
)
1281 unsigned int len
=sizeof(struct sockaddr_un
);
1283 struct sockaddr addr
;
1284 new = accept(fd
, &addr
, &len
);
1286 fprintf(stderr
,"%s: mgmt accept %s",progname
,strerror(errno
));
1289 if (nfds
< max_total_sockets
) {
1290 snprintf(buf
,MAXCMD
,header
,PACKAGE_VERSION
);
1291 write(new,buf
,strlen(buf
));
1292 write(new,prompt
,strlen(prompt
));
1294 pfd
[nfds
].events
=POLLIN
| POLLHUP
;
1297 fprintf(stderr
,"%s: too many mgmt connections",progname
);
1304 int main(int argc
, char *argv
[])
1306 struct vde_iface
*vif
;
1307 struct pollfd
*pfd
, *pfdout
;
1308 struct vde_buff
*vdb_in
, *vdb_out
;
1309 struct vde_route
*vr
;
1312 struct vde_ethernet_header
*eh
;
1313 char *vdesock
,*argp
, *ipaddr
, *nm
=NULL
, *gw
, *mgmt
=NULL
;
1314 struct vde_open_args open_args
={.port
=0,.group
=NULL
,.mode
=0700};
1316 struct routing_policy
*rp
;
1320 static struct option long_options
[] = {
1321 {"help",0 , 0, 'h'},
1322 {"route",1 , 0, 'r'},
1323 {"defaultgw", 1, 0, 'G'},
1324 {"vdeplug", 1, 0, 'v'},
1325 {"mgmt", 1, 0, 'M'},
1326 //TODO {"daemon",0 , 0,'d'},
1328 progname
=strdup(argv
[0]);
1329 VDEROUTER
.route_table
= NULL
;
1330 VDEROUTER
.arp_table
= NULL
;
1331 VDEROUTER
.arp_pending
= NULL
;
1332 VDEROUTER
.modlist
= NULL
;
1333 VDEROUTER
.default_gw
= 0U;
1334 policy_register(&unlimited_fifo_routing_policy
);
1338 c
= GETOPT_LONG (argc
, argv
, "hM:r:G:v:",
1339 long_options
, &option_index
);
1347 mgmt
=strdup(optarg
);
1351 ipaddr
=strdup(optarg
);
1352 argp
= index(ipaddr
,'/');
1357 argp
= index(gw
,':');
1364 vr
=(struct vde_route
*)malloc(sizeof(struct vde_route
));
1365 vr
->network
= unicast_ip(ascii2ip(ipaddr
));
1366 vr
->nm
= ascii2nm(nm
);
1367 vr
->gw
= unicast_ip(ascii2ip(gw
));
1369 fprintf(stderr
,"route: Cannot set network address to '%s'\n",ipaddr
);
1373 fprintf(stderr
,"route: Cannot set netmask to '%s'\n",nm
);
1374 if(nm
!=NULL
&& nm
[0]=='0'){
1375 fprintf(stderr
,"(Did you mean to set default gateway? then -G)\n");
1380 fprintf(stderr
,"route: Cannot set gateway address to '%s'\n",gw
);
1383 VDEROUTER
.route_table
= add_route(vr
, VDEROUTER
.route_table
);
1387 VDEROUTER
.default_gw
=unicast_ip(ascii2ip(optarg
));
1388 if(!VDEROUTER
.default_gw
){
1389 fprintf(stderr
,"Cannot set default gateway address to '%s'\n",optarg
);
1394 vdesock
=strdup(optarg
);
1395 argp
= index(vdesock
,':');
1399 ipaddr
= strdup(argp
);
1400 argp
= index(ipaddr
,'/');
1408 vif
= (struct vde_iface
*) malloc(sizeof (struct vde_iface
));
1410 vif
->vdec
= vde_open(vdesock
,"vde_L3",&open_args
);
1412 fprintf(stderr
,"vdeplug %s: %s\n",vdesock
,strerror(errno
));
1416 vif
->ipaddr
= unicast_ip(ascii2ip(ipaddr
));
1418 fprintf(stderr
,"vdeplug %s: Cannot set ip address to '%s'\n",vdesock
,ipaddr
);
1422 vif
->nm
= ascii2nm(nm
);
1424 fprintf(stderr
,"vdeplug %s: Cannot set netmask to '%s'\n",vdesock
,nm
);
1425 if(nm
!=NULL
&& nm
[0]=='0'){
1426 fprintf(stderr
,"(Did you mean to set default gateway? then -G)\n");
1432 memcpy(vif
->mac
,ip2mac(vif
->ipaddr
),6);
1436 rp
= getpolicy("ufifo");
1438 fprintf(stderr
,"Error getting policy ufifo: %s",dlerror());
1439 set_interface_policy(vif
,rp
);
1440 if(!vif
->policy_init(vif
,"")){
1441 fprintf(stderr
,"Error setting default policy.\n");
1445 VDEROUTER
.interfaces
= add_iface(vif
, VDEROUTER
.interfaces
);
1457 max_total_sockets
= numif
+ 4;
1458 pfd
= (struct pollfd
*) malloc ((max_total_sockets
) * sizeof(struct pollfd
));
1459 vif
= VDEROUTER
.interfaces
;
1462 pfd
[i
].fd
= vde_datafd(vif
->vdec
);
1463 pfd
[i
++].events
=POLLIN
| POLLHUP
;
1468 int mgmtfd
=openmgmt(mgmt
);
1470 pfd
[mgmtindex
].fd
=mgmtfd
;
1471 pfd
[mgmtindex
].events
=POLLIN
| POLLHUP
;
1477 pr
= poll(pfd
,npfd
,10);
1484 for(i
=0,vif
=VDEROUTER
.interfaces
; i
<numif
&& vif
!=NULL
; i
++, vif
= vif
->next
){
1485 if(pfd
[i
].revents
== POLLIN
){
1487 vdb_in
=vdebuff_alloc(1550);
1490 vdb_in
->len
=vde_recv(vif
->vdec
,vdb_in
->data
,1548,0);
1492 fprintf(stderr
,"Rcvd a %luB packet. VDECONN@%p. Protocol = %d.\n",vdb_in
->len
,&(vif
->vdec
),ntohs(*((uint16_t *)(vdb_in
->data
+12))));
1495 //Next line is a mac address filter.
1496 if((memcmp(eh
->dst
,vif
->mac
,6) == 0) || ((is_multicast_mac(eh
->dst
)) && (memcmp(eh
->src
,vif
->mac
,6)!=0))){
1497 if(eh
->buftype
== ntohs(PTYPE_ARP
)){
1498 pktin
+= parse_arp(vdb_in
);
1500 if(eh
->buftype
== ntohs(PTYPE_IP
)){
1501 pktin
+= parse_ip(vdb_in
);
1506 if (pr
>0) { // if there are still events to handle (performance: packet switching first)
1507 int mgmtfdstart
=numif
;
1508 if (mgmtindex
>= 0) {
1509 if (pfd
[mgmtindex
].revents
!= 0) {
1510 npfd
=newmgmtconn(pfd
[mgmtindex
].fd
,pfd
,npfd
);
1513 mgmtfdstart
=mgmtindex
+1;
1515 if (mgmtfdstart
>= 0 && npfd
> mgmtfdstart
) {
1517 for (i
=mgmtfdstart
;i
<npfd
;i
++) {
1518 if (pfd
[i
].revents
& POLLHUP
||
1519 (pfd
[i
].revents
& POLLIN
&& mgmtcommand(pfd
[i
].fd
) < 0))
1520 npfd
=delmgmtconn(i
,pfd
,npfd
);
1521 if (pfd
[i
].revents
) pr
--;
1527 int outqueues
= 0, outloop
= 0;
1528 pfdout
= (struct pollfd
*) malloc ((max_total_sockets
) * sizeof(struct pollfd
));
1529 vif
=VDEROUTER
.interfaces
;
1531 pfdout
[outqueues
].fd
= vde_datafd(vif
->vdec
);
1532 pfdout
[outqueues
++].events
= POLLOUT
;
1536 vif
=VDEROUTER
.interfaces
;
1537 if (poll(pfdout
,outqueues
,0) > 0){
1538 for(outloop
= 0; outloop
< outqueues
; outloop
++){
1539 if(pfdout
[outloop
].revents
&POLLOUT
&& vif
->q_out
){
1546 while(VDEROUTER
.arp_pending
){
1547 vdb_out
=VDEROUTER
.arp_pending
;
1548 ip_output_ready(vdb_out
);
1549 VDEROUTER
.arp_pending
=vdb_out
->next
;
1556 * After being parsed, this is the point where packets
1557 * get to higher protocols
1559 int ip_input(struct vde_buff
*vdb
)
1562 struct iphdr
*iph
=iphead(vdb
);
1563 if(*((uint8_t*)(iph
)) != 0x45)
1565 switch(iph
->protocol
){
1567 return parse_icmp(vdb
);
1571 return service_unreachable(vdb
);
1573 // return -1; // not reached